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
42 changes: 35 additions & 7 deletions resources/lib/UnityGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,17 @@ public function cancelGroupJoinRequest(UnityUser $user, bool $send_mail = true):
// // now we delete the ldap entry
// $this->entry->ensureExists();
// $this->entry->delete();
// $this->REDIS->removeCacheArray("sorted_groups", "", $this->gid);
// $default_value_getter = [$this->LDAP, "getSortedGroupsForRedis"];
// $this->REDIS->removeCacheArray("sorted_groups", "", $this->gid, $default_value_getter);
// foreach ($users as $user) {
// $this->REDIS->removeCacheArray($user->uid, "groups", $this->gid);
// $this->REDIS->removeCacheArray(
// $user->uid,
// "groups",
// $this->gid,
// fn() => $this->getGroupMemberUIDs(true),
// );
// }
// // FIXME group not removed from user's groups array

// // send email to every user of the now deleted PI group
// if ($send_mail) {
Expand Down Expand Up @@ -417,7 +424,8 @@ private function init(): void
$this->entry->setAttribute("gidnumber", strval($nextGID));
$this->entry->setAttribute("memberuid", [$owner->uid]);
$this->entry->write();
$this->REDIS->appendCacheArray("sorted_groups", "", $this->gid);
$default_value_getter = [$this->LDAP, "getSortedGroupsForRedis"];
$this->REDIS->appendCacheArray("sorted_groups", "", $this->gid, $default_value_getter);
// TODO if we ever make this project based,
// we need to update the cache here with the memberuid
}
Expand All @@ -426,16 +434,36 @@ private function addUserToGroup(UnityUser $new_user): void
{
$this->entry->appendAttribute("memberuid", $new_user->uid);
$this->entry->write();
$this->REDIS->appendCacheArray($this->gid, "members", $new_user->uid);
$this->REDIS->appendCacheArray($new_user->uid, "groups", $this->gid);
$this->REDIS->appendCacheArray(
$this->gid,
"members",
$new_user->uid,
fn() => $this->getGroupMemberUIDs(true),
);
$this->REDIS->appendCacheArray(
$new_user->uid,
"groups",
$this->gid,
fn() => $this->LDAP->getPIGroupGIDsWithMemberUID($new_user->uid),
);
}

private function removeUserFromGroup(UnityUser $old_user): void
{
$this->entry->removeAttributeEntryByValue("memberuid", $old_user->uid);
$this->entry->write();
$this->REDIS->removeCacheArray($this->gid, "members", $old_user->uid);
$this->REDIS->removeCacheArray($old_user->uid, "groups", $this->gid);
$this->REDIS->removeCacheArray(
$this->gid,
"members",
$old_user->uid,
fn() => $this->getGroupMemberUIDs(true),
);
$this->REDIS->removeCacheArray(
$old_user->uid,
"groups",
$this->gid,
fn() => $this->LDAP->getPIGroupGIDsWithMemberUID($old_user->uid),
);
}

public function memberExists(UnityUser $user): bool
Expand Down
23 changes: 23 additions & 0 deletions resources/lib/UnityLDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -458,4 +458,27 @@ public function getUidFromEmail(string $email): LDAPEntry
}
throw new exceptions\EntryNotFoundException($email);
}

public function getSortedQualifiedUsersForRedis(): array
{
$qualified_users = $this->getQualifiedUsersUIDs();
sort($qualified_users);
return $qualified_users;
}

public function getSortedOrgsForRedis(): array
{
$attributes = $this->getAllOrgGroupsAttributes(["cn"]);
$groups = array_map(fn($x) => $x["cn"][0], $attributes);
sort($groups);
return $groups;
}

public function getSortedGroupsForRedis(): array
{
$attributes = $this->getAllPIGroupsAttributes(["cn"]);
$groups = array_map(fn($x) => $x["cn"][0], $attributes);
sort($groups);
return $groups;
}
}
17 changes: 14 additions & 3 deletions resources/lib/UnityOrg.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public function init(): void
$this->entry->setAttribute("objectclass", UnityLDAP::POSIX_GROUP_CLASS);
$this->entry->setAttribute("gidnumber", strval($nextGID));
$this->entry->write();
$this->REDIS->appendCacheArray("sorted_orgs", "", $this->gid);
$default_value_getter = [$this->LDAP, "getSortedOrgsForRedis"];
$this->REDIS->appendCacheArray("sorted_orgs", "", $this->gid, $default_value_getter);
}

