diff --git a/go.mod b/go.mod index 40c460bc9df..e3c7f49fd3b 100644 --- a/go.mod +++ b/go.mod @@ -275,3 +275,5 @@ require ( // we need to use a fork to make the windows build pass replace github.com/pkg/xattr => github.com/micbar/xattr v0.4.6-0.20220215112335-88e74d648fb7 + +replace github.com/cs3org/reva/v2 => github.com/micbar/reva/v2 v2.0.0-20220322143902-b52b81bc4840 diff --git a/go.sum b/go.sum index eac537abe07..c94fbe400df 100644 --- a/go.sum +++ b/go.sum @@ -335,8 +335,6 @@ github.com/crewjam/saml v0.4.6/go.mod h1:ZBOXnNPFzB3CgOkRm7Nd6IVdkG+l/wF+0ZXLqD9 github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4= github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19 h1:1jqPH58jCxvbaJ9WLIJ7W2/m622bWS6ChptzljSG6IQ= github.com/cs3org/go-cs3apis v0.0.0-20220126114148-64c025ccdd19/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva/v2 v2.0.0-20220321093112-25cedab9f739 h1:GD8ZoMqRKclM0dP5hjSMXals9vRWHPH2hOeBruCuQlg= -github.com/cs3org/reva/v2 v2.0.0-20220321093112-25cedab9f739/go.mod h1:XNtK1HEClNzmz5vyQa2DUw4KH3oqBjQoEsV1LhAGlV0= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= @@ -996,6 +994,8 @@ github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103 h1:Z/i1e+gTZrmcGeZy github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103/go.mod h1:o9YPB5aGP8ob35Vy6+vyq3P3bWe7NQWzf+JLiXCiMaE= github.com/mennanov/fieldmask-utils v0.5.0 h1:8em4akN0NM3hmmrg8VbvOPfdS4SSBdbFd53m9VtfOg0= github.com/mennanov/fieldmask-utils v0.5.0/go.mod h1:lah2lHczE2ff+7SqnNKpB+YzaO7M3h5iNO4LgPTJheM= +github.com/micbar/reva/v2 v2.0.0-20220322143902-b52b81bc4840 h1:+ZEf/GSUzb4Fp428/+HQ3OnCwultdRdwwG8iJPsVscc= +github.com/micbar/reva/v2 v2.0.0-20220322143902-b52b81bc4840/go.mod h1:XNtK1HEClNzmz5vyQa2DUw4KH3oqBjQoEsV1LhAGlV0= github.com/micbar/xattr v0.4.6-0.20220215112335-88e74d648fb7 h1:M0R40eUlyqxMuZn3Knx4DJTwHE3TiPFzcWUA/BKtDMM= github.com/micbar/xattr v0.4.6-0.20220215112335-88e74d648fb7/go.mod h1:sBD3RAqlr8Q+RC3FutZcikpT8nyDrIEEBw2J744gVWs= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= diff --git a/graph/pkg/service/v0/driveitems.go b/graph/pkg/service/v0/driveitems.go index a5eb21a65f9..699cf7f2fa9 100644 --- a/graph/pkg/service/v0/driveitems.go +++ b/graph/pkg/service/v0/driveitems.go @@ -92,6 +92,28 @@ func (g Graph) getDriveItem(ctx context.Context, root *storageprovider.ResourceI return cs3ResourceToDriveItem(res.Info) } +func (g Graph) getRemoteItem(ctx context.Context, root *storageprovider.ResourceId, baseURL *url.URL) (*libregraph.RemoteItem, error) { + client := g.GetGatewayClient() + + ref := &storageprovider.Reference{ + ResourceId: root, + } + res, err := client.Stat(ctx, &storageprovider.StatRequest{Ref: ref}) + if err != nil { + return nil, err + } + if res.Status.Code != cs3rpc.Code_CODE_OK { + return nil, fmt.Errorf("could not stat %s: %s", ref, res.Status.Message) + } + item, err := cs3ResourceToRemoteItem(res.Info) + if err != nil { + return nil, err + } + + item.WebDavUrl = libregraph.PtrString(path.Join(baseURL.String(), resourceid.OwnCloudResourceIDWrap(root))) + return item, nil +} + func formatDriveItems(mds []*storageprovider.ResourceInfo) ([]*libregraph.DriveItem, error) { responses := make([]*libregraph.DriveItem, 0, len(mds)) for i := range mds { @@ -140,7 +162,38 @@ func cs3ResourceToDriveItem(res *storageprovider.ResourceInfo) (*libregraph.Driv return driveItem, nil } -func (g Graph) getPathForDriveItem(ctx context.Context, ID *storageprovider.ResourceId) (*string, error) { +func cs3ResourceToRemoteItem(res *storageprovider.ResourceInfo) (*libregraph.RemoteItem, error) { + size := new(int64) + *size = int64(res.Size) // TODO lurking overflow: make size of libregraph drive item use uint64 + + remoteItem := &libregraph.RemoteItem{ + Id: libregraph.PtrString(resourceid.OwnCloudResourceIDWrap(res.Id)), + Size: size, + } + + if name := path.Base(res.Path); name != "" { + remoteItem.Name = &name + } + if res.Etag != "" { + //remoteItem.ETag = &res.Etag + } + if res.Mtime != nil { + lastModified := cs3TimestampToTime(res.Mtime) + remoteItem.LastModifiedDateTime = &lastModified + } + if res.Type == storageprovider.ResourceType_RESOURCE_TYPE_FILE && res.MimeType != "" { + // We cannot use a libregraph.File here because the openapi codegenerator autodetects 'File' as a go type ... + remoteItem.File = &libregraph.OpenGraphFile{ + MimeType: &res.MimeType, + } + } + if res.Type == storageprovider.ResourceType_RESOURCE_TYPE_CONTAINER { + remoteItem.Folder = &libregraph.Folder{} + } + return remoteItem, nil +} + +func (g Graph) getPathForResource(ctx context.Context, ID *storageprovider.ResourceId) (*string, error) { client := g.GetGatewayClient() var path *string res, err := client.GetPath(ctx, &storageprovider.GetPathRequest{ResourceId: ID}) @@ -185,13 +238,13 @@ func (g Graph) getSpecialDriveItem(ctx context.Context, ID *storageprovider.Reso g.logger.Error().Err(err).Str("ID", ID.OpaqueId).Msg("Could not get readme Item") return nil } - itemPath, err := g.getPathForDriveItem(ctx, ID) + itemPath, err := g.getPathForResource(ctx, ID) if err != nil { g.logger.Error().Err(err).Str("ID", ID.OpaqueId).Msg("Could not get readme path") return nil } spaceItem.SpecialFolder = &libregraph.SpecialFolder{Name: libregraph.PtrString(itemName)} - spaceItem.WebDavUrl = libregraph.PtrString(baseURL.String() + path.Join(space.Root.OpaqueId, *itemPath)) + spaceItem.WebDavUrl = libregraph.PtrString(baseURL.String() + path.Join(space.Root.StorageId, *itemPath)) return spaceItem } diff --git a/graph/pkg/service/v0/drives.go b/graph/pkg/service/v0/drives.go index a82f284223c..21be0f2f140 100644 --- a/graph/pkg/service/v0/drives.go +++ b/graph/pkg/service/v0/drives.go @@ -240,7 +240,7 @@ func (g Graph) CreateDrive(w http.ResponseWriter, r *http.Request) { return } - newDrive, err := g.cs3StorageSpaceToDrive(wdu, resp.StorageSpace) + newDrive, err := g.cs3StorageSpaceToDrive(r.Context(), wdu, resp.StorageSpace) if err != nil { g.logger.Error().Err(err).Msg("error parsing space") errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) @@ -382,12 +382,15 @@ func (g Graph) UpdateDrive(w http.ResponseWriter, r *http.Request) { func (g Graph) formatDrives(ctx context.Context, baseURL *url.URL, storageSpaces []*storageprovider.StorageSpace) ([]*libregraph.Drive, error) { responses := make([]*libregraph.Drive, 0, len(storageSpaces)) for _, storageSpace := range storageSpaces { - res, err := g.cs3StorageSpaceToDrive(baseURL, storageSpace) + res, err := g.cs3StorageSpaceToDrive(ctx, baseURL, storageSpace) if err != nil { return nil, err } res.Special = g.GetExtendedSpaceProperties(ctx, baseURL, storageSpace) res.Quota, err = g.getDriveQuota(ctx, storageSpace) + if res.Root.RemoteItem != nil { + res.Root.RemoteItem, err = g.getRemoteItem(ctx, resourceid.OwnCloudResourceIDUnwrap(*res.Root.RemoteItem.Id), baseURL) + } if err != nil { return nil, err } @@ -429,7 +432,7 @@ func (g Graph) ListStorageSpacesWithFilters(ctx context.Context, filters []*stor return res, err } -func (g Graph) cs3StorageSpaceToDrive(baseURL *url.URL, space *storageprovider.StorageSpace) (*libregraph.Drive, error) { +func (g Graph) cs3StorageSpaceToDrive(ctx context.Context, baseURL *url.URL, space *storageprovider.StorageSpace) (*libregraph.Drive, error) { if space.Root == nil { return nil, fmt.Errorf("space has no root") } @@ -491,8 +494,12 @@ func (g Graph) cs3StorageSpaceToDrive(baseURL *url.URL, space *storageprovider.S } } + spaceID := space.Root.StorageId + if space.Root.OpaqueId != space.Root.StorageId { + spaceID = rootID + } drive := &libregraph.Drive{ - Id: &space.Root.StorageId, + Id: &spaceID, Name: &space.Name, //"createdDateTime": "string (timestamp)", // TODO read from StorageSpace ... needs Opaque for now //"description": "string", // TODO read from StorageSpace ... needs Opaque for now @@ -502,6 +509,18 @@ func (g Graph) cs3StorageSpaceToDrive(baseURL *url.URL, space *storageprovider.S Permissions: permissions, }, } + if space.SpaceType == "mountpoint" { + grantID := storageprovider.ResourceId{ + StorageId: utils.ReadPlainFromOpaque(space.Opaque, "grantStorageID"), + OpaqueId: utils.ReadPlainFromOpaque(space.Opaque, "grantOpaqueID"), + } + if grantID.StorageId != "" && grantID.OpaqueId != "" { + drive.Root.RemoteItem = &libregraph.RemoteItem{ + Id: libregraph.PtrString(resourceid.OwnCloudResourceIDWrap(&grantID)), + } + } + } + if space.Opaque != nil { if description, ok := space.Opaque.Map["description"]; ok { drive.Description = libregraph.PtrString(string(description.Value)) @@ -526,7 +545,7 @@ func (g Graph) cs3StorageSpaceToDrive(baseURL *url.URL, space *storageprovider.S // TODO read from StorageSpace ... needs Opaque for now // TODO how do we build the url? // for now: read from request - webDavURL := baseURL.String() + space.Root.StorageId + webDavURL := baseURL.String() + spaceID drive.Root.WebDavUrl = &webDavURL }