From a11a492c5c93d76b22f58ccb48d566b15782f9d9 Mon Sep 17 00:00:00 2001 From: David Christofas Date: Fri, 25 Mar 2022 17:09:38 +0100 Subject: [PATCH] enable all space members to see shares --- changelog/unreleased/spaces-shares.md | 7 +++ .../handlers/apps/sharing/shares/spaces.go | 7 ++- pkg/share/manager/json/json.go | 44 +++++++++++++++++-- 3 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 changelog/unreleased/spaces-shares.md diff --git a/changelog/unreleased/spaces-shares.md b/changelog/unreleased/spaces-shares.md new file mode 100644 index 00000000000..47c02f66874 --- /dev/null +++ b/changelog/unreleased/spaces-shares.md @@ -0,0 +1,7 @@ +Enhancement: Enable space members to list shares inside the space + +If there are shared resources in a space then all members are allowed to see those shares. +The json share manager was enhanced to check if the user is allowed to see a share by checking the grants on a resource. + +https://github.com/owncloud/ocis/issues/3370 +https://github.com/cs3org/reva/pull/2674 diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go index 60e332387b9..d91a9e1b4b3 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go @@ -95,11 +95,16 @@ func (h *Handler) addSpaceMember(w http.ResponseWriter, r *http.Request, info *p return } + permissions := role.CS3ResourcePermissions() + // All members of a space should be able to list shares inside that space. + // The viewer role doesn't have the ListGrants permission so we set it here. + permissions.ListGrants = true + createShareRes, err := client.CreateShare(ctx, &collaborationv1beta1.CreateShareRequest{ ResourceInfo: info, Grant: &collaborationv1beta1.ShareGrant{ Permissions: &collaborationv1beta1.SharePermissions{ - Permissions: role.CS3ResourcePermissions(), + Permissions: permissions, }, Grantee: &grantee, }, diff --git a/pkg/share/manager/json/json.go b/pkg/share/manager/json/json.go index deb09582d2b..68b66ffe74e 100644 --- a/pkg/share/manager/json/json.go +++ b/pkg/share/manager/json/json.go @@ -24,15 +24,19 @@ import ( "io/fs" "io/ioutil" "os" + "strings" "sync" "time" userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" + "github.com/cs3org/reva/v2/pkg/appctx" ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/errtypes" + "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/v2/pkg/share" "github.com/google/uuid" "github.com/mitchellh/mapstructure" @@ -55,6 +59,10 @@ func New(m map[string]interface{}) (share.Manager, error) { return nil, err } + if c.GatewayAddr == "" { + return nil, errors.New("share manager config is missing gateway address") + } + c.init() // load or create file @@ -161,7 +169,8 @@ type mgr struct { } type config struct { - File string `mapstructure:"file"` + File string `mapstructure:"file"` + GatewayAddr string `mapstructure:"gateway_addr"` } func (c *config) init() { @@ -335,12 +344,41 @@ func (m *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference } func (m *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.Share, error) { - var ss []*collaboration.Share m.Lock() defer m.Unlock() + log := appctx.GetLogger(ctx) user := ctxpkg.ContextMustGetUser(ctx) + + client, err := pool.GetGatewayServiceClient(m.c.GatewayAddr) + if err != nil { + return nil, errors.Wrap(err, "failed to list shares") + } + cache := make(map[string]struct{}) + var ss []*collaboration.Share for _, s := range m.model.Shares { - if share.IsCreatedByUser(s, user) && share.MatchesFilters(s, filters) { + if share.MatchesFilters(s, filters) { + // Only add the share if the share was created by the user or if + // the user has ListGrants permissions on the shared resource. + // The ListGrants check is necessary when a space member wants + // to list shares in a space. + // We are using a cache here so that we don't have to stat a + // resource multiple times. + key := strings.Join([]string{s.ResourceId.StorageId, s.ResourceId.OpaqueId}, "!") + if _, hit := cache[key]; !hit && !share.IsCreatedByUser(s, user) { + sRes, err := client.Stat(ctx, &provider.StatRequest{Ref: &provider.Reference{ResourceId: s.ResourceId}}) + if err != nil || sRes.Status.Code != rpcv1beta1.Code_CODE_OK { + log.Error(). + Err(err). + Interface("status", sRes.Status). + Interface("resource_id", s.ResourceId). + Msg("ListShares: could not stat resource") + continue + } + if !sRes.Info.PermissionSet.ListGrants { + continue + } + cache[key] = struct{}{} + } ss = append(ss, s) } }