File transfer
This commit is contained in:
123
app/Addons/AdvancedAdmin/Services/Roles/PermissionResolver.php
Normal file
123
app/Addons/AdvancedAdmin/Services/Roles/PermissionResolver.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Permission Resolver — Core of the Role-Based Permission System
|
||||
*
|
||||
* Resolution order (first match wins):
|
||||
* 1. Server-level explicit DENY → false
|
||||
* 2. Server-level explicit ALLOW → true
|
||||
* 3. Role DENY (highest priority role first) → false
|
||||
* 4. Role ALLOW → true
|
||||
* 5. Default → false
|
||||
*
|
||||
* @author Ball Studios <https://git.balls.studio>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Addons\AdvancedAdmin\Services\Roles;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Pterodactyl\Addons\AdvancedAdmin\Models\Role;
|
||||
use Pterodactyl\Addons\AdvancedAdmin\Models\RoleAuditLog;
|
||||
use Pterodactyl\Addons\AdvancedAdmin\Models\ServerPermissionOverride;
|
||||
use Pterodactyl\Addons\AdvancedAdmin\Models\ServerRoleAssignment;
|
||||
|
||||
class PermissionResolver
|
||||
{
|
||||
/**
|
||||
* Resolve whether a user has a permission on a server.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function resolve(int $userId, int $serverId, string $permission): bool
|
||||
{
|
||||
// 1 & 2: Check server-level override
|
||||
$override = ServerPermissionOverride::query()
|
||||
->where('server_id', $serverId)
|
||||
->where('user_id', $userId)
|
||||
->where('permission', $permission)
|
||||
->first();
|
||||
|
||||
if ($override && !$override->isUnset()) {
|
||||
return $override->isAllow();
|
||||
}
|
||||
|
||||
// 3 & 4: Check role-level (sorted by priority desc — highest wins)
|
||||
$roles = $this->getUserRolesForServer($userId, $serverId);
|
||||
|
||||
foreach ($roles as $role) {
|
||||
$value = $role->getPermission($permission);
|
||||
if ($value === 'deny') return false;
|
||||
if ($value === 'allow') return true;
|
||||
}
|
||||
|
||||
// 5: Default deny
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full effective permission map for a user on a server.
|
||||
* Returns array of [permission => ['value' => bool, 'source' => string]]
|
||||
*
|
||||
* @param string[] $allPermissions
|
||||
* @return array<string, array{value: bool, source: string}>
|
||||
*/
|
||||
public function resolveAll(int $userId, int $serverId, array $allPermissions): array
|
||||
{
|
||||
$overrides = ServerPermissionOverride::query()
|
||||
->where('server_id', $serverId)
|
||||
->where('user_id', $userId)
|
||||
->get()
|
||||
->keyBy('permission');
|
||||
|
||||
$roles = $this->getUserRolesForServer($userId, $serverId);
|
||||
|
||||
$result = [];
|
||||
foreach ($allPermissions as $permission) {
|
||||
[$value, $source] = $this->resolveWithSource($permission, $overrides, $roles);
|
||||
$result[$permission] = ['value' => $value, 'source' => $source];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's assigned roles for a server, ordered by priority DESC.
|
||||
*/
|
||||
public function getUserRolesForServer(int $userId, int $serverId): Collection
|
||||
{
|
||||
return ServerRoleAssignment::query()
|
||||
->where('server_id', $serverId)
|
||||
->where('user_id', $userId)
|
||||
->with(['role.permissions'])
|
||||
->get()
|
||||
->map(fn ($a) => $a->role)
|
||||
->filter()
|
||||
->sortByDesc('priority')
|
||||
->values();
|
||||
}
|
||||
|
||||
// ─── Internal ─────────────────────────────────────────────────────────────
|
||||
|
||||
private function resolveWithSource(
|
||||
string $permission,
|
||||
Collection $overrides,
|
||||
Collection $roles
|
||||
): array {
|
||||
// Server override
|
||||
if ($overrides->has($permission)) {
|
||||
$o = $overrides->get($permission);
|
||||
if (!$o->isUnset()) {
|
||||
return [$o->isAllow(), 'server_override'];
|
||||
}
|
||||
}
|
||||
|
||||
// Role
|
||||
foreach ($roles as $role) {
|
||||
$value = $role->getPermission($permission);
|
||||
if ($value === 'deny') return [false, "role:{$role->name}"];
|
||||
if ($value === 'allow') return [true, "role:{$role->name}"];
|
||||
}
|
||||
|
||||
return [false, 'default'];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user