package svc import "github.com/owncloud/ocis/settings/pkg/proto/v0" func (g Service) hasPermission( roleIDs []string, resource *proto.Resource, operations []proto.Permission_Operation, constraint proto.Permission_Constraint, ) bool { permissions, err := g.manager.ListPermissionsByResource(resource, roleIDs) if err != nil { g.logger.Debug().Err(err). Str("resource-type", resource.Type.String()). Str("resource-id", resource.Id). Msg("permissions could not be loaded for resource") return false } permissions = getFilteredPermissionsByOperations(permissions, operations) return isConstraintFulfilled(permissions, constraint) } // filterPermissionsByOperations returns the subset of the given permissions, where at least one of the given operations is fulfilled. func getFilteredPermissionsByOperations(permissions []*proto.Permission, operations []proto.Permission_Operation) []*proto.Permission { var filteredPermissions []*proto.Permission for _, permission := range permissions { if isAnyOperationFulfilled(permission, operations) { filteredPermissions = append(filteredPermissions, permission) } } return filteredPermissions } // isAnyOperationFulfilled checks if the permissions is about any of the operations func isAnyOperationFulfilled(permission *proto.Permission, operations []proto.Permission_Operation) bool { for _, operation := range operations { if operation == permission.Operation { return true } } return false } // isConstraintFulfilled checks if one of the permissions has the same or a parent of the constraint. // this is only a comparison on ENUM level. More sophisticated checks cannot happen here... func isConstraintFulfilled(permissions []*proto.Permission, constraint proto.Permission_Constraint) bool { for _, permission := range permissions { // comparing enum by order is not a feasible solution, because `SHARED` is not a superset of `OWN`. if permission.Constraint == proto.Permission_CONSTRAINT_ALL { return true } if permission.Constraint != proto.Permission_CONSTRAINT_UNKNOWN && permission.Constraint == constraint { return true } } return false }