diff --git a/resources/lib/UnityPerms.php b/resources/lib/UnityPerms.php new file mode 100644 index 0000000..e16a66d --- /dev/null +++ b/resources/lib/UnityPerms.php @@ -0,0 +1,131 @@ +SQL = $SQL; + $this->USER = $USER; + } + + public function checkApproveUser($uid, $operated_on, $group) + { + if (!$this->USER->isInGroup($uid, $group)) { + return false; + } + + $role = $this->SQL->getRole($uid, $group); + + if ($this->SQL->hasPerm($role, 'unity.admin') || $this->SQL->hasPerm($role, 'unity.admin_no_grant')) { + return true; + } + + if (!$this->SQL->hasPerm($role, 'unity.approve_user')) { + return false; + } + + $operated_on_role = $this->SQL->getRole($operated_on, $group); + + if ($this->SQL->getPriority($operated_on_role) >= $this->SQL->getPriority($role)) { + return false; + } + + return true; + } + + public function checkDenyUser($uid, $operated_on, $group) + { + if (!$this->USER->isInGroup($uid, $group)) { + return false; + } + + $role = $this->SQL->getRole($uid, $group); + + if ($this->SQL->hasPerm($role, 'unity.admin') || $this->SQL->hasPerm($role, 'unity.admin_no_grant')) { + return true; + } + + if (!$this->SQL->hasPerm($role, 'unity.deny_user')) { + return false; + } + + $operated_on_role = $this->SQL->getRole($operated_on, $group); + + if ($this->SQL->getPriority($operated_on_role) >= $this->SQL->getPriority($role)) { + return false; + } + + return true; + } + + public function checkGrantRole($uid, $group, $role) + { + if (!$this->USER->isInGroup($uid, $group)) { + return false; + } + + if (!$this->SQL->roleAvailableInGroup($uid, $group, $role)) { + return false; + } + + $user_role = $this->SQL->getRole($uid, $group); + + if ($this->SQL->hasPerm($user_role, 'unity.admin_no_grant') && $role == 'unity.admin') { + return false; + } + + if ($this->SQL->hasPerm($user_role, 'unity.admin') || $this->SQL->hasPerm($user_role, 'unity.admin_no_grant')) { + return true; + } + + if (!$this->SQL->hasPerm($user_role, 'unity.grant_role')) { + return false; + } + + $role_to_grant = $this->SQL->getRole($role, $group); + + if ($this->SQL->getPriority($role_to_grant) >= $this->SQL->getPriority($user_role)) { + return false; + } + + return true; + } + + public function checkRevokeRole($uid, $group, $role) + { + if (!$this->USER->isInGroup($uid, $group)) { + return false; + } + + if (!$this->SQL->roleAvailableInGroup($uid, $group, $role)) { + return false; + } + + $user_role = $this->SQL->getRole($uid, $group); + + if ($this->SQL->hasPerm($user_role, 'unity.admin_no_grant') && $role == 'unity.admin') { + return false; + } + + if ($this->SQL->hasPerm($user_role, 'unity.admin') || $this->SQL->hasPerm($user_role, 'unity.admin_no_grant')) { + return true; + } + + if (!$this->SQL->hasPerm($user_role, 'unity.revoke_role')) { + return false; + } + + $role_to_revoke = $this->SQL->getRole($role, $group); + + if ($this->SQL->getPriority($role_to_revoke) >= $this->SQL->getPriority($user_role)) { + return false; + } + + return true; + } +} diff --git a/resources/lib/UnitySQL.php b/resources/lib/UnitySQL.php index 1dccc71..904ea2f 100644 --- a/resources/lib/UnitySQL.php +++ b/resources/lib/UnitySQL.php @@ -14,6 +14,12 @@ class UnitySQL private const TABLE_AUDIT_LOG = "audit_log"; private const TABLE_ACCOUNT_DELETION_REQUESTS = "account_deletion_requests"; private const TABLE_SITEVARS = "sitevars"; + private const TABLE_GROUP_ROLES = "groupRoles"; + private const TABLE_GROUP_TYPES = "groupTypes"; + private const TABLE_GROUP_ROLE_ASSIGNMENTS = "groupRoleAssignments"; + private const TABLE_GROUP_REQUESTS = "groupRequests"; + private const TABLE_GROUP_JOIN_REQUESTS = "groupJoinRequests"; + private const REQUEST_ADMIN = "admin"; @@ -299,4 +305,70 @@ public function updateSiteVar($name, $value) $stmt->execute(); } + + public function getRole($uid, $group) + { + $stmt = $this->conn->prepare( + "SELECT * FROM " . self::TABLE_GROUP_ROLE_ASSIGNMENTS . " WHERE user=:uid AND `group`=:group" + ); + $stmt->bindParam(":uid", $uid); + $stmt->bindParam(":group", $group); + + $stmt->execute(); + + return $stmt->fetchAll()[0]['role']; + } + + public function hasPerm($role, $perm) + { + $stmt = $this->conn->prepare( + "SELECT * FROM " . self::TABLE_GROUP_ROLES . " WHERE slug=:role" + ); + $stmt->bindParam(":role", $role); + + $stmt->execute(); + + $row = $stmt->fetchAll()[0]; + $perms = explode(",", $row['perms']); + return in_array($perm, $perms); + } + + public function getPriority($role) + { + $stmt = $this->conn->prepare( + "SELECT * FROM " . self::TABLE_GROUP_ROLES . " WHERE slug=:role" + ); + $stmt->bindParam(":role", $role); + + $stmt->execute(); + + $row = $stmt->fetchAll()[0]; + return $row['priority']; + } + + public function roleAvailableInGroup($uid, $group, $role) + { + $stmt = $this->conn->prepare( + "SELECT * FROM " . self::TABLE_GROUP_ROLE_ASSIGNMENTS . " WHERE user=:uid AND `group`=:group" + ); + $stmt->bindParam(":uid", $uid); + $stmt->bindParam(":group", $group); + + $stmt->execute(); + $row = $stmt->fetchAll()[0]; + + $group_slug = $row['group']; + + $stmt = $this->conn->prepare( + "SELECT * FROM " . self::TABLE_GROUP_TYPES . " WHERE slug=:slug" + ); + + $stmt->bindParam(":slug", $group_slug); + $stmt->execute(); + + $row = $stmt->fetchAll()[0]; + $roles = explode(",", $row['roles']); + + return in_array($role, $roles); + } } diff --git a/resources/lib/UnityUser.php b/resources/lib/UnityUser.php index d2cc6d2..4f88eac 100644 --- a/resources/lib/UnityUser.php +++ b/resources/lib/UnityUser.php @@ -671,4 +671,29 @@ public function hasRequestedAccountDeletion() { return $this->SQL->accDeletionRequestExists($this->getUID()); } + + /** + * Checks whether a user is in a group or not + * @param string $uid uid of the user + * @param string or object $group group to check + * @return boolean true if user is in group, false if not + */ + + public function isInGroup($uid, $group) + { + if (gettype($group) == "string") { + $group_checked = new UnityGroup( + $group, + $this->LDAP, + $this->SQL, + $this->MAILER, + $this->REDIS, + $this->WEBHOOK + ); + } else { + $group_checked = $group; + } + + return in_array($uid, $group_checked->getGroupMemberUIDs()); + } } diff --git a/tools/docker-dev/sql/bootstrap.sql b/tools/docker-dev/sql/bootstrap.sql index 0baec68..96f8ad7 100644 --- a/tools/docker-dev/sql/bootstrap.sql +++ b/tools/docker-dev/sql/bootstrap.sql @@ -3,9 +3,9 @@ -- https://www.phpmyadmin.net/ -- -- Host: 127.0.0.1 --- Generation Time: Jul 11, 2023 at 04:05 PM --- Server version: 10.3.37-MariaDB-0ubuntu0.20.04.1 --- PHP Version: 7.4.3-4ubuntu2.17 +-- Generation Time: Jul 13, 2023 at 02:29 AM +-- Server version: 10.3.38-MariaDB-0ubuntu0.20.04.1 +-- PHP Version: 7.4.3-4ubuntu2.19 SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET AUTOCOMMIT = 0; @@ -65,6 +65,80 @@ CREATE TABLE `events` ( -- -------------------------------------------------------- +-- +-- Table structure for table `groupJoinRequests` +-- + +CREATE TABLE `groupJoinRequests` ( + `id` int(11) NOT NULL, + `group_name` varchar(1000) NOT NULL, + `requestor` varchar(1000) NOT NULL, + `requested_on` timestamp NOT NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `groupRequests` +-- + +CREATE TABLE `groupRequests` ( + `id` int(11) NOT NULL, + `group_type` varchar(1000) NOT NULL, + `group_name` varchar(1000) NOT NULL, + `requestor` varchar(1000) NOT NULL, + `requested_on` timestamp NOT NULL DEFAULT current_timestamp(), + `start_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `end_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `groupRoleAssignments` +-- + +CREATE TABLE `groupRoleAssignments` ( + `id` int(11) NOT NULL, + `user` varchar(1000) NOT NULL, + `role` varchar(1000) NOT NULL, + `group` varchar(1000) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `groupRoles` +-- + +CREATE TABLE `groupRoles` ( + `id` int(11) NOT NULL, + `name` varchar(1000) NOT NULL, + `slug` varchar(1000) NOT NULL, + `priority` int(11) NOT NULL, + `color` varchar(1000) NOT NULL, + `perms` varchar(1000) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `groupTypes` +-- + +CREATE TABLE `groupTypes` ( + `id` int(11) NOT NULL, + `name` varchar(1000) NOT NULL, + `slug` varchar(1000) NOT NULL, + `color` varchar(1000) NOT NULL, + `time_limited` tinyint(1) NOT NULL, + `def_role` varchar(1000) NOT NULL, + `av_roles` varchar(1000) NOT NULL, + `can_request` tinyint(1) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + -- -- Table structure for table `notices` -- @@ -166,6 +240,36 @@ ALTER TABLE `audit_log` ALTER TABLE `events` ADD PRIMARY KEY (`id`); +-- +-- Indexes for table `groupJoinRequests` +-- +ALTER TABLE `groupJoinRequests` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `groupRequests` +-- +ALTER TABLE `groupRequests` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `groupRoleAssignments` +-- +ALTER TABLE `groupRoleAssignments` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `groupRoles` +-- +ALTER TABLE `groupRoles` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `groupTypes` +-- +ALTER TABLE `groupTypes` + ADD PRIMARY KEY (`id`); + -- -- Indexes for table `notices` -- @@ -218,6 +322,36 @@ ALTER TABLE `audit_log` ALTER TABLE `events` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `groupJoinRequests` +-- +ALTER TABLE `groupJoinRequests` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `groupRequests` +-- +ALTER TABLE `groupRequests` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `groupRoleAssignments` +-- +ALTER TABLE `groupRoleAssignments` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `groupRoles` +-- +ALTER TABLE `groupRoles` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- AUTO_INCREMENT for table `groupTypes` +-- +ALTER TABLE `groupTypes` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + -- -- AUTO_INCREMENT for table `notices` --