roles.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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 admin_required, bearer_auth_required
  9. from dms.services.role_service import (
  10. create_role,
  11. delete_role,
  12. list_role_permissions,
  13. list_role_users,
  14. list_roles,
  15. update_role,
  16. update_role_permissions,
  17. update_role_users,
  18. )
  19. def _integer_query(name: str, default: int) -> int:
  20. raw_value = request.args.get(name)
  21. if raw_value is None or raw_value == "":
  22. return default
  23. try:
  24. return int(raw_value)
  25. except ValueError as exc:
  26. raise InvalidArgumentError(f"{name}必须是整数") from exc
  27. def _json_body():
  28. if not request.is_json:
  29. raise InvalidArgumentError("请求体必须是JSON对象")
  30. body = request.get_json(silent=True)
  31. if not isinstance(body, dict):
  32. raise InvalidArgumentError("请求体必须是JSON对象")
  33. return body
  34. def _parse_role_id(value: str) -> int:
  35. if not value.isdecimal() or int(value) <= 0:
  36. raise InvalidArgumentError("id必须是正整数形式的字符串ID")
  37. return int(value)
  38. def _parse_delete_row_version(value: str | None) -> int:
  39. if value is None or not value.isdecimal():
  40. raise InvalidArgumentError("rowVersion必须是非负整数")
  41. return int(value)
  42. @api_v1.get("/roles")
  43. @bearer_auth_required
  44. @admin_required
  45. def roles():
  46. data = list_roles(
  47. keyword=request.args.get("keyword"),
  48. status=request.args.get("status"),
  49. page_request=PageRequest(
  50. page=_integer_query("page", 1),
  51. page_size=_integer_query("pageSize", 20),
  52. ),
  53. )
  54. return success_response(data)
  55. @api_v1.post("/roles")
  56. @bearer_auth_required
  57. @admin_required
  58. def create_role_route():
  59. return success_response(create_role(_json_body()), status=201)
  60. @api_v1.put("/roles/<id>")
  61. @bearer_auth_required
  62. @admin_required
  63. def update_role_route(id: str):
  64. return success_response(update_role(_parse_role_id(id), _json_body()))
  65. @api_v1.delete("/roles/<id>")
  66. @bearer_auth_required
  67. @admin_required
  68. def delete_role_route(id: str):
  69. return success_response(
  70. delete_role(
  71. _parse_role_id(id),
  72. _parse_delete_row_version(request.args.get("rowVersion")),
  73. )
  74. )
  75. @api_v1.get("/roles/<id>/permissions")
  76. @bearer_auth_required
  77. @admin_required
  78. def role_permissions(id: str):
  79. return success_response(list_role_permissions(_parse_role_id(id)))
  80. @api_v1.put("/roles/<id>/permissions")
  81. @bearer_auth_required
  82. @admin_required
  83. def update_role_permissions_route(id: str):
  84. return success_response(
  85. update_role_permissions(_parse_role_id(id), _json_body())
  86. )
  87. @api_v1.get("/roles/<id>/users")
  88. @bearer_auth_required
  89. @admin_required
  90. def role_users(id: str):
  91. return success_response(list_role_users(_parse_role_id(id)))
  92. @api_v1.put("/roles/<id>/users")
  93. @bearer_auth_required
  94. @admin_required
  95. def update_role_users_route(id: str):
  96. return success_response(update_role_users(_parse_role_id(id), _json_body()))