public function exists(): bool
Expand Down Expand Up @@ -94,13 +95,23 @@ public function addUser(UnityUser $user): void
{
$this->entry->appendAttribute("memberuid", $user->uid);
$this->entry->write();
$this->REDIS->appendCacheArray($this->gid, "members", $user->uid);
$this->REDIS->appendCacheArray(
$this->gid,
"members",
$user->uid,
fn() => $this->getOrgMemberUIDs(true),
);
}

public function removeUser(UnityUser $user): void
{
$this->entry->removeAttributeEntryByValue("memberuid", $user->uid);
$this->entry->write();
$this->REDIS->removeCacheArray($this->gid, "members", $user->uid);
$this->REDIS->removeCacheArray(
$this->gid,
"members",
$user->uid,
fn() => $this->getOrgMemberUIDs(true),
);
}
}
57 changes: 27 additions & 30 deletions resources/lib/UnityRedis.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace UnityWebPortal\lib;

use Redis;
use Exception;
use TypeError;

class UnityRedis
{
Expand Down Expand Up @@ -61,44 +61,41 @@ public function getCache(string $object, string $key): mixed
return null;
}

public function appendCacheArray(string $object, string $key, mixed $value): void
{
public function appendCacheArray(
string $object,
string $key,
mixed $value,
callable $default_value_getter,
): void {
if (!$this->enabled) {
return;
}

$cached_val = $this->getCache($object, $key);
if (is_null($cached_val)) {
$this->setCache($object, $key, [$value]);
} else {
if (!is_array($cached_val)) {
throw new Exception("This cache value is not an array");
}

array_push($cached_val, $value);
sort($cached_val);
$this->setCache($object, $key, $cached_val);
$old_val = $this->getCache($object, $key) ?? $default_value_getter();
if (!is_array($old_val)) {
throw new TypeError("redis[$object][$key] is not an array!");
}
$new_val = $old_val;
array_push($new_val, $value);
sort($new_val);
$this->setCache($object, $key, $new_val);
}

// TODO return void
public function removeCacheArray(string $object, string $key, mixed $value)
{
public function removeCacheArray(
string $object,
string $key,
mixed $value,
callable $default_value_getter,
) {
if (!$this->enabled) {
return null;
return;
}

$cached_val = $this->getCache($object, $key);
if (is_null($cached_val)) {
$this->setCache($object, $key, []);
} else {
if (!is_array($cached_val)) {
throw new Exception("This cache value is not an array");
}

$cached_val = array_diff($cached_val, [$value]);
$this->setCache($object, $key, $cached_val);
$old_val = $this->getCache($object, $key) ?? $default_value_getter();
if (!is_array($old_val)) {
throw new TypeError("redis[$object][$key] is not an array!");
}
$new_val = array_diff($old_val, [$value]);
sort($new_val);
$this->setCache($object, $key, $new_val);
}

public function flushAll(): void
Expand Down
8 changes: 7 additions & 1 deletion resources/lib/UnityUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,13 @@ public function init(
$this->LDAP->getQualifiedUserGroup()->appendAttribute("memberuid", $this->uid);
$this->LDAP->getQualifiedUserGroup()->write();

$this->REDIS->appendCacheArray("sorted_qualified_users", "", $this->uid);
$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);

Expand Down
16 changes: 12 additions & 4 deletions test/phpunit-bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ function ensureUserDoesNotExist()
$all_users_group->write();
ensure(!in_array($USER->uid, $all_users_group->getAttribute("memberuid")));
}
$REDIS->removeCacheArray("sorted_qualified_users", "", $USER->uid);
$default_value_getter = [$LDAP, "getSortedQualifiedUsersForRedis"];
$REDIS->removeCacheArray("sorted_qualified_users", "", $USER->uid, $default_value_getter);
}

function ensureOrgGroupDoesNotExist()
Expand All @@ -204,7 +205,8 @@ function ensureOrgGroupDoesNotExist()
$org_group->delete();
ensure(!$org_group->exists());
}
$REDIS->removeCacheArray("sorted_orgs", "", $SSO["org"]);
$default_value_getter = [$LDAP, "getSortedOrgsForRedis"];
$REDIS->removeCacheArray("sorted_orgs", "", $SSO["org"], $default_value_getter);
}

