diff --git a/resources/init.php b/resources/init.php index b34df57a..6de0837c 100644 --- a/resources/init.php +++ b/resources/init.php @@ -42,6 +42,7 @@ $CONFIG["ldap"]["user"], $CONFIG["ldap"]["pass"], __DIR__ . "/../deployment/custom_user_mappings", + $CONFIG["ldap"]["basedn"], $CONFIG["ldap"]["user_ou"], $CONFIG["ldap"]["group_ou"], $CONFIG["ldap"]["pigroup_ou"], diff --git a/resources/lib/UnityLDAP.php b/resources/lib/UnityLDAP.php index b63f75c9..22df6ebb 100644 --- a/resources/lib/UnityLDAP.php +++ b/resources/lib/UnityLDAP.php @@ -26,6 +26,7 @@ class UnityLDAP extends ldapConn ); // string vars for OUs + private $STR_BASEOU; private $STR_USEROU; private $STR_GROUPOU; private $STR_PIGROUPOU; @@ -33,6 +34,7 @@ class UnityLDAP extends ldapConn private $STR_ADMINGROUP; // Instance vars for various ldapEntry objects + private $baseOU; private $userOU; private $groupOU; private $pi_groupOU; @@ -49,6 +51,7 @@ public function __construct( $dn, $pass, $custom_user_mappings, + $base_ou, $user_ou, $group_ou, $pigroup_ou, @@ -59,6 +62,7 @@ public function __construct( ) { parent::__construct($host, $dn, $pass); + $this->STR_BASEOU = $base_ou; $this->STR_USEROU = $user_ou; $this->STR_GROUPOU = $group_ou; $this->STR_PIGROUPOU = $pigroup_ou; @@ -66,6 +70,7 @@ public function __construct( $this->STR_ADMINGROUP = $admin_group; // Get Global Entries + $this->baseOU = $this->getEntry($base_ou); $this->userOU = $this->getEntry($user_ou); $this->groupOU = $this->getEntry($group_ou); $this->pi_groupOU = $this->getEntry($pigroup_ou); @@ -218,6 +223,13 @@ public function getUnassignedID($uid, $UnitySQL) return $next_uid; } + public function getAllUsersUIDs() + { + // should not use $user_ou->getChildren or $base_ou->getChildren(objectClass=posixAccount) + // Unity users might be outside user ou, and not all users in LDAP tree are unity users + return $this->userGroup->getAttribute("memberuid"); + } + // // Functions that return user/group objects // @@ -231,21 +243,35 @@ public function getAllUsers($UnitySQL, $UnityMailer, $UnityRedis, $UnityWebhook, foreach ($users as $user) { array_push($out, new UnityUser($user, $this, $UnitySQL, $UnityMailer, $UnityRedis, $UnityWebhook)); } - return $out; } } - $users = $this->userGroup->getAttribute("memberuid"); + $users = $this->getAllUsersUIDs(); sort($users); foreach ($users as $user) { $params = array($user, $this, $UnitySQL, $UnityMailer, $UnityRedis, $UnityWebhook); array_push($out, new UnityUser(...$params)); } - return $out; } + public function getAllUsersAttributes($attributes = []) + { + $include_uids = $this->getAllUsersAttributes(); + $user_attributes = $this->baseOU->getChildrenArray( + $attributes, + true, // recursive + "objectClass=posixAccount" + ); + foreach ($user_attributes as $i => $attributes) { + if (!in_array($attributes["uid"][0], $include_uids)) { + unset($user_attributes[$i]); + } + } + return $user_attributes; + } + public function getAllPIGroups($UnitySQL, $UnityMailer, $UnityRedis, $UnityWebhook, $ignorecache = false) { $out = array(); @@ -278,6 +304,58 @@ public function getAllPIGroups($UnitySQL, $UnityMailer, $UnityRedis, $UnityWebho return $out; } + public function getAllPIGroupsAttributes($attributes = []) + { + return $this->pi_groupOU->getChildrenArray($attributes); + } + + public function getPIGroupGIDsWithMemberUID($uid) + { + return array_map( + fn($x) => $x["cn"][0], + $this->pi_groupOU->getChildrenArray( + ["cn"], + false, + "(memberuid=" . ldap_escape($uid, LDAP_ESCAPE_FILTER) . ")", + ) + ); + } + + public function getAllPIGroupOwnerAttributes($attributes = []) + { + // get the PI groups, filter for just the GIDs, then map the GIDs to owner UIDs + $owner_uids = array_map( + fn($x) => UnityGroup::getUIDFromPIUID($x), + array_map( + fn($x) => $x["cn"][0], + $this->pi_groupOU->getChildrenArray(["cn"]), + ), + ); + $owner_attributes = $this->getAllUsersAttributes($attributes); + foreach ($owner_attributes as $i => $attributes) { + if (!in_array($attributes["uid"][0], $owner_uids)) { + unset($owner_attributes[$i]); + } + } + return $owner_attributes; + } + + /** Returns an assosiative array where keys are UIDs and values are arrays of PI GIDs */ + public function getAllUID2PIGIDs() + { + // initialize output so each UID is a key with an empty array as its value + $uids = $this->getAllUsersUIDs(); + $uid2pigids = array_combine($uids, array_fill(0, count($uids), [])); + // for each PI group, append that GID to the member list for each of its member UIDs + foreach ($this->getAllPIGroupsAttributes(["cn", "memberuid"]) as $array) { + $gid = $array["cn"][0]; + foreach ($array["memberuid"] as $uid) { + array_push($uid2pigids[$uid], $gid); + } + } + return $uid2pigids; + } + public function getAllOrgGroups($UnitySQL, $UnityMailer, $UnityRedis, $UnityWebhook, $ignorecache = false) { $out = array(); @@ -309,6 +387,11 @@ public function getAllOrgGroups($UnitySQL, $UnityMailer, $UnityRedis, $UnityWebh return $out; } + public function getAllOrgGroupsAttributes($attributes = []) + { + return $this->org_groupOU->getChildrenArray($attributes); + } + public function getUserEntry($uid) { $uid = ldap_escape($uid, LDAP_ESCAPE_DN); diff --git a/resources/lib/UnityUser.php b/resources/lib/UnityUser.php index 983e2a5f..b5038832 100644 --- a/resources/lib/UnityUser.php +++ b/resources/lib/UnityUser.php @@ -606,48 +606,21 @@ public function getOrgGroup() /** * Gets the groups this user is assigned to, can be more than one - * @return [type] + * @return string[] */ - public function getGroups($ignorecache = false) + public function getPIGroupGIDs($ignorecache = false) { - $out = array(); - if (!$ignorecache) { $cached_val = $this->REDIS->getCache($this->getUID(), "groups"); if (!is_null($cached_val)) { - $groups = $cached_val; - foreach ($groups as $group) { - $group_obj = new UnityGroup( - $group, - $this->LDAP, - $this->SQL, - $this->MAILER, - $this->REDIS, - $this->WEBHOOK - ); - array_push($out, $group_obj); - } - - return $out; - } - } - - $all_pi_groups = $this->LDAP->getAllPIGroups($this->SQL, $this->MAILER, $this->REDIS, $ignorecache); - - $cache_arr = array(); - - foreach ($all_pi_groups as $pi_group) { - if (in_array($this->getUID(), $pi_group->getGroupMemberUIDs())) { - array_push($out, $pi_group); - array_push($cache_arr, $pi_group->getPIUID()); + return $cached_val; } } - + $gids = $this->LDAP->getPIGroupGIDsWithMemberUID($this->uid); if (!$ignorecache) { - $this->REDIS->setCache($this->getUID(), "groups", $cache_arr); + $this->REDIS->setCache($this->getUID(), "groups", $gids); } - - return $out; + return $gids; } /** diff --git a/test/functional/AccountDeletionRequestTest.php b/test/functional/AccountDeletionRequestTest.php index 08eb2af4..49172adf 100644 --- a/test/functional/AccountDeletionRequestTest.php +++ b/test/functional/AccountDeletionRequestTest.php @@ -35,7 +35,7 @@ public function testRequestAccountDeletionUserHasNoGroups() { global $USER, $SQL; switchUser(...getUserHasNotRequestedAccountDeletionHasNoGroups()); - $this->assertEmpty($USER->getGroups()); + $this->assertEmpty($USER->getPIGroupGIDs()); $this->assertNumberAccountDeletionRequests(0); try { http_post( @@ -59,7 +59,7 @@ public function testRequestAccountDeletionUserHasGroup() // FIXME this should be an error global $USER, $SQL; switchUser(...getUserHasNotRequestedAccountDeletionHasGroup()); - $this->assertNotEmpty($USER->getGroups()); + $this->assertNotEmpty($USER->getPIGroupGIDs()); $this->assertNumberAccountDeletionRequests(0); try { http_post( diff --git a/webroot/admin/pi-mgmt.php b/webroot/admin/pi-mgmt.php index c546704b..d21d1ae9 100644 --- a/webroot/admin/pi-mgmt.php +++ b/webroot/admin/pi-mgmt.php @@ -109,21 +109,14 @@
$gid
"; } + echo "You cannot request to delete your account while you are in a PI group.
"; diff --git a/webroot/panel/groups.php b/webroot/panel/groups.php index ed5b8ba4..b0b68ba4 100644 --- a/webroot/panel/groups.php +++ b/webroot/panel/groups.php @@ -63,7 +63,7 @@