feat: add /auth/me route

This commit is contained in:
ivannoskov
2025-11-19 15:38:16 +03:00
parent bba37fbb21
commit 1d070b63cc
8 changed files with 74 additions and 19 deletions

View File

@@ -1,15 +1,15 @@
services:
# backend:
# build:
# context: .
# args:
# GIT_COMMIT: ${GIT_COMMIT:-unknown}
# env_file:
# - .env
# ports:
# - "8000:8000"
# depends_on:
# - postgres
backend:
build:
context: .
args:
GIT_COMMIT: ${GIT_COMMIT:-unknown}
env_file:
- .env
ports:
- "8000:8000"
depends_on:
- postgres
postgres:
image: postgres:17-alpine

View File

@@ -9,11 +9,9 @@ from src.controller.http.views import views_router
api_router = APIRouter()
# Public auth endpoints (no prefix)
api_router.include_router(auth_router)
# API v1 endpoints
api_v1_router = APIRouter(prefix='/api/v1')
api_v1_router.include_router(auth_router)
api_v1_router.include_router(target_channels_router)
api_v1_router.include_router(external_channels_router)
api_v1_router.include_router(creatives_router)

View File

@@ -1,17 +1,25 @@
from typing import Annotated
from fastapi import Depends
from fastapi.routing import APIRouter
from src import dto
from src.dependencies import get_usecase
from src.usecase import Usecase
from src import dependencies, dto
from src.adapter.jwt import JWTPayload
auth_router = APIRouter(prefix='/auth', tags=['auth'])
@auth_router.get('/complete')
async def complete_auth(token: str, usecase: Usecase = Depends(get_usecase)) -> dto.ValidateLoginTokenOutput:
return await usecase.validate_login_token(
async def complete_auth(token: str) -> dto.ValidateLoginTokenOutput:
return await dependencies.get_usecase().validate_login_token(
input=dto.ValidateLoginTokenInput(
token=token,
)
)
@auth_router.get('/me')
async def get_me(
current_user: Annotated[JWTPayload, Depends(dependencies.get_current_user)],
) -> dto.UserOutput:
return await dependencies.get_usecase().get_me(user_id=current_user.user_id)

View File

@@ -37,6 +37,7 @@ __all__ = (
'FetchViewsInputManually',
'FetchViewsManuallyOutput',
'UpdateViewsManuallyInput',
'UserOutput',
)
from .creative import (
@@ -78,6 +79,7 @@ from .target_channel import (
)
from .telegram_login import TelegramLoginInput
from .validate_login_token import ValidateLoginTokenInput, ValidateLoginTokenOutput
from .user import UserOutput
from .views import (
FetchViewsInputManually,
FetchViewsManuallyOutput,

10
src/dto/user.py Normal file
View File

@@ -0,0 +1,10 @@
import uuid
import pydantic
class UserOutput(pydantic.BaseModel):
id: uuid.UUID
telegram_id: int
username: str | None

View File

@@ -2,6 +2,7 @@ from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from shared import logger
from src import dependencies
@@ -48,4 +49,16 @@ dependencies.set_usecase(usecase)
views_worker = FetchViewsWorker(config=settings.fetch_views_worker)
app = FastAPI(lifespan=lifespan, version=settings.logger.APP_VERSION)
app.add_middleware(
CORSMiddleware,
allow_origins=[
"https://app.tgexchange.ru",
"http://app.tgexchange.ru",
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(api_router)

View File

@@ -10,6 +10,7 @@ from .creative.delete_creative import delete_creative
from .creative.get_creative import get_creative
from .creative.get_creatives import get_creatives
from .creative.update_creative import update_creative
from .get_me import get_me
from .external_channel.create_external_channel import create_external_channel
from .external_channel.delete_external_channel import delete_external_channel
from .external_channel.get_external_channels import get_external_channels
@@ -171,6 +172,7 @@ class Usecase:
validate_login_token = validate_login_token
telegram_login = telegram_login
get_me = get_me
connect_target_chan = connect_target_chan
get_user_target_chans = get_user_target_chans
disconnect_target_chan = disconnect_target_chan

22
src/usecase/get_me.py Normal file
View File

@@ -0,0 +1,22 @@
import typing
import uuid
from src import domain, dto
if typing.TYPE_CHECKING:
from . import Usecase
async def get_me(self: 'Usecase', user_id: uuid.UUID) -> dto.UserOutput:
async with self.database.transaction():
user = await self.database.get_user(user_id=user_id)
if not user:
raise domain.UserNotFound(user_id)
return dto.UserOutput(
id=user.id,
telegram_id=user.telegram_id,
username=user.username,
)