From d09c0bd032154d2a352db0fa56bb49cd420d5f78 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Mon, 10 Nov 2025 11:45:42 -0500 Subject: [PATCH 1/2] remove data from request table --- resources/lib/UnityGroup.php | 112 +++++++---------------- resources/lib/UnitySQL.php | 21 +---- tools/docker-dev/sql/bootstrap.sql | 4 - webroot/admin/ajax/get_group_members.php | 17 ++-- webroot/admin/pi-mgmt.php | 16 ++-- webroot/panel/account.php | 8 +- webroot/panel/groups.php | 15 +-- webroot/panel/new_account.php | 22 +---- webroot/panel/pi.php | 18 ++-- 9 files changed, 68 insertions(+), 165 deletions(-) diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index b047e243..9a76b87b 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -65,43 +65,28 @@ public function exists(): bool return $this->entry->exists(); } - public function requestGroup( - string $firstname, - string $lastname, - string $email, - string $org, - bool $send_mail_to_admins, - bool $send_mail = true, - ): void { + public function requestGroup(bool $send_mail_to_admins, bool $send_mail = true): void + { if ($this->exists()) { return; } if ($this->SQL->accDeletionRequestExists($this->getOwner()->uid)) { return; } - $this->SQL->addRequest($this->getOwner()->uid, $firstname, $lastname, $email, $org); + $context = [ + "user" => $this->getOwner()->uid, + "org" => $this->getOwner()->getOrg(), + "name" => $this->getOwner()->getFullName(), + "email" => $this->getOwner()->getMail(), + ]; + $this->SQL->addRequest($this->getOwner()->uid); if ($send_mail) { - $this->MAILER->sendMail($email, "group_request"); - $this->WEBHOOK->sendWebhook("group_request_admin", [ - "user" => $this->getOwner()->uid, - "org" => $org, - "name" => "$firstname $lastname", - "email" => $email, - ]); + $this->MAILER->sendMail($this->getOwner()->getMail(), "group_request"); + $this->WEBHOOK->sendWebhook("group_request_admin", $context); if ($send_mail_to_admins) { - $this->MAILER->sendMail("admin", "group_request_admin", [ - "user" => $this->getOwner()->uid, - "org" => $org, - "name" => "$firstname $lastname", - "email" => $email, - ]); + $this->MAILER->sendMail("admin", "group_request_admin", $context); } - $this->MAILER->sendMail("pi_approve", "group_request_admin", [ - "user" => $this->getOwner()->uid, - "org" => $org, - "name" => "$firstname $lastname", - "email" => $email, - ]); + $this->MAILER->sendMail("pi_approve", "group_request_admin", $context); } } @@ -115,15 +100,7 @@ public function approveGroup(?UnityUser $operator = null, bool $send_mail = true if ($this->exists()) { return; } - if (!$this->getOwner()->exists()) { - $this->getOwner()->init( - $request["firstname"], - $request["lastname"], - $request["email"], - $request["org"], - $send_mail, - ); - } + \ensure(!$this->getOwner()->exists()); $this->init(); $this->SQL->removeRequest($this->getOwner()->uid); $operator = is_null($operator) ? $this->getOwner()->uid : $operator->uid; @@ -134,7 +111,7 @@ public function approveGroup(?UnityUser $operator = null, bool $send_mail = true $this->getOwner()->uid, ); if ($send_mail) { - $this->MAILER->sendMail($request["email"], "group_created"); + $this->MAILER->sendMail($this->getOwner()->getMail(), "group_created"); } } @@ -156,7 +133,7 @@ public function denyGroup(?UnityUser $operator = null, bool $send_mail = true): $this->getOwner()->uid, ); if ($send_mail) { - $this->MAILER->sendMail($request["email"], "group_denied"); + $this->MAILER->sendMail($this->getOwner()->getMail(), "group_denied"); } } @@ -237,14 +214,7 @@ public function cancelGroupJoinRequest(UnityUser $user, bool $send_mail = true): public function approveUser(UnityUser $new_user, bool $send_mail = true): void { $request = $this->SQL->getRequest($new_user->uid, $this->gid); - if (!$new_user->exists()) { - $new_user->init( - $request["firstname"], - $request["lastname"], - $request["email"], - $request["org"], - ); - } + \ensure(!$new_user->exists()); $this->addUserToGroup($new_user); $this->SQL->removeRequest($new_user->uid, $this->gid); if ($send_mail) { @@ -254,9 +224,9 @@ public function approveUser(UnityUser $new_user, bool $send_mail = true): void $this->MAILER->sendMail($this->getOwner()->getMail(), "group_user_added_owner", [ "group" => $this->gid, "user" => $new_user->uid, - "name" => $request["firstname"] . " " . $request["lastname"], - "email" => $request["email"], - "org" => $request["org"], + "name" => $new_user->getFullname(), + "email" => $new_user->getMail(), + "org" => $new_user->getOrg(), ]); } } @@ -267,7 +237,7 @@ public function denyUser(UnityUser $new_user, bool $send_mail = true): void // remove request, this will fail silently if the request doesn't exist $this->SQL->removeRequest($new_user->uid, $this->gid); if ($send_mail) { - $this->MAILER->sendMail($request["email"], "group_user_denied", [ + $this->MAILER->sendMail($new_user->getMail(), "group_user_denied", [ "group" => $this->gid, ]); $this->MAILER->sendMail($this->getOwner()->getMail(), "group_user_denied_owner", [ @@ -304,14 +274,8 @@ public function removeUser(UnityUser $new_user, bool $send_mail = true): void } } - public function newUserRequest( - UnityUser $new_user, - string $firstname, - string $lastname, - string $email, - string $org, - bool $send_mail = true, - ): void { + public function newUserRequest(UnityUser $new_user, bool $send_mail = true): void + { if ($this->memberExists($new_user)) { UnityHTTPD::errorLog("warning", "user '$new_user' already in group"); return; @@ -324,17 +288,17 @@ public function newUserRequest( throw new Exception("user '$new_user' requested account deletion"); return; } - $this->addRequest($new_user->uid, $firstname, $lastname, $email, $org); + $this->addRequest($new_user->uid); if ($send_mail) { - $this->MAILER->sendMail($email, "group_user_request", [ + $this->MAILER->sendMail($new_user->getMail(), "group_user_request", [ "group" => $this->gid, ]); $this->MAILER->sendMail($this->getOwner()->getMail(), "group_user_request_owner", [ "group" => $this->gid, "user" => $new_user->uid, - "name" => "$firstname $lastname", - "email" => $email, - "org" => $org, + "name" => $new_user->getFullname(), + "email" => $new_user->getMail(), + "org" => $new_user->getOrg(), ]); } } @@ -352,14 +316,7 @@ public function getRequests(): array $this->REDIS, $this->WEBHOOK, ); - array_push($out, [ - $user, - $request["timestamp"], - $request["firstname"], - $request["lastname"], - $request["email"], - $request["org"], - ]); + array_push($out, [$user, $request["timestamp"]]); } return $out; } @@ -471,14 +428,9 @@ public function memberExists(UnityUser $user): bool return in_array($user->uid, $this->getGroupMemberUIDs()); } - private function addRequest( - string $uid, - string $firstname, - string $lastname, - string $email, - string $org, - ): void { - $this->SQL->addRequest($uid, $firstname, $lastname, $email, $org, $this->gid); + private function addRequest(string $uid): void + { + $this->SQL->addRequest($uid, $this->gid); } public function getOwner(): UnityUser diff --git a/resources/lib/UnitySQL.php b/resources/lib/UnitySQL.php index 2c086ebe..5d4c7803 100644 --- a/resources/lib/UnitySQL.php +++ b/resources/lib/UnitySQL.php @@ -34,32 +34,17 @@ public function getConn(): PDO // // requests table methods // - public function addRequest( - string $requestor, - string $firstname, - string $lastname, - string $email, - string $org, - string $dest = self::REQUEST_BECOME_PI, - ): void { + public function addRequest(string $requestor, string $dest = self::REQUEST_BECOME_PI): void + { if ($this->requestExists($requestor, $dest)) { return; } $stmt = $this->conn->prepare( - "INSERT INTO " . - self::TABLE_REQS . - " " . - "(uid, firstname, lastname, email, org, request_for) VALUES " . - "(:uid, :firstname, :lastname, :email, :org, :request_for)", + "INSERT INTO " . self::TABLE_REQS . " (uid, request_for) VALUES (:uid, :request_for)", ); $stmt->bindParam(":uid", $requestor); $stmt->bindParam(":request_for", $dest); - $stmt->bindParam(":firstname", $firstname); - $stmt->bindParam(":lastname", $lastname); - $stmt->bindParam(":email", $email); - $stmt->bindParam(":org", $org); - $stmt->execute(); } diff --git a/tools/docker-dev/sql/bootstrap.sql b/tools/docker-dev/sql/bootstrap.sql index d8c6ac8d..7efb5722 100644 --- a/tools/docker-dev/sql/bootstrap.sql +++ b/tools/docker-dev/sql/bootstrap.sql @@ -124,10 +124,6 @@ CREATE TABLE `requests` ( `id` int(11) NOT NULL, `request_for` varchar(131) NOT NULL, `uid` varchar(128) NOT NULL, - `firstname` varchar(768) NOT NULL, - `lastname` varchar(768) NOT NULL, - `email` varchar(768) NOT NULL, - `org` varchar(768) NOT NULL, `timestamp` timestamp NOT NULL DEFAULT current_timestamp() ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; diff --git a/webroot/admin/ajax/get_group_members.php b/webroot/admin/ajax/get_group_members.php index cebf4115..9d98e44e 100644 --- a/webroot/admin/ajax/get_group_members.php +++ b/webroot/admin/ajax/get_group_members.php @@ -54,23 +54,24 @@ $i++; } -foreach ($requests as $i => [$user, $timestamp, $firstname, $lastname, $email, $org]) { +foreach ($requests as $i => [$user, $timestamp]) { if ($i >= $count - 1) { echo ""; } else { echo ""; } - $uid = $user->uid; - echo "" . $firstname . " " . $lastname . ""; - echo "" . $uid . ""; - echo "" . $email . ""; + $name = $user->getFullName(); + $email = $user->getMail(); + echo "$name"; + echo "$user->uid"; + echo "$email"; echo ""; echo "
+ onsubmit='return confirm(\"Are you sure you want to approve $user->uid ?\");'> - - + +
"; echo ""; diff --git a/webroot/admin/pi-mgmt.php b/webroot/admin/pi-mgmt.php index f70a9fba..5a2ae67d 100644 --- a/webroot/admin/pi-mgmt.php +++ b/webroot/admin/pi-mgmt.php @@ -65,20 +65,24 @@ $requests = $SQL->getRequests(); foreach ($requests as $request) { + $uid = $request["uid"]; + $request_user = new UnityUser($uid, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK); + $name = $request_user->getFullname(); + $email = $request_user->getMail(); echo ""; - echo "" . $request["firstname"] . " " . $request["lastname"] . ""; - echo "" . $request["uid"] . ""; - echo "" . $request["email"] . ""; + echo "$name"; + echo "$uid"; + echo "$email"; echo "" . date("jS F, Y", strtotime($request['timestamp'])) . ""; echo ""; echo "
- + + onclick='return confirm(\"Are you sure you want to approve $uid?\");'> + onclick='return confirm(\"Are you sure you want to deny $uid?\");'>
"; echo ""; echo ""; diff --git a/webroot/panel/account.php b/webroot/panel/account.php index fbeee48f..e2c1a2df 100644 --- a/webroot/panel/account.php +++ b/webroot/panel/account.php @@ -79,13 +79,7 @@ "USER='{$USER->uid}' SSO[user]='{$SSO["user"]}'" ); } - $USER->getPIGroup()->requestGroup( - $SSO["firstname"], - $SSO["lastname"], - $SSO["mail"], - $SSO["org"], - $SEND_PIMESG_TO_ADMINS - ); + $USER->getPIGroup()->requestGroup($SEND_PIMESG_TO_ADMINS); break; case "cancel_pi_request": $USER->getPIGroup()->cancelGroupRequest(); diff --git a/webroot/panel/groups.php b/webroot/panel/groups.php index d13327a0..cabefae3 100644 --- a/webroot/panel/groups.php +++ b/webroot/panel/groups.php @@ -37,21 +37,8 @@ array_push($modalErrors, "You're already in this PI group"); } } - if ($USER->uid != $SSO["user"]) { - $sso_user = $SSO["user"]; - UnityHTTPD::badRequest( - "cannot request due to uid mismatch: " . - "USER='{$USER->uid}' SSO[user]='$sso_user'" - ); - } if (empty($modalErrors)) { - $pi_account->newUserRequest( - $USER, - $SSO["firstname"], - $SSO["lastname"], - $SSO["mail"], - $SSO["org"] - ); + $pi_account->newUserRequest($USER); } break; case "removePIForm": diff --git a/webroot/panel/new_account.php b/webroot/panel/new_account.php index 604f95a4..2446f2c3 100644 --- a/webroot/panel/new_account.php +++ b/webroot/panel/new_account.php @@ -18,12 +18,6 @@ if (!isset($_POST["eula"]) || $_POST["eula"] != "agree") { UnityHTTPD::badRequest("user did not agree to EULA"); } - if ($USER->uid != $SSO["user"]) { - $sso_user = $SSO["user"]; - UnityHTTPD::badRequest( - "cannot request due to uid mismatch: USER='{$USER->uid}' SSO[user]='$sso_user'" - ); - } if ($_POST["new_user_sel"] == "not_pi") { $pi_groupname = $_POST["pi"]; if (substr($pi_groupname, 0, 3) !== "pi_" && str_contains($pi_groupname, "@")) { @@ -36,25 +30,13 @@ if (!$form_group->exists()) { UnityHTTPD::badRequest("The selected PI '" . $pi_groupname . "'does not exist"); } - $form_group->newUserRequest( - $USER, - $SSO["firstname"], - $SSO["lastname"], - $SSO["mail"], - $SSO["org"] - ); + $form_group->newUserRequest($USER); } if ($_POST["new_user_sel"] == "pi") { if (!isset($_POST["confirm_pi"]) || $_POST["confirm_pi"] != "agree") { UnityHTTPD::badRequest("user did not agree to account policy"); } - $USER->getPIGroup()->requestGroup( - $SSO["firstname"], - $SSO["lastname"], - $SSO["mail"], - $SSO["org"], - $SEND_PIMESG_TO_ADMINS - ); + $USER->getPIGroup()->requestGroup($SEND_PIMESG_TO_ADMINS); } } elseif (isset($_POST["cancel"])) { foreach ($pending_requests as $request) { diff --git a/webroot/panel/pi.php b/webroot/panel/pi.php index 08531a0c..efcc5257 100644 --- a/webroot/panel/pi.php +++ b/webroot/panel/pi.php @@ -53,23 +53,25 @@ echo "
Pending Requests
"; echo ""; - foreach ($requests as [$user, $timestamp, $firstname, $lastname, $email, $org]) { + foreach ($requests as [$user, $timestamp]) { $uid = $user->uid; + $name = $user->getFullName(); + $email = $user->getMail(); $date = date("jS F, Y", strtotime($timestamp)); echo ""; - echo ""; - echo ""; - echo ""; - echo ""; + echo ""; + echo ""; + echo ""; + echo ""; echo ""; echo ""; From 40ea9cff3d8c8d9b041a64778d7ffb9ad34ff2d8 Mon Sep 17 00:00:00 2001 From: Simon Leary Date: Fri, 14 Nov 2025 16:34:39 -0500 Subject: [PATCH 2/2] add users to ldap immediately --- CONTRIBUTING.md | 1 + README.md | 2 + resources/lib/UnityGroup.php | 6 +- resources/lib/UnityUser.php | 62 +++- resources/mail/user_dequalified.php | 10 + .../{user_created.php => user_qualified.php} | 4 +- test/functional/NewUserTest.php | 333 ------------------ test/functional/PIBecomeApproveTest.php | 94 +++++ test/functional/PIMemberRequestTest.php | 4 +- test/functional/PiBecomeRequestTest.php | 10 +- test/functional/PiMemberApproveTest.php | 230 ++++++++---- test/functional/PiMemberDenyTest.php | 11 +- test/functional/PiRemoveUserTest.php | 18 +- test/functional/RegisterUserTest.php | 45 +++ test/phpunit-bootstrap.php | 21 +- tools/docker-dev/identity/bootstrap.ldif | 23 ++ tools/docker-dev/web/Dockerfile | 2 + tools/docker-dev/web/htpasswd | 2 + webroot/panel/account.php | 34 +- webroot/panel/new_account.php | 195 +--------- 20 files changed, 467 insertions(+), 640 deletions(-) create mode 100644 resources/mail/user_dequalified.php rename resources/mail/{user_created.php => user_qualified.php} (84%) delete mode 100644 test/functional/NewUserTest.php create mode 100644 test/functional/PIBecomeApproveTest.php create mode 100644 test/functional/RegisterUserTest.php diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 998e4c7b..19f6d515 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,6 +63,7 @@ Notable users: - `user1@org1.test` - admin, PI - `user2@org1.test` - not admin, not PI - `user2000@org2.test` - does not yet have an account +- `user2005@org1.test` - regsitered but not qualified (not a PI or in a PI group) ### Changes to Dev Environment diff --git a/README.md b/README.md index 29081e3d..3fafe43f 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,8 @@ rm "$prod" && ln -s "$old" "$prod" ### 1.3 -> 1.4 - the `[ldap]user_group` option has been renamed to `[ldap]qualified_user_group` +- the `user_created ` mail template has been renamed to `user_qualified` +- the `user_dequalified` mail template has been added ### 1.2 -> 1.3 diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php index 9a76b87b..3517a022 100644 --- a/resources/lib/UnityGroup.php +++ b/resources/lib/UnityGroup.php @@ -100,7 +100,7 @@ public function approveGroup(?UnityUser $operator = null, bool $send_mail = true if ($this->exists()) { return; } - \ensure(!$this->getOwner()->exists()); + \ensure($this->getOwner()->exists()); $this->init(); $this->SQL->removeRequest($this->getOwner()->uid); $operator = is_null($operator) ? $this->getOwner()->uid : $operator->uid; @@ -113,6 +113,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 } /** @@ -214,7 +215,7 @@ public function cancelGroupJoinRequest(UnityUser $user, bool $send_mail = true): public function approveUser(UnityUser $new_user, bool $send_mail = true): void { $request = $this->SQL->getRequest($new_user->uid, $this->gid); - \ensure(!$new_user->exists()); + \ensure($new_user->exists()); $this->addUserToGroup($new_user); $this->SQL->removeRequest($new_user->uid, $this->gid); if ($send_mail) { @@ -229,6 +230,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 } public function denyUser(UnityUser $new_user, bool $send_mail = true): void diff --git a/resources/lib/UnityUser.php b/resources/lib/UnityUser.php index db22a6a4..76c839a8 100644 --- a/resources/lib/UnityUser.php +++ b/resources/lib/UnityUser.php @@ -105,24 +105,54 @@ public function init( $org->addUser($this); } - $this->LDAP->getQualifiedUserGroup()->appendAttribute("memberuid", $this->uid); - $this->LDAP->getQualifiedUserGroup()->write(); - - $default_value_getter = [$this->LDAP, "getSortedQualifiedUsersForRedis"]; - $this->REDIS->appendCacheArray( - "sorted_qualified_users", - "", - $this->uid, - $default_value_getter, - ); - $this->SQL->addLog($this->uid, $_SERVER["REMOTE_ADDR"], "user_added", $this->uid); + } - if ($send_mail) { - $this->MAILER->sendMail($this->getMail(), "user_created", [ - "user" => $this->uid, - "org" => $this->getOrg(), - ]); + public function isQualified(): bool + { + return $this->LDAP->getQualifiedUserGroup()->attributeValueExists("memberUid", $this->uid); + } + + public function setIsQualified(bool $newIsQualified, bool $doSendMail = true): void + { + $oldIsQualified = $this->isQualified(); + if ($oldIsQualified == $newIsQualified) { + return; + } + if ($newIsQualified) { + $this->LDAP->getQualifiedUserGroup()->appendAttribute("memberuid", $this->uid); + $this->LDAP->getQualifiedUserGroup()->write(); + $default_value_getter = [$this->LDAP, "getSortedQualifiedUsersForRedis"]; + $this->REDIS->appendCacheArray( + "sorted_qualified_users", + "", + $this->uid, + $default_value_getter, + ); + if ($doSendMail) { + $this->MAILER->sendMail($this->getMail(), "user_qualified", [ + "user" => $this->uid, + "org" => $this->getOrg(), + ]); + } + } else { + $this->LDAP + ->getQualifiedUserGroup() + ->removeAttributeEntryByValue("memberuid", $this->uid); + $this->LDAP->getQualifiedUserGroup()->write(); + $default_value_getter = [$this->LDAP, "getSortedQualifiedUsersForRedis"]; + $this->REDIS->removeCacheArray( + "sorted_qualified_users", + "", + $this->uid, + $default_value_getter, + ); + if ($doSendMail) { + $this->MAILER->sendMail($this->getMail(), "user_dequalified", [ + "user" => $this->uid, + "org" => $this->getOrg(), + ]); + } } } diff --git a/resources/mail/user_dequalified.php b/resources/mail/user_dequalified.php new file mode 100644 index 00000000..36efcc04 --- /dev/null +++ b/resources/mail/user_dequalified.php @@ -0,0 +1,10 @@ +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_created.php b/resources/mail/user_qualified.php similarity index 84% rename from resources/mail/user_created.php rename to resources/mail/user_qualified.php index 4298e777..512930c3 100644 --- a/resources/mail/user_created.php +++ b/resources/mail/user_qualified.php @@ -1,7 +1,7 @@ Subject = "User Created"; ?> +// this template is sent when a user account becomes qualified +$this->Subject = "User Activated"; ?>

