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

1"""Auth 시스템의 예외 핸들러""" 

2 

3from typing import Any 

4 

5from fastapi import Request, status 

6from fastapi.responses import JSONResponse 

7 

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) 

23 

24 

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 } 

35 

36 if details: 

37 content["error"]["details"] = details 

38 

39 return JSONResponse(status_code=status_code, content=content) 

40 

41 

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 ) 

50 

51 

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 ) 

60 

61 

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 ) 

72 

73 

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 ) 

82 

83 

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 ) 

92 

93 

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 ) 

104 

105 

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 ) 

116 

117 

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 ) 

128 

129 

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 ) 

140 

141 

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 ) 

152 

153 

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 ) 

164 

165 

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 ) 

174 

175 

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 ) 

186 

187 

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} 

204 

205 

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)