From a2f618b4c9bf1d1ee21d54cdf9b02097b520b0dc Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Tue, 15 Mar 2022 17:26:34 +0100 Subject: [PATCH] add remote item and fix mountpoint --- go.mod | 4 +- go.sum | 8 ++-- graph/pkg/service/v0/driveitems.go | 61 ++++++++++++++++++++++++++++-- graph/pkg/service/v0/drives.go | 32 +++++++++++++--- graph/pkg/service/v0/graph_test.go | 36 +++++++++--------- 5 files changed, 110 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index 3191b4b5101..8b752547041 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.18.1 - github.com/owncloud/libre-graph-api-go v0.13.1 + github.com/owncloud/libre-graph-api-go v0.13.2 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.12.1 github.com/rs/zerolog v1.26.1 @@ -272,3 +272,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-20220325152342-12eabed07d4b diff --git a/go.sum b/go.sum index af6cdc79d02..123aec3b1e9 100644 --- a/go.sum +++ b/go.sum @@ -338,8 +338,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-20220324071614-82800d7ef768 h1:9QNIi4oyHyv1ua8oPyeBdLcMU6hKDyNmGuSxWmf01BM= -github.com/cs3org/reva/v2 v2.0.0-20220324071614-82800d7ef768/go.mod h1:kFqm3iwrRHyEnP606H+wSWmJzjk0nj2kPShsowriqxg= 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= @@ -990,6 +988,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-20220325152342-12eabed07d4b h1:5oWofosj7SRMGSjGdMgaIc4ASyYtvct2XZH6Hfyeh2A= +github.com/micbar/reva/v2 v2.0.0-20220325152342-12eabed07d4b/go.mod h1:kFqm3iwrRHyEnP606H+wSWmJzjk0nj2kPShsowriqxg= 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= @@ -1133,8 +1133,8 @@ github.com/orcaman/concurrent-map v0.0.0-20210501183033-44dafcb38ecc/go.mod h1:L github.com/orcaman/concurrent-map v1.0.0 h1:I/2A2XPCb4IuQWcQhBhSwGfiuybl/J0ev9HDbW65HOY= github.com/orcaman/concurrent-map v1.0.0/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI= github.com/ovh/go-ovh v1.1.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA= -github.com/owncloud/libre-graph-api-go v0.13.1 h1:Pdg+3mmYOeKb5Gr+eUHM6L1CpHcEkaNjcBnxTZfm80s= -github.com/owncloud/libre-graph-api-go v0.13.1/go.mod h1:579sFrPP7aP24LZXGPopLfvE+hAka/2DYHk0+Ij+w+U= +github.com/owncloud/libre-graph-api-go v0.13.2 h1:Qv79QuGP6GHGMuA8kwpdGOamSgrauoZGWKwF8vn2GgA= +github.com/owncloud/libre-graph-api-go v0.13.2/go.mod h1:579sFrPP7aP24LZXGPopLfvE+hAka/2DYHk0+Ij+w+U= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= diff --git a/graph/pkg/service/v0/driveitems.go b/graph/pkg/service/v0/driveitems.go index a5eb21a65f9..1eec27331ca 100644 --- a/graph/pkg/service/v0/driveitems.go +++ b/graph/pkg/service/v0/driveitems.go @@ -92,6 +92,30 @@ 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 { + // Only log this, there could be mountpoints which have no grant + g.logger.Debug().Msg(res.Status.Message) + return nil, nil + } + item, err := cs3ResourceToRemoteItem(res.Info) + if err != nil { + return nil, err + } + + item.WebDavUrl = libregraph.PtrString(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 +164,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 +240,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.Id.String(), *itemPath)) return spaceItem } diff --git a/graph/pkg/service/v0/drives.go b/graph/pkg/service/v0/drives.go index a82f284223c..19c176cc076 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,7 +382,7 @@ 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 } @@ -429,7 +429,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 +491,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 +506,24 @@ func (g Graph) cs3StorageSpaceToDrive(baseURL *url.URL, space *storageprovider.S Permissions: permissions, }, } + if space.SpaceType == "mountpoint" { + var remoteItem *libregraph.RemoteItem + grantID := storageprovider.ResourceId{ + StorageId: utils.ReadPlainFromOpaque(space.Opaque, "grantStorageID"), + OpaqueId: utils.ReadPlainFromOpaque(space.Opaque, "grantOpaqueID"), + } + if grantID.StorageId != "" && grantID.OpaqueId != "" { + var err error + remoteItem, err = g.getRemoteItem(ctx, &grantID, baseURL) + if err != nil { + g.logger.Debug().Err(err).Msg("Could not fetch remote item for mountpoint") + } + } + if remoteItem != nil { + drive.Root.RemoteItem = remoteItem + } + } + if space.Opaque != nil { if description, ok := space.Opaque.Map["description"]; ok { drive.Description = libregraph.PtrString(string(description.Value)) @@ -526,7 +548,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 } diff --git a/graph/pkg/service/v0/graph_test.go b/graph/pkg/service/v0/graph_test.go index 30c1160772d..533420ef611 100644 --- a/graph/pkg/service/v0/graph_test.go +++ b/graph/pkg/service/v0/graph_test.go @@ -65,11 +65,11 @@ var _ = Describe("Graph", func() { Status: status.NewOK(ctx), StorageSpaces: []*provider.StorageSpace{ { - Id: &provider.StorageSpaceId{OpaqueId: "aspaceid"}, + Id: &provider.StorageSpaceId{OpaqueId: "sameID"}, SpaceType: "aspacetype", Root: &provider.ResourceId{ - StorageId: "aspaceid", - OpaqueId: "anopaqueid", + StorageId: "sameID", + OpaqueId: "sameID", }, Name: "aspacename", }, @@ -94,11 +94,11 @@ var _ = Describe("Graph", func() { "value":[ { "driveType":"aspacetype", - "id":"aspaceid", + "id":"sameID", "name":"aspacename", "root":{ - "id":"aspaceid!anopaqueid", - "webDavUrl":"https://localhost:9200/dav/spaces/aspaceid" + "id":"sameID!sameID", + "webDavUrl":"https://localhost:9200/dav/spaces/sameID" } } ] @@ -110,11 +110,11 @@ var _ = Describe("Graph", func() { Status: status.NewOK(ctx), StorageSpaces: []*provider.StorageSpace{ { - Id: &provider.StorageSpaceId{OpaqueId: "bspaceid"}, + Id: &provider.StorageSpaceId{OpaqueId: "bsameID"}, SpaceType: "bspacetype", Root: &provider.ResourceId{ - StorageId: "bspaceid", - OpaqueId: "bopaqueid", + StorageId: "bsameID", + OpaqueId: "bsameID", }, Name: "bspacename", Opaque: &typesv1beta1.Opaque{ @@ -125,11 +125,11 @@ var _ = Describe("Graph", func() { }, }, { - Id: &provider.StorageSpaceId{OpaqueId: "aspaceid"}, + Id: &provider.StorageSpaceId{OpaqueId: "asameID"}, SpaceType: "aspacetype", Root: &provider.ResourceId{ - StorageId: "aspaceid", - OpaqueId: "anopaqueid", + StorageId: "asameID", + OpaqueId: "asameID", }, Name: "aspacename", Opaque: &typesv1beta1.Opaque{ @@ -161,23 +161,23 @@ var _ = Describe("Graph", func() { { "driveAlias":"aspacetype/aspacename", "driveType":"aspacetype", - "id":"aspaceid", + "id":"asameID", "name":"aspacename", "root":{ "eTag":"101112131415", - "id":"aspaceid!anopaqueid", - "webDavUrl":"https://localhost:9200/dav/spaces/aspaceid" + "id":"asameID!asameID", + "webDavUrl":"https://localhost:9200/dav/spaces/asameID" } }, { "driveAlias":"bspacetype/bspacename", "driveType":"bspacetype", - "id":"bspaceid", + "id":"bsameID", "name":"bspacename", "root":{ "eTag":"123456789", - "id":"bspaceid!bopaqueid", - "webDavUrl":"https://localhost:9200/dav/spaces/bspaceid" + "id":"bsameID!bsameID", + "webDavUrl":"https://localhost:9200/dav/spaces/bsameID" } } ]