function ensureUserNotInPIGroup(UnityGroup $pi_group)
Expand All @@ -214,7 +216,12 @@ function ensureUserNotInPIGroup(UnityGroup $pi_group)
$pi_group->removeUser($USER);
ensure(!$pi_group->memberExists($USER));
}
$REDIS->removeCacheArray($pi_group->gid, "members", $USER->uid);
$REDIS->removeCacheArray(
$pi_group->gid,
"members",
$USER->uid,
fn() => $pi_group->getGroupMemberUIDs(true),
);
}

function ensurePIGroupDoesNotExist()
Expand All @@ -225,7 +232,8 @@ function ensurePIGroupDoesNotExist()
$LDAP->getPIGroupEntry($gid)->delete();
ensure(!$USER->getPIGroup()->exists());
}
$REDIS->removeCacheArray("sorted_groups", "", $gid);
$default_value_getter = [$LDAP, "getSortedGroupsForRedis"];
$REDIS->removeCacheArray("sorted_groups", "", $gid, $default_value_getter);
}

function getNormalUser()
Expand Down
30 changes: 8 additions & 22 deletions workers/update-ldap-cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,11 @@
echo "waiting for LDAP search (users)...\n";
$users = $LDAP->search("objectClass=posixAccount", CONFIG["ldap"]["basedn"], []);
echo "response received.\n";
$user_CNs = $LDAP->getQualifiedUserGroup()->getAttribute("memberuid");
sort($user_CNs);
$REDIS->setCache("sorted_qualified_users", "", $user_CNs);
$sorted_qualified_users_UIDs = $LDAP->getSortedQualifiedUsersForRedis();
$REDIS->setCache("sorted_qualified_users", "", $sorted_qualified_users_UIDs);
foreach ($users as $user) {
$uid = $user->getAttribute("cn")[0];
if (!in_array($uid, $user_CNs)) {
if (!in_array($uid, $sorted_qualified_users_UIDs)) {
continue;
}
$REDIS->setCache($uid, "firstname", $user->getAttribute("givenname")[0]);
Expand All @@ -59,13 +58,7 @@
echo "waiting for LDAP search (org groups)...\n";
$org_groups = $org_group_ou->getChildrenArrayStrict(["cn", "memberuid"], true);
echo "response received.\n";
// phpcs:disable
$org_group_CNs = array_map(function ($x) {
return $x["cn"][0];
}, $org_groups);
// phpcs:enable
sort($org_group_CNs);
$REDIS->setCache("sorted_orgs", "", $org_group_CNs);
$REDIS->setCache("sorted_orgs", "", $LDAP->getSortedOrgsForRedis());
foreach ($org_groups as $org_group) {
$gid = $org_group["cn"][0];
$REDIS->setCache($gid, "members", $org_group["memberuid"] ?? []);
Expand All @@ -75,27 +68,20 @@
echo "waiting for LDAP search (pi groups)...\n";
$pi_groups = $pi_group_ou->getChildrenArrayStrict(["cn", "memberuid"], true);
echo "response received.\n";
// phpcs:disable
$pi_group_CNs = array_map(function ($x) {
return $x["cn"][0];
}, $pi_groups);
// phpcs:enable
sort($pi_group_CNs);
// FIXME should be sorted_pi_groups
$REDIS->setCache("sorted_groups", "", $pi_group_CNs);
$REDIS->setCache("sorted_groups", "", $LDAP->getSortedGroupsForRedis());

$user_pi_group_member_of = [];
foreach ($user_CNs as $uid) {
foreach ($sorted_qualified_users_UIDs as $uid) {
$user_pi_group_member_of[$uid] = [];
}
foreach ($pi_groups as $pi_group) {
$gid = $pi_group["cn"][0];
$members = $pi_group["memberuid"] ?? [];
foreach ($members as $uid) {
if (in_array($uid, $user_CNs)) {
if (in_array($uid, $sorted_qualified_users_UIDs)) {
array_push($user_pi_group_member_of[$uid], $gid);
} else {
echo "warning: group '$gid' has member '$uid' who is not in the users group!\n";
echo "warning: group '$gid' has member '$uid' who is not qualfied!\n";
}
}
$REDIS->setCache($gid, "members", $pi_group["memberuid"] ?? []);
Expand Down