Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

return share-types in ocs propfind responses #1329

Merged
merged 2 commits into from
Dec 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions changelog/unreleased/ocis-ocs-share-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: include share types in ocs propfind responses

Added the share types to the ocs propfind response when a resource has been shared.

https://github.com/owncloud/ocis/issues/929
https://github.com/cs3org/reva/pull/1329
5 changes: 3 additions & 2 deletions internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1249,13 +1249,14 @@ func (s *svc) ListContainerStream(_ *provider.ListContainerStreamRequest, _ gate
return errtypes.NotSupported("Unimplemented")
}

func (s *svc) listHome(ctx context.Context) (*provider.ListContainerResponse, error) {
func (s *svc) listHome(ctx context.Context, req *provider.ListContainerRequest) (*provider.ListContainerResponse, error) {
lcr, err := s.listContainer(ctx, &provider.ListContainerRequest{
Ref: &provider.Reference{
Spec: &provider.Reference_Path{
Path: s.getHome(ctx),
},
},
ArbitraryMetadataKeys: req.ArbitraryMetadataKeys,
})
if err != nil {
return &provider.ListContainerResponse{
Expand Down Expand Up @@ -1361,7 +1362,7 @@ func (s *svc) ListContainer(ctx context.Context, req *provider.ListContainerRequ
}

if path.Clean(p) == s.getHome(ctx) {
return s.listHome(ctx)
return s.listHome(ctx, req)
}

if s.isSharedFolder(ctx, p) {
Expand Down
21 changes: 15 additions & 6 deletions internal/http/services/owncloud/ocdav/propfind.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ func (s *svc) handlePropfind(w http.ResponseWriter, r *http.Request, ns string)
if info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER && depth == "1" {
req := &provider.ListContainerRequest{
Ref: ref,
ArbitraryMetadataKeys: []string{
"http://owncloud.org/ns/share-types",
},
}
res, err := client.ListContainer(ctx, req)
if err != nil {
Expand Down Expand Up @@ -143,6 +146,9 @@ func (s *svc) handlePropfind(w http.ResponseWriter, r *http.Request, ns string)
}
req := &provider.ListContainerRequest{
Ref: ref,
ArbitraryMetadataKeys: []string{
"http://owncloud.org/ns/share-types",
},
}
res, err := client.ListContainer(ctx, req)
if err != nil {
Expand Down Expand Up @@ -284,7 +290,6 @@ func (s *svc) newProp(key, val string) *propertyXML {
// ns is the CS3 namespace that needs to be removed from the CS3 path before
// prefixing it with the baseURI
func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provider.ResourceInfo, ns string) (*responseXML, error) {

md.Path = strings.TrimPrefix(md.Path, ns)

baseURI := ctx.Value(ctxKeyBaseURI).(string)
Expand Down Expand Up @@ -442,6 +447,15 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide
} else {
propstatNotFound.Prop = append(propstatNotFound.Prop, s.newProp("oc:checksums", ""))
}
case "share-types": // desktop
k := md.GetArbitraryMetadata()
amd := k.GetMetadata()
if amdv, ok := amd[fmt.Sprintf("%s/%s", pf.Prop[i].Space, pf.Prop[i].Local)]; ok {
st := fmt.Sprintf("<oc:share-type>%s</oc:share-type>", amdv)
propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:share-types", st))
} else {
propstatNotFound.Prop = append(propstatNotFound.Prop, s.newProp("oc:"+pf.Prop[i].Local, ""))
}
case "owner-display-name": // phoenix only
// TODO(jfd): lookup displayname? or let clients do that? They should cache that IMO
fallthrough
Expand All @@ -459,11 +473,6 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide
// see https://doc.owncloud.com/server/admin_manual/configuration/server/occ_command.html#maintenance-commands
// TODO(jfd): double check the client behavior with reva on backup restore
fallthrough
case "share-types": // desktop
// <oc:share-types>
// <oc:share-type>1</oc:share-type>
// </oc:share-types>
fallthrough
default:
propstatNotFound.Prop = append(propstatNotFound.Prop, s.newProp("oc:"+pf.Prop[i].Local, ""))
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/storage/fs/ocis/grants.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ func (fs *ocisfs) RemoveGrant(ctx context.Context, ref *provider.Reference, g *p

var attr string
if g.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_GROUP {
attr = grantPrefix + "g:" + g.Grantee.Id.OpaqueId
attr = grantPrefix + _groupAcePrefix + g.Grantee.Id.OpaqueId
} else {
attr = grantPrefix + "u:" + g.Grantee.Id.OpaqueId
attr = grantPrefix + _userAcePrefix + g.Grantee.Id.OpaqueId
}

np := fs.lu.toInternalPath(node.ID)
Expand Down
29 changes: 28 additions & 1 deletion pkg/storage/fs/ocis/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,18 @@ import (
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/mime"
"github.com/cs3org/reva/pkg/sdk/common"
"github.com/cs3org/reva/pkg/storage/utils/ace"
"github.com/pkg/errors"
"github.com/pkg/xattr"
"github.com/rs/zerolog/log"
)

const (
_shareTypesKey = "http://owncloud.org/ns/share-types"
_userShareType = "0"
)

// Node represents a node in the tree and provides methods to get a Parent or Child instance
type Node struct {
lu *Lookup
Expand Down Expand Up @@ -291,7 +297,7 @@ func (n *Node) Owner() (id string, idp string, err error) {
}

// AsResourceInfo return the node as CS3 ResourceInfo
func (n *Node) AsResourceInfo(ctx context.Context) (ri *provider.ResourceInfo, err error) {
func (n *Node) AsResourceInfo(ctx context.Context, mdKeys []string) (ri *provider.ResourceInfo, err error) {
log := appctx.GetLogger(ctx)

var fn string
Expand Down Expand Up @@ -399,6 +405,12 @@ func (n *Node) AsResourceInfo(ctx context.Context) (ri *provider.ResourceInfo, e
log.Error().Err(err).Interface("node", n).Msg("could not list attributes")
}

if common.FindString(mdKeys, _shareTypesKey) != -1 {
if n.hasUserShares(ctx) {
ri.ArbitraryMetadata.Metadata[_shareTypesKey] = _userShareType
}
}

log.Debug().
Interface("ri", ri).
Msg("AsResourceInfo")
Expand Down Expand Up @@ -469,3 +481,18 @@ func (n *Node) ReadGrant(ctx context.Context, grantee string) (g *provider.Grant
}
return e.Grant(), nil
}

func (n *Node) hasUserShares(ctx context.Context) bool {
g, err := n.ListGrantees(ctx)
if err != nil {
appctx.GetLogger(ctx).Error().Err(err).Msg("hasUserShares: listGrantees")
return false
}

for i := range g {
if strings.Contains(g[i], grantPrefix+_userAcePrefix) {
return true
}
}
return false
}
4 changes: 2 additions & 2 deletions pkg/storage/fs/ocis/ocis.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ func (fs *ocisfs) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []s
return nil, errtypes.PermissionDenied(node.ID)
}

return node.AsResourceInfo(ctx)
return node.AsResourceInfo(ctx, mdKeys)
}

func (fs *ocisfs) ListFolder(ctx context.Context, ref *provider.Reference, mdKeys []string) (finfos []*provider.ResourceInfo, err error) {
Expand Down Expand Up @@ -402,7 +402,7 @@ func (fs *ocisfs) ListFolder(ctx context.Context, ref *provider.Reference, mdKey
}

for i := range children {
if ri, err := children[i].AsResourceInfo(ctx); err == nil {
if ri, err := children[i].AsResourceInfo(ctx, mdKeys); err == nil {
finfos = append(finfos, ri)
}
}
Expand Down
11 changes: 8 additions & 3 deletions pkg/storage/fs/ocis/permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ import (
"github.com/pkg/xattr"
)

const (
_userAcePrefix = "u:"
_groupAcePrefix = "g:"
)

var defaultPermissions *provider.ResourcePermissions = &provider.ResourcePermissions{
// no permissions
}
Expand Down Expand Up @@ -100,15 +105,15 @@ func (p *Permissions) HasPermission(ctx context.Context, n *Node, check func(*pr
return false, err
}

userace := grantPrefix + "u:" + u.Id.OpaqueId
userace := grantPrefix + _userAcePrefix + u.Id.OpaqueId
userFound := false
for i := range grantees {
// we only need the find the user once per node
switch {
case !userFound && grantees[i] == userace:
g, err = cn.ReadGrant(ctx, grantees[i])
case strings.HasPrefix(grantees[i], grantPrefix+"g:"):
gr := strings.TrimPrefix(grantees[i], grantPrefix+"g:")
case strings.HasPrefix(grantees[i], grantPrefix+_groupAcePrefix):
gr := strings.TrimPrefix(grantees[i], grantPrefix+_groupAcePrefix)
if groupsMap[gr] {
g, err = cn.ReadGrant(ctx, grantees[i])
} else {
Expand Down