feat: add /auth/me route
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
10
src/dto/user.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import uuid
|
||||||
|
|
||||||
|
import pydantic
|
||||||
|
|
||||||
|
|
||||||
|
class UserOutput(pydantic.BaseModel):
|
||||||
|
id: uuid.UUID
|
||||||
|
telegram_id: int
|
||||||
|
username: str | None
|
||||||
|
|
||||||
13
src/main.py
13
src/main.py
@@ -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)
|
||||||
|
|||||||
@@ -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
22
src/usecase/get_me.py
Normal 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,
|
||||||
|
)
|
||||||
|
|
||||||
Reference in New Issue
Block a user