upstream sync

This commit is contained in:
Senad Uka
2018-05-03 07:55:09 +02:00
parent 99c10b75fb
commit 50a6362b67
26 changed files with 530 additions and 172 deletions

View File

@@ -1,6 +1,8 @@
package serverconfig
import (
"fmt"
"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/infra/auth"
@@ -44,6 +46,8 @@ func MiddlewareWithConfig(cfg *config.Config, svc *applicationservice.Service, l
config := &DefaultConfig
config.Enforcer = casbin.NewEnforcer("authorization_model.conf", "authorization_policy.csv")
config.Svc = svc
config.Logger = log
config.Application = cfg
@@ -68,26 +72,130 @@ func setAuthorizationMiddleware(e *echo.Echo, log *logger.Logger, cfg *config.Co
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)
a.Logger.Warningf("Cannot get user details. %v\n", err)
user = viewmodel.User{}
}
method := c.Request().Method
path := c.Request().URL.Path
//objectOrganization := a.organizationGoverningObject(c, user)
return a.Enforcer.Enforce(user, path, method)
objectsRole, objectsOrganization, objectsOrganizationType, object := a.policyObjectAttributes(c, user)
currentUsersOrganization := viewmodel.Organization{}
if len(user.Organizations) > 0 {
currentUsersOrganization = user.Organizations[0]
}
currentUsersRole := viewmodel.Profile{}
if len(user.Profiles) > 0 {
currentUsersRole = user.Profiles[0]
}
currentUsersOrganizationType := ""
if len(user.Profiles) > 0 {
currentUsersOrganizationType = user.Profiles[0].Organization.Type.Key
}
orgRelation := organizationsRelation(currentUsersOrganization, objectsOrganization)
objRelation := a.objectRelation(object, user)
// parameters to Enforce must match the request section of the authorization_model.conf
return a.Enforcer.Enforce(currentUsersRole.Key,
objectsRole.Key,
objectsOrganizationType,
currentUsersOrganizationType,
orgRelation,
objRelation,
path,
method)
}
func (a *Config) organizationGoverningObject(c echo.Context, userDetails viewmodel.User) (result viewmodel.Organization) {
// policyObjectAttributes returns all information about the object being accessed for the policy
// in case object exists and returns users information if it is a new object
func (a *Config) policyObjectAttributes(c echo.Context, userDetails viewmodel.User) (viewmodel.Profile, viewmodel.Organization, string, interface{}) {
existingUser := strings.Contains(c.Request().URL.Path, "/users") && len(c.ParamValues()) > 0
newUser := strings.Contains(c.Request().URL.Path, "/users") && len(c.ParamValues()) <= 0
var object interface{}
const userIDParamName = "user_uuid"
existingUser := strings.Contains(c.Request().URL.Path, "/users/") && c.Param(userIDParamName) != ""
newUser := strings.Contains(c.Request().URL.Path, "/users/") && c.Param(userIDParamName) == ""
const organizationIDParamName = "org_uuid"
existingOrganization := strings.Contains(c.Request().URL.Path, "/organization") && c.Param(organizationIDParamName) != ""
newOrganization := strings.Contains(c.Request().URL.Path, "/organization") && c.Param(organizationIDParamName) == ""
fmt.Println("**********")
fmt.Printf("url %v\n", c.Param(userIDParamName))
fmt.Printf("user %v\n", userDetails.ID)
fmt.Printf("existing %v\n", existingUser)
fmt.Printf("new %v\n", newUser)
fmt.Println("**********")
switch {
case existingUser:
user, _ := a.Svc.Users.GetByUUID(c.ParamValues()[0], "")
result = user.Organizations[0]
case newUser:
result = userDetails.Organizations[0]
object, _ = a.Svc.Users.GetByUUID(c.Param(userIDParamName), "")
case newUser && len(userDetails.Organizations) > 0:
object = userDetails
case existingOrganization:
object, _ = a.Svc.Organization.GetByUUID(c.Param(organizationIDParamName), userDetails)
case newOrganization:
object = viewmodel.Organization{}
}
return
objectsRole := viewmodel.Profile{}
switch obj := object.(type) {
case viewmodel.User:
if len(obj.Profiles) > 0 {
objectsRole = obj.Profiles[0]
}
}
objectsOrganization := viewmodel.Organization{}
switch obj := object.(type) {
case viewmodel.User:
if len(obj.Profiles) > 0 {
objectsOrganization = obj.Profiles[0].Organization
}
case viewmodel.Organization:
objectsOrganization = obj
}
objectsOrganizationType := objectsOrganization.Type.Key
return objectsRole, objectsOrganization, objectsOrganizationType, object
}
func organizationsRelation(requestOrganization, currentUsersOrganization viewmodel.Organization) string {
if requestOrganization.UUID == currentUsersOrganization.UUID {
return "[equal]"
}
for _, childOrg := range currentUsersOrganization.ChildOrgs {
if childOrg.UUID == requestOrganization.UUID {
return "[equal-or-child]"
}
}
for _, childOrg := range requestOrganization.ChildOrgs {
if childOrg.UUID == currentUsersOrganization.UUID {
return "[parent]"
}
}
return "[unrelated]"
}
// organizationGoverningObject returns the role that is the owner of the object that is being accessed
// in case object exists and returns users role if it is a new object
func (a *Config) objectRelation(object interface{}, currentUser viewmodel.User) string {
switch obj := object.(type) {
case viewmodel.User:
if obj.ID == currentUser.ID {
return "[self]"
} else {
return "[other]"
}
}
return "[other]"
}