users.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. """当前用户、用户分页查询与用户维护写操作。"""
  2. from __future__ import annotations
  3. from flask import request
  4. from sqlalchemy import select
  5. from dms.api.v1.blueprint import api_v1
  6. from dms.common.errors import AuthenticationError, InvalidArgumentError
  7. from dms.common.pagination import PageRequest
  8. from dms.common.response import success_response
  9. from dms.extensions import db
  10. from dms.models import User
  11. from dms.security.auth_context import get_auth_context
  12. from dms.security.decorators import admin_required, bearer_auth_required
  13. from dms.services.user_service import (
  14. create_user,
  15. delete_user,
  16. list_users,
  17. parse_string_id,
  18. reset_user_password,
  19. update_user,
  20. user_summary,
  21. )
  22. def _integer_query(name: str, default: int) -> int:
  23. raw_value = request.args.get(name)
  24. if raw_value is None or raw_value == "":
  25. return default
  26. try:
  27. return int(raw_value)
  28. except ValueError as exc:
  29. raise InvalidArgumentError(f"{name}必须是整数") from exc
  30. def _boolean_query(name: str, default: bool) -> bool:
  31. raw_value = request.args.get(name)
  32. if raw_value is None or raw_value == "":
  33. return default
  34. normalized = raw_value.lower()
  35. if normalized not in {"true", "false"}:
  36. raise InvalidArgumentError(f"{name}必须是true或false")
  37. return normalized == "true"
  38. def _json_body():
  39. if not request.is_json:
  40. raise InvalidArgumentError("请求体必须是JSON对象")
  41. body = request.get_json(silent=True)
  42. if not isinstance(body, dict):
  43. raise InvalidArgumentError("请求体必须是JSON对象")
  44. return body
  45. def _parse_user_id(value: str) -> int:
  46. if not value.isdecimal() or int(value) <= 0:
  47. raise InvalidArgumentError("id必须是正整数形式的字符串ID")
  48. return int(value)
  49. def _parse_delete_row_version(value: str | None) -> int:
  50. if value is None or not value.isdecimal():
  51. raise InvalidArgumentError("rowVersion必须是非负整数")
  52. return int(value)
  53. @api_v1.get("/users/me")
  54. @bearer_auth_required
  55. def current_user():
  56. context = get_auth_context()
  57. user = db.session.scalar(
  58. select(User).where(User.id == context.user_id, User.is_deleted.is_(False))
  59. )
  60. if user is None:
  61. raise AuthenticationError()
  62. return success_response(user_summary(user))
  63. @api_v1.get("/users")
  64. @bearer_auth_required
  65. @admin_required
  66. def users():
  67. page_request = PageRequest(
  68. page=_integer_query("page", 1),
  69. page_size=_integer_query("pageSize", 20),
  70. )
  71. data = list_users(
  72. organization_id=parse_string_id(
  73. request.args.get("organizationId"),
  74. name="organizationId",
  75. ),
  76. include_descendants=_boolean_query("includeDescendants", False),
  77. keyword=request.args.get("keyword"),
  78. status=request.args.get("status"),
  79. page_request=page_request,
  80. )
  81. return success_response(data)
  82. @api_v1.post("/users")
  83. @bearer_auth_required
  84. @admin_required
  85. def create_user_route():
  86. return success_response(create_user(_json_body()), status=201)
  87. @api_v1.put("/users/<id>")
  88. @bearer_auth_required
  89. @admin_required
  90. def update_user_route(id: str):
  91. return success_response(update_user(_parse_user_id(id), _json_body()))
  92. @api_v1.delete("/users/<id>")
  93. @bearer_auth_required
  94. @admin_required
  95. def delete_user_route(id: str):
  96. return success_response(
  97. delete_user(
  98. _parse_user_id(id),
  99. _parse_delete_row_version(request.args.get("rowVersion")),
  100. )
  101. )
  102. @api_v1.post("/users/<id>/reset-password")
  103. @bearer_auth_required
  104. @admin_required
  105. def reset_user_password_route(id: str):
  106. return success_response(
  107. reset_user_password(_parse_user_id(id), _json_body())
  108. )