diff --git a/test/functional/WorkerUnityCourseTest.php b/test/functional/WorkerUnityCourseTest.php index 187c713e9..f0d522d25 100644 --- a/test/functional/WorkerUnityCourseTest.php +++ b/test/functional/WorkerUnityCourseTest.php @@ -5,7 +5,9 @@ class WorkerUnityCourseTest extends UnityWebPortalTestCase private static string $course_owner_uid = "cs124_org1_test"; private static string $course_gid = "pi_cs124_org1_test"; private static array $course_owner_name = ["cs124", "Fall 2025"]; - private static string $manager_uid = "user2_org1_test"; + private static string $test1_manager_uid = "user2_org1_test"; + private static array $test2_manager_uids = ["user2_org1_test", "user1_org1_test"]; + private static string $test2_manager_uids_str = " user2_org1_test , user1_org1_test , ,,, user2_org1_test "; private static string $manager_mail = "user2@org1.test"; private static string $courseOwnerMail = "user2+cs124@org1.test"; @@ -13,7 +15,7 @@ public function testCreateCourse() { global $LDAP, $USER; $this->switchUser("Blank"); - $this->assertEquals(self::$manager_uid, $USER->uid); + $this->assertEquals(self::$test1_manager_uid, $USER->uid); $this->assertEquals(self::$manager_mail, $USER->getMail()); $manager = $USER; $pi_group_entry = $LDAP->getPIGroupEntry(self::$course_gid); @@ -24,14 +26,12 @@ public function testCreateCourse() self::$course_owner_name[0], self::$course_owner_name[1], self::$course_owner_uid, - self::$manager_uid, + self::$test1_manager_uid, ]); $stdin_file_path = getPathFromFileHandle($stdin_file); try { executeWorker("unity-course.php", stdinFilePath: $stdin_file_path); // error_log(implode("\n", $output_lines)); - // our LDAP conn doesn't know about changes from subprocess - unset($GLOBALS["ldapconn"]); $this->switchUser("Admin"); $pi_group_entry = $LDAP->getPIGroupEntry(self::$course_gid); $owner_user_entry = $LDAP->getUserEntry(self::$course_owner_uid); @@ -52,4 +52,43 @@ public function testCreateCourse() unlink($stdin_file_path); } } + + public function testCreateCourseMultipleManagers() + { + global $LDAP, $USER; + $this->switchUser("Blank"); + $pi_group_entry = $LDAP->getPIGroupEntry(self::$course_gid); + $owner_user_entry = $LDAP->getUserEntry(self::$course_owner_uid); + $this->assertFalse($pi_group_entry->exists()); + $this->assertFalse($owner_user_entry->exists()); + $stdin_file = writeLinesToTmpFile([ + self::$course_owner_name[0], + self::$course_owner_name[1], + self::$course_owner_uid, + self::$test2_manager_uids_str, + ]); + $stdin_file_path = getPathFromFileHandle($stdin_file); + try { + executeWorker("unity-course.php", stdinFilePath: $stdin_file_path); + // error_log(implode("\n", $output_lines)); + $this->switchUser("Admin"); + $pi_group_entry = $LDAP->getPIGroupEntry(self::$course_gid); + $owner_user_entry = $LDAP->getUserEntry(self::$course_owner_uid); + $this->assertTrue($pi_group_entry->exists()); + $this->assertTrue($owner_user_entry->exists()); + $this->assertEquals(self::$courseOwnerMail, $owner_user_entry->getAttribute("mail")[0]); + $this->assertEqualsCanonicalizing( + array_merge([self::$course_owner_uid], self::$test2_manager_uids), + $pi_group_entry->getAttribute("memberuid"), + ); + $this->assertEqualsCanonicalizing( + self::$test2_manager_uids, + $pi_group_entry->getAttribute("manageruid"), + ); + } finally { + ensurePIGroupDoesNotExist(self::$course_gid); + ensureUserDoesNotExist(self::$course_owner_uid); + unlink($stdin_file_path); + } + } } diff --git a/workers/unity-course.php b/workers/unity-course.php index 889f6d00e..19653d630 100755 --- a/workers/unity-course.php +++ b/workers/unity-course.php @@ -20,19 +20,36 @@ function flatten_attributes(array $attributes): array return array_map(fn($v) => count($v) === 1 ? $v[0] : $v, $attributes); } +/** return string[] */ +function parse_comma_delimited_list(string $input): array +{ + $output = trim($input); + $output = explode(",", $output); + $output = array_map("trim", $output); + $output = array_unique($output); + $output = array_filter($output, fn($x) => $x !== ""); + return $output; +} + $givenName = trim(readline("Enter the course ID (example: CS123): ")); $sn = trim(readline("Enter the year and semester of the course (example: Fall 2025): ")); $cn = strtolower( trim(readline("Please enter the cn to be used for the course (example: cs123_umass_edu): ")), ); -$manager_uid = trim( - readline("Enter the UID of the group manager (example: simonleary_umass_edu): "), +$manager_uids = parse_comma_delimited_list( + readline("Enter the UID(s) of the group manager(s) (example: simonleary_umass_edu,bryank_uri_edu): ") ); +if (count($manager_uids) === 0) { + _die("at least one group manager UID is required", 1); +} $org_gid = cn2org($cn); -$manager = new UnityUser($manager_uid, $LDAP, $SQL, $MAILER); -if (!$manager->exists()) { - _die("no such user: '$manager_uid'", 1); +$managers = []; +foreach ($manager_uids as $manager_uid) { + array_push($managers, new UnityUser($manager_uid, $LDAP, $SQL, $MAILER)); + if (!end($managers)->exists()) { + _die("no such user: '$manager_uid'", 1); + } } $course_user = new UnityUser($cn, $LDAP, $SQL, $MAILER); @@ -49,7 +66,7 @@ function flatten_attributes(array $attributes): array $course_user->setFlag(UserFlag::IMMORTAL, true, false, true); $course_pi_group = $course_user->getPIGroup(); -$course_user->setMail($course_pi_group->addPlusAddressToMail($manager->getMail())); +$course_user->setMail($course_pi_group->addPlusAddressToMail($managers[0]->getMail())); if ($course_pi_group->exists()) { $course_pi_group_dn = $LDAP->getPIGroupEntry($course_pi_group->gid)->getDN(); @@ -58,9 +75,11 @@ function flatten_attributes(array $attributes): array $course_pi_group->requestGroup(false, false); $course_pi_group->approveGroup(); -$course_pi_group->newUserRequest($manager, false); -$course_pi_group->approveUser($manager); -$course_pi_group->addManagerUID($manager_uid); +foreach ($managers as $manager) { + $course_pi_group->newUserRequest($manager, false); + $course_pi_group->approveUser($manager); + $course_pi_group->addManagerUID($manager->uid); +} print "LDAP entries created:\n"; print _json_encode(