Hello,

diff --git a/test/functional/NewUserTest.php b/test/functional/NewUserTest.php deleted file mode 100644 index 30a12bd7..00000000 --- a/test/functional/NewUserTest.php +++ /dev/null @@ -1,333 +0,0 @@ -assertEquals( - $expected, - $SQL->requestExists($USER->uid, UnitySQL::REQUEST_BECOME_PI), - ); - } - - private function assertRequestedMembership(bool $expected, string $gid) - { - global $USER, $SQL; - $this->assertEquals($expected, $SQL->requestExists($USER->uid, $gid)); - } - - private function requestGroupCreation() - { - http_post(__DIR__ . "/../../webroot/panel/new_account.php", [ - "new_user_sel" => "pi", - "eula" => "agree", - "confirm_pi" => "agree", - ]); - } - - private function requestGroupMembership(string $gid_or_mail) - { - http_post(__DIR__ . "/../../webroot/panel/new_account.php", [ - "new_user_sel" => "not_pi", - "eula" => "agree", - "pi" => $gid_or_mail, - ]); - } - - private function cancelAllRequests() - { - http_post( - __DIR__ . "/../../webroot/panel/new_account.php", - ["cancel" => "true"], // value of cancel is arbitrary - ); - } - - private function approveUserByAdmin($gid, $uid) - { - http_post(__DIR__ . "/../../webroot/admin/pi-mgmt.php", [ - "form_type" => "reqChild", - "action" => "Approve", - "pi" => $gid, - "uid" => $uid, - ]); - } - - private function approveUserByPI($uid) - { - http_post(__DIR__ . "/../../webroot/panel/pi.php", [ - "form_type" => "userReq", - "action" => "Approve", - "uid" => $uid, - ]); - } - - private function approveGroup($uid) - { - http_post(__DIR__ . "/../../webroot/admin/pi-mgmt.php", [ - "form_type" => "req", - "action" => "Approve", - "uid" => $uid, - ]); - } - - #[DataProvider("provider")] - public function testCreateUserByJoinGoupByPI($user_to_create_args, $expected_uid_gid) - { - global $USER, $SSO, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK; - $pi_user_args = getUserIsPIHasNoMembersNoMemberRequests(); - switchUser(...$pi_user_args); - $pi_group = $USER->getPIGroup(); - $gid = $pi_group->gid; - switchUser(...$user_to_create_args); - $this->assertTrue(!$USER->exists()); - $newOrg = new UnityOrg($SSO["org"], $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK); - $this->assertTrue(!$newOrg->exists()); - $this->assertTrue($pi_group->exists()); - $this->assertTrue(!$pi_group->memberExists($USER)); - $this->assertRequestedMembership(false, $gid); - try { - $this->requestGroupMembership($pi_group->gid); - $this->assertRequestedMembership(true, $gid); - - // $second_request_failed = false; - // try { - $this->requestGroupMembership($pi_group->gid); - // } catch(Exception) { - // $second_request_failed = true; - // } - // $this->assertTrue($second_request_failed); - $this->assertRequestedMembership(true, $gid); - - $this->cancelAllRequests(); - $this->assertRequestedMembership(false, $gid); - - $this->requestGroupMembership($pi_group->gid); - $this->assertTrue($pi_group->requestExists($USER)); - $this->assertRequestedMembership(true, $gid); - - $REDIS->flushAll(); // regression test: flush used to break requests - - $approve_uid = $SSO["user"]; - switchUser(...$pi_user_args); - $this->approveUserByPI($approve_uid); - switchUser(...$user_to_create_args); - - $this->assertTrue(!$pi_group->requestExists($USER)); - $this->assertRequestedMembership(false, $gid); - $this->assertTrue($pi_group->memberExists($USER)); - $this->assertTrue($USER->exists()); - $this->assertTrue($newOrg->exists()); - - $user_entry = $LDAP->getUserEntry($approve_uid); - $qualified_user_group_entry = $LDAP->getGroupEntry($approve_uid); - $this->assertEquals($expected_uid_gid, $user_entry->getAttribute("uidnumber")[0]); - $this->assertEquals( - $expected_uid_gid, - $qualified_user_group_entry->getAttribute("gidnumber")[0], - ); - - // $third_request_failed = false; - // try { - $this->requestGroupMembership($pi_group->gid); - // } catch(Exception) { - // $third_request_failed = true; - // } - // $this->assertTrue($third_request_failed); - $this->assertRequestedMembership(false, $gid); - $this->assertTrue(!$pi_group->requestExists($USER)); - } finally { - switchUser(...$user_to_create_args); - ensureOrgGroupDoesNotExist(); - ensureUserNotInPIGroup($pi_group); - ensureUserDoesNotExist(); - } - } - - public function testCreateMultipleUsersByJoinGoupByPI() - { - global $USER, $SSO, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK; - $pi_user_args = getUserIsPIHasNoMembersNoMemberRequests(); - switchUser(...$pi_user_args); - $pi_group = $USER->getPIGroup(); - $gid = $pi_group->gid; - $this->assertTrue($pi_group->exists()); - $users_to_create_args = getNonexistentUsersWithExistentOrg(); - try { - foreach ($users_to_create_args as $user_to_create_args) { - switchUser(...$user_to_create_args); - $this->assertTrue(!$USER->exists()); - $this->assertTrue(!$pi_group->memberExists($USER)); - $this->assertRequestedMembership(false, $gid); - $this->requestGroupMembership($pi_group->gid); - $this->assertRequestedMembership(true, $gid); - $approve_uid = $USER->uid; - switchUser(...$pi_user_args); - // $this->assertTrue(!$pi_group->memberExists($USER)); - $this->approveUserByPI($approve_uid); - switchUser(...$user_to_create_args); - $this->assertTrue(!$pi_group->requestExists($USER)); - $this->assertRequestedMembership(false, $gid); - $this->assertTrue($pi_group->memberExists($USER)); - $this->assertTrue($USER->exists()); - } - } finally { - foreach ($users_to_create_args as $user_to_create_args) { - switchUser(...$user_to_create_args); - ensureUserNotInPIGroup($pi_group); - ensureUserDoesNotExist(); - } - } - } - - #[DataProvider("provider")] - public function testCreateUserByJoinGoupByAdmin($user_to_create_args, $expected_uid_gid) - { - global $USER, $SSO, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK; - switchUser(...getUserIsPIHasNoMembersNoMemberRequests()); - $pi_group = $USER->getPIGroup(); - $gid = $pi_group->gid; - switchUser(...$user_to_create_args); - $this->assertTrue(!$USER->exists()); - $newOrg = new UnityOrg($SSO["org"], $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK); - $this->assertTrue(!$newOrg->exists()); - $this->assertTrue($pi_group->exists()); - $this->assertTrue(!$pi_group->memberExists($USER)); - $this->assertRequestedMembership(false, $gid); - try { - $this->requestGroupMembership($pi_group->gid); - $this->assertRequestedMembership(true, $gid); - - // $second_request_failed = false; - // try { - $this->requestGroupMembership($pi_group->gid); - // } catch(Exception) { - // $second_request_failed = true; - // } - // $this->assertTrue($second_request_failed); - $this->assertRequestedMembership(true, $gid); - - $this->cancelAllRequests(); - $this->assertRequestedMembership(false, $gid); - - $this->requestGroupMembership($pi_group->getOwner()->getMail()); - $this->assertTrue($pi_group->requestExists($USER)); - $this->assertRequestedMembership(true, $gid); - - $REDIS->flushAll(); // regression test: flush used to break requests - - $approve_uid = $SSO["user"]; - switchUser(...getAdminUser()); - $this->approveUserByAdmin($gid, $approve_uid); - switchUser(...$user_to_create_args); - - $this->assertTrue(!$pi_group->requestExists($USER)); - $this->assertRequestedMembership(false, $gid); - $this->assertTrue($pi_group->memberExists($USER)); - $this->assertTrue($USER->exists()); - $this->assertTrue($newOrg->exists()); - - $user_entry = $LDAP->getUserEntry($approve_uid); - $qualified_user_group_entry = $LDAP->getGroupEntry($approve_uid); - $this->assertEquals($expected_uid_gid, $user_entry->getAttribute("uidnumber")[0]); - $this->assertEquals( - $expected_uid_gid, - $qualified_user_group_entry->getAttribute("gidnumber")[0], - ); - - // $third_request_failed = false; - // try { - $this->requestGroupMembership($pi_group->gid); - // } catch(Exception) { - // $third_request_failed = true; - // } - // $this->assertTrue($third_request_failed); - $this->assertRequestedMembership(false, $gid); - $this->assertTrue(!$pi_group->requestExists($USER)); - } finally { - switchUser(...$user_to_create_args); - ensureOrgGroupDoesNotExist(); - ensureUserNotInPIGroup($pi_group); - ensureUserDoesNotExist(); - } - } - - #[DataProvider("provider")] - public function testCreateUserByCreateGroup($user_to_create_args, $expected_uid_gid) - { - global $USER, $SSO, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK; - switchuser(...$user_to_create_args); - $pi_group = $USER->getPIGroup(); - $this->assertTrue(!$USER->exists()); - $this->assertTrue(!$pi_group->exists()); - $newOrg = new UnityOrg($SSO["org"], $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK); - $this->assertTrue(!$newOrg->exists()); - try { - $this->requestGroupCreation(); - $this->assertRequestedPIGroup(true); - - // $second_request_failed = false; - // try { - $this->requestGroupCreation(); - // } catch(Exception) { - // $second_request_failed = true; - // } - // $this->assertTrue($second_request_failed); - $this->assertRequestedPIGroup(true); - - $this->cancelAllRequests(); - $this->assertRequestedPIGroup(false); - - $this->requestGroupCreation(); - $this->assertRequestedPIGroup(true); - - $REDIS->flushAll(); // regression test: flush used to break requests - - $approve_uid = $SSO["user"]; - switchUser(...getAdminUser()); - $this->approveGroup($approve_uid); - switchUser(...$user_to_create_args); - - $this->assertRequestedPIGroup(false); - $this->assertTrue($pi_group->exists()); - $this->assertTrue($USER->exists()); - $this->assertTrue($newOrg->exists()); - - $user_entry = $LDAP->getUserEntry($approve_uid); - $qualified_user_group_entry = $LDAP->getGroupEntry($approve_uid); - $this->assertEquals($expected_uid_gid, $user_entry->getAttribute("uidnumber")[0]); - $this->assertEquals( - $expected_uid_gid, - $qualified_user_group_entry->getAttribute("gidnumber")[0], - ); - - // $third_request_failed = false; - // try { - $this->requestGroupCreation(); - // } catch(Exception) { - // $third_request_failed = true; - // } - // $this->assertTrue($third_request_failed); - $this->assertRequestedPIGroup(false); - } finally { - switchUser(...$user_to_create_args); - ensureOrgGroupDoesNotExist(); - ensurePIGroupDoesNotExist(); - ensureUserDoesNotExist(); - } - } -} diff --git a/test/functional/PIBecomeApproveTest.php b/test/functional/PIBecomeApproveTest.php new file mode 100644 index 00000000..2b741a45 --- /dev/null +++ b/test/functional/PIBecomeApproveTest.php @@ -0,0 +1,94 @@ +assertEquals( + $expected, + $SQL->requestExists($USER->uid, UnitySQL::REQUEST_BECOME_PI), + ); + } + + private function requestGroupCreation() + { + http_post(__DIR__ . "/../../webroot/panel/account.php", [ + "form_type" => "pi_request", + "tos" => "agree", + "account_policy" => "agree", + ]); + } + + private function cancelRequestGroupCreation() + { + http_post(__DIR__ . "/../../webroot/panel/account.php", [ + "form_type" => "cancel_pi_request", + ]); + } + + private function approveGroup($uid) + { + http_post(__DIR__ . "/../../webroot/admin/pi-mgmt.php", [ + "form_type" => "req", + "action" => "Approve", + "uid" => $uid, + ]); + } + + public function testApprovePI() + { + global $USER, $SSO, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK; + $user_to_qualify_args = getUnqualifiedUser(); + switchuser(...$user_to_qualify_args); + $pi_group = $USER->getPIGroup(); + $this->assertTrue($USER->exists()); + $this->assertTrue(!$pi_group->exists()); + try { + $this->requestGroupCreation(); + $this->assertRequestedPIGroup(true); + + // $second_request_failed = false; + // try { + $this->requestGroupCreation(); + // } catch(Exception) { + // $second_request_failed = true; + // } + // $this->assertTrue($second_request_failed); + $this->assertRequestedPIGroup(true); + + $this->cancelRequestGroupCreation(); + $this->assertRequestedPIGroup(false); + + $this->requestGroupCreation(); + $this->assertRequestedPIGroup(true); + + $REDIS->flushAll(); // regression test: flush used to break requests + + $approve_uid = $SSO["user"]; + switchUser(...getAdminUser()); + $this->approveGroup($approve_uid); + switchUser(...$user_to_qualify_args); + + $this->assertRequestedPIGroup(false); + $this->assertTrue($pi_group->exists()); + $this->assertTrue($USER->isQualified()); + + // $third_request_failed = false; + // try { + $this->requestGroupCreation(); + // } catch(Exception) { + // $third_request_failed = true; + // } + // $this->assertTrue($third_request_failed); + $this->assertRequestedPIGroup(false); + } finally { + switchUser(...$user_to_qualify_args); + ensurePIGroupDoesNotExist(); + } + } +} diff --git a/test/functional/PIMemberRequestTest.php b/test/functional/PIMemberRequestTest.php index 7a913d67..cea66ae7 100644 --- a/test/functional/PIMemberRequestTest.php +++ b/test/functional/PIMemberRequestTest.php @@ -3,7 +3,7 @@ use PHPUnit\Framework\TestCase; use UnityWebPortal\lib\UnitySQL; -class PiMemberRequestTest extends TestCase +class PIMemberRequestTest extends TestCase { private function requestMembership(string $gid_or_mail) { @@ -32,7 +32,7 @@ public function testRequestMembership() $this->assertTrue($USER->isPI()); $this->assertTrue($pi_group->exists()); $this->assertEqualsCanonicalizing([$pi], $pi_group->getGroupMembers()); - $this->assertEquals([], $SQL->getRequests($gid)); + $this->assertEqualsCanonicalizing([], $SQL->getRequests($gid)); switchUser(...getUserNotPiNotRequestedBecomePi()); $uid = $USER->uid; $this->assertFalse($USER->isPI()); diff --git a/test/functional/PiBecomeRequestTest.php b/test/functional/PiBecomeRequestTest.php index d1306c46..5714a6b9 100644 --- a/test/functional/PiBecomeRequestTest.php +++ b/test/functional/PiBecomeRequestTest.php @@ -3,7 +3,7 @@ use PHPUnit\Framework\TestCase; use UnityWebPortal\lib\UnitySQL; -class PiBecomeRequestTest extends TestCase +class PIBecomeRequestTest extends TestCase { private function assertNumberPiBecomeRequests(int $x) { @@ -41,6 +41,8 @@ public function testRequestBecomePi() try { http_post(__DIR__ . "/../../webroot/panel/account.php", [ "form_type" => "pi_request", + "tos" => "agree", + "account_policy" => "agree", ]); $this->assertNumberPiBecomeRequests(1); http_post(__DIR__ . "/../../webroot/panel/account.php", [ @@ -49,10 +51,14 @@ public function testRequestBecomePi() $this->assertNumberPiBecomeRequests(0); http_post(__DIR__ . "/../../webroot/panel/account.php", [ "form_type" => "pi_request", + "tos" => "agree", + "account_policy" => "agree", ]); $this->assertNumberPiBecomeRequests(1); http_post(__DIR__ . "/../../webroot/panel/account.php", [ "form_type" => "pi_request", + "tos" => "agree", + "account_policy" => "agree", ]); $this->assertNumberPiBecomeRequests(1); } finally { @@ -72,6 +78,8 @@ public function testRequestBecomePiUserRequestedAccountDeletion() try { http_post(__DIR__ . "/../../webroot/panel/account.php", [ "form_type" => "pi_request", + "tos" => "agree", + "account_policy" => "agree", ]); $this->assertNumberPiBecomeRequests(0); } finally { diff --git a/test/functional/PiMemberApproveTest.php b/test/functional/PiMemberApproveTest.php index c861df13..3ad8a7d3 100644 --- a/test/functional/PiMemberApproveTest.php +++ b/test/functional/PiMemberApproveTest.php @@ -1,106 +1,206 @@ "userReq", - "action" => "Approve", - "uid" => $uid, - ]); + sort($expected_members); + $found_members = $group->getGroupMemberUIDs(); + sort($found_members); + $this->assertEqualsCanonicalizing($expected_members, $found_members); + } + + private function assertRequestedMembership(bool $expected, string $gid) + { + global $USER, $SQL; + $this->assertEquals($expected, $SQL->requestExists($USER->uid, $gid)); } - private function requestJoinPI(string $gid) + private function requestGroupMembership(string $gid_or_mail) { http_post(__DIR__ . "/../../webroot/panel/groups.php", [ "form_type" => "addPIform", - "pi" => $gid, "tos" => "agree", + "pi" => $gid_or_mail, ]); } - private function assertGroupMembers(UnityGroup $group, array $members) + private function cancelRequestGroupMembership($gid) { - $this->assertEqualsCanonicalizing($members, $group->getGroupMemberUIDs()); + http_post(__DIR__ . "/../../webroot/panel/groups.php", [ + "form_type" => "cancelPIForm", + "pi" => $gid, + ]); } - public function testApproveRequest() + private function approveUserByAdmin($gid, $uid) { - global $USER; - $userSwitchArgs = getNormalUser(); - $piSwitchArgs = getUserIsPIHasNoMembersNoMemberRequests(); - switchUser(...$userSwitchArgs); - $user = $USER; - $uid = $USER->uid; - switchUser(...$piSwitchArgs); - $piUID = $USER->uid; - $piGroup = $USER->getPIGroup(); + http_post(__DIR__ . "/../../webroot/admin/pi-mgmt.php", [ + "form_type" => "reqChild", + "action" => "Approve", + "pi" => $gid, + "uid" => $uid, + ]); + } - $this->assertTrue($piGroup->exists()); - $this->assertGroupMembers($piGroup, [$piUID]); - $this->assertEmpty($piGroup->getRequests()); - try { - switchUser(...$userSwitchArgs); - $this->requestJoinPI($piGroup->gid); - $this->assertFalse($piGroup->memberExists($user)); - - switchUser(...$piSwitchArgs); - $this->approveUser($uid); - $this->assertTrue(!$piGroup->requestExists($user)); - $this->assertEmpty($piGroup->getRequests()); - $this->assertGroupMembers($piGroup, [$piUID, $uid]); - $this->assertTrue($piGroup->memberExists($user)); - } finally { - if ($piGroup->memberExists($user)) { - $piGroup->removeUser($user); - } - if ($piGroup->requestExists($user)) { - $piGroup->cancelGroupJoinRequest($user); - } - } + private function approveUserByPI($uid) + { + http_post(__DIR__ . "/../../webroot/panel/pi.php", [ + "form_type" => "userReq", + "action" => "Approve", + "uid" => $uid, + ]); } public function testApproveNonexistentRequest() { global $USER; - switchUser(...getNormalUser2()); + $user_args = getNormalUser2(); + switchUser(...$user_args); $user = $USER; $uid = $USER->uid; switchUser(...getUserIsPIHasNoMembersNoMemberRequests()); $piUID = $USER->uid; $piGroup = $USER->getPIGroup(); - $this->assertTrue($piGroup->exists()); $this->assertGroupMembers($piGroup, [$piUID]); $this->assertEmpty($piGroup->getRequests()); $this->assertFalse($piGroup->memberExists($user)); $this->assertEmpty($piGroup->getRequests()); try { - $this->expectException(Exception::class); - $piGroup->approveUser($user); + $this->expectException(Exception::class); // FIXME more specific exception type + $this->approveUserByPI($uid); + } finally { + switchUser(...$user_args); + ensureUserNotInPIGroup($piGroup); + } + } + public function testApproveMemberByPI() + { + global $USER, $SSO, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK; + $user_to_approve_args = getUnqualifiedUser(); + $pi_user_args = getUserIsPIHasNoMembersNoMemberRequests(); + switchUser(...$pi_user_args); + $pi_uid = $USER->uid; + $pi_group = $USER->getPIGroup(); + $gid = $pi_group->gid; + switchUser(...$user_to_approve_args); + $this->assertTrue($USER->exists()); + $this->assertTrue($pi_group->exists()); + $this->assertGroupMembers($pi_group, [$pi_uid]); + $this->assertTrue(!$pi_group->memberExists($USER)); + $this->assertRequestedMembership(false, $gid); + try { + $this->requestGroupMembership($pi_group->gid); + $this->assertRequestedMembership(true, $gid); + + // $second_request_failed = false; + // try { + $this->requestGroupMembership($pi_group->gid); + // } catch(Exception) { + // $second_request_failed = true; + // } + // $this->assertTrue($second_request_failed); + $this->assertRequestedMembership(true, $gid); + + $this->cancelRequestGroupMembership($gid); + $this->assertRequestedMembership(false, $gid); + + $this->requestGroupMembership($pi_group->gid); + $this->assertTrue($pi_group->requestExists($USER)); + $this->assertRequestedMembership(true, $gid); + + $REDIS->flushAll(); // regression test: flush used to break requests + + $approve_uid = $SSO["user"]; + switchUser(...$pi_user_args); + $this->approveUserByPI($approve_uid); + switchUser(...$user_to_approve_args); + + $this->assertTrue(!$pi_group->requestExists($USER)); + $this->assertRequestedMembership(false, $gid); + $this->assertTrue($pi_group->memberExists($USER)); + $this->assertTrue($USER->isQualified()); + + // $third_request_failed = false; + // try { + $this->requestGroupMembership($pi_group->gid); + // } catch(Exception) { + // $third_request_failed = true; + // } + // $this->assertTrue($third_request_failed); + $this->assertRequestedMembership(false, $gid); + $this->assertTrue(!$pi_group->requestExists($USER)); + } finally { + switchUser(...$user_to_approve_args); + ensureUserNotInPIGroup($pi_group); + $this->assertGroupMembers($pi_group, [$pi_uid]); + } + } + + public function testApproveMemberByAdmin() + { + global $USER, $SSO, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK; + $user_to_approve_args = getUnqualifiedUser(); + switchUser(...getUserIsPIHasNoMembersNoMemberRequests()); + $pi_group = $USER->getPIGroup(); + $pi_uid = $USER->uid; + $gid = $pi_group->gid; + switchUser(...$user_to_approve_args); + $this->assertTrue($USER->exists()); + $this->assertTrue($pi_group->exists()); + $this->assertGroupMembers($pi_group, [$pi_uid]); + $this->assertTrue(!$pi_group->memberExists($USER)); + $this->assertRequestedMembership(false, $gid); + try { + $this->requestGroupMembership($pi_group->gid); + $this->assertRequestedMembership(true, $gid); + + // $second_request_failed = false; + // try { + $this->requestGroupMembership($pi_group->gid); + // } catch(Exception) { + // $second_request_failed = true; + // } + // $this->assertTrue($second_request_failed); + $this->assertRequestedMembership(true, $gid); + + $this->cancelRequestGroupMembership($gid); + $this->assertRequestedMembership(false, $gid); + + $this->requestGroupMembership($pi_group->getOwner()->getMail()); + $this->assertTrue($pi_group->requestExists($USER)); + $this->assertRequestedMembership(true, $gid); + + $REDIS->flushAll(); // regression test: flush used to break requests + + $approve_uid = $SSO["user"]; + switchUser(...getAdminUser()); + $this->approveUserByAdmin($gid, $approve_uid); + switchUser(...$user_to_approve_args); + + $this->assertTrue(!$pi_group->requestExists($USER)); + $this->assertRequestedMembership(false, $gid); + $this->assertTrue($pi_group->memberExists($USER)); + $this->assertTrue($USER->isQualified()); + + // $third_request_failed = false; + // try { + $this->requestGroupMembership($pi_group->gid); + // } catch(Exception) { + // $third_request_failed = true; + // } + // $this->assertTrue($third_request_failed); + $this->assertRequestedMembership(false, $gid); + $this->assertTrue(!$pi_group->requestExists($USER)); } finally { - if ($piGroup->memberExists($user)) { - $piGroup->removeUser($user); - } + switchUser(...$user_to_approve_args); + ensureUserNotInPIGroup($pi_group); + $this->assertGroupMembers($pi_group, [$pi_uid]); } } } diff --git a/test/functional/PiMemberDenyTest.php b/test/functional/PiMemberDenyTest.php index ad68e156..aa3092c5 100644 --- a/test/functional/PiMemberDenyTest.php +++ b/test/functional/PiMemberDenyTest.php @@ -3,8 +3,9 @@ use PHPUnit\Framework\TestCase; use PHPUnit\Framework\Attributes\DataProvider; use UnityWebPortal\lib\UnityUser; +use function PHPUnit\Framework\assertEquals; -class PiMemberDenyTest extends TestCase +class PIMemberDenyTest extends TestCase { static $requestUid; @@ -35,13 +36,7 @@ public function testDenyRequest() $this->assertEmpty($piGroup->getRequests()); $requestedUser = new UnityUser(self::$requestUid, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK); try { - $piGroup->newUserRequest( - $requestedUser, - $requestedUser->getFirstname(), - $requestedUser->getLastname(), - $requestedUser->getMail(), - $requestedUser->getOrg(), - ); + $piGroup->newUserRequest($requestedUser); $this->assertFalse($piGroup->memberExists($requestedUser)); $piGroup->denyUser($requestedUser); diff --git a/test/functional/PiRemoveUserTest.php b/test/functional/PiRemoveUserTest.php index 6118ad6c..954e01b8 100644 --- a/test/functional/PiRemoveUserTest.php +++ b/test/functional/PiRemoveUserTest.php @@ -4,7 +4,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use UnityWebPortal\lib\UnityUser; -class PiRemoveUserTest extends TestCase +class PIRemoveUserTest extends TestCase { private function removeUser(string $uid) { @@ -44,13 +44,7 @@ public function testRemoveUser() $this->assertFalse($piGroup->memberExists($memberToDelete)); } finally { if (!$piGroup->memberExists($memberToDelete)) { - $piGroup->newUserRequest( - $memberToDelete, - $memberToDelete->getFirstname(), - $memberToDelete->getLastname(), - $memberToDelete->getMail(), - $memberToDelete->getOrg(), - ); + $piGroup->newUserRequest($memberToDelete); $piGroup->approveUser($memberToDelete); } } @@ -70,13 +64,7 @@ public function testRemovePIFromTheirOwnGroup() $this->assertTrue($piGroup->memberExists($pi)); } finally { if (!$piGroup->memberExists($pi)) { - $piGroup->newUserRequest( - $pi, - $pi->getFirstname(), - $pi->getLastname(), - $pi->getMail(), - $pi->getOrg(), - ); + $piGroup->newUserRequest($pi); $piGroup->approveUser($pi); } } diff --git a/test/functional/RegisterUserTest.php b/test/functional/RegisterUserTest.php new file mode 100644 index 00000000..a51c7309 --- /dev/null +++ b/test/functional/RegisterUserTest.php @@ -0,0 +1,45 @@ + "agree"]); + } + + #[DataProvider("provider")] + public function testRegisterUserAndCreateOrg($user_to_register_args, $expected_uid_gid) + { + global $USER, $SSO, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK; + switchuser(...$user_to_register_args); + $user_entry = $LDAP->getUserEntry($USER->uid); + $user_group_entry = $LDAP->getGroupEntry($USER->uid); + $org_entry = $LDAP->getOrgGroupEntry($SSO["org"]); + $this->assertTrue(!$user_entry->exists()); + $this->assertTrue(!$user_group_entry->exists()); + $this->assertTrue(!$org_entry->exists()); + try { + $this->register(); + $this->assertTrue($user_entry->exists()); + $this->assertTrue($user_group_entry->exists()); + $this->assertTrue($org_entry->exists()); + $this->assertEquals($expected_uid_gid, $user_entry->getAttribute("uidnumber")[0]); + $this->assertEquals($expected_uid_gid, $user_group_entry->getAttribute("gidnumber")[0]); + } finally { + ensureOrgGroupDoesNotExist(); + ensureUserDoesNotExist(); + } + } +} diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php index c4c2af03..2091029e 100644 --- a/test/phpunit-bootstrap.php +++ b/test/phpunit-bootstrap.php @@ -181,17 +181,17 @@ function ensureUserDoesNotExist() $USER->getGroupEntry()->delete(); ensure(!$USER->getGroupEntry()->exists()); } - $all_users_group = $LDAP->getQualifiedUserGroup(); - $all_member_uids = $all_users_group->getAttribute("memberuid"); + $qualified_users_group = $LDAP->getQualifiedUserGroup(); + $all_member_uids = $qualified_users_group->getAttribute("memberuid"); if (in_array($USER->uid, $all_member_uids)) { - $all_users_group->setAttribute( + $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])), ); - $all_users_group->write(); - ensure(!in_array($USER->uid, $all_users_group->getAttribute("memberuid"))); + $qualified_users_group->write(); + ensure(!in_array($USER->uid, $qualified_users_group->getAttribute("memberuid"))); } $default_value_getter = [$LDAP, "getSortedQualifiedUsersForRedis"]; $REDIS->removeCacheArray("sorted_qualified_users", "", $USER->uid, $default_value_getter); @@ -291,6 +291,11 @@ function getNonExistentUser() return ["user2001@org998.test", "foo", "bar", "user2001@org998.test"]; } +function getUnqualifiedUser() +{ + return ["user2005@org1.test", "foo", "bar", "user2005@org1.test"]; +} + function getNonexistentUsersWithExistentOrg() { return [ @@ -316,15 +321,15 @@ function getMultipleValueAttributesAndExpectedSSO() { return [ [ - "REMOTE_USER" => "user2003@org998.test", + "REMOTE_USER" => "user2003@org1.test", "givenName" => "foo;foo", "sn" => "bar;bar", - "mail" => "user2003@org998.test;user2003@org998.test", + "mail" => "user2003@org1.test;user2003@org1.test", ], [ "firstname" => "foo", "lastname" => "bar", - "mail" => "user2003@org998.test", + "mail" => "user2003@org1.test", ], ]; } diff --git a/tools/docker-dev/identity/bootstrap.ldif b/tools/docker-dev/identity/bootstrap.ldif index 6f78b020..ff979344 100644 --- a/tools/docker-dev/identity/bootstrap.ldif +++ b/tools/docker-dev/identity/bootstrap.ldif @@ -9178,6 +9178,12 @@ gidnumber: 1956 objectclass: posixGroup objectclass: top +dn: cn=user2005_org1_test,ou=groups,dc=unityhpc,dc=test +cn: user2005_org1_test +gidnumber: 33130 +objectclass: posixGroup +objectclass: top + dn: ou=org_groups,dc=unityhpc,dc=test objectclass: organizationalUnit objectclass: top @@ -37206,3 +37212,20 @@ sshpublickey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6DRkoDjDgI39kKmuUAgMC18+O3o sshpublickey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLCxBujVxoB5T95BAQfwlG0cQSGldVap3w/cNAHobgaa9rOcino2Dw5EHXQl+O0yrDGRRQ1sEIZrTLhHNcWLUZ1d6exSRfg8AvjghAczKNi7H8oLMCp4hMVz3RzqozZaxhXDYQb1n4igf8jtX/VBvixEgSkDrRxPCFFkr14CT0xXhR02fnoFSMbedtXphClTiF6ry94mzl91CkdWP9JHY1w8LCJh6wlXCyiIorydoADPAjFIw766TRe2eUNHn0gDPVrF8KUhaYDW8wKG6u8PORotNBr3zw/QRCjpgbwh1w6xNZti/N+rEjczFTnECmlcOkDrkw5j4OqiLEIBw3j9vF uid: user1304_org1_test uidnumber: 1956 + +dn: cn=user2005_org1_test,ou=users,dc=unityhpc,dc=test +cn: user2005_org1_test +gidnumber: 33130 +givenname: Givenname +homedirectory: /home/user2005_org1_test +loginshell: /bin/bash +mail: user2005@org1.test +o: org1_test +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +objectclass: ldapPublicKey +sn: Surname +gecos: Givenname Surname +uid: user2005_org1_test +uidnumber: 33130 diff --git a/tools/docker-dev/web/Dockerfile b/tools/docker-dev/web/Dockerfile index a65eee49..22e1d472 100644 --- a/tools/docker-dev/web/Dockerfile +++ b/tools/docker-dev/web/Dockerfile @@ -28,6 +28,8 @@ RUN sed -i '/display_errors/c\display_errors = on' /etc/php/8.3/apache2/php.ini RUN sed -i '/zend.assertions/c\zend.assertions = 1' /etc/php/8.3/apache2/php.ini RUN sed -i '/zend.assertions/c\zend.assertions = 1' /etc/php/8.3/cli/php.ini RUN sed -i '/memory_limit/c\memory_limit = -1' /etc/php/8.3/apache2/php.ini +RUN sed -i '/zend.exception_ignore_args/c\zend.exception_ignore_args = 0' /etc/php/8.3/apache2/php.ini +RUN sed -i '/zend.exception_ignore_args/c\zend.exception_ignore_args = 0' /etc/php/8.3/cli/php.ini RUN echo 'xdebug.mode=coverage' >> /etc/php/8.3/cli/php.ini # Start apache2 server diff --git a/tools/docker-dev/web/htpasswd b/tools/docker-dev/web/htpasswd index 2e7ce610..1400af50 100644 --- a/tools/docker-dev/web/htpasswd +++ b/tools/docker-dev/web/htpasswd @@ -1309,3 +1309,5 @@ user2002@org999.test:$apr1$Rgrex74Z$rgJx6sCnGQN9UVMmhVG2R1 # nonexistent users with an existent org user2003@org1.test:$apr1$Rgrex74Z$rgJx6sCnGQN9UVMmhVG2R1 user2004@org1.test:$apr1$Rgrex74Z$rgJx6sCnGQN9UVMmhVG2R1 +# unqualified users +user2005@org1.test:$apr1$Rgrex74Z$rgJx6sCnGQN9UVMmhVG2R1 diff --git a/webroot/panel/account.php b/webroot/panel/account.php index e2c1a2df..7de8a29c 100644 --- a/webroot/panel/account.php +++ b/webroot/panel/account.php @@ -73,11 +73,8 @@ if ($SQL->requestExists($USER->uid)) { UnityHTTPD::badRequest("already requested to be PI"); } - if ($USER->uid != $SSO["user"]) { - UnityHTTPD::badRequest( - "cannot request due to uid mismatch: " . - "USER='{$USER->uid}' SSO[user]='{$SSO["user"]}'" - ); + if (!isset($_POST["tos"]) || $_POST["tos"] != "agree") { + UnityHTTPD::badRequest("user did not agree to terms of service"); } $USER->getPIGroup()->requestGroup($SEND_PIMESG_TO_ADMINS); break; @@ -126,14 +123,14 @@ if ($isPI) { echo "

You are curently a principal investigator on the Unity Cluster

"; -} elseif ($hasGroups) { - echo "

You are curently a user on the Unity Cluster

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

You are curently a qualified user on the Unity Cluster

"; } else { echo "

- You are currently not assigned to any PI, and will be + You are currently an unqualified user, and will be unable to use the cluster. - Go to the + To become qualified, go to the My PIs page to join a PI, or click on the button below if you are a PI. Do not click the button below if you are a student. @@ -167,9 +164,24 @@ "; } else { - echo ""; $onclick = "return confirm(\"Are you sure you want to request a PI account?\")"; - echo ""; + $tos_url = CONFIG["site"]["terms_of_service_url"]; + $account_policy_url = CONFIG["site"]["account_policy_url"]; + echo " + +
+ +
+ + + "; } } echo ""; diff --git a/webroot/panel/new_account.php b/webroot/panel/new_account.php index 2446f2c3..336db9f1 100644 --- a/webroot/panel/new_account.php +++ b/webroot/panel/new_account.php @@ -2,193 +2,34 @@ require_once __DIR__ . "/../../resources/autoload.php"; -use UnityWebPortal\lib\exceptions\EntryNotFoundException; use UnityWebPortal\lib\UnityHTTPD; -use UnityWebPortal\lib\UnityGroup; -use UnityWebPortal\lib\UnitySQL; +use UnityWebPortal\lib\UnityUser; if ($USER->exists()) { UnityHTTPD::redirect(CONFIG["site"]["prefix"] . "/panel/account.php"); } - -$pending_requests = $SQL->getRequestsByUser($USER->uid); - if ($_SERVER["REQUEST_METHOD"] == "POST") { - if (isset($_POST["new_user_sel"])) { - if (!isset($_POST["eula"]) || $_POST["eula"] != "agree") { - UnityHTTPD::badRequest("user did not agree to EULA"); - } - if ($_POST["new_user_sel"] == "not_pi") { - $pi_groupname = $_POST["pi"]; - if (substr($pi_groupname, 0, 3) !== "pi_" && str_contains($pi_groupname, "@")) { - try { - $pi_groupname = UnityGroup::ownerMail2GID($pi_groupname); - } catch (EntryNotFoundException) { - } - } - $form_group = new UnityGroup($pi_groupname, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK); - if (!$form_group->exists()) { - UnityHTTPD::badRequest("The selected PI '" . $pi_groupname . "'does not exist"); - } - $form_group->newUserRequest($USER); - } - if ($_POST["new_user_sel"] == "pi") { - if (!isset($_POST["confirm_pi"]) || $_POST["confirm_pi"] != "agree") { - UnityHTTPD::badRequest("user did not agree to account policy"); - } - $USER->getPIGroup()->requestGroup($SEND_PIMESG_TO_ADMINS); - } - } elseif (isset($_POST["cancel"])) { - foreach ($pending_requests as $request) { - if ($request["request_for"] == "admin") { - $USER->getPIGroup()->cancelGroupRequest(); - } else { - $pi_group = new UnityGroup( - $request["request_for"], - $LDAP, - $SQL, - $MAILER, - $REDIS, - $WEBHOOK - ); - $pi_group->cancelGroupJoinRequest($user = $USER); - } - } - } + $user = new UnityUser($SSO["user"], $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK); + $user->init($SSO["firstname"], $SSO["lastname"], $SSO["mail"], $SSO["org"]); + // header.php will redirect to this same page again and then this page will redirect to account } require $LOC_HEADER; ?> -

Request Account

+

Register New Account


- - 0) : ?> -

You have pending account activation requests:

- - -
-

Requesting Ownership of PI Account/Group

-

You will receive an email when your account has been approved.

-

- $name if you have not heard back in one business day."; - ?> -

-
-

Requesting Membership in a PI Group

-

You will receive an email when your account has been approved by the PI.

-

You may need to remind them.

-
-
- - - - -
-

Please verify that the information below is correct before continuing

-
- Name   - -
- Email   - -
-

Your unity cluster username will be

- -

In order to activate your account on the Unity cluster, - you must join an existing PI group, or request your own PI group.

- -
- - - - -
- - -
- -
- - -
- - -
- - - - - - +

Please verify that the information below is correct before continuing

+
+ Name   + +
+ Email   + +
+

Your unity cluster username will be

+
+
+ +
" . $firstname . " " . $lastname . "" . $uid . "" . $email . "" . $date . "$name$uid$email$date"; echo "
- + + onclick='return confirm(\"Are you sure you want to approve $uid?\")'> + onclick='return confirm(\"Are you sure you want to deny $uid?\")'>
"; echo "