errors.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. """DMS业务异常。"""
  2. from __future__ import annotations
  3. from typing import Any
  4. class DmsError(Exception):
  5. code = "INTERNAL_ERROR"
  6. status_code = 500
  7. default_message = "服务器内部错误"
  8. def __init__(
  9. self,
  10. message: str | None = None,
  11. *,
  12. details: Any = None,
  13. code: str | None = None,
  14. ) -> None:
  15. super().__init__(message or self.default_message)
  16. self.message = message or self.default_message
  17. self.details = details
  18. self.code = code or self.code
  19. class InvalidArgumentError(DmsError):
  20. code = "INVALID_ARGUMENT"
  21. status_code = 400
  22. default_message = "请求参数错误"
  23. class AuthenticationError(DmsError):
  24. code = "TOKEN_INVALID"
  25. status_code = 401
  26. default_message = "未认证或登录凭证无效"
  27. class InvalidCredentialsError(AuthenticationError):
  28. code = "INVALID_CREDENTIALS"
  29. default_message = "用户名或密码错误"
  30. class TokenExpiredError(AuthenticationError):
  31. code = "TOKEN_EXPIRED"
  32. default_message = "登录凭证已过期"
  33. class UserDisabledError(AuthenticationError):
  34. code = "USER_DISABLED"
  35. default_message = "用户已被禁用"
  36. class AuthVersionMismatchError(AuthenticationError):
  37. code = "AUTH_VERSION_MISMATCH"
  38. default_message = "登录状态已失效,请重新登录"
  39. class PortalTokenInvalidError(AuthenticationError):
  40. code = "PORTAL_TOKEN_INVALID"
  41. default_message = "门户跳转凭证无效或已过期"
  42. class PortalTicketInvalidError(AuthenticationError):
  43. code = "PORTAL_TICKET_INVALID"
  44. default_message = "设置密码凭证无效或已过期,请从门户重新跳转"
  45. class ForbiddenError(DmsError):
  46. code = "FORBIDDEN"
  47. status_code = 403
  48. default_message = "无权限执行此操作"
  49. class SecurityLevelForbiddenError(ForbiddenError):
  50. code = "SECURITY_LEVEL_FORBIDDEN"
  51. default_message = "用户密级不足,无法查看该文档"
  52. class DocumentViewForbiddenError(ForbiddenError):
  53. code = "DOCUMENT_VIEW_FORBIDDEN"
  54. default_message = "无权查看该文档"
  55. class DocumentDownloadForbiddenError(ForbiddenError):
  56. code = "DOCUMENT_DOWNLOAD_FORBIDDEN"
  57. default_message = "无权下载该文档"
  58. class ResourceNotFoundError(DmsError):
  59. code = "RESOURCE_NOT_FOUND"
  60. status_code = 404
  61. default_message = "请求的资源不存在"
  62. class ConflictError(DmsError):
  63. code = "DATA_VERSION_CONFLICT"
  64. status_code = 409
  65. default_message = "数据冲突"
  66. class CategoryInUseError(ConflictError):
  67. code = "CATEGORY_IN_USE"
  68. default_message = "分类仍被子分类或方案文档占用"
  69. class CategoryNotLeafError(ConflictError):
  70. code = "CATEGORY_NOT_LEAF"
  71. default_message = "只有有效叶子分类可以直接存放主案"
  72. class CategoryFlatModeConflictError(ConflictError):
  73. code = "CATEGORY_FLAT_MODE_CONFLICT"
  74. default_message = "该一级分类下已存在子方案或配套资料挂载,请先解绑后再切换为扁平模式"
  75. class MainPlanNotFoundError(ResourceNotFoundError):
  76. code = "MAIN_PLAN_NOT_FOUND"
  77. default_message = "主案不存在"
  78. class FileNotFoundError(ResourceNotFoundError):
  79. code = "FILE_NOT_FOUND"
  80. default_message = "文档文件不存在"
  81. class PreviewUnavailableError(DmsError):
  82. code = "PREVIEW_UNAVAILABLE"
  83. status_code = 415
  84. default_message = "当前文件类型不支持在线预览"
  85. class PreviewConverterUnavailableError(DmsError):
  86. code = "PREVIEW_CONVERTER_UNAVAILABLE"
  87. status_code = 503
  88. default_message = "预览转换器未配置或不可用"
  89. class PreviewConversionTimeoutError(DmsError):
  90. code = "PREVIEW_CONVERSION_TIMEOUT"
  91. status_code = 504
  92. default_message = "文档转换超时,请稍后重试"
  93. class PreviewConversionFailedError(DmsError):
  94. code = "PREVIEW_CONVERSION_FAILED"
  95. status_code = 502
  96. default_message = "文档转换为PDF失败"
  97. class BatchManifestMismatchError(InvalidArgumentError):
  98. code = "BATCH_MANIFEST_MISMATCH"
  99. default_message = "批量文件数量与元数据数量不一致"
  100. class MainPlanHasChildrenError(ConflictError):
  101. code = "MAIN_PLAN_HAS_CHILDREN"
  102. default_message = "主案仍存在有效子方案"
  103. class DocumentNameConflictError(ConflictError):
  104. code = "DOCUMENT_NAME_CONFLICT"
  105. default_message = "同一范围内已存在同名方案"
  106. class AttachmentInUseError(ConflictError):
  107. code = "ATTACHMENT_IN_USE"
  108. default_message = "共享附件仍被主案挂载"
  109. class AttachmentHasNoAclError(InvalidArgumentError):
  110. code = "ATTACHMENT_HAS_NO_ACL"
  111. default_message = "共享附件不配置访问权限"
  112. class SubPlanPermissionInheritedError(ConflictError):
  113. code = "SUB_PLAN_PERMISSION_INHERITED"
  114. default_message = "子方案动态继承主案权限,不能独立配置"
  115. class DuplicatePermissionSubjectError(InvalidArgumentError):
  116. code = "DUPLICATE_PERMISSION_SUBJECT"
  117. default_message = "权限主体不能重复"
  118. class UnsupportedFileTypeError(DmsError):
  119. code = "UNSUPPORTED_FILE_TYPE"
  120. status_code = 415
  121. default_message = "不支持的文件类型"
  122. class PayloadTooLargeError(DmsError):
  123. code = "PAYLOAD_TOO_LARGE"
  124. status_code = 413
  125. default_message = "请求内容过大"
  126. class InternalError(DmsError):
  127. code = "INTERNAL_ERROR"
  128. status_code = 500
  129. default_message = "服务器内部错误"
  130. class DocumentNotDeletedError(ConflictError):
  131. code = "DOCUMENT_NOT_DELETED"
  132. default_message = "文档当前不在回收站中"
  133. class FileIntegrityMismatchError(ConflictError):
  134. code = "FILE_INTEGRITY_MISMATCH"
  135. default_message = "文档文件完整性校验失败"
  136. class FilePathInvalidError(InternalError):
  137. code = "FILE_PATH_INVALID"
  138. default_message = "文档存储路径异常"
  139. class RestoreFileChangedError(ConflictError):
  140. code = "RESTORE_FILE_CHANGED"
  141. default_message = "校验期间文件发生变化"
  142. class RestoreCategoryInvalidError(ConflictError):
  143. code = "RESTORE_CATEGORY_INVALID"
  144. default_message = "原方案分类无效,无法恢复"
  145. class RestoreParentInvalidError(ConflictError):
  146. code = "RESTORE_PARENT_INVALID"
  147. default_message = "原所属主案无效,无法恢复"
  148. class RestorePermissionInvalidError(ConflictError):
  149. code = "RESTORE_PERMISSION_INVALID"
  150. default_message = "恢复后无法形成有效权限配置"
  151. class RestoreRelationConflictError(ConflictError):
  152. code = "RESTORE_RELATION_CONFLICT"
  153. default_message = "历史权限或挂载关系与当前有效关系冲突"
  154. class OrganizationInUseError(ConflictError):
  155. code = "ORGANIZATION_IN_USE"
  156. default_message = "机构仍存在下级机构或挂载用户"
  157. class UserSelfProtectionError(ForbiddenError):
  158. code = "USER_SELF_PROTECTION"
  159. default_message = "不能对本账号执行该操作"
  160. class RoleInUseError(ConflictError):
  161. code = "ROLE_IN_USE"
  162. default_message = "角色仍有关联用户,无法删除"
  163. class DocumentPasswordRequiredError(ForbiddenError):
  164. code = "DOCUMENT_PASSWORD_REQUIRED"
  165. default_message = "该方案已设置密码保护,请输入密码后重试"
  166. class DocumentPasswordInvalidError(ForbiddenError):
  167. code = "DOCUMENT_PASSWORD_INVALID"
  168. default_message = "方案密码错误"
  169. class LoginIpForbiddenError(ForbiddenError):
  170. code = "LOGIN_IP_FORBIDDEN"
  171. default_message = "当前IP不在该部门允许的登录IP范围内"