mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-06 04:09:40 -06:00
enhancement: add unified roles filters
This commit is contained in:
@@ -2104,6 +2104,7 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on =
|
||||
"NATS_NATS_PORT": 9233,
|
||||
"OCIS_JWT_SECRET": "some-ocis-jwt-secret",
|
||||
"EVENTHISTORY_STORE": "memory",
|
||||
"UNIFIED_ROLES_AVAILABLE_ROLES": "b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5,a8d5fe5e-96e3-418d-825b-534dbdf22b99,fb6c3e19-e378-47e5-b277-9732f9de6e21,58c63c02-1d89-4572-916a-870abc5a1b7d,2d00ce52-1fc2-4dbc-8b95-a73b73395f5a,1c996275-f1c9-4e71-abdf-a42f6495e960,312c0871-5ef7-4b3a-85b6-0e4074c64049,aa97fe03-7980-45ac-9e50-b325749fd7e6",
|
||||
}
|
||||
|
||||
if deploy_type == "":
|
||||
|
||||
@@ -25,7 +25,7 @@ To enable a role, include the UID of the role in the list of available roles.
|
||||
|
||||
A new command has been introduced to simplify the process of finding out which UID belongs to which role. The command is:
|
||||
|
||||
```bash
|
||||
```
|
||||
$ ocis graph list-unified-roles
|
||||
```
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ func unifiedRolesStatus(cfg *config.Config) *cli.Command {
|
||||
|
||||
var data [][]string
|
||||
|
||||
for _, definition := range unifiedrole.GetBuiltinRoleDefinitionList() {
|
||||
for _, definition := range unifiedrole.GetDefinitions(unifiedrole.RoleFilterAll()) {
|
||||
data = append(data, []string{"", definition.GetId(), definition.GetDescription()})
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ func EnsureDefaults(cfg *config.Config) {
|
||||
|
||||
// set default roles, if no roles are defined, we need to take care and provide all the default roles
|
||||
if len(cfg.UnifiedRoles.AvailableRoles) == 0 {
|
||||
for _, definition := range unifiedrole.GetBuiltinRoleDefinitionList(
|
||||
for _, definition := range unifiedrole.GetDefinitions(
|
||||
// filter out the roles that are disabled by default
|
||||
unifiedrole.RoleFilterInvert(unifiedrole.RoleFilterIDs(_disabledByDefaultUnifiedRoleRoleIDs...)),
|
||||
) {
|
||||
|
||||
@@ -8,12 +8,11 @@ import (
|
||||
|
||||
ociscfg "github.com/owncloud/ocis/v2/ocis-pkg/config"
|
||||
defaults2 "github.com/owncloud/ocis/v2/ocis-pkg/config/defaults"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/config/envdecode"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/config"
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults"
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/config/envdecode"
|
||||
)
|
||||
|
||||
// ParseConfig loads configuration from known paths.
|
||||
@@ -80,7 +79,7 @@ func Validate(cfg *config.Config) error {
|
||||
|
||||
for _, uid := range cfg.UnifiedRoles.AvailableRoles {
|
||||
// check if the role is known
|
||||
if len(unifiedrole.GetBuiltinRoleDefinitionList(unifiedrole.RoleFilterIDs(uid))) == 0 {
|
||||
if len(unifiedrole.GetDefinitions(unifiedrole.RoleFilterIDs(uid))) == 0 {
|
||||
// collect all possible errors to return them all at once
|
||||
err = errors.Join(err, fmt.Errorf("%w: %s", unifiedrole.ErrUnknownUnifiedRole, uid))
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/grants"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole"
|
||||
)
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ func (s DriveItemPermissionsService) Invite(ctx context.Context, resourceId *sto
|
||||
return libregraph.Permission{}, unifiedrole.ErrUnknownUnifiedRole
|
||||
}
|
||||
|
||||
role, err := unifiedrole.NewUnifiedRoleFromID(roleID)
|
||||
role, err := unifiedrole.GetDefinition(unifiedrole.RoleFilterIDs(roleID))
|
||||
if err != nil {
|
||||
s.logger.Debug().Err(err).Interface("role", invite.GetRoles()[0]).Msg("unable to convert requested role")
|
||||
return libregraph.Permission{}, err
|
||||
@@ -129,7 +129,7 @@ func (s DriveItemPermissionsService) Invite(ctx context.Context, resourceId *sto
|
||||
cs3ResourcePermissions := unifiedrole.PermissionsToCS3ResourcePermissions(unifiedRolePermissions)
|
||||
|
||||
permission := &libregraph.Permission{}
|
||||
if role := unifiedrole.CS3ResourcePermissionsToUnifiedRole(cs3ResourcePermissions, condition); role != nil {
|
||||
if role := unifiedrole.CS3ResourcePermissionsToDefinition(cs3ResourcePermissions, condition); role != nil {
|
||||
permission.Roles = []string{role.GetId()}
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ func (s DriveItemPermissionsService) ListPermissions(ctx context.Context, itemID
|
||||
collectionOfPermissions = libregraph.CollectionOfPermissionsWithAllowedValues{
|
||||
LibreGraphPermissionsActionsAllowedValues: allowedActions,
|
||||
LibreGraphPermissionsRolesAllowedValues: conversions.ToValueSlice(
|
||||
unifiedrole.GetApplicableRoleDefinitionsForActions(
|
||||
unifiedrole.GetRolesByPermissions(
|
||||
allowedActions,
|
||||
condition,
|
||||
listFederatedRoles,
|
||||
|
||||
@@ -169,13 +169,13 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
driveItemInvite.Recipients = []libregraph.DriveRecipient{
|
||||
{ObjectId: libregraph.PtrString("1"), LibreGraphRecipientType: libregraph.PtrString("user")},
|
||||
}
|
||||
driveItemInvite.Roles = []string{unifiedrole.NewViewerUnifiedRole().GetId()}
|
||||
driveItemInvite.Roles = []string{unifiedrole.UnifiedRoleViewerID}
|
||||
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(permission.GetRoles()).To(HaveLen(1))
|
||||
Expect(permission.GetRoles()[0]).To(Equal(unifiedrole.NewViewerUnifiedRole().GetId()))
|
||||
Expect(permission.GetRoles()[0]).To(Equal(unifiedrole.UnifiedRoleViewerID))
|
||||
})
|
||||
|
||||
It("succeeds with folder roles (happy path)", func() {
|
||||
@@ -185,20 +185,20 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
driveItemInvite.Recipients = []libregraph.DriveRecipient{
|
||||
{ObjectId: libregraph.PtrString("1"), LibreGraphRecipientType: libregraph.PtrString("user")},
|
||||
}
|
||||
driveItemInvite.Roles = []string{unifiedrole.NewEditorUnifiedRole().GetId()}
|
||||
driveItemInvite.Roles = []string{unifiedrole.UnifiedRoleEditorID}
|
||||
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
Expect(permission.GetRoles()).To(HaveLen(1))
|
||||
Expect(permission.GetRoles()[0]).To(Equal(unifiedrole.NewEditorUnifiedRole().GetId()))
|
||||
Expect(permission.GetRoles()[0]).To(Equal(unifiedrole.UnifiedRoleEditorID))
|
||||
})
|
||||
|
||||
It("fails with when trying to set a space role on a file", func() {
|
||||
driveItemInvite.Recipients = []libregraph.DriveRecipient{
|
||||
{ObjectId: libregraph.PtrString("1"), LibreGraphRecipientType: libregraph.PtrString("user")},
|
||||
}
|
||||
driveItemInvite.Roles = []string{unifiedrole.NewManagerUnifiedRole().GetId()}
|
||||
driveItemInvite.Roles = []string{unifiedrole.UnifiedRoleManagerID}
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
|
||||
Expect(err).To(MatchError(errorcode.New(errorcode.InvalidRequest, "role not applicable to this resource")))
|
||||
@@ -209,7 +209,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
driveItemInvite.Recipients = []libregraph.DriveRecipient{
|
||||
{ObjectId: libregraph.PtrString("1"), LibreGraphRecipientType: libregraph.PtrString("user")},
|
||||
}
|
||||
driveItemInvite.Roles = []string{unifiedrole.NewEditorUnifiedRole().GetId()}
|
||||
driveItemInvite.Roles = []string{unifiedrole.UnifiedRoleEditorID}
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
|
||||
Expect(err).To(MatchError(errorcode.New(errorcode.InvalidRequest, "role not applicable to this resource")))
|
||||
@@ -221,7 +221,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
driveItemInvite.Recipients = []libregraph.DriveRecipient{
|
||||
{ObjectId: libregraph.PtrString("1"), LibreGraphRecipientType: libregraph.PtrString("user")},
|
||||
}
|
||||
driveItemInvite.Roles = []string{unifiedrole.NewFileEditorUnifiedRole().GetId()}
|
||||
driveItemInvite.Roles = []string{unifiedrole.UnifiedRoleFileEditorID}
|
||||
permission, err := driveItemPermissionsService.Invite(context.Background(), driveItemId, driveItemInvite)
|
||||
|
||||
Expect(err).To(MatchError(errorcode.New(errorcode.InvalidRequest, "role not applicable to this resource")))
|
||||
@@ -836,7 +836,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
|
||||
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
|
||||
|
||||
driveItemPermission.SetRoles([]string{unifiedrole.NewSpaceViewerUnifiedRole().GetId()})
|
||||
driveItemPermission.SetRoles([]string{unifiedrole.UnifiedRoleSpaceViewerID})
|
||||
res, err := driveItemPermissionsService.UpdatePermission(context.Background(), driveItemId, "permissionid", driveItemPermission)
|
||||
Expect(err).To(MatchError(errorcode.New(errorcode.InvalidRequest, "role not applicable to this resource")))
|
||||
Expect(res).To(BeZero())
|
||||
@@ -853,7 +853,7 @@ var _ = Describe("DriveItemPermissionsService", func() {
|
||||
gatewayClient.On("Stat", mock.Anything, mock.Anything).Return(statResponse, nil)
|
||||
gatewayClient.On("GetUser", mock.Anything, mock.Anything).Return(getUserResponse, nil)
|
||||
|
||||
driveItemPermission.SetRoles([]string{unifiedrole.NewFileEditorUnifiedRole().GetId()})
|
||||
driveItemPermission.SetRoles([]string{unifiedrole.UnifiedRoleFileEditorID})
|
||||
spaceId := &provider.ResourceId{
|
||||
StorageId: "1",
|
||||
SpaceId: "2",
|
||||
@@ -1036,7 +1036,7 @@ var _ = Describe("DriveItemPermissionsApi", func() {
|
||||
ObjectId: libregraph.PtrString("1"),
|
||||
LibreGraphRecipientType: libregraph.PtrString("user")},
|
||||
},
|
||||
Roles: []string{unifiedrole.NewViewerUnifiedRole().GetId()},
|
||||
Roles: []string{unifiedrole.UnifiedRoleViewerID},
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -191,10 +191,10 @@ func (g BaseGraphService) cs3SpacePermissionsToLibreGraph(ctx context.Context, s
|
||||
p.SetExpirationDateTime(time.Unix(int64(exp.GetSeconds()), int64(exp.GetNanos())))
|
||||
}
|
||||
|
||||
if role := unifiedrole.CS3ResourcePermissionsToUnifiedRole(perm, unifiedrole.UnifiedRoleConditionDrive); role != nil {
|
||||
if role := unifiedrole.CS3ResourcePermissionsToDefinition(perm, unifiedrole.UnifiedRoleConditionDrive); role != nil {
|
||||
switch apiVersion {
|
||||
case APIVersion_1:
|
||||
if r := unifiedrole.GetLegacyName(*role); r != "" {
|
||||
if r := unifiedrole.GetLegacyDefinitionName(*role); r != "" {
|
||||
p.SetRoles([]string{r})
|
||||
}
|
||||
case APIVersion_1_Beta_1:
|
||||
@@ -392,7 +392,7 @@ func (g BaseGraphService) cs3UserShareToPermission(ctx context.Context, share *c
|
||||
if share.GetCtime() != nil {
|
||||
perm.SetCreatedDateTime(cs3TimestampToTime(share.GetCtime()))
|
||||
}
|
||||
role := unifiedrole.CS3ResourcePermissionsToUnifiedRole(
|
||||
role := unifiedrole.CS3ResourcePermissionsToDefinition(
|
||||
share.GetPermissions().GetPermissions(),
|
||||
roleCondition,
|
||||
)
|
||||
@@ -695,7 +695,7 @@ func (g BaseGraphService) updateUserShare(ctx context.Context, permissionID stri
|
||||
var permissionsUpdated, ok bool
|
||||
if roles, ok = newPermission.GetRolesOk(); ok && len(roles) > 0 {
|
||||
for _, roleID := range roles {
|
||||
role, err := unifiedrole.NewUnifiedRoleFromID(roleID)
|
||||
role, err := unifiedrole.GetDefinition(unifiedrole.RoleFilterIDs(roleID))
|
||||
if err != nil {
|
||||
g.logger.Debug().Err(err).Interface("role", role).Msg("unable to convert requested role")
|
||||
return nil, err
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/render"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/errorcode"
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole"
|
||||
@@ -15,7 +14,7 @@ import (
|
||||
// GetRoleDefinitions a list of permission roles than can be used when sharing with users or groups
|
||||
func (g Graph) GetRoleDefinitions(w http.ResponseWriter, r *http.Request) {
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, unifiedrole.GetBuiltinRoleDefinitionList(unifiedrole.RoleFilterIDs(g.config.UnifiedRoles.AvailableRoles...)))
|
||||
render.JSON(w, r, unifiedrole.GetDefinitions(unifiedrole.RoleFilterIDs(g.config.UnifiedRoles.AvailableRoles...)))
|
||||
}
|
||||
|
||||
// GetRoleDefinition a permission role than can be used when sharing with users or groups
|
||||
@@ -27,7 +26,7 @@ func (g Graph) GetRoleDefinition(w http.ResponseWriter, r *http.Request) {
|
||||
errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "unescaping role id failed")
|
||||
return
|
||||
}
|
||||
role, err := getRoleDefinition(roleID, g.config.UnifiedRoles.AvailableRoles)
|
||||
role, err := unifiedrole.GetDefinition(unifiedrole.RoleFilterIDs(roleID))
|
||||
if err != nil {
|
||||
logger.Debug().Str("roleID", roleID).Msg("could not get role: not found")
|
||||
errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, err.Error())
|
||||
@@ -36,12 +35,3 @@ func (g Graph) GetRoleDefinition(w http.ResponseWriter, r *http.Request) {
|
||||
render.Status(r, http.StatusOK)
|
||||
render.JSON(w, r, role)
|
||||
}
|
||||
|
||||
func getRoleDefinition(roleID string, availableRoles []string) (*libregraph.UnifiedRoleDefinition, error) {
|
||||
for _, role := range unifiedrole.GetBuiltinRoleDefinitionList(unifiedrole.RoleFilterIDs(availableRoles...)) {
|
||||
if role != nil && role.Id != nil && *role.Id == roleID {
|
||||
return role, nil
|
||||
}
|
||||
}
|
||||
return nil, unifiedrole.ErrUnknownUnifiedRole
|
||||
}
|
||||
|
||||
@@ -16,11 +16,12 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/errorcode"
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/identity"
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// StrictJSONUnmarshal is a wrapper around json.Unmarshal that returns an error if the json contains unknown fields.
|
||||
@@ -426,7 +427,7 @@ func cs3ReceivedShareToLibreGraphPermissions(ctx context.Context, logger *log.Lo
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
role := unifiedrole.CS3ResourcePermissionsToUnifiedRole(permissionSet, condition)
|
||||
role := unifiedrole.CS3ResourcePermissionsToDefinition(permissionSet, condition)
|
||||
|
||||
if role != nil {
|
||||
permission.SetRoles([]string{role.GetId()})
|
||||
|
||||
226
services/graph/pkg/unifiedrole/conversion.go
Normal file
226
services/graph/pkg/unifiedrole/conversion.go
Normal file
@@ -0,0 +1,226 @@
|
||||
package unifiedrole
|
||||
|
||||
import (
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/cs3org/reva/v2/pkg/conversions"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
)
|
||||
|
||||
// PermissionsToCS3ResourcePermissions converts the provided libregraph UnifiedRolePermissions to a cs3 ResourcePermissions
|
||||
func PermissionsToCS3ResourcePermissions(unifiedRolePermissions []*libregraph.UnifiedRolePermission) *provider.ResourcePermissions {
|
||||
p := &provider.ResourcePermissions{}
|
||||
|
||||
for _, permission := range unifiedRolePermissions {
|
||||
for _, allowedResourceAction := range permission.AllowedResourceActions {
|
||||
switch allowedResourceAction {
|
||||
case DriveItemPermissionsCreate:
|
||||
p.AddGrant = true
|
||||
case DriveItemChildrenCreate:
|
||||
p.CreateContainer = true
|
||||
case DriveItemStandardDelete:
|
||||
p.Delete = true
|
||||
case DriveItemPathRead:
|
||||
p.GetPath = true
|
||||
case DriveItemQuotaRead:
|
||||
p.GetQuota = true
|
||||
case DriveItemContentRead:
|
||||
p.InitiateFileDownload = true
|
||||
case DriveItemUploadCreate:
|
||||
p.InitiateFileUpload = true
|
||||
case DriveItemPermissionsRead:
|
||||
p.ListGrants = true
|
||||
case DriveItemChildrenRead:
|
||||
p.ListContainer = true
|
||||
case DriveItemVersionsRead:
|
||||
p.ListFileVersions = true
|
||||
case DriveItemDeletedRead:
|
||||
p.ListRecycle = true
|
||||
case DriveItemPathUpdate:
|
||||
p.Move = true
|
||||
case DriveItemPermissionsDelete:
|
||||
p.RemoveGrant = true
|
||||
case DriveItemDeletedDelete:
|
||||
p.PurgeRecycle = true
|
||||
case DriveItemVersionsUpdate:
|
||||
p.RestoreFileVersion = true
|
||||
case DriveItemDeletedUpdate:
|
||||
p.RestoreRecycleItem = true
|
||||
case DriveItemBasicRead:
|
||||
p.Stat = true
|
||||
case DriveItemPermissionsUpdate:
|
||||
p.UpdateGrant = true
|
||||
case DriveItemPermissionsDeny:
|
||||
p.DenyGrant = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// CS3ResourcePermissionsToLibregraphActions converts the provided cs3 ResourcePermissions to a list of
|
||||
// libregraph actions
|
||||
func CS3ResourcePermissionsToLibregraphActions(p *provider.ResourcePermissions) []string {
|
||||
var actions []string
|
||||
|
||||
if p.GetAddGrant() {
|
||||
actions = append(actions, DriveItemPermissionsCreate)
|
||||
}
|
||||
|
||||
if p.GetCreateContainer() {
|
||||
actions = append(actions, DriveItemChildrenCreate)
|
||||
}
|
||||
|
||||
if p.GetDelete() {
|
||||
actions = append(actions, DriveItemStandardDelete)
|
||||
}
|
||||
|
||||
if p.GetGetPath() {
|
||||
actions = append(actions, DriveItemPathRead)
|
||||
}
|
||||
|
||||
if p.GetGetQuota() {
|
||||
actions = append(actions, DriveItemQuotaRead)
|
||||
}
|
||||
|
||||
if p.GetInitiateFileDownload() {
|
||||
actions = append(actions, DriveItemContentRead)
|
||||
}
|
||||
|
||||
if p.GetInitiateFileUpload() {
|
||||
actions = append(actions, DriveItemUploadCreate)
|
||||
}
|
||||
|
||||
if p.GetListGrants() {
|
||||
actions = append(actions, DriveItemPermissionsRead)
|
||||
}
|
||||
|
||||
if p.GetListContainer() {
|
||||
actions = append(actions, DriveItemChildrenRead)
|
||||
}
|
||||
|
||||
if p.GetListFileVersions() {
|
||||
actions = append(actions, DriveItemVersionsRead)
|
||||
}
|
||||
|
||||
if p.GetListRecycle() {
|
||||
actions = append(actions, DriveItemDeletedRead)
|
||||
}
|
||||
|
||||
if p.GetMove() {
|
||||
actions = append(actions, DriveItemPathUpdate)
|
||||
}
|
||||
|
||||
if p.GetRemoveGrant() {
|
||||
actions = append(actions, DriveItemPermissionsDelete)
|
||||
}
|
||||
|
||||
if p.GetPurgeRecycle() {
|
||||
actions = append(actions, DriveItemDeletedDelete)
|
||||
}
|
||||
|
||||
if p.GetRestoreFileVersion() {
|
||||
actions = append(actions, DriveItemVersionsUpdate)
|
||||
}
|
||||
|
||||
if p.GetRestoreRecycleItem() {
|
||||
actions = append(actions, DriveItemDeletedUpdate)
|
||||
}
|
||||
|
||||
if p.GetStat() {
|
||||
actions = append(actions, DriveItemBasicRead)
|
||||
}
|
||||
|
||||
if p.GetUpdateGrant() {
|
||||
actions = append(actions, DriveItemPermissionsUpdate)
|
||||
}
|
||||
|
||||
if p.GetDenyGrant() {
|
||||
actions = append(actions, DriveItemPermissionsDeny)
|
||||
}
|
||||
|
||||
return actions
|
||||
}
|
||||
|
||||
// CS3ResourcePermissionsToDefinition tries to find the UnifiedRoleDefinition that matches the supplied
|
||||
// CS3 ResourcePermissions and constraints.
|
||||
func _CS3ResourcePermissionsToDefinition(p *provider.ResourcePermissions, constraints string) *libregraph.UnifiedRoleDefinition {
|
||||
a := CS3ResourcePermissionsToLibregraphActions(p)
|
||||
actionSet := map[string]struct{}{}
|
||||
for _, action := range a {
|
||||
actionSet[action] = struct{}{}
|
||||
}
|
||||
|
||||
var res *libregraph.UnifiedRoleDefinition
|
||||
for _, uRole := range GetDefinitions(RoleFilterAll()) {
|
||||
matchFound := false
|
||||
for _, uPerm := range uRole.GetRolePermissions() {
|
||||
if uPerm.GetCondition() != constraints {
|
||||
// the requested constraints don't match, this isn't our role
|
||||
continue
|
||||
}
|
||||
|
||||
// if the actions converted from the ResourcePermissions equal the action the defined for the role, we have match
|
||||
if resourceActionsEqual(actionSet, uPerm.GetAllowedResourceActions()) {
|
||||
matchFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if matchFound {
|
||||
res = uRole
|
||||
break
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func resourceActionsEqual(targetActionSet map[string]struct{}, actions []string) bool {
|
||||
if len(targetActionSet) != len(actions) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, action := range actions {
|
||||
if _, ok := targetActionSet[action]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func CS3ResourcePermissionsToDefinition(p *provider.ResourcePermissions, constraints string) *libregraph.UnifiedRoleDefinition {
|
||||
var res *libregraph.UnifiedRoleDefinition
|
||||
matches := GetDefinitions(RoleFilterPermission(RoleFilterMatchExact, constraints, CS3ResourcePermissionsToLibregraphActions(p)...))
|
||||
if len(matches) >= 1 {
|
||||
res = matches[0]
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// cs3RoleToDisplayName converts a CS3 role to a human-readable display name
|
||||
func cs3RoleToDisplayName(role *conversions.Role) string {
|
||||
if role == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch role.Name {
|
||||
case conversions.RoleViewer:
|
||||
return _viewerUnifiedRoleDisplayName
|
||||
case conversions.RoleSpaceViewer:
|
||||
return _spaceViewerUnifiedRoleDisplayName
|
||||
case conversions.RoleEditor:
|
||||
return _editorUnifiedRoleDisplayName
|
||||
case conversions.RoleSpaceEditor:
|
||||
return _spaceEditorUnifiedRoleDisplayName
|
||||
case conversions.RoleFileEditor:
|
||||
return _fileEditorUnifiedRoleDisplayName
|
||||
case conversions.RoleEditorLite:
|
||||
return _editorLiteUnifiedRoleDisplayName
|
||||
case conversions.RoleManager:
|
||||
return _managerUnifiedRoleDisplayName
|
||||
case conversions.RoleSecureViewer:
|
||||
return _secureViewerUnifiedRoleDisplayName
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
76
services/graph/pkg/unifiedrole/conversion_test.go
Normal file
76
services/graph/pkg/unifiedrole/conversion_test.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package unifiedrole_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
cs3Conversions "github.com/cs3org/reva/v2/pkg/conversions"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/types"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/conversions"
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole"
|
||||
)
|
||||
|
||||
func TestPermissionsToCS3ResourcePermissions(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
cs3Role *cs3Conversions.Role
|
||||
unifiedRoleDefinition *libregraph.UnifiedRoleDefinition
|
||||
match bool
|
||||
}{
|
||||
cs3Conversions.RoleViewer: {cs3Conversions.NewViewerRole(), unifiedrole.RoleViewer, true},
|
||||
cs3Conversions.RoleEditor: {cs3Conversions.NewEditorRole(), unifiedrole.RoleEditor, true},
|
||||
cs3Conversions.RoleFileEditor: {cs3Conversions.NewFileEditorRole(), unifiedrole.RoleFileEditor, true},
|
||||
cs3Conversions.RoleManager: {cs3Conversions.NewManagerRole(), unifiedrole.RoleManager, true},
|
||||
cs3Conversions.RoleSecureViewer: {cs3Conversions.NewSecureViewerRole(), unifiedrole.RoleSecureViewer, true},
|
||||
"no match": {cs3Conversions.NewFileEditorRole(), unifiedrole.RoleManager, false},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
permsFromCS3 := tc.cs3Role.CS3ResourcePermissions()
|
||||
permsFromUnifiedRole := unifiedrole.PermissionsToCS3ResourcePermissions(
|
||||
conversions.ToPointerSlice(tc.unifiedRoleDefinition.RolePermissions),
|
||||
)
|
||||
|
||||
var matcher types.GomegaMatcher
|
||||
|
||||
if tc.match {
|
||||
matcher = Equal(permsFromUnifiedRole)
|
||||
} else {
|
||||
matcher = Not(Equal(permsFromUnifiedRole))
|
||||
}
|
||||
|
||||
g.Expect(permsFromCS3).To(matcher)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCS3ResourcePermissionsToDefinition(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
cs3ResourcePermissions *provider.ResourcePermissions
|
||||
unifiedRoleDefinition *libregraph.UnifiedRoleDefinition
|
||||
constraints string
|
||||
}{
|
||||
cs3Conversions.RoleViewer + "1": {cs3Conversions.NewViewerRole().CS3ResourcePermissions(), unifiedrole.RoleViewer, unifiedrole.UnifiedRoleConditionFile},
|
||||
cs3Conversions.RoleViewer + "2": {cs3Conversions.NewViewerRole().CS3ResourcePermissions(), unifiedrole.RoleViewer, unifiedrole.UnifiedRoleConditionFolder},
|
||||
cs3Conversions.RoleEditor: {cs3Conversions.NewEditorRole().CS3ResourcePermissions(), unifiedrole.RoleEditor, unifiedrole.UnifiedRoleConditionFolder},
|
||||
cs3Conversions.RoleFileEditor: {cs3Conversions.NewFileEditorRole().CS3ResourcePermissions(), unifiedrole.RoleFileEditor, unifiedrole.UnifiedRoleConditionFile},
|
||||
cs3Conversions.RoleManager: {cs3Conversions.NewManagerRole().CS3ResourcePermissions(), unifiedrole.RoleManager, unifiedrole.UnifiedRoleConditionDrive},
|
||||
cs3Conversions.RoleSpaceViewer: {cs3Conversions.NewSpaceViewerRole().CS3ResourcePermissions(), unifiedrole.RoleSpaceViewer, unifiedrole.UnifiedRoleConditionDrive},
|
||||
cs3Conversions.RoleSpaceEditor: {cs3Conversions.NewSpaceEditorRole().CS3ResourcePermissions(), unifiedrole.RoleSpaceEditor, unifiedrole.UnifiedRoleConditionDrive},
|
||||
cs3Conversions.RoleSecureViewer + "1": {cs3Conversions.NewSecureViewerRole().CS3ResourcePermissions(), unifiedrole.RoleSecureViewer, unifiedrole.UnifiedRoleConditionFile},
|
||||
cs3Conversions.RoleSecureViewer + "2": {cs3Conversions.NewSecureViewerRole().CS3ResourcePermissions(), unifiedrole.RoleSecureViewer, unifiedrole.UnifiedRoleConditionFolder},
|
||||
"custom 1": {&provider.ResourcePermissions{GetPath: true}, nil, unifiedrole.UnifiedRoleConditionFolder},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
NewWithT(t).Expect(
|
||||
unifiedrole.CS3ResourcePermissionsToDefinition(tc.cs3ResourcePermissions, tc.constraints),
|
||||
).To(Equal(tc.unifiedRoleDefinition))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,7 @@ import (
|
||||
var (
|
||||
// ErrUnknownUnifiedRole is returned when an unknown unified role is requested.
|
||||
ErrUnknownUnifiedRole = errors.New("unknown unified role, check if the role is enabled")
|
||||
|
||||
// ErrTooManyResults is returned when a filter returns too many results.
|
||||
ErrTooManyResults = errors.New("too many results, consider using a more specific filter")
|
||||
)
|
||||
|
||||
16
services/graph/pkg/unifiedrole/export_test.go
Normal file
16
services/graph/pkg/unifiedrole/export_test.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package unifiedrole
|
||||
|
||||
var (
|
||||
// roles
|
||||
RoleViewer = roleViewer
|
||||
RoleSpaceViewer = roleSpaceViewer
|
||||
RoleEditor = roleEditor
|
||||
RoleSpaceEditor = roleSpaceEditor
|
||||
RoleFileEditor = roleFileEditor
|
||||
RoleEditorLite = roleEditorLite
|
||||
RoleManager = roleManager
|
||||
RoleSecureViewer = roleSecureViewer
|
||||
|
||||
// functions
|
||||
WeightDefinitions = weightDefinitions
|
||||
)
|
||||
87
services/graph/pkg/unifiedrole/filter.go
Normal file
87
services/graph/pkg/unifiedrole/filter.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package unifiedrole
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
)
|
||||
|
||||
type (
|
||||
// RoleFilter is used to filter role collections
|
||||
RoleFilter func(r *libregraph.UnifiedRoleDefinition) bool
|
||||
|
||||
// RoleFilterMatch defines the match behavior of a role filter
|
||||
RoleFilterMatch int
|
||||
)
|
||||
|
||||
const (
|
||||
// RoleFilterMatchExact is the behavior for role filters that require an exact match
|
||||
RoleFilterMatchExact RoleFilterMatch = iota
|
||||
|
||||
// RoleFilterMatchSome is the behavior for role filters that require some match
|
||||
RoleFilterMatchSome
|
||||
)
|
||||
|
||||
// RoleFilterInvert inverts the provided role filter
|
||||
func RoleFilterInvert(f RoleFilter) RoleFilter {
|
||||
return func(r *libregraph.UnifiedRoleDefinition) bool {
|
||||
return !f(r)
|
||||
}
|
||||
}
|
||||
|
||||
// RoleFilterAll returns a role filter that matches all roles
|
||||
func RoleFilterAll() RoleFilter {
|
||||
return func(r *libregraph.UnifiedRoleDefinition) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// RoleFilterIDs returns a role filter that matches the provided ids
|
||||
// the filter is always OR!
|
||||
func RoleFilterIDs(ids ...string) RoleFilter {
|
||||
return func(r *libregraph.UnifiedRoleDefinition) bool {
|
||||
return slices.Contains(ids, r.GetId())
|
||||
}
|
||||
}
|
||||
|
||||
// RoleFilterPermission returns a role filter that matches the provided condition and actions pair
|
||||
func RoleFilterPermission(matchBehavior RoleFilterMatch, condition string, wantActions ...string) RoleFilter {
|
||||
return func(r *libregraph.UnifiedRoleDefinition) bool {
|
||||
for _, permission := range r.GetRolePermissions() {
|
||||
if permission.GetCondition() != condition {
|
||||
continue
|
||||
}
|
||||
|
||||
givenActions := permission.GetAllowedResourceActions()
|
||||
|
||||
switch {
|
||||
case matchBehavior == RoleFilterMatchExact && slices.Equal(givenActions, wantActions):
|
||||
return true
|
||||
case matchBehavior == RoleFilterMatchSome:
|
||||
matches := 0
|
||||
|
||||
for _, action := range givenActions {
|
||||
if !slices.Contains(wantActions, action) {
|
||||
break
|
||||
}
|
||||
|
||||
matches++
|
||||
}
|
||||
|
||||
return len(givenActions) == matches
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// filterRoles filters the provided roles by the provided filter
|
||||
func filterRoles(roles []*libregraph.UnifiedRoleDefinition, filter RoleFilter) []*libregraph.UnifiedRoleDefinition {
|
||||
return slices.DeleteFunc(
|
||||
slices.Clone(roles),
|
||||
func(r *libregraph.UnifiedRoleDefinition) bool {
|
||||
return !filter(r)
|
||||
},
|
||||
)
|
||||
}
|
||||
129
services/graph/pkg/unifiedrole/filter_test.go
Normal file
129
services/graph/pkg/unifiedrole/filter_test.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package unifiedrole_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole"
|
||||
)
|
||||
|
||||
func TestRoleFilterIDs(t *testing.T) {
|
||||
NewWithT(t).Expect(
|
||||
unifiedrole.RoleFilterIDs(
|
||||
unifiedrole.UnifiedRoleEditorLiteID,
|
||||
unifiedrole.UnifiedRoleSpaceEditorID,
|
||||
)(unifiedrole.RoleEditorLite),
|
||||
).To(BeTrue())
|
||||
}
|
||||
|
||||
func TestRoleFilterInvert(t *testing.T) {
|
||||
NewWithT(t).Expect(
|
||||
unifiedrole.RoleFilterInvert(
|
||||
unifiedrole.RoleFilterAll(),
|
||||
)(unifiedrole.RoleEditorLite),
|
||||
).To(BeFalse())
|
||||
}
|
||||
|
||||
func TestRoleFilterAll(t *testing.T) {
|
||||
NewWithT(t).Expect(
|
||||
unifiedrole.RoleFilterAll()(unifiedrole.RoleEditorLite),
|
||||
).To(BeTrue())
|
||||
}
|
||||
|
||||
func TestRoleFilterPermissions(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
unifiedRolePermission []libregraph.UnifiedRolePermission
|
||||
filterCondition string
|
||||
filterActions []string
|
||||
filterMatch bool
|
||||
}{
|
||||
"true | single": {
|
||||
unifiedRolePermission: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
Condition: proto.String(unifiedrole.UnifiedRoleConditionDrive),
|
||||
AllowedResourceActions: []string{
|
||||
unifiedrole.DriveItemPermissionsCreate,
|
||||
},
|
||||
},
|
||||
},
|
||||
filterCondition: unifiedrole.UnifiedRoleConditionDrive,
|
||||
filterActions: []string{
|
||||
unifiedrole.DriveItemPermissionsCreate,
|
||||
},
|
||||
filterMatch: true,
|
||||
},
|
||||
"true | multiple": {
|
||||
unifiedRolePermission: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
Condition: proto.String(unifiedrole.UnifiedRoleConditionFolder),
|
||||
AllowedResourceActions: []string{
|
||||
unifiedrole.DriveItemDeletedRead,
|
||||
},
|
||||
},
|
||||
{
|
||||
Condition: proto.String(unifiedrole.UnifiedRoleConditionDrive),
|
||||
AllowedResourceActions: []string{
|
||||
unifiedrole.DriveItemPermissionsCreate,
|
||||
},
|
||||
},
|
||||
},
|
||||
filterCondition: unifiedrole.UnifiedRoleConditionDrive,
|
||||
filterActions: []string{
|
||||
unifiedrole.DriveItemPermissionsCreate,
|
||||
},
|
||||
filterMatch: true,
|
||||
},
|
||||
"false | cross match": {
|
||||
unifiedRolePermission: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
Condition: proto.String(unifiedrole.UnifiedRoleConditionDrive),
|
||||
AllowedResourceActions: []string{
|
||||
unifiedrole.DriveItemDeletedRead,
|
||||
},
|
||||
},
|
||||
{
|
||||
Condition: proto.String(unifiedrole.UnifiedRoleConditionFolder),
|
||||
AllowedResourceActions: []string{
|
||||
unifiedrole.DriveItemPermissionsCreate,
|
||||
},
|
||||
},
|
||||
},
|
||||
filterCondition: unifiedrole.UnifiedRoleConditionDrive,
|
||||
filterActions: []string{unifiedrole.DriveItemPermissionsCreate},
|
||||
filterMatch: false,
|
||||
},
|
||||
"false | too many actions": {
|
||||
unifiedRolePermission: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
Condition: proto.String(unifiedrole.UnifiedRoleConditionDrive),
|
||||
AllowedResourceActions: []string{
|
||||
unifiedrole.DriveItemDeletedRead,
|
||||
unifiedrole.DriveItemPermissionsCreate,
|
||||
},
|
||||
},
|
||||
},
|
||||
filterCondition: unifiedrole.UnifiedRoleConditionDrive,
|
||||
filterActions: []string{
|
||||
unifiedrole.DriveItemPermissionsCreate,
|
||||
},
|
||||
filterMatch: false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
NewWithT(t).Expect(
|
||||
unifiedrole.RoleFilterPermission(
|
||||
unifiedrole.RoleFilterMatchExact,
|
||||
tc.filterCondition,
|
||||
tc.filterActions...,
|
||||
)(&libregraph.UnifiedRoleDefinition{
|
||||
RolePermissions: tc.unifiedRolePermission,
|
||||
}),
|
||||
).To(Equal(tc.filterMatch))
|
||||
})
|
||||
}
|
||||
}
|
||||
359
services/graph/pkg/unifiedrole/roles.go
Normal file
359
services/graph/pkg/unifiedrole/roles.go
Normal file
@@ -0,0 +1,359 @@
|
||||
package unifiedrole
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"slices"
|
||||
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/conversions"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/l10n"
|
||||
)
|
||||
|
||||
const (
|
||||
// UnifiedRoleViewerID Unified role viewer id.
|
||||
UnifiedRoleViewerID = "b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5"
|
||||
// UnifiedRoleSpaceViewerID Unified role space viewer id.
|
||||
UnifiedRoleSpaceViewerID = "a8d5fe5e-96e3-418d-825b-534dbdf22b99"
|
||||
// UnifiedRoleEditorID Unified role editor id.
|
||||
UnifiedRoleEditorID = "fb6c3e19-e378-47e5-b277-9732f9de6e21"
|
||||
// UnifiedRoleSpaceEditorID Unified role space editor id.
|
||||
UnifiedRoleSpaceEditorID = "58c63c02-1d89-4572-916a-870abc5a1b7d"
|
||||
// UnifiedRoleFileEditorID Unified role file editor id.
|
||||
UnifiedRoleFileEditorID = "2d00ce52-1fc2-4dbc-8b95-a73b73395f5a"
|
||||
// UnifiedRoleEditorLiteID Unified role editor-lite id.
|
||||
UnifiedRoleEditorLiteID = "1c996275-f1c9-4e71-abdf-a42f6495e960"
|
||||
// UnifiedRoleManagerID Unified role manager id.
|
||||
UnifiedRoleManagerID = "312c0871-5ef7-4b3a-85b6-0e4074c64049"
|
||||
// UnifiedRoleSecureViewerID Unified role secure viewer id.
|
||||
UnifiedRoleSecureViewerID = "aa97fe03-7980-45ac-9e50-b325749fd7e6"
|
||||
|
||||
// UnifiedRoleConditionDrive defines constraint that matches a Driveroot/Spaceroot
|
||||
UnifiedRoleConditionDrive = "exists @Resource.Root"
|
||||
// UnifiedRoleConditionFolder defines constraints that matches a DriveItem representing a Folder
|
||||
UnifiedRoleConditionFolder = "exists @Resource.Folder"
|
||||
// UnifiedRoleConditionFile defines a constraint that matches a DriveItem representing a File
|
||||
UnifiedRoleConditionFile = "exists @Resource.File"
|
||||
|
||||
DriveItemPermissionsCreate = "libre.graph/driveItem/permissions/create"
|
||||
DriveItemChildrenCreate = "libre.graph/driveItem/children/create"
|
||||
DriveItemStandardDelete = "libre.graph/driveItem/standard/delete"
|
||||
DriveItemPathRead = "libre.graph/driveItem/path/read"
|
||||
DriveItemQuotaRead = "libre.graph/driveItem/quota/read"
|
||||
DriveItemContentRead = "libre.graph/driveItem/content/read"
|
||||
DriveItemUploadCreate = "libre.graph/driveItem/upload/create"
|
||||
DriveItemPermissionsRead = "libre.graph/driveItem/permissions/read"
|
||||
DriveItemChildrenRead = "libre.graph/driveItem/children/read"
|
||||
DriveItemVersionsRead = "libre.graph/driveItem/versions/read"
|
||||
DriveItemDeletedRead = "libre.graph/driveItem/deleted/read"
|
||||
DriveItemPathUpdate = "libre.graph/driveItem/path/update"
|
||||
DriveItemPermissionsDelete = "libre.graph/driveItem/permissions/delete"
|
||||
DriveItemDeletedDelete = "libre.graph/driveItem/deleted/delete"
|
||||
DriveItemVersionsUpdate = "libre.graph/driveItem/versions/update"
|
||||
DriveItemDeletedUpdate = "libre.graph/driveItem/deleted/update"
|
||||
DriveItemBasicRead = "libre.graph/driveItem/basic/read"
|
||||
DriveItemPermissionsUpdate = "libre.graph/driveItem/permissions/update"
|
||||
DriveItemPermissionsDeny = "libre.graph/driveItem/permissions/deny"
|
||||
)
|
||||
|
||||
var (
|
||||
// UnifiedRole Viewer, Role Description (resolves directly)
|
||||
_viewerUnifiedRoleDescription = l10n.Template("View and download.")
|
||||
|
||||
// UnifiedRole Viewer, Role DisplayName (resolves directly)
|
||||
_viewerUnifiedRoleDisplayName = l10n.Template("Can view")
|
||||
|
||||
// UnifiedRole SpaceViewer, Role Description (resolves directly)
|
||||
_spaceViewerUnifiedRoleDescription = l10n.Template("View and download.")
|
||||
|
||||
// UnifiedRole SpaseViewer, Role DisplayName (resolves directly)
|
||||
_spaceViewerUnifiedRoleDisplayName = l10n.Template("Can view")
|
||||
|
||||
// UnifiedRole Editor, Role Description (resolves directly)
|
||||
_editorUnifiedRoleDescription = l10n.Template("View, download, upload, edit, add and delete.")
|
||||
|
||||
// UnifiedRole Editor, Role DisplayName (resolves directly)
|
||||
_editorUnifiedRoleDisplayName = l10n.Template("Can edit")
|
||||
|
||||
// UnifiedRole SpaseEditor, Role Description (resolves directly)
|
||||
_spaceEditorUnifiedRoleDescription = l10n.Template("View, download, upload, edit, add and delete.")
|
||||
|
||||
// UnifiedRole SpaseEditor, Role DisplayName (resolves directly)
|
||||
_spaceEditorUnifiedRoleDisplayName = l10n.Template("Can edit")
|
||||
|
||||
// UnifiedRole FileEditor, Role Description (resolves directly)
|
||||
_fileEditorUnifiedRoleDescription = l10n.Template("View, download and edit.")
|
||||
|
||||
// UnifiedRole FileEditor, Role DisplayName (resolves directly)
|
||||
_fileEditorUnifiedRoleDisplayName = l10n.Template("Can edit")
|
||||
|
||||
// UnifiedRole EditorLite, Role Description (resolves directly)
|
||||
_editorLiteUnifiedRoleDescription = l10n.Template("View, download and upload.")
|
||||
|
||||
// UnifiedRole EditorLite, Role DisplayName (resolves directly)
|
||||
_editorLiteUnifiedRoleDisplayName = l10n.Template("Can upload")
|
||||
|
||||
// UnifiedRole Manager, Role Description (resolves directly)
|
||||
_managerUnifiedRoleDescription = l10n.Template("View, download, upload, edit, add, delete and manage members.")
|
||||
|
||||
// UnifiedRole Manager, Role DisplayName (resolves directly)
|
||||
_managerUnifiedRoleDisplayName = l10n.Template("Can manage")
|
||||
|
||||
// UnifiedRole SecureViewer, Role Description (resolves directly)
|
||||
_secureViewerUnifiedRoleDescription = l10n.Template("View only documents, images and PDFs. Watermarks will be applied.")
|
||||
|
||||
// UnifiedRole SecureViewer, Role DisplayName (resolves directly)
|
||||
_secureViewerUnifiedRoleDisplayName = l10n.Template("Can view (secure)")
|
||||
|
||||
// legacyNames contains the legacy role names.
|
||||
legacyNames = map[string]string{
|
||||
UnifiedRoleViewerID: conversions.RoleViewer,
|
||||
// one V1 api the "spaceviewer" role was call "viewer" and the "spaceeditor" was "editor",
|
||||
// we need to stay compatible with that
|
||||
UnifiedRoleSpaceViewerID: "viewer",
|
||||
UnifiedRoleSpaceEditorID: "editor",
|
||||
UnifiedRoleEditorID: conversions.RoleEditor,
|
||||
UnifiedRoleFileEditorID: conversions.RoleFileEditor,
|
||||
UnifiedRoleEditorLiteID: conversions.RoleEditorLite,
|
||||
UnifiedRoleManagerID: conversions.RoleManager,
|
||||
UnifiedRoleSecureViewerID: conversions.RoleSecureViewer,
|
||||
}
|
||||
|
||||
// buildInRoles contains the built-in roles.
|
||||
buildInRoles = []*libregraph.UnifiedRoleDefinition{
|
||||
roleViewer,
|
||||
roleSpaceViewer,
|
||||
roleEditor,
|
||||
roleSpaceEditor,
|
||||
roleFileEditor,
|
||||
roleEditorLite,
|
||||
roleManager,
|
||||
roleSecureViewer,
|
||||
}
|
||||
|
||||
// roleViewer creates a viewer role.
|
||||
roleViewer = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewViewerRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleViewerID),
|
||||
Description: proto.String(_viewerUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFile),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleSpaceViewer creates a spaceviewer role
|
||||
roleSpaceViewer = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewSpaceViewerRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleSpaceViewerID),
|
||||
Description: proto.String(_spaceViewerUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleEditor creates an editor role.
|
||||
roleEditor = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewEditorRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleEditorID),
|
||||
Description: proto.String(_editorUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleSpaceEditor creates an editor role
|
||||
roleSpaceEditor = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewSpaceEditorRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleSpaceEditorID),
|
||||
Description: proto.String(_spaceEditorUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleFileEditor creates a file-editor role
|
||||
roleFileEditor = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewFileEditorRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleFileEditorID),
|
||||
Description: proto.String(_fileEditorUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFile),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleEditorLite creates an editor-lite role
|
||||
roleEditorLite = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewEditorLiteRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleEditorLiteID),
|
||||
Description: proto.String(_editorLiteUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleManager creates a manager role
|
||||
roleManager = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewManagerRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleManagerID),
|
||||
Description: proto.String(_managerUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleSecureViewer creates a secure viewer role
|
||||
roleSecureViewer = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewSecureViewerRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleSecureViewerID),
|
||||
Description: proto.String(_secureViewerUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFile),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}()
|
||||
)
|
||||
|
||||
// GetDefinitions returns a role filter that matches the provided resources
|
||||
func GetDefinitions(filter RoleFilter) []*libregraph.UnifiedRoleDefinition {
|
||||
return filterRoles(buildInRoles, filter)
|
||||
}
|
||||
|
||||
// GetDefinition returns a role filter that matches the provided resources
|
||||
func GetDefinition(filter RoleFilter) (*libregraph.UnifiedRoleDefinition, error) {
|
||||
definitions := filterRoles(buildInRoles, filter)
|
||||
if len(definitions) == 0 {
|
||||
return nil, ErrUnknownUnifiedRole
|
||||
}
|
||||
|
||||
return definitions[0], nil
|
||||
}
|
||||
|
||||
// GetRolesByPermissions returns a list of role definitions
|
||||
// that match the provided actions and constraints
|
||||
func GetRolesByPermissions(actions []string, constraints string, descending bool) []*libregraph.UnifiedRoleDefinition {
|
||||
roles := GetDefinitions(RoleFilterPermission(RoleFilterMatchSome, constraints, actions...))
|
||||
roles = weightDefinitions(roles, constraints, descending)
|
||||
|
||||
return roles
|
||||
}
|
||||
|
||||
// GetLegacyDefinitionName returns the legacy role name for the provided role
|
||||
func GetLegacyDefinitionName(definition libregraph.UnifiedRoleDefinition) string {
|
||||
return legacyNames[definition.GetId()]
|
||||
}
|
||||
|
||||
// weightDefinitions sorts the provided role definitions by the number of permissions[n].actions they grant,
|
||||
// the implementation is optimistic and assumes that the weight relies on the number of available actions.
|
||||
// descending - false - sorts the roles from least to most permissions
|
||||
// descending - true - sorts the roles from most to least permissions
|
||||
func weightDefinitions(definitions []*libregraph.UnifiedRoleDefinition, constraints string, descending bool) []*libregraph.UnifiedRoleDefinition {
|
||||
slices.SortFunc(definitions, func(i, j *libregraph.UnifiedRoleDefinition) int {
|
||||
var ia []string
|
||||
for _, rp := range i.GetRolePermissions() {
|
||||
if rp.GetCondition() == constraints {
|
||||
ia = append(ia, rp.GetAllowedResourceActions()...)
|
||||
}
|
||||
}
|
||||
|
||||
var ja []string
|
||||
for _, rp := range j.GetRolePermissions() {
|
||||
if rp.GetCondition() == constraints {
|
||||
ja = append(ja, rp.GetAllowedResourceActions()...)
|
||||
}
|
||||
}
|
||||
|
||||
switch descending {
|
||||
case true:
|
||||
return cmp.Compare(len(ja), len(ia))
|
||||
default:
|
||||
return cmp.Compare(len(ia), len(ja))
|
||||
}
|
||||
})
|
||||
|
||||
for i, definition := range definitions {
|
||||
definition.LibreGraphWeight = libregraph.PtrInt32(int32(i) + 1)
|
||||
}
|
||||
|
||||
// return for the sake of consistency, optional because the slice is modified in place
|
||||
return definitions
|
||||
}
|
||||
|
||||
// GetAllowedResourceActions returns the allowed resource actions for the provided role by condition
|
||||
func GetAllowedResourceActions(role *libregraph.UnifiedRoleDefinition, condition string) []string {
|
||||
if role == nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
for _, p := range role.GetRolePermissions() {
|
||||
if p.GetCondition() == condition {
|
||||
return p.GetAllowedResourceActions()
|
||||
}
|
||||
}
|
||||
|
||||
return []string{}
|
||||
}
|
||||
236
services/graph/pkg/unifiedrole/roles_test.go
Normal file
236
services/graph/pkg/unifiedrole/roles_test.go
Normal file
@@ -0,0 +1,236 @@
|
||||
package unifiedrole_test
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole"
|
||||
)
|
||||
|
||||
func TestGetDefinition(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
ids []string
|
||||
unifiedRoleDefinition *libregraph.UnifiedRoleDefinition
|
||||
expectError error
|
||||
}{
|
||||
"pass single": {
|
||||
ids: []string{unifiedrole.UnifiedRoleViewerID},
|
||||
unifiedRoleDefinition: unifiedrole.RoleViewer,
|
||||
},
|
||||
"pass many": {
|
||||
ids: []string{unifiedrole.UnifiedRoleViewerID, unifiedrole.UnifiedRoleEditorID},
|
||||
unifiedRoleDefinition: unifiedrole.RoleViewer,
|
||||
},
|
||||
"fail unknown": {
|
||||
ids: []string{"unknown"},
|
||||
expectError: unifiedrole.ErrUnknownUnifiedRole,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
definition, err := unifiedrole.GetDefinition(unifiedrole.RoleFilterIDs(tc.ids...))
|
||||
|
||||
if tc.expectError != nil {
|
||||
g.Expect(err).To(MatchError(tc.expectError))
|
||||
} else {
|
||||
g.Expect(err).NotTo(HaveOccurred())
|
||||
g.Expect(definition).To(Equal(tc.unifiedRoleDefinition))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWeightDefinitions(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
unifiedRoleDefinition []*libregraph.UnifiedRoleDefinition
|
||||
constraint string
|
||||
descending bool
|
||||
expectedDefinitions []*libregraph.UnifiedRoleDefinition
|
||||
}{
|
||||
"ascending": {
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleFileEditor,
|
||||
},
|
||||
unifiedrole.UnifiedRoleConditionFile,
|
||||
false,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleFileEditor,
|
||||
},
|
||||
},
|
||||
"descending": {
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleFileEditor,
|
||||
},
|
||||
unifiedrole.UnifiedRoleConditionFile,
|
||||
true,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleFileEditor,
|
||||
unifiedrole.RoleViewer,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
for i, generatedDefinition := range unifiedrole.WeightDefinitions(tc.unifiedRoleDefinition, tc.constraint, tc.descending) {
|
||||
g.Expect(generatedDefinition.Id).To(Equal(tc.expectedDefinitions[i].Id))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRolesByPermissions(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
givenActions []string
|
||||
constraints string
|
||||
unifiedRoleDefinition []*libregraph.UnifiedRoleDefinition
|
||||
}{
|
||||
"ViewerUnifiedRole": {
|
||||
givenActions: rolesToAction(unifiedrole.RoleViewer),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFolder,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
},
|
||||
},
|
||||
"ViewerUnifiedRole | share": {
|
||||
givenActions: rolesToAction(unifiedrole.RoleViewer),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
},
|
||||
},
|
||||
"NewFileEditorUnifiedRole": {
|
||||
givenActions: rolesToAction(unifiedrole.RoleFileEditor),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleFileEditor,
|
||||
},
|
||||
},
|
||||
"NewEditorUnifiedRole": {
|
||||
givenActions: rolesToAction(unifiedrole.RoleEditor),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFolder,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleEditorLite,
|
||||
unifiedrole.RoleEditor,
|
||||
},
|
||||
},
|
||||
"GetRoles 1": {
|
||||
givenActions: rolesToAction(unifiedrole.GetDefinitions(unifiedrole.RoleFilterAll())...),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleFileEditor,
|
||||
},
|
||||
},
|
||||
"GetRoles 2": {
|
||||
givenActions: rolesToAction(unifiedrole.GetDefinitions(unifiedrole.RoleFilterAll())...),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFolder,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleEditorLite,
|
||||
unifiedrole.RoleEditor,
|
||||
},
|
||||
},
|
||||
"GetRoles 3": {
|
||||
givenActions: rolesToAction(unifiedrole.GetDefinitions(unifiedrole.RoleFilterAll())...),
|
||||
constraints: unifiedrole.UnifiedRoleConditionDrive,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSpaceViewer,
|
||||
unifiedrole.RoleSpaceEditor,
|
||||
unifiedrole.RoleManager,
|
||||
},
|
||||
},
|
||||
"single": {
|
||||
givenActions: []string{unifiedrole.DriveItemQuotaRead},
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{},
|
||||
},
|
||||
"mixed": {
|
||||
givenActions: append(rolesToAction(unifiedrole.RoleEditorLite), unifiedrole.DriveItemQuotaRead),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFolder,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleEditorLite,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
generatedDefinitions := unifiedrole.GetRolesByPermissions(tc.givenActions, tc.constraints, false)
|
||||
|
||||
g.Expect(len(generatedDefinitions)).To(Equal(len(tc.unifiedRoleDefinition)))
|
||||
|
||||
for i, generatedDefinition := range generatedDefinitions {
|
||||
g.Expect(generatedDefinition.Id).To(Equal(tc.unifiedRoleDefinition[i].Id))
|
||||
g.Expect(*generatedDefinition.LibreGraphWeight).To(Equal(int32(i + 1)))
|
||||
}
|
||||
|
||||
generatedActions := rolesToAction(generatedDefinitions...)
|
||||
|
||||
g.Expect(len(tc.givenActions) >= len(generatedActions)).To(BeTrue())
|
||||
for _, generatedAction := range generatedActions {
|
||||
g.Expect(slices.Contains(tc.givenActions, generatedAction)).To(BeTrue())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllowedResourceActions(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
unifiedRoleDefinition *libregraph.UnifiedRoleDefinition
|
||||
condition string
|
||||
expectedActions []string
|
||||
}{
|
||||
"no role": {
|
||||
expectedActions: []string{},
|
||||
},
|
||||
"no match": {
|
||||
unifiedRoleDefinition: &libregraph.UnifiedRoleDefinition{
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{Condition: proto.String(unifiedrole.UnifiedRoleConditionDrive), AllowedResourceActions: []string{unifiedrole.DriveItemPermissionsCreate}},
|
||||
{Condition: proto.String(unifiedrole.UnifiedRoleConditionFolder), AllowedResourceActions: []string{unifiedrole.DriveItemDeletedRead}},
|
||||
},
|
||||
},
|
||||
condition: unifiedrole.UnifiedRoleConditionFile,
|
||||
expectedActions: []string{},
|
||||
},
|
||||
"match": {
|
||||
unifiedRoleDefinition: &libregraph.UnifiedRoleDefinition{
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{Condition: proto.String(unifiedrole.UnifiedRoleConditionDrive), AllowedResourceActions: []string{unifiedrole.DriveItemPermissionsCreate}},
|
||||
{Condition: proto.String(unifiedrole.UnifiedRoleConditionFolder), AllowedResourceActions: []string{unifiedrole.DriveItemDeletedRead}},
|
||||
},
|
||||
},
|
||||
condition: unifiedrole.UnifiedRoleConditionFolder,
|
||||
expectedActions: []string{unifiedrole.DriveItemDeletedRead},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
NewWithT(t).
|
||||
Expect(unifiedrole.GetAllowedResourceActions(tc.unifiedRoleDefinition, tc.condition)).
|
||||
To(ContainElements(tc.expectedActions))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,603 +0,0 @@
|
||||
package unifiedrole
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"errors"
|
||||
"slices"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/l10n"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/conversions"
|
||||
)
|
||||
|
||||
// roleFilter is used to filter role collections
|
||||
type roleFilter func(r *libregraph.UnifiedRoleDefinition) bool
|
||||
|
||||
var (
|
||||
// RoleFilterInvert inverts the provided role filter
|
||||
RoleFilterInvert = func(f roleFilter) roleFilter {
|
||||
return func(r *libregraph.UnifiedRoleDefinition) bool {
|
||||
return !f(r)
|
||||
}
|
||||
}
|
||||
|
||||
// RoleFilterIDs returns a role filter that matches the provided ids
|
||||
RoleFilterIDs = func(ids ...string) roleFilter {
|
||||
return func(r *libregraph.UnifiedRoleDefinition) bool {
|
||||
for _, id := range ids {
|
||||
if r.GetId() == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
// UnifiedRoleViewerID Unified role viewer id.
|
||||
UnifiedRoleViewerID = "b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5"
|
||||
// UnifiedRoleSpaceViewerID Unified role space viewer id.
|
||||
UnifiedRoleSpaceViewerID = "a8d5fe5e-96e3-418d-825b-534dbdf22b99"
|
||||
// UnifiedRoleEditorID Unified role editor id.
|
||||
UnifiedRoleEditorID = "fb6c3e19-e378-47e5-b277-9732f9de6e21"
|
||||
// UnifiedRoleSpaceEditorID Unified role space editor id.
|
||||
UnifiedRoleSpaceEditorID = "58c63c02-1d89-4572-916a-870abc5a1b7d"
|
||||
// UnifiedRoleFileEditorID Unified role file editor id.
|
||||
UnifiedRoleFileEditorID = "2d00ce52-1fc2-4dbc-8b95-a73b73395f5a"
|
||||
// UnifiedRoleEditorLiteID Unified role editor-lite id.
|
||||
UnifiedRoleEditorLiteID = "1c996275-f1c9-4e71-abdf-a42f6495e960"
|
||||
// UnifiedRoleManagerID Unified role manager id.
|
||||
UnifiedRoleManagerID = "312c0871-5ef7-4b3a-85b6-0e4074c64049"
|
||||
// UnifiedRoleSecureViewerID Unified role secure viewer id.
|
||||
UnifiedRoleSecureViewerID = "aa97fe03-7980-45ac-9e50-b325749fd7e6"
|
||||
|
||||
// UnifiedRoleConditionDrive defines constraint that matches a Driveroot/Spaceroot
|
||||
UnifiedRoleConditionDrive = "exists @Resource.Root"
|
||||
// UnifiedRoleConditionFolder defines constraints that matches a DriveItem representing a Folder
|
||||
UnifiedRoleConditionFolder = "exists @Resource.Folder"
|
||||
// UnifiedRoleConditionFile defines a constraint that matches a DriveItem representing a File
|
||||
UnifiedRoleConditionFile = "exists @Resource.File"
|
||||
|
||||
DriveItemPermissionsCreate = "libre.graph/driveItem/permissions/create"
|
||||
DriveItemChildrenCreate = "libre.graph/driveItem/children/create"
|
||||
DriveItemStandardDelete = "libre.graph/driveItem/standard/delete"
|
||||
DriveItemPathRead = "libre.graph/driveItem/path/read"
|
||||
DriveItemQuotaRead = "libre.graph/driveItem/quota/read"
|
||||
DriveItemContentRead = "libre.graph/driveItem/content/read"
|
||||
DriveItemUploadCreate = "libre.graph/driveItem/upload/create"
|
||||
DriveItemPermissionsRead = "libre.graph/driveItem/permissions/read"
|
||||
DriveItemChildrenRead = "libre.graph/driveItem/children/read"
|
||||
DriveItemVersionsRead = "libre.graph/driveItem/versions/read"
|
||||
DriveItemDeletedRead = "libre.graph/driveItem/deleted/read"
|
||||
DriveItemPathUpdate = "libre.graph/driveItem/path/update"
|
||||
DriveItemPermissionsDelete = "libre.graph/driveItem/permissions/delete"
|
||||
DriveItemDeletedDelete = "libre.graph/driveItem/deleted/delete"
|
||||
DriveItemVersionsUpdate = "libre.graph/driveItem/versions/update"
|
||||
DriveItemDeletedUpdate = "libre.graph/driveItem/deleted/update"
|
||||
DriveItemBasicRead = "libre.graph/driveItem/basic/read"
|
||||
DriveItemPermissionsUpdate = "libre.graph/driveItem/permissions/update"
|
||||
DriveItemPermissionsDeny = "libre.graph/driveItem/permissions/deny"
|
||||
)
|
||||
|
||||
var legacyNames = map[string]string{
|
||||
UnifiedRoleViewerID: conversions.RoleViewer,
|
||||
// one V1 api the "spaceviewer" role was call "viewer" and the "spaceeditor" was "editor",
|
||||
// we need to stay compatible with that
|
||||
UnifiedRoleSpaceViewerID: "viewer",
|
||||
UnifiedRoleSpaceEditorID: "editor",
|
||||
UnifiedRoleEditorID: conversions.RoleEditor,
|
||||
UnifiedRoleFileEditorID: conversions.RoleFileEditor,
|
||||
UnifiedRoleEditorLiteID: conversions.RoleEditorLite,
|
||||
UnifiedRoleManagerID: conversions.RoleManager,
|
||||
UnifiedRoleSecureViewerID: conversions.RoleSecureViewer,
|
||||
}
|
||||
|
||||
var (
|
||||
// UnifiedRole Viewer, Role Description (resolves directly)
|
||||
_viewerUnifiedRoleDescription = l10n.Template("View and download.")
|
||||
// UnifiedRole Viewer, Role DisplayName (resolves directly)
|
||||
_viewerUnifiedRoleDisplayName = l10n.Template("Can view")
|
||||
|
||||
// UnifiedRole SpaceViewer, Role Description (resolves directly)
|
||||
_spaceViewerUnifiedRoleDescription = l10n.Template("View and download.")
|
||||
// UnifiedRole SpaseViewer, Role DisplayName (resolves directly)
|
||||
_spaceViewerUnifiedRoleDisplayName = l10n.Template("Can view")
|
||||
|
||||
// UnifiedRole Editor, Role Description (resolves directly)
|
||||
_editorUnifiedRoleDescription = l10n.Template("View, download, upload, edit, add and delete.")
|
||||
// UnifiedRole Editor, Role DisplayName (resolves directly)
|
||||
_editorUnifiedRoleDisplayName = l10n.Template("Can edit")
|
||||
|
||||
// UnifiedRole SpaseEditor, Role Description (resolves directly)
|
||||
_spaceEditorUnifiedRoleDescription = l10n.Template("View, download, upload, edit, add and delete.")
|
||||
// UnifiedRole SpaseEditor, Role DisplayName (resolves directly)
|
||||
_spaceEditorUnifiedRoleDisplayName = l10n.Template("Can edit")
|
||||
|
||||
// UnifiedRole FileEditor, Role Description (resolves directly)
|
||||
_fileEditorUnifiedRoleDescription = l10n.Template("View, download and edit.")
|
||||
// UnifiedRole FileEditor, Role DisplayName (resolves directly)
|
||||
_fileEditorUnifiedRoleDisplayName = l10n.Template("Can edit")
|
||||
|
||||
// UnifiedRole EditorLite, Role Description (resolves directly)
|
||||
_editorLiteUnifiedRoleDescription = l10n.Template("View, download and upload.")
|
||||
// UnifiedRole EditorLite, Role DisplayName (resolves directly)
|
||||
_editorLiteUnifiedRoleDisplayName = l10n.Template("Can upload")
|
||||
|
||||
// UnifiedRole Manager, Role Description (resolves directly)
|
||||
_managerUnifiedRoleDescription = l10n.Template("View, download, upload, edit, add, delete and manage members.")
|
||||
// UnifiedRole Manager, Role DisplayName (resolves directly)
|
||||
_managerUnifiedRoleDisplayName = l10n.Template("Can manage")
|
||||
|
||||
// UnifiedRole SecureViewer, Role Description (resolves directly)
|
||||
_secureViewerUnifiedRoleDescription = l10n.Template("View only documents, images and PDFs. Watermarks will be applied.")
|
||||
// UnifiedRole SecureViewer, Role DisplayName (resolves directly)
|
||||
_secureViewerUnifiedRoleDisplayName = l10n.Template("Can view (secure)")
|
||||
)
|
||||
|
||||
// NewViewerUnifiedRole creates a viewer role.
|
||||
func NewViewerUnifiedRole() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewViewerRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleViewerID),
|
||||
Description: proto.String(_viewerUnifiedRoleDescription),
|
||||
DisplayName: displayName(r),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: convert(r),
|
||||
Condition: proto.String(UnifiedRoleConditionFile),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: convert(r),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}
|
||||
|
||||
// NewSpaceViewerUnifiedRole creates a spaceviewer role
|
||||
func NewSpaceViewerUnifiedRole() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewSpaceViewerRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleSpaceViewerID),
|
||||
Description: proto.String(_spaceViewerUnifiedRoleDescription),
|
||||
DisplayName: displayName(r),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: convert(r),
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}
|
||||
|
||||
// NewEditorUnifiedRole creates an editor role.
|
||||
func NewEditorUnifiedRole() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewEditorRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleEditorID),
|
||||
Description: proto.String(_editorUnifiedRoleDescription),
|
||||
DisplayName: displayName(r),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: convert(r),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}
|
||||
|
||||
// NewSpaceEditorUnifiedRole creates an editor role
|
||||
func NewSpaceEditorUnifiedRole() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewSpaceEditorRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleSpaceEditorID),
|
||||
Description: proto.String(_spaceEditorUnifiedRoleDescription),
|
||||
DisplayName: displayName(r),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: convert(r),
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}
|
||||
|
||||
// NewFileEditorUnifiedRole creates a file-editor role
|
||||
func NewFileEditorUnifiedRole() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewFileEditorRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleFileEditorID),
|
||||
Description: proto.String(_fileEditorUnifiedRoleDescription),
|
||||
DisplayName: displayName(r),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: convert(r),
|
||||
Condition: proto.String(UnifiedRoleConditionFile),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}
|
||||
|
||||
// NewEditorLiteUnifiedRole creates an editor-lite role
|
||||
func NewEditorLiteUnifiedRole() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewEditorLiteRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleEditorLiteID),
|
||||
Description: proto.String(_editorLiteUnifiedRoleDescription),
|
||||
DisplayName: displayName(r),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: convert(r),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}
|
||||
|
||||
// NewManagerUnifiedRole creates a manager role
|
||||
func NewManagerUnifiedRole() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewManagerRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleManagerID),
|
||||
Description: proto.String(_managerUnifiedRoleDescription),
|
||||
DisplayName: displayName(r),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: convert(r),
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}
|
||||
|
||||
// NewSecureViewerUnifiedRole creates a secure viewer role
|
||||
func NewSecureViewerUnifiedRole() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewSecureViewerRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleSecureViewerID),
|
||||
Description: proto.String(_secureViewerUnifiedRoleDescription),
|
||||
DisplayName: displayName(r),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: convert(r),
|
||||
Condition: proto.String(UnifiedRoleConditionFile),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: convert(r),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(0),
|
||||
}
|
||||
}
|
||||
|
||||
// NewUnifiedRoleFromID returns a unified role definition from the provided id
|
||||
func NewUnifiedRoleFromID(id string) (*libregraph.UnifiedRoleDefinition, error) {
|
||||
// fixMe: should we consider all roles or only the ones that are enabled?
|
||||
for _, definition := range GetBuiltinRoleDefinitionList() {
|
||||
if definition.GetId() != id {
|
||||
continue
|
||||
}
|
||||
|
||||
return definition, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("role not found")
|
||||
}
|
||||
|
||||
func GetBuiltinRoleDefinitionList(filter ...roleFilter) []*libregraph.UnifiedRoleDefinition {
|
||||
roles := []*libregraph.UnifiedRoleDefinition{
|
||||
NewViewerUnifiedRole(),
|
||||
NewSpaceViewerUnifiedRole(),
|
||||
NewEditorUnifiedRole(),
|
||||
NewSpaceEditorUnifiedRole(),
|
||||
NewFileEditorUnifiedRole(),
|
||||
NewEditorLiteUnifiedRole(),
|
||||
NewManagerUnifiedRole(),
|
||||
NewSecureViewerUnifiedRole(),
|
||||
}
|
||||
|
||||
for _, f := range filter {
|
||||
roles = slices.DeleteFunc(roles, func(r *libregraph.UnifiedRoleDefinition) bool {
|
||||
return !f(r)
|
||||
})
|
||||
}
|
||||
|
||||
return roles
|
||||
}
|
||||
|
||||
// GetApplicableRoleDefinitionsForActions returns a list of role definitions
|
||||
// that match the provided actions and constraints
|
||||
func GetApplicableRoleDefinitionsForActions(actions []string, constraints string, descending bool) []*libregraph.UnifiedRoleDefinition {
|
||||
// fixMe: should we consider all roles or only the ones that are enabled?
|
||||
builtin := GetBuiltinRoleDefinitionList()
|
||||
definitions := make([]*libregraph.UnifiedRoleDefinition, 0, len(builtin))
|
||||
|
||||
for _, definition := range builtin {
|
||||
var definitionMatch bool
|
||||
|
||||
for _, permission := range definition.GetRolePermissions() {
|
||||
if permission.GetCondition() != constraints {
|
||||
continue
|
||||
}
|
||||
|
||||
for i, action := range permission.GetAllowedResourceActions() {
|
||||
if !slices.Contains(actions, action) {
|
||||
break
|
||||
}
|
||||
if i == len(permission.GetAllowedResourceActions())-1 {
|
||||
definitionMatch = true
|
||||
}
|
||||
}
|
||||
|
||||
if definitionMatch {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if definitionMatch {
|
||||
definitions = append(definitions, definition)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return WeightRoleDefinitions(definitions, constraints, descending)
|
||||
}
|
||||
|
||||
// WeightRoleDefinitions sorts the provided role definitions by the number of permissions[n].actions they grant,
|
||||
// the implementation is optimistic and assumes that the weight relies on the number of available actions.
|
||||
// descending - false - sorts the roles from least to most permissions
|
||||
// descending - true - sorts the roles from most to least permissions
|
||||
func WeightRoleDefinitions(roleDefinitions []*libregraph.UnifiedRoleDefinition, constraints string, descending bool) []*libregraph.UnifiedRoleDefinition {
|
||||
slices.SortFunc(roleDefinitions, func(i, j *libregraph.UnifiedRoleDefinition) int {
|
||||
var ia []string
|
||||
for _, rp := range i.GetRolePermissions() {
|
||||
if rp.GetCondition() == constraints {
|
||||
ia = append(ia, rp.GetAllowedResourceActions()...)
|
||||
}
|
||||
}
|
||||
|
||||
var ja []string
|
||||
for _, rp := range j.GetRolePermissions() {
|
||||
if rp.GetCondition() == constraints {
|
||||
ja = append(ja, rp.GetAllowedResourceActions()...)
|
||||
}
|
||||
}
|
||||
|
||||
switch descending {
|
||||
case true:
|
||||
return cmp.Compare(len(ja), len(ia))
|
||||
default:
|
||||
return cmp.Compare(len(ia), len(ja))
|
||||
}
|
||||
})
|
||||
|
||||
for i, definition := range roleDefinitions {
|
||||
definition.LibreGraphWeight = libregraph.PtrInt32(int32(i) + 1)
|
||||
}
|
||||
|
||||
// return for the sage of consistency, optional because the slice is modified in place
|
||||
return roleDefinitions
|
||||
}
|
||||
|
||||
// PermissionsToCS3ResourcePermissions converts the provided libregraph UnifiedRolePermissions to a cs3 ResourcePermissions
|
||||
func PermissionsToCS3ResourcePermissions(unifiedRolePermissions []*libregraph.UnifiedRolePermission) *provider.ResourcePermissions {
|
||||
p := &provider.ResourcePermissions{}
|
||||
|
||||
for _, permission := range unifiedRolePermissions {
|
||||
for _, allowedResourceAction := range permission.AllowedResourceActions {
|
||||
switch allowedResourceAction {
|
||||
case DriveItemPermissionsCreate:
|
||||
p.AddGrant = true
|
||||
case DriveItemChildrenCreate:
|
||||
p.CreateContainer = true
|
||||
case DriveItemStandardDelete:
|
||||
p.Delete = true
|
||||
case DriveItemPathRead:
|
||||
p.GetPath = true
|
||||
case DriveItemQuotaRead:
|
||||
p.GetQuota = true
|
||||
case DriveItemContentRead:
|
||||
p.InitiateFileDownload = true
|
||||
case DriveItemUploadCreate:
|
||||
p.InitiateFileUpload = true
|
||||
case DriveItemPermissionsRead:
|
||||
p.ListGrants = true
|
||||
case DriveItemChildrenRead:
|
||||
p.ListContainer = true
|
||||
case DriveItemVersionsRead:
|
||||
p.ListFileVersions = true
|
||||
case DriveItemDeletedRead:
|
||||
p.ListRecycle = true
|
||||
case DriveItemPathUpdate:
|
||||
p.Move = true
|
||||
case DriveItemPermissionsDelete:
|
||||
p.RemoveGrant = true
|
||||
case DriveItemDeletedDelete:
|
||||
p.PurgeRecycle = true
|
||||
case DriveItemVersionsUpdate:
|
||||
p.RestoreFileVersion = true
|
||||
case DriveItemDeletedUpdate:
|
||||
p.RestoreRecycleItem = true
|
||||
case DriveItemBasicRead:
|
||||
p.Stat = true
|
||||
case DriveItemPermissionsUpdate:
|
||||
p.UpdateGrant = true
|
||||
case DriveItemPermissionsDeny:
|
||||
p.DenyGrant = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// CS3ResourcePermissionsToLibregraphActions converts the provided cs3 ResourcePermissions to a list of
|
||||
// libregraph actions
|
||||
func CS3ResourcePermissionsToLibregraphActions(p *provider.ResourcePermissions) (actions []string) {
|
||||
if p.GetAddGrant() {
|
||||
actions = append(actions, DriveItemPermissionsCreate)
|
||||
}
|
||||
if p.GetCreateContainer() {
|
||||
actions = append(actions, DriveItemChildrenCreate)
|
||||
}
|
||||
if p.GetDelete() {
|
||||
actions = append(actions, DriveItemStandardDelete)
|
||||
}
|
||||
if p.GetGetPath() {
|
||||
actions = append(actions, DriveItemPathRead)
|
||||
}
|
||||
if p.GetGetQuota() {
|
||||
actions = append(actions, DriveItemQuotaRead)
|
||||
}
|
||||
if p.GetInitiateFileDownload() {
|
||||
actions = append(actions, DriveItemContentRead)
|
||||
}
|
||||
if p.GetInitiateFileUpload() {
|
||||
actions = append(actions, DriveItemUploadCreate)
|
||||
}
|
||||
if p.GetListGrants() {
|
||||
actions = append(actions, DriveItemPermissionsRead)
|
||||
}
|
||||
if p.GetListContainer() {
|
||||
actions = append(actions, DriveItemChildrenRead)
|
||||
}
|
||||
if p.GetListFileVersions() {
|
||||
actions = append(actions, DriveItemVersionsRead)
|
||||
}
|
||||
if p.GetListRecycle() {
|
||||
actions = append(actions, DriveItemDeletedRead)
|
||||
}
|
||||
if p.GetMove() {
|
||||
actions = append(actions, DriveItemPathUpdate)
|
||||
}
|
||||
if p.GetRemoveGrant() {
|
||||
actions = append(actions, DriveItemPermissionsDelete)
|
||||
}
|
||||
if p.GetPurgeRecycle() {
|
||||
actions = append(actions, DriveItemDeletedDelete)
|
||||
}
|
||||
if p.GetRestoreFileVersion() {
|
||||
actions = append(actions, DriveItemVersionsUpdate)
|
||||
}
|
||||
if p.GetRestoreRecycleItem() {
|
||||
actions = append(actions, DriveItemDeletedUpdate)
|
||||
}
|
||||
if p.GetStat() {
|
||||
actions = append(actions, DriveItemBasicRead)
|
||||
}
|
||||
if p.GetUpdateGrant() {
|
||||
actions = append(actions, DriveItemPermissionsUpdate)
|
||||
}
|
||||
if p.GetDenyGrant() {
|
||||
actions = append(actions, DriveItemPermissionsDeny)
|
||||
}
|
||||
return actions
|
||||
}
|
||||
|
||||
func GetLegacyName(role libregraph.UnifiedRoleDefinition) string {
|
||||
return legacyNames[role.GetId()]
|
||||
}
|
||||
|
||||
// CS3ResourcePermissionsToUnifiedRole tries to find the UnifiedRoleDefinition that matches the supplied
|
||||
// CS3 ResourcePermissions and constraints.
|
||||
func CS3ResourcePermissionsToUnifiedRole(p *provider.ResourcePermissions, constraints string) *libregraph.UnifiedRoleDefinition {
|
||||
actionSet := map[string]struct{}{}
|
||||
for _, action := range CS3ResourcePermissionsToLibregraphActions(p) {
|
||||
actionSet[action] = struct{}{}
|
||||
}
|
||||
|
||||
var res *libregraph.UnifiedRoleDefinition
|
||||
// fixMe: should we consider all roles or only the ones that are enabled?
|
||||
for _, uRole := range GetBuiltinRoleDefinitionList() {
|
||||
matchFound := false
|
||||
for _, uPerm := range uRole.GetRolePermissions() {
|
||||
if uPerm.GetCondition() != constraints {
|
||||
// the requested constraints don't match, this isn't our role
|
||||
continue
|
||||
}
|
||||
|
||||
// if the actions converted from the ResourcePermissions equal the action the defined for the role, we have match
|
||||
if resourceActionsEqual(actionSet, uPerm.GetAllowedResourceActions()) {
|
||||
matchFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if matchFound {
|
||||
res = uRole
|
||||
break
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func resourceActionsEqual(targetActionSet map[string]struct{}, actions []string) bool {
|
||||
if len(targetActionSet) != len(actions) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, action := range actions {
|
||||
if _, ok := targetActionSet[action]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func displayName(role *conversions.Role) *string {
|
||||
if role == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var displayName string
|
||||
switch role.Name {
|
||||
case conversions.RoleViewer:
|
||||
displayName = _viewerUnifiedRoleDisplayName
|
||||
case conversions.RoleSpaceViewer:
|
||||
displayName = _spaceViewerUnifiedRoleDisplayName
|
||||
case conversions.RoleEditor:
|
||||
displayName = _editorUnifiedRoleDisplayName
|
||||
case conversions.RoleSpaceEditor:
|
||||
displayName = _spaceEditorUnifiedRoleDisplayName
|
||||
case conversions.RoleFileEditor:
|
||||
displayName = _fileEditorUnifiedRoleDisplayName
|
||||
case conversions.RoleEditorLite:
|
||||
displayName = _editorLiteUnifiedRoleDisplayName
|
||||
case conversions.RoleManager:
|
||||
displayName = _managerUnifiedRoleDisplayName
|
||||
case conversions.RoleSecureViewer:
|
||||
displayName = _secureViewerUnifiedRoleDisplayName
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
return proto.String(displayName)
|
||||
}
|
||||
|
||||
func convert(role *conversions.Role) []string {
|
||||
actions := make([]string, 0, 8)
|
||||
if role == nil && role.CS3ResourcePermissions() == nil {
|
||||
return actions
|
||||
}
|
||||
return CS3ResourcePermissionsToLibregraphActions(role.CS3ResourcePermissions())
|
||||
}
|
||||
|
||||
func GetAllowedResourceActions(role *libregraph.UnifiedRoleDefinition, condition string) []string {
|
||||
for _, p := range role.GetRolePermissions() {
|
||||
if p.GetCondition() == condition {
|
||||
return p.GetAllowedResourceActions()
|
||||
}
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
@@ -1,13 +1,24 @@
|
||||
package unifiedrole_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"slices"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
)
|
||||
|
||||
func TestUnifiedrole(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Unifiedrole Suite")
|
||||
func rolesToAction(definitions ...*libregraph.UnifiedRoleDefinition) []string {
|
||||
var actions []string
|
||||
|
||||
for _, definition := range definitions {
|
||||
for _, permission := range definition.GetRolePermissions() {
|
||||
for _, action := range permission.GetAllowedResourceActions() {
|
||||
if slices.Contains(actions, action) {
|
||||
continue
|
||||
}
|
||||
actions = append(actions, action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return actions
|
||||
}
|
||||
|
||||
@@ -1,305 +0,0 @@
|
||||
package unifiedrole_test
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
rConversions "github.com/cs3org/reva/v2/pkg/conversions"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/conversions"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/types"
|
||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||
|
||||
"github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole"
|
||||
)
|
||||
|
||||
var _ = Describe("unifiedroles", func() {
|
||||
DescribeTable("CS3ResourcePermissionsToUnifiedRole",
|
||||
func(legacyRole *rConversions.Role, unifiedRole *libregraph.UnifiedRoleDefinition, constraints string) {
|
||||
cs3perm := legacyRole.CS3ResourcePermissions()
|
||||
|
||||
r := unifiedrole.CS3ResourcePermissionsToUnifiedRole(cs3perm, constraints)
|
||||
Expect(r.GetId()).To(Equal(unifiedRole.GetId()))
|
||||
|
||||
},
|
||||
Entry(rConversions.RoleViewer, rConversions.NewViewerRole(), unifiedrole.NewViewerUnifiedRole(), unifiedrole.UnifiedRoleConditionFile),
|
||||
Entry(rConversions.RoleViewer, rConversions.NewViewerRole(), unifiedrole.NewViewerUnifiedRole(), unifiedrole.UnifiedRoleConditionFolder),
|
||||
Entry(rConversions.RoleEditor, rConversions.NewEditorRole(), unifiedrole.NewEditorUnifiedRole(), unifiedrole.UnifiedRoleConditionFolder),
|
||||
Entry(rConversions.RoleFileEditor, rConversions.NewFileEditorRole(), unifiedrole.NewFileEditorUnifiedRole(), unifiedrole.UnifiedRoleConditionFile),
|
||||
Entry(rConversions.RoleManager, rConversions.NewManagerRole(), unifiedrole.NewManagerUnifiedRole(), unifiedrole.UnifiedRoleConditionDrive),
|
||||
Entry(rConversions.RoleSpaceViewer, rConversions.NewSpaceViewerRole(), unifiedrole.NewSpaceViewerUnifiedRole(), unifiedrole.UnifiedRoleConditionDrive),
|
||||
Entry(rConversions.RoleSpaceEditor, rConversions.NewSpaceEditorRole(), unifiedrole.NewSpaceEditorUnifiedRole(), unifiedrole.UnifiedRoleConditionDrive),
|
||||
Entry(rConversions.RoleSecureViewer, rConversions.NewSecureViewerRole(), unifiedrole.NewSecureViewerUnifiedRole(), unifiedrole.UnifiedRoleConditionFile),
|
||||
Entry(rConversions.RoleSecureViewer, rConversions.NewSecureViewerRole(), unifiedrole.NewSecureViewerUnifiedRole(), unifiedrole.UnifiedRoleConditionFolder),
|
||||
)
|
||||
|
||||
DescribeTable("UnifiedRolePermissionsToCS3ResourcePermissions",
|
||||
func(cs3Role *rConversions.Role, libregraphRole *libregraph.UnifiedRoleDefinition, match bool) {
|
||||
permsFromCS3 := cs3Role.CS3ResourcePermissions()
|
||||
permsFromUnifiedRole := unifiedrole.PermissionsToCS3ResourcePermissions(
|
||||
conversions.ToPointerSlice(libregraphRole.RolePermissions),
|
||||
)
|
||||
|
||||
var matcher types.GomegaMatcher
|
||||
|
||||
if match {
|
||||
matcher = Equal(permsFromUnifiedRole)
|
||||
} else {
|
||||
matcher = Not(Equal(permsFromUnifiedRole))
|
||||
}
|
||||
|
||||
Expect(permsFromCS3).To(matcher)
|
||||
},
|
||||
Entry(rConversions.RoleViewer, rConversions.NewViewerRole(), unifiedrole.NewViewerUnifiedRole(), true),
|
||||
Entry(rConversions.RoleEditor, rConversions.NewEditorRole(), unifiedrole.NewEditorUnifiedRole(), true),
|
||||
Entry(rConversions.RoleFileEditor, rConversions.NewFileEditorRole(), unifiedrole.NewFileEditorUnifiedRole(), true),
|
||||
Entry(rConversions.RoleManager, rConversions.NewManagerRole(), unifiedrole.NewManagerUnifiedRole(), true),
|
||||
Entry(rConversions.RoleSecureViewer, rConversions.NewSecureViewerRole(), unifiedrole.NewSecureViewerUnifiedRole(), true),
|
||||
Entry("no match", rConversions.NewFileEditorRole(), unifiedrole.NewManagerUnifiedRole(), false),
|
||||
)
|
||||
|
||||
DescribeTable("WeightRoleDefinitions",
|
||||
func(roleDefinitions []*libregraph.UnifiedRoleDefinition, constraint string, descending bool, expectedDefinitions []*libregraph.UnifiedRoleDefinition) {
|
||||
|
||||
for i, generatedDefinition := range unifiedrole.WeightRoleDefinitions(roleDefinitions, constraint, descending) {
|
||||
Expect(generatedDefinition.Id).To(Equal(expectedDefinitions[i].Id))
|
||||
}
|
||||
},
|
||||
|
||||
Entry("ascending",
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
unifiedrole.NewFileEditorUnifiedRole(),
|
||||
},
|
||||
unifiedrole.UnifiedRoleConditionFile,
|
||||
false,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
unifiedrole.NewFileEditorUnifiedRole(),
|
||||
},
|
||||
),
|
||||
|
||||
Entry("descending",
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
unifiedrole.NewFileEditorUnifiedRole(),
|
||||
},
|
||||
unifiedrole.UnifiedRoleConditionFile,
|
||||
true,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewFileEditorUnifiedRole(),
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
{
|
||||
rolesToAction := func(definitions ...*libregraph.UnifiedRoleDefinition) []string {
|
||||
var actions []string
|
||||
|
||||
for _, definition := range definitions {
|
||||
for _, permission := range definition.GetRolePermissions() {
|
||||
for _, action := range permission.GetAllowedResourceActions() {
|
||||
if slices.Contains(actions, action) {
|
||||
continue
|
||||
}
|
||||
actions = append(actions, action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return actions
|
||||
}
|
||||
|
||||
DescribeTable("GetApplicableRoleDefinitionsForActions",
|
||||
func(givenActions []string, constraints string, listFederatedRoles bool, expectedDefinitions []*libregraph.UnifiedRoleDefinition) {
|
||||
|
||||
generatedDefinitions := unifiedrole.GetApplicableRoleDefinitionsForActions(givenActions, constraints, listFederatedRoles, false)
|
||||
|
||||
Expect(len(generatedDefinitions)).To(Equal(len(expectedDefinitions)))
|
||||
|
||||
for i, generatedDefinition := range generatedDefinitions {
|
||||
Expect(generatedDefinition.Id).To(Equal(expectedDefinitions[i].Id))
|
||||
Expect(*generatedDefinition.LibreGraphWeight).To(Equal(int32(i + 1)))
|
||||
}
|
||||
|
||||
generatedActions := rolesToAction(generatedDefinitions...)
|
||||
Expect(len(givenActions) >= len(generatedActions)).To(BeTrue())
|
||||
|
||||
for _, generatedAction := range generatedActions {
|
||||
Expect(slices.Contains(givenActions, generatedAction)).To(BeTrue())
|
||||
}
|
||||
},
|
||||
|
||||
Entry(
|
||||
"ViewerUnifiedRole",
|
||||
rolesToAction(unifiedrole.NewViewerUnifiedRole()),
|
||||
unifiedrole.UnifiedRoleConditionFolder,
|
||||
false,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewSecureViewerUnifiedRole(),
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
},
|
||||
),
|
||||
|
||||
Entry(
|
||||
"ViewerUnifiedRole | share",
|
||||
rolesToAction(unifiedrole.NewViewerUnifiedRole()),
|
||||
unifiedrole.UnifiedRoleConditionFile,
|
||||
false,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewSecureViewerUnifiedRole(),
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
},
|
||||
),
|
||||
|
||||
Entry(
|
||||
"ViewerUnifiedRole | share",
|
||||
rolesToAction(unifiedrole.NewViewerUnifiedRole()),
|
||||
unifiedrole.UnifiedRoleConditionFile,
|
||||
true,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
},
|
||||
),
|
||||
|
||||
Entry(
|
||||
"EditorUnifiedRole | share folder",
|
||||
rolesToAction(unifiedrole.NewEditorUnifiedRole()),
|
||||
unifiedrole.UnifiedRoleConditionFolder,
|
||||
true,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
unifiedrole.NewEditorUnifiedRole(),
|
||||
},
|
||||
),
|
||||
|
||||
Entry(
|
||||
"EditorUnifiedRole | share file",
|
||||
rolesToAction(unifiedrole.NewEditorUnifiedRole()),
|
||||
unifiedrole.UnifiedRoleConditionFile,
|
||||
true,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
unifiedrole.NewFileEditorUnifiedRole(),
|
||||
},
|
||||
),
|
||||
|
||||
Entry(
|
||||
"NewFileEditorUnifiedRole",
|
||||
rolesToAction(unifiedrole.NewFileEditorUnifiedRole()),
|
||||
unifiedrole.UnifiedRoleConditionFile,
|
||||
false,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewSecureViewerUnifiedRole(),
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
unifiedrole.NewFileEditorUnifiedRole(),
|
||||
},
|
||||
),
|
||||
|
||||
Entry(
|
||||
"NewEditorUnifiedRole",
|
||||
rolesToAction(unifiedrole.NewEditorUnifiedRole()),
|
||||
unifiedrole.UnifiedRoleConditionFolder,
|
||||
false,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewSecureViewerUnifiedRole(),
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
unifiedrole.NewEditorLiteUnifiedRole(),
|
||||
unifiedrole.NewEditorUnifiedRole(),
|
||||
},
|
||||
),
|
||||
|
||||
Entry(
|
||||
"GetBuiltinRoleDefinitionList",
|
||||
rolesToAction(unifiedrole.GetBuiltinRoleDefinitionList()...),
|
||||
unifiedrole.UnifiedRoleConditionFile,
|
||||
false,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewSecureViewerUnifiedRole(),
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
unifiedrole.NewFileEditorUnifiedRole(),
|
||||
},
|
||||
),
|
||||
|
||||
Entry(
|
||||
"GetBuiltinRoleDefinitionList",
|
||||
rolesToAction(unifiedrole.GetBuiltinRoleDefinitionList()...),
|
||||
unifiedrole.UnifiedRoleConditionFolder,
|
||||
false,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewSecureViewerUnifiedRole(),
|
||||
unifiedrole.NewViewerUnifiedRole(),
|
||||
unifiedrole.NewEditorLiteUnifiedRole(),
|
||||
unifiedrole.NewEditorUnifiedRole(),
|
||||
},
|
||||
),
|
||||
|
||||
Entry(
|
||||
"GetBuiltinRoleDefinitionList",
|
||||
rolesToAction(unifiedrole.GetBuiltinRoleDefinitionList()...),
|
||||
unifiedrole.UnifiedRoleConditionDrive,
|
||||
false,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewSpaceViewerUnifiedRole(),
|
||||
unifiedrole.NewSpaceEditorUnifiedRole(),
|
||||
unifiedrole.NewManagerUnifiedRole(),
|
||||
},
|
||||
),
|
||||
|
||||
Entry(
|
||||
"single",
|
||||
[]string{unifiedrole.DriveItemQuotaRead},
|
||||
unifiedrole.UnifiedRoleConditionFile,
|
||||
false,
|
||||
[]*libregraph.UnifiedRoleDefinition{},
|
||||
),
|
||||
|
||||
Entry(
|
||||
"mixed",
|
||||
append(rolesToAction(unifiedrole.NewEditorLiteUnifiedRole()), unifiedrole.DriveItemQuotaRead),
|
||||
unifiedrole.UnifiedRoleConditionFolder,
|
||||
false,
|
||||
[]*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.NewSecureViewerUnifiedRole(),
|
||||
unifiedrole.NewEditorLiteUnifiedRole(),
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
var newUnifiedRoleFromIDEntries []TableEntry
|
||||
attachEntry := func(name, id string, definition *libregraph.UnifiedRoleDefinition, errors bool) {
|
||||
e := Entry(
|
||||
name,
|
||||
id,
|
||||
definition,
|
||||
errors,
|
||||
)
|
||||
|
||||
newUnifiedRoleFromIDEntries = append(newUnifiedRoleFromIDEntries, e)
|
||||
}
|
||||
|
||||
for _, definition := range unifiedrole.GetBuiltinRoleDefinitionList() {
|
||||
attachEntry(definition.GetDisplayName(), definition.GetId(), definition, false)
|
||||
}
|
||||
|
||||
attachEntry("unknown", "123", nil, true)
|
||||
|
||||
DescribeTable("NewUnifiedRoleFromID",
|
||||
func(id string, expectedRole *libregraph.UnifiedRoleDefinition, expectError bool) {
|
||||
role, err := unifiedrole.NewUnifiedRoleFromID(id)
|
||||
|
||||
if expectError {
|
||||
Expect(err).To(HaveOccurred())
|
||||
} else {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(role).To(Equal(expectedRole))
|
||||
}
|
||||
},
|
||||
newUnifiedRoleFromIDEntries,
|
||||
)
|
||||
}
|
||||
})
|
||||
@@ -90,9 +90,9 @@ func rolesAndActions(ctx context.Context, sl validator.StructLevel, roles, actio
|
||||
|
||||
switch roles, ok := ctx.Value(_contextRoleIDsValueKey).([]string); {
|
||||
case ok:
|
||||
definitions = unifiedrole.GetBuiltinRoleDefinitionList(unifiedrole.RoleFilterIDs(roles...))
|
||||
definitions = unifiedrole.GetDefinitions(unifiedrole.RoleFilterIDs(roles...))
|
||||
default:
|
||||
definitions = unifiedrole.GetBuiltinRoleDefinitionList()
|
||||
definitions = unifiedrole.GetDefinitions(unifiedrole.RoleFilterAll())
|
||||
}
|
||||
|
||||
for _, definition := range definitions {
|
||||
|
||||
@@ -27,8 +27,8 @@ var _ = Describe("libregraph", func() {
|
||||
|
||||
driveItemInvite = libregraph.DriveItemInvite{
|
||||
Recipients: []libregraph.DriveRecipient{driveRecipient},
|
||||
Roles: []string{unifiedrole.UnifiedRoleEditorID},
|
||||
LibreGraphPermissionsActions: []string{unifiedrole.DriveItemVersionsUpdate},
|
||||
Roles: []string{role.UnifiedRoleEditorID},
|
||||
LibreGraphPermissionsActions: []string{role.DriveItemVersionsUpdate},
|
||||
ExpirationDateTime: libregraph.PtrTime(time.Now().Add(time.Hour)),
|
||||
}
|
||||
|
||||
@@ -61,8 +61,8 @@ var _ = Describe("libregraph", func() {
|
||||
}),
|
||||
Entry("fail: multiple role assignment", func() (libregraph.DriveItemInvite, bool) {
|
||||
driveItemInvite.Roles = []string{
|
||||
unifiedrole.UnifiedRoleEditorID,
|
||||
unifiedrole.UnifiedRoleManagerID,
|
||||
role.UnifiedRoleEditorID,
|
||||
role.UnifiedRoleManagerID,
|
||||
}
|
||||
driveItemInvite.LibreGraphPermissionsActions = nil
|
||||
return driveItemInvite, false
|
||||
@@ -84,8 +84,8 @@ var _ = Describe("libregraph", func() {
|
||||
}),
|
||||
Entry("fail: different number of roles and actions", func() (libregraph.DriveItemInvite, bool) {
|
||||
driveItemInvite.LibreGraphPermissionsActions = []string{
|
||||
unifiedrole.DriveItemVersionsUpdate,
|
||||
unifiedrole.DriveItemChildrenCreate,
|
||||
role.DriveItemVersionsUpdate,
|
||||
role.DriveItemChildrenCreate,
|
||||
}
|
||||
return driveItemInvite, false
|
||||
}),
|
||||
|
||||
@@ -70,5 +70,5 @@ func TestService_Get(t *testing.T) {
|
||||
// brandingTheme
|
||||
assert.Equal(t, jsonData.Get("_branding").String(), "_branding")
|
||||
// themeDefaults
|
||||
assert.Equal(t, jsonData.Get("common.shareRoles."+unifiedrole.UnifiedRoleViewerID+".name").String(), "UnifiedRoleViewer")
|
||||
assert.Equal(t, jsonData.Get("common.shareRoles."+role.UnifiedRoleViewerID+".name").String(), "UnifiedRoleViewer")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user