Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions resources/init.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
if (time() - ($_SESSION["LAST_ACTIVITY"] ?? 0) > CONFIG["site"]["session_cleanup_idle_seconds"]) {
$_SESSION["csrf_tokens"] = [];
$_SESSION["messages"] = [];
if (array_key_exists("pi_group_gid_to_owner_gecos_and_mail", $_SESSION)) {
unset($_SESSION["pi_group_gid_to_owner_gecos_and_mail"]);
}
session_write_close();
session_start();
}
Expand Down
10 changes: 0 additions & 10 deletions resources/lib/UnityGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -361,16 +361,6 @@ public static function GID2OwnerUID(string $gid): string
return substr($gid, strlen(self::PI_PREFIX));
}

/**
* @throws \UnityWebPortal\lib\exceptions\EntryNotFoundException
*/
public static function ownerMail2GID(string $email): string
{
global $LDAP;
$owner_uid = $LDAP->getUidFromEmail($email); // throws EntryNotFoundException
return self::ownerUID2GID($owner_uid);
}

public function getGroupMembersAttributes(array $attributes, array $default_values = []): array
{
return $this->LDAP->getUsersAttributes(
Expand Down
14 changes: 0 additions & 14 deletions resources/lib/UnityLDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -291,20 +291,6 @@ public function getOrgGroupEntry(string $gid): LDAPEntry
return $this->getEntry(UnityLDAP::RDN . "=$gid," . CONFIG["ldap"]["orggroup_ou"]);
}

/**
* @throws \UnityWebPortal\lib\exceptions\EntryNotFoundException
*/
public function getUidFromEmail(string $email): string
{
$email = ldap_escape($email, flags: LDAP_ESCAPE_FILTER);
$entries = $this->userOU->getChildrenArrayStrict(["uid"], true, "(mail=$email)");
if (count($entries) == 0) {
throw new exceptions\EntryNotFoundException($email);
} else {
return $entries[0]["uid"][0];
}
}

/**
* returns an array with each UID as an array key
* @throws \UnityWebPortal\lib\exceptions\EntryNotFoundException
Expand Down
16 changes: 0 additions & 16 deletions test/functional/PIMemberRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,6 @@ public function testRequestMembershipBogus()
}
}

public function testRequestMembershipByOwnerMail()
{
global $USER, $SQL;
$this->switchUser("EmptyPIGroupOwner");
$pi_group = $USER->getPIGroup();
$this->switchUser("Blank");
try {
$this->requestMembership($pi_group->getOwner()->getMail());
$this->assertTrue($pi_group->requestExists($USER));
} finally {
if ($SQL->requestExists($USER->uid, $pi_group->gid)) {
$SQL->removeRequest($USER->uid, $pi_group->gid);
}
}
}

public function testRequestMembershipDuplicate()
{
global $USER, $SQL;
Expand Down
30 changes: 30 additions & 0 deletions webroot/panel/ajax/pi_search.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

require_once __DIR__ . "/../../../resources/autoload.php"; // Load required libs
use UnityWebPortal\lib\UnityHTTPD;

$search_query = strtolower(UnityHTTPD::getQueryParameter("search"));
if ($search_query === "") {
echo "[]";
UnityHTTPD::die();
}
if (!array_key_exists("pi_group_gid_to_owner_gecos_and_mail", $_SESSION)) {
UnityHTTPD::internalServerError(
'$_SESSION["pi_group_gid_to_owner_gecos_and_mail"] does not exist!',
"Session cache not found. Try reloading the page."
);
}
$pi_group_gid_to_owner_gecos_and_mail = $_SESSION["pi_group_gid_to_owner_gecos_and_mail"];
$output = [];
foreach ($pi_group_gid_to_owner_gecos_and_mail as $gid => [$gecos, $mail]) {
$gid = strtolower($gid);
$gecos = strtolower($gecos);
$mail = strtolower($mail);
if (str_contains($gid, $search_query) || str_contains($gecos, $search_query) || str_contains($mail, $search_query)) {
array_push($output, $gid);
if (count($output) >= 10) {
break;
}
}
}
echo jsonEncode($output);
13 changes: 3 additions & 10 deletions webroot/panel/groups.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,10 @@

$getPIGroupFromPost = function () {
global $LDAP, $SQL, $MAILER, $WEBHOOK;
$gid_or_mail = UnityHTTPD::getPostData("pi");
if (substr($gid_or_mail, 0, 3) !== "pi_" && str_contains($gid_or_mail, "@")) {
try {
$gid_or_mail = UnityGroup::ownerMail2GID($gid_or_mail);
} catch (EntryNotFoundException) {
// oh well, we tried
}
}
$pi_group = new UnityGroup($gid_or_mail, $LDAP, $SQL, $MAILER, $WEBHOOK);
$gid = UnityHTTPD::getPostData("pi");
$pi_group = new UnityGroup($gid, $LDAP, $SQL, $MAILER, $WEBHOOK);
if (!$pi_group->exists()) {
UnityHTTPD::messageError("This PI Doesn't Exist", $gid_or_mail);
UnityHTTPD::messageError("This PI Doesn't Exist", $gid);
UnityHTTPD::redirect();
}
return $pi_group;
Expand Down
94 changes: 62 additions & 32 deletions webroot/panel/modal/new_pi.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,23 @@

require_once __DIR__ . "/../../../resources/autoload.php";
use UnityWebPortal\lib\UnityHTTPD;
use UnityWebPortal\lib\UnityGroup;
$CSRFTokenHiddenFormInput = UnityHTTPD::getCSRFTokenHiddenFormInput();

// cache PI group info in $_SESSION for ajax pi_search.php
// cache persists only until the user loads this page again
$owner_uids = $LDAP->getAllPIGroupOwnerUIDs();
$owner_attributes = $LDAP->getUsersAttributes(
$owner_uids,
["uid", "gecos", "mail"],
default_values: ["gecos" => [""], "mail" => [""]]
);
$pi_group_gid_to_owner_gecos_and_mail = [];
foreach ($owner_attributes as $attributes) {
$gid = UnityGroup::ownerUID2GID($attributes["uid"][0]);
$pi_group_gid_to_owner_gecos_and_mail[$gid] = [$attributes["gecos"][0], $attributes["mail"][0]];
}
$_SESSION["pi_group_gid_to_owner_gecos_and_mail"] = $pi_group_gid_to_owner_gecos_and_mail;
?>

<form
Expand All @@ -13,7 +29,13 @@
<?php echo $CSRFTokenHiddenFormInput; ?>
<input type="hidden" name="form_type" value="addPIform">
<div style="position: relative;">
<input type="text" id="pi_search" name="pi" placeholder="Search PI by NetID" required>
<input
type="text"
id="pi_search"
name="pi"
placeholder="Search by GID, Name, or Email"
required
>
<div class="searchWrapper" style="display: none;"></div>
</div>
<label>
Expand All @@ -23,40 +45,48 @@
Terms of Service
</a>.
</label>
<input type="submit" value="Send Request">
<input type="submit" value="Send Request" disabled>
</form>

<script>
$("input[type=text][name=pi]").keyup(function() {
var searchWrapper = $("div.searchWrapper");
const url = '<?php echo getURL("panel/modal/pi_search.php") ?>';
$.ajax({
url: `${url}?search=` + $(this).val(),
success: function(result) {
searchWrapper.html(result);

if (result == "") {
searchWrapper.hide();
} else {
searchWrapper.show();
(function () {
const input = $("input[name=pi]");
const wrapper = $("div.searchWrapper");
const submit = $("#newPIform > input[type=submit]");
function updateSearch() {
const query = input.val();
$.ajax({
url: '<?php echo getURL("panel/ajax/pi_search.php") ?>',
data: {"search": query},
success: function(data) {
const results = JSON.parse(data);
if (results.length === 0) {
wrapper.html("<span>No Results</span>").show();
submit.prop("disabled", true);
} else if (results.includes(query)) {
// search query exactly matches a PI group GID
wrapper.html("").hide();
submit.prop("disabled", false);
} else {
const html = results.map(gid => `<span>${gid}</span>`).join('');
wrapper.html(html).show();
submit.prop("disabled", true);
}
},
error: function(result) {
const error_msg_div = $("<div></div>");
error_msg_div.html(result.responseText);
submit.after(error_msg_div);
wrapper.html("").hide();
submit.prop("disabled", true);
}
},
error: function (result) {
searchWrapper.html(result.responseText);
searchWrapper.show();
},
});
};
input.on("keyup", () => updateSearch());
wrapper.on("click", "span", function() {
input.val($(this).text());
updateSearch();
});
});

$("div.searchWrapper").on("click", "span", function (event) {
var textBox = $("input[type=text][name=pi]");
textBox.val($(this).html());
});

/**
* Hides the searchresult box on click anywhere
*/
$(document).click(function() {
$("div.searchWrapper").hide();
});
$(document).on("click", () => wrapper.hide());
})();
</script>
49 changes: 0 additions & 49 deletions webroot/panel/modal/pi_search.php

This file was deleted.