package v2 import ( "fmt" "github.com/getkin/kin-openapi/openapi3filter" "github.com/google/uuid" "github.com/labstack/echo/v4" "github.com/osbuild/osbuild-composer/internal/auth" ) // getTenantChannel returns the tenant channel for the provided request context func (s *Server) getTenantChannel(ctx echo.Context) (string, error) { // channel is empty if JWT is not enabled var channel string if s.config.JWTEnabled { tenant, err := auth.GetFromClaims(ctx.Request().Context(), s.config.TenantProviderFields) if err != nil { return "", err } // prefix the tenant to prevent collisions if support for specifying channels in a request is ever added channel = "org-" + tenant } return channel, nil } type ComposeHandlerFunc func(ctx echo.Context, id string) error // Ensures that the job's channel matches the JWT cannel set in the echo.Context func (s *Server) EnsureJobChannel(next ComposeHandlerFunc) ComposeHandlerFunc { return func(c echo.Context, id string) error { jobId, err := uuid.Parse(id) if err != nil { return HTTPError(ErrorInvalidComposeId) } ctxChannel, err := s.getTenantChannel(c) if err != nil { return HTTPErrorWithInternal(ErrorTenantNotFound, err) } jobChannel, err := s.workers.JobChannel(jobId) if err != nil { fmt.Println(err) return HTTPErrorWithInternal(ErrorComposeNotFound, err) } if jobChannel != ctxChannel { return HTTPError(ErrorComposeNotFound) } return next(c, id) } } func (s *Server) ValidateRequest(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { request := c.Request() // extract route and parameters from request route, params, err := s.router.FindRoute(request) if err != nil { return HTTPErrorWithInternal(ErrorResourceNotFound, err) } input := &openapi3filter.RequestValidationInput{ Request: request, PathParams: params, Route: route, Options: &openapi3filter.Options{ AuthenticationFunc: openapi3filter.NoopAuthenticationFunc, }, } ctx := request.Context() if err := openapi3filter.ValidateRequest(ctx, input); err != nil { details := "" re, ok := err.(*openapi3filter.RequestError) if ok { details = re.Error() } return HTTPErrorWithDetails(ErrorValidationFailed, err, details) } return next(c) } }