Compare commits
5 Commits
3bb4b323e7
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| acdb9fd9c2 | |||
| 73a84d762f | |||
| f5f0eee857 | |||
| e6111e0a0e | |||
| 3830e54988 |
@@ -23,6 +23,11 @@ class AutocompleteController extends Controller
|
||||
{
|
||||
$this->requireAccess($request, $server);
|
||||
|
||||
// Pterodactyl's route model binding resolves by UUID; ensure we have the integer PK
|
||||
if ($server->id === null) {
|
||||
$server = Server::where('uuid', $server->uuid)->firstOrFail();
|
||||
}
|
||||
|
||||
$query = (string) $request->get('q', '');
|
||||
$suggestions = $this->engine->suggest(
|
||||
$server->id,
|
||||
|
||||
@@ -85,17 +85,62 @@ class ServerRoleController extends Controller
|
||||
}
|
||||
|
||||
/** GET /api/client/servers/{server}/addons/permissions/effective/{userId} */
|
||||
public function effectivePermissions(Request $request, Server $server, int $targetUserId): JsonResponse
|
||||
public function effectivePermissions(Request $request, Server $server, string $targetUserId): JsonResponse
|
||||
{
|
||||
$this->authorizeServerAdmin($request, $server);
|
||||
// Allow callers to pass "me" to resolve to their own user ID
|
||||
if ($targetUserId === 'me') {
|
||||
$targetUserId = (string) $request->user()?->id;
|
||||
}
|
||||
|
||||
$effective = $this->resolver->resolveAll(
|
||||
$targetUserId,
|
||||
$server->id,
|
||||
RoleService::KNOWN_PERMISSIONS
|
||||
);
|
||||
// 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.');
|
||||
}
|
||||
|
||||
return response()->json(['data' => $effective]);
|
||||
// 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 */
|
||||
|
||||
130
app/Addons/AdvancedAdmin/Models/CommandDefinition.php
Normal file
130
app/Addons/AdvancedAdmin/Models/CommandDefinition.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Addons\AdvancedAdmin\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class CommandDefinition extends Model
|
||||
{
|
||||
protected $table = 'addon_command_definitions';
|
||||
|
||||
protected $fillable = [
|
||||
'server_id',
|
||||
'node_id',
|
||||
'egg_id',
|
||||
'plugin_source',
|
||||
'command_name',
|
||||
'definition',
|
||||
'is_active',
|
||||
// Virtual/fillable fields for controller convenience
|
||||
'command',
|
||||
'description',
|
||||
'syntax',
|
||||
'dangerous',
|
||||
'plugin',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'definition' => 'array',
|
||||
'is_active' => 'boolean',
|
||||
'dangerous' => 'boolean',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'command',
|
||||
'description',
|
||||
'syntax',
|
||||
'dangerous',
|
||||
'plugin',
|
||||
];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
// Add global scope to alias command_name as command for ordering
|
||||
static::addGlobalScope('alias_command', function ($builder) {
|
||||
$builder->select('addon_command_definitions.*')
|
||||
->selectRaw('addon_command_definitions.command_name as command');
|
||||
});
|
||||
|
||||
// Sync helper fields to database columns on saving
|
||||
static::saving(function (CommandDefinition $model) {
|
||||
if ($model->plugin) {
|
||||
$model->plugin_source = $model->plugin;
|
||||
}
|
||||
|
||||
if ($model->command) {
|
||||
$model->command_name = $model->command;
|
||||
}
|
||||
|
||||
$def = $model->definition ?? [];
|
||||
$def['name'] = $model->command_name ?? $def['name'] ?? '';
|
||||
$def['description'] = $model->description ?? $def['description'] ?? '';
|
||||
$def['syntax'] = $model->syntax ?? $def['syntax'] ?? '';
|
||||
$def['dangerous'] = (bool) ($model->dangerous ?? $def['dangerous'] ?? false);
|
||||
$def['plugin'] = $model->plugin_source ?? $def['plugin'] ?? 'custom';
|
||||
$def['args'] = $def['args'] ?? [];
|
||||
|
||||
$model->definition = $def;
|
||||
});
|
||||
}
|
||||
|
||||
// Accessors and Mutators for virtual fields
|
||||
|
||||
public function getCommandAttribute()
|
||||
{
|
||||
return $this->command_name;
|
||||
}
|
||||
|
||||
public function setCommandAttribute($value)
|
||||
{
|
||||
$this->command_name = $value;
|
||||
$this->attributes['command_name'] = $value;
|
||||
}
|
||||
|
||||
public function getDescriptionAttribute()
|
||||
{
|
||||
return $this->definition['description'] ?? '';
|
||||
}
|
||||
|
||||
public function setDescriptionAttribute($value)
|
||||
{
|
||||
$def = $this->definition ?? [];
|
||||
$def['description'] = $value;
|
||||
$this->definition = $def;
|
||||
}
|
||||
|
||||
public function getSyntaxAttribute()
|
||||
{
|
||||
return $this->definition['syntax'] ?? '';
|
||||
}
|
||||
|
||||
public function setSyntaxAttribute($value)
|
||||
{
|
||||
$def = $this->definition ?? [];
|
||||
$def['syntax'] = $value;
|
||||
$this->definition = $def;
|
||||
}
|
||||
|
||||
public function getDangerousAttribute()
|
||||
{
|
||||
return (bool) ($this->definition['dangerous'] ?? false);
|
||||
}
|
||||
|
||||
public function setDangerousAttribute($value)
|
||||
{
|
||||
$def = $this->definition ?? [];
|
||||
$def['dangerous'] = (bool) $value;
|
||||
$this->definition = $def;
|
||||
}
|
||||
|
||||
public function getPluginAttribute()
|
||||
{
|
||||
return $this->plugin_source;
|
||||
}
|
||||
|
||||
public function setPluginAttribute($value)
|
||||
{
|
||||
$this->plugin_source = $value;
|
||||
$this->attributes['plugin_source'] = $value;
|
||||
}
|
||||
}
|
||||
25
app/Addons/AdvancedAdmin/Models/ConsolePlayerCache.php
Normal file
25
app/Addons/AdvancedAdmin/Models/ConsolePlayerCache.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Addons\AdvancedAdmin\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ConsolePlayerCache extends Model
|
||||
{
|
||||
protected $table = 'addon_console_player_cache';
|
||||
|
||||
protected $primaryKey = null;
|
||||
public $incrementing = false;
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = [
|
||||
'server_id',
|
||||
'player_name',
|
||||
'last_seen_at',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'server_id' => 'integer',
|
||||
'last_seen_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
@@ -103,7 +103,11 @@ class DefaultRolesSeeder extends Seeder
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->command) {
|
||||
$this->command->info("Created default role: {$roleData['name']}");
|
||||
} else {
|
||||
echo "Created default role: {$roleData['name']}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,12 @@ use Pterodactyl\Addons\AdvancedAdmin\Http\Controllers\Client\AutocompleteControl
|
||||
|
||||
Route::group([
|
||||
'prefix' => 'api/client/servers/{server}',
|
||||
'middleware' => ['api', 'auth:sanctum', 'addon.ratelimit'],
|
||||
'middleware' => [
|
||||
'api',
|
||||
'auth:sanctum',
|
||||
'addon.ratelimit',
|
||||
\Pterodactyl\Http\Middleware\Api\Client\SubstituteClientBindings::class,
|
||||
],
|
||||
], function () {
|
||||
|
||||
// ── Network Traffic ───────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user