import asyncio from fastapi import Request from app.common.repository.admin_user_repository import AdminUserRepository from app.constants.model.admin_user.admin_user_status_code import AdminUserStatusCode from app.exception.err_exception import ErrException from app.lib.response.admin_return import AdminReturn from app.request.admin.login_request import LoginRequest from app.service.admin.base_admin_service import BaseAdminService from app.service.base_token_service import BaseTokenService class LoginService(BaseAdminService): def __init__( self, user_repository: AdminUserRepository, token_service: BaseTokenService, admin_return: AdminReturn, ) -> None: super().__init__(admin_return) self.user_repository = user_repository self.token_service = token_service async def handle(self, payload: LoginRequest, request: Request) -> dict: admin_info = await self.user_repository.find_by_username(payload.username) if admin_info is None: raise ErrException("后台管理员不存在") password_valid = await asyncio.to_thread( admin_info.verify_password, payload.password, ) if not password_valid: raise ErrException("密码错误") if admin_info.status == AdminUserStatusCode.DISABLE: raise ErrException("用户已禁用") await self.user_repository.record_login(admin_info.id, self._client_ip(request)) jwt = self.token_service.get_jwt("admin") return self.admin_return.success( "success", { "access_token": jwt.builder_access_token(str(admin_info.id)), "refresh_token": jwt.builder_refresh_token(str(admin_info.id)), "expire_at": int(jwt.get_config("ttl", 0)), }, ) @staticmethod def _client_ip(request: Request) -> str: forwarded = request.headers.get("x-forwarded-for") if forwarded: return forwarded.split(",", 1)[0].strip() return request.client.host if request.client else ""