Initial QSfera import
This commit is contained in:
@@ -0,0 +1,234 @@
|
||||
package unifiedrole
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/conversions"
|
||||
libregraph "github.com/opencloud-eu/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
|
||||
}
|
||||
|
||||
// CS3ResourcePermissionsToRole converts the provided cs3 ResourcePermissions to a libregraph UnifiedRoleDefinition
|
||||
func CS3ResourcePermissionsToRole(roleSet []*libregraph.UnifiedRoleDefinition, p *provider.ResourcePermissions, constraints string, listFederatedRoles bool) *libregraph.UnifiedRoleDefinition {
|
||||
actionSet := map[string]struct{}{}
|
||||
for _, action := range CS3ResourcePermissionsToLibregraphActions(p) {
|
||||
actionSet[action] = struct{}{}
|
||||
}
|
||||
|
||||
var res *libregraph.UnifiedRoleDefinition
|
||||
for _, uRole := range roleSet {
|
||||
definitionMatch := false
|
||||
|
||||
for _, permission := range uRole.GetRolePermissions() {
|
||||
// this is a dirty comparison because we are not really parsing the SDDL, but as long as we && the conditions we are good
|
||||
isFederatedRole := strings.Contains(permission.GetCondition(), UnifiedRoleConditionFederatedUser)
|
||||
switch {
|
||||
case !strings.Contains(permission.GetCondition(), constraints):
|
||||
continue
|
||||
case listFederatedRoles && !isFederatedRole:
|
||||
continue
|
||||
case !listFederatedRoles && isFederatedRole:
|
||||
continue
|
||||
}
|
||||
|
||||
// if the actions converted from the ResourcePermissions equal the action the defined for the role, we have match
|
||||
if resourceActionsEqual(actionSet, permission.GetAllowedResourceActions()) {
|
||||
definitionMatch = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if definitionMatch {
|
||||
res = uRole
|
||||
break
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// resourceActionsEqual checks if the provided actions are equal to the actions defined for a resource
|
||||
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
|
||||
}
|
||||
|
||||
// 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.RoleViewerListGrants:
|
||||
return _viewerListGrantsUnifiedRoleDisplayName
|
||||
case conversions.RoleSpaceViewer:
|
||||
return _spaceViewerUnifiedRoleDisplayName
|
||||
case conversions.RoleEditor:
|
||||
return _editorUnifiedRoleDisplayName
|
||||
case conversions.RoleEditorListGrants:
|
||||
return _editorListGrantsUnifiedRoleDisplayName
|
||||
case conversions.RoleSpaceEditor:
|
||||
return _spaceEditorUnifiedRoleDisplayName
|
||||
case conversions.RoleSpaceEditorWithoutVersions:
|
||||
return _spaceEditorWithoutVersionsUnifiedRoleDisplayName
|
||||
case conversions.RoleFileEditor:
|
||||
return _fileEditorUnifiedRoleDisplayName
|
||||
case conversions.RoleFileEditorListGrants:
|
||||
return _fileEditorListGrantsUnifiedRoleDisplayName
|
||||
case conversions.RoleEditorLite:
|
||||
return _editorLiteUnifiedRoleDisplayName
|
||||
case conversions.RoleManager:
|
||||
return _managerUnifiedRoleDisplayName
|
||||
case conversions.RoleSecureViewer:
|
||||
return _secureViewerUnifiedRoleDisplayName
|
||||
case conversions.RoleDenied:
|
||||
return _deniedUnifiedRoleDisplayName
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package unifiedrole_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/types"
|
||||
cs3Conversions "github.com/opencloud-eu/reva/v2/pkg/conversions"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
|
||||
"github.com/qsfera/server/pkg/conversions"
|
||||
"github.com/qsfera/server/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.RoleViewerListGrants: {cs3Conversions.NewViewerListGrantsRole(), unifiedrole.RoleViewerListGrants, true},
|
||||
cs3Conversions.RoleEditor: {cs3Conversions.NewEditorRole(), unifiedrole.RoleEditor, true},
|
||||
cs3Conversions.RoleEditorListGrants: {cs3Conversions.NewEditorListGrantsRole(), unifiedrole.RoleEditorListGrants, true},
|
||||
cs3Conversions.RoleFileEditor: {cs3Conversions.NewFileEditorRole(), unifiedrole.RoleFileEditor, true},
|
||||
cs3Conversions.RoleFileEditorListGrants: {cs3Conversions.NewFileEditorListGrantsRole(), unifiedrole.RoleFileEditorListGrants, true},
|
||||
cs3Conversions.RoleManager: {cs3Conversions.NewManagerRole(), unifiedrole.RoleManager, true},
|
||||
cs3Conversions.RoleSecureViewer: {cs3Conversions.NewSecureViewerRole(), unifiedrole.RoleSecureViewer, true},
|
||||
cs3Conversions.RoleDenied: {cs3Conversions.NewDeniedRole(), unifiedrole.RoleDenied, 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 TestCS3ResourcePermissionsToRole(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},
|
||||
cs3Conversions.RoleDenied: {cs3Conversions.NewDeniedRole().CS3ResourcePermissions(), unifiedrole.RoleDenied, 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.CS3ResourcePermissionsToRole(unifiedrole.BuildInRoles, tc.cs3ResourcePermissions, tc.constraints, false),
|
||||
).To(Equal(tc.unifiedRoleDefinition))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package unifiedrole
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrUnknownRole is returned when an unknown unified role is requested.
|
||||
ErrUnknownRole = errors.New("unknown role, check if the role is enabled")
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
package unifiedrole
|
||||
|
||||
var (
|
||||
RoleViewer = roleViewer
|
||||
RoleViewerListGrants = roleViewerListGrants
|
||||
RoleSpaceViewer = roleSpaceViewer
|
||||
RoleEditor = roleEditor
|
||||
RoleEditorListGrants = roleEditorListGrants
|
||||
RoleSpaceEditor = roleSpaceEditor
|
||||
RoleSpaceEditorWithoutVersions = roleSpaceEditorWithoutVersions
|
||||
RoleFileEditor = roleFileEditor
|
||||
RoleFileEditorListGrants = roleFileEditorListGrants
|
||||
RoleEditorLite = roleEditorLite
|
||||
RoleManager = roleManager
|
||||
RoleSecureViewer = roleSecureViewer
|
||||
RoleDenied = roleDenied
|
||||
|
||||
BuildInRoles = buildInRoles
|
||||
|
||||
WeightDefinitions = weightRoles
|
||||
)
|
||||
@@ -0,0 +1,44 @@
|
||||
package unifiedrole
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
)
|
||||
|
||||
type (
|
||||
// RoleFilter is used to filter role collections
|
||||
RoleFilter func(*libregraph.UnifiedRoleDefinition) bool
|
||||
)
|
||||
|
||||
// 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())
|
||||
}
|
||||
}
|
||||
|
||||
// filterRoles filters the provided roles by the provided filter
|
||||
func filterRoles(roles []*libregraph.UnifiedRoleDefinition, f RoleFilter) []*libregraph.UnifiedRoleDefinition {
|
||||
return slices.DeleteFunc(
|
||||
slices.Clone(roles),
|
||||
func(r *libregraph.UnifiedRoleDefinition) bool {
|
||||
return !f(r)
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package unifiedrole_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
|
||||
"github.com/qsfera/server/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(
|
||||
func(_ *libregraph.UnifiedRoleDefinition) bool {
|
||||
return true
|
||||
},
|
||||
)(unifiedrole.RoleEditorLite),
|
||||
).To(BeFalse())
|
||||
}
|
||||
|
||||
func TestRoleFilterAll(t *testing.T) {
|
||||
NewWithT(t).Expect(
|
||||
unifiedrole.RoleFilterAll()(unifiedrole.RoleEditorLite),
|
||||
).To(BeTrue())
|
||||
}
|
||||
@@ -0,0 +1,562 @@
|
||||
package unifiedrole
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/opencloud-eu/reva/v2/pkg/conversions"
|
||||
|
||||
"github.com/qsfera/server/pkg/l10n"
|
||||
)
|
||||
|
||||
const (
|
||||
// UnifiedRoleViewerID Unified role viewer id.
|
||||
UnifiedRoleViewerID = "b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5"
|
||||
// UnifiedRoleViewerListGrantsID Unified role viewer id.
|
||||
UnifiedRoleViewerListGrantsID = "d5041006-ebb3-4b4a-b6a4-7c180ecfb17d"
|
||||
// UnifiedRoleSpaceViewerID Unified role space viewer id.
|
||||
UnifiedRoleSpaceViewerID = "a8d5fe5e-96e3-418d-825b-534dbdf22b99"
|
||||
// UnifiedRoleEditorID Unified role editor id.
|
||||
UnifiedRoleEditorID = "fb6c3e19-e378-47e5-b277-9732f9de6e21"
|
||||
// UnifiedRoleEditorListGrantsID Unified role editor id.
|
||||
UnifiedRoleEditorListGrantsID = "e8ea8b21-abd4-45d2-b893-8d1546378e9e"
|
||||
// UnifiedRoleSpaceEditorID Unified role space editor id.
|
||||
UnifiedRoleSpaceEditorID = "58c63c02-1d89-4572-916a-870abc5a1b7d"
|
||||
// UnifiedRoleSpaceEditorWithoutVersionsID Unified role space editor without list/restore versions id.
|
||||
UnifiedRoleSpaceEditorWithoutVersionsID = "3284f2d5-0070-4ad8-ac40-c247f7c1fb27"
|
||||
// UnifiedRoleFileEditorID Unified role file editor id.
|
||||
UnifiedRoleFileEditorID = "2d00ce52-1fc2-4dbc-8b95-a73b73395f5a"
|
||||
// UnifiedRoleFileEditorListGrantsID Unified role file editor id.
|
||||
UnifiedRoleFileEditorListGrantsID = "c1235aea-d106-42db-8458-7d5610fb0a67"
|
||||
// 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"
|
||||
// UnifiedRoleDeniedID Unified role to deny all access.
|
||||
UnifiedRoleDeniedID = "63e64e19-8d43-42ec-a738-2b6af2610efa"
|
||||
|
||||
// Wile the below conditions follow the SDDL syntax, they are not parsed anywhere. We use them as strings to
|
||||
// represent the constraints that a role definition applies to. For the actual syntax, see the SDDL documentation
|
||||
// at https://learn.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-definition-language-for-conditional-aces-#conditional-expressions
|
||||
|
||||
// Some roles apply to a specific type of resource, for example, a role that applies to a file or a folder.
|
||||
// @Resource is the placeholder for the resource that the role is applied to
|
||||
// .Root, .Folder and .File are facets of the driveItem resource that indicate the type of the resource if they are present.
|
||||
|
||||
// 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"
|
||||
|
||||
// Some roles apply to a specific type of user, for example, a role that applies to a federated user.
|
||||
// @Subject is the placeholder for the subject that the role is applied to. For sharing roles this is the user that the resource is shared with.
|
||||
// .UserType is the type of the user: 'Member' for a member of the organization, 'Guest' for a guest user, 'Federated' for a federated user.
|
||||
|
||||
// UnifiedRoleConditionFederatedUser defines a constraint that matches a federated user
|
||||
UnifiedRoleConditionFederatedUser = "@Subject.UserType==\"Federated\""
|
||||
|
||||
// For federated sharing we need roles that combine the constraints for the resource and the user.
|
||||
// UnifiedRoleConditionFileFederatedUser defines a constraint that matches a File and a federated user
|
||||
UnifiedRoleConditionFileFederatedUser = UnifiedRoleConditionFile + " && " + UnifiedRoleConditionFederatedUser
|
||||
// UnifiedRoleConditionFolderFederatedUser defines a constraint that matches a Folder and a federated user
|
||||
UnifiedRoleConditionFolderFederatedUser = UnifiedRoleConditionFolder + " && " + UnifiedRoleConditionFederatedUser
|
||||
|
||||
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 ViewerListGrants, Role Description (resolves directly)
|
||||
_viewerListGrantsUnifiedRoleDescription = l10n.Template("View, download and show all invited people.")
|
||||
|
||||
// UnifiedRole Viewer, Role DisplayName (resolves directly)
|
||||
_viewerListGrantsUnifiedRoleDisplayName = 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")
|
||||
|
||||
// UnifiedRoleListGrants Editor, Role Description (resolves directly)
|
||||
_editorListGrantsUnifiedRoleDescription = l10n.Template("View, download, upload, edit, add, delete and show all invited people.")
|
||||
|
||||
// UnifiedRole EditorListGrants, Role DisplayName (resolves directly)
|
||||
_editorListGrantsUnifiedRoleDisplayName = l10n.Template("Can edit")
|
||||
|
||||
// UnifiedRole SpaseEditor, Role Description (resolves directly)
|
||||
_spaceEditorUnifiedRoleDescription = l10n.Template("View, download, upload, edit, add, delete including the history.")
|
||||
|
||||
// UnifiedRole SpaseEditor, Role DisplayName (resolves directly)
|
||||
_spaceEditorUnifiedRoleDisplayName = l10n.Template("Can edit")
|
||||
|
||||
// UnifiedRole SpaseEditorWithoutVersions, Role Description (resolves directly)
|
||||
_spaceEditorWithoutVersionsUnifiedRoleDescription = l10n.Template("View, download, upload, edit, add and delete.")
|
||||
|
||||
// UnifiedRole SpaseEditorWithoutVersions, Role DisplayName (resolves directly)
|
||||
_spaceEditorWithoutVersionsUnifiedRoleDisplayName = l10n.Template("Can edit without versions")
|
||||
|
||||
// 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 FileEditorListGrants, Role Description (resolves directly)
|
||||
_fileEditorListGrantsUnifiedRoleDescription = l10n.Template("View, download, edit and show all invited people.")
|
||||
|
||||
// UnifiedRole FileEditorListGrants, Role DisplayName (resolves directly)
|
||||
_fileEditorListGrantsUnifiedRoleDisplayName = 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)")
|
||||
|
||||
// UnifiedRole FullDenial, Role Description (resolves directly)
|
||||
_deniedUnifiedRoleDescription = l10n.Template("Deny all access.")
|
||||
|
||||
// UnifiedRole FullDenial, Role DisplayName (resolves directly)
|
||||
_deniedUnifiedRoleDisplayName = l10n.Template("Cannot access")
|
||||
|
||||
// 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",
|
||||
UnifiedRoleSpaceEditorWithoutVersionsID: conversions.RoleSpaceEditorWithoutVersions,
|
||||
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,
|
||||
roleViewerListGrants,
|
||||
roleSpaceViewer,
|
||||
roleEditor,
|
||||
roleEditorListGrants,
|
||||
roleSpaceEditor,
|
||||
roleSpaceEditorWithoutVersions,
|
||||
roleFileEditor,
|
||||
roleFileEditorListGrants,
|
||||
roleEditorLite,
|
||||
roleManager,
|
||||
roleSecureViewer,
|
||||
roleDenied,
|
||||
}
|
||||
|
||||
// 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),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFileFederatedUser),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolderFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(10),
|
||||
}
|
||||
}()
|
||||
|
||||
// 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(20),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleViewerListGrants creates a viewer role.
|
||||
roleViewerListGrants = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewViewerListGrantsRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleViewerListGrantsID),
|
||||
Description: proto.String(_viewerListGrantsUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFile),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFileFederatedUser),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolderFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(30),
|
||||
}
|
||||
}()
|
||||
|
||||
// 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(40),
|
||||
}
|
||||
}()
|
||||
|
||||
// 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(50),
|
||||
}
|
||||
}()
|
||||
|
||||
// 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),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolderFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(60),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleEditorListGrants creates an editor role.
|
||||
roleEditorListGrants = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewEditorListGrantsRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleEditorListGrantsID),
|
||||
Description: proto.String(_editorListGrantsUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolderFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(70),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleSpaceEditorWithoutVersions creates an editor without versions role
|
||||
roleSpaceEditorWithoutVersions = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewSpaceEditorWithoutVersionsRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleSpaceEditorWithoutVersionsID),
|
||||
Description: proto.String(_spaceEditorWithoutVersionsUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionDrive),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(80),
|
||||
}
|
||||
}()
|
||||
|
||||
// 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(90),
|
||||
}
|
||||
}()
|
||||
|
||||
// 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),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFileFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(100),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleFileEditorListGrants creates a file-editor role
|
||||
roleFileEditorListGrants = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewFileEditorListGrantsRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleFileEditorListGrantsID),
|
||||
Description: proto.String(_fileEditorListGrantsUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFile),
|
||||
},
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFileFederatedUser),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(110),
|
||||
}
|
||||
}()
|
||||
|
||||
// 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(120),
|
||||
}
|
||||
}()
|
||||
|
||||
// roleDenied creates a secure viewer role
|
||||
roleDenied = func() *libregraph.UnifiedRoleDefinition {
|
||||
r := conversions.NewDeniedRole()
|
||||
return &libregraph.UnifiedRoleDefinition{
|
||||
Id: proto.String(UnifiedRoleDeniedID),
|
||||
Description: proto.String(_deniedUnifiedRoleDescription),
|
||||
DisplayName: proto.String(cs3RoleToDisplayName(r)),
|
||||
RolePermissions: []libregraph.UnifiedRolePermission{
|
||||
{
|
||||
AllowedResourceActions: CS3ResourcePermissionsToLibregraphActions(r.CS3ResourcePermissions()),
|
||||
Condition: proto.String(UnifiedRoleConditionFolder),
|
||||
},
|
||||
},
|
||||
LibreGraphWeight: proto.Int32(200),
|
||||
}
|
||||
}()
|
||||
)
|
||||
|
||||
// GetRoles returns a role filter that matches the provided resources
|
||||
func GetRoles(f RoleFilter) []*libregraph.UnifiedRoleDefinition {
|
||||
return filterRoles(buildInRoles, f)
|
||||
}
|
||||
|
||||
// GetRole returns a role filter that matches the provided resources
|
||||
func GetRole(f RoleFilter) (*libregraph.UnifiedRoleDefinition, error) {
|
||||
roles := filterRoles(buildInRoles, f)
|
||||
if len(roles) == 0 {
|
||||
return nil, ErrUnknownRole
|
||||
}
|
||||
|
||||
return roles[0], nil
|
||||
}
|
||||
|
||||
// GetRolesByPermissions returns a list of role definitions
|
||||
// that match the provided actions and constraints
|
||||
func GetRolesByPermissions(roleSet []*libregraph.UnifiedRoleDefinition, actions []string, constraints string, listFederatedRoles, descending bool) []*libregraph.UnifiedRoleDefinition {
|
||||
roles := make([]*libregraph.UnifiedRoleDefinition, 0, len(roleSet))
|
||||
|
||||
for _, role := range roleSet {
|
||||
var match bool
|
||||
|
||||
for _, permission := range role.GetRolePermissions() {
|
||||
// this is a dirty comparison because we are not really parsing the SDDL, but as long as we && the conditions we are good
|
||||
isFederatedRole := strings.Contains(permission.GetCondition(), UnifiedRoleConditionFederatedUser)
|
||||
switch {
|
||||
case !strings.Contains(permission.GetCondition(), constraints):
|
||||
continue
|
||||
case listFederatedRoles && !isFederatedRole:
|
||||
continue
|
||||
case !listFederatedRoles && isFederatedRole:
|
||||
continue
|
||||
}
|
||||
|
||||
for i, action := range permission.GetAllowedResourceActions() {
|
||||
if !slices.Contains(actions, action) {
|
||||
break
|
||||
}
|
||||
if i == len(permission.GetAllowedResourceActions())-1 {
|
||||
match = true
|
||||
}
|
||||
}
|
||||
if role.GetId() == UnifiedRoleDeniedID && slices.Contains(actions, DriveItemPermissionsDeny) {
|
||||
match = true
|
||||
}
|
||||
if match {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if match {
|
||||
roles = append(roles, role)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return weightRoles(roles, constraints, descending)
|
||||
}
|
||||
|
||||
// GetLegacyRoleName returns the legacy role name for the provided role
|
||||
func GetLegacyRoleName(role libregraph.UnifiedRoleDefinition) string {
|
||||
return legacyNames[role.GetId()]
|
||||
}
|
||||
|
||||
// weightRoles sorts the provided role definitions by the number of LibreGraphWeight,
|
||||
// descending - false - sorts the roles from least to most permissions
|
||||
// descending - true - sorts the roles from most to least permissions
|
||||
func weightRoles(roleSet []*libregraph.UnifiedRoleDefinition, constraints string, descending bool) []*libregraph.UnifiedRoleDefinition {
|
||||
slices.SortFunc(roleSet, func(a, b *libregraph.UnifiedRoleDefinition) int {
|
||||
if descending {
|
||||
return cmp.Compare(b.GetLibreGraphWeight(), a.GetLibreGraphWeight())
|
||||
}
|
||||
return cmp.Compare(a.GetLibreGraphWeight(), b.GetLibreGraphWeight())
|
||||
})
|
||||
|
||||
return roleSet
|
||||
}
|
||||
|
||||
// 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{}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
package unifiedrole_test
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/qsfera/server/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.ErrUnknownRole,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
definition, err := unifiedrole.GetRole(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
|
||||
listFederatedRoles bool
|
||||
unifiedRoleDefinition []*libregraph.UnifiedRoleDefinition
|
||||
}{
|
||||
"RoleViewer | folder": {
|
||||
givenActions: getRoleActions(unifiedrole.RoleViewer),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFolder,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
},
|
||||
},
|
||||
"RoleViewer | file": {
|
||||
givenActions: getRoleActions(unifiedrole.RoleViewer),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
},
|
||||
},
|
||||
"RoleViewer | file | federated": {
|
||||
givenActions: getRoleActions(unifiedrole.RoleViewer),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
listFederatedRoles: true,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
},
|
||||
},
|
||||
"RoleFileEditor | file": {
|
||||
givenActions: getRoleActions(unifiedrole.RoleFileEditor),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleFileEditor,
|
||||
},
|
||||
},
|
||||
"RoleEditor | folder": {
|
||||
givenActions: getRoleActions(unifiedrole.RoleEditor),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFolder,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleEditorLite,
|
||||
unifiedrole.RoleEditor,
|
||||
},
|
||||
},
|
||||
"RoleEditor | folder | federated": {
|
||||
givenActions: getRoleActions(unifiedrole.RoleEditor),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFolder,
|
||||
listFederatedRoles: true,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleEditor,
|
||||
},
|
||||
},
|
||||
"RoleEditor | file | federated": {
|
||||
givenActions: getRoleActions(unifiedrole.RoleEditor),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
listFederatedRoles: true,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleFileEditor,
|
||||
},
|
||||
},
|
||||
"BuildInRoles | file": {
|
||||
givenActions: getRoleActions(unifiedrole.BuildInRoles...),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewerListGrants,
|
||||
unifiedrole.RoleFileEditor,
|
||||
unifiedrole.RoleFileEditorListGrants,
|
||||
},
|
||||
},
|
||||
"BuildInRoles | folder": {
|
||||
givenActions: getRoleActions(unifiedrole.BuildInRoles...),
|
||||
constraints: unifiedrole.UnifiedRoleConditionFolder,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleViewer,
|
||||
unifiedrole.RoleSecureViewer,
|
||||
unifiedrole.RoleViewerListGrants,
|
||||
unifiedrole.RoleEditorLite,
|
||||
unifiedrole.RoleEditor,
|
||||
unifiedrole.RoleEditorListGrants,
|
||||
unifiedrole.RoleDenied,
|
||||
},
|
||||
},
|
||||
"BuildInRoles | drive": {
|
||||
givenActions: getRoleActions(unifiedrole.BuildInRoles...),
|
||||
constraints: unifiedrole.UnifiedRoleConditionDrive,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{
|
||||
unifiedrole.RoleSpaceViewer,
|
||||
unifiedrole.RoleSpaceEditorWithoutVersions,
|
||||
unifiedrole.RoleSpaceEditor,
|
||||
unifiedrole.RoleManager,
|
||||
},
|
||||
},
|
||||
"custom | file": {
|
||||
givenActions: []string{unifiedrole.DriveItemQuotaRead},
|
||||
constraints: unifiedrole.UnifiedRoleConditionFile,
|
||||
unifiedRoleDefinition: []*libregraph.UnifiedRoleDefinition{},
|
||||
},
|
||||
"RoleEditorLite and custom | folder": {
|
||||
givenActions: append(getRoleActions(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(unifiedrole.BuildInRoles, tc.givenActions, tc.constraints, tc.listFederatedRoles, 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(tc.unifiedRoleDefinition[i].LibreGraphWeight))
|
||||
}
|
||||
|
||||
generatedActions := getRoleActions(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))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package unifiedrole_test
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
libregraph "github.com/opencloud-eu/libre-graph-api-go"
|
||||
)
|
||||
|
||||
func getRoleActions(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
|
||||
}
|
||||
Reference in New Issue
Block a user