diff --git a/changelog/unreleased/sharing-ng-spacepermissions.md b/changelog/unreleased/sharing-ng-spacepermissions.md new file mode 100644 index 000000000..e703decea --- /dev/null +++ b/changelog/unreleased/sharing-ng-spacepermissions.md @@ -0,0 +1,7 @@ +Enhancement: The graph endpoints for listing permission works for spaces now + +We enhanced the 'graph/v1beta1/drives/{{driveid}}/items/{{itemid}}/permissions' endpoint +to list permission of the space when the 'itemid' refers to a space root. + +https://github.com/owncloud/ocis/pull/8642 +https://github.com/owncloud/ocis/issues/8352 diff --git a/services/graph/pkg/service/v0/driveitems_test.go b/services/graph/pkg/service/v0/driveitems_test.go index 46aca87a0..534f233d5 100644 --- a/services/graph/pkg/service/v0/driveitems_test.go +++ b/services/graph/pkg/service/v0/driveitems_test.go @@ -17,6 +17,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" + types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/go-chi/chi/v5" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -1156,6 +1157,7 @@ var _ = Describe("Driveitems", func() { listSharesResponse *collaboration.ListSharesResponse listPublicSharesMock *mock.Call listPublicSharesResponse *link.ListPublicSharesResponse + rctx *chi.Context ) toResourceID := func(in string) *provider.ResourceId { @@ -1166,10 +1168,7 @@ var _ = Describe("Driveitems", func() { } BeforeEach(func() { - rctx := chi.NewRouteContext() - rctx.URLParams.Add("driveID", "1$2") - rctx.URLParams.Add("itemID", "1$2!3") - + rctx = chi.NewRouteContext() ctx = context.WithValue(ctx, chi.RouteCtxKey, rctx) ctx = revactx.ContextSetUser(ctx, currentUser) @@ -1210,6 +1209,9 @@ var _ = Describe("Driveitems", func() { }) It("lists permissions", func() { + rctx.URLParams.Add("driveID", "1$2") + rctx.URLParams.Add("itemID", "1$2!3") + svc.ListPermissions( rr, httptest.NewRequest(http.MethodGet, "/", nil). @@ -1230,6 +1232,62 @@ var _ = Describe("Driveitems", func() { Expect(value.Get("#").Num).To(Equal(float64(1))) Expect(value.Get("0.id").Str).To(Equal("123")) }) + It("lists permissions on a storage space", func() { + rctx.URLParams.Add("driveID", "1$2") + rctx.URLParams.Add("itemID", "1$2!2") + statResponse.Info.Id.OpaqueId = "2" + grantMap := map[string]*provider.ResourcePermissions{ + "userid": roleconversions.NewSpaceViewerRole().CS3ResourcePermissions(), + } + grantMapJSON, _ := json.Marshal(grantMap) + spaceOpaque := &types.Opaque{ + Map: map[string]*types.OpaqueEntry{ + "grants": { + Decoder: "json", + Value: grantMapJSON, + }, + }, + } + + listSpacesMock := gatewayClient.On("ListStorageSpaces", mock.Anything, mock.Anything) + listSpacesResponse := &provider.ListStorageSpacesResponse{ + Status: status.NewOK(ctx), + StorageSpaces: []*provider.StorageSpace{ + { + Id: &provider.StorageSpaceId{ + OpaqueId: "2", + }, + Opaque: spaceOpaque, + }, + }, + } + listSpacesMock.Return(listSpacesResponse, nil) + + getUserMock := gatewayClient.On("GetUser", mock.Anything, mock.Anything) + getUserMockResponse := &userpb.GetUserResponse{ + Status: status.NewOK(ctx), + User: &userpb.User{ + Id: &userpb.UserId{OpaqueId: "userid"}, + DisplayName: "Test User", + }, + } + getUserMock.Return(getUserMockResponse, nil) + + svc.ListPermissions( + rr, + httptest.NewRequest(http.MethodGet, "/", nil). + WithContext(ctx), + ) + + Expect(rr.Code).To(Equal(http.StatusOK)) + p := libregraph.NewCollectionOfPermissions() + err := json.Unmarshal(rr.Body.Bytes(), p) + Expect(err).To(BeNil()) + permissions := p.GetValue() + Expect(len(permissions)).To(Equal(1)) + Expect(permissions[0].GetId()).ToNot(Equal("")) + }) + }) Describe("GetRootDriveChildren", func() { diff --git a/services/graph/pkg/service/v0/drives.go b/services/graph/pkg/service/v0/drives.go index 682540855..e4f0df839 100644 --- a/services/graph/pkg/service/v0/drives.go +++ b/services/graph/pkg/service/v0/drives.go @@ -916,6 +916,7 @@ func (g Graph) cs3PermissionsToLibreGraph(ctx context.Context, space *storagepro } else { identitySet.SetUser(identity) } + p.SetId(identitySetToSpacePermissionID(identitySet)) p.SetGrantedToV2(identitySet) } diff --git a/services/graph/pkg/service/v0/utils.go b/services/graph/pkg/service/v0/utils.go index 270db47e3..8618f1602 100644 --- a/services/graph/pkg/service/v0/utils.go +++ b/services/graph/pkg/service/v0/utils.go @@ -131,6 +131,21 @@ func groupIdToIdentity(ctx context.Context, cache identity.IdentityCache, groupI return identity, err } +// identitySetToSpacePermissionID generates an Id for a permission from an identitySet. In libregraph +// permissions need to have an id. For user share permission we just use the cs3 share id as the permission-id +// As permissions on space to not map to a cs3 share we need something else of the ids. So we just +// construct the id for the id of the user or group that the permission applies to and prefix that +// with a "u:" for userids and "g:" for group ids. +func identitySetToSpacePermissionID(identitySet libregraph.SharePointIdentitySet) (id string) { + switch { + case identitySet.HasUser(): + id = "u:" + identitySet.User.GetId() + case identitySet.HasGroup(): + id = "g:" + identitySet.Group.GetId() + } + return id +} + func cs3ReceivedSharesToDriveItems(ctx context.Context, logger *log.Logger, gatewayClient gateway.GatewayAPIClient,