package serverconfig import ( "bitbucket.org/nemt/nemt-portal-api/application/applicationservice" "bitbucket.org/nemt/nemt-portal-api/application/viewmodel" "bitbucket.org/nemt/nemt-portal-api/infra/auth" "bitbucket.org/nemt/nemt-portal-api/infra/config" "bitbucket.org/nemt/nemt-portal-api/infra/logger" "bitbucket.org/nemt/nemt-portal-api/server/router/routeutils" "github.com/casbin/casbin" "github.com/labstack/echo" "github.com/labstack/echo/middleware" "strings" ) type ( // Config defines the config for CasbinAuth middleware. Config struct { // Skipper defines a function to skip middleware. Skipper middleware.Skipper // Enforcer CasbinAuth main rule. // Required. Enforcer *casbin.Enforcer Application *config.Config Svc *applicationservice.Service Logger *logger.Logger } ) var ( // DefaultConfig is the default CasbinAuth middleware config. DefaultConfig = Config{ Skipper: middleware.DefaultSkipper, } ) // MiddlewareWithConfig returns a CasbinAuth middleware with config. // See `Middleware()`. func MiddlewareWithConfig(cfg *config.Config, svc *applicationservice.Service, log *logger.Logger) echo.MiddlewareFunc { config := &DefaultConfig config.Svc = svc config.Logger = log config.Application = cfg return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { if config.Skipper(c) || config.CheckPermission(c) { return next(c) } return routeutils.HandleHTMLError(c, echo.ErrForbidden) } } } func setAuthorizationMiddleware(e *echo.Echo, log *logger.Logger, cfg *config.Config, svc *applicationservice.Service) { e.Use(MiddlewareWithConfig(cfg, svc, log)) } // CheckPermission checks the user/method/path combination from the request. // Returns true (permission granted) or false (permission forbidden) func (a *Config) CheckPermission(c echo.Context) bool { user, err := auth.GetUserDetail(c, a.Application) if err != nil { a.Logger.Warningf("Cannot get user details. %v ", err) } method := c.Request().Method path := c.Request().URL.Path //objectOrganization := a.organizationGoverningObject(c, user) return a.Enforcer.Enforce(user, path, method) } func (a *Config) organizationGoverningObject(c echo.Context, userDetails viewmodel.User) (result viewmodel.Organization) { existingUser := strings.Contains(c.Request().URL.Path, "/users") && len(c.ParamValues()) > 0 newUser := strings.Contains(c.Request().URL.Path, "/users") && len(c.ParamValues()) <= 0 switch { case existingUser: user, _ := a.Svc.Users.GetByUUID(c.ParamValues()[0], "") result = user.Organizations[0] case newUser: result = userDetails.Organizations[0] } return }