Skip to content

Commit

Permalink
Clean share client library and optimize root nodes loading
Browse files Browse the repository at this point in the history
  • Loading branch information
cdujeu committed Nov 18, 2024
1 parent 7d12a28 commit ad720a4
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 93 deletions.
9 changes: 6 additions & 3 deletions common/nodes/compose/reverse.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func ReverseClient(ctx context.Context, oo ...nodes.Option) *Reverse {
}
}

// WorkspaceCanSeeNode will check workspaces roots to see if a node in below one of them
// WorkspaceCanSeeNode checks if a node appears inside a workspace, and if so, returns the node with its path relative to this workspace
func (r *Reverse) WorkspaceCanSeeNode(ctx context.Context, accessList *permissions.AccessList, workspace *idm.Workspace, node *tree.Node) (*tree.Node, bool) {
if node == nil {
return node, false
Expand Down Expand Up @@ -109,7 +109,7 @@ func (r *Reverse) WorkspaceCanSeeNode(ctx context.Context, accessList *permissio
}
}
newNode := node.Clone()
r.WrapCallback(func(inputFilter nodes.FilterFunc, outputFilter nodes.FilterFunc) error {
_ = r.WrapCallback(func(inputFilter nodes.FilterFunc, outputFilter nodes.FilterFunc) error {
branchInfo := nodes.BranchInfo{}
branchInfo.Workspace = workspace
branchInfo.Root = parent
Expand Down Expand Up @@ -148,7 +148,10 @@ func (r *Reverse) getRoot(ctx context.Context, rootId string) *tree.Node {
if r.rootsCache.Get(rootId, &node) {
return node
}
resp, e := r.GetClientsPool().GetTreeClient().ReadNode(ctx, &tree.ReadNodeRequest{Node: &tree.Node{Uuid: rootId}})
resp, e := r.GetClientsPool().GetTreeClient().ReadNode(ctx, &tree.ReadNodeRequest{
Node: &tree.Node{Uuid: rootId},
StatFlags: []uint32{tree.StatFlagNone},
})
if e == nil && resp.Node != nil {
resp.Node.Path = strings.Trim(resp.Node.Path, "/")
r.rootsCache.Set(rootId, resp.Node.Clone())
Expand Down
13 changes: 10 additions & 3 deletions common/utils/permissions/access-list.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ package permissions

import (
"context"
"github.com/pydio/cells/v4/common/utils/std"
"sort"
"strings"
"sync"
Expand All @@ -35,8 +34,10 @@ import (
"github.com/pydio/cells/v4/common/log"
"github.com/pydio/cells/v4/common/proto/idm"
"github.com/pydio/cells/v4/common/proto/tree"
"github.com/pydio/cells/v4/common/service/context/metadata"
"github.com/pydio/cells/v4/common/utils/configx"
json "github.com/pydio/cells/v4/common/utils/jsonx"
"github.com/pydio/cells/v4/common/utils/std"
)

// PolicyResolver implements the check of an object against a set of ACL policies
Expand Down Expand Up @@ -450,6 +451,8 @@ func (a *AccessList) loadNodePathAcls(ctx context.Context, resolver VirtualPathR
a.maskBPLock.Lock()
defer a.maskBPLock.Unlock()

flagNone := tree.StatFlags([]uint32{tree.StatFlagNone})

a.masksByPaths = make(map[string]Bitmask, len(a.masksByUUIDs))
if len(a.masksByUUIDs) == 0 {
// Do not open an unnecessary stream...
Expand All @@ -458,7 +461,8 @@ func (a *AccessList) loadNodePathAcls(ctx context.Context, resolver VirtualPathR
cli := tree.NewNodeProviderStreamerClient(grpc.GetClientConnFromCtx(ctx, common.ServiceTree))
ct, ca := context.WithCancel(ctx)
defer ca()
st, e := cli.ReadNodeStream(ct)
// Set StatFlagNone in context for meta streamer underlying initialization
st, e := cli.ReadNodeStream(metadata.WithAdditionalMetadata(ct, flagNone.AsMeta()))
if e != nil {
return e
}
Expand All @@ -469,7 +473,10 @@ func (a *AccessList) loadNodePathAcls(ctx context.Context, resolver VirtualPathR
a.masksByPaths[strings.TrimSuffix(n.Path, "/")] = b
continue
}
err := st.Send(&tree.ReadNodeRequest{Node: &tree.Node{Uuid: nodeID}})
err := st.Send(&tree.ReadNodeRequest{
Node: &tree.Node{Uuid: nodeID},
StatFlags: flagNone,
})
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion data/search/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (s *Handler) sharedResourcesAsNodes(ctx context.Context, query *tree.Query)
query.FreeString = freeString

sc := share.NewClient(s.runtimeCtx, nil)
rr, e := sc.ListSharedResources(ctx, "", scope, true, resources.ResourceProviderHandler{})
rr, e := sc.ListSharedResources(ctx, "", scope, true, resources.ResourceProviderHandler{}, query.PathPrefix...)
if e != nil {
return nil, false, e
}
Expand Down
19 changes: 15 additions & 4 deletions idm/share/client-acls.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"google.golang.org/protobuf/types/known/anypb"

"github.com/pydio/cells/v4/common"
"github.com/pydio/cells/v4/common/auth"
"github.com/pydio/cells/v4/common/client/grpc"
"github.com/pydio/cells/v4/common/log"
"github.com/pydio/cells/v4/common/proto/idm"
Expand All @@ -51,6 +52,9 @@ func (sc *Client) WorkspaceToCellObject(ctx context.Context, workspace *idm.Work
return nil, err
}
log.Logger(ctx).Debug("Detected Roots for object", log.DangerouslyZapSmallSlice("roots", detectedRoots))
if len(detectedRoots) == 0 {
log.Logger(ctx).Warn("Empty detected roots for cell workspace", workspace.Zap())
}
roomAcls := sc.AclsToCellAcls(ctx, acls)

log.Logger(ctx).Debug("Computed roomAcls before load", zap.Any("roomAcls", roomAcls))
Expand All @@ -59,8 +63,15 @@ func (sc *Client) WorkspaceToCellObject(ctx context.Context, workspace *idm.Work
return nil, err
}
rootNodes := sc.LoadDetectedRootNodes(ctx, detectedRoots, accessList)
if len(rootNodes) == 0 {
log.Logger(ctx).Warn("Empty loaded roots for cell workspace", workspace.Zap(), log.DangerouslyZapSmallSlice("roots", detectedRoots))
}
var nodesSlices []*tree.Node
for _, node := range rootNodes {
if !sc.contextualizeRootToWorkspace(node, workspace.UUID) {
log.Logger(ctx).Warn("Loaded root node misses workspace relative path, ignoring!", node.Zap())
continue
}
nodesSlices = append(nodesSlices, node)
}

Expand Down Expand Up @@ -523,19 +534,19 @@ func (sc *Client) DeleteLinkWorkspace(ctx context.Context, workspaceId string) e

// DeleteWorkspace deletes a workspace and associated policies and ACLs. It also
// deletes the room node if necessary.
func (sc *Client) DeleteWorkspace(ctx context.Context, ownerLogin string, scope idm.WorkspaceScope, workspaceId string) error {
func (sc *Client) DeleteWorkspace(ctx context.Context, ownerUuid string, scope idm.WorkspaceScope, workspaceId string) error {

workspace, _, err := sc.GetOrCreateWorkspace(ctx, nil, workspaceId, scope, "", "", "", false)
if err != nil {
return err
}
if scope == idm.WorkspaceScope_ROOM {
// check if we must delete the room node
acl, _, er := permissions.AccessListFromUser(ctx, ownerLogin, false)
acl, ownerUser, er := permissions.AccessListFromUser(ctx, ownerUuid, true)
if er != nil {
return er
}
if output, err := sc.WorkspaceToCellObject(ctx, workspace, acl); err == nil {
if output, err := sc.WorkspaceToCellObject(auth.WithImpersonate(ctx, ownerUser), workspace, acl); err == nil {
log.Logger(ctx).Debug("Will Delete Workspace for Room", zap.Any("room", output))
var roomNode *tree.Node
for _, node := range output.RootNodes {
Expand All @@ -545,7 +556,7 @@ func (sc *Client) DeleteWorkspace(ctx context.Context, ownerLogin string, scope
}
}
if roomNode != nil {
if err := sc.DeleteRootNodeRecursively(ctx, ownerLogin, roomNode); err != nil {
if err := sc.DeleteRootNodeRecursively(ctx, ownerUser, roomNode); err != nil {
return err
}
}
Expand Down
4 changes: 3 additions & 1 deletion idm/share/client-front-configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ func (sc *Client) aclParams(ctx context.Context) (configx.Values, error) {
if e != nil {
return nil, e
}
permissions.AccessListLoadFrontValues(ctx, acl)
if er := permissions.AccessListLoadFrontValues(ctx, acl); er != nil {
return nil, er
}
return acl.FlattenedFrontValues().Val("parameters", "action.share"), nil
}

Expand Down
23 changes: 13 additions & 10 deletions idm/share/client-hidden-user.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,17 +239,20 @@ func (sc *Client) ClearLostHiddenUsers(ctx context.Context) error {
if er != nil {
break
}
if doc, er := sc.SearchHashDocumentForUser(ctx, resp.User.Login); er == nil && doc != nil {
log.Logger(ctx).Debug("Found Link for user", resp.User.ZapLogin(), zap.Any("doc", doc))
} else if er == nil && doc == nil {
deleteQ, _ := anypb.New(&idm.UserSingleQuery{Uuid: resp.User.Uuid})
if _, e := uClient.DeleteUser(ctx, &idm.DeleteUserRequest{Query: &service.Query{SubQueries: []*anypb.Any{deleteQ}}}); e != nil {
log.Logger(ctx).Error("Error while trying to delete lost hidden user", resp.User.ZapLogin(), zap.Error(e))
} else {
log.Logger(ctx).Info("Found and deleted hidden User without any link attached!", resp.User.ZapLogin())
}
} else if er != nil {
doc, er := sc.SearchHashDocumentForUser(ctx, resp.User.Login)
if er != nil {
log.Logger(ctx).Error("Cannot load docs for user", resp.User.ZapLogin(), zap.Error(er))
continue
}
if doc != nil {
log.Logger(ctx).Debug("Found Link for user", resp.User.ZapLogin(), zap.Any("doc", doc))
continue
}
deleteQ, _ := anypb.New(&idm.UserSingleQuery{Uuid: resp.User.Uuid})
if _, e := uClient.DeleteUser(ctx, &idm.DeleteUserRequest{Query: &service.Query{SubQueries: []*anypb.Any{deleteQ}}}); e != nil {
log.Logger(ctx).Error("Error while trying to delete lost hidden user", resp.User.ZapLogin(), zap.Error(e))
} else {
log.Logger(ctx).Info("Found and deleted hidden User without any link attached!", resp.User.ZapLogin())
}
}
return nil
Expand Down
9 changes: 7 additions & 2 deletions idm/share/client-list.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/pydio/cells/v4/common/auth"
"github.com/pydio/cells/v4/common/auth/claim"
"github.com/pydio/cells/v4/common/client/grpc"
"github.com/pydio/cells/v4/common/log"
"github.com/pydio/cells/v4/common/proto/idm"
"github.com/pydio/cells/v4/common/proto/rest"
service2 "github.com/pydio/cells/v4/common/proto/service"
Expand All @@ -44,7 +45,7 @@ type SharedResource struct {
}

// ListSharedResources lists all links and cells Owned by a given user
func (sc *Client) ListSharedResources(ctx context.Context, subject string, scope idm.WorkspaceScope, ownedBy bool, p resources.ResourceProviderHandler) ([]*SharedResource, error) {
func (sc *Client) ListSharedResources(ctx context.Context, subject string, scope idm.WorkspaceScope, ownedBy bool, p resources.ResourceProviderHandler, pathPrefixes ...string) ([]*SharedResource, error) {
var out []*SharedResource

var subjects []string
Expand Down Expand Up @@ -138,7 +139,11 @@ func (sc *Client) ListSharedResources(ctx context.Context, subject string, scope

// Build resources
for nodeId, node := range rootNodes {

// contextualize node to the first workspace found, favoring pathPrefixes
if replaced := sc.contextualizeRootToWorkspace(node, "", pathPrefixes...); !replaced {
log.Logger(ctx).Debug("Cannot contextualize node, ignoring node", node.Zap())
continue
}
resource := &SharedResource{
Node: node,
}
Expand Down
Loading

0 comments on commit ad720a4

Please sign in to comment.