Skip to content

Commit

Permalink
Merge pull request #5453 from owncloud/space-member-expiration
Browse files Browse the repository at this point in the history
add an expiration to the space member permissions
  • Loading branch information
David Christofas authored Feb 9, 2023
2 parents 26f7523 + b6ea8a8 commit ef37f66
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 104 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/blevesearch/bleve/v2 v2.3.5
github.com/coreos/go-oidc/v3 v3.4.0
github.com/cs3org/go-cs3apis v0.0.0-20221012090518-ef2996678965
github.com/cs3org/reva/v2 v2.12.1-0.20230203122123-cd2b2a5feca9
github.com/cs3org/reva/v2 v2.12.1-0.20230208154945-81b9c3e9d310
github.com/disintegration/imaging v1.6.2
github.com/ggwhite/go-masker v1.0.9
github.com/go-chi/chi/v5 v5.0.7
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@ github.com/bwesterb/go-ristretto v1.2.1/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7N
github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=
github.com/c0rby/go-cs3apis v0.0.0-20230110100311-5b424f1baa35 h1:bbpRY/l4z5MTH+TRGZdkIqDM9JXQQewJdO1o+80zcok=
github.com/c0rby/go-cs3apis v0.0.0-20230110100311-5b424f1baa35/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/c0rby/reva/v2 v2.0.0-20230125143632-a7e24c8dd66b h1:PKbmBHmUzd5d9GdpBlJY2p0a3dqg7YboEYg0Kolt3xs=
github.com/c0rby/reva/v2 v2.0.0-20230125143632-a7e24c8dd66b/go.mod h1:u73Df9JAZsDj43GIjQIb3DO1PLJuPutZXkRqQH0oGXA=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
Expand Down Expand Up @@ -343,8 +345,8 @@ github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3p
github.com/crewjam/saml v0.4.6/go.mod h1:ZBOXnNPFzB3CgOkRm7Nd6IVdkG+l/wF+0ZXLqD96t1A=
github.com/crewjam/saml v0.4.9 h1:X2jDv4dv3IvfT9t+RhADavzNFAcq3fVxzTCIH3G605U=
github.com/crewjam/saml v0.4.9/go.mod h1:9Zh6dWPtB3MSzTRt8fIFH60Z351QQ+s7hCU3J/tTlA4=
github.com/cs3org/reva/v2 v2.12.1-0.20230203122123-cd2b2a5feca9 h1:iokM4RfMgO0HhIERr1MWjRJkIwTt4XhL3fOSc3emlhY=
github.com/cs3org/reva/v2 v2.12.1-0.20230203122123-cd2b2a5feca9/go.mod h1:u73Df9JAZsDj43GIjQIb3DO1PLJuPutZXkRqQH0oGXA=
github.com/cs3org/reva/v2 v2.12.1-0.20230208154945-81b9c3e9d310 h1:UIsxP51vo9Z7OJTclC6yYetgtAPZaoLJ8d41c6WkT+o=
github.com/cs3org/reva/v2 v2.12.1-0.20230208154945-81b9c3e9d310/go.mod h1:u73Df9JAZsDj43GIjQIb3DO1PLJuPutZXkRqQH0oGXA=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
Expand Down
209 changes: 108 additions & 101 deletions services/graph/pkg/service/v0/drives.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"sort"
"strconv"
"strings"
"time"

"github.com/CiscoM31/godata"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
Expand Down Expand Up @@ -540,107 +541,7 @@ func (g Graph) cs3StorageSpaceToDrive(ctx context.Context, baseURL *url.URL, spa
}
spaceID := storagespace.FormatResourceID(spaceRid)

var permissions []libregraph.Permission
if space.Opaque != nil {
var permissionsMap map[string]*storageprovider.ResourcePermissions
var groupsMap map[string]struct{}

opaqueGrants, ok := space.Opaque.Map["grants"]
if ok {
err := json.Unmarshal(opaqueGrants.Value, &permissionsMap)
if err != nil {
logger.Debug().
Err(err).
Interface("space", space.Root).
Bytes("grants", opaqueGrants.Value).
Msg("unable to parse space: failed to read spaces grants")
}
}

opaqueGroups, ok := space.Opaque.Map["groups"]
if ok {
err := json.Unmarshal(opaqueGroups.Value, &groupsMap)
if err != nil {
logger.Debug().
Err(err).
Interface("space", space.Root).
Bytes("groups", opaqueGroups.Value).
Msg("unable to parse space: failed to read spaces groups")
}
}

if len(permissionsMap) != 0 {
managerIdentities := []libregraph.IdentitySet{}
editorIdentities := []libregraph.IdentitySet{}
viewerIdentities := []libregraph.IdentitySet{}

for id, perm := range permissionsMap {
// This temporary variable is necessary since we need to pass a pointer to the
// libregraph.Identity and if we pass the pointer from the loop every identity
// will have the same id.
tmp := id
var identitySet libregraph.IdentitySet
if _, ok := groupsMap[id]; ok {
var group libregraph.Group
if item := g.groupsCache.Get(id); item == nil {
if requestedGroup, err := g.identityBackend.GetGroup(ctx, id, url.Values{}); err == nil {
group = *requestedGroup
g.groupsCache.Set(id, group, ttlcache.DefaultTTL)
}
} else {
group = item.Value()
}

identitySet = libregraph.IdentitySet{Group: &libregraph.Identity{Id: &tmp, DisplayName: group.GetDisplayName()}}
} else {
var user libregraph.User
if item := g.usersCache.Get(id); item == nil {
if requestedUser, err := g.identityBackend.GetUser(ctx, id, &godata.GoDataRequest{}); err == nil {
user = *requestedUser
g.usersCache.Set(id, user, ttlcache.DefaultTTL)
}
} else {
user = item.Value()
}

identitySet = libregraph.IdentitySet{User: &libregraph.Identity{Id: &tmp, DisplayName: user.GetDisplayName()}}
}

// we need to map the permissions to the roles
switch {
// having RemoveGrant qualifies you as a manager
case perm.RemoveGrant:
managerIdentities = append(managerIdentities, identitySet)
// InitiateFileUpload means you are an editor
case perm.InitiateFileUpload:
editorIdentities = append(editorIdentities, identitySet)
// Stat permission at least makes you a viewer
case perm.Stat:
viewerIdentities = append(viewerIdentities, identitySet)
}
}

permissions = make([]libregraph.Permission, 0, 3)
if len(managerIdentities) != 0 {
permissions = append(permissions, libregraph.Permission{
GrantedToIdentities: managerIdentities,
Roles: []string{"manager"},
})
}
if len(editorIdentities) != 0 {
permissions = append(permissions, libregraph.Permission{
GrantedToIdentities: editorIdentities,
Roles: []string{"editor"},
})
}
if len(viewerIdentities) != 0 {
permissions = append(permissions, libregraph.Permission{
GrantedToIdentities: viewerIdentities,
Roles: []string{"viewer"},
})
}
}
}
permissions := g.cs3PermissionsToLibreGraph(ctx, space)

