Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,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_GUEST,
Id: &providerpb.Grantee_Email{Email: "guest@example.com"},
},
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)
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: "foo@example.com",
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:" + 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
37 changes: 37 additions & 0 deletions pkg/storage/utils/ace/ace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ var _ = Describe("ACE", func() {
Permissions: &provider.ResourcePermissions{
CreateContainer: true,
},
Creator: &userpb.UserId{},
}

guestGrant = &provider.Grant{
Grantee: &provider.Grantee{
Type: provider.GranteeType_GRANTEE_TYPE_MAIL,
Id: &provider.Grantee_Mail{
Mail: "guest@example.com",
},
},
Permissions: &provider.ResourcePermissions{
CreateContainer: true,
},
Creator: &userpb.UserId{},
}
)

Expand All @@ -76,6 +90,12 @@ var _ = Describe("ACE", func() {
ace := ace.FromGrant(groupGrant)
Expect(ace.Principal()).To(Equal("g:foo"))
})

It("creates an ACE from a guest grant", func() {
guestGrant.Grantee.Id = &provider.Grantee_Mail{Mail: "GUEST@example.com"}
ace := ace.FromGrant(guestGrant)
Expect(ace.Principal()).To(Equal("m:guest@example.com"))
})
})

Describe("Grant", func() {
Expand All @@ -86,6 +106,23 @@ var _ = Describe("ACE", func() {
grant.Grantee.Opaque = nil
Expect(grant).To(BeComparableTo(userGrant, protocmp.Transform()))
})

It("returns a proper Grant for group ACE", func() {
ace := ace.FromGrant(groupGrant)
grant := ace.Grant()
// do not check opaque values
grant.Grantee.Opaque = nil
Expect(grant).To(BeComparableTo(groupGrant, protocmp.Transform()))
})

It("returns a proper Grant for guest ACE", func() {
guestGrant.Grantee.Id = &provider.Grantee_Mail{Mail: "guest@example.com"}
ace := ace.FromGrant(guestGrant)
grant := ace.Grant()
// do not check opaque values
grant.Grantee.Opaque = nil
Expect(grant).To(BeComparableTo(guestGrant, protocmp.Transform()))
})
})

Describe("marshalling", func() {
Expand Down