角色权限、RequirePermission、/me permissions 与 migration 000015; Reviewer Approve → Closed。Next:ECR-013B Contract Definition。 Co-authored-by: Cursor <cursoragent@cursor.com>
43 lines
1.2 KiB
Go
43 lines
1.2 KiB
Go
package middleware
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/yuxingu/digital-psychology/apps/api/pkg/response"
|
|
)
|
|
|
|
// AdminPermissionChecker validates admin permission codes.
|
|
type AdminPermissionChecker interface {
|
|
HasPermission(ctx context.Context, adminID uuid.UUID, code string) (bool, error)
|
|
DenyPermission(ctx context.Context, adminID uuid.UUID, code, path string)
|
|
}
|
|
|
|
// RequireAdminPermission aborts with 403 when the admin lacks code.
|
|
func RequireAdminPermission(checker AdminPermissionChecker, code string) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
adminID, ok := AdminIDFromContext(c)
|
|
if !ok {
|
|
response.Fail(c, http.StatusUnauthorized, 40102, "admin session invalid")
|
|
c.Abort()
|
|
return
|
|
}
|
|
okPerm, err := checker.HasPermission(c.Request.Context(), adminID, code)
|
|
if err != nil {
|
|
response.Fail(c, http.StatusInternalServerError, 50000, "permission check failed")
|
|
c.Abort()
|
|
return
|
|
}
|
|
if !okPerm {
|
|
checker.DenyPermission(c.Request.Context(), adminID, code, c.FullPath())
|
|
response.Fail(c, http.StatusForbidden, 40301, "forbidden")
|
|
c.Abort()
|
|
return
|
|
}
|
|
c.Next()
|
|
}
|
|
}
|