diff --git a/services/graph/pkg/service/v0/sharedbyme.go b/services/graph/pkg/service/v0/sharedbyme.go index 18621d3f52f..26ebf1dacd1 100644 --- a/services/graph/pkg/service/v0/sharedbyme.go +++ b/services/graph/pkg/service/v0/sharedbyme.go @@ -17,6 +17,7 @@ import ( libregraph "github.com/owncloud/libre-graph-api-go" "github.com/owncloud/ocis/v2/services/graph/pkg/identity" "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode" + "github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole" ) type driveItemsByResourceID map[string]libregraph.DriveItem @@ -160,7 +161,18 @@ func (g Graph) cs3UserSharesToDriveItems(ctx context.Context, shares []*collabor if s.GetExpiration() != nil { perm.SetExpirationDateTime(cs3TimestampToTime(s.GetExpiration())) } - + role := unifiedrole.CS3ResourcePermissionsToUnifiedRole( + *s.GetPermissions().GetPermissions(), + unifiedrole.UnifiedRoleConditionGrantee, + g.config.FilesSharing.EnableResharing, + ) + if role != nil { + perm.SetRoles([]string{role.GetId()}) + } else { + actions := unifiedrole.CS3ResourcePermissionsToLibregraphActions(*s.GetPermissions().GetPermissions()) + perm.SetLibreGraphPermissionsActions(actions) + perm.SetRoles(nil) + } perm.SetGrantedToV2(grantedTo) item.Permissions = append(item.Permissions, perm) driveItems[resIDStr] = item diff --git a/services/graph/pkg/service/v0/sharedbyme_test.go b/services/graph/pkg/service/v0/sharedbyme_test.go index edfe78cfe9f..ac128364abe 100644 --- a/services/graph/pkg/service/v0/sharedbyme_test.go +++ b/services/graph/pkg/service/v0/sharedbyme_test.go @@ -15,6 +15,7 @@ import ( collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/v2/pkg/conversions" "github.com/cs3org/reva/v2/pkg/rgrpc/status" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/v2/pkg/storagespace" @@ -28,6 +29,7 @@ import ( "github.com/owncloud/ocis/v2/services/graph/pkg/config/defaults" identitymocks "github.com/owncloud/ocis/v2/services/graph/pkg/identity/mocks" service "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0" + "github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole" "github.com/stretchr/testify/mock" "google.golang.org/grpc" ) @@ -45,6 +47,8 @@ var _ = Describe("sharedbyme", func() { rr *httptest.ResponseRecorder ) expiration := time.Now() + + editorResourcePermissions := conversions.NewEditorRole(true).CS3ResourcePermissions() userShare := collaboration.Share{ Id: &collaboration.ShareId{ OpaqueId: "share-id", @@ -62,6 +66,9 @@ var _ = Describe("sharedbyme", func() { }, }, }, + Permissions: &collaboration.SharePermissions{ + Permissions: editorResourcePermissions, + }, } groupShare := collaboration.Share{ Id: &collaboration.ShareId{ @@ -80,6 +87,9 @@ var _ = Describe("sharedbyme", func() { }, }, }, + Permissions: &collaboration.SharePermissions{ + Permissions: editorResourcePermissions, + }, } userShareWithExpiration := collaboration.Share{ Id: &collaboration.ShareId{ @@ -98,6 +108,9 @@ var _ = Describe("sharedbyme", func() { }, }, }, + Permissions: &collaboration.SharePermissions{ + Permissions: editorResourcePermissions, + }, Expiration: utils.TimeToTS(expiration), } @@ -218,6 +231,7 @@ var _ = Describe("sharedbyme", func() { cfg.TokenManager.JWTSecret = "loremipsum" cfg.Commons = &shared.Commons{} cfg.GRPCClientTLS = &shared.GRPCClientTLS{} + cfg.FilesSharing.EnableResharing = true svc, _ = service.NewService( service.Config(cfg), @@ -323,6 +337,10 @@ var _ = Describe("sharedbyme", func() { Expect(user.GetId()).To(Equal(userShare.GetGrantee().GetUserId().GetOpaqueId())) _, ok = perm[0].GetLinkOk() Expect(ok).To(BeFalse()) + roles, ok := perm[0].GetRolesOk() + Expect(ok).To(BeTrue()) + Expect(len(roles)).To(Equal(1)) + Expect(roles[0]).To(Equal(unifiedrole.UnifiedRoleEditorID)) }) It("returns a proper driveItem, when a single group share is returned", func() { @@ -363,6 +381,10 @@ var _ = Describe("sharedbyme", func() { Expect(group.GetId()).To(Equal(groupShare.GetGrantee().GetGroupId().GetOpaqueId())) _, ok = perm[0].GetLinkOk() Expect(ok).To(BeFalse()) + roles, ok := perm[0].GetRolesOk() + Expect(ok).To(BeTrue()) + Expect(len(roles)).To(Equal(1)) + Expect(roles[0]).To(Equal(unifiedrole.UnifiedRoleEditorID)) }) It("returns a single driveItem, when a mulitple shares for the same resource are returned", func() { diff --git a/services/graph/pkg/unifiedrole/unifiedrole.go b/services/graph/pkg/unifiedrole/unifiedrole.go index ac69b9dde08..d1244750227 100644 --- a/services/graph/pkg/unifiedrole/unifiedrole.go +++ b/services/graph/pkg/unifiedrole/unifiedrole.go @@ -265,6 +265,50 @@ func CS3ResourcePermissionsToLibregraphActions(p provider.ResourcePermissions) ( return actions } +// CS3ResourcePermissionsToUnifiedRole tries to find the UnifiedRoleDefinition that matches the supplied +// CS3 ResourcePermissions and constraints. +func CS3ResourcePermissionsToUnifiedRole(p provider.ResourcePermissions, constraints string, resharing bool) *libregraph.UnifiedRoleDefinition { + actionSet := map[string]struct{}{} + for _, action := range CS3ResourcePermissionsToLibregraphActions(p) { + actionSet[action] = struct{}{} + } + + var res *libregraph.UnifiedRoleDefinition + for _, uRole := range GetBuiltinRoleDefinitionList(resharing) { + 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 diff --git a/services/graph/pkg/unifiedrole/unifiedrole_suite_test.go b/services/graph/pkg/unifiedrole/unifiedrole_suite_test.go new file mode 100644 index 00000000000..2e9a378086b --- /dev/null +++ b/services/graph/pkg/unifiedrole/unifiedrole_suite_test.go @@ -0,0 +1,13 @@ +package unifiedrole_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestUnifiedrole(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Unifiedrole Suite") +} diff --git a/services/graph/pkg/unifiedrole/unifiedrole_test.go b/services/graph/pkg/unifiedrole/unifiedrole_test.go new file mode 100644 index 00000000000..a29402b9d7c --- /dev/null +++ b/services/graph/pkg/unifiedrole/unifiedrole_test.go @@ -0,0 +1,26 @@ +package unifiedrole_test + +import ( + "github.com/cs3org/reva/v2/pkg/conversions" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + 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 *conversions.Role, unifiedRole *libregraph.UnifiedRoleDefinition) { + cs3perm := legacyRole.CS3ResourcePermissions() + + r := unifiedrole.CS3ResourcePermissionsToUnifiedRole(*cs3perm, unifiedrole.UnifiedRoleConditionGrantee, true) + Expect(r.GetId()).To(Equal(unifiedRole.GetId())) + + }, + Entry(conversions.RoleViewer, conversions.NewViewerRole(true), unifiedrole.NewViewerUnifiedRole(true)), + Entry(conversions.RoleEditor, conversions.NewEditorRole(true), unifiedrole.NewEditorUnifiedRole(true)), + Entry(conversions.RoleFileEditor, conversions.NewFileEditorRole(), unifiedrole.NewFileEditorUnifiedRole()), + Entry(conversions.RoleCoowner, conversions.NewCoownerRole(), unifiedrole.NewCoownerUnifiedRole()), + Entry(conversions.RoleManager, conversions.NewManagerRole(), unifiedrole.NewManagerUnifiedRole()), + ) +})