Skip to content

Commit

Permalink
Support OCM shares as well on wopi apps
Browse files Browse the repository at this point in the history
  • Loading branch information
glpatcern committed Mar 7, 2023
1 parent 8474891 commit 744c4e5
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 20 deletions.
42 changes: 25 additions & 17 deletions pkg/app/provider/wopi/wopi.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func New(m map[string]interface{}) (app.Provider, error) {
}

wopiClient := rhttp.GetHTTPClient(
rhttp.Timeout(time.Duration(5*int64(time.Second))),
rhttp.Timeout(time.Duration(10*int64(time.Second))),
rhttp.Insecure(c.InsecureConnections),
)
wopiClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
Expand Down Expand Up @@ -184,30 +184,25 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc
// either append `/files/spaces/<full_path>` or the proper URL prefix + `/<relative_path>`
var rPath string
var pathErr error
_, ok = utils.HasPublicShareRole(u)
_, pubrole := utils.HasPublicShareRole(u)
_, ocmrole := utils.HasOCMShareRole(u)
switch {
case ok:
case pubrole:
// we are in a public link, username is not set so it will default to "Guest xyz"
ut = anonymous
rPath, pathErr = getPathForExternalLink(ctx, scopes, resource, publicLinkURLPrefix)
if pathErr != nil {
log.Warn().Err(pathErr).Msg("wopi: failed to extract relative path from public link scope")
}
case u.Username == "":
case ocmrole:
// OCM users have no username: use displayname@Idp
ut = ocm
idpURL, e := url.Parse(u.Id.Idp)
if e != nil {
q.Add("username", u.DisplayName+" @ "+u.Id.Idp)
} else {
q.Add("username", u.DisplayName+" @ "+idpURL.Hostname())
}
q.Add("username", u.DisplayName+" @ "+u.Id.Idp)
// and resolve the folder
rPath, pathErr = getPathForExternalLink(ctx, scopes, resource, ocmLinkURLPrefix)
if pathErr != nil {
log.Warn().Err(pathErr).Msg("wopi: failed to extract relative path from ocm link scope")
}
q.Add("usertype", "ocm")
default:
// in all other cases use the resource's path
if ut == invalid {
Expand Down Expand Up @@ -508,12 +503,25 @@ func parseWopiDiscovery(body io.Reader) (map[string]map[string]string, error) {
}

func getPathForExternalLink(ctx context.Context, scopes map[string]*authpb.Scope, resource *provider.ResourceInfo, pathPrefix string) (string, error) {
shares, err := scope.GetPublicOcmSharesFromScopes(scopes)
pubshares, err := scope.GetPublicSharesFromScopes(scopes)
if err != nil {
return "", err
}
ocmshares, err := scope.GetOCMSharesFromScopes(scopes)
if err != nil {
return "", err
}
if len(shares) > 1 {
return "", errors.New("More than one public or OCM share found in the scope, lookup not implemented")
var resID *provider.ResourceId
var token string
switch {
case len(pubshares) == 1:
resID = pubshares[0].ResourceId
token = pubshares[0].Token
case len(ocmshares) == 1:
resID = ocmshares[0].ResourceId
token = ocmshares[0].Token
default:
return "", errors.New("Either one public xor OCM share is supported, lookups not implemented")
}

client, err := pool.GetGatewayServiceClient(pool.Endpoint(sharedconf.GetGatewaySVC("")))
Expand All @@ -522,7 +530,7 @@ func getPathForExternalLink(ctx context.Context, scopes map[string]*authpb.Scope
}
statRes, err := client.Stat(ctx, &provider.StatRequest{
Ref: &provider.Reference{
ResourceId: shares[0].ResourceId,
ResourceId: resID,
},
})
if err != nil {
Expand All @@ -531,7 +539,7 @@ func getPathForExternalLink(ctx context.Context, scopes map[string]*authpb.Scope

if statRes.Info.Path == resource.Path {
// this is a direct link to the resource
return pathPrefix + shares[0].Token, nil
return pathPrefix + token, nil
}
// otherwise we are in a subfolder of the public link
relPath, err := filepath.Rel(statRes.Info.Path, resource.Path)
Expand All @@ -541,5 +549,5 @@ func getPathForExternalLink(ctx context.Context, scopes map[string]*authpb.Scope
if strings.HasPrefix(relPath, "../") {
return "", errors.New("Scope path does not contain target resource")
}
return path.Join(pathPrefix+shares[0].Token, path.Dir(relPath)), nil
return path.Join(pathPrefix+token, path.Dir(relPath)), nil
}
21 changes: 21 additions & 0 deletions pkg/auth/scope/ocmshare.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/utils"
"github.com/rs/zerolog"
)
Expand Down Expand Up @@ -134,3 +135,23 @@ func AddOCMShareScope(share *ocmv1beta1.Share, role authpb.Role, scopes map[stri
}
return scopes, nil
}

// GetOCMSharesFromScopes returns all OCM shares in the given scope.
func GetOCMSharesFromScopes(scopes map[string]*authpb.Scope) ([]*ocmv1beta1.Share, error) {
var shares []*ocmv1beta1.Share
for k, s := range scopes {
if strings.HasPrefix(k, "ocmshare:") {
res := s.Resource
if res.Decoder != "json" {
return nil, errtypes.InternalError("resource should be json encoded")
}
var share ocmv1beta1.Share
err := utils.UnmarshalJSONToProtoV1(res.Value, &share)
if err != nil {
return nil, err
}
shares = append(shares, &share)
}
}
return shares, nil
}
6 changes: 3 additions & 3 deletions pkg/auth/scope/publicshare.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ func AddPublicShareScope(share *link.PublicShare, role authpb.Role, scopes map[s
return scopes, nil
}

// GetPublicOcmSharesFromScopes returns all public and OCM shares in the given scope.
func GetPublicOcmSharesFromScopes(scopes map[string]*authpb.Scope) ([]*link.PublicShare, error) {
// GetPublicSharesFromScopes returns all public shares in the given scope.
func GetPublicSharesFromScopes(scopes map[string]*authpb.Scope) ([]*link.PublicShare, error) {
var shares []*link.PublicShare
for k, s := range scopes {
if strings.HasPrefix(k, "publicshare:") || strings.HasPrefix(k, "ocmshare:") {
if strings.HasPrefix(k, "publicshare:") {
res := s.Resource
if res.Decoder != "json" {
return nil, errtypes.InternalError("resource should be json encoded")
Expand Down

0 comments on commit 744c4e5

Please sign in to comment.