From cf5f1bcb8ebec2ab235c9bdf1c671c6c7ed28bce Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Tue, 19 Dec 2023 13:51:20 +0100 Subject: [PATCH] fix: share jail usage for the listSharedWithMe endpoint --- services/graph/pkg/service/v0/sharedwithme.go | 300 +++++++++++------- 1 file changed, 184 insertions(+), 116 deletions(-) diff --git a/services/graph/pkg/service/v0/sharedwithme.go b/services/graph/pkg/service/v0/sharedwithme.go index 56457e3a71..04e559c6d3 100644 --- a/services/graph/pkg/service/v0/sharedwithme.go +++ b/services/graph/pkg/service/v0/sharedwithme.go @@ -3,17 +3,19 @@ package svc import ( "context" "net/http" + "reflect" "strings" - rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/go-chi/render" libregraph "github.com/owncloud/libre-graph-api-go" + "github.com/cs3org/reva/v2/pkg/storagespace" + "github.com/cs3org/reva/v2/pkg/utils" + "github.com/owncloud/ocis/v2/ocis-pkg/conversions" "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" ) // ListSharedWithMe lists the files shared with the current user. @@ -38,185 +40,251 @@ func (g Graph) listSharedWithMe(ctx context.Context) ([]libregraph.DriveItem, er } listReceivedSharesResponse, err := gatewayClient.ListReceivedShares(ctx, &collaboration.ListReceivedSharesRequest{}) - if err != nil { + if errCode := errorcode.FromCS3Status(listReceivedSharesResponse.GetStatus(), err); errCode != nil { g.logger.Error().Err(err).Msg("listing shares failed") - return nil, errorcode.New(errorcode.GeneralException, err.Error()) - } - - switch listReceivedSharesResponse.Status.Code { - case rpc.Code_CODE_NOT_FOUND: - return nil, identity.ErrNotFound + return nil, *errCode } var driveItems []libregraph.DriveItem for _, receivedShare := range listReceivedSharesResponse.GetShares() { - share := receivedShare.GetShare() - if share == nil { - g.logger.Error().Interface("ListReceivedShares", listReceivedSharesResponse).Msg("unexpected empty ReceivedShare.Share") + statRequest := &storageprovider.StatRequest{} + + switch receivedShare.GetState() { + case collaboration.ShareState_SHARE_STATE_ACCEPTED: + statRequest.Ref = &storageprovider.Reference{ + ResourceId: &storageprovider.ResourceId{ + StorageId: utils.ShareStorageProviderID, + OpaqueId: receivedShare.GetShare().GetId().GetOpaqueId(), + SpaceId: utils.ShareStorageSpaceID, + }, + } + case collaboration.ShareState_SHARE_STATE_PENDING: + // return no remoteItem + fallthrough + case collaboration.ShareState_SHARE_STATE_REJECTED: + // what to return here? same as pending? + statRequest.Ref = &storageprovider.Reference{ + ResourceId: receivedShare.GetShare().GetResourceId(), + } + default: continue } - driveItem := &libregraph.DriveItem{} - - statResponse, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: share.GetResourceId()}}) - if err != nil { + statResponse, err := gatewayClient.Stat(ctx, statRequest) + if errCode := errorcode.FromCS3Status(statResponse.GetStatus(), err); errCode != nil { g.logger.Error().Err(err).Msg("could not stat") continue } - if statResponse.GetStatus().GetCode() != rpc.Code_CODE_OK { - g.logger.Error().Err(err).Msg("invalid stat response") - continue - } - resourceInfo := statResponse.GetInfo() - var driveOwner *libregraph.Identity + var commonResourceOwner *libregraph.Identity if userID := statResponse.GetInfo().GetOwner(); userID != nil { if user, err := g.identityCache.GetUser(ctx, userID.GetOpaqueId()); err != nil { g.logger.Error().Err(err).Msg("could not get user") continue } else { - driveOwner = &libregraph.Identity{ + commonResourceOwner = &libregraph.Identity{ DisplayName: user.GetDisplayName(), Id: libregraph.PtrString(user.GetId()), } } } - var shareCreator *libregraph.Identity - if userID := share.GetCreator(); userID != nil { + var commonShareCreator *libregraph.Identity + if userID := receivedShare.GetShare().GetCreator(); userID != nil { if user, err := g.identityCache.GetUser(ctx, userID.GetOpaqueId()); err != nil { g.logger.Error().Err(err).Msg("could not get user") continue } else { - shareCreator = &libregraph.Identity{ + commonShareCreator = &libregraph.Identity{ DisplayName: user.GetDisplayName(), Id: libregraph.PtrString(user.GetId()), } } } - if cTime := share.GetCtime(); cTime != nil { - driveItem.CreatedDateTime = libregraph.PtrTime(cs3TimestampToTime(cTime)) - } - - driveItem.ETag = libregraph.PtrString(strings.Trim(statResponse.GetInfo().GetEtag(), "\"")) - - if id := share.GetId().GetOpaqueId(); id != "" { - driveItem.Id = libregraph.PtrString(id) - } - - if mTime := share.GetMtime(); mTime != nil { - driveItem.LastModifiedDateTime = libregraph.PtrTime(cs3TimestampToTime(mTime)) - } - - if name := resourceInfo.GetName(); name != "" { - driveItem.Name = libregraph.PtrString(name) - } - + var commonPermission *libregraph.Permission { - addParentReference := false - parentReference := &libregraph.ItemReference{} + permission := libregraph.NewPermission() - if id := share.GetId().GetOpaqueId(); id != "" { - parentReference.DriveId = libregraph.PtrString(id) - addParentReference = true + if id := receivedShare.GetShare().GetId().GetOpaqueId(); id != "" { + permission.SetId(id) } - if addParentReference { - driveItem.ParentReference = parentReference + if permissionSet := statResponse.GetInfo().GetPermissionSet(); permissionSet != nil { + if actions := unifiedrole.CS3ResourcePermissionsToLibregraphActions(*permissionSet); len(actions) > 0 { + permission.SetLibreGraphPermissionsActions(actions) + } + + if role := unifiedrole.CS3ResourcePermissionsToUnifiedRole( + *permissionSet, + unifiedrole.UnifiedRoleConditionGrantee, + g.config.FilesSharing.EnableResharing, + ); role != nil { + permission.SetRoles([]string{role.GetId()}) + } + } + + if expiration := receivedShare.GetShare().GetExpiration(); expiration != nil { + permission.SetExpirationDateTime(cs3TimestampToTime(expiration)) + } + + switch grantee := receivedShare.GetShare().GetGrantee(); { + case grantee.GetType() == storageprovider.GranteeType_GRANTEE_TYPE_USER: + permission.SetGrantedToV2(libregraph.SharePointIdentitySet{ + User: &libregraph.Identity{ + Id: conversions.ToPointer(grantee.GetUserId().GetOpaqueId()), + }, + }) + case grantee.GetType() == storageprovider.GranteeType_GRANTEE_TYPE_GROUP: + permission.SetGrantedToV2(libregraph.SharePointIdentitySet{ + Group: &libregraph.Identity{ + Id: conversions.ToPointer(grantee.GetGroupId().GetOpaqueId()), + }, + }) + } + + if !reflect.ValueOf(*permission).IsZero() { + commonPermission = permission } } + driveItem := libregraph.NewDriveItem() { - remoteItem := &libregraph.RemoteItem{} - - if id := resourceInfo.GetId(); id != nil { - remoteItem.Id = libregraph.PtrString(storagespace.FormatResourceID(*id)) - } - - if mTime := resourceInfo.GetMtime(); mTime != nil { - remoteItem.LastModifiedDateTime = libregraph.PtrTime(cs3TimestampToTime(mTime)) - } - - if name := resourceInfo.GetName(); name != "" { - remoteItem.Name = libregraph.PtrString(name) - } - - // fixMe: - // - negative permission could distort the size, am i right? - remoteItem.Size = libregraph.PtrInt64(int64(resourceInfo.GetSize())) - - remoteItem.CreatedBy = &libregraph.IdentitySet{ - User: driveOwner, + if commonShareCreator != nil { + driveItem.SetCreatedBy(libregraph.IdentitySet{ + User: commonShareCreator, + }) } { + parentReference := libregraph.NewItemReference() - addFileSystemInfo := false - fileSystemInfo := &libregraph.FileSystemInfo{} - - if cTime := share.GetCtime(); cTime != nil { - // fixMe: - // - ms uses the root resource ctime for that, - // the stat response does not contain any information about this, use share instead? - fileSystemInfo.CreatedDateTime = libregraph.PtrTime(cs3TimestampToTime(cTime)) - addFileSystemInfo = true + if spaceType := statResponse.GetInfo().GetSpace().GetSpaceType(); spaceType != "" { + parentReference.SetDriveType(spaceType) } - if mTime := resourceInfo.GetMtime(); mTime != nil { - fileSystemInfo.LastModifiedDateTime = libregraph.PtrTime(cs3TimestampToTime(mTime)) - addFileSystemInfo = true + if root := statResponse.GetInfo().GetSpace().GetRoot(); root != nil { + parentReference.SetDriveId(storagespace.FormatResourceID(*root)) } - if addFileSystemInfo { - remoteItem.FileSystemInfo = fileSystemInfo + if !reflect.ValueOf(*parentReference).IsZero() { + driveItem.ParentReference = parentReference } } + } - switch resourceInfo.GetType() { - case storageprovider.ResourceType_RESOURCE_TYPE_CONTAINER: - remoteItem.Folder = &libregraph.Folder{} - case storageprovider.ResourceType_RESOURCE_TYPE_FILE: - openGraphFile := &libregraph.OpenGraphFile{} + switch receivedShare.GetState() { + case collaboration.ShareState_SHARE_STATE_ACCEPTED: + if resourceID := statRequest.GetRef().GetResourceId(); resourceID != nil { + driveItem.SetId(storagespace.FormatResourceID(*resourceID)) + } - if mimeType := resourceInfo.GetMimeType(); mimeType != "" { - openGraphFile.MimeType = libregraph.PtrString(mimeType) - } + if name := receivedShare.GetMountPoint().GetPath(); name != "" { + driveItem.SetName(receivedShare.GetMountPoint().GetPath()) + } - remoteItem.File = openGraphFile - case storageprovider.ResourceType_RESOURCE_TYPE_INVALID: - g.logger.Error().Msg("invalid resource type") - continue + if mTime := receivedShare.GetShare().GetMtime(); mTime != nil { + driveItem.SetLastModifiedDateTime(cs3TimestampToTime(mTime)) + } + + if cTime := receivedShare.GetShare().GetCtime(); cTime != nil { + driveItem.SetCreatedDateTime(cs3TimestampToTime(cTime)) } { - addShared := false - shared := &libregraph.Shared{ - Owner: &libregraph.IdentitySet{ - User: shareCreator, - }, - SharedBy: &libregraph.IdentitySet{ - User: shareCreator, - }, + remoteItem := libregraph.NewRemoteItem() + + if id := statResponse.GetInfo().GetId(); id != nil { + remoteItem.SetId(storagespace.FormatResourceID(*id)) } - if cTime := share.GetCtime(); cTime != nil { - shared.SharedDateTime = libregraph.PtrTime(cs3TimestampToTime(cTime)) - addShared = true + if mTime := statResponse.GetInfo().GetMtime(); mTime != nil { + remoteItem.SetLastModifiedDateTime(cs3TimestampToTime(mTime)) } - if shareCreator != nil { - shared.Owner.User = shareCreator - shared.SharedBy.User = shareCreator - addShared = true + if name := statResponse.GetInfo().GetName(); name != "" { + remoteItem.SetName(name) } - if addShared { - remoteItem.Shared = shared + if size := statResponse.GetInfo().GetSize(); size != 0 { + remoteItem.SetSize(int64(size)) + } + + if etag := statResponse.GetInfo().GetEtag(); etag != "" { + remoteItem.SetETag(strings.Trim(etag, "\"")) + } + + if commonResourceOwner != nil { + remoteItem.SetCreatedBy(libregraph.IdentitySet{ + User: commonResourceOwner, + }) + } + + switch info := statResponse.GetInfo(); { + case info.GetType() == storageprovider.ResourceType_RESOURCE_TYPE_CONTAINER: + remoteItem.Folder = libregraph.NewFolder() + case info.GetType() == storageprovider.ResourceType_RESOURCE_TYPE_FILE: + openGraphFile := libregraph.NewOpenGraphFile() + + if mimeType := info.GetMimeType(); mimeType != "" { + openGraphFile.MimeType = &mimeType + } + + remoteItem.File = openGraphFile + case info.GetType() == storageprovider.ResourceType_RESOURCE_TYPE_INVALID: + g.logger.Info().Interface("info", info).Msg("invalid resource type") + } + + if commonPermission != nil { + remoteItem.SetPermissions([]libregraph.Permission{*commonPermission}) + } + + { + shared := libregraph.NewShared() + + if cTime := receivedShare.GetShare().GetCtime(); cTime != nil { + shared.SetSharedDateTime(cs3TimestampToTime(cTime)) + } + + if commonResourceOwner != nil { + shared.SetOwner(libregraph.IdentitySet{ + User: commonResourceOwner, + }) + } + + if commonShareCreator != nil { + shared.SetSharedBy(libregraph.IdentitySet{ + User: commonShareCreator, + }) + } + + if !reflect.ValueOf(*shared).IsZero() { + remoteItem.SetShared(*shared) + } + } + + if !reflect.ValueOf(*remoteItem).IsZero() { + driveItem.SetRemoteItem(*remoteItem) } } + case collaboration.ShareState_SHARE_STATE_PENDING: + fallthrough + case collaboration.ShareState_SHARE_STATE_REJECTED: + if id := statResponse.GetInfo().GetId(); id != nil { + driveItem.SetId(storagespace.FormatResourceID(*id)) + } - driveItem.RemoteItem = remoteItem + if name := statResponse.GetInfo().GetName(); name != "" { + driveItem.SetName(name) + } + + if mTime := statResponse.GetInfo().GetMtime(); mTime != nil { + driveItem.SetLastModifiedDateTime(cs3TimestampToTime(mTime)) + } + + if commonPermission != nil { + driveItem.SetPermissions([]libregraph.Permission{*commonPermission}) + } } driveItems = append(driveItems, *driveItem)