203 lines
6.1 KiB
PHP
203 lines
6.1 KiB
PHP
<?php
|
|
|
|
namespace objects;
|
|
|
|
use classes\db;
|
|
use classes\object_property;
|
|
use Exception;
|
|
use traits\db_object_t;
|
|
use Throwable;
|
|
|
|
class groups_permissions_o extends db
|
|
{
|
|
use db_object_t;
|
|
|
|
public object_property $group_id;
|
|
public object_property $permission;
|
|
|
|
public function structure(): void
|
|
{
|
|
$this->setTable('groups_permissions');
|
|
}
|
|
|
|
/**
|
|
* Add a permission to a group
|
|
* @param int $group_id
|
|
* @param string $permission
|
|
* @return void
|
|
* @throws Exception If the object was not created successfully
|
|
*/
|
|
public function add(int $group_id, string $permission): void
|
|
{
|
|
// Check if the group exists
|
|
$group = new groups_o();
|
|
$group->select($group_id);
|
|
$group->requireSelected();
|
|
// Check if the permission already exists for the group
|
|
$isAlreadyDefined = self::getFieldsWhere([
|
|
'group_id' => $group_id,
|
|
'permission' => $permission
|
|
], ['id']);
|
|
// Throw an exception if the permission already exists for the group
|
|
if ($isAlreadyDefined) {
|
|
throw new Exception('The permission already exists for the group.');
|
|
}
|
|
// Add the permission
|
|
$tmp_id = self::add_object([
|
|
'group_id' => $group_id,
|
|
'permission' => $permission
|
|
]);
|
|
$this->id = $tmp_id;
|
|
self::getObjectProperties();
|
|
if (!$this->id) {
|
|
throw new Exception('The permission was not created successfully.');
|
|
}
|
|
$this->invalidateGroupSessionCaches($group_id);
|
|
self::objectChanged();
|
|
}
|
|
|
|
public function getObjectProperties(): void
|
|
{
|
|
$this->group_id = new object_property($this->table, $this->id, 'group_id', 'int', false);
|
|
$this->permission = new object_property($this->table, $this->id, 'permission', 'string', false);
|
|
}
|
|
|
|
public function objectChanged(): void
|
|
{
|
|
// Cache invalidation is handled in add/remove where group context is guaranteed.
|
|
}
|
|
|
|
/**
|
|
* Remove a permission from a group
|
|
* @param int $group_id
|
|
* @param string $permission
|
|
* @return void
|
|
* @throws Exception If the permission does not exist for the group
|
|
* @throws Exception If the object was not deleted successfully
|
|
* @throws Exception If the group does not exist
|
|
*/
|
|
public function remove(int $group_id, string $permission): void
|
|
{
|
|
// Check if the group exists
|
|
$group = new groups_o();
|
|
$group->select($group_id);
|
|
$group->requireSelected();
|
|
// Check if the permission exists for the group
|
|
$isDefined = self::getFieldsWhere([
|
|
'group_id' => $group_id,
|
|
'permission' => $permission
|
|
], ['id']);
|
|
// Throw an exception if the permission does not exist for the group
|
|
if (!$isDefined) {
|
|
throw new Exception('The permission does not exist for the group.');
|
|
}
|
|
// Get the id of the permission entry in the database
|
|
$id = $isDefined[0]['id'];
|
|
// Remove the permission
|
|
$tmp_id = new groups_permissions_o();
|
|
$tmp_id->select((int)$id);
|
|
$tmp_id->requireSelected();
|
|
$tmp_id->delete();
|
|
$this->invalidateGroupSessionCaches($group_id);
|
|
}
|
|
|
|
/**
|
|
* Invalidate cached permissions and session payloads for users associated with a group.
|
|
*/
|
|
private function invalidateGroupSessionCaches(int $group_id): void
|
|
{
|
|
if ($group_id <= 0 || !defined('redis')) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
$userRows = (new users_o())->getFieldsWhere([
|
|
'group_id' => $group_id,
|
|
], ['id']);
|
|
|
|
if (count($userRows) === 0) {
|
|
return;
|
|
}
|
|
|
|
$userIds = [];
|
|
foreach ($userRows as $userRow) {
|
|
$id = (int)($userRow['id'] ?? 0);
|
|
if ($id > 0) {
|
|
$userIds[] = $id;
|
|
}
|
|
}
|
|
$userIds = array_values(array_unique($userIds));
|
|
|
|
if (count($userIds) === 0) {
|
|
return;
|
|
}
|
|
|
|
foreach ($userIds as $userId) {
|
|
redis->clear_keys('perm:user:' . $userId . ':*');
|
|
}
|
|
|
|
$tokenRows = (new tokens_o())->getFieldsWhere([
|
|
'user_id' => $userIds,
|
|
], ['token']);
|
|
|
|
foreach ($tokenRows as $tokenRow) {
|
|
$token = (string)($tokenRow['token'] ?? '');
|
|
if ($token === '') {
|
|
continue;
|
|
}
|
|
redis->clear_auth_session($token);
|
|
}
|
|
} catch (Throwable) {
|
|
// Cache invalidation must not block permission updates.
|
|
}
|
|
}
|
|
|
|
public function asArray(): array
|
|
{
|
|
return [
|
|
'id' => (int)$this->id,
|
|
'group_id' => (int)$this->group_id->value(),
|
|
'permission' => (string)$this->permission->value()
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get all permissions for a group
|
|
* @param int $group_id
|
|
* @return array
|
|
*/
|
|
public function getGroupPermissions(int $group_id): array
|
|
{
|
|
$raw_permissions = self::getFieldsWhere([
|
|
'group_id' => $group_id
|
|
], ['permission']);
|
|
$permissions = [];
|
|
foreach ( $raw_permissions as $permission ) {
|
|
$permissions[] = $permission['permission'];
|
|
}
|
|
return $permissions;
|
|
}
|
|
|
|
/**
|
|
* Get all permissions for a group matching a regex
|
|
* @throws Exception If the group does not exist
|
|
*/
|
|
public function getGroupPermissionsMatching(int $id, string $regex): array
|
|
{
|
|
// Check if the group exists
|
|
$group = new groups_o();
|
|
$group->select($id);
|
|
if (!$group->exists()) {
|
|
return [];
|
|
}
|
|
// Get the permissions
|
|
$permissions = self::getFieldsWhere([
|
|
'group_id' => $id
|
|
], ['permission']);
|
|
// Filter the permissions
|
|
return array_filter($permissions, function ($permission) use ($regex) {
|
|
return preg_match($regex, $permission['permission']);
|
|
});
|
|
}
|
|
}
|