Coverage for src / mysingle / auth / exception_handlers.py: 0%
39 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-02 00:58 +0900
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-02 00:58 +0900
1"""Auth 시스템의 예외 핸들러"""
3from typing import Any
5from fastapi import Request, status
6from fastapi.responses import JSONResponse
8from .exceptions import (
9 AuthenticationFailed,
10 AuthException,
11 AuthorizationFailed,
12 InvalidID,
13 InvalidPasswordException,
14 InvalidResetPasswordToken,
15 InvalidVerifyToken,
16 JWTStrategyDestroyNotSupportedError,
17 TokenExpired,
18 UserAlreadyExists,
19 UserAlreadyVerified,
20 UserInactive,
21 UserNotExists,
22)
25def create_error_response(
26 status_code: int, error_code: str, message: str, details: Any = None
27) -> JSONResponse:
28 """표준화된 에러 응답 생성"""
29 content = {
30 "error": {
31 "code": error_code,
32 "message": message,
33 }
34 }
36 if details:
37 content["error"]["details"] = details
39 return JSONResponse(status_code=status_code, content=content)
42async def auth_exception_handler(request: Request, exc: AuthException) -> JSONResponse:
43 """Auth 기본 예외 핸들러"""
44 return create_error_response(
45 status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
46 error_code="AUTH_ERROR",
47 message=exc.message,
48 details=exc.details,
49 )
52async def invalid_id_handler(request: Request, exc: InvalidID) -> JSONResponse:
53 """잘못된 ID 예외 핸들러"""
54 return create_error_response(
55 status_code=status.HTTP_400_BAD_REQUEST,
56 error_code="INVALID_ID",
57 message=exc.message,
58 details=exc.details,
59 )
62async def user_already_exists_handler(
63 request: Request, exc: UserAlreadyExists
64) -> JSONResponse:
65 """사용자 이미 존재 예외 핸들러"""
66 return create_error_response(
67 status_code=status.HTTP_409_CONFLICT,
68 error_code="USER_ALREADY_EXISTS",
69 message=exc.message,
70 details=exc.details,
71 )
74async def user_not_exists_handler(request: Request, exc: UserNotExists) -> JSONResponse:
75 """사용자 존재하지 않음 예외 핸들러"""
76 return create_error_response(
77 status_code=status.HTTP_404_NOT_FOUND,
78 error_code="USER_NOT_FOUND",
79 message=exc.message,
80 details=exc.details,
81 )
84async def user_inactive_handler(request: Request, exc: UserInactive) -> JSONResponse:
85 """비활성 사용자 예외 핸들러"""
86 return create_error_response(
87 status_code=status.HTTP_403_FORBIDDEN,
88 error_code="USER_INACTIVE",
89 message=exc.message,
90 details=exc.details,
91 )
94async def user_already_verified_handler(
95 request: Request, exc: UserAlreadyVerified
96) -> JSONResponse:
97 """이미 인증된 사용자 예외 핸들러"""
98 return create_error_response(
99 status_code=status.HTTP_400_BAD_REQUEST,
100 error_code="USER_ALREADY_VERIFIED",
101 message=exc.message,
102 details=exc.details,
103 )
106async def invalid_verify_token_handler(
107 request: Request, exc: InvalidVerifyToken
108) -> JSONResponse:
109 """잘못된 인증 토큰 예외 핸들러"""
110 return create_error_response(
111 status_code=status.HTTP_400_BAD_REQUEST,
112 error_code="INVALID_VERIFY_TOKEN",
113 message=exc.message,
114 details=exc.details,
115 )
118async def invalid_reset_password_token_handler(
119 request: Request, exc: InvalidResetPasswordToken
120) -> JSONResponse:
121 """잘못된 비밀번호 재설정 토큰 예외 핸들러"""
122 return create_error_response(
123 status_code=status.HTTP_400_BAD_REQUEST,
124 error_code="INVALID_RESET_TOKEN",
125 message=exc.message,
126 details=exc.details,
127 )
130async def invalid_password_handler(
131 request: Request, exc: InvalidPasswordException
132) -> JSONResponse:
133 """잘못된 비밀번호 예외 핸들러"""
134 return create_error_response(
135 status_code=status.HTTP_400_BAD_REQUEST,
136 error_code="INVALID_PASSWORD",
137 message=exc.message,
138 details=exc.details,
139 )
142async def authentication_failed_handler(
143 request: Request, exc: AuthenticationFailed
144) -> JSONResponse:
145 """인증 실패 예외 핸들러"""
146 return create_error_response(
147 status_code=status.HTTP_401_UNAUTHORIZED,
148 error_code="AUTHENTICATION_FAILED",
149 message=exc.message,
150 details=exc.details,
151 )
154async def authorization_failed_handler(
155 request: Request, exc: AuthorizationFailed
156) -> JSONResponse:
157 """인가 실패 예외 핸들러"""
158 return create_error_response(
159 status_code=status.HTTP_403_FORBIDDEN,
160 error_code="AUTHORIZATION_FAILED",
161 message=exc.message,
162 details=exc.details,
163 )
166async def token_expired_handler(request: Request, exc: TokenExpired) -> JSONResponse:
167 """토큰 만료 예외 핸들러"""
168 return create_error_response(
169 status_code=status.HTTP_401_UNAUTHORIZED,
170 error_code="TOKEN_EXPIRED",
171 message=exc.message,
172 details=exc.details,
173 )
176async def jwt_destroy_not_supported_handler(
177 request: Request, exc: JWTStrategyDestroyNotSupportedError
178) -> JSONResponse:
179 """JWT 토큰 파기 미지원 예외 핸들러"""
180 return create_error_response(
181 status_code=status.HTTP_501_NOT_IMPLEMENTED,
182 error_code="JWT_DESTROY_NOT_SUPPORTED",
183 message=exc.message,
184 details=exc.details,
185 )
188# 예외 핸들러 매핑
189EXCEPTION_HANDLERS: dict[type, Any] = {
190 InvalidID: invalid_id_handler,
191 UserAlreadyExists: user_already_exists_handler,
192 UserNotExists: user_not_exists_handler,
193 UserInactive: user_inactive_handler,
194 UserAlreadyVerified: user_already_verified_handler,
195 InvalidVerifyToken: invalid_verify_token_handler,
196 InvalidResetPasswordToken: invalid_reset_password_token_handler,
197 InvalidPasswordException: invalid_password_handler,
198 AuthenticationFailed: authentication_failed_handler,
199 AuthorizationFailed: authorization_failed_handler,
200 TokenExpired: token_expired_handler,
201 JWTStrategyDestroyNotSupportedError: jwt_destroy_not_supported_handler,
202 AuthException: auth_exception_handler, # 기본 핸들러는 마지막에
203}
206def register_auth_exception_handlers(app: Any) -> None:
207 """FastAPI 앱에 Auth 예외 핸들러들을 등록"""
208 for exception_type, handler in EXCEPTION_HANDLERS.items():
209 app.add_exception_handler(exception_type, handler)