graph/sharedbyme: populate the permissions property

Set the exipration date, grantedToV2 and link attributes on the
permissions.

The displayName for users and groups isn't expanded yet (only the "id" is set)
Also, the "roles" attribute cannot be populated yet.
This commit is contained in:
Ralf Haferkamp
2023-10-18 16:32:45 +02:00
committed by Ralf Haferkamp
parent 454ec52955
commit 580a4e0d92
2 changed files with 201 additions and 23 deletions
+48 -1
View File
@@ -3,6 +3,8 @@ package svc
import (
"context"
"net/http"
"net/url"
"path"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
@@ -30,7 +32,7 @@ func (g Graph) GetSharedByMe(w http.ResponseWriter, r *http.Request) {
return
}
_, err = g.listPublicShares(ctx, driveItems)
driveItems, err = g.listPublicShares(ctx, driveItems)
if err != nil {
errorcode.RenderError(w, r, err)
return
@@ -116,6 +118,29 @@ func (g Graph) cs3UserSharesToDriveItems(ctx context.Context, shares []*collabor
}
item = *itemptr
}
perm := libregraph.Permission{}
perm.SetRoles([]string{})
perm.SetId(s.Id.OpaqueId)
grantedTo := libregraph.SharePointIdentitySet{}
switch s.Grantee.Type {
case storageprovider.GranteeType_GRANTEE_TYPE_USER:
user := libregraph.NewIdentityWithDefaults()
user.SetId(s.Grantee.GetUserId().GetOpaqueId())
grantedTo.SetUser(*user)
case storageprovider.GranteeType_GRANTEE_TYPE_GROUP:
grp := libregraph.NewIdentityWithDefaults()
grp.SetId(s.Grantee.GetGroupId().GetOpaqueId())
grantedTo.SetGroup(*grp)
}
// set expiration date
if s.GetExpiration() != nil {
perm.SetExpirationDateTime(cs3TimestampToTime(s.GetExpiration()))
}
perm.SetGrantedToV2(grantedTo)
item.Permissions = append(item.Permissions, perm)
driveItems[resIDStr] = item
}
return driveItems, nil
@@ -134,6 +159,28 @@ func (g Graph) cs3PublicSharesToDriveItems(ctx context.Context, shares []*link.P
}
item = *itemptr
}
perm := libregraph.Permission{}
perm.SetRoles([]string{})
perm.SetId(s.Id.OpaqueId)
link := libregraph.SharingLink{}
webURL, err := url.Parse(g.config.Spaces.WebDavBase)
if err != nil {
g.logger.Error().
Err(err).
Str("url", g.config.Spaces.WebDavBase).
Msg("failed to parse webURL base url")
return driveItems, err
}
webURL.Path = path.Join(webURL.Path, "s", s.GetToken())
link.SetWebUrl(webURL.String())
perm.SetLink(link)
// set expiration date
if s.GetExpiration() != nil {
perm.SetExpirationDateTime(cs3TimestampToTime(s.GetExpiration()))
}
item.Permissions = append(item.Permissions, perm)
driveItems[resIDStr] = item
}
+153 -22
View File
@@ -22,7 +22,6 @@ import (
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
libregraph "github.com/owncloud/libre-graph-api-go"
"github.com/owncloud/ocis/v2/ocis-pkg/shared"
"github.com/owncloud/ocis/v2/services/graph/mocks"
"github.com/owncloud/ocis/v2/services/graph/pkg/config"
@@ -44,9 +43,8 @@ var _ = Describe("sharedbyme", func() {
identityBackend *identitymocks.Backend
rr *httptest.ResponseRecorder
newGroup *libregraph.Group
)
expiration := time.Now()
userShare := collaboration.Share{
Id: &collaboration.ShareId{
OpaqueId: "share-id",
@@ -100,7 +98,19 @@ var _ = Describe("sharedbyme", func() {
},
},
},
Expiration: utils.TimeToTS(time.Now()),
Expiration: utils.TimeToTS(expiration),
}
publicShare := link.PublicShare{
Id: &link.PublicShareId{
OpaqueId: "public-share-id",
},
Token: "public-share-token",
ResourceId: &provider.ResourceId{
StorageId: "storageid",
SpaceId: "spaceid",
OpaqueId: "public-share-opaqueid",
},
}
BeforeEach(func() {
@@ -110,14 +120,6 @@ var _ = Describe("sharedbyme", func() {
pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway")
gatewayClient = &cs3mocks.GatewayAPIClient{}
gatewayClient.On("ListPublicShares", mock.Anything, mock.Anything).Return(
&link.ListPublicSharesResponse{
Status: status.NewOK(ctx),
Share: []*link.PublicShare{},
},
nil,
)
// no stat for the image
gatewayClient.On("Stat",
mock.Anything,
mock.MatchedBy(
@@ -130,6 +132,18 @@ var _ = Describe("sharedbyme", func() {
Id: userShareWithExpiration.ResourceId,
},
}, nil)
gatewayClient.On("Stat",
mock.Anything,
mock.MatchedBy(
func(req *provider.StatRequest) bool {
return req.Ref.ResourceId.OpaqueId == publicShare.ResourceId.OpaqueId
})).
Return(&provider.StatResponse{
Status: status.NewOK(ctx),
Info: &provider.ResourceInfo{
Id: publicShare.ResourceId,
},
}, nil)
gatewayClient.On("Stat",
mock.Anything,
mock.Anything).
@@ -148,9 +162,6 @@ var _ = Describe("sharedbyme", func() {
)
identityBackend = &identitymocks.Backend{}
newGroup = libregraph.NewGroup()
newGroup.SetMembersodataBind([]string{"/users/user1"})
newGroup.SetId("group1")
rr = httptest.NewRecorder()
ctx = context.Background()
@@ -169,8 +180,27 @@ var _ = Describe("sharedbyme", func() {
)
})
emptyListPublicSharesMock := func() {
gatewayClient.On("ListPublicShares", mock.Anything, mock.Anything).Return(
&link.ListPublicSharesResponse{
Status: status.NewOK(ctx),
Share: []*link.PublicShare{},
},
nil,
)
}
emptyListSharesMock := func() {
gatewayClient.On("ListShares", mock.Anything, mock.Anything).Return(
&collaboration.ListSharesResponse{
Status: status.NewOK(ctx),
Shares: []*collaboration.Share{},
},
nil,
)
}
Describe("GetSharedByMe", func() {
It("handles a failing ListShares", func() {
emptyListPublicSharesMock()
gatewayClient.On("ListShares", mock.Anything, mock.Anything).Return(nil, errors.New("some error"))
r := httptest.NewRequest(http.MethodGet, "/graph/v1.0/me/drives/sharedByMe", nil)
svc.GetSharedByMe(rr, r)
@@ -178,6 +208,7 @@ var _ = Describe("sharedbyme", func() {
})
It("handles ListShares returning an error status", func() {
emptyListPublicSharesMock()
gatewayClient.On("ListShares", mock.Anything, mock.Anything).Return(
&collaboration.ListSharesResponse{Status: status.NewInternal(ctx, "error listing shares")},
nil,
@@ -189,13 +220,8 @@ var _ = Describe("sharedbyme", func() {
})
It("succeeds, when no shares are returned", func() {
gatewayClient.On("ListShares", mock.Anything, mock.Anything).Return(
&collaboration.ListSharesResponse{
Status: status.NewOK(ctx),
Shares: []*collaboration.Share{},
},
nil,
)
emptyListPublicSharesMock()
emptyListSharesMock()
r := httptest.NewRequest(http.MethodGet, "/graph/v1.0/me/drives/sharedByMe", nil)
svc.GetSharedByMe(rr, r)
@@ -212,6 +238,7 @@ var _ = Describe("sharedbyme", func() {
})
It("returns a proper driveItem, when a single user share is returned", func() {
emptyListPublicSharesMock()
gatewayClient.On("ListShares", mock.Anything, mock.Anything).Return(
&collaboration.ListSharesResponse{
Status: status.NewOK(ctx),
@@ -237,9 +264,22 @@ var _ = Describe("sharedbyme", func() {
di := res.Value[0]
Expect(di.GetId()).To(Equal(storagespace.FormatResourceID(*userShare.GetResourceId())))
perm := di.GetPermissions()
Expect(perm[0].GetId()).To(Equal(userShare.GetId().GetOpaqueId()))
_, ok := perm[0].GetExpirationDateTimeOk()
Expect(ok).To(BeFalse())
_, ok = perm[0].GrantedToV2.GetGroupOk()
Expect(ok).To(BeFalse())
user, ok := perm[0].GrantedToV2.GetUserOk()
Expect(ok).To(BeTrue())
Expect(user.GetId()).To(Equal(userShare.GetGrantee().GetUserId().GetOpaqueId()))
_, ok = perm[0].GetLinkOk()
Expect(ok).To(BeFalse())
})
It("returns a proper driveItem, when a single group share is returned", func() {
emptyListPublicSharesMock()
gatewayClient.On("ListShares", mock.Anything, mock.Anything).Return(
&collaboration.ListSharesResponse{
Status: status.NewOK(ctx),
@@ -264,9 +304,22 @@ var _ = Describe("sharedbyme", func() {
di := res.Value[0]
Expect(di.GetId()).To(Equal(storagespace.FormatResourceID(*groupShare.GetResourceId())))
perm := di.GetPermissions()
Expect(perm[0].GetId()).To(Equal(userShare.GetId().GetOpaqueId()))
_, ok := perm[0].GetExpirationDateTimeOk()
Expect(ok).To(BeFalse())
_, ok = perm[0].GrantedToV2.GetUserOk()
Expect(ok).To(BeFalse())
group, ok := perm[0].GrantedToV2.GetGroupOk()
Expect(ok).To(BeTrue())
Expect(group.GetId()).To(Equal(groupShare.GetGrantee().GetGroupId().GetOpaqueId()))
_, ok = perm[0].GetLinkOk()
Expect(ok).To(BeFalse())
})
It("returns a single driveItem, when a mulitple shares for the same resource are returned", func() {
emptyListPublicSharesMock()
gatewayClient.On("ListShares", mock.Anything, mock.Anything).Return(
&collaboration.ListSharesResponse{
Status: status.NewOK(ctx),
@@ -292,9 +345,13 @@ var _ = Describe("sharedbyme", func() {
di := res.Value[0]
Expect(di.GetId()).To(Equal(storagespace.FormatResourceID(*groupShare.GetResourceId())))
// one permission per share
Expect(len(di.GetPermissions())).To(Equal(2))
})
It("return a driveItem with the expiration date set, for expiring shares", func() {
emptyListPublicSharesMock()
gatewayClient.On("ListShares", mock.Anything, mock.Anything).Return(
&collaboration.ListSharesResponse{
Status: status.NewOK(ctx),
@@ -319,6 +376,80 @@ var _ = Describe("sharedbyme", func() {
di := res.Value[0]
Expect(di.GetId()).To(Equal(storagespace.FormatResourceID(*userShareWithExpiration.GetResourceId())))
perm := di.GetPermissions()
Expect(perm[0].GetId()).To(Equal(userShareWithExpiration.GetId().GetOpaqueId()))
exp, ok := perm[0].GetExpirationDateTimeOk()
Expect(ok).To(BeTrue())
Expect(exp.Equal(expiration)).To(BeTrue())
_, ok = perm[0].GrantedToV2.GetGroupOk()
Expect(ok).To(BeFalse())
user, ok := perm[0].GrantedToV2.GetUserOk()
Expect(ok).To(BeTrue())
Expect(user.GetId()).To(Equal(userShareWithExpiration.GetGrantee().GetUserId().GetOpaqueId()))
_, ok = perm[0].GetLinkOk()
Expect(ok).To(BeFalse())
})
// Public Shares / "links" in graph terms
It("handles a failing ListPublicShares", func() {
gatewayClient.On("ListPublicShares", mock.Anything, mock.Anything).Return(nil, errors.New("some error"))
emptyListSharesMock()
r := httptest.NewRequest(http.MethodGet, "/graph/v1.0/me/drives/sharedByMe", nil)
svc.GetSharedByMe(rr, r)
Expect(rr.Code).To(Equal(http.StatusInternalServerError))
})
It("handles ListPublicShares returning an error status", func() {
emptyListSharesMock()
gatewayClient.On("ListPublicShares", mock.Anything, mock.Anything).Return(
&link.ListPublicSharesResponse{Status: status.NewInternal(ctx, "error listing shares")},
nil,
)
r := httptest.NewRequest(http.MethodGet, "/graph/v1.0/me/drives/sharedByMe", nil)
svc.GetSharedByMe(rr, r)
Expect(rr.Code).To(Equal(http.StatusInternalServerError))
})
It("returns a proper driveItem, when a single public share is returned", func() {
emptyListSharesMock()
gatewayClient.On("ListPublicShares", mock.Anything, mock.Anything).Return(
&link.ListPublicSharesResponse{
Status: status.NewOK(ctx),
Share: []*link.PublicShare{
&publicShare,
},
},
nil,
)
r := httptest.NewRequest(http.MethodGet, "/graph/v1.0/me/drives/sharedByMe", nil)
svc.GetSharedByMe(rr, r)
Expect(rr.Code).To(Equal(http.StatusOK))
data, err := io.ReadAll(rr.Body)
Expect(err).ToNot(HaveOccurred())
res := itemsList{}
err = json.Unmarshal(data, &res)
Expect(err).ToNot(HaveOccurred())
Expect(len(res.Value)).To(Equal(1))
di := res.Value[0]
Expect(di.GetId()).To(Equal(storagespace.FormatResourceID(*publicShare.GetResourceId())))
perm := di.GetPermissions()
Expect(perm[0].GetId()).To(Equal(publicShare.GetId().GetOpaqueId()))
_, ok := perm[0].GetExpirationDateTimeOk()
Expect(ok).To(BeFalse())
_, ok = perm[0].GetGrantedToV2Ok()
Expect(ok).To(BeFalse())
link, ok := perm[0].GetLinkOk()
Expect(ok).To(BeTrue())
Expect(link.GetWebUrl()).To(Equal("https://localhost:9200/s/" + publicShare.GetToken()))
})
})
})