package middleware import ( "errors" "fmt" "github.com/gin-gonic/gin" "edge-infra.dev/pkg/sds/emergencyaccess/apierror" errorhandler "edge-infra.dev/pkg/sds/emergencyaccess/apierror/handler" "edge-infra.dev/pkg/sds/emergencyaccess/eaconst" "edge-infra.dev/pkg/sds/emergencyaccess/types" ) // SaveAuthToContext returns a gin middleware function that creates a // [types.User] struct from any incoming `X-Auth-XXX` headers, and saves the // struct into the context. Incoming `X-Auth-XXXX` headers must be // pre-authenticated as the middleware does not verify the authenticity of the // data. If no incoming headers are present, an empty user is saved to the // context. // // Requires enabling the [gin.Engine.ContextWithFallback] option. func SaveAuthToContext() gin.HandlerFunc { return func(c *gin.Context) { ctx := c.Request.Context() username := c.Request.Header.Get(eaconst.HeaderAuthKeyUsername) email := c.Request.Header.Get(eaconst.HeaderAuthKeyEmail) roles := c.Request.Header.Values(eaconst.HeaderAuthKeyRoles) banners := c.Request.Header.Values(eaconst.HeaderAuthKeyBanners) user := types.User{ Username: username, Email: email, Roles: roles, Banners: banners, } ctx = types.UserIntoContext(ctx, user) c.Request = c.Request.Clone(ctx) c.Next() } } // VerifyUserDetailsInContext returns a gin middleware function that verifies the // [types.User] struct stored in the context. It makes sure that the Username // and Email fields are valid. If there is no [types.User] in context or the // fields are invalid, it fails with an error. // // Requires enabling the [gin.Engine.ContextWithFallback] option. func VerifyUserDetailsInContext() gin.HandlerFunc { return func(c *gin.Context) { user, ok := types.UserFromContext(c) if !ok { errorhandler.ErrorHandler(c, apierror.E(apierror.ErrUserNotFound, fmt.Errorf("user details not found in authservice request"))) return } var err error if user.Username == "" { err = errors.Join(err, fmt.Errorf("username not found in authservice request")) } if user.Email == "" { err = errors.Join(err, fmt.Errorf("email not found in authservice request")) } if err != nil { errorhandler.ErrorHandler(c, apierror.E(apierror.ErrUserNotFound, err)) return } c.Next() } }