diff --git a/pkg/web/handler/core.go b/pkg/web/handler/core.go index b4cfb9d29..fe2b5be40 100644 --- a/pkg/web/handler/core.go +++ b/pkg/web/handler/core.go @@ -66,3 +66,43 @@ func DoCreate(_ context.Context, obj CObject, a web.Auth) error { events.DispatchPending(s) return nil } + +// DoReadOne runs the permission check + model ReadOne + commit pipeline for a +// CObject. obj should have its identifying fields set before call. On success, +// obj is fully populated. maxPermission is exposed via the x-max-permission +// header in the Echo wrapper; Huma wrapper may ignore it. +func DoReadOne(_ context.Context, obj CObject, a web.Auth) (maxPermission int, err error) { + s := db.NewSession() + defer func() { + if cerr := s.Close(); cerr != nil { + log.Errorf("Could not close session: %s", cerr) + } + }() + + canRead, maxPermission, err := obj.CanRead(s, a) + if err != nil { + _ = s.Rollback() + events.CleanupPending(s) + return 0, err + } + if !canRead { + _ = s.Rollback() + events.CleanupPending(s) + log.Warningf("Tried to read while not having the permissions for it (User: %v)", a) + return 0, echo.NewHTTPError(http.StatusForbidden, "You don't have the permission to see this") + } + + if err := obj.ReadOne(s, a); err != nil { + _ = s.Rollback() + events.CleanupPending(s) + return 0, err + } + + if err := s.Commit(); err != nil { + events.CleanupPending(s) + return 0, err + } + + events.DispatchPending(s) + return maxPermission, nil +} diff --git a/pkg/web/handler/read_one.go b/pkg/web/handler/read_one.go index 8d05e765f..f52c6001a 100644 --- a/pkg/web/handler/read_one.go +++ b/pkg/web/handler/read_one.go @@ -22,8 +22,6 @@ import ( "net/http" "strconv" - "code.vikunja.io/api/pkg/db" - "code.vikunja.io/api/pkg/events" "code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/modules/auth" @@ -52,49 +50,14 @@ func (c *WebHandler) ReadOneWeb(ctx *echo.Context) error { return echo.NewHTTPError(http.StatusInternalServerError, "Could not determine the current user.").Wrap(err) } - // Create the db session - s := db.NewSession() - defer func() { - err = s.Close() - if err != nil { - log.Errorf("Could not close session: %s", err) - } - }() - - canRead, maxPermission, err := currentStruct.CanRead(s, currentAuth) + maxPermission, err := DoReadOne(ctx.Request().Context(), currentStruct, currentAuth) if err != nil { - _ = s.Rollback() - events.CleanupPending(s) - return err - } - if !canRead { - _ = s.Rollback() - events.CleanupPending(s) - log.Warningf("Tried to read while not having the permissions for it (User: %v)", currentAuth) - return echo.NewHTTPError(http.StatusForbidden, "You don't have the permission to see this") - } - - // Get our object - err = currentStruct.ReadOne(s, currentAuth) - if err != nil { - _ = s.Rollback() - events.CleanupPending(s) return err } // Set the headers - if canRead { - ctx.Response().Header().Set("x-max-permission", strconv.FormatInt(int64(maxPermission), 10)) - ctx.Response().Header().Set("Access-Control-Expose-Headers", "x-max-permission") - } - - err = s.Commit() - if err != nil { - events.CleanupPending(s) - return err - } - - events.DispatchPending(s) + ctx.Response().Header().Set("x-max-permission", strconv.FormatInt(int64(maxPermission), 10)) + ctx.Response().Header().Set("Access-Control-Expose-Headers", "x-max-permission") return ctx.JSON(http.StatusOK, currentStruct) }