diff --git a/changelog/unreleased/ocis-ocs-share-types.md b/changelog/unreleased/ocis-ocs-share-types.md
new file mode 100644
index 0000000000..c185458b64
--- /dev/null
+++ b/changelog/unreleased/ocis-ocs-share-types.md
@@ -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
diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go
index 399ab087a4..7e376eea2b 100644
--- a/internal/grpc/services/gateway/storageprovider.go
+++ b/internal/grpc/services/gateway/storageprovider.go
@@ -1586,13 +1586,14 @@ func (s *svc) ListContainerStream(_ *provider.ListContainerStreamRequest, _ gate
return errors.New("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{
@@ -1726,7 +1727,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) {
diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go
index e6fbdd591f..58f8659ddc 100644
--- a/internal/http/services/owncloud/ocdav/propfind.go
+++ b/internal/http/services/owncloud/ocdav/propfind.go
@@ -107,6 +107,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 {
@@ -142,6 +145,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 {
@@ -283,7 +289,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)
@@ -441,6 +446,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("%s", 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
@@ -458,11 +472,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
- //
- // 1
- //
- fallthrough
default:
propstatNotFound.Prop = append(propstatNotFound.Prop, s.newProp("oc:"+pf.Prop[i].Local, ""))
}
diff --git a/pkg/storage/fs/ocis/node.go b/pkg/storage/fs/ocis/node.go
index 2a6d32ed67..f2215b4a94 100644
--- a/pkg/storage/fs/ocis/node.go
+++ b/pkg/storage/fs/ocis/node.go
@@ -34,12 +34,17 @@ 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"
+)
+
// Node represents a node in the tree and provides methods to get a Parent or Child instance
type Node struct {
lu *Lookup
@@ -279,7 +284,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
@@ -376,6 +381,9 @@ func (n *Node) AsResourceInfo(ctx context.Context) (ri *provider.ResourceInfo, e
for i := range attrs {
if strings.HasPrefix(attrs[i], metadataPrefix) {
k := strings.TrimPrefix(attrs[i], metadataPrefix)
+ if common.FindString(mdKeys, k) == -1 {
+ continue
+ }
if v, err := xattr.Get(nodePath, attrs[i]); err == nil {
ri.ArbitraryMetadata.Metadata[k] = string(v)
} else {
@@ -387,6 +395,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] = "0"
+ }
+ }
+
log.Debug().
Interface("ri", ri).
Msg("AsResourceInfo")
@@ -455,3 +469,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+"u") {
+ return true
+ }
+ }
+ return false
+}
diff --git a/pkg/storage/fs/ocis/ocis.go b/pkg/storage/fs/ocis/ocis.go
index 59f092997b..2cb9d2be10 100644
--- a/pkg/storage/fs/ocis/ocis.go
+++ b/pkg/storage/fs/ocis/ocis.go
@@ -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) {
@@ -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)
}
}