drive := &libregraph.Drive{
Id: libregraph.PtrString(spaceID),
Expand Down Expand Up @@ -736,6 +637,112 @@ func (g Graph) cs3StorageSpaceToDrive(ctx context.Context, baseURL *url.URL, spa
return drive, nil
}

func (g Graph) cs3PermissionsToLibreGraph(ctx context.Context, space *storageprovider.StorageSpace) []libregraph.Permission {
if space.Opaque == nil {
return nil
}
logger := g.logger.SubloggerWithRequestID(ctx)

var permissionsMap map[string]*storageprovider.ResourcePermissions
opaqueGrants, ok := space.Opaque.Map["grants"]
if ok {
err := json.Unmarshal(opaqueGrants.Value, &permissionsMap)
if err != nil {
logger.Debug().
Err(err).
Interface("space", space.Root).
Bytes("grants", opaqueGrants.Value).
Msg("unable to parse space: failed to read spaces grants")
}
}
if len(permissionsMap) == 0 {
return nil
}

var permissionsExpirations map[string]*types.Timestamp
opaqueGrantsExpirations, ok := space.Opaque.Map["grants_expirations"]
if ok {
err := json.Unmarshal(opaqueGrantsExpirations.Value, &permissionsExpirations)
if err != nil {
logger.Debug().
Err(err).
Interface("space", space.Root).
Bytes("grants_expirations", opaqueGrantsExpirations.Value).
Msg("unable to parse space: failed to read spaces grants expirations")
}
}

var groupsMap map[string]struct{}
opaqueGroups, ok := space.Opaque.Map["groups"]
if ok {
err := json.Unmarshal(opaqueGroups.Value, &groupsMap)
if err != nil {
logger.Debug().
Err(err).
Interface("space", space.Root).
Bytes("groups", opaqueGroups.Value).
Msg("unable to parse space: failed to read spaces groups")
}
}

permissions := make([]libregraph.Permission, 0, len(permissionsMap))
for id, perm := range permissionsMap {
// This temporary variable is necessary since we need to pass a pointer to the
// libregraph.Identity and if we pass the pointer from the loop every identity
// will have the same id.
tmp := id
var identitySet libregraph.IdentitySet
if _, ok := groupsMap[id]; ok {
var group libregraph.Group
if item := g.groupsCache.Get(id); item == nil {
if requestedGroup, err := g.identityBackend.GetGroup(ctx, id, url.Values{}); err == nil {
group = *requestedGroup
g.groupsCache.Set(id, group, ttlcache.DefaultTTL)
}
} else {
group = item.Value()
}

identitySet = libregraph.IdentitySet{Group: &libregraph.Identity{Id: &tmp, DisplayName: group.GetDisplayName()}}
} else {
var user libregraph.User
if item := g.usersCache.Get(id); item == nil {
if requestedUser, err := g.identityBackend.GetUser(ctx, id, &godata.GoDataRequest{}); err == nil {
user = *requestedUser
g.usersCache.Set(id, user, ttlcache.DefaultTTL)
}
} else {
user = item.Value()
}

identitySet = libregraph.IdentitySet{User: &libregraph.Identity{Id: &tmp, DisplayName: user.GetDisplayName()}}
}

p := libregraph.Permission{
GrantedToIdentities: []libregraph.IdentitySet{identitySet},
}

if exp := permissionsExpirations[id]; exp != nil {
p.ExpirationDateTime = libregraph.PtrTime(time.Unix(int64(exp.GetSeconds()), int64(exp.GetNanos())))
}

// we need to map the permissions to the roles
switch {
// having RemoveGrant qualifies you as a manager
case perm.RemoveGrant:
p.SetRoles([]string{"manager"})
// InitiateFileUpload means you are an editor
case perm.InitiateFileUpload:
p.SetRoles([]string{"editor"})
// Stat permission at least makes you a viewer
case perm.Stat:
p.SetRoles([]string{"viewer"})
}
permissions = append(permissions, p)
}
return permissions
}

func (g Graph) getDriveQuota(ctx context.Context, space *storageprovider.StorageSpace) (libregraph.Quota, error) {
logger := g.logger.SubloggerWithRequestID(ctx)
client := g.GetGatewayClient()
Expand Down

0 comments on commit ef37f66

Please sign in to comment.