143 lines
3.8 KiB
PHP
143 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace KTXC\Stores;
|
|
|
|
use KTXC\Db\DataStore;
|
|
use KTXC\Module\ModuleManager;
|
|
use KTXF\Utile\UUID;
|
|
|
|
/**
|
|
* Role Store - Database operations for user roles
|
|
*/
|
|
class UserRolesStore
|
|
{
|
|
protected const COLLECTION_NAME = 'user_roles';
|
|
|
|
public function __construct(
|
|
protected readonly DataStore $store,
|
|
protected readonly ModuleManager $moduleManager
|
|
) {}
|
|
|
|
// =========================================================================
|
|
// Role Operations
|
|
// =========================================================================
|
|
|
|
/**
|
|
* List all roles for a tenant
|
|
*/
|
|
public function listRoles(string $tenant): array
|
|
{
|
|
$cursor = $this->store->selectCollection(self::COLLECTION_NAME)->find(
|
|
['tid' => $tenant],
|
|
['sort' => ['label' => 1]]
|
|
);
|
|
|
|
$roles = [];
|
|
foreach ($cursor as $entry) {
|
|
$role = (array)$entry;
|
|
// Ensure permissions is an array
|
|
if (isset($role['permissions'])) {
|
|
$role['permissions'] = (array)$role['permissions'];
|
|
}
|
|
$roles[] = $role;
|
|
}
|
|
|
|
return $roles;
|
|
}
|
|
|
|
/**
|
|
* Fetch role by tenant and role ID
|
|
*/
|
|
public function fetchByRid(string $tenant, string $rid): ?array
|
|
{
|
|
$entry = $this->store->selectCollection(self::COLLECTION_NAME)->findOne([
|
|
'tid' => $tenant,
|
|
'rid' => $rid
|
|
]);
|
|
|
|
if (!$entry) {
|
|
return null;
|
|
}
|
|
|
|
return (array)$entry;
|
|
}
|
|
|
|
/**
|
|
* Create a new role
|
|
*/
|
|
public function createRole(string $tenant, array $roleData): array
|
|
{
|
|
$roleData['tid'] = $tenant;
|
|
$roleData['rid'] = $roleData['rid'] ?? UUID::v4();
|
|
$roleData['label'] = $roleData['label'] ?? 'Unnamed Role';
|
|
$roleData['description'] = $roleData['description'] ?? '';
|
|
$roleData['permissions'] = $roleData['permissions'] ?? [];
|
|
$roleData['system'] = $roleData['system'] ?? false;
|
|
|
|
$this->store->selectCollection(self::COLLECTION_NAME)->insertOne($roleData);
|
|
|
|
return $this->fetchByRid($tenant, $roleData['rid']);
|
|
}
|
|
|
|
/**
|
|
* Update an existing role
|
|
*/
|
|
public function updateRole(string $tenant, string $rid, array $updates): bool
|
|
{
|
|
// Prevent updating system flag
|
|
unset($updates['tid'], $updates['rid'], $updates['system']);
|
|
|
|
if (empty($updates)) {
|
|
return false;
|
|
}
|
|
|
|
$result = $this->store->selectCollection(self::COLLECTION_NAME)->updateOne(
|
|
['tid' => $tenant, 'rid' => $rid],
|
|
['$set' => $updates]
|
|
);
|
|
|
|
return $result->getModifiedCount() > 0;
|
|
}
|
|
|
|
/**
|
|
* Delete a role
|
|
*/
|
|
public function deleteRole(string $tenant, string $rid): bool
|
|
{
|
|
// Check if role is system role
|
|
$role = $this->fetchByRid($tenant, $rid);
|
|
if (!$role || ($role['system'] ?? false)) {
|
|
return false; // Cannot delete system roles
|
|
}
|
|
|
|
$result = $this->store->selectCollection(self::COLLECTION_NAME)->deleteOne([
|
|
'tid' => $tenant,
|
|
'rid' => $rid
|
|
]);
|
|
|
|
return $result->getDeletedCount() > 0;
|
|
}
|
|
|
|
/**
|
|
* Count users assigned to a role
|
|
*/
|
|
public function countUsersInRole(string $tenant, string $rid): int
|
|
{
|
|
$count = $this->store->selectCollection('user_accounts')->countDocuments([
|
|
'tid' => $tenant,
|
|
'roles' => $rid
|
|
]);
|
|
|
|
return (int)$count;
|
|
}
|
|
|
|
/**
|
|
* Get all available permissions from modules
|
|
* Grouped by category with metadata
|
|
*/
|
|
public function availablePermissions(): array
|
|
{
|
|
return $this->moduleManager->availablePermissions();
|
|
}
|
|
}
|