roles.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. """角色管理:角色 CRUD、权限矩阵与用户关联。"""
  2. from __future__ import annotations
  3. from flask import request
  4. from dms.api.v1.blueprint import api_v1
  5. from dms.common.errors import InvalidArgumentError
  6. from dms.common.pagination import PageRequest
  7. from dms.common.response import success_response
  8. from dms.security.decorators import (
  9. admin_required,
  10. bearer_auth_required,
  11. reauth_required,
  12. role_edit_required,
  13. )
  14. from dms.services.role_service import (
  15. create_role,
  16. delete_role,
  17. list_role_permissions,
  18. list_role_users,
  19. list_roles,
  20. reorder_roles,
  21. update_role,
  22. update_role_permissions,
  23. update_role_users,
  24. )
  25. def _integer_query(name: str, default: int) -> int:
  26. raw_value = request.args.get(name)
  27. if raw_value is None or raw_value == "":
  28. return default
  29. try:
  30. return int(raw_value)
  31. except ValueError as exc:
  32. raise InvalidArgumentError(f"{name}必须是整数") from exc
  33. def _json_body():
  34. if not request.is_json:
  35. raise InvalidArgumentError("请求体必须是JSON对象")
  36. body = request.get_json(silent=True)
  37. if not isinstance(body, dict):
  38. raise InvalidArgumentError("请求体必须是JSON对象")
  39. return body
  40. def _parse_role_id(value: str) -> int:
  41. if not value.isdecimal() or int(value) <= 0:
  42. raise InvalidArgumentError("id必须是正整数形式的字符串ID")
  43. return int(value)
  44. def _parse_delete_row_version(value: str | None) -> int:
  45. if value is None or not value.isdecimal():
  46. raise InvalidArgumentError("rowVersion必须是非负整数")
  47. return int(value)
  48. @api_v1.get("/roles")
  49. @bearer_auth_required
  50. @admin_required
  51. def roles():
  52. data = list_roles(
  53. keyword=request.args.get("keyword"),
  54. status=request.args.get("status"),
  55. page_request=PageRequest(
  56. page=_integer_query("page", 1),
  57. page_size=_integer_query("pageSize", 20),
  58. ),
  59. )
  60. return success_response(data)
  61. @api_v1.post("/roles")
  62. @bearer_auth_required
  63. @admin_required
  64. @role_edit_required
  65. def create_role_route():
  66. return success_response(create_role(_json_body()), status=201)
  67. @api_v1.put("/roles/reorder")
  68. @bearer_auth_required
  69. @admin_required
  70. @role_edit_required
  71. def reorder_roles_route():
  72. return success_response(reorder_roles(_json_body()))
  73. @api_v1.put("/roles/<id>")
  74. @bearer_auth_required
  75. @admin_required
  76. @role_edit_required
  77. def update_role_route(id: str):
  78. return success_response(update_role(_parse_role_id(id), _json_body()))
  79. @api_v1.delete("/roles/<id>")
  80. @bearer_auth_required
  81. @admin_required
  82. @role_edit_required
  83. def delete_role_route(id: str):
  84. return success_response(
  85. delete_role(
  86. _parse_role_id(id),
  87. _parse_delete_row_version(request.args.get("rowVersion")),
  88. )
  89. )
  90. @api_v1.get("/roles/<id>/permissions")
  91. @bearer_auth_required
  92. @admin_required
  93. def role_permissions(id: str):
  94. return success_response(list_role_permissions(_parse_role_id(id)))
  95. @api_v1.put("/roles/<id>/permissions")
  96. @bearer_auth_required
  97. @admin_required
  98. @role_edit_required
  99. @reauth_required
  100. def update_role_permissions_route(id: str):
  101. return success_response(
  102. update_role_permissions(_parse_role_id(id), _json_body())
  103. )
  104. @api_v1.get("/roles/<id>/users")
  105. @bearer_auth_required
  106. @admin_required
  107. def role_users(id: str):
  108. return success_response(list_role_users(_parse_role_id(id)))
  109. @api_v1.put("/roles/<id>/users")
  110. @bearer_auth_required
  111. @admin_required
  112. @role_edit_required
  113. def update_role_users_route(id: str):
  114. return success_response(update_role_users(_parse_role_id(id), _json_body()))