Files
api/services/nginx/app/objects/groups_permissions_o.php
T

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']);
});
}
}