diff --git a/changelog/unreleased/webdav-references.md b/changelog/unreleased/webdav-references.md new file mode 100644 index 0000000000..1bcfb1259e --- /dev/null +++ b/changelog/unreleased/webdav-references.md @@ -0,0 +1,6 @@ +Enhancement: Add functionality to create webdav references for OCM shares. + +Webdav references will now be created in users' shares directory with the target +set to the original resource's location in their mesh provider. + +https://github.com/cs3org/reva/pull/974 diff --git a/cmd/reva/ocm-share-create.go b/cmd/reva/ocm-share-create.go index 1c16962705..86b36e237c 100644 --- a/cmd/reva/ocm-share-create.go +++ b/cmd/reva/ocm-share-create.go @@ -22,6 +22,7 @@ import ( "encoding/json" "fmt" "os" + "path" "strconv" "time" @@ -122,17 +123,21 @@ func ocmShareCreateCommand() *command { if err != nil { return err } - permOpaque := &types.Opaque{ + opaqueObj := &types.Opaque{ Map: map[string]*types.OpaqueEntry{ "permissions": &types.OpaqueEntry{ Decoder: "json", Value: val, }, + "name": &types.OpaqueEntry{ + Decoder: "plain", + Value: []byte(path.Base(res.Info.Path)), + }, }, } shareRequest := &ocm.CreateOCMShareRequest{ - Opaque: permOpaque, + Opaque: opaqueObj, ResourceId: res.Info.Id, Grant: grant, RecipientMeshProvider: providerInfo.ProviderInfo, diff --git a/examples/oc-phoenix/providers.demo.json b/examples/oc-phoenix/providers.demo.json index b1532ba5ed..fb471b914f 100644 --- a/examples/oc-phoenix/providers.demo.json +++ b/examples/oc-phoenix/providers.demo.json @@ -19,6 +19,19 @@ }, "api_version": "0.0.1", "host": "http://127.0.0.1:13001/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "CERNBox Webdav API" + }, + "name": "CERNBox - Webdav API", + "path": "http://127.0.0.1:13001/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "http://127.0.0.1:13001/" } ] }, @@ -42,6 +55,19 @@ }, "api_version": "0.0.1", "host": "http://127.0.0.1:13001/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "CESNET Webdav API" + }, + "name": "CESNET - Webdav API", + "path": "http://127.0.0.1:13001/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "http://127.0.0.1:13001/" } ] }, @@ -65,6 +91,19 @@ }, "api_version": "0.0.1", "host": "http://127.0.0.1:13001/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "Example Webdav API" + }, + "name": "Example - Webdav API", + "path": "http://127.0.0.1:13001/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "http://127.0.0.1:13001/" } ] }, @@ -88,6 +127,19 @@ }, "api_version": "0.0.1", "host": "http://127.0.0.1:13001/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "Test Webdav API" + }, + "name": "Test - Webdav API", + "path": "http://127.0.0.1:13001/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "http://127.0.0.1:13001/" } ] } diff --git a/examples/ocm-partners/providers.demo.json b/examples/ocm-partners/providers.demo.json index 09f4d1c204..45831cfd75 100644 --- a/examples/ocm-partners/providers.demo.json +++ b/examples/ocm-partners/providers.demo.json @@ -19,6 +19,19 @@ }, "api_version": "0.0.1", "host": "https://sciencemesh.cernbox.cern.ch/iop/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "CERNBox Webdav API" + }, + "name": "CERNBox - Webdav API", + "path": "https://sciencemesh.cernbox.cern.ch/iop/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "https://sciencemesh.cernbox.cern.ch/iop/" } ] }, @@ -42,6 +55,19 @@ }, "api_version": "0.0.1", "host": "https://sciencemesh.cesnet.cz/iop/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "CESNET Webdav API" + }, + "name": "CESNET - Webdav API", + "path": "https://sciencemesh.cesnet.cz/iop/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "https://sciencemesh.cesnet.cz/iop/" } ] }, @@ -65,6 +91,19 @@ }, "api_version": "0.0.1", "host": "https://sciencemesh-test.uni-muenster.de/api/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "WWU Webdav API" + }, + "name": "WWU - Webdav API", + "path": "https://sciencemesh-test.uni-muenster.de/api/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "https://sciencemesh-test.uni-muenster.de/api/" } ] }, @@ -88,6 +127,19 @@ }, "api_version": "0.0.1", "host": "https://sciencemesh.cubbit.io/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "Cubbit Webdav API" + }, + "name": "Cubbit - Webdav API", + "path": "https://sciencemesh.cubbit.io/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "https://sciencemesh.cubbit.io/" } ] }, @@ -111,6 +163,19 @@ }, "api_version": "0.0.1", "host": "https://cs3mesh.softwaremind.com/iop/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "Ailleron Webdav API" + }, + "name": "Ailleron - Webdav API", + "path": "https://cs3mesh.softwaremind.com/iop/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "https://cs3mesh.softwaremind.com/iop/" } ] }, @@ -134,6 +199,19 @@ }, "api_version": "0.0.1", "host": "https://app.cs3mesh-iop.k8s.surfsara.nl/iop/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "Surfsara Webdav API" + }, + "name": "Surfsara - Webdav API", + "path": "https://app.cs3mesh-iop.k8s.surfsara.nl/iop/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "https://app.cs3mesh-iop.k8s.surfsara.nl/iop/" } ] } diff --git a/examples/ocmd/providers.demo.json b/examples/ocmd/providers.demo.json index c4d36cfeef..e79d341c92 100644 --- a/examples/ocmd/providers.demo.json +++ b/examples/ocmd/providers.demo.json @@ -19,6 +19,19 @@ }, "api_version": "0.0.1", "host": "http://127.0.0.1:19001/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "CERNBox Webdav API" + }, + "name": "CERNBox - Webdav API", + "path": "http://127.0.0.1:19001/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "http://127.0.0.1:19001/" } ] }, @@ -42,6 +55,19 @@ }, "api_version": "0.0.1", "host": "http://127.0.0.1:17001/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "CESNET Webdav API" + }, + "name": "CESNET - Webdav API", + "path": "http://127.0.0.1:17001/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "http://127.0.0.1:17001/" } ] }, @@ -65,6 +91,19 @@ }, "api_version": "0.0.1", "host": "http://127.0.0.1:19001/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "Example Webdav API" + }, + "name": "Example - Webdav API", + "path": "http://127.0.0.1:19001/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "http://127.0.0.1:19001/" } ] }, @@ -88,6 +127,19 @@ }, "api_version": "0.0.1", "host": "http://127.0.0.1:19001/" + }, + { + "endpoint": { + "type": { + "name": "Webdav", + "description": "Test Webdav API" + }, + "name": "Test - Webdav API", + "path": "http://127.0.0.1:19001/webdav/", + "isMonitored": true + }, + "api_version": "0.0.1", + "host": "http://127.0.0.1:19001/" } ] } diff --git a/examples/standalone/standalone.toml b/examples/standalone/standalone.toml index 7350f2b1f2..8a59ea2929 100644 --- a/examples/standalone/standalone.toml +++ b/examples/standalone/standalone.toml @@ -1,7 +1,17 @@ # services to enable [grpc.services.gateway] +commit_share_to_storage_grant = true +commit_share_to_storage_ref = true + [grpc.services.storageregistry] -[grpc.services.storageprovider] +[grpc.services.storageregistry.drivers.static] +home_provider = "/home" + +[grpc.services.storageregistry.drivers.static.rules] +"/home" = "localhost:17000" +"/reva" = "localhost:18000" +"123e4567-e89b-12d3-a456-426655440000" = "localhost:18000" + [grpc.services.authprovider] [grpc.services.authregistry] [grpc.services.userprovider] @@ -13,6 +23,5 @@ [grpc.services.ocmproviderauthorizer] [http.services.datagateway] -[http.services.dataprovider] [http.services.prometheus] [http.services.ocmd] diff --git a/examples/standalone/storage-home.toml b/examples/standalone/storage-home.toml new file mode 100644 index 0000000000..faea5066b7 --- /dev/null +++ b/examples/standalone/storage-home.toml @@ -0,0 +1,14 @@ +[grpc] +address = "0.0.0.0:17000" + +[grpc.services.storageprovider] +driver = "localhome" +mount_path = "/home" +mount_id = "123e4567-e89b-12d3-a456-426655440000" +data_server_url = "http://localhost:17001/data" + +[http] +address = "0.0.0.0:17001" + +[http.services.dataprovider] +driver = "localhome" diff --git a/examples/standalone/storage-reva.toml b/examples/standalone/storage-reva.toml new file mode 100644 index 0000000000..b6b6209db1 --- /dev/null +++ b/examples/standalone/storage-reva.toml @@ -0,0 +1,7 @@ +[grpc] +address = "0.0.0.0:18000" + +[grpc.services.storageprovider] +driver = "local" +mount_path = "/reva" +mount_id = "123e4567-e89b-12d3-a456-426655440000" diff --git a/internal/grpc/services/gateway/ocmshareprovider.go b/internal/grpc/services/gateway/ocmshareprovider.go index a38ba82469..9f5c507055 100644 --- a/internal/grpc/services/gateway/ocmshareprovider.go +++ b/internal/grpc/services/gateway/ocmshareprovider.go @@ -20,10 +20,16 @@ package gateway import ( "context" + "fmt" + "path" + "strings" + ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1" + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" + "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/pkg/errors" @@ -247,7 +253,7 @@ func (s *svc) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateReceive panic("gateway: error updating a received share: the share is nil") } - createRefStatus, err := s.createReference(ctx, share.Share.ResourceId) + createRefStatus, err := s.createWebdavReference(ctx, share.Share) return &ocm.UpdateReceivedOCMShareResponse{ Status: createRefStatus, }, err @@ -277,3 +283,71 @@ func (s *svc) GetReceivedOCMShare(ctx context.Context, req *ocm.GetReceivedOCMSh return res, nil } + +func (s *svc) createWebdavReference(ctx context.Context, share *ocm.Share) (*rpc.Status, error) { + + log := appctx.GetLogger(ctx) + + meshProvider, err := s.GetInfoByDomain(ctx, &ocmprovider.GetInfoByDomainRequest{ + Domain: share.Creator.Idp, + }) + if err != nil { + err := errors.Wrap(err, "gateway: error calling GetInfoByDomain") + return status.NewInternal(ctx, err, "error updating received share"), nil + } + var webdavEndpoint string + for _, s := range meshProvider.ProviderInfo.Services { + if s.Endpoint.Type.Name == "Webdav" { + webdavEndpoint = s.Endpoint.Path + } + } + + homeRes, err := s.GetHome(ctx, &provider.GetHomeRequest{}) + if err != nil { + err := errors.Wrap(err, "gateway: error calling GetHome") + return status.NewInternal(ctx, err, "error updating received share"), nil + } + + parts := strings.Split(share.Id.OpaqueId, ":") + if len(parts) < 2 { + err := errors.New("resource ID does not follow the layout id:name ") + return status.NewInternal(ctx, err, "error decoding resource ID"), nil + } + + // reference path is the home path + some name on the corresponding + // mesh provider (webdav:webdav_endpoint:/home/MyShares/x) + // It is the responsibility of the gateway to resolve these references and merge the response back + // from the main request. + // TODO(labkode): the name of the share should be the filename it points to by default. + refPath := path.Join(homeRes.Path, s.c.ShareFolder, path.Base(parts[1])) + log.Info().Msg("mount path will be:" + refPath) + + createRefReq := &provider.CreateReferenceRequest{ + Path: refPath, + // webdav is the Scheme and %s/%s is the Opaque parts of a net.URL. + TargetUri: fmt.Sprintf("webdav:%s/%s@%s", share.ResourceId.GetStorageId(), share.ResourceId.GetOpaqueId(), webdavEndpoint), + } + + c, err := s.findByPath(ctx, refPath) + if err != nil { + if _, ok := err.(errtypes.IsNotFound); ok { + return status.NewNotFound(ctx, "storage provider not found"), nil + } + return status.NewInternal(ctx, err, "error finding storage provider"), nil + } + + createRefRes, err := c.CreateReference(ctx, createRefReq) + if err != nil { + log.Err(err).Msg("gateway: error calling GetHome") + return &rpc.Status{ + Code: rpc.Code_CODE_INTERNAL, + }, nil + } + + if createRefRes.Status.Code != rpc.Code_CODE_OK { + err := status.NewErrorFromCode(createRefRes.Status.GetCode(), "gateway") + return status.NewInternal(ctx, err, "error updating received share"), nil + } + + return status.NewOK(ctx), nil +} diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index ead6d49d6f..fc6f565081 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -960,7 +960,7 @@ func (s *svc) checkRef(ctx context.Context, ri *provider.ResourceInfo) (*provide return nil, err } - newResourceInfo, err := s.handleRef(ctx, target) + newResourceInfo, err := s.handleRef(ctx, ri) if err != nil { err := errors.Wrapf(err, "gateway: error handling ref target:%s", target) return nil, err @@ -968,10 +968,10 @@ func (s *svc) checkRef(ctx context.Context, ri *provider.ResourceInfo) (*provide return newResourceInfo, nil } -func (s *svc) handleRef(ctx context.Context, targetURI string) (*provider.ResourceInfo, error) { - uri, err := url.Parse(targetURI) +func (s *svc) handleRef(ctx context.Context, ri *provider.ResourceInfo) (*provider.ResourceInfo, error) { + uri, err := url.Parse(ri.Target) if err != nil { - return nil, errors.Wrapf(err, "gateway: error parsing target uri:%s", targetURI) + return nil, errors.Wrapf(err, "gateway: error parsing target uri:%s", ri.Target) } scheme := uri.Scheme @@ -979,6 +979,8 @@ func (s *svc) handleRef(ctx context.Context, targetURI string) (*provider.Resour switch scheme { case "cs3": return s.handleCS3Ref(ctx, uri.Opaque) + case "webdav": + return s.handleWebdavRef(ctx, ri) default: err := errors.New("gateway: no reference handler for scheme:" + scheme) return nil, err @@ -1028,6 +1030,12 @@ func (s *svc) handleCS3Ref(ctx context.Context, opaque string) (*provider.Resour return res.Info, nil } +func (s *svc) handleWebdavRef(ctx context.Context, ri *provider.ResourceInfo) (*provider.ResourceInfo, error) { + // A webdav ref has the following layout: /@webdav_endpoint + // TODO: Once file transfer functionalities have been added. + return ri, nil +} + func (s *svc) ListContainerStream(req *provider.ListContainerStreamRequest, ss gateway.GatewayAPI_ListContainerStreamServer) error { return errors.New("Unimplemented") } diff --git a/internal/grpc/services/gateway/usershareprovider.go b/internal/grpc/services/gateway/usershareprovider.go index 320dc4a35e..4d430f0521 100644 --- a/internal/grpc/services/gateway/usershareprovider.go +++ b/internal/grpc/services/gateway/usershareprovider.go @@ -332,7 +332,6 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update if share == nil { panic("gateway: error updating a received share: the share is nil") } - createRefStatus, err := s.createReference(ctx, share.Share.ResourceId) return &collaboration.UpdateReceivedShareResponse{ Status: createRefStatus, diff --git a/internal/grpc/services/ocmcore/ocmcore.go b/internal/grpc/services/ocmcore/ocmcore.go index 66bae96877..8300efabb8 100644 --- a/internal/grpc/services/ocmcore/ocmcore.go +++ b/internal/grpc/services/ocmcore/ocmcore.go @@ -22,6 +22,7 @@ import ( "context" "encoding/json" "fmt" + "strings" ocmcore "github.com/cs3org/go-cs3apis/cs3/ocm/core/v1beta1" ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1" @@ -106,9 +107,17 @@ func (s *service) UnprotectedEndpoints() []string { } func (s *service) CreateOCMCoreShare(ctx context.Context, req *ocmcore.CreateOCMCoreShareRequest) (*ocmcore.CreateOCMCoreShareResponse, error) { + parts := strings.Split(req.ProviderId, ":") + if len(parts) < 2 { + err := errors.New("resource ID does not follow the layout storageid:opaqueid " + req.ProviderId) + return &ocmcore.CreateOCMCoreShareResponse{ + Status: status.NewInternal(ctx, err, "error decoding resource ID"), + }, nil + } + resource := &provider.ResourceId{ - StorageId: req.ProviderId, - OpaqueId: req.Name, + StorageId: parts[0], + OpaqueId: parts[1], } opaqueObj := req.Protocol.Opaque.Map["permissions"] @@ -137,7 +146,7 @@ func (s *service) CreateOCMCoreShare(ctx context.Context, req *ocmcore.CreateOCM }, } - share, err := s.sm.Share(ctx, resource, grant, nil, "", req.Owner) + share, err := s.sm.Share(ctx, resource, grant, req.Name, nil, "", req.Owner) if err != nil { return &ocmcore.CreateOCMCoreShareResponse{ Status: status.NewInternal(ctx, err, "error creating ocm core share"), diff --git a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go index fb5b13a305..f2be71782d 100644 --- a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go +++ b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go @@ -111,29 +111,46 @@ func (s *service) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareReq }, nil } - opaqueObj, ok := req.Opaque.Map["permissions"] + permOpaque, ok := req.Opaque.Map["permissions"] if !ok { return &ocm.CreateOCMShareResponse{ Status: status.NewInternal(ctx, errors.New("resource permissions not set"), ""), }, nil } - var permissions map[string]string - if opaqueObj.Decoder == "json" { - err := json.Unmarshal(opaqueObj.Value, &permissions) + switch permOpaque.Decoder { + case "json": + err := json.Unmarshal(permOpaque.Value, &permissions) if err != nil { return &ocm.CreateOCMShareResponse{ Status: status.NewInternal(ctx, err, "error decoding resource permissions"), }, nil } - } else { - err := errors.New("opaque entry decoder is not json") + default: + err := errors.New("opaque entry decoder not recognized") + return &ocm.CreateOCMShareResponse{ + Status: status.NewInternal(ctx, err, "invalid opaque entry decoder"), + }, nil + } + + nameOpaque, ok := req.Opaque.Map["name"] + if !ok { + return &ocm.CreateOCMShareResponse{ + Status: status.NewInternal(ctx, errors.New("resource name not set"), ""), + }, nil + } + var name string + switch nameOpaque.Decoder { + case "plain": + name = string(nameOpaque.Value) + default: + err := errors.New("opaque entry decoder not recognized: " + nameOpaque.Decoder) return &ocm.CreateOCMShareResponse{ Status: status.NewInternal(ctx, err, "invalid opaque entry decoder"), }, nil } - share, err := s.sm.Share(ctx, req.ResourceId, req.Grant, req.RecipientMeshProvider, permissions["name"], nil) + share, err := s.sm.Share(ctx, req.ResourceId, req.Grant, name, req.RecipientMeshProvider, permissions["name"], nil) if err != nil { return &ocm.CreateOCMShareResponse{ Status: status.NewInternal(ctx, err, "error creating share"), diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index 8a8d8900c4..229665c009 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -541,6 +541,10 @@ func (h *Handler) createFederatedCloudShare(w http.ResponseWriter, r *http.Reque Decoder: "json", Value: val, }, + "name": &types.OpaqueEntry{ + Decoder: "plain", + Value: []byte(path.Base(statRes.Info.Path)), + }, }, }, ResourceId: statRes.Info.Id, diff --git a/pkg/ocm/invite/manager/json/json.go b/pkg/ocm/invite/manager/json/json.go index 644c760eeb..ad7eb2cfb2 100644 --- a/pkg/ocm/invite/manager/json/json.go +++ b/pkg/ocm/invite/manager/json/json.go @@ -248,7 +248,6 @@ func (m *manager) AcceptInvite(ctx context.Context, invite *invitepb.InviteToken if acceptedUser.Id.GetOpaqueId() == remoteUser.Id.OpaqueId && acceptedUser.Id.GetIdp() == remoteUser.Id.Idp { return errors.New("json: user already added to accepted users") } - } m.model.AcceptedUsers[userKey] = append(m.model.AcceptedUsers[userKey], remoteUser) if err := m.model.Save(); err != nil { diff --git a/pkg/ocm/share/manager/json/json.go b/pkg/ocm/share/manager/json/json.go index 354c702524..d1bc4188dc 100644 --- a/pkg/ocm/share/manager/json/json.go +++ b/pkg/ocm/share/manager/json/json.go @@ -187,7 +187,9 @@ func getOCMEndpoint(originProvider *ocmprovider.ProviderInfo) (string, error) { return "", errors.New("json: ocm endpoint not specified for mesh provider") } -func (m *mgr) Share(ctx context.Context, md *provider.ResourceId, g *ocm.ShareGrant, pi *ocmprovider.ProviderInfo, pm string, owner *userpb.UserId) (*ocm.Share, error) { +func (m *mgr) Share(ctx context.Context, md *provider.ResourceId, g *ocm.ShareGrant, name string, + pi *ocmprovider.ProviderInfo, pm string, owner *userpb.UserId) (*ocm.Share, error) { + id := genID() now := time.Now().UnixNano() ts := &typespb.Timestamp{ @@ -213,6 +215,7 @@ func (m *mgr) Share(ctx context.Context, md *provider.ResourceId, g *ocm.ShareGr return nil, errors.New("json: owner of resource not provided") } userID = owner + id += ":" + name } else { userID = user.ContextMustGetUser(ctx).GetId() } @@ -267,8 +270,8 @@ func (m *mgr) Share(ctx context.Context, md *provider.ResourceId, g *ocm.ShareGr requestBody := url.Values{ "shareWith": {g.Grantee.Id.OpaqueId}, - "name": {md.OpaqueId}, - "providerId": {md.StorageId}, + "name": {name}, + "providerId": {fmt.Sprintf("%s:%s", md.StorageId, md.OpaqueId)}, "owner": {userID.OpaqueId}, "protocol": {string(protocol)}, "meshProvider": {userID.Idp}, diff --git a/pkg/ocm/share/manager/memory/memory.go b/pkg/ocm/share/manager/memory/memory.go index 1ba3f64762..d1ce2219e3 100644 --- a/pkg/ocm/share/manager/memory/memory.go +++ b/pkg/ocm/share/manager/memory/memory.go @@ -97,7 +97,8 @@ func getOCMEndpoint(originProvider *ocmprovider.ProviderInfo) (string, error) { return "", errors.New("memory: ocm endpoint not specified for mesh provider") } -func (m *mgr) Share(ctx context.Context, md *provider.ResourceId, g *ocm.ShareGrant, pi *ocmprovider.ProviderInfo, pm string, owner *userpb.UserId) (*ocm.Share, error) { +func (m *mgr) Share(ctx context.Context, md *provider.ResourceId, g *ocm.ShareGrant, name string, + pi *ocmprovider.ProviderInfo, pm string, owner *userpb.UserId) (*ocm.Share, error) { id := genID() now := time.Now().UnixNano() @@ -122,6 +123,7 @@ func (m *mgr) Share(ctx context.Context, md *provider.ResourceId, g *ocm.ShareGr return nil, errors.New("json: owner of resource not provided") } userID = owner + id += ":" + name } else { userID = user.ContextMustGetUser(ctx).GetId() } @@ -178,8 +180,8 @@ func (m *mgr) Share(ctx context.Context, md *provider.ResourceId, g *ocm.ShareGr requestBody := url.Values{ "shareWith": {g.Grantee.Id.OpaqueId}, - "name": {md.OpaqueId}, - "providerId": {md.StorageId}, + "name": {name}, + "providerId": {fmt.Sprintf("%s:%s", md.StorageId, md.OpaqueId)}, "owner": {userID.OpaqueId}, "protocol": {string(protocol)}, "meshProvider": {userID.Idp}, diff --git a/pkg/ocm/share/share.go b/pkg/ocm/share/share.go index 208418ab77..d6f1bbd8dd 100644 --- a/pkg/ocm/share/share.go +++ b/pkg/ocm/share/share.go @@ -30,7 +30,7 @@ import ( // Manager is the interface that manipulates the OCM shares. type Manager interface { // Create a new share in fn with the given acl. - Share(ctx context.Context, md *provider.ResourceId, g *ocm.ShareGrant, pi *ocmprovider.ProviderInfo, pm string, owner *userpb.UserId) (*ocm.Share, error) + Share(ctx context.Context, md *provider.ResourceId, g *ocm.ShareGrant, name string, pi *ocmprovider.ProviderInfo, pm string, owner *userpb.UserId) (*ocm.Share, error) // GetShare gets the information for a share by the given ref. GetShare(ctx context.Context, ref *ocm.ShareReference) (*ocm.Share, error) diff --git a/pkg/storage/utils/localfs/localfs.go b/pkg/storage/utils/localfs/localfs.go index d4a056a9ab..dbcca04118 100644 --- a/pkg/storage/utils/localfs/localfs.go +++ b/pkg/storage/utils/localfs/localfs.go @@ -165,9 +165,9 @@ func (fs *localfs) wrapReferences(ctx context.Context, p string) string { if err != nil { panic(err) } - internal = path.Join(fs.conf.References, layout, "home", p) + internal = path.Join(fs.conf.References, layout, p) } else { - internal = path.Join(fs.conf.References, "home", p) + internal = path.Join(fs.conf.References, p) } return internal } @@ -257,9 +257,17 @@ func (fs *localfs) normalize(ctx context.Context, fi os.FileInfo, fn string, mdK return nil, err } + var layout string + if !fs.conf.DisableHome { + layout, err = fs.GetHome(ctx) + if err != nil { + return nil, err + } + } + // A fileid is constructed like `fileid-url_encoded_path`. See GetPathByID for the inverse conversion md := &provider.ResourceInfo{ - Id: &provider.ResourceId{OpaqueId: "fileid-" + url.QueryEscape(fp)}, + Id: &provider.ResourceId{OpaqueId: "fileid-" + url.QueryEscape(path.Join(layout, fp))}, Path: fp, Type: getResourceType(fi.IsDir()), Etag: calcEtag(ctx, fi),