Skip to content
Closed
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 .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ repos:
resources/lib/phpopenldaper/.*|
vendor/.*|
resources/lib/.*|
resources/mail/.*|
)$

- repo: https://github.com/rbubley/mirrors-prettier
Expand All @@ -47,6 +48,7 @@ repos:
vendor/.*|
resources/templates/.*|
webroot/.*|
resources/mail/.*|
)$

# linters (work required) ########################################################################
Expand Down Expand Up @@ -81,6 +83,7 @@ repos:
resources/lib/phpopenldaper/.*|
vendor/.*|
resources/lib/.*|
resources/mail/.*|
)$
- id: php-l
name: php -l
Expand Down
7 changes: 5 additions & 2 deletions defaults/config.ini.default
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,18 @@ 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)
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
Expand Down
1 change: 1 addition & 0 deletions resources/autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
2 changes: 1 addition & 1 deletion resources/init.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
82 changes: 82 additions & 0 deletions resources/lib/PosixGroup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace UnityWebPortal\lib;

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
{
protected LDAPEntry $entry;

public function __construct(LDAPEntry $entry)
{
$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 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 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 memberUIDExists(string $uid): bool
{
return in_array($uid, $this->getMemberUIDs());
}
}
70 changes: 11 additions & 59 deletions resources/lib/UnityGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@
/**
* Class that represents a single PI group in the Unity Cluster.
*/
class UnityGroup
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;
Expand All @@ -26,42 +24,19 @@ public function __construct(
UnityMailer $MAILER,
UnityWebhook $WEBHOOK,
) {
$gid = trim($gid);
parent::__construct($LDAP->getPIGroupEntry(trim($gid)));
$this->gid = $gid;
$this->entry = $LDAP->getPIGroupEntry($gid);

$this->LDAP = $LDAP;
$this->SQL = $SQL;
$this->MAILER = $MAILER;
$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()) {
Expand Down Expand Up @@ -110,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
}

/**
Expand Down Expand Up @@ -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->addMemberUID($new_user->uid);
$this->SQL->removeRequest($new_user->uid, $this->gid);
if ($send_mail) {
$this->MAILER->sendMail($new_user->getMail(), "group_user_added", [
Expand All @@ -216,7 +191,8 @@ 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
// 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
Expand All @@ -240,14 +216,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->memberUIDExists($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->removeMemberUID($new_user->uid);
if ($send_mail) {
$this->MAILER->sendMail($new_user->getMail(), "group_user_removed", [
"group" => $this->gid,
Expand All @@ -264,7 +240,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->memberUIDExists($new_user->uid)) {
UnityHTTPD::errorLog("warning", "user '$new_user' already in group");
return;
}
Expand Down Expand Up @@ -310,7 +286,7 @@ public function getRequests(): array

public function getGroupMembers(): array
{
$members = $this->getGroupMemberUIDs();
$members = $this->getMemberUIDs();
$out = [];
foreach ($members as $member) {
$user_obj = new UnityUser(
Expand All @@ -325,13 +301,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();
Expand All @@ -358,23 +327,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);
Expand Down Expand Up @@ -418,7 +370,7 @@ public static function ownerMail2GID(string $email): string
public function getGroupMembersAttributes(array $attributes, array $default_values = []): array
{
return $this->LDAP->getUsersAttributes(
$this->getGroupMemberUIDs(),
$this->getMemberUIDs(),
$attributes,
$default_values,
);
Expand Down
23 changes: 8 additions & 15 deletions resources/lib/UnityLDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -35,8 +36,8 @@ class UnityLDAP extends LDAPConn
private LDAPEntry $groupOU;
private LDAPEntry $pi_groupOU;
private LDAPEntry $org_groupOU;
private LDAPEntry $adminGroup;
private LDAPEntry $qualifiedUserGroup;

public array $userModifierGroups;

public function __construct()
{
Expand All @@ -46,8 +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 = $this->getEntry(CONFIG["ldap"]["admin_group"]);
$this->qualifiedUserGroup = $this->getEntry(CONFIG["ldap"]["qualified_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
Expand All @@ -70,16 +73,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;
Expand Down Expand Up @@ -191,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->getAttribute("memberuid");
return $this->userModifierGroups["qualified"]->getMemberUIDs();
}

public function getQualifiedUsers($UnitySQL, $UnityMailer, $UnityWebhook): array
Expand Down
Loading