Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
7 changes: 4 additions & 3 deletions internal/grpc/services/usershareprovider/usershareprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,9 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar
user := ctxpkg.ContextMustGetUser(ctx)
// check if the grantee is a user or group
if req.GetGrant().GetGrantee().GetType() == provider.GranteeType_GRANTEE_TYPE_USER {
// check if the tenantId of the user matches the tenantId of the target user
if user.GetId().GetTenantId() != req.GetGrant().GetGrantee().GetUserId().GetTenantId() {
// check if the tenantId of the user matches the tenantId of the target user, skipping guests
if req.GetGrant().GetGrantee().GetUserId().GetType() != userpb.UserType_USER_TYPE_GUEST &&
user.GetId().GetTenantId() != req.GetGrant().GetGrantee().GetUserId().GetTenantId() {
log.Warn().Msg("user tenantId does not match the target user tenantId, this is not supported yet")
return &collaboration.CreateShareResponse{
Status: status.NewPermissionDenied(ctx, nil, "user tenantId does not match the target user tenantId"),
Expand Down Expand Up @@ -206,7 +207,7 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar
UserId: &userpb.UserId{
OpaqueId: req.GetGrant().GetGrantee().GetUserId().GetOpaqueId(),
Idp: user.GetId().GetIdp(),
Type: userpb.UserType_USER_TYPE_PRIMARY},
Type: req.GetGrant().GetGrantee().GetUserId().GetType()},
}
}
// some for group grantees
Expand Down
23 changes: 23 additions & 0 deletions internal/grpc/services/usershareprovider/usershareprovider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ var _ = Describe("user share provider service", func() {
Entry("ListGrants", conversions.RoleFromName("manager").CS3ResourcePermissions(), &providerpb.ResourcePermissions{ListGrants: true}, rpcpb.Code_CODE_OK, 1),
)
})

Context("create share with tenant awareness", func() {
JustBeforeEach(func() {
rgrpcService := usershareprovider.New(gatewaySelector, manager, []*regexp.Regexp{})
Expand Down Expand Up @@ -490,6 +491,28 @@ var _ = Describe("user share provider service", func() {

manager.AssertNumberOfCalls(GinkgoT(), "Share", 1)
})

It("succeeds when sharing with a guest using an email address", func() {
createShareResponse, err := provider.CreateShare(ctx, &collaborationpb.CreateShareRequest{
ResourceInfo: &providerpb.ResourceInfo{
PermissionSet: conversions.RoleFromName("manager").CS3ResourcePermissions(),
},
Grant: &collaborationpb.ShareGrant{
Grantee: &providerpb.Grantee{
Type: providerpb.GranteeType_GRANTEE_TYPE_USER,
Id: &providerpb.Grantee_UserId{UserId: &userpb.UserId{OpaqueId: "[email protected]", Type: userpb.UserType_USER_TYPE_GUEST}},
},
Permissions: &collaborationpb.SharePermissions{
Permissions: conversions.RoleFromName("viewer").CS3ResourcePermissions(),
},
},
})

Expect(err).ToNot(HaveOccurred())
Expect(createShareResponse.Status.Code).To(Equal(rpcpb.Code_CODE_OK))

manager.AssertNumberOfCalls(GinkgoT(), "Share", 1)
})
})
})

