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: services:
# backend: backend:
# build: build:
# context: . context: .
# args: args:
# GIT_COMMIT: ${GIT_COMMIT:-unknown} GIT_COMMIT: ${GIT_COMMIT:-unknown}
# env_file: env_file:
# - .env - .env
# ports: ports:
# - "8000:8000" - "8000:8000"
# depends_on: depends_on:
# - postgres - postgres
postgres: postgres:
image: postgres:17-alpine image: postgres:17-alpine

View File

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

View File

@@ -1,17 +1,25 @@
from typing import Annotated
from fastapi import Depends from fastapi import Depends
from fastapi.routing import APIRouter from fastapi.routing import APIRouter
from src import dto from src import dependencies, dto
from src.dependencies import get_usecase from src.adapter.jwt import JWTPayload
from src.usecase import Usecase
auth_router = APIRouter(prefix='/auth', tags=['auth']) auth_router = APIRouter(prefix='/auth', tags=['auth'])
@auth_router.get('/complete') @auth_router.get('/complete')
async def complete_auth(token: str, usecase: Usecase = Depends(get_usecase)) -> dto.ValidateLoginTokenOutput: async def complete_auth(token: str) -> dto.ValidateLoginTokenOutput:
return await usecase.validate_login_token( return await dependencies.get_usecase().validate_login_token(
input=dto.ValidateLoginTokenInput( input=dto.ValidateLoginTokenInput(
token=token, 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', 'FetchViewsInputManually',
'FetchViewsManuallyOutput', 'FetchViewsManuallyOutput',
'UpdateViewsManuallyInput', 'UpdateViewsManuallyInput',
'UserOutput',
) )
from .creative import ( from .creative import (
@@ -78,6 +79,7 @@ from .target_channel import (
) )
from .telegram_login import TelegramLoginInput from .telegram_login import TelegramLoginInput
from .validate_login_token import ValidateLoginTokenInput, ValidateLoginTokenOutput from .validate_login_token import ValidateLoginTokenInput, ValidateLoginTokenOutput
from .user import UserOutput
from .views import ( from .views import (
FetchViewsInputManually, FetchViewsInputManually,
FetchViewsManuallyOutput, 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 contextlib import asynccontextmanager
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from shared import logger from shared import logger
from src import dependencies from src import dependencies
@@ -48,4 +49,16 @@ dependencies.set_usecase(usecase)
views_worker = FetchViewsWorker(config=settings.fetch_views_worker) views_worker = FetchViewsWorker(config=settings.fetch_views_worker)
app = FastAPI(lifespan=lifespan, version=settings.logger.APP_VERSION) 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) 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_creative import get_creative
from .creative.get_creatives import get_creatives from .creative.get_creatives import get_creatives
from .creative.update_creative import update_creative 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.create_external_channel import create_external_channel
from .external_channel.delete_external_channel import delete_external_channel from .external_channel.delete_external_channel import delete_external_channel
from .external_channel.get_external_channels import get_external_channels from .external_channel.get_external_channels import get_external_channels
@@ -171,6 +172,7 @@ class Usecase:
validate_login_token = validate_login_token validate_login_token = validate_login_token
telegram_login = telegram_login telegram_login = telegram_login
get_me = get_me
connect_target_chan = connect_target_chan connect_target_chan = connect_target_chan
get_user_target_chans = get_user_target_chans get_user_target_chans = get_user_target_chans
disconnect_target_chan = disconnect_target_chan 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,
)