package middleware import ( "context" "net/http" "server/internal/db" "server/internal/db/sqlc" "server/internal/pkg/cache" "server/internal/pkg/cache/cachekey" "server/internal/pkg/errs" "server/internal/pkg/httputil" "strings" "github.com/go-chi/chi/v5" ) const ( IsAdminKey contextKey = "is_admin" ) type AuthMiddleware struct { store *db.Store cache *cache.Caches } func NewAuthMiddleware(store *db.Store, cache *cache.Caches) *AuthMiddleware { return &AuthMiddleware{ cache: cache, store: store, } } func (m *AuthMiddleware) Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() var err error claims, ok := GetClaims(ctx) if !ok || claims.UserID == 0 { httputil.Fail(w, errs.ErrUnauthorized) return } // 判断是否有管理员权限 目前只判断uid是否为1 isAdmin := userIsAdmin(claims.UserID) if isAdmin { ctx = context.WithValue(ctx, IsAdminKey, isAdmin) next.ServeHTTP(w, r.WithContext(ctx)) return } // 不是管理员 判断api权限 hasPermission, err := userHasApiPermission(ctx, r, m.store, claims.UserID, m.cache) if err != nil { httputil.Fail(w, err) return } if !hasPermission { httputil.Fail(w, errs.ErrPermissionDenied) return } next.ServeHTTP(w, r) }) } func userIsAdmin(uid int32) bool { if uid == 1 { return true } return false } func userHasApiPermission(ctx context.Context, r *http.Request, store *db.Store, uid int32, c *cache.Caches) (bool, error) { var ( apis []sqlc.GetSysUserApisRow err error ) // 先从缓存中获取api数据 k := cachekey.UserApiPermissions(uid) apis, err = cache.GetOrSetJSON[[]sqlc.GetSysUserApisRow](ctx, c, k, 0, func() ([]sqlc.GetSysUserApisRow, error) { return store.GetSysUserApis(ctx, uid) }) if err != nil { return false, err } requestPath := chi.RouteContext(r.Context()).RoutePattern() requestPath = strings.TrimPrefix(requestPath, "/api") requestMethod := r.Method for _, api := range apis { if api.Path == requestPath && api.Method == requestMethod { return true, nil } } return false, nil }