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 @@ Actions -getAllPIGroups($SQL, $MAILER, $REDIS, $WEBHOOK); - - usort($accounts, function ($a, $b) { - return strcmp($a->getPIUID(), $b->getPIUID()); - }); - - foreach ($accounts as $pi_group) { - $pi_user = $pi_group->getOwner(); - + getAllPIGroupOwnerAttributes(["uid", "gecos", "mail"]); + usort($owner_attributes, fn($a, $b) => strcmp($a["uid"][0], $b["uid"][0])); + foreach ($owner_attributes as $attributes) { echo ""; - echo "" . $pi_user->getFirstname() . - " " . $pi_user->getLastname() . ""; - echo "" . $pi_group->getPIUID() . ""; - echo "" . $pi_user->getMail() . ""; + echo "" . $attributes["gecos"][0] . ""; + echo "" . UnityGroup::getPIUIDfromUID($attributes["uid"][0]) . ""; + echo "" . $attributes["mail"][0] . ""; echo ""; } ?> diff --git a/webroot/admin/user-mgmt.php b/webroot/admin/user-mgmt.php index e27725c2..ddc2c2bf 100644 --- a/webroot/admin/user-mgmt.php +++ b/webroot/admin/user-mgmt.php @@ -37,36 +37,31 @@ getAllUsers($SQL, $MAILER, $REDIS, $WEBHOOK); - - usort($users, function ($a, $b) { - return strcmp($a->getUID(), $b->getUID()); - }); - - foreach ($users as $user) { - if ($user->hasRequestedAccountDeletion()) { + $UID2PIGIDs = $LDAP->getAllUID2PIGIDs(); + $user_attributes = $LDAP->getAllUsersAttributes(["uid", "gecos", "o", "mail"]); + usort($user_attributes, fn ($a, $b) => strcmp($a["uid"][0], $b["uid"][0])); + foreach ($user_attributes as $attributes) { + $uid = $attributes["uid"][0]; + if ($SQL->accDeletionRequestExists($uid)) { echo ""; } else { echo ""; } - echo "" . $user->getFirstname() . " " . $user->getLastname() . ""; - echo "" . $user->getUID() . ""; - echo "" . $user->getOrg() . ""; - echo "" . $user->getMail() . ""; + echo "" . $attributes["gecos"][0] . ""; + echo "" . $uid . ""; + echo "" . $attributes["o"][0] . ""; + echo "" . $attributes["mail"][0] . ""; echo ""; - $cur_user_groups = $user->getGroups(); - foreach ($cur_user_groups as $cur_group) { - echo "" . $cur_group->getPIUID() . ""; - if ($cur_group !== array_key_last($cur_user_groups)) { - echo '
'; - } + foreach ($UID2PIGIDs[$uid] as $gid) { + echo "

$gid

"; } + echo "
"; echo ""; echo ""; echo "
+ onsubmit='return confirm(\"Are you sure you want to switch to the user '$uid'?\");'> - +
"; echo ""; diff --git a/webroot/panel/account.php b/webroot/panel/account.php index f63a1f7a..fc573645 100644 --- a/webroot/panel/account.php +++ b/webroot/panel/account.php @@ -78,7 +78,7 @@ $USER->getPIGroup()->cancelGroupRequest(); break; case "account_deletion_request": - $hasGroups = count($USER->getGroups()) > 0; + $hasGroups = count($USER->getPIGroupGIDs()) > 0; if ($hasGroups) { break; } @@ -117,7 +117,7 @@ getGroups()) > 0; +$isActive = count($USER->getPIGroupGIDs()) > 0; $isPI = $USER->isPI(); if ($isPI) { @@ -222,7 +222,7 @@
Account Deletion
getGroups()) > 0; +$hasGroups = count($USER->getPIGroupGIDs()) > 0; if ($hasGroups) { 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 @@
getGroups(); +$PIGroupGIDs = $USER->getPIGroupGIDs(); $requests = $SQL->getRequestsByUser($USER->getUID()); @@ -97,19 +97,19 @@ } echo ""; - if (count($groups) > 0) { + if (count($PIGroupGIDs) > 0) { echo "
"; } } echo "
Current Groups
"; -if ($USER->isPI() && count($groups) == 1) { +if ($USER->isPI() && count($PIGroupGIDs) == 1) { echo "You are only a member of your own PI group. Navigate to the my users page to see your group."; } -if (count($groups) == 0) { +if (count($PIGroupGIDs) == 0) { echo "You are not a member of any groups. Request to join a PI using the button below, or request your own PI account on the account settings page"; @@ -117,7 +117,8 @@ echo ""; -foreach ($groups as $group) { +foreach ($PIGroupGIDs as $gid) { + $group = new UnityGroup($gid, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK); $owner = $group->getOwner(); if ($USER->getUID() == $owner->getUID()) {