handler_manage.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package auth
  2. import (
  3. "errors"
  4. "net/http"
  5. "time"
  6. "github.com/gin-gonic/gin"
  7. )
  8. // 会话、授信设备、Token 的 handler,对照 docs/api.md 第三、四、五节。
  9. // 这三个资源都只允许会话身份操作(Token 一律 403),在路由层挂 RequireSession。
  10. type listResponse struct {
  11. Items any `json:"items"`
  12. Total int `json:"total"`
  13. }
  14. // ListSessions 实现 GET /api/sessions(api.md 3.1)。
  15. func (h *Handler) ListSessions(c *gin.Context) {
  16. items, err := h.svc.ListSessions(c.Request.Context(), UserID(c), SessionID(c))
  17. if err != nil {
  18. InternalError(c, err)
  19. return
  20. }
  21. c.JSON(http.StatusOK, listResponse{Items: items, Total: len(items)})
  22. }
  23. // DeleteSession 实现 DELETE /api/sessions/:id(api.md 3.2)。
  24. func (h *Handler) DeleteSession(c *gin.Context) {
  25. id := c.Param("id")
  26. createdAt, err := h.svc.FindSessionOwner(c.Request.Context(), UserID(c), id)
  27. if err != nil {
  28. if errors.Is(err, ErrSessionNotFound) {
  29. NotFound(c)
  30. return
  31. }
  32. InternalError(c, err)
  33. return
  34. }
  35. err = h.svc.RevokeSession(c.Request.Context(), UserID(c), id, SessionID(c))
  36. if err != nil {
  37. switch {
  38. case errors.Is(err, ErrCannotRevokeCurrentSession):
  39. ValidationFailed(c, map[string]string{"id": ErrCannotRevokeCurrentSession.Error()})
  40. case errors.Is(err, ErrSessionNotFound):
  41. NotFound(c)
  42. default:
  43. InternalError(c, err)
  44. }
  45. return
  46. }
  47. if h.OnSessionRevoked != nil {
  48. h.OnSessionRevoked(c, h.auditContext(c), id, createdAt.Format(time.RFC3339))
  49. }
  50. c.Status(http.StatusNoContent)
  51. }
  52. // ListTrustedDevices 实现 GET /api/trusted-devices(api.md 4.1)。
  53. func (h *Handler) ListTrustedDevices(c *gin.Context) {
  54. items, err := h.svc.ListTrustedDevices(c.Request.Context(), UserID(c))
  55. if err != nil {
  56. InternalError(c, err)
  57. return
  58. }
  59. c.JSON(http.StatusOK, listResponse{Items: items, Total: len(items)})
  60. }
  61. // DeleteTrustedDevice 实现 DELETE /api/trusted-devices/:id(api.md 4.2)。
  62. func (h *Handler) DeleteTrustedDevice(c *gin.Context) {
  63. id := c.Param("id")
  64. device, err := h.svc.FindTrustedDevice(c.Request.Context(), UserID(c), id)
  65. if err != nil {
  66. if errors.Is(err, ErrTrustedDeviceNotFound) {
  67. NotFound(c)
  68. return
  69. }
  70. InternalError(c, err)
  71. return
  72. }
  73. if err := h.svc.RevokeTrustedDevice(c.Request.Context(), UserID(c), id); err != nil {
  74. if errors.Is(err, ErrTrustedDeviceNotFound) {
  75. NotFound(c)
  76. return
  77. }
  78. InternalError(c, err)
  79. return
  80. }
  81. if h.OnDeviceRevoked != nil {
  82. h.OnDeviceRevoked(c, h.auditContext(c), device.DeviceName)
  83. }
  84. c.Status(http.StatusNoContent)
  85. }
  86. // ListTokens 实现 GET /api/tokens(api.md 5.1)。
  87. func (h *Handler) ListTokens(c *gin.Context) {
  88. items, err := h.svc.ListAPITokens(c.Request.Context(), UserID(c))
  89. if err != nil {
  90. InternalError(c, err)
  91. return
  92. }
  93. c.JSON(http.StatusOK, listResponse{Items: items, Total: len(items)})
  94. }
  95. type createTokenRequest struct {
  96. Name string `json:"name" binding:"required"`
  97. Scope string `json:"scope" binding:"required"`
  98. ExpiresAt *time.Time `json:"expires_at"`
  99. }
  100. // CreateToken 实现 POST /api/tokens(api.md 5.2)。
  101. func (h *Handler) CreateToken(c *gin.Context) {
  102. var req createTokenRequest
  103. if !bind(c, &req) {
  104. return
  105. }
  106. if err := ValidateScope(req.Scope); err != nil {
  107. ValidationFailed(c, map[string]string{"scope": err.Error()})
  108. return
  109. }
  110. created, err := h.svc.CreateAPIToken(c.Request.Context(), UserID(c), req.Name, req.Scope, req.ExpiresAt)
  111. if err != nil {
  112. InternalError(c, err)
  113. return
  114. }
  115. if h.OnTokenCreated != nil {
  116. h.OnTokenCreated(c, h.auditContext(c), created.Name, created.Scope, created.TokenPrefix)
  117. }
  118. // 明文只在这里返回一次(api.md 5.2 / auth.md 第五节规则 1)
  119. c.JSON(http.StatusCreated, created)
  120. }
  121. // DeleteToken 实现 DELETE /api/tokens/:id(api.md 5.3)。
  122. func (h *Handler) DeleteToken(c *gin.Context) {
  123. id := c.Param("id")
  124. token, err := h.svc.RevokeAPIToken(c.Request.Context(), UserID(c), id)
  125. if err != nil {
  126. switch {
  127. case errors.Is(err, ErrTokenNotFound):
  128. NotFound(c)
  129. case errors.Is(err, ErrTokenAlreadyRevoked):
  130. ValidationFailed(c, map[string]string{"id": ErrTokenAlreadyRevoked.Error()})
  131. default:
  132. InternalError(c, err)
  133. }
  134. return
  135. }
  136. if h.OnTokenRevoked != nil {
  137. h.OnTokenRevoked(c, h.auditContext(c), token.Name, token.TokenPrefix)
  138. }
  139. c.Status(http.StatusNoContent)
  140. }
苏ICP备2026082406号
苏公网安备 待审核