From d152bc3153766ffb91e1152b0e609fd0b623f1a7 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 11:34:21 -0500 Subject: [PATCH 01/17] remove duplicated code from UnityGroup/UnityOrg --- resources/lib/UnityGroup.php | 69 +++---------------- resources/lib/UnityOrg.php | 34 +-------- resources/lib/UnityUser.php | 6 +- resources/lib/phpopenldaper | 2 +- .../functional/AccountDeletionRequestTest.php | 2 +- test/functional/PIMemberRequestTest.php | 2 +- test/functional/PiMemberApproveTest.php | 10 +-- test/functional/PiMemberDenyTest.php | 8 +-- test/functional/PiRemoveUserTest.php | 14 ++-- test/phpunit-bootstrap.php | 10 +-- webroot/panel/ajax/get_group_members.php | 2 +- webroot/panel/groups.php | 2 +- workers/remove-users-from-group.php | 2 +- 13 files changed, 41 insertions(+), 122 deletions(-) diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index 688d7106..928c6641 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -4,11 +4,12 @@ use PHPOpenLDAPer\LDAPEntry; use Exception; +use PHPOpenLDAPer\PosixGroup; /** * Class that represents a single PI group in the Unity Cluster. */ -class UnityGroup +class UnityGroup extends PosixGroup { public const string PI_PREFIX = "pi_"; @@ -36,32 +37,6 @@ public function __construct( $this->WEBHOOK = $WEBHOOK; } - public function equals(UnityGroup $other_group): bool - { - if (!is_a($other_group, self::class)) { - throw new Exception( - "Unable to check equality because the parameter is not a " . - self::class . - " object", - ); - } - - return $this->gid == $other_group->gid; - } - - public function __toString(): string - { - return $this->gid; - } - - /** - * Checks if the current PI is an approved and existent group - */ - public function exists(): bool - { - return $this->entry->exists(); - } - public function requestGroup(bool $send_mail_to_admins, bool $send_mail = true): void { if ($this->exists()) { @@ -202,7 +177,7 @@ public function approveUser(UnityUser $new_user, bool $send_mail = true): void { $request = $this->SQL->getRequest($new_user->uid, $this->gid); \ensure($new_user->exists()); - $this->addUserToGroup($new_user); + $this->addMember($new_user->uid); $this->SQL->removeRequest($new_user->uid, $this->gid); if ($send_mail) { $this->MAILER->sendMail($new_user->getMail(), "group_user_added", [ @@ -240,14 +215,14 @@ public function denyUser(UnityUser $new_user, bool $send_mail = true): void public function removeUser(UnityUser $new_user, bool $send_mail = true): void { - if (!$this->memberExists($new_user)) { + if (!$this->memberExists($new_user->uid)) { return; } if ($new_user->uid == $this->getOwner()->uid) { throw new Exception("Cannot delete group owner from group. Disband group instead"); } // remove request, this will fail silently if the request doesn't exist - $this->removeUserFromGroup($new_user); + $this->removeMember($new_user->uid); if ($send_mail) { $this->MAILER->sendMail($new_user->getMail(), "group_user_removed", [ "group" => $this->gid, @@ -264,7 +239,7 @@ public function removeUser(UnityUser $new_user, bool $send_mail = true): void public function newUserRequest(UnityUser $new_user, bool $send_mail = true): void { - if ($this->memberExists($new_user)) { + if ($this->memberExists($new_user->uid)) { UnityHTTPD::errorLog("warning", "user '$new_user' already in group"); return; } @@ -310,7 +285,7 @@ public function getRequests(): array public function getGroupMembers(): array { - $members = $this->getGroupMemberUIDs(); + $members = $this->getMembers(); $out = []; foreach ($members as $member) { $user_obj = new UnityUser( @@ -325,13 +300,6 @@ public function getGroupMembers(): array return $out; } - public function getGroupMemberUIDs(): array - { - $members = $this->entry->getAttribute("memberuid"); - sort($members); - return $members; - } - public function requestExists(UnityUser $user): bool { $requesters = $this->getRequests(); @@ -358,23 +326,6 @@ private function init(): void // we need to update the cache here with the memberuid } - private function addUserToGroup(UnityUser $new_user): void - { - $this->entry->appendAttribute("memberuid", $new_user->uid); - $this->entry->write(); - } - - private function removeUserFromGroup(UnityUser $old_user): void - { - $this->entry->removeAttributeEntryByValue("memberuid", $old_user->uid); - $this->entry->write(); - } - - public function memberExists(UnityUser $user): bool - { - return in_array($user->uid, $this->getGroupMemberUIDs()); - } - private function addRequest(string $uid): void { $this->SQL->addRequest($uid, $this->gid); @@ -417,10 +368,6 @@ public static function ownerMail2GID(string $email): string public function getGroupMembersAttributes(array $attributes, array $default_values = []): array { - return $this->LDAP->getUsersAttributes( - $this->getGroupMemberUIDs(), - $attributes, - $default_values, - ); + return $this->LDAP->getUsersAttributes($this->getMembers(), $attributes, $default_values); } } diff --git a/resources/lib/UnityOrg.php b/resources/lib/UnityOrg.php index 07d12ec1..12b9b110 100644 --- a/resources/lib/UnityOrg.php +++ b/resources/lib/UnityOrg.php @@ -2,8 +2,9 @@ namespace UnityWebPortal\lib; use PHPOpenLDAPer\LDAPEntry; +use PHPOpenLDAPer\PosixGroup; -class UnityOrg +class UnityOrg extends PosixGroup { public string $gid; private LDAPEntry $entry; @@ -38,19 +39,9 @@ public function init(): void $this->entry->write(); } - public function exists(): bool - { - return $this->entry->exists(); - } - - public function inOrg(UnityUser $user): bool - { - return in_array($user->uid, $this->getOrgMemberUIDs()); - } - public function getOrgMembers(): array { - $members = $this->getOrgMemberUIDs(); + $members = $this->getMembers(); $out = []; foreach ($members as $member) { $user_obj = new UnityUser( @@ -64,23 +55,4 @@ public function getOrgMembers(): array } return $out; } - - public function getOrgMemberUIDs(): array - { - $members = $this->entry->getAttribute("memberuid"); - sort($members); - return $members; - } - - public function addUser(UnityUser $user): void - { - $this->entry->appendAttribute("memberuid", $user->uid); - $this->entry->write(); - } - - public function removeUser(UnityUser $user): void - { - $this->entry->removeAttributeEntryByValue("memberuid", $user->uid); - $this->entry->write(); - } } diff --git a/resources/lib/UnityUser.php b/resources/lib/UnityUser.php index 086f53af..9f887e7b 100644 --- a/resources/lib/UnityUser.php +++ b/resources/lib/UnityUser.php @@ -90,8 +90,8 @@ public function init( $org->init(); } - if (!$org->inOrg($this)) { - $org->addUser($this); + if (!$org->memberExists($this->uid)) { + $org->addMember($this->uid); } $this->SQL->addLog($this->uid, $_SERVER["REMOTE_ADDR"], "user_added", $this->uid); @@ -416,6 +416,6 @@ public function isInGroup(string $uid, UnityGroup $group): bool $group_checked = $group; } - return in_array($uid, $group_checked->getGroupMemberUIDs()); + return in_array($uid, $group_checked->getMembers()); } } diff --git a/resources/lib/phpopenldaper b/resources/lib/phpopenldaper index 7b93caa1..5e0f09c3 160000 --- a/resources/lib/phpopenldaper +++ b/resources/lib/phpopenldaper @@ -1 +1 @@ -Subproject commit 7b93caa16fc023f3c656f6560b1a6d72acb8677d +Subproject commit 5e0f09c3dc9b8818bdefed3b7891221b70fde88a diff --git a/test/functional/AccountDeletionRequestTest.php b/test/functional/AccountDeletionRequestTest.php index 83177b25..82480cc3 100644 --- a/test/functional/AccountDeletionRequestTest.php +++ b/test/functional/AccountDeletionRequestTest.php @@ -49,7 +49,7 @@ public function testRequestAccountDeletionUserHasRequest() switchUser(...$pi_args); $pi = $USER; $pi_group = $USER->getPIGroup(); - $this->assertEqualsCanonicalizing([$pi->uid], $pi_group->getGroupMemberUIDs()); + $this->assertEqualsCanonicalizing([$pi->uid], $pi_group->getMembers()); $user_args = getBlankUser(); switchUser(...$user_args); $this->assertEmpty($USER->getPIGroupGIDs()); diff --git a/test/functional/PIMemberRequestTest.php b/test/functional/PIMemberRequestTest.php index f42c600a..4b8eacbf 100644 --- a/test/functional/PIMemberRequestTest.php +++ b/test/functional/PIMemberRequestTest.php @@ -38,7 +38,7 @@ public function testRequestMembership() $uid = $USER->uid; $this->assertFalse($USER->isPI()); $this->assertFalse($SQL->requestExists($uid, UnitySQL::REQUEST_BECOME_PI)); - $this->assertFalse($pi_group->memberExists($USER)); + $this->assertFalse($pi_group->memberExists($USER->uid)); try { $this->requestMembership($gid); $this->assertTrue($SQL->requestExists($uid, $gid)); diff --git a/test/functional/PiMemberApproveTest.php b/test/functional/PiMemberApproveTest.php index db9cb2b0..d04ff380 100644 --- a/test/functional/PiMemberApproveTest.php +++ b/test/functional/PiMemberApproveTest.php @@ -54,7 +54,7 @@ public function testApproveNonexistentRequest() $this->assertTrue($piGroup->exists()); $this->assertGroupMembers($piGroup, [$piUID]); $this->assertEmpty($piGroup->getRequests()); - $this->assertFalse($piGroup->memberExists($user)); + $this->assertFalse($piGroup->memberExists($user->uid)); $this->assertEmpty($piGroup->getRequests()); try { $this->expectException(Exception::class); // FIXME more specific exception type @@ -77,7 +77,7 @@ public function testApproveMemberByPI() $this->assertTrue($USER->exists()); $this->assertTrue($pi_group->exists()); $this->assertGroupMembers($pi_group, [$pi_uid]); - $this->assertTrue(!$pi_group->memberExists($USER)); + $this->assertTrue(!$pi_group->memberExists($USER->uid)); $this->assertRequestedMembership(false, $gid); try { $this->requestGroupMembership($pi_group->gid); @@ -106,7 +106,7 @@ public function testApproveMemberByPI() $this->assertTrue(!$pi_group->requestExists($USER)); $this->assertRequestedMembership(false, $gid); - $this->assertTrue($pi_group->memberExists($USER)); + $this->assertTrue($pi_group->memberExists($USER->uid)); $this->assertTrue($USER->isQualified()); // $third_request_failed = false; @@ -137,7 +137,7 @@ public function testApproveMemberByAdmin() $this->assertTrue($USER->exists()); $this->assertTrue($pi_group->exists()); $this->assertGroupMembers($pi_group, [$pi_uid]); - $this->assertTrue(!$pi_group->memberExists($USER)); + $this->assertTrue(!$pi_group->memberExists($USER->uid)); $this->assertRequestedMembership(false, $gid); try { $this->requestGroupMembership($pi_group->gid); @@ -166,7 +166,7 @@ public function testApproveMemberByAdmin() $this->assertTrue(!$pi_group->requestExists($USER)); $this->assertRequestedMembership(false, $gid); - $this->assertTrue($pi_group->memberExists($USER)); + $this->assertTrue($pi_group->memberExists($USER->uid)); $this->assertTrue($USER->isQualified()); // $third_request_failed = false; diff --git a/test/functional/PiMemberDenyTest.php b/test/functional/PiMemberDenyTest.php index f93a1fd5..1acd937a 100644 --- a/test/functional/PiMemberDenyTest.php +++ b/test/functional/PiMemberDenyTest.php @@ -31,17 +31,17 @@ public function testDenyRequest() $pi = $USER; $piGroup = $USER->getPIGroup(); $this->assertTrue($piGroup->exists()); - $this->assertEqualsCanonicalizing([$pi->uid], $piGroup->getGroupMemberUIDs()); + $this->assertEqualsCanonicalizing([$pi->uid], $piGroup->getMembers()); $this->assertEmpty($piGroup->getRequests()); $requestedUser = new UnityUser(self::$requestUid, $LDAP, $SQL, $MAILER, $WEBHOOK); try { $piGroup->newUserRequest($requestedUser); - $this->assertFalse($piGroup->memberExists($requestedUser)); + $this->assertFalse($piGroup->memberExists($requestedUser->uid)); $piGroup->denyUser($requestedUser); $this->assertEmpty($piGroup->getRequests()); - $this->assertEqualsCanonicalizing([$pi->uid], $piGroup->getGroupMemberUIDs()); - $this->assertFalse($piGroup->memberExists($requestedUser)); + $this->assertEqualsCanonicalizing([$pi->uid], $piGroup->getMembers()); + $this->assertFalse($piGroup->memberExists($requestedUser->uid)); } finally { $SQL->removeRequest(self::$requestUid, $piGroup->gid); } diff --git a/test/functional/PiRemoveUserTest.php b/test/functional/PiRemoveUserTest.php index 7956d1c3..9cf4b658 100644 --- a/test/functional/PiRemoveUserTest.php +++ b/test/functional/PiRemoveUserTest.php @@ -21,7 +21,7 @@ public function testRemoveUser() $piUid = $USER->uid; $piGroup = $USER->getPIGroup(); $this->assertTrue($piGroup->exists()); - $memberUIDs = $piGroup->getGroupMemberUIDs(); + $memberUIDs = $piGroup->getMembers(); // the 0th member of the PI group is the PI $this->assertGreaterThan(1, count($memberUIDs)); // the ordering of the uids in getGroupMemberUIDs is different each time @@ -37,12 +37,12 @@ public function testRemoveUser() } } $this->assertNotEquals($pi->uid, $memberToDelete->uid); - $this->assertTrue($piGroup->memberExists($memberToDelete)); + $this->assertTrue($piGroup->memberExists($memberToDelete->uid)); try { $this->removeUser($memberToDelete->uid); - $this->assertFalse($piGroup->memberExists($memberToDelete)); + $this->assertFalse($piGroup->memberExists($memberToDelete->uid)); } finally { - if (!$piGroup->memberExists($memberToDelete)) { + if (!$piGroup->memberExists($memberToDelete->uid)) { $piGroup->newUserRequest($memberToDelete); $piGroup->approveUser($memberToDelete); } @@ -56,13 +56,13 @@ public function testRemovePIFromTheirOwnGroup() $pi = $USER; $piGroup = $USER->getPIGroup(); $this->assertTrue($piGroup->exists()); - $this->assertTrue($piGroup->memberExists($pi)); + $this->assertTrue($piGroup->memberExists($pi->uid)); $this->expectException(Exception::class); try { $this->removeUser($pi->uid); - $this->assertTrue($piGroup->memberExists($pi)); + $this->assertTrue($piGroup->memberExists($pi->uid)); } finally { - if (!$piGroup->memberExists($pi)) { + if (!$piGroup->memberExists($pi->uid)) { $piGroup->newUserRequest($pi); $piGroup->approveUser($pi); } diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index c613602f..c1c279a0 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -174,9 +174,9 @@ function ensureUserDoesNotExist() $SQL->deleteRequestsByUser($USER->uid); if ($USER->exists()) { $org = $USER->getOrgGroup(); - if ($org->exists() and $org->inOrg($USER)) { + if ($org->exists() and $org->memberExists($USER->uid)) { $org->removeUser($USER); - ensure(!$org->inOrg($USER)); + ensure(!$org->memberExists($USER->uid)); } $LDAP->getUserEntry($USER->uid)->delete(); ensure(!$USER->exists()); @@ -220,9 +220,9 @@ function ensureUserNotRequestedAccountDeletion() function ensureUserNotInPIGroup(UnityGroup $pi_group) { global $USER; - if ($pi_group->memberExists($USER)) { + if ($pi_group->memberExists($USER->uid)) { $pi_group->removeUser($USER); - ensure(!$pi_group->memberExists($USER)); + ensure(!$pi_group->memberExists($USER->uid)); } } @@ -365,7 +365,7 @@ public function assertMessageExists( public function assertGroupMembers(UnityGroup $group, array $expected_members) { sort($expected_members); - $found_members = $group->getGroupMemberUIDs(); + $found_members = $group->getMembers(); sort($found_members); $this->assertEqualsCanonicalizing($expected_members, $found_members); } diff --git a/webroot/panel/ajax/get_group_members.php b/webroot/panel/ajax/get_group_members.php index 177d31e0..8369ef78 100644 --- a/webroot/panel/ajax/get_group_members.php +++ b/webroot/panel/ajax/get_group_members.php @@ -8,7 +8,7 @@ $gid = UnityHTTPD::getQueryParameter("gid"); $group = new UnityGroup($gid, $LDAP, $SQL, $MAILER, $WEBHOOK); -if (!$group->memberExists($USER)) { +if (!$group->memberExists($USER->uid)) { UnityHTTPD::forbidden("not a group member"); } $members = $group->getGroupMembersAttributes(["gecos", "mail"]); diff --git a/webroot/panel/groups.php b/webroot/panel/groups.php index a04030d1..a7bf027c 100644 --- a/webroot/panel/groups.php +++ b/webroot/panel/groups.php @@ -39,7 +39,7 @@ ); UnityHTTPD::redirect(); } - if ($pi_account->memberExists($USER)) { + if ($pi_account->memberExists($USER->uid)) { UnityHTTPD::messageError( "Invalid Group Membership Request", "You're already in this PI group" diff --git a/workers/remove-users-from-group.php b/workers/remove-users-from-group.php index 20fbb52e..33061b7b 100755 --- a/workers/remove-users-from-group.php +++ b/workers/remove-users-from-group.php @@ -27,7 +27,7 @@ function _die($msg) while (($line = fgets($handle)) !== false) { $uid = trim($line); $user = new UnityUser($uid, $LDAP, $SQL, $MAILER, $WEBHOOK); - if (!$group->memberExists($user)) { + if (!$group->memberExists($user->uid)) { print "Skipping '$uid' who doesn't appear to be in '$gid'\n"; continue; } From 6a1b956017086d4a7bc57e6c850c2a8f06216c09 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 11:36:57 -0500 Subject: [PATCH 02/17] change function names --- resources/lib/UnityGroup.php | 16 ++++++++++------ resources/lib/UnityOrg.php | 2 +- resources/lib/UnityUser.php | 6 +++--- resources/lib/phpopenldaper | 2 +- test/functional/AccountDeletionRequestTest.php | 2 +- test/functional/PIMemberRequestTest.php | 2 +- test/functional/PiMemberApproveTest.php | 10 +++++----- test/functional/PiMemberDenyTest.php | 8 ++++---- test/functional/PiRemoveUserTest.php | 14 +++++++------- test/phpunit-bootstrap.php | 10 +++++----- webroot/panel/ajax/get_group_members.php | 2 +- webroot/panel/groups.php | 2 +- workers/remove-users-from-group.php | 2 +- 13 files changed, 41 insertions(+), 37 deletions(-) diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index 928c6641..bb455407 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -177,7 +177,7 @@ public function approveUser(UnityUser $new_user, bool $send_mail = true): void { $request = $this->SQL->getRequest($new_user->uid, $this->gid); \ensure($new_user->exists()); - $this->addMember($new_user->uid); + $this->addMemberUID($new_user->uid); $this->SQL->removeRequest($new_user->uid, $this->gid); if ($send_mail) { $this->MAILER->sendMail($new_user->getMail(), "group_user_added", [ @@ -215,14 +215,14 @@ public function denyUser(UnityUser $new_user, bool $send_mail = true): void public function removeUser(UnityUser $new_user, bool $send_mail = true): void { - if (!$this->memberExists($new_user->uid)) { + if (!$this->mermberUIDExists($new_user->uid)) { return; } if ($new_user->uid == $this->getOwner()->uid) { throw new Exception("Cannot delete group owner from group. Disband group instead"); } // remove request, this will fail silently if the request doesn't exist - $this->removeMember($new_user->uid); + $this->removeMemberUID($new_user->uid); if ($send_mail) { $this->MAILER->sendMail($new_user->getMail(), "group_user_removed", [ "group" => $this->gid, @@ -239,7 +239,7 @@ public function removeUser(UnityUser $new_user, bool $send_mail = true): void public function newUserRequest(UnityUser $new_user, bool $send_mail = true): void { - if ($this->memberExists($new_user->uid)) { + if ($this->mermberUIDExists($new_user->uid)) { UnityHTTPD::errorLog("warning", "user '$new_user' already in group"); return; } @@ -285,7 +285,7 @@ public function getRequests(): array public function getGroupMembers(): array { - $members = $this->getMembers(); + $members = $this->getMemberUIDs(); $out = []; foreach ($members as $member) { $user_obj = new UnityUser( @@ -368,6 +368,10 @@ public static function ownerMail2GID(string $email): string public function getGroupMembersAttributes(array $attributes, array $default_values = []): array { - return $this->LDAP->getUsersAttributes($this->getMembers(), $attributes, $default_values); + return $this->LDAP->getUsersAttributes( + $this->getMemberUIDs(), + $attributes, + $default_values, + ); } } diff --git a/resources/lib/UnityOrg.php b/resources/lib/UnityOrg.php index 12b9b110..6168d940 100644 --- a/resources/lib/UnityOrg.php +++ b/resources/lib/UnityOrg.php @@ -41,7 +41,7 @@ public function init(): void public function getOrgMembers(): array { - $members = $this->getMembers(); + $members = $this->getMemberUIDs(); $out = []; foreach ($members as $member) { $user_obj = new UnityUser( diff --git a/resources/lib/UnityUser.php b/resources/lib/UnityUser.php index 9f887e7b..0ae2f935 100644 --- a/resources/lib/UnityUser.php +++ b/resources/lib/UnityUser.php @@ -90,8 +90,8 @@ public function init( $org->init(); } - if (!$org->memberExists($this->uid)) { - $org->addMember($this->uid); + if (!$org->mermberUIDExists($this->uid)) { + $org->addMemberUID($this->uid); } $this->SQL->addLog($this->uid, $_SERVER["REMOTE_ADDR"], "user_added", $this->uid); @@ -416,6 +416,6 @@ public function isInGroup(string $uid, UnityGroup $group): bool $group_checked = $group; } - return in_array($uid, $group_checked->getMembers()); + return in_array($uid, $group_checked->getMemberUIDs()); } } diff --git a/resources/lib/phpopenldaper b/resources/lib/phpopenldaper index 5e0f09c3..cd136ac6 160000 --- a/resources/lib/phpopenldaper +++ b/resources/lib/phpopenldaper @@ -1 +1 @@ -Subproject commit 5e0f09c3dc9b8818bdefed3b7891221b70fde88a +Subproject commit cd136ac61fa1362f253aee6fc87eb97544aa2faf diff --git a/test/functional/AccountDeletionRequestTest.php b/test/functional/AccountDeletionRequestTest.php index 82480cc3..8b595901 100644 --- a/test/functional/AccountDeletionRequestTest.php +++ b/test/functional/AccountDeletionRequestTest.php @@ -49,7 +49,7 @@ public function testRequestAccountDeletionUserHasRequest() switchUser(...$pi_args); $pi = $USER; $pi_group = $USER->getPIGroup(); - $this->assertEqualsCanonicalizing([$pi->uid], $pi_group->getMembers()); + $this->assertEqualsCanonicalizing([$pi->uid], $pi_group->getMemberUIDs()); $user_args = getBlankUser(); switchUser(...$user_args); $this->assertEmpty($USER->getPIGroupGIDs()); diff --git a/test/functional/PIMemberRequestTest.php b/test/functional/PIMemberRequestTest.php index 4b8eacbf..4a30176e 100644 --- a/test/functional/PIMemberRequestTest.php +++ b/test/functional/PIMemberRequestTest.php @@ -38,7 +38,7 @@ public function testRequestMembership() $uid = $USER->uid; $this->assertFalse($USER->isPI()); $this->assertFalse($SQL->requestExists($uid, UnitySQL::REQUEST_BECOME_PI)); - $this->assertFalse($pi_group->memberExists($USER->uid)); + $this->assertFalse($pi_group->mermberUIDExists($USER->uid)); try { $this->requestMembership($gid); $this->assertTrue($SQL->requestExists($uid, $gid)); diff --git a/test/functional/PiMemberApproveTest.php b/test/functional/PiMemberApproveTest.php index d04ff380..f1c5f2fd 100644 --- a/test/functional/PiMemberApproveTest.php +++ b/test/functional/PiMemberApproveTest.php @@ -54,7 +54,7 @@ public function testApproveNonexistentRequest() $this->assertTrue($piGroup->exists()); $this->assertGroupMembers($piGroup, [$piUID]); $this->assertEmpty($piGroup->getRequests()); - $this->assertFalse($piGroup->memberExists($user->uid)); + $this->assertFalse($piGroup->mermberUIDExists($user->uid)); $this->assertEmpty($piGroup->getRequests()); try { $this->expectException(Exception::class); // FIXME more specific exception type @@ -77,7 +77,7 @@ public function testApproveMemberByPI() $this->assertTrue($USER->exists()); $this->assertTrue($pi_group->exists()); $this->assertGroupMembers($pi_group, [$pi_uid]); - $this->assertTrue(!$pi_group->memberExists($USER->uid)); + $this->assertTrue(!$pi_group->mermberUIDExists($USER->uid)); $this->assertRequestedMembership(false, $gid); try { $this->requestGroupMembership($pi_group->gid); @@ -106,7 +106,7 @@ public function testApproveMemberByPI() $this->assertTrue(!$pi_group->requestExists($USER)); $this->assertRequestedMembership(false, $gid); - $this->assertTrue($pi_group->memberExists($USER->uid)); + $this->assertTrue($pi_group->mermberUIDExists($USER->uid)); $this->assertTrue($USER->isQualified()); // $third_request_failed = false; @@ -137,7 +137,7 @@ public function testApproveMemberByAdmin() $this->assertTrue($USER->exists()); $this->assertTrue($pi_group->exists()); $this->assertGroupMembers($pi_group, [$pi_uid]); - $this->assertTrue(!$pi_group->memberExists($USER->uid)); + $this->assertTrue(!$pi_group->mermberUIDExists($USER->uid)); $this->assertRequestedMembership(false, $gid); try { $this->requestGroupMembership($pi_group->gid); @@ -166,7 +166,7 @@ public function testApproveMemberByAdmin() $this->assertTrue(!$pi_group->requestExists($USER)); $this->assertRequestedMembership(false, $gid); - $this->assertTrue($pi_group->memberExists($USER->uid)); + $this->assertTrue($pi_group->mermberUIDExists($USER->uid)); $this->assertTrue($USER->isQualified()); // $third_request_failed = false; diff --git a/test/functional/PiMemberDenyTest.php b/test/functional/PiMemberDenyTest.php index 1acd937a..bf28fa36 100644 --- a/test/functional/PiMemberDenyTest.php +++ b/test/functional/PiMemberDenyTest.php @@ -31,17 +31,17 @@ public function testDenyRequest() $pi = $USER; $piGroup = $USER->getPIGroup(); $this->assertTrue($piGroup->exists()); - $this->assertEqualsCanonicalizing([$pi->uid], $piGroup->getMembers()); + $this->assertEqualsCanonicalizing([$pi->uid], $piGroup->getMemberUIDs()); $this->assertEmpty($piGroup->getRequests()); $requestedUser = new UnityUser(self::$requestUid, $LDAP, $SQL, $MAILER, $WEBHOOK); try { $piGroup->newUserRequest($requestedUser); - $this->assertFalse($piGroup->memberExists($requestedUser->uid)); + $this->assertFalse($piGroup->mermberUIDExists($requestedUser->uid)); $piGroup->denyUser($requestedUser); $this->assertEmpty($piGroup->getRequests()); - $this->assertEqualsCanonicalizing([$pi->uid], $piGroup->getMembers()); - $this->assertFalse($piGroup->memberExists($requestedUser->uid)); + $this->assertEqualsCanonicalizing([$pi->uid], $piGroup->getMemberUIDs()); + $this->assertFalse($piGroup->mermberUIDExists($requestedUser->uid)); } finally { $SQL->removeRequest(self::$requestUid, $piGroup->gid); } diff --git a/test/functional/PiRemoveUserTest.php b/test/functional/PiRemoveUserTest.php index 9cf4b658..f4669a64 100644 --- a/test/functional/PiRemoveUserTest.php +++ b/test/functional/PiRemoveUserTest.php @@ -21,7 +21,7 @@ public function testRemoveUser() $piUid = $USER->uid; $piGroup = $USER->getPIGroup(); $this->assertTrue($piGroup->exists()); - $memberUIDs = $piGroup->getMembers(); + $memberUIDs = $piGroup->getMemberUIDs(); // the 0th member of the PI group is the PI $this->assertGreaterThan(1, count($memberUIDs)); // the ordering of the uids in getGroupMemberUIDs is different each time @@ -37,12 +37,12 @@ public function testRemoveUser() } } $this->assertNotEquals($pi->uid, $memberToDelete->uid); - $this->assertTrue($piGroup->memberExists($memberToDelete->uid)); + $this->assertTrue($piGroup->mermberUIDExists($memberToDelete->uid)); try { $this->removeUser($memberToDelete->uid); - $this->assertFalse($piGroup->memberExists($memberToDelete->uid)); + $this->assertFalse($piGroup->mermberUIDExists($memberToDelete->uid)); } finally { - if (!$piGroup->memberExists($memberToDelete->uid)) { + if (!$piGroup->mermberUIDExists($memberToDelete->uid)) { $piGroup->newUserRequest($memberToDelete); $piGroup->approveUser($memberToDelete); } @@ -56,13 +56,13 @@ public function testRemovePIFromTheirOwnGroup() $pi = $USER; $piGroup = $USER->getPIGroup(); $this->assertTrue($piGroup->exists()); - $this->assertTrue($piGroup->memberExists($pi->uid)); + $this->assertTrue($piGroup->mermberUIDExists($pi->uid)); $this->expectException(Exception::class); try { $this->removeUser($pi->uid); - $this->assertTrue($piGroup->memberExists($pi->uid)); + $this->assertTrue($piGroup->mermberUIDExists($pi->uid)); } finally { - if (!$piGroup->memberExists($pi->uid)) { + if (!$piGroup->mermberUIDExists($pi->uid)) { $piGroup->newUserRequest($pi); $piGroup->approveUser($pi); } diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index c1c279a0..c2530af4 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -174,9 +174,9 @@ function ensureUserDoesNotExist() $SQL->deleteRequestsByUser($USER->uid); if ($USER->exists()) { $org = $USER->getOrgGroup(); - if ($org->exists() and $org->memberExists($USER->uid)) { + if ($org->exists() and $org->mermberUIDExists($USER->uid)) { $org->removeUser($USER); - ensure(!$org->memberExists($USER->uid)); + ensure(!$org->mermberUIDExists($USER->uid)); } $LDAP->getUserEntry($USER->uid)->delete(); ensure(!$USER->exists()); @@ -220,9 +220,9 @@ function ensureUserNotRequestedAccountDeletion() function ensureUserNotInPIGroup(UnityGroup $pi_group) { global $USER; - if ($pi_group->memberExists($USER->uid)) { + if ($pi_group->mermberUIDExists($USER->uid)) { $pi_group->removeUser($USER); - ensure(!$pi_group->memberExists($USER->uid)); + ensure(!$pi_group->mermberUIDExists($USER->uid)); } } @@ -365,7 +365,7 @@ public function assertMessageExists( public function assertGroupMembers(UnityGroup $group, array $expected_members) { sort($expected_members); - $found_members = $group->getMembers(); + $found_members = $group->getMemberUIDs(); sort($found_members); $this->assertEqualsCanonicalizing($expected_members, $found_members); } diff --git a/webroot/panel/ajax/get_group_members.php b/webroot/panel/ajax/get_group_members.php index 8369ef78..8de03235 100644 --- a/webroot/panel/ajax/get_group_members.php +++ b/webroot/panel/ajax/get_group_members.php @@ -8,7 +8,7 @@ $gid = UnityHTTPD::getQueryParameter("gid"); $group = new UnityGroup($gid, $LDAP, $SQL, $MAILER, $WEBHOOK); -if (!$group->memberExists($USER->uid)) { +if (!$group->mermberUIDExists($USER->uid)) { UnityHTTPD::forbidden("not a group member"); } $members = $group->getGroupMembersAttributes(["gecos", "mail"]); diff --git a/webroot/panel/groups.php b/webroot/panel/groups.php index a7bf027c..b12b27d0 100644 --- a/webroot/panel/groups.php +++ b/webroot/panel/groups.php @@ -39,7 +39,7 @@ ); UnityHTTPD::redirect(); } - if ($pi_account->memberExists($USER->uid)) { + if ($pi_account->mermberUIDExists($USER->uid)) { UnityHTTPD::messageError( "Invalid Group Membership Request", "You're already in this PI group" diff --git a/workers/remove-users-from-group.php b/workers/remove-users-from-group.php index 33061b7b..aa4f4f97 100755 --- a/workers/remove-users-from-group.php +++ b/workers/remove-users-from-group.php @@ -27,7 +27,7 @@ function _die($msg) while (($line = fgets($handle)) !== false) { $uid = trim($line); $user = new UnityUser($uid, $LDAP, $SQL, $MAILER, $WEBHOOK); - if (!$group->memberExists($user->uid)) { + if (!$group->mermberUIDExists($user->uid)) { print "Skipping '$uid' who doesn't appear to be in '$gid'\n"; continue; } From b97ff20d266fd36402bf28abc22d5a25208b2cee Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 11:38:41 -0500 Subject: [PATCH 03/17] require --- resources/autoload.php | 1 + test/phpunit-bootstrap.php | 1 + 2 files changed, 2 insertions(+) diff --git a/resources/autoload.php b/resources/autoload.php index 158db4bc..2001c2a9 100644 --- a/resources/autoload.php +++ b/resources/autoload.php @@ -10,6 +10,7 @@ // submodule require_once __DIR__ . "/lib/phpopenldaper/src/PHPOpenLDAPer/LDAPEntry.php"; require_once __DIR__ . "/lib/phpopenldaper/src/PHPOpenLDAPer/LDAPConn.php"; +require_once __DIR__ . "/lib/phpopenldaper/src/PHPOpenLDAPer/PosixGroup.php"; // load libs require_once __DIR__ . "/lib/UnityLDAP.php"; diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index c2530af4..42c4bb6e 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -2,6 +2,7 @@ // submodule require_once __DIR__ . "/../resources/lib/phpopenldaper/src/PHPOpenLDAPer/LDAPEntry.php"; require_once __DIR__ . "/../resources/lib/phpopenldaper/src/PHPOpenLDAPer/LDAPConn.php"; +require_once __DIR__ . "/../resources/lib/phpopenldaper/src/PHPOpenLDAPer/PosixGroup.php"; require_once __DIR__ . "/../resources/lib/UnityLDAP.php"; require_once __DIR__ . "/../resources/lib/UnityUser.php"; From a26cad7666197d46e66c8f0fb2b09ea5abb777bf Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 11:41:22 -0500 Subject: [PATCH 04/17] keep base class in this repo --- resources/autoload.php | 2 +- resources/lib/PosixGroup.php | 69 ++++++++++++++++++++++++++++++++++++ resources/lib/UnityGroup.php | 1 - resources/lib/UnityOrg.php | 1 - resources/lib/phpopenldaper | 2 +- test/phpunit-bootstrap.php | 2 +- 6 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 resources/lib/PosixGroup.php diff --git a/resources/autoload.php b/resources/autoload.php index 2001c2a9..739087ae 100644 --- a/resources/autoload.php +++ b/resources/autoload.php @@ -10,7 +10,6 @@ // submodule require_once __DIR__ . "/lib/phpopenldaper/src/PHPOpenLDAPer/LDAPEntry.php"; require_once __DIR__ . "/lib/phpopenldaper/src/PHPOpenLDAPer/LDAPConn.php"; -require_once __DIR__ . "/lib/phpopenldaper/src/PHPOpenLDAPer/PosixGroup.php"; // load libs require_once __DIR__ . "/lib/UnityLDAP.php"; @@ -25,6 +24,7 @@ require_once __DIR__ . "/lib/UnityWebhook.php"; require_once __DIR__ . "/lib/UnityGithub.php"; require_once __DIR__ . "/lib/utils.php"; +require_once __DIR__ . "/lib/PosixGroup.php"; require_once __DIR__ . "/lib/exceptions/NoDieException.php"; require_once __DIR__ . "/lib/exceptions/SSOException.php"; require_once __DIR__ . "/lib/exceptions/ArrayKeyException.php"; diff --git a/resources/lib/PosixGroup.php b/resources/lib/PosixGroup.php new file mode 100644 index 00000000..ec047897 --- /dev/null +++ b/resources/lib/PosixGroup.php @@ -0,0 +1,69 @@ +gid = $gid; + $this->entry = $entry; + } + + public function getDN(): string + { + return $this->entry->getDN(); + } + + public function equals(PosixGroup $other_group): bool + { + if (!is_a($other_group, self::class)) { + throw new Exception( + "Unable to check equality because the parameter is not a " . + self::class . + " object", + ); + } + return $this->getDN() == $other_group->getDN(); + } + + public function __toString(): string + { + return $this->gid; + } + + public function exists(): bool + { + return $this->entry->exists(); + } + + public function getMemberUIDs(): array + { + $members = $this->entry->getAttribute("memberuid"); + sort($members); + return $members; + } + + public function addMemberUID(string $uid): void + { + $this->entry->appendAttribute("memberuid", $uid); + $this->entry->write(); + } + + public function removeMemberUID(string $uid): void + { + $this->entry->removeAttributeEntryByValue("memberuid", $uid); + $this->entry->write(); + } + + public function mermberUIDExists(string $uid): bool + { + return in_array($uid, $this->getMemberUIDs()); + } +} diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index bb455407..2613a89e 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -4,7 +4,6 @@ use PHPOpenLDAPer\LDAPEntry; use Exception; -use PHPOpenLDAPer\PosixGroup; /** * Class that represents a single PI group in the Unity Cluster. diff --git a/resources/lib/UnityOrg.php b/resources/lib/UnityOrg.php index 6168d940..45e2bf71 100644 --- a/resources/lib/UnityOrg.php +++ b/resources/lib/UnityOrg.php @@ -2,7 +2,6 @@ namespace UnityWebPortal\lib; use PHPOpenLDAPer\LDAPEntry; -use PHPOpenLDAPer\PosixGroup; class UnityOrg extends PosixGroup { diff --git a/resources/lib/phpopenldaper b/resources/lib/phpopenldaper index cd136ac6..7b93caa1 160000 --- a/resources/lib/phpopenldaper +++ b/resources/lib/phpopenldaper @@ -1 +1 @@ -Subproject commit cd136ac61fa1362f253aee6fc87eb97544aa2faf +Subproject commit 7b93caa16fc023f3c656f6560b1a6d72acb8677d diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index 42c4bb6e..a7e2ec71 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -2,7 +2,6 @@ // submodule require_once __DIR__ . "/../resources/lib/phpopenldaper/src/PHPOpenLDAPer/LDAPEntry.php"; require_once __DIR__ . "/../resources/lib/phpopenldaper/src/PHPOpenLDAPer/LDAPConn.php"; -require_once __DIR__ . "/../resources/lib/phpopenldaper/src/PHPOpenLDAPer/PosixGroup.php"; require_once __DIR__ . "/../resources/lib/UnityLDAP.php"; require_once __DIR__ . "/../resources/lib/UnityUser.php"; @@ -16,6 +15,7 @@ require_once __DIR__ . "/../resources/lib/UnityWebhook.php"; require_once __DIR__ . "/../resources/lib/UnityGithub.php"; require_once __DIR__ . "/../resources/lib/utils.php"; +require_once __DIR__ . "/../resources/lib/PosixGroup.php"; require_once __DIR__ . "/../resources/lib/exceptions/NoDieException.php"; require_once __DIR__ . "/../resources/lib/exceptions/SSOException.php"; require_once __DIR__ . "/../resources/lib/exceptions/ArrayKeyException.php"; From 216db6fff9ef0b82a5c71f9f13736b23608118c6 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 11:52:22 -0500 Subject: [PATCH 05/17] add comment --- resources/lib/PosixGroup.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/lib/PosixGroup.php b/resources/lib/PosixGroup.php index ec047897..37697326 100644 --- a/resources/lib/PosixGroup.php +++ b/resources/lib/PosixGroup.php @@ -5,6 +5,10 @@ use PHPOpenLDAPer\LDAPEntry; use \Exception; +/* +does not extend LDAPEntry because UnityGroup extends this and I don't want UnityGroup +to extend LDAPEntry because the functions from LDAPEntry should not be exposed there +*/ class PosixGroup { private LDAPEntry $entry; From 7d41fbf99883b2dbc42bccc7a469b3e2902bee70 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 12:11:05 -0500 Subject: [PATCH 06/17] reorder autoload --- resources/autoload.php | 2 +- test/phpunit-bootstrap.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/autoload.php b/resources/autoload.php index 739087ae..0531a750 100644 --- a/resources/autoload.php +++ b/resources/autoload.php @@ -14,6 +14,7 @@ // load libs require_once __DIR__ . "/lib/UnityLDAP.php"; require_once __DIR__ . "/lib/UnityUser.php"; +require_once __DIR__ . "/lib/PosixGroup.php"; require_once __DIR__ . "/lib/UnityGroup.php"; require_once __DIR__ . "/lib/UnityOrg.php"; require_once __DIR__ . "/lib/UnitySQL.php"; @@ -24,7 +25,6 @@ require_once __DIR__ . "/lib/UnityWebhook.php"; require_once __DIR__ . "/lib/UnityGithub.php"; require_once __DIR__ . "/lib/utils.php"; -require_once __DIR__ . "/lib/PosixGroup.php"; require_once __DIR__ . "/lib/exceptions/NoDieException.php"; require_once __DIR__ . "/lib/exceptions/SSOException.php"; require_once __DIR__ . "/lib/exceptions/ArrayKeyException.php"; diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index a7e2ec71..1c7d352f 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -5,6 +5,7 @@ require_once __DIR__ . "/../resources/lib/UnityLDAP.php"; require_once __DIR__ . "/../resources/lib/UnityUser.php"; +require_once __DIR__ . "/../resources/lib/PosixGroup.php"; require_once __DIR__ . "/../resources/lib/UnityGroup.php"; require_once __DIR__ . "/../resources/lib/UnityOrg.php"; require_once __DIR__ . "/../resources/lib/UnitySQL.php"; @@ -15,7 +16,6 @@ require_once __DIR__ . "/../resources/lib/UnityWebhook.php"; require_once __DIR__ . "/../resources/lib/UnityGithub.php"; require_once __DIR__ . "/../resources/lib/utils.php"; -require_once __DIR__ . "/../resources/lib/PosixGroup.php"; require_once __DIR__ . "/../resources/lib/exceptions/NoDieException.php"; require_once __DIR__ . "/../resources/lib/exceptions/SSOException.php"; require_once __DIR__ . "/../resources/lib/exceptions/ArrayKeyException.php"; From 101de31cde638baec66c62f914f163e41a50920c Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 12:12:39 -0500 Subject: [PATCH 07/17] construct PosixGroup --- resources/lib/UnityGroup.php | 5 +---- resources/lib/UnityOrg.php | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index 2613a89e..03a3a719 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -26,10 +26,7 @@ public function __construct( UnityMailer $MAILER, UnityWebhook $WEBHOOK, ) { - $gid = trim($gid); - $this->gid = $gid; - $this->entry = $LDAP->getPIGroupEntry($gid); - + parent::__construct($LDAP->getPIGroupEntry($gid), trim($gid)); $this->LDAP = $LDAP; $this->SQL = $SQL; $this->MAILER = $MAILER; diff --git a/resources/lib/UnityOrg.php b/resources/lib/UnityOrg.php index 45e2bf71..0e7e4a69 100644 --- a/resources/lib/UnityOrg.php +++ b/resources/lib/UnityOrg.php @@ -19,10 +19,7 @@ public function __construct( UnityMailer $MAILER, UnityWebhook $WEBHOOK, ) { - $gid = trim($gid); - $this->gid = $gid; - $this->entry = $LDAP->getOrgGroupEntry($this->gid); - + parent::__construct($LDAP->getOrgGroupEntry($this->gid), trim($gid)); $this->LDAP = $LDAP; $this->SQL = $SQL; $this->MAILER = $MAILER; From ab872386d79bf01493d93d820f2fa3a398ed99f9 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 12:15:07 -0500 Subject: [PATCH 08/17] fix attributes --- resources/lib/PosixGroup.php | 4 ++-- resources/lib/UnityGroup.php | 3 --- resources/lib/UnityOrg.php | 2 -- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/resources/lib/PosixGroup.php b/resources/lib/PosixGroup.php index 37697326..472797d0 100644 --- a/resources/lib/PosixGroup.php +++ b/resources/lib/PosixGroup.php @@ -11,8 +11,8 @@ */ class PosixGroup { - private LDAPEntry $entry; - private string $gid; + protected LDAPEntry $entry; + public string $gid; public function __construct(LDAPEntry $entry, string $gid) { diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index 03a3a719..62522f0d 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -11,9 +11,6 @@ class UnityGroup extends PosixGroup { public const string PI_PREFIX = "pi_"; - - public string $gid; - private LDAPEntry $entry; private UnityLDAP $LDAP; private UnitySQL $SQL; private UnityMailer $MAILER; diff --git a/resources/lib/UnityOrg.php b/resources/lib/UnityOrg.php index 0e7e4a69..8bc8a0c8 100644 --- a/resources/lib/UnityOrg.php +++ b/resources/lib/UnityOrg.php @@ -5,8 +5,6 @@ class UnityOrg extends PosixGroup { - public string $gid; - private LDAPEntry $entry; private UnityLDAP $LDAP; private UnitySQL $SQL; private UnityMailer $MAILER; From 42c7a080928f4f53e14d25ea41fb8fcb4b518b19 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 12:16:25 -0500 Subject: [PATCH 09/17] fix premature access --- resources/lib/UnityGroup.php | 3 ++- resources/lib/UnityOrg.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index 62522f0d..81a1f302 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -23,7 +23,8 @@ public function __construct( UnityMailer $MAILER, UnityWebhook $WEBHOOK, ) { - parent::__construct($LDAP->getPIGroupEntry($gid), trim($gid)); + $gid = trim($gid); + parent::__construct($LDAP->getPIGroupEntry($gid), $gid); $this->LDAP = $LDAP; $this->SQL = $SQL; $this->MAILER = $MAILER; diff --git a/resources/lib/UnityOrg.php b/resources/lib/UnityOrg.php index 8bc8a0c8..01255780 100644 --- a/resources/lib/UnityOrg.php +++ b/resources/lib/UnityOrg.php @@ -17,7 +17,8 @@ public function __construct( UnityMailer $MAILER, UnityWebhook $WEBHOOK, ) { - parent::__construct($LDAP->getOrgGroupEntry($this->gid), trim($gid)); + $gid = trim($gid); + parent::__construct($LDAP->getOrgGroupEntry($gid), $gid); $this->LDAP = $LDAP; $this->SQL = $SQL; $this->MAILER = $MAILER; From 0da224dea0db05056bf505d2b2bbd3732ab0fe5f Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 12:18:58 -0500 Subject: [PATCH 10/17] add batch member add/rm functions --- resources/lib/PosixGroup.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/resources/lib/PosixGroup.php b/resources/lib/PosixGroup.php index 472797d0..a4c6bf20 100644 --- a/resources/lib/PosixGroup.php +++ b/resources/lib/PosixGroup.php @@ -60,12 +60,28 @@ public function addMemberUID(string $uid): void $this->entry->write(); } + public function addMemberUIDs(array $uids): void + { + foreach ($uids as $uid) { + $this->entry->appendAttribute("memberuid", $uid); + } + $this->entry->write(); + } + public function removeMemberUID(string $uid): void { $this->entry->removeAttributeEntryByValue("memberuid", $uid); $this->entry->write(); } + public function removeMemberUIDs(array $uids): void + { + foreach ($uids as $uid) { + $this->entry->removeAttributeEntryByValue("memberuid", $uid); + } + $this->entry->write(); + } + public function mermberUIDExists(string $uid): bool { return in_array($uid, $this->getMemberUIDs()); From ece216facda0da9d79fe899ae40779dcb08f54e9 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 12:45:41 -0500 Subject: [PATCH 11/17] remove $gid from PosixGroup --- resources/lib/PosixGroup.php | 9 +-------- resources/lib/UnityGroup.php | 9 +++++++-- resources/lib/UnityOrg.php | 9 +++++++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/resources/lib/PosixGroup.php b/resources/lib/PosixGroup.php index a4c6bf20..5a271d58 100644 --- a/resources/lib/PosixGroup.php +++ b/resources/lib/PosixGroup.php @@ -12,11 +12,9 @@ class PosixGroup { protected LDAPEntry $entry; - public string $gid; - public function __construct(LDAPEntry $entry, string $gid) + public function __construct(LDAPEntry $entry) { - $this->gid = $gid; $this->entry = $entry; } @@ -37,11 +35,6 @@ public function equals(PosixGroup $other_group): bool return $this->getDN() == $other_group->getDN(); } - public function __toString(): string - { - return $this->gid; - } - public function exists(): bool { return $this->entry->exists(); diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index 81a1f302..ebfeb069 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -11,6 +11,7 @@ class UnityGroup extends PosixGroup { public const string PI_PREFIX = "pi_"; + public string $gid; private UnityLDAP $LDAP; private UnitySQL $SQL; private UnityMailer $MAILER; @@ -23,14 +24,18 @@ public function __construct( UnityMailer $MAILER, UnityWebhook $WEBHOOK, ) { - $gid = trim($gid); - parent::__construct($LDAP->getPIGroupEntry($gid), $gid); + parent::__construct($LDAP->getPIGroupEntry(trim($gid))); $this->LDAP = $LDAP; $this->SQL = $SQL; $this->MAILER = $MAILER; $this->WEBHOOK = $WEBHOOK; } + public function __toString(): string + { + return $this->gid; + } + public function requestGroup(bool $send_mail_to_admins, bool $send_mail = true): void { if ($this->exists()) { diff --git a/resources/lib/UnityOrg.php b/resources/lib/UnityOrg.php index 01255780..ac676284 100644 --- a/resources/lib/UnityOrg.php +++ b/resources/lib/UnityOrg.php @@ -5,6 +5,7 @@ class UnityOrg extends PosixGroup { + public string $gid; private UnityLDAP $LDAP; private UnitySQL $SQL; private UnityMailer $MAILER; @@ -17,14 +18,18 @@ public function __construct( UnityMailer $MAILER, UnityWebhook $WEBHOOK, ) { - $gid = trim($gid); - parent::__construct($LDAP->getOrgGroupEntry($gid), $gid); + parent::__construct($LDAP->getOrgGroupEntry(trim($gid))); $this->LDAP = $LDAP; $this->SQL = $SQL; $this->MAILER = $MAILER; $this->WEBHOOK = $WEBHOOK; } + public function __toString(): string + { + return $this->gid; + } + public function init(): void { \ensure(!$this->entry->exists()); From fc3269651bcd88383cfa9ff1329f1756b09fab13 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 12:54:12 -0500 Subject: [PATCH 12/17] mermber -> member --- resources/lib/PosixGroup.php | 2 +- resources/lib/UnityGroup.php | 4 ++-- resources/lib/UnityUser.php | 2 +- test/functional/PIMemberRequestTest.php | 2 +- test/functional/PiMemberApproveTest.php | 10 +++++----- test/functional/PiMemberDenyTest.php | 4 ++-- test/functional/PiRemoveUserTest.php | 12 ++++++------ test/phpunit-bootstrap.php | 8 ++++---- webroot/panel/ajax/get_group_members.php | 2 +- webroot/panel/groups.php | 2 +- workers/remove-users-from-group.php | 2 +- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/resources/lib/PosixGroup.php b/resources/lib/PosixGroup.php index 5a271d58..5850e326 100644 --- a/resources/lib/PosixGroup.php +++ b/resources/lib/PosixGroup.php @@ -75,7 +75,7 @@ public function removeMemberUIDs(array $uids): void $this->entry->write(); } - public function mermberUIDExists(string $uid): bool + public function memberUIDExists(string $uid): bool { return in_array($uid, $this->getMemberUIDs()); } diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index ebfeb069..895dbfbf 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -214,7 +214,7 @@ public function denyUser(UnityUser $new_user, bool $send_mail = true): void public function removeUser(UnityUser $new_user, bool $send_mail = true): void { - if (!$this->mermberUIDExists($new_user->uid)) { + if (!$this->memberUIDExists($new_user->uid)) { return; } if ($new_user->uid == $this->getOwner()->uid) { @@ -238,7 +238,7 @@ public function removeUser(UnityUser $new_user, bool $send_mail = true): void public function newUserRequest(UnityUser $new_user, bool $send_mail = true): void { - if ($this->mermberUIDExists($new_user->uid)) { + if ($this->memberUIDExists($new_user->uid)) { UnityHTTPD::errorLog("warning", "user '$new_user' already in group"); return; } diff --git a/resources/lib/UnityUser.php b/resources/lib/UnityUser.php index 0ae2f935..16b4514f 100644 --- a/resources/lib/UnityUser.php +++ b/resources/lib/UnityUser.php @@ -90,7 +90,7 @@ public function init( $org->init(); } - if (!$org->mermberUIDExists($this->uid)) { + if (!$org->memberUIDExists($this->uid)) { $org->addMemberUID($this->uid); } diff --git a/test/functional/PIMemberRequestTest.php b/test/functional/PIMemberRequestTest.php index 4a30176e..5d3975f1 100644 --- a/test/functional/PIMemberRequestTest.php +++ b/test/functional/PIMemberRequestTest.php @@ -38,7 +38,7 @@ public function testRequestMembership() $uid = $USER->uid; $this->assertFalse($USER->isPI()); $this->assertFalse($SQL->requestExists($uid, UnitySQL::REQUEST_BECOME_PI)); - $this->assertFalse($pi_group->mermberUIDExists($USER->uid)); + $this->assertFalse($pi_group->memberUIDExists($USER->uid)); try { $this->requestMembership($gid); $this->assertTrue($SQL->requestExists($uid, $gid)); diff --git a/test/functional/PiMemberApproveTest.php b/test/functional/PiMemberApproveTest.php index f1c5f2fd..51e90acb 100644 --- a/test/functional/PiMemberApproveTest.php +++ b/test/functional/PiMemberApproveTest.php @@ -54,7 +54,7 @@ public function testApproveNonexistentRequest() $this->assertTrue($piGroup->exists()); $this->assertGroupMembers($piGroup, [$piUID]); $this->assertEmpty($piGroup->getRequests()); - $this->assertFalse($piGroup->mermberUIDExists($user->uid)); + $this->assertFalse($piGroup->memberUIDExists($user->uid)); $this->assertEmpty($piGroup->getRequests()); try { $this->expectException(Exception::class); // FIXME more specific exception type @@ -77,7 +77,7 @@ public function testApproveMemberByPI() $this->assertTrue($USER->exists()); $this->assertTrue($pi_group->exists()); $this->assertGroupMembers($pi_group, [$pi_uid]); - $this->assertTrue(!$pi_group->mermberUIDExists($USER->uid)); + $this->assertTrue(!$pi_group->memberUIDExists($USER->uid)); $this->assertRequestedMembership(false, $gid); try { $this->requestGroupMembership($pi_group->gid); @@ -106,7 +106,7 @@ public function testApproveMemberByPI() $this->assertTrue(!$pi_group->requestExists($USER)); $this->assertRequestedMembership(false, $gid); - $this->assertTrue($pi_group->mermberUIDExists($USER->uid)); + $this->assertTrue($pi_group->memberUIDExists($USER->uid)); $this->assertTrue($USER->isQualified()); // $third_request_failed = false; @@ -137,7 +137,7 @@ public function testApproveMemberByAdmin() $this->assertTrue($USER->exists()); $this->assertTrue($pi_group->exists()); $this->assertGroupMembers($pi_group, [$pi_uid]); - $this->assertTrue(!$pi_group->mermberUIDExists($USER->uid)); + $this->assertTrue(!$pi_group->memberUIDExists($USER->uid)); $this->assertRequestedMembership(false, $gid); try { $this->requestGroupMembership($pi_group->gid); @@ -166,7 +166,7 @@ public function testApproveMemberByAdmin() $this->assertTrue(!$pi_group->requestExists($USER)); $this->assertRequestedMembership(false, $gid); - $this->assertTrue($pi_group->mermberUIDExists($USER->uid)); + $this->assertTrue($pi_group->memberUIDExists($USER->uid)); $this->assertTrue($USER->isQualified()); // $third_request_failed = false; diff --git a/test/functional/PiMemberDenyTest.php b/test/functional/PiMemberDenyTest.php index bf28fa36..b7a29c31 100644 --- a/test/functional/PiMemberDenyTest.php +++ b/test/functional/PiMemberDenyTest.php @@ -36,12 +36,12 @@ public function testDenyRequest() $requestedUser = new UnityUser(self::$requestUid, $LDAP, $SQL, $MAILER, $WEBHOOK); try { $piGroup->newUserRequest($requestedUser); - $this->assertFalse($piGroup->mermberUIDExists($requestedUser->uid)); + $this->assertFalse($piGroup->memberUIDExists($requestedUser->uid)); $piGroup->denyUser($requestedUser); $this->assertEmpty($piGroup->getRequests()); $this->assertEqualsCanonicalizing([$pi->uid], $piGroup->getMemberUIDs()); - $this->assertFalse($piGroup->mermberUIDExists($requestedUser->uid)); + $this->assertFalse($piGroup->memberUIDExists($requestedUser->uid)); } finally { $SQL->removeRequest(self::$requestUid, $piGroup->gid); } diff --git a/test/functional/PiRemoveUserTest.php b/test/functional/PiRemoveUserTest.php index f4669a64..89110da8 100644 --- a/test/functional/PiRemoveUserTest.php +++ b/test/functional/PiRemoveUserTest.php @@ -37,12 +37,12 @@ public function testRemoveUser() } } $this->assertNotEquals($pi->uid, $memberToDelete->uid); - $this->assertTrue($piGroup->mermberUIDExists($memberToDelete->uid)); + $this->assertTrue($piGroup->memberUIDExists($memberToDelete->uid)); try { $this->removeUser($memberToDelete->uid); - $this->assertFalse($piGroup->mermberUIDExists($memberToDelete->uid)); + $this->assertFalse($piGroup->memberUIDExists($memberToDelete->uid)); } finally { - if (!$piGroup->mermberUIDExists($memberToDelete->uid)) { + if (!$piGroup->memberUIDExists($memberToDelete->uid)) { $piGroup->newUserRequest($memberToDelete); $piGroup->approveUser($memberToDelete); } @@ -56,13 +56,13 @@ public function testRemovePIFromTheirOwnGroup() $pi = $USER; $piGroup = $USER->getPIGroup(); $this->assertTrue($piGroup->exists()); - $this->assertTrue($piGroup->mermberUIDExists($pi->uid)); + $this->assertTrue($piGroup->memberUIDExists($pi->uid)); $this->expectException(Exception::class); try { $this->removeUser($pi->uid); - $this->assertTrue($piGroup->mermberUIDExists($pi->uid)); + $this->assertTrue($piGroup->memberUIDExists($pi->uid)); } finally { - if (!$piGroup->mermberUIDExists($pi->uid)) { + if (!$piGroup->memberUIDExists($pi->uid)) { $piGroup->newUserRequest($pi); $piGroup->approveUser($pi); } diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index 1c7d352f..91411d95 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -175,9 +175,9 @@ function ensureUserDoesNotExist() $SQL->deleteRequestsByUser($USER->uid); if ($USER->exists()) { $org = $USER->getOrgGroup(); - if ($org->exists() and $org->mermberUIDExists($USER->uid)) { + if ($org->exists() and $org->memberUIDExists($USER->uid)) { $org->removeUser($USER); - ensure(!$org->mermberUIDExists($USER->uid)); + ensure(!$org->memberUIDExists($USER->uid)); } $LDAP->getUserEntry($USER->uid)->delete(); ensure(!$USER->exists()); @@ -221,9 +221,9 @@ function ensureUserNotRequestedAccountDeletion() function ensureUserNotInPIGroup(UnityGroup $pi_group) { global $USER; - if ($pi_group->mermberUIDExists($USER->uid)) { + if ($pi_group->memberUIDExists($USER->uid)) { $pi_group->removeUser($USER); - ensure(!$pi_group->mermberUIDExists($USER->uid)); + ensure(!$pi_group->memberUIDExists($USER->uid)); } } diff --git a/webroot/panel/ajax/get_group_members.php b/webroot/panel/ajax/get_group_members.php index 8de03235..15c0b08a 100644 --- a/webroot/panel/ajax/get_group_members.php +++ b/webroot/panel/ajax/get_group_members.php @@ -8,7 +8,7 @@ $gid = UnityHTTPD::getQueryParameter("gid"); $group = new UnityGroup($gid, $LDAP, $SQL, $MAILER, $WEBHOOK); -if (!$group->mermberUIDExists($USER->uid)) { +if (!$group->memberUIDExists($USER->uid)) { UnityHTTPD::forbidden("not a group member"); } $members = $group->getGroupMembersAttributes(["gecos", "mail"]); diff --git a/webroot/panel/groups.php b/webroot/panel/groups.php index b12b27d0..ce76ae12 100644 --- a/webroot/panel/groups.php +++ b/webroot/panel/groups.php @@ -39,7 +39,7 @@ ); UnityHTTPD::redirect(); } - if ($pi_account->mermberUIDExists($USER->uid)) { + if ($pi_account->memberUIDExists($USER->uid)) { UnityHTTPD::messageError( "Invalid Group Membership Request", "You're already in this PI group" diff --git a/workers/remove-users-from-group.php b/workers/remove-users-from-group.php index aa4f4f97..198b9ee9 100755 --- a/workers/remove-users-from-group.php +++ b/workers/remove-users-from-group.php @@ -27,7 +27,7 @@ function _die($msg) while (($line = fgets($handle)) !== false) { $uid = trim($line); $user = new UnityUser($uid, $LDAP, $SQL, $MAILER, $WEBHOOK); - if (!$group->mermberUIDExists($user->uid)) { + if (!$group->memberUIDExists($user->uid)) { print "Skipping '$uid' who doesn't appear to be in '$gid'\n"; continue; } From 8cd80262f2703d4966d760266b2a4f6eb8f191bb Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 12:56:17 -0500 Subject: [PATCH 13/17] forgot to set attribute --- resources/lib/UnityGroup.php | 1 + resources/lib/UnityOrg.php | 1 + 2 files changed, 2 insertions(+) diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index 895dbfbf..8d24a61b 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -25,6 +25,7 @@ public function __construct( UnityWebhook $WEBHOOK, ) { parent::__construct($LDAP->getPIGroupEntry(trim($gid))); + $this->gid = $gid; $this->LDAP = $LDAP; $this->SQL = $SQL; $this->MAILER = $MAILER; diff --git a/resources/lib/UnityOrg.php b/resources/lib/UnityOrg.php index ac676284..4ccedcc3 100644 --- a/resources/lib/UnityOrg.php +++ b/resources/lib/UnityOrg.php @@ -19,6 +19,7 @@ public function __construct( UnityWebhook $WEBHOOK, ) { parent::__construct($LDAP->getOrgGroupEntry(trim($gid))); + $this->gid = $gid; $this->LDAP = $LDAP; $this->SQL = $SQL; $this->MAILER = $MAILER; From a28ff42e1a93ca5f93dfb162aecfbc021dc9464a Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 13:01:35 -0500 Subject: [PATCH 14/17] fix function name --- test/phpunit-bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index 91411d95..ce3792ba 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -176,7 +176,7 @@ function ensureUserDoesNotExist() if ($USER->exists()) { $org = $USER->getOrgGroup(); if ($org->exists() and $org->memberUIDExists($USER->uid)) { - $org->removeUser($USER); + $org->removeMemberUID($USER->uid); ensure(!$org->memberUIDExists($USER->uid)); } $LDAP->getUserEntry($USER->uid)->delete(); From ca94443d2865370e310f6ef73c578a9269c142c6 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 13:13:08 -0500 Subject: [PATCH 15/17] 1st draft --- defaults/config.ini.default | 5 ++++- resources/lib/UnityLDAP.php | 38 ++++++++++++++++++++++--------------- resources/lib/UnityUser.php | 13 ++++--------- test/phpunit-bootstrap.php | 14 ++------------ 4 files changed, 33 insertions(+), 37 deletions(-) diff --git a/defaults/config.ini.default b/defaults/config.ini.default index a505140f..c291a0f6 100644 --- a/defaults/config.ini.default +++ b/defaults/config.ini.default @@ -26,11 +26,14 @@ pass = "password" ; Admin bind password custom_user_mappings_dir = "deployment/custom_user_mappings" ; for internal use only basedn = "dc=unityhpc,dc=test" ; Base search DN user_ou = "ou=users,dc=unityhpc,dc=test" ; User organizational unit (may contain more than user group) -qualified_user_group = "cn=unityusers,dc=unityhpc,dc=test" ; Qualified user group (in at least one PI group) group_ou = "ou=groups,dc=unityhpc,dc=test" ; Group organizational unit pigroup_ou = "ou=pi_groups,dc=unityhpc,dc=test" ; PI Group organizational unit orggroup_ou = "ou=org_groups,dc=unityhpc,dc=test" ; ORG group organizational unit admin_group = "cn=web_admins,dc=unityhpc,dc=test" ; admin dn (members of this group are admins on the web portal) +qualified_user_group = "cn=unityusers,dc=unityhpc,dc=test" ; Qualified user group (in at least one PI group) +locked_user_group = "cn=locked,dc=unityhpc,dc=test" ; locked user group dn +idlelocked_user_group = "cn=idlelocked,dc=unityhpc,dc=test" ; idlelocked user group dn +ghost_user_group = "cn=ghost,dc=unityhpc,dc=test" ; ghost user group dn def_user_shell = "/bin/bash" ; Default shell for new users offset_UIDGID = 1000000 ; start point when allocating new UID/GID pairs for a new user offset_PIGID = 2000000 ; start point when allocating new GID for a new PI group diff --git a/resources/lib/UnityLDAP.php b/resources/lib/UnityLDAP.php index 292be4a1..a407f8e7 100644 --- a/resources/lib/UnityLDAP.php +++ b/resources/lib/UnityLDAP.php @@ -5,6 +5,7 @@ use UnityWebPortal\lib\exceptions\EntryNotFoundException; use PHPOpenLDAPer\LDAPConn; use PHPOpenLDAPer\LDAPEntry; +use UnityWebPortal\lib\PosixGroup; /** * An LDAP connection class which extends LDAPConn tailored for the Unity Cluster @@ -35,8 +36,12 @@ class UnityLDAP extends LDAPConn private LDAPEntry $groupOU; private LDAPEntry $pi_groupOU; private LDAPEntry $org_groupOU; - private LDAPEntry $adminGroup; - private LDAPEntry $qualifiedUserGroup; + + public PosixGroup $adminGroup; + public PosixGroup $qualifiedUserGroup; + public PosixGroup $lockedUserGroup; + public PosixGroup $idlelockedUserGroup; + public PosixGroup $ghostUserGroup; public function __construct() { @@ -46,8 +51,21 @@ public function __construct() $this->groupOU = $this->getEntry(CONFIG["ldap"]["group_ou"]); $this->pi_groupOU = $this->getEntry(CONFIG["ldap"]["pigroup_ou"]); $this->org_groupOU = $this->getEntry(CONFIG["ldap"]["orggroup_ou"]); - $this->adminGroup = $this->getEntry(CONFIG["ldap"]["admin_group"]); - $this->qualifiedUserGroup = $this->getEntry(CONFIG["ldap"]["qualified_user_group"]); + $this->adminGroup = new PosixGroup( + new LDAPEntry($this->conn, CONFIG["ldap"]["admin_group"]), + ); + $this->qualifiedUserGroup = new PosixGroup( + new LDAPEntry($this->conn, CONFIG["ldap"]["qualified_user_group"]), + ); + $this->lockedUserGroup = new PosixGroup( + new LDAPEntry($this->conn, CONFIG["ldap"]["locked_user_group"]), + ); + $this->idlelockedUserGroup = new PosixGroup( + new LDAPEntry($this->conn, CONFIG["ldap"]["idlelocked_user_group"]), + ); + $this->ghostUserGroup = new PosixGroup( + new LDAPEntry($this->conn, CONFIG["ldap"]["ghost_user_group"]), + ); } public function getUserOU(): LDAPEntry @@ -70,16 +88,6 @@ public function getOrgGroupOU(): LDAPEntry return $this->org_groupOU; } - public function getAdminGroup(): LDAPEntry - { - return $this->adminGroup; - } - - public function getQualifiedUserGroup(): LDAPEntry - { - return $this->qualifiedUserGroup; - } - public function getDefUserShell(): string { return $this->def_user_shell; @@ -191,7 +199,7 @@ public function getQualifiedUsersUIDs(): array { // should not use $user_ou->getChildren or $base_ou->getChildren(objectClass=posixAccount) // qualified users might be outside user ou, and not all users in LDAP tree are qualified users - return $this->qualifiedUserGroup->getAttribute("memberuid"); + return $this->qualifiedUserGroup->getMemberUIDs(); } public function getQualifiedUsers($UnitySQL, $UnityMailer, $UnityWebhook): array diff --git a/resources/lib/UnityUser.php b/resources/lib/UnityUser.php index 16b4514f..d1795097 100644 --- a/resources/lib/UnityUser.php +++ b/resources/lib/UnityUser.php @@ -99,7 +99,7 @@ public function init( public function isQualified(): bool { - return $this->LDAP->getQualifiedUserGroup()->attributeValueExists("memberUid", $this->uid); + return $this->LDAP->qualifiedUserGroup->memberUIDExists($this->uid); } public function setIsQualified(bool $newIsQualified, bool $doSendMail = true): void @@ -109,8 +109,7 @@ public function setIsQualified(bool $newIsQualified, bool $doSendMail = true): v return; } if ($newIsQualified) { - $this->LDAP->getQualifiedUserGroup()->appendAttribute("memberuid", $this->uid); - $this->LDAP->getQualifiedUserGroup()->write(); + $this->LDAP->qualifiedUserGroup->addMemberUID($this->uid); if ($doSendMail) { $this->MAILER->sendMail($this->getMail(), "user_qualified", [ "user" => $this->uid, @@ -118,10 +117,7 @@ public function setIsQualified(bool $newIsQualified, bool $doSendMail = true): v ]); } } else { - $this->LDAP - ->getQualifiedUserGroup() - ->removeAttributeEntryByValue("memberuid", $this->uid); - $this->LDAP->getQualifiedUserGroup()->write(); + $this->LDAP->qualifiedUserGroup->removeMemberUID($this->uid); if ($doSendMail) { $this->MAILER->sendMail($this->getMail(), "user_dequalified", [ "user" => $this->uid, @@ -324,8 +320,7 @@ public function getHomeDir(): string */ public function isAdmin(): bool { - $admins = $this->LDAP->getAdminGroup()->getAttribute("memberuid"); - return in_array($this->uid, $admins); + return $this->LDAP->adminGroup->memberUIDExists($this->uid); } /** diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index ce3792ba..0b446af2 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -186,18 +186,8 @@ function ensureUserDoesNotExist() $USER->getGroupEntry()->delete(); ensure(!$USER->getGroupEntry()->exists()); } - $qualified_users_group = $LDAP->getQualifiedUserGroup(); - $all_member_uids = $qualified_users_group->getAttribute("memberuid"); - if (in_array($USER->uid, $all_member_uids)) { - $qualified_users_group->setAttribute( - "memberuid", - // array_diff will break the contiguity of the array indexes - // ldap_mod_replace requires contiguity, array_values restores contiguity - array_values(array_diff($all_member_uids, [$USER->uid])), - ); - $qualified_users_group->write(); - ensure(!in_array($USER->uid, $qualified_users_group->getAttribute("memberuid"))); - } + $USER->setIsQualified(false); + ensure(!$LDAP->qualifiedUserGroup->memberUIDExists($USER->uid)); } function ensureOrgGroupDoesNotExist() From 820d8ace813a9fade5f5592e52fb53c3ada4c6d7 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 13:27:28 -0500 Subject: [PATCH 16/17] modifiers --- defaults/config.ini.default | 10 ++++---- resources/init.php | 2 +- resources/lib/UnityGroup.php | 4 ++-- resources/lib/UnityLDAP.php | 27 +++++---------------- resources/lib/UnityUser.php | 30 ++++++++++-------------- test/functional/PIBecomeApproveTest.php | 2 +- test/functional/PiMemberApproveTest.php | 4 ++-- test/functional/ViewAsUserTest.php | 4 ++-- test/phpunit-bootstrap.php | 4 ++-- webroot/admin/ajax/get_group_members.php | 2 +- webroot/admin/ajax/get_page_contents.php | 2 +- webroot/admin/content.php | 2 +- webroot/admin/notices.php | 2 +- webroot/admin/pi-mgmt.php | 2 +- webroot/admin/user-mgmt.php | 2 +- webroot/panel/account.php | 2 +- 16 files changed, 40 insertions(+), 61 deletions(-) diff --git a/defaults/config.ini.default b/defaults/config.ini.default index c291a0f6..71376d44 100644 --- a/defaults/config.ini.default +++ b/defaults/config.ini.default @@ -29,15 +29,15 @@ user_ou = "ou=users,dc=unityhpc,dc=test" ; User organizational unit (may contai group_ou = "ou=groups,dc=unityhpc,dc=test" ; Group organizational unit pigroup_ou = "ou=pi_groups,dc=unityhpc,dc=test" ; PI Group organizational unit orggroup_ou = "ou=org_groups,dc=unityhpc,dc=test" ; ORG group organizational unit -admin_group = "cn=web_admins,dc=unityhpc,dc=test" ; admin dn (members of this group are admins on the web portal) -qualified_user_group = "cn=unityusers,dc=unityhpc,dc=test" ; Qualified user group (in at least one PI group) -locked_user_group = "cn=locked,dc=unityhpc,dc=test" ; locked user group dn -idlelocked_user_group = "cn=idlelocked,dc=unityhpc,dc=test" ; idlelocked user group dn -ghost_user_group = "cn=ghost,dc=unityhpc,dc=test" ; ghost user group dn def_user_shell = "/bin/bash" ; Default shell for new users offset_UIDGID = 1000000 ; start point when allocating new UID/GID pairs for a new user offset_PIGID = 2000000 ; start point when allocating new GID for a new PI group offset_ORGGID = 3000000 ; start point when allocating new GID for a new org group +user_modifier_groups[admin] = "cn=web_admins,dc=unityhpc,dc=test" ; admin user group dn +user_modifier_groups[ghost] = "cn=ghost,dc=unityhpc,dc=test" ; ghost user group dn +user_modifier_groups[idlelocked] = "cn=idlelocked,dc=unityhpc,dc=test" ; idlelocked user group dn +user_modifier_groups[locked] = "cn=locked,dc=unityhpc,dc=test" ; locked user group dn +user_modifier_groups[qualified] = "cn=unityusers,dc=unityhpc,dc=test" ; qualified user group (in at least one PI group) [sql] host = "sql" ; mariadb hostname diff --git a/resources/init.php b/resources/init.php index f23f2c2d..0fa0e395 100644 --- a/resources/init.php +++ b/resources/init.php @@ -44,7 +44,7 @@ $_SESSION["SSO"] = $SSO; $OPERATOR = new UnityUser($SSO["user"], $LDAP, $SQL, $MAILER, $WEBHOOK); - $_SESSION["is_admin"] = $OPERATOR->isAdmin(); + $_SESSION["is_admin"] = $OPERATOR->getModifier("admin"); if (isset($_SESSION["viewUser"]) && $_SESSION["is_admin"]) { $USER = new UnityUser($_SESSION["viewUser"], $LDAP, $SQL, $MAILER, $WEBHOOK); diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index 8d24a61b..9c6300ee 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -85,7 +85,7 @@ public function approveGroup(?UnityUser $operator = null, bool $send_mail = true if ($send_mail) { $this->MAILER->sendMail($this->getOwner()->getMail(), "group_created"); } - $this->getOwner()->setIsQualified(true); // having your own group makes you qualified + $this->getOwner()->setModifier("qualified", true); // having your own group makes you qualified } /** @@ -191,7 +191,7 @@ public function approveUser(UnityUser $new_user, bool $send_mail = true): void "org" => $new_user->getOrg(), ]); } - $new_user->setIsQualified(true); // being in a group makes you qualified + $new_user->setModifier("qualified", true); // being in a group makes you qualified } public function denyUser(UnityUser $new_user, bool $send_mail = true): void diff --git a/resources/lib/UnityLDAP.php b/resources/lib/UnityLDAP.php index a407f8e7..bf6d4303 100644 --- a/resources/lib/UnityLDAP.php +++ b/resources/lib/UnityLDAP.php @@ -37,11 +37,7 @@ class UnityLDAP extends LDAPConn private LDAPEntry $pi_groupOU; private LDAPEntry $org_groupOU; - public PosixGroup $adminGroup; - public PosixGroup $qualifiedUserGroup; - public PosixGroup $lockedUserGroup; - public PosixGroup $idlelockedUserGroup; - public PosixGroup $ghostUserGroup; + public array $userModifierGroups; public function __construct() { @@ -51,21 +47,10 @@ public function __construct() $this->groupOU = $this->getEntry(CONFIG["ldap"]["group_ou"]); $this->pi_groupOU = $this->getEntry(CONFIG["ldap"]["pigroup_ou"]); $this->org_groupOU = $this->getEntry(CONFIG["ldap"]["orggroup_ou"]); - $this->adminGroup = new PosixGroup( - new LDAPEntry($this->conn, CONFIG["ldap"]["admin_group"]), - ); - $this->qualifiedUserGroup = new PosixGroup( - new LDAPEntry($this->conn, CONFIG["ldap"]["qualified_user_group"]), - ); - $this->lockedUserGroup = new PosixGroup( - new LDAPEntry($this->conn, CONFIG["ldap"]["locked_user_group"]), - ); - $this->idlelockedUserGroup = new PosixGroup( - new LDAPEntry($this->conn, CONFIG["ldap"]["idlelocked_user_group"]), - ); - $this->ghostUserGroup = new PosixGroup( - new LDAPEntry($this->conn, CONFIG["ldap"]["ghost_user_group"]), - ); + $this->userModifierGroups = []; + foreach (CONFIG["ldap"]["user_modifier_groups"] as $gid => $dn) { + $this->userModifierGroups[$gid] = new PosixGroup(new LDAPEntry($this->conn, $dn)); + } } public function getUserOU(): LDAPEntry @@ -199,7 +184,7 @@ public function getQualifiedUsersUIDs(): array { // should not use $user_ou->getChildren or $base_ou->getChildren(objectClass=posixAccount) // qualified users might be outside user ou, and not all users in LDAP tree are qualified users - return $this->qualifiedUserGroup->getMemberUIDs(); + return $this->userModifierGroups["qualified"]->getMemberUIDs(); } public function getQualifiedUsers($UnitySQL, $UnityMailer, $UnityWebhook): array diff --git a/resources/lib/UnityUser.php b/resources/lib/UnityUser.php index d1795097..642332dd 100644 --- a/resources/lib/UnityUser.php +++ b/resources/lib/UnityUser.php @@ -97,31 +97,33 @@ public function init( $this->SQL->addLog($this->uid, $_SERVER["REMOTE_ADDR"], "user_added", $this->uid); } - public function isQualified(): bool + public function getModifier($modifier): bool { - return $this->LDAP->qualifiedUserGroup->memberUIDExists($this->uid); + return $this->LDAP->userModifierGroups[$modifier]->memberUIDExists($this->uid); } - public function setIsQualified(bool $newIsQualified, bool $doSendMail = true): void + public function setModifier($modifier, bool $newValue, bool $doSendMail = true): void { - $oldIsQualified = $this->isQualified(); - if ($oldIsQualified == $newIsQualified) { + $oldValue = $this->getModifier($modifier); + if ($oldValue == $newValue) { return; } - if ($newIsQualified) { - $this->LDAP->qualifiedUserGroup->addMemberUID($this->uid); + if ($newValue) { + $this->LDAP->userModifierGroups[$modifier]->addMemberUID($this->uid); if ($doSendMail) { - $this->MAILER->sendMail($this->getMail(), "user_qualified", [ + $this->MAILER->sendMail($this->getMail(), "user_modifier_added", [ "user" => $this->uid, "org" => $this->getOrg(), + "modifier" => $modifier, ]); } } else { - $this->LDAP->qualifiedUserGroup->removeMemberUID($this->uid); + $this->LDAP->userModifierGroups[$modifier]->removeMemberUID($this->uid); if ($doSendMail) { - $this->MAILER->sendMail($this->getMail(), "user_dequalified", [ + $this->MAILER->sendMail($this->getMail(), "user_modifier_removed", [ "user" => $this->uid, "org" => $this->getOrg(), + "modifier" => $modifier, ]); } } @@ -315,14 +317,6 @@ public function getHomeDir(): string return $this->entry->getAttribute("homedirectory"); } - /** - * Checks if the current account is an admin - */ - public function isAdmin(): bool - { - return $this->LDAP->adminGroup->memberUIDExists($this->uid); - } - /** * Checks if current user is a PI */ diff --git a/test/functional/PIBecomeApproveTest.php b/test/functional/PIBecomeApproveTest.php index afe7a9e3..451853e7 100644 --- a/test/functional/PIBecomeApproveTest.php +++ b/test/functional/PIBecomeApproveTest.php @@ -64,7 +64,7 @@ public function testApprovePI() $this->assertRequestedPIGroup(false); $this->assertTrue($pi_group->exists()); - $this->assertTrue($USER->isQualified()); + $this->assertTrue($USER->getModifier("qualified")); // $third_request_failed = false; // try { diff --git a/test/functional/PiMemberApproveTest.php b/test/functional/PiMemberApproveTest.php index 51e90acb..06639843 100644 --- a/test/functional/PiMemberApproveTest.php +++ b/test/functional/PiMemberApproveTest.php @@ -107,7 +107,7 @@ public function testApproveMemberByPI() $this->assertTrue(!$pi_group->requestExists($USER)); $this->assertRequestedMembership(false, $gid); $this->assertTrue($pi_group->memberUIDExists($USER->uid)); - $this->assertTrue($USER->isQualified()); + $this->assertTrue($USER->getModifier("qualified")); // $third_request_failed = false; // try { @@ -167,7 +167,7 @@ public function testApproveMemberByAdmin() $this->assertTrue(!$pi_group->requestExists($USER)); $this->assertRequestedMembership(false, $gid); $this->assertTrue($pi_group->memberUIDExists($USER->uid)); - $this->assertTrue($USER->isQualified()); + $this->assertTrue($USER->getModifier("qualified")); // $third_request_failed = false; // try { diff --git a/test/functional/ViewAsUserTest.php b/test/functional/ViewAsUserTest.php index 99383c1c..b3a20b01 100644 --- a/test/functional/ViewAsUserTest.php +++ b/test/functional/ViewAsUserTest.php @@ -10,7 +10,7 @@ public function _testViewAsUser(array $beforeUser, array $afterUser) switchUser(...$afterUser); $afterUid = $USER->uid; switchUser(...$beforeUser); - // $this->assertTrue($USER->isAdmin()); + // $this->assertTrue($USER->getModifier("admin")); $beforeUid = $USER->uid; // $this->assertNotEquals($afterUid, $beforeUid); http_post(__DIR__ . "/../../webroot/admin/user-mgmt.php", [ @@ -57,7 +57,7 @@ public function testNonAdminViewAsAdmin() global $USER; switchUser(...getAdminUser()); $adminUid = $USER->uid; - $this->assertTrue($USER->isAdmin()); + $this->assertTrue($USER->getModifier("admin")); switchUser(...getNormalUser()); http_post(__DIR__ . "/../../webroot/admin/user-mgmt.php", [ "form_type" => "viewAsUser", diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index 0b446af2..a31a1deb 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -186,8 +186,8 @@ function ensureUserDoesNotExist() $USER->getGroupEntry()->delete(); ensure(!$USER->getGroupEntry()->exists()); } - $USER->setIsQualified(false); - ensure(!$LDAP->qualifiedUserGroup->memberUIDExists($USER->uid)); + $USER->setModifier("qualified", false); + ensure(!$LDAP->userModifierGroups["qualified"]->memberUIDExists($USER->uid)); } function ensureOrgGroupDoesNotExist() diff --git a/webroot/admin/ajax/get_group_members.php b/webroot/admin/ajax/get_group_members.php index 7bd4c618..e3dcc8e2 100644 --- a/webroot/admin/ajax/get_group_members.php +++ b/webroot/admin/ajax/get_group_members.php @@ -5,7 +5,7 @@ use UnityWebPortal\lib\UnityGroup; use UnityWebPortal\lib\UnityHTTPD; -if (!$USER->isAdmin()) { +if (!$USER->getModifier("admin")) { UnityHTTPD::forbidden("not an admin"); } diff --git a/webroot/admin/ajax/get_page_contents.php b/webroot/admin/ajax/get_page_contents.php index b4f62292..c27b3971 100644 --- a/webroot/admin/ajax/get_page_contents.php +++ b/webroot/admin/ajax/get_page_contents.php @@ -4,7 +4,7 @@ use UnityWebPortal\lib\UnityHTTPD; -if (!$USER->isAdmin()) { +if (!$USER->getModifier("admin")) { UnityHTTPD::forbidden("not an admin"); } diff --git a/webroot/admin/content.php b/webroot/admin/content.php index 620a8fac..4001a2e6 100644 --- a/webroot/admin/content.php +++ b/webroot/admin/content.php @@ -4,7 +4,7 @@ use UnityWebPortal\lib\UnityHTTPD; -if (!$USER->isAdmin()) { +if (!$USER->getModifier("admin")) { UnityHTTPD::forbidden("not an admin"); } diff --git a/webroot/admin/notices.php b/webroot/admin/notices.php index 2c42cac9..3cb9d1f2 100644 --- a/webroot/admin/notices.php +++ b/webroot/admin/notices.php @@ -4,7 +4,7 @@ use UnityWebPortal\lib\UnityHTTPD; -if (!$USER->isAdmin()) { +if (!$USER->getModifier("admin")) { UnityHTTPD::forbidden("not an admin"); } diff --git a/webroot/admin/pi-mgmt.php b/webroot/admin/pi-mgmt.php index 7b161a4b..16d94976 100644 --- a/webroot/admin/pi-mgmt.php +++ b/webroot/admin/pi-mgmt.php @@ -7,7 +7,7 @@ use UnityWebPortal\lib\UnityHTTPD; use UnityWebPortal\lib\UnitySQL; -if (!$USER->isAdmin()) { +if (!$USER->getModifier("admin")) { UnityHTTPD::forbidden("not an admin"); } diff --git a/webroot/admin/user-mgmt.php b/webroot/admin/user-mgmt.php index 47b347fc..56c20754 100644 --- a/webroot/admin/user-mgmt.php +++ b/webroot/admin/user-mgmt.php @@ -4,7 +4,7 @@ use UnityWebPortal\lib\UnityHTTPD; -if (!$USER->isAdmin()) { +if (!$USER->getModifier("admin")) { UnityHTTPD::forbidden("not an admin"); } diff --git a/webroot/panel/account.php b/webroot/panel/account.php index 8c2cf1a2..a3003653 100644 --- a/webroot/panel/account.php +++ b/webroot/panel/account.php @@ -131,7 +131,7 @@ if ($isPI) { echo "

You are curently a principal investigator on the Unity Cluster

"; -} elseif ($USER->isQualified()) { +} elseif ($USER->getModifier("qualified")) { echo "

You are curently a qualified user on the Unity Cluster

"; } else { $tos_url = CONFIG["site"]["terms_of_service_url"]; From 5ab0edaef3dfcd98011256f1703a732cb85eb4c1 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 15 Dec 2025 14:58:27 -0500 Subject: [PATCH 17/17] setup mail templates --- .pre-commit-config.yaml | 3 + resources/lib/UnityGroup.php | 3 +- resources/lib/UnityUser.php | 22 +++++++- resources/mail/user_dequalified.php | 10 ---- resources/mail/user_modifier_added.php | 55 +++++++++++++++++++ resources/mail/user_modifier_added_admin.php | 39 +++++++++++++ resources/mail/user_modifier_removed.php | 44 +++++++++++++++ .../mail/user_modifier_removed_admin.php | 39 +++++++++++++ resources/mail/user_qualified.php | 20 ------- 9 files changed, 202 insertions(+), 33 deletions(-) delete mode 100644 resources/mail/user_dequalified.php create mode 100644 resources/mail/user_modifier_added.php create mode 100644 resources/mail/user_modifier_added_admin.php create mode 100644 resources/mail/user_modifier_removed.php create mode 100644 resources/mail/user_modifier_removed_admin.php delete mode 100644 resources/mail/user_qualified.php diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4cb2b061..7488fb88 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,6 +31,7 @@ repos: resources/lib/phpopenldaper/.*| vendor/.*| resources/lib/.*| + resources/mail/.*| )$ - repo: https://github.com/rbubley/mirrors-prettier @@ -47,6 +48,7 @@ repos: vendor/.*| resources/templates/.*| webroot/.*| + resources/mail/.*| )$ # linters (work required) ######################################################################## @@ -81,6 +83,7 @@ repos: resources/lib/phpopenldaper/.*| vendor/.*| resources/lib/.*| + resources/mail/.*| )$ - id: php-l name: php -l diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index 9c6300ee..9c07cdbd 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -191,7 +191,8 @@ public function approveUser(UnityUser $new_user, bool $send_mail = true): void "org" => $new_user->getOrg(), ]); } - $new_user->setModifier("qualified", true); // being in a group makes you qualified + // being in a group makes you qualified + $new_user->setModifier("qualified", true, true, false); } public function denyUser(UnityUser $new_user, bool $send_mail = true): void diff --git a/resources/lib/UnityUser.php b/resources/lib/UnityUser.php index 642332dd..b3395841 100644 --- a/resources/lib/UnityUser.php +++ b/resources/lib/UnityUser.php @@ -102,8 +102,12 @@ public function getModifier($modifier): bool return $this->LDAP->userModifierGroups[$modifier]->memberUIDExists($this->uid); } - public function setModifier($modifier, bool $newValue, bool $doSendMail = true): void - { + public function setModifier( + $modifier, + bool $newValue, + bool $doSendMail = true, + bool $doSendMailAdmin = true, + ): void { $oldValue = $this->getModifier($modifier); if ($oldValue == $newValue) { return; @@ -117,6 +121,13 @@ public function setModifier($modifier, bool $newValue, bool $doSendMail = true): "modifier" => $modifier, ]); } + if ($doSendMailAdmin) { + $this->MAILER->sendMail($this->getMail(), "user_modifier_added_admin", [ + "user" => $this->uid, + "org" => $this->getOrg(), + "modifier" => $modifier, + ]); + } } else { $this->LDAP->userModifierGroups[$modifier]->removeMemberUID($this->uid); if ($doSendMail) { @@ -126,6 +137,13 @@ public function setModifier($modifier, bool $newValue, bool $doSendMail = true): "modifier" => $modifier, ]); } + if ($doSendMailAdmin) { + $this->MAILER->sendMail($this->getMail(), "user_modifier_removed_admin", [ + "user" => $this->uid, + "org" => $this->getOrg(), + "modifier" => $modifier, + ]); + } } } diff --git a/resources/mail/user_dequalified.php b/resources/mail/user_dequalified.php deleted file mode 100644 index 36efcc04..00000000 --- a/resources/mail/user_dequalified.php +++ /dev/null @@ -1,10 +0,0 @@ -Subject = "User Deactivated"; ?> - -

Hello,

- -

Your account on the Unity cluster has been deactivated.

- -

If you believe this to be a mistake, please reply to this email as soon as possible.

diff --git a/resources/mail/user_modifier_added.php b/resources/mail/user_modifier_added.php new file mode 100644 index 00000000..ac25beb2 --- /dev/null +++ b/resources/mail/user_modifier_added.php @@ -0,0 +1,55 @@ + +Subject = "User Activated"; ?> +

Hello,

+

Your account on the Unity cluster has been activated. Your account details are below:

+

+Username +
+Organization +

+

+Please login to the web portal to access Unity. +If you need console access, you will need to set your SSH keys in the +account settings +page. +

+

If you believe this to be a mistake, please reply to this email as soon as possible.

+ + + + +Subject = "User Deleted"; ?> +

Hello,

+

Your account on the Unity cluster has been deleted.

+

If you believe this to be a mistake, please reply to this email as soon as possible.

+ + + + +Subject = "User Locked"; ?> +

Hello,

+

Your account on the Unity cluster has been locked.

+

If you believe this to be a mistake, please reply to this email as soon as possible.

+ + + + +Subject = "User Locked"; ?> +

Hello,

+

Your account on the Unity cluster has been locked due to inactivity.

+

If you believe this to be a mistake, please reply to this email as soon as possible.

+ + + + +Subject = "User Promoted"; ?> +

Hello,

+

Your account on the Unity cluster has been promoted to admin.

+

If you believe this to be a mistake, please reply to this email as soon as possible.

+ + + + + + diff --git a/resources/mail/user_modifier_added_admin.php b/resources/mail/user_modifier_added_admin.php new file mode 100644 index 00000000..99cc8691 --- /dev/null +++ b/resources/mail/user_modifier_added_admin.php @@ -0,0 +1,39 @@ + +Subject = "User Qualified"; ?> +

Hello,

+

User "" has been qualified.

+ + + + +Subject = "User Ghosted"; ?> +

Hello,

+

User "" has been marked as ghost.

+ + + + +Subject = "User Locked"; ?> +

Hello,

+

User "" has been locked.

+ + + + +Subject = "User Idle Locked"; ?> +

Hello,

+

User "" has been idle locked.

+ + + + +Subject = "User Promoted"; ?> +

Hello,

+

User "" has been promoted to admin.

+ + + + + + diff --git a/resources/mail/user_modifier_removed.php b/resources/mail/user_modifier_removed.php new file mode 100644 index 00000000..37873a6b --- /dev/null +++ b/resources/mail/user_modifier_removed.php @@ -0,0 +1,44 @@ + +Subject = "User Deactivated"; ?> +

Hello,

+

Your account on the Unity cluster has been deactivated.

+

If you believe this to be a mistake, please reply to this email as soon as possible.

+ + + + +Subject = "User Resurrected"; ?> +

Hello,

+

Your account on the Unity cluster has been resurrected.

+

If you believe this to be a mistake, please reply to this email as soon as possible.

+ + + + +Subject = "User Unlocked"; ?> +

Hello,

+

Your account on the Unity cluster has been unlocked.

+

If you believe this to be a mistake, please reply to this email as soon as possible.

+ + + + +Subject = "User Unlocked"; ?> +

Hello,

+

Your account on the Unity cluster has been unlocked.

+

If you believe this to be a mistake, please reply to this email as soon as possible.

+ + + + +Subject = "User Demoted"; ?> +

Hello,

+

Your account on the Unity cluster has been demoted from admin.

+

If you believe this to be a mistake, please reply to this email as soon as possible.

+ + + + + + diff --git a/resources/mail/user_modifier_removed_admin.php b/resources/mail/user_modifier_removed_admin.php new file mode 100644 index 00000000..1aac930d --- /dev/null +++ b/resources/mail/user_modifier_removed_admin.php @@ -0,0 +1,39 @@ + +Subject = "User Dequalified"; ?> +

Hello,

+

User "" has been dequalified.

+ + + + +Subject = "User Resurrected"; ?> +

Hello,

+

User "" has been resurrected (no longer marked as ghost).

+ + + + +Subject = "User Unlocked"; ?> +

Hello,

+

User "" has been unlocked.

+ + + + +Subject = "User Idle Unlocked"; ?> +

Hello,

+

User "" has been idle unlocked.

+ + + + +Subject = "User Demoted"; ?> +

Hello,

+

User "" has been demoted from admin.

+ + + + + + diff --git a/resources/mail/user_qualified.php b/resources/mail/user_qualified.php deleted file mode 100644 index 512930c3..00000000 --- a/resources/mail/user_qualified.php +++ /dev/null @@ -1,20 +0,0 @@ -Subject = "User Activated"; ?> - -

Hello,

- -

Your account on the Unity cluster has been activated. Your account details are below:

- -

-Username -
-Organization -

- -

Please login to the web portal to access Unity. - If you need console access, you will need to set your SSH keys in the - account settings page.

- -

If you believe this to be a mistake, please reply to this email as soon as possible.