forked from erp-dev/erp
feat: error_code + api doc + printing-job fields
This commit is contained in:
101
flower/exception_handler.py
Normal file
101
flower/exception_handler.py
Normal file
@@ -0,0 +1,101 @@
|
||||
from rest_framework import exceptions, status
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import exception_handler
|
||||
from rest_framework_simplejwt.exceptions import InvalidToken
|
||||
|
||||
from flower.error_code import AuthErrorCode
|
||||
|
||||
|
||||
def auth_error_response(*, error_code: AuthErrorCode, code: str, message: str, http_status: int, extra=None):
|
||||
data = {
|
||||
'error_code': int(error_code),
|
||||
'code': code,
|
||||
'message': message,
|
||||
'detail': message,
|
||||
}
|
||||
if extra:
|
||||
data.update(extra)
|
||||
return Response(data, status=http_status)
|
||||
|
||||
|
||||
def _stringify_detail(detail):
|
||||
if hasattr(detail, 'code'):
|
||||
return str(detail), str(detail.code)
|
||||
return str(detail), None
|
||||
|
||||
|
||||
def _extract_exception_detail(exc):
|
||||
detail = getattr(exc, 'detail', None)
|
||||
if isinstance(detail, dict):
|
||||
raw_detail = detail.get('detail')
|
||||
raw_code = detail.get('code')
|
||||
messages = detail.get('messages')
|
||||
message = str(raw_detail) if raw_detail is not None else ''
|
||||
code = str(raw_code) if raw_code is not None else None
|
||||
extra = {'messages': messages} if messages is not None else None
|
||||
return message, code, extra
|
||||
|
||||
message, code = _stringify_detail(detail)
|
||||
return message, code, None
|
||||
|
||||
|
||||
def custom_exception_handler(exc, context):
|
||||
if isinstance(exc, InvalidToken):
|
||||
_, _, extra = _extract_exception_detail(exc)
|
||||
return auth_error_response(
|
||||
error_code=AuthErrorCode.TOKEN_NOT_VALID,
|
||||
code='token_not_valid',
|
||||
message='Token 无效或已过期',
|
||||
http_status=status.HTTP_401_UNAUTHORIZED,
|
||||
extra=extra,
|
||||
)
|
||||
|
||||
if isinstance(exc, exceptions.NotAuthenticated):
|
||||
return auth_error_response(
|
||||
error_code=AuthErrorCode.NOT_AUTHENTICATED,
|
||||
code='not_authenticated',
|
||||
message='未提供认证凭据',
|
||||
http_status=status.HTTP_401_UNAUTHORIZED,
|
||||
)
|
||||
|
||||
if isinstance(exc, exceptions.AuthenticationFailed):
|
||||
message, code, extra = _extract_exception_detail(exc)
|
||||
if code == 'bad_authorization_header':
|
||||
return auth_error_response(
|
||||
error_code=AuthErrorCode.BAD_AUTHORIZATION_HEADER,
|
||||
code='bad_authorization_header',
|
||||
message='Authorization 请求头格式错误',
|
||||
http_status=status.HTTP_401_UNAUTHORIZED,
|
||||
)
|
||||
if code == 'user_not_found':
|
||||
return auth_error_response(
|
||||
error_code=AuthErrorCode.TOKEN_USER_NOT_FOUND,
|
||||
code='token_user_not_found',
|
||||
message='Token 对应用户不存在',
|
||||
http_status=status.HTTP_401_UNAUTHORIZED,
|
||||
)
|
||||
if code == 'user_inactive':
|
||||
return auth_error_response(
|
||||
error_code=AuthErrorCode.TOKEN_USER_INACTIVE,
|
||||
code='token_user_inactive',
|
||||
message='Token 对应用户已被禁用',
|
||||
http_status=status.HTTP_401_UNAUTHORIZED,
|
||||
)
|
||||
|
||||
return auth_error_response(
|
||||
error_code=AuthErrorCode.TOKEN_NOT_VALID,
|
||||
code=code or 'authentication_failed',
|
||||
message=message or '认证失败',
|
||||
http_status=status.HTTP_401_UNAUTHORIZED,
|
||||
extra=extra,
|
||||
)
|
||||
|
||||
if isinstance(exc, exceptions.PermissionDenied):
|
||||
return auth_error_response(
|
||||
error_code=AuthErrorCode.PERMISSION_DENIED,
|
||||
code='permission_denied',
|
||||
message='无权限访问该资源',
|
||||
http_status=status.HTTP_403_FORBIDDEN,
|
||||
)
|
||||
|
||||
return exception_handler(exc, context)
|
||||
Reference in New Issue
Block a user