summaryrefslogtreecommitdiffstats
path: root/apps/user_ldap
diff options
context:
space:
mode:
authorArthur Schiwon <blizzz@arthur-schiwon.de>2021-12-12 14:09:16 +0100
committerCarl Schwan <carl@carlschwan.eu>2022-10-20 12:08:09 +0200
commit1e4ac22c946969088a2265730095775e8fc5c645 (patch)
tree53b92f0ab673bf2c8e1fd7a33a43a2e2c2ee7d7d /apps/user_ldap
parent53b6d67bc19dfb75b6be64cae9ffeaf6fbfbdd6d (diff)
downloadnextcloud-server-1e4ac22c946969088a2265730095775e8fc5c645.tar.gz
nextcloud-server-1e4ac22c946969088a2265730095775e8fc5c645.zip
Make it possible to return nested records whem walking over groups
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
Diffstat (limited to 'apps/user_ldap')
-rw-r--r--apps/user_ldap/lib/Group_LDAP.php47
1 files changed, 43 insertions, 4 deletions
diff --git a/apps/user_ldap/lib/Group_LDAP.php b/apps/user_ldap/lib/Group_LDAP.php
index 5072f9d3f74..3db3c6c7664 100644
--- a/apps/user_ldap/lib/Group_LDAP.php
+++ b/apps/user_ldap/lib/Group_LDAP.php
@@ -360,7 +360,7 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
$nesting = (int)$this->access->connection->ldapNestedGroups;
// depending on the input, we either have a list of DNs or a list of LDAP records
// also, the output expects either DNs or records. Testing the first element should suffice.
- $recordMode = is_array($list) && isset($list[0]) && is_array($list[0]) && isset($list[0]['dn'][0]);
+ $recordMode = isset($list[0]) && is_array($list[0]) && isset($list[0]['dn'][0]);
if ($nesting !== 1) {
if ($recordMode) {
@@ -392,6 +392,36 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
return $recordMode ? array_filter($seen, 'is_array') : array_keys($seen);
}
+ private function walkNestedGroupsReturnRecords(string $dn, Closure $fetcher, array $list, array &$seen = []): array {
+ $nesting = (int)$this->access->connection->ldapNestedGroups;
+
+ if ($nesting !== 1) {
+ // the keys are numeric, but should hold the DN
+ return array_reduce($list, function ($transformed, $record) use ($dn) {
+ if ($record['dn'][0] != $dn) {
+ $transformed[$record['dn'][0]] = $record;
+ }
+ return $transformed;
+ }, []);
+ }
+
+ while ($record = array_shift($list)) {
+ $recordDN = $record['dn'][0] ?? $record;
+ if ($recordDN === $dn || array_key_exists($recordDN, $seen)) {
+ // Prevent loops
+ continue;
+ }
+ $fetched = $fetcher($record);
+ $list = array_merge($list, $fetched);
+ if (!isset($seen[$recordDN]) || is_bool($seen[$recordDN]) && is_array($record)) {
+ $seen[$recordDN] = $record;
+ }
+ }
+
+ // on record mode, filter out intermediate state
+ return array_filter($seen, 'is_array');
+ }
+
/**
* translates a gidNumber into an ownCloud internal name
*
@@ -848,6 +878,9 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
// avoid loops
return [];
}
+ if ($this->cachedGroupsByMember[$dn]) {
+ return $this->cachedGroupsByMember[$dn];
+ }
$allGroups = [];
$seen[$dn] = true;
$filter = $this->access->connection->ldapGroupMemberAssocAttr . '=' . $dn;
@@ -875,9 +908,11 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
$dn = "";
}
- $allGroups = $this->walkNestedGroups($dn, $fetcher, $groups, $seen);
+ $allGroups = $this->walkNestedGroupsReturnRecords($dn, $fetcher, $groups, $seen);
$visibleGroups = $this->filterValidGroups($allGroups);
- return array_intersect_key($allGroups, $visibleGroups);
+ $effectiveGroups = array_intersect_key($allGroups, $visibleGroups);
+ $this->cachedGroupsByMember[$dn] = $effectiveGroups;
+ return $effectiveGroups;
}
/**
@@ -1183,7 +1218,11 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
$validGroupDNs = [];
foreach ($listOfGroups as $key => $item) {
$dn = is_string($item) ? $item : $item['dn'][0];
- $gid = $this->access->dn2groupname($dn);
+ if(is_array($item) && !isset($item[$this->access->connection->ldapGroupDisplayName][0])) {
+ continue;
+ }
+ $name = $item[$this->access->connection->ldapGroupDisplayName][0] ?? null;
+ $gid = $this->access->dn2groupname($dn, $name);
if (!$gid) {
continue;
}