Expand Down
9 changes: 8 additions & 1 deletion pkg/storage/fs/posix/tree/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,14 @@ func New(lu node.PathLookup, bs node.Blobstore, um usermapper.Mapper, trashbin *
return nil, err
}
case "natswatcher":
t.watcher, err = natswatcher.New(context.TODO(), t, o.NatsWatcher, o.WatchRoot, log)
cfg := options.NatsWatcherConfig{
Endpoint: "nats://localhost:9233",
Cluster: "test-cluster",
Durable: "natswatcher",
Stream: "leilfs-events",
TLSInsecure: true,
}
t.watcher, err = natswatcher.New(context.TODO(), t, cfg, o.WatchRoot, log)
Comment thread
micbar marked this conversation as resolved.
Outdated
if err != nil {
return nil, err
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/storage/pkg/decomposedfs/decomposedfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ type Decomposedfs struct {
UserCache *ttlcache.Cache
userSpaceIndex *spaceidindex.Index
groupSpaceIndex *spaceidindex.Index
mailSpaceIndex *spaceidindex.Index
spaceTypeIndex *spaceidindex.Index

log *zerolog.Logger
Expand Down Expand Up @@ -216,6 +217,11 @@ func New(o *options.Options, aspects aspects.Aspects, log *zerolog.Logger) (stor
if err != nil {
return nil, err
}
mailSpaceIndex := spaceidindex.New(filepath.Join(o.Root, "indexes"), "by-mail")
err = mailSpaceIndex.Init()
if err != nil {
return nil, err
}
spaceTypeIndex := spaceidindex.New(filepath.Join(o.Root, "indexes"), "by-type")
err = spaceTypeIndex.Init()
if err != nil {
Expand All @@ -242,6 +248,7 @@ func New(o *options.Options, aspects aspects.Aspects, log *zerolog.Logger) (stor
UserCache: ttlcache.NewCache(),
userSpaceIndex: userSpaceIndex,
groupSpaceIndex: groupSpaceIndex,
mailSpaceIndex: mailSpaceIndex,
spaceTypeIndex: spaceTypeIndex,
log: log,
}
Expand Down
11 changes: 9 additions & 2 deletions pkg/storage/pkg/decomposedfs/grants.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"path/filepath"
"strings"

userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/opencloud-eu/reva/v2/internal/grpc/services/storageprovider"
"github.com/opencloud-eu/reva/v2/pkg/appctx"
Expand Down Expand Up @@ -235,8 +236,14 @@ func (fs *Decomposedfs) RemoveGrant(ctx context.Context, ref *provider.Reference
switch g.Grantee.Type {
case provider.GranteeType_GRANTEE_TYPE_USER:
// remove from user index
if err := fs.userSpaceIndex.Remove(g.Grantee.GetUserId().GetOpaqueId(), grantNode.SpaceID); err != nil {
return err
if g.Grantee.GetUserId().GetType() == userpb.UserType_USER_TYPE_GUEST {
if err := fs.mailSpaceIndex.Remove(g.Grantee.GetUserId().GetOpaqueId(), grantNode.SpaceID); err != nil {
return err
}
} else {
if err := fs.userSpaceIndex.Remove(g.Grantee.GetUserId().GetOpaqueId(), grantNode.SpaceID); err != nil {
return err
}
}
case provider.GranteeType_GRANTEE_TYPE_GROUP:
// remove from group index
Expand Down
48 changes: 40 additions & 8 deletions pkg/storage/pkg/decomposedfs/grants_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,24 @@ import (

var _ = Describe("Grants", func() {
var (
env *helpers.DecomposedTestEnv
ref *provider.Reference
grant *provider.Grant
env *helpers.DecomposedTestEnv
ref *provider.Reference
grant *provider.Grant
userid *userpb.UserId
)

BeforeEach(func() {
userid = &userpb.UserId{
OpaqueId: "4c510ada-c86b-4815-8820-42cdf82c3d51",
}
})

JustBeforeEach(func() {
grant = &provider.Grant{
Grantee: &provider.Grantee{
Type: provider.GranteeType_GRANTEE_TYPE_USER,
Id: &provider.Grantee_UserId{
UserId: &userpb.UserId{
OpaqueId: "4c510ada-c86b-4815-8820-42cdf82c3d51",
},
UserId: userid,
},
},
Permissions: &provider.ResourcePermissions{
Expand All @@ -59,9 +64,7 @@ var _ = Describe("Grants", func() {
OpaqueId: helpers.OwnerID,
},
}
})

JustBeforeEach(func() {
var err error
env, err = helpers.NewTestEnv(nil)
Expect(err).ToNot(HaveOccurred())
Expand Down Expand Up @@ -178,5 +181,34 @@ var _ = Describe("Grants", func() {
Expect(len(grants)).To(Equal(0))
})
})

Context("with guest grants", func() {
BeforeEach(func() {
userid = &userpb.UserId{
OpaqueId: "[email protected]",
Type: userpb.UserType_USER_TYPE_GUEST,
}
})

It("adds, lists and removes the guest grant", func() {
err := env.Fs.AddGrant(env.Ctx, ref, grant)
Expect(err).ToNot(HaveOccurred())

grants, err := env.Fs.ListGrants(env.Ctx, ref)
Expect(err).ToNot(HaveOccurred())
Expect(len(grants)).To(Equal(1))

g := grants[0]
Expect(g.Grantee.GetUserId().OpaqueId).To(Equal(grant.Grantee.GetUserId().OpaqueId))
Expect(g.Grantee.GetUserId().Type).To(Equal(userpb.UserType_USER_TYPE_GUEST))

err = env.Fs.RemoveGrant(env.Ctx, ref, grant)
Expect(err).ToNot(HaveOccurred())

grants, err = env.Fs.ListGrants(env.Ctx, ref)
Expect(err).ToNot(HaveOccurred())
Expect(len(grants)).To(Equal(0))
})
})
})
})
2 changes: 2 additions & 0 deletions pkg/storage/pkg/decomposedfs/metadata/prefixes/prefixes.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const (
GrantPrefix string = OcPrefix + "grant."
GrantUserAcePrefix string = OcPrefix + "grant." + UserAcePrefix
GrantGroupAcePrefix string = OcPrefix + "grant." + GroupAcePrefix
GrantMailAcePrefix string = OcPrefix + "grant." + MailAcePrefix
MetadataPrefix string = OcPrefix + "md."

// favorite flag, per user
Expand Down Expand Up @@ -105,6 +106,7 @@ const (

UserAcePrefix string = "u:"
GroupAcePrefix string = "g:"
MailAcePrefix string = "m:"
)

func FavoriteKey(uid *userpb.UserId) string {
Expand Down
11 changes: 8 additions & 3 deletions pkg/storage/pkg/decomposedfs/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -1234,10 +1234,15 @@ func (n *Node) ReadGrant(ctx context.Context, grantee string) (g *provider.Grant
func (n *Node) DeleteGrant(ctx context.Context, g *provider.Grant, acquireLock bool) (err error) {

var attr string
if g.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_GROUP {
switch g.Grantee.Type {
case provider.GranteeType_GRANTEE_TYPE_GROUP:
attr = prefixes.GrantGroupAcePrefix + g.Grantee.GetGroupId().OpaqueId
} else {
attr = prefixes.GrantUserAcePrefix + g.Grantee.GetUserId().OpaqueId
default:
prefix := prefixes.GrantUserAcePrefix
if g.Grantee.GetUserId().GetType() == userpb.UserType_USER_TYPE_GUEST {
prefix = prefixes.GrantMailAcePrefix
}
attr = prefix + g.Grantee.GetUserId().OpaqueId
}

if err = n.RemoveXattr(ctx, attr, acquireLock); err != nil {
Expand Down
23 changes: 19 additions & 4 deletions pkg/storage/pkg/decomposedfs/spaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,9 @@ func (fs *Decomposedfs) updateIndexes(ctx context.Context, grantee *provider.Gra
// create space grant index
switch grantee.Type {
case provider.GranteeType_GRANTEE_TYPE_USER:
if grantee.GetUserId().GetType() == userv1beta1.UserType_USER_TYPE_GUEST {
return fs.linkSpaceByMail(ctx, grantee.GetUserId().GetOpaqueId(), spaceID, target)
}
return fs.linkSpaceByUser(ctx, grantee.GetUserId().GetOpaqueId(), spaceID, target)
case provider.GranteeType_GRANTEE_TYPE_GROUP:
return fs.linkSpaceByGroup(ctx, grantee.GetGroupId().GetOpaqueId(), spaceID, target)
Expand All @@ -870,6 +873,10 @@ func (fs *Decomposedfs) linkSpaceByGroup(ctx context.Context, groupID, spaceID,
return fs.groupSpaceIndex.Add(groupID, spaceID, target)
}

func (fs *Decomposedfs) linkSpaceByMail(ctx context.Context, mail, spaceID, target string) error {
return fs.mailSpaceIndex.Add(mail, spaceID, target)
}

func (fs *Decomposedfs) linkStorageSpaceType(ctx context.Context, spaceType, spaceID, target string) error {
return fs.spaceTypeIndex.Add(spaceType, spaceID, target)
}
Expand Down Expand Up @@ -943,10 +950,18 @@ func (fs *Decomposedfs) StorageSpaceFromNode(ctx context.Context, n *node.Node,
// invalidate space grant
switch g.Grantee.Type {
case provider.GranteeType_GRANTEE_TYPE_USER:
// remove from user index
if err := fs.userSpaceIndex.Remove(g.Grantee.GetUserId().GetOpaqueId(), n.GetSpaceID()); err != nil {
sublog.Error().Err(err).Str("grantee", id).
Msg("failed to delete expired user space index")
if g.Grantee.GetUserId().GetType() == userv1beta1.UserType_USER_TYPE_GUEST {
// remove from mail index
if err := fs.mailSpaceIndex.Remove(g.Grantee.GetUserId().GetOpaqueId(), n.GetSpaceID()); err != nil {
sublog.Error().Err(err).Str("grantee", id).
Msg("failed to delete expired mail space index")
}
} else {
// remove from user index
if err := fs.userSpaceIndex.Remove(g.Grantee.GetUserId().GetOpaqueId(), n.GetSpaceID()); err != nil {
sublog.Error().Err(err).Str("grantee", id).
Msg("failed to delete expired user space index")
}
}
case provider.GranteeType_GRANTEE_TYPE_GROUP:
// remove from group index
Expand Down
15 changes: 12 additions & 3 deletions pkg/storage/utils/ace/ace.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,12 @@ func FromGrant(g *provider.Grant) *ACE {
}

func UserAce(id *userpb.UserId) string {
return "u:" + id.OpaqueId
switch id.GetType() {
case userpb.UserType_USER_TYPE_GUEST:
return "m:" + strings.ToLower(id.OpaqueId)
default:
return "u:" + id.OpaqueId
}
}

// Principal returns the principal of the ACE, eg. `u:<userid>` or `g:<groupid>`
Expand Down Expand Up @@ -260,7 +265,7 @@ func Unmarshal(principal string, v []byte) (e *ACE, err error) {
return nil, fmt.Errorf("inconsistent ace: expected group")
}
} else {
if principal[:1] != "u" {
if principal[:1] != "u" && principal[:1] != "m" {
return nil, fmt.Errorf("inconsistent ace: expected user")
}
}
Expand Down Expand Up @@ -288,7 +293,11 @@ func (e *ACE) Grant() *provider.Grant {
if e.granteeType() == provider.GranteeType_GRANTEE_TYPE_GROUP {
g.Grantee.Id = &provider.Grantee_GroupId{GroupId: &grouppb.GroupId{OpaqueId: id}}
} else if e.granteeType() == provider.GranteeType_GRANTEE_TYPE_USER {
g.Grantee.Id = &provider.Grantee_UserId{UserId: &userpb.UserId{OpaqueId: id}}
if strings.HasPrefix(e.principal, "m:") {
g.Grantee.Id = &provider.Grantee_UserId{UserId: &userpb.UserId{OpaqueId: id, Type: userpb.UserType_USER_TYPE_GUEST}}
} else {
g.Grantee.Id = &provider.Grantee_UserId{UserId: &userpb.UserId{OpaqueId: id, Type: userpb.UserType_USER_TYPE_PRIMARY}}
}
}

if e.expires != 0 {
Expand Down
Loading