Skip to content

Commit

Permalink
Forward OpenFileInAppProvider calls for OCM shares to remote reva
Browse files Browse the repository at this point in the history
  • Loading branch information
ishank011 committed Sep 7, 2020
1 parent dc779a5 commit 302050f
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 107 deletions.
137 changes: 120 additions & 17 deletions internal/grpc/services/gateway/appprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ package gateway

import (
"context"
"fmt"
"net/url"
"strings"

providerpb "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1"
registry "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
storageprovider "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"
Expand All @@ -37,19 +37,36 @@ import (
)

func (s *svc) OpenFileInAppProvider(ctx context.Context, req *gateway.OpenFileInAppProviderRequest) (*providerpb.OpenFileInAppProviderResponse, error) {
p, st := s.getPath(ctx, req.Ref)
if st.Code != rpc.Code_CODE_OK {
if st.Code == rpc.Code_CODE_NOT_FOUND {
return &providerpb.OpenFileInAppProviderResponse{
Status: status.NewNotFound(ctx, "gateway: file not found:"+req.Ref.String()),
}, nil
}
return &providerpb.OpenFileInAppProviderResponse{
Status: st,
}, nil
}

accessToken, ok := tokenpkg.ContextGetToken(ctx)
if !ok || accessToken == "" {
if s.isSharedFolder(ctx, p) {
return &providerpb.OpenFileInAppProviderResponse{
Status: status.NewUnauthenticated(ctx, errors.New("Access token is invalid or empty"), ""),
Status: status.NewInvalid(ctx, "gateway: can't open shares folder"),
}, nil
}

statReq := &provider.StatRequest{
Ref: req.Ref,
resName, resChild := p, ""
if s.isShareChild(ctx, p) {
resName, resChild = s.splitShare(ctx, p)
}

statRes, err := s.Stat(ctx, statReq)
statRes, err := s.stat(ctx, &storageprovider.StatRequest{
Ref: &storageprovider.Reference{
Spec: &storageprovider.Reference_Path{
Path: resName,
},
},
})
if err != nil {
return &providerpb.OpenFileInAppProviderResponse{
Status: status.NewInternal(ctx, err, "gateway: error calling Stat on the resource path for the app provider: "+req.Ref.GetPath()),
Expand All @@ -64,7 +81,98 @@ func (s *svc) OpenFileInAppProvider(ctx context.Context, req *gateway.OpenFileIn

fileInfo := statRes.Info

provider, err := s.findAppProvider(ctx, fileInfo)
// The file is a share
if fileInfo.Type == storageprovider.ResourceType_RESOURCE_TYPE_REFERENCE {
uri, err := url.Parse(fileInfo.Target)
if err != nil {
return &providerpb.OpenFileInAppProviderResponse{
Status: status.NewInternal(ctx, err, "gateway: error parsing target uri: "+fileInfo.Target),
}, nil
}
if uri.Scheme == "webdav" {
return s.openFederatedShares(ctx, fileInfo.Target, req.ViewMode, resChild)
}

res, err := s.Stat(ctx, &storageprovider.StatRequest{
Ref: req.Ref,
})
if err != nil {
return &providerpb.OpenFileInAppProviderResponse{
Status: status.NewInternal(ctx, err, "gateway: error calling Stat on the resource path for the app provider: "+req.Ref.GetPath()),
}, nil
}
if res.Status.Code != rpc.Code_CODE_OK {
err := status.NewErrorFromCode(res.Status.GetCode(), "gateway")
return &providerpb.OpenFileInAppProviderResponse{
Status: status.NewInternal(ctx, err, "Stat failed on the resource path for the app provider: "+req.Ref.GetPath()),
}, nil
}
fileInfo = res.Info
}
return s.openLocalResources(ctx, fileInfo, req.ViewMode)
}

func (s *svc) openFederatedShares(ctx context.Context, targetURL string, vm gateway.OpenFileInAppProviderRequest_ViewMode,
nameQueries ...string) (*providerpb.OpenFileInAppProviderResponse, error) {
targetURL, err := appendNameQuery(targetURL, nameQueries...)
if err != nil {
return nil, err
}
ep, err := s.extractEndpointInfo(ctx, targetURL)
if err != nil {
return nil, err
}

ref := &storageprovider.Reference{
Spec: &storageprovider.Reference_Path{
Path: ep.filePath,
},
}
appProviderReq := &gateway.OpenFileInAppProviderRequest{
Ref: ref,
ViewMode: vm,
}

meshProvider, err := s.GetInfoByDomain(ctx, &ocmprovider.GetInfoByDomainRequest{
Domain: ep.endpoint,
})
if err != nil {
return nil, errors.Wrap(err, "gateway: error calling GetInfoByDomain")
}
var gatewayEP string
for _, s := range meshProvider.ProviderInfo.Services {
if strings.ToLower(s.Endpoint.Type.Name) == "gateway" {
gatewayEP = s.Endpoint.Path
}
}

gatewayClient, err := pool.GetGatewayServiceClient(gatewayEP)
if err != nil {
err = errors.Wrap(err, "gateway: error calling GetGatewayClient")
return &providerpb.OpenFileInAppProviderResponse{
Status: status.NewInternal(ctx, err, "error getting gateway client"),
}, nil
}

ctx = tokenpkg.ContextSetToken(ctx, ep.token)
res, err := gatewayClient.OpenFileInAppProvider(ctx, appProviderReq)
if err != nil {
return nil, errors.Wrap(err, "gateway: error calling OpenFileInAppProvider")
}
return res, nil
}

func (s *svc) openLocalResources(ctx context.Context, ri *storageprovider.ResourceInfo,
vm gateway.OpenFileInAppProviderRequest_ViewMode) (*providerpb.OpenFileInAppProviderResponse, error) {

accessToken, ok := tokenpkg.ContextGetToken(ctx)
if !ok || accessToken == "" {
return &providerpb.OpenFileInAppProviderResponse{
Status: status.NewUnauthenticated(ctx, errors.New("Access token is invalid or empty"), ""),
}, nil
}

provider, err := s.findAppProvider(ctx, ri)
if err != nil {
err = errors.Wrap(err, "gateway: error calling findAppProvider")
var st *rpc.Status
Expand All @@ -86,14 +194,9 @@ func (s *svc) OpenFileInAppProvider(ctx context.Context, req *gateway.OpenFileIn
}, nil
}

// build the appProvider specific request with the required extra info that has been obtained

log := appctx.GetLogger(ctx)
log.Debug().Msg(fmt.Sprintf("request: %s", req))

appProviderReq := &providerpb.OpenFileInAppProviderRequest{
ResourceInfo: fileInfo,
ViewMode: providerpb.OpenFileInAppProviderRequest_ViewMode(req.ViewMode),
ResourceInfo: ri,
ViewMode: providerpb.OpenFileInAppProviderRequest_ViewMode(vm),
AccessToken: accessToken,
}

Expand Down
20 changes: 2 additions & 18 deletions internal/grpc/services/gateway/ocmshareprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ 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"
Expand Down Expand Up @@ -288,20 +286,6 @@ func (s *svc) createWebdavReference(ctx context.Context, share *ocm.Share) (*rpc

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 strings.ToLower(s.Endpoint.Type.Name) == "webdav" {
webdavEndpoint = s.Endpoint.Path
}
}

var token string
tokenOpaque, ok := share.Grantee.Opaque.Map["token"]
if !ok {
Expand Down Expand Up @@ -330,8 +314,8 @@ func (s *svc) createWebdavReference(ctx context.Context, share *ocm.Share) (*rpc

createRefReq := &provider.CreateReferenceRequest{
Path: refPath,
// webdav is the scheme, token@webdav_endpoint the opaque part and the share name the query of the URL.
TargetUri: fmt.Sprintf("webdav:%s@%s?name=%s", token, webdavEndpoint, share.Name),
// webdav is the scheme, token@host the opaque part and the share name the query of the URL.
TargetUri: fmt.Sprintf("webdav://%s@%s?name=%s", token, share.Creator.Idp, share.Name),
}

c, err := s.findByPath(ctx, refPath)
Expand Down
44 changes: 0 additions & 44 deletions internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,6 @@ func (s *svc) InitiateFileDownload(ctx context.Context, req *provider.InitiateFi
}, nil
}

if statRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_REFERENCE {
err := errors.New(fmt.Sprintf("gateway: expected reference: got:%+v", statRes.Info))
log.Err(err).Msg("gateway: error creating container")
return &gateway.InitiateFileDownloadResponse{
Status: status.NewInternal(ctx, err, "gateway: error creating container"),
}, nil
}

ri, protocol, err := s.checkRef(ctx, statRes.Info)
if err != nil {
if _, ok := err.(errtypes.IsNotFound); ok {
Expand Down Expand Up @@ -347,14 +339,6 @@ func (s *svc) InitiateFileUpload(ctx context.Context, req *provider.InitiateFile
}, nil
}

if statRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_REFERENCE {
err := errors.New(fmt.Sprintf("gateway: expected reference: got:%+v", statRes.Info))
log.Err(err).Msg("gateway: error creating container")
return &gateway.InitiateFileUploadResponse{
Status: status.NewInternal(ctx, err, "gateway: error uploading"),
}, nil
}

ri, protocol, err := s.checkRef(ctx, statRes.Info)
if err != nil {
if _, ok := err.(errtypes.IsNotFound); ok {
Expand Down Expand Up @@ -558,14 +542,6 @@ func (s *svc) CreateContainer(ctx context.Context, req *provider.CreateContainer
}, nil
}

if statRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_REFERENCE {
err := errors.New(fmt.Sprintf("gateway: expected reference: got:%+v", statRes.Info))
log.Err(err).Msg("gateway: error creating container")
return &provider.CreateContainerResponse{
Status: status.NewInternal(ctx, err, "gateway: error creating container"),
}, nil
}

ri, protocol, err := s.checkRef(ctx, statRes.Info)
if err != nil {
if _, ok := err.(errtypes.IsNotFound); ok {
Expand Down Expand Up @@ -706,14 +682,6 @@ func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provide
}, nil
}

if statRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_REFERENCE {
err := errors.New(fmt.Sprintf("gateway: expected reference: got:%+v", statRes.Info))
log.Err(err).Msg("gateway: error deleting")
return &provider.DeleteResponse{
Status: status.NewInternal(ctx, err, "gateway: error deleting"),
}, nil
}

ri, protocol, err := s.checkRef(ctx, statRes.Info)
if err != nil {
if _, ok := err.(errtypes.IsNotFound); ok {
Expand Down Expand Up @@ -849,14 +817,6 @@ func (s *svc) Move(ctx context.Context, req *provider.MoveRequest) (*provider.Mo
}, nil
}

if statRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_REFERENCE {
err := errors.New(fmt.Sprintf("gateway: expected reference: got:%+v", statRes.Info))
log.Err(err).Msg("gateway: error deleting")
return &provider.MoveResponse{
Status: status.NewInternal(ctx, err, "gateway: error deleting"),
}, nil
}

ri, protocol, err := s.checkRef(ctx, statRes.Info)
if err != nil {
if _, ok := err.(errtypes.IsNotFound); ok {
Expand Down Expand Up @@ -1052,10 +1012,6 @@ func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.St
}, nil
}

if statRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_REFERENCE {
panic("gateway: a share name must be of type reference: ref:" + statRes.Info.Path)
}

ri, protocol, err := s.checkRef(ctx, statRes.Info)
if err != nil {
if _, ok := err.(errtypes.IsNotFound); ok {
Expand Down
Loading

0 comments on commit 302050f

Please sign in to comment.