admin_compliance.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. package middleware
  2. import (
  3. "net/http"
  4. "strings"
  5. "github.com/Wei-Shaw/sub2api/internal/service"
  6. "github.com/gin-gonic/gin"
  7. )
  8. func AdminComplianceGuard(settingService *service.SettingService) gin.HandlerFunc {
  9. return func(c *gin.Context) {
  10. if settingService == nil || isAdminComplianceBypassPath(c.Request.URL.Path) {
  11. c.Next()
  12. return
  13. }
  14. subject, ok := GetAuthSubjectFromContext(c)
  15. if !ok {
  16. AbortWithError(c, http.StatusUnauthorized, "UNAUTHORIZED", "Authorization required")
  17. return
  18. }
  19. acknowledged, err := settingService.IsAdminComplianceAcknowledged(c.Request.Context(), subject.UserID)
  20. if err != nil {
  21. AbortWithError(c, http.StatusInternalServerError, "INTERNAL_ERROR", "Internal server error")
  22. return
  23. }
  24. if acknowledged {
  25. c.Next()
  26. return
  27. }
  28. c.JSON(http.StatusLocked, gin.H{
  29. "code": "ADMIN_COMPLIANCE_ACK_REQUIRED",
  30. "message": "administrator compliance acknowledgement is required",
  31. "metadata": gin.H{
  32. "version": service.AdminComplianceVersion,
  33. "document_path_zh": service.AdminComplianceDocumentPathZH,
  34. "document_path_en": service.AdminComplianceDocumentPathEN,
  35. "document_url_zh": service.AdminComplianceDocumentURLZH,
  36. "document_url_en": service.AdminComplianceDocumentURLEN,
  37. },
  38. })
  39. c.Abort()
  40. }
  41. }
  42. func isAdminComplianceBypassPath(path string) bool {
  43. path = strings.TrimSpace(path)
  44. return path == "/api/v1/admin/compliance" || strings.HasPrefix(path, "/api/v1/admin/compliance/")
  45. }