RequireModelAccess returns a global middleware that checks the user is allowed to use the resolved model. It extracts the model name directly from the request (path param, query param, JSON body, or form value) rather than relying on a context key set by downstream route-specific middleware.
(db *gorm.DB)
| 301 | // (path param, query param, JSON body, or form value) rather than relying on a |
| 302 | // context key set by downstream route-specific middleware. |
| 303 | func RequireModelAccess(db *gorm.DB) echo.MiddlewareFunc { |
| 304 | if db == nil { |
| 305 | return NoopMiddleware() |
| 306 | } |
| 307 | return func(next echo.HandlerFunc) echo.HandlerFunc { |
| 308 | return func(c echo.Context) error { |
| 309 | user := GetUser(c) |
| 310 | if user == nil { |
| 311 | return next(c) |
| 312 | } |
| 313 | if user.Role == RoleAdmin { |
| 314 | return next(c) |
| 315 | } |
| 316 | |
| 317 | // Check if this user even has a model allowlist enabled before |
| 318 | // doing the expensive body read. Most users won't have restrictions. |
| 319 | // Uses request-scoped cache to avoid duplicate DB hit when |
| 320 | // RequireRouteFeature already fetched permissions. |
| 321 | perm, err := GetCachedUserPermissions(c, db, user.ID) |
| 322 | if err != nil { |
| 323 | return c.JSON(http.StatusInternalServerError, schema.ErrorResponse{ |
| 324 | Error: &schema.APIError{ |
| 325 | Message: "failed to check permissions", |
| 326 | Code: http.StatusInternalServerError, |
| 327 | Type: "server_error", |
| 328 | }, |
| 329 | }) |
| 330 | } |
| 331 | allowlist := perm.AllowedModels |
| 332 | if !allowlist.Enabled { |
| 333 | return next(c) |
| 334 | } |
| 335 | |
| 336 | modelName := extractModelFromRequest(c) |
| 337 | if modelName == "" { |
| 338 | return next(c) |
| 339 | } |
| 340 | |
| 341 | for _, m := range allowlist.Models { |
| 342 | if m == modelName { |
| 343 | return next(c) |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | return c.JSON(http.StatusForbidden, schema.ErrorResponse{ |
| 348 | Error: &schema.APIError{ |
| 349 | Message: "access denied to model: " + modelName, |
| 350 | Code: http.StatusForbidden, |
| 351 | Type: "authorization_error", |
| 352 | }, |
| 353 | }) |
| 354 | } |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | // extractModelFromRequest extracts the model name from various request sources. |
| 359 | // It checks URL path params, query params, JSON body, and form values. |
no test coverage detected