72 lines
2.8 KiB
Diff
72 lines
2.8 KiB
Diff
# UNDF: UNDF-2026-000001025
|
|
--- a/backend/onedrive/metadata.go
|
|
+++ b/backend/onedrive/metadata.go
|
|
@@ -432,6 +432,24 @@ func (m *Metadata) sortPermissions() (add, update, remove []*api.PermissionsType
|
|
new, old := m.queuedPermissions, m.permissions
|
|
if len(old) == 0 || m.permsAddOnly {
|
|
m.orderPermissions(new)
|
|
return new, nil, nil // they must all be "add"
|
|
}
|
|
|
|
+ // Build O(1) lookup maps by permission ID to avoid O(P^2) nested scans.
|
|
+ // sortPermissions is called once per file when --metadata is set; large
|
|
+ // SharePoint sites can carry hundreds of permissions per document, making
|
|
+ // the original slices.ContainsFunc / slices.Contains calls O(P^2).
|
|
+ oldByID := make(map[string]*api.PermissionsType, len(old))
|
|
+ for _, o := range old {
|
|
+ if o != nil && o.ID != "" {
|
|
+ oldByID[o.ID] = o
|
|
+ }
|
|
+ }
|
|
+ newByID := make(map[string]*api.PermissionsType, len(new))
|
|
+ for _, n := range new {
|
|
+ if n != nil && n.ID != "" {
|
|
+ newByID[n.ID] = n
|
|
+ }
|
|
+ }
|
|
+ addSet := make(map[string]struct{}, len(new))
|
|
+ updateSet := make(map[string]struct{}, len(new))
|
|
+
|
|
for _, n := range new {
|
|
if n == nil {
|
|
continue
|
|
}
|
|
if n.ID != "" {
|
|
// sanity check: ensure there's a matching "old" id with a non-matching role
|
|
- if !slices.ContainsFunc(old, func(o *api.PermissionsType) bool {
|
|
- return o.ID == n.ID && slices.Compare(o.Roles, n.Roles) != 0 && len(o.Roles) > 0 && len(n.Roles) > 0 && !slices.Contains(o.Roles, api.OwnerRole)
|
|
- }) {
|
|
+ o, exists := oldByID[n.ID]
|
|
+ if !exists || !(slices.Compare(o.Roles, n.Roles) != 0 && len(o.Roles) > 0 && len(n.Roles) > 0 && !slices.Contains(o.Roles, api.OwnerRole)) {
|
|
fs.Debugf(m.remote, "skipping update for invalid roles: %v (perm ID: %v)", n.Roles, n.ID)
|
|
continue
|
|
}
|
|
@@ -462,12 +480,14 @@ func (m *Metadata) sortPermissions() (add, update, remove []*api.PermissionsType
|
|
fs.Debugf(m.remote, "sortPermissions: will update role to %v", n.Roles)
|
|
update = append(update, n)
|
|
+ updateSet[n.ID] = struct{}{}
|
|
} else {
|
|
fs.Debugf(m.remote, "sortPermissions: will add permission: %v %v", n, n.Roles)
|
|
add = append(add, n)
|
|
+ addSet[n.ID] = struct{}{}
|
|
}
|
|
}
|
|
for _, o := range old {
|
|
if slices.Contains(o.Roles, api.OwnerRole) {
|
|
fs.Debugf(m.remote, "skipping remove permission -- can't remove 'owner' role")
|
|
continue
|
|
}
|
|
- newHasOld := slices.ContainsFunc(new, func(n *api.PermissionsType) bool {
|
|
- if n == nil || n.ID == "" {
|
|
- return false // can't remove perms without an ID
|
|
- }
|
|
- return n.ID == o.ID
|
|
- })
|
|
- if !newHasOld && o.ID != "" && !slices.Contains(add, o) && !slices.Contains(update, o) {
|
|
+ _, newHasOld := newByID[o.ID]
|
|
+ _, inAdd := addSet[o.ID]
|
|
+ _, inUpdate := updateSet[o.ID]
|
|
+ if !newHasOld && o.ID != "" && !inAdd && !inUpdate {
|
|
fs.Debugf(m.remote, "sortPermissions: will remove permission: %v %v (perm ID: %v)", o, o.Roles, o.ID)
|
|
remove = append(remove, o)
|
|
}
|