* @license MIT */ namespace Pterodactyl\Addons\AdvancedAdmin\Http\Controllers\Client; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Routing\Controller; use Pterodactyl\Addons\AdvancedAdmin\Http\Resources\RoleResource; use Pterodactyl\Addons\AdvancedAdmin\Http\Resources\EffectivePermissionResource; use Pterodactyl\Addons\AdvancedAdmin\Models\ServerRoleAssignment; use Pterodactyl\Addons\AdvancedAdmin\Services\Roles\PermissionResolver; use Pterodactyl\Addons\AdvancedAdmin\Services\Roles\RoleService; use Pterodactyl\Models\Server; class ServerRoleController extends Controller { public function __construct( private readonly RoleService $roleService, private readonly PermissionResolver $resolver, ) {} /** GET /api/client/servers/{server}/addons/roles/users */ public function listUsers(Request $request, Server $server): JsonResponse { $this->authorizeServerAdmin($request, $server); $assignments = ServerRoleAssignment::query() ->where('server_id', $server->id) ->with(['user', 'role.permissions']) ->get() ->groupBy('user_id') ->map(function ($items) { $user = $items->first()->user; $roles = $items->pluck('role'); return ['user' => $user, 'roles' => $roles]; }) ->values(); return response()->json(['data' => $assignments]); } /** POST /api/client/servers/{server}/addons/roles/assign */ public function assign(Request $request, Server $server): JsonResponse { $this->authorizeServerAdmin($request, $server); $data = $request->validate([ 'user_id' => 'required|integer|exists:users,id', 'role_id' => 'required|integer|exists:addon_roles,id', ]); $assignment = $this->roleService->assignToUser( $server->id, $data['user_id'], $data['role_id'], $request->user()->id, ); return response()->json(['data' => $assignment], 201); } /** DELETE /api/client/servers/{server}/addons/roles/assign */ public function unassign(Request $request, Server $server): JsonResponse { $this->authorizeServerAdmin($request, $server); $data = $request->validate([ 'user_id' => 'required|integer|exists:users,id', 'role_id' => 'required|integer|exists:addon_roles,id', ]); $this->roleService->unassignFromUser( $server->id, $data['user_id'], $data['role_id'], $request->user()->id, ); return response()->json(['deleted' => true]); } /** GET /api/client/servers/{server}/addons/permissions/effective/{userId} */ public function effectivePermissions(Request $request, Server $server, string $targetUserId): JsonResponse { // Allow callers to pass "me" to resolve to their own user ID if ($targetUserId === 'me') { $targetUserId = (string) $request->user()?->id; } // Non-admins can only query their own permissions $user = $request->user(); $isAdmin = $user && ($user->root_admin || $server->owner_id === $user->id); if (!$isAdmin && (string) $user?->id !== $targetUserId) { abort(403, 'You may only query your own permissions.'); } // If target user is the owner, return an Owner role item if ((int) $targetUserId === $server->owner_id) { $ownerRole = [ 'role' => [ 'id' => 0, 'name' => 'Owner', 'color' => '#f59e0b', 'description' => 'Full server access — assigned to the server owner', 'permissions' => array_keys(RoleService::KNOWN_PERMISSIONS), 'created_at' => now()->toIso8601String(), ], 'source' => 'Server Owner', ]; return response()->json(['data' => [$ownerRole]]); } // Get user's assigned roles on this server $roles = $this->resolver->getUserRolesForServer((int) $targetUserId, $server->id); $data = []; foreach ($roles as $role) { $allowedPermissions = []; foreach ($role->permissions as $p) { if ($p->value === 'allow') { $allowedPermissions[] = $p->permission; } } $data[] = [ 'role' => [ 'id' => $role->id, 'name' => $role->name, 'color' => $role->color, 'description' => $role->description, 'permissions' => $allowedPermissions, 'created_at' => $role->created_at?->toIso8601String(), ], 'source' => 'Role Assignment', ]; } return response()->json(['data' => $data]); } /** PUT /api/client/servers/{server}/addons/permissions/override */ public function setOverride(Request $request, Server $server): JsonResponse { $this->authorizeServerAdmin($request, $server); $data = $request->validate([ 'user_id' => 'required|integer|exists:users,id', 'permission' => 'required|string|max:100', 'value' => 'required|in:allow,deny,unset', ]); $override = $this->roleService->setOverride( $server->id, $data['user_id'], $data['permission'], $data['value'], $request->user()->id, ); return response()->json(['data' => $override]); } private function authorizeServerAdmin(Request $request, Server $server): void { $user = $request->user(); abort_unless($user, 401); $isOwner = $server->owner_id === $user->id; $isAdmin = $user->root_admin; // Subusers with user.update can also manage roles on their server $isSubuserAdmin = false; if (!$isOwner && !$isAdmin) { $subuser = $server->subusers()->where('user_id', $user->id)->first(); $isSubuserAdmin = $subuser && in_array('user.update', $subuser->permissions ?? [], true); } abort_unless($isOwner || $isAdmin || $isSubuserAdmin, 403, 'Insufficient privileges.'); } }