mirror of
https://github.com/pelican-dev/panel.git
synced 2025-05-19 21:04:44 +02:00
Refactor api key permissions (#361)
* use RESOURCE_NAME for requests * use RESOURCE_NAME for transformers * add permissions field to api key * add migration for new permissions field * update tests * remove debug log * set column type to "json" * remove default attribute to fix tests * fix default value for permissions * fix after merge * fix after merge * allow to "register" custom permissions * add "role" to default resource names * fix after merge * fix phpstan * fix migrations
This commit is contained in:
parent
ac67656d82
commit
b3501be6ec
@ -11,6 +11,7 @@ use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\ToggleButtons;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class CreateApiKey extends CreateRecord
|
||||
{
|
||||
@ -41,7 +42,7 @@ class CreateApiKey extends CreateRecord
|
||||
'md' => 2,
|
||||
])
|
||||
->schema(
|
||||
collect(ApiKey::RESOURCES)->map(fn ($resource) => ToggleButtons::make("r_$resource")
|
||||
collect(ApiKey::getPermissionList())->map(fn ($resource) => ToggleButtons::make('permissions_' . $resource)
|
||||
->label(str($resource)->replace('_', ' ')->title())->inline()
|
||||
->options([
|
||||
0 => 'None',
|
||||
@ -87,4 +88,20 @@ class CreateApiKey extends CreateRecord
|
||||
->columnSpanFull(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function handleRecordCreation(array $data): Model
|
||||
{
|
||||
$permissions = [];
|
||||
|
||||
foreach (ApiKey::getPermissionList() as $permission) {
|
||||
if (isset($data['permissions_' . $permission])) {
|
||||
$permissions[$permission] = intval($data['permissions_' . $permission]);
|
||||
unset($data['permissions_' . $permission]);
|
||||
}
|
||||
}
|
||||
|
||||
$data['permissions'] = $permissions;
|
||||
|
||||
return parent::handleRecordCreation($data);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace App\Http\Requests\Admin\Api;
|
||||
|
||||
use App\Models\ApiKey;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Admin\AdminFormRequest;
|
||||
|
||||
class StoreApplicationApiKeyRequest extends AdminFormRequest
|
||||
@ -16,9 +15,12 @@ class StoreApplicationApiKeyRequest extends AdminFormRequest
|
||||
{
|
||||
$modelRules = ApiKey::getRules();
|
||||
|
||||
return collect(AdminAcl::getResourceList())->mapWithKeys(function ($resource) use ($modelRules) {
|
||||
return [AdminAcl::COLUMN_IDENTIFIER . $resource => $modelRules['r_' . $resource]];
|
||||
})->merge(['memo' => $modelRules['memo']])->toArray();
|
||||
$rules = [
|
||||
'memo' => $modelRules['memo'],
|
||||
'permissions' => $modelRules['permissions'],
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public function attributes(): array
|
||||
@ -30,8 +32,8 @@ class StoreApplicationApiKeyRequest extends AdminFormRequest
|
||||
|
||||
public function getKeyPermissions(): array
|
||||
{
|
||||
return collect($this->validated())->filter(function ($value, $key) {
|
||||
return substr($key, 0, strlen(AdminAcl::COLUMN_IDENTIFIER)) === AdminAcl::COLUMN_IDENTIFIER;
|
||||
})->toArray();
|
||||
$data = $this->validated();
|
||||
|
||||
return array_keys($data['permissions']);
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Allocations;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Allocation;
|
||||
|
||||
class DeleteAllocationRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_ALLOCATIONS;
|
||||
protected ?string $resource = Allocation::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Allocations;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Allocation;
|
||||
|
||||
class GetAllocationsRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_ALLOCATIONS;
|
||||
protected ?string $resource = Allocation::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Allocations;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Allocation;
|
||||
|
||||
class StoreAllocationRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_ALLOCATIONS;
|
||||
protected ?string $resource = Allocation::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\DatabaseHosts;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\DatabaseHost;
|
||||
|
||||
class DeleteDatabaseHostRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_DATABASE_HOSTS;
|
||||
protected ?string $resource = DatabaseHost::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\DatabaseHosts;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\DatabaseHost;
|
||||
|
||||
class GetDatabaseHostRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_DATABASE_HOSTS;
|
||||
protected ?string $resource = DatabaseHost::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
|
||||
class StoreDatabaseHostRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_DATABASE_HOSTS;
|
||||
protected ?string $resource = DatabaseHost::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Eggs;
|
||||
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Models\Egg;
|
||||
|
||||
class GetEggRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_EGGS;
|
||||
protected ?string $resource = Egg::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Eggs;
|
||||
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Models\Egg;
|
||||
|
||||
class GetEggsRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_EGGS;
|
||||
protected ?string $resource = Egg::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Mounts;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Mount;
|
||||
|
||||
class DeleteMountRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_MOUNTS;
|
||||
protected ?string $resource = Mount::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Mounts;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Mount;
|
||||
|
||||
class GetMountRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_MOUNTS;
|
||||
protected ?string $resource = Mount::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Mounts;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Mount;
|
||||
|
||||
class StoreMountRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_MOUNTS;
|
||||
protected ?string $resource = Mount::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Nodes;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Node;
|
||||
|
||||
class DeleteNodeRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_NODES;
|
||||
protected ?string $resource = Node::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Nodes;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Node;
|
||||
|
||||
class GetNodesRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_NODES;
|
||||
protected ?string $resource = Node::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
|
||||
class StoreNodeRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_NODES;
|
||||
protected ?string $resource = Node::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Roles;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Role;
|
||||
|
||||
class DeleteRoleRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_ROLES;
|
||||
protected ?string $resource = Role::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Roles;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Role;
|
||||
|
||||
class GetRoleRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_ROLES;
|
||||
protected ?string $resource = Role::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Roles;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Role;
|
||||
|
||||
class StoreRoleRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_ROLES;
|
||||
protected ?string $resource = Role::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Servers\Databases;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Database;
|
||||
|
||||
class GetServerDatabaseRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_SERVER_DATABASES;
|
||||
protected ?string $resource = Database::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Servers\Databases;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Database;
|
||||
|
||||
class GetServerDatabasesRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_SERVER_DATABASES;
|
||||
protected ?string $resource = Database::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -9,10 +9,11 @@ use Illuminate\Database\Query\Builder;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Services\Databases\DatabaseManagementService;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Database;
|
||||
|
||||
class StoreServerDatabaseRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_SERVER_DATABASES;
|
||||
protected ?string $resource = Database::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Servers;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Server;
|
||||
|
||||
class GetExternalServerRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_SERVERS;
|
||||
protected ?string $resource = Server::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Servers;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Server;
|
||||
|
||||
class GetServerRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_SERVERS;
|
||||
protected ?string $resource = Server::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Servers;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\Server;
|
||||
|
||||
class ServerWriteRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_SERVERS;
|
||||
protected ?string $resource = Server::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
|
||||
class StoreServerRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_SERVERS;
|
||||
protected ?string $resource = Server::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
|
||||
|
@ -8,7 +8,7 @@ use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
|
||||
class UpdateServerStartupRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_SERVERS;
|
||||
protected ?string $resource = Server::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Users;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\User;
|
||||
|
||||
class DeleteUserRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_USERS;
|
||||
protected ?string $resource = User::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Users;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\User;
|
||||
|
||||
class GetExternalUserRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_USERS;
|
||||
protected ?string $resource = User::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::READ;
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ namespace App\Http\Requests\Api\Application\Users;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl as Acl;
|
||||
use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
use App\Models\User;
|
||||
|
||||
class GetUsersRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = Acl::RESOURCE_USERS;
|
||||
protected ?string $resource = User::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = Acl::READ;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use App\Http\Requests\Api\Application\ApplicationApiRequest;
|
||||
|
||||
class StoreUserRequest extends ApplicationApiRequest
|
||||
{
|
||||
protected ?string $resource = AdminAcl::RESOURCE_USERS;
|
||||
protected ?string $resource = User::RESOURCE_NAME;
|
||||
|
||||
protected int $permission = AdminAcl::WRITE;
|
||||
|
||||
|
@ -43,7 +43,7 @@ class Allocation extends Model
|
||||
{
|
||||
/**
|
||||
* The resource name for this model when it is transformed into an
|
||||
* API representation using fractal.
|
||||
* API representation using fractal. Also used as name for api key permissions.
|
||||
*/
|
||||
public const RESOURCE_NAME = 'allocation';
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use Illuminate\Support\Str;
|
||||
use Webmozart\Assert\Assert;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
@ -15,20 +15,13 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
* @property int $key_type
|
||||
* @property string $identifier
|
||||
* @property string $token
|
||||
* @property array $permissions
|
||||
* @property array $allowed_ips
|
||||
* @property string|null $memo
|
||||
* @property \Illuminate\Support\Carbon|null $last_used_at
|
||||
* @property \Illuminate\Support\Carbon|null $expires_at
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property int $r_servers
|
||||
* @property int $r_nodes
|
||||
* @property int $r_allocations
|
||||
* @property int $r_users
|
||||
* @property int $r_eggs
|
||||
* @property int $r_database_hosts
|
||||
* @property int $r_server_databases
|
||||
* @property int $r_mounts
|
||||
* @property \App\Models\User $tokenable
|
||||
* @property \App\Models\User $user
|
||||
*
|
||||
@ -84,8 +77,6 @@ class ApiKey extends Model
|
||||
*/
|
||||
public const KEY_LENGTH = 32;
|
||||
|
||||
public const RESOURCES = ['servers', 'nodes', 'allocations', 'users', 'eggs', 'database_hosts', 'server_databases', 'mounts'];
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*/
|
||||
@ -99,18 +90,11 @@ class ApiKey extends Model
|
||||
'key_type',
|
||||
'identifier',
|
||||
'token',
|
||||
'permissions',
|
||||
'allowed_ips',
|
||||
'memo',
|
||||
'last_used_at',
|
||||
'expires_at',
|
||||
'r_' . AdminAcl::RESOURCE_USERS,
|
||||
'r_' . AdminAcl::RESOURCE_ALLOCATIONS,
|
||||
'r_' . AdminAcl::RESOURCE_DATABASE_HOSTS,
|
||||
'r_' . AdminAcl::RESOURCE_SERVER_DATABASES,
|
||||
'r_' . AdminAcl::RESOURCE_EGGS,
|
||||
'r_' . AdminAcl::RESOURCE_NODES,
|
||||
'r_' . AdminAcl::RESOURCE_SERVERS,
|
||||
'r_' . AdminAcl::RESOURCE_MOUNTS,
|
||||
];
|
||||
|
||||
/**
|
||||
@ -118,6 +102,7 @@ class ApiKey extends Model
|
||||
*/
|
||||
protected $attributes = [
|
||||
'allowed_ips' => '[]',
|
||||
'permissions' => '[]',
|
||||
];
|
||||
|
||||
/**
|
||||
@ -134,24 +119,19 @@ class ApiKey extends Model
|
||||
'key_type' => 'present|integer|min:0|max:2',
|
||||
'identifier' => 'required|string|size:16|unique:api_keys,identifier',
|
||||
'token' => 'required|string',
|
||||
'permissions' => 'array',
|
||||
'permissions.*' => 'integer|min:0|max:3',
|
||||
'memo' => 'required|nullable|string|max:500',
|
||||
'allowed_ips' => 'array',
|
||||
'allowed_ips.*' => 'string',
|
||||
'last_used_at' => 'nullable|date',
|
||||
'expires_at' => 'nullable|date',
|
||||
'r_' . AdminAcl::RESOURCE_USERS => 'integer|min:0|max:3',
|
||||
'r_' . AdminAcl::RESOURCE_ALLOCATIONS => 'integer|min:0|max:3',
|
||||
'r_' . AdminAcl::RESOURCE_DATABASE_HOSTS => 'integer|min:0|max:3',
|
||||
'r_' . AdminAcl::RESOURCE_SERVER_DATABASES => 'integer|min:0|max:3',
|
||||
'r_' . AdminAcl::RESOURCE_EGGS => 'integer|min:0|max:3',
|
||||
'r_' . AdminAcl::RESOURCE_NODES => 'integer|min:0|max:3',
|
||||
'r_' . AdminAcl::RESOURCE_SERVERS => 'integer|min:0|max:3',
|
||||
'r_' . AdminAcl::RESOURCE_MOUNTS => 'integer|min:0|max:3',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'permissions' => 'array',
|
||||
'allowed_ips' => 'array',
|
||||
'user_id' => 'int',
|
||||
'last_used_at' => 'datetime',
|
||||
@ -159,14 +139,6 @@ class ApiKey extends Model
|
||||
'token' => 'encrypted',
|
||||
self::CREATED_AT => 'datetime',
|
||||
self::UPDATED_AT => 'datetime',
|
||||
'r_' . AdminAcl::RESOURCE_USERS => 'int',
|
||||
'r_' . AdminAcl::RESOURCE_ALLOCATIONS => 'int',
|
||||
'r_' . AdminAcl::RESOURCE_DATABASE_HOSTS => 'int',
|
||||
'r_' . AdminAcl::RESOURCE_SERVER_DATABASES => 'int',
|
||||
'r_' . AdminAcl::RESOURCE_EGGS => 'int',
|
||||
'r_' . AdminAcl::RESOURCE_NODES => 'int',
|
||||
'r_' . AdminAcl::RESOURCE_SERVERS => 'int',
|
||||
'r_' . AdminAcl::RESOURCE_MOUNTS => 'int',
|
||||
];
|
||||
}
|
||||
|
||||
@ -188,6 +160,41 @@ class ApiKey extends Model
|
||||
return $this->user();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the permission for the given resource.
|
||||
*/
|
||||
public function getPermission(string $resource): int
|
||||
{
|
||||
return $this->permissions[$resource] ?? AdminAcl::NONE;
|
||||
}
|
||||
|
||||
public const DEFAULT_RESOURCE_NAMES = [
|
||||
Server::RESOURCE_NAME,
|
||||
Node::RESOURCE_NAME,
|
||||
Allocation::RESOURCE_NAME,
|
||||
User::RESOURCE_NAME,
|
||||
Egg::RESOURCE_NAME,
|
||||
DatabaseHost::RESOURCE_NAME,
|
||||
Database::RESOURCE_NAME,
|
||||
Mount::RESOURCE_NAME,
|
||||
Role::RESOURCE_NAME,
|
||||
];
|
||||
|
||||
private static array $customResourceNames = [];
|
||||
|
||||
public static function registerCustomResourceName(string $resourceName): void
|
||||
{
|
||||
$customResourceNames[] = $resourceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all possible permission keys.
|
||||
*/
|
||||
public static function getPermissionList(): array
|
||||
{
|
||||
return array_unique(array_merge(self::DEFAULT_RESOURCE_NAMES, self::$customResourceNames));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the model matching the provided token.
|
||||
*/
|
||||
|
@ -23,7 +23,7 @@ class Database extends Model
|
||||
{
|
||||
/**
|
||||
* The resource name for this model when it is transformed into an
|
||||
* API representation using fractal.
|
||||
* API representation using fractal. Also used as name for api key permissions.
|
||||
*/
|
||||
public const RESOURCE_NAME = 'server_database';
|
||||
|
||||
|
@ -21,7 +21,7 @@ class DatabaseHost extends Model
|
||||
{
|
||||
/**
|
||||
* The resource name for this model when it is transformed into an
|
||||
* API representation using fractal.
|
||||
* API representation using fractal. Also used as name for api key permissions.
|
||||
*/
|
||||
public const RESOURCE_NAME = 'database_host';
|
||||
|
||||
|
@ -51,7 +51,7 @@ class Egg extends Model
|
||||
{
|
||||
/**
|
||||
* The resource name for this model when it is transformed into an
|
||||
* API representation using fractal.
|
||||
* API representation using fractal. Also used as name for api key permissions.
|
||||
*/
|
||||
public const RESOURCE_NAME = 'egg';
|
||||
|
||||
|
@ -49,7 +49,7 @@ class Node extends Model
|
||||
|
||||
/**
|
||||
* The resource name for this model when it is transformed into an
|
||||
* API representation using fractal.
|
||||
* API representation using fractal. Also used as name for api key permissions.
|
||||
*/
|
||||
public const RESOURCE_NAME = 'node';
|
||||
|
||||
|
@ -124,7 +124,7 @@ class Server extends Model
|
||||
|
||||
/**
|
||||
* The resource name for this model when it is transformed into an
|
||||
* API representation using fractal.
|
||||
* API representation using fractal. Also used as name for api key permissions.
|
||||
*/
|
||||
public const RESOURCE_NAME = 'server';
|
||||
|
||||
|
@ -104,7 +104,7 @@ class User extends Model implements AuthenticatableContract, AuthorizableContrac
|
||||
|
||||
/**
|
||||
* The resource name for this model when it is transformed into an
|
||||
* API representation using fractal.
|
||||
* API representation using fractal. Also used as name for api key permissions.
|
||||
*/
|
||||
public const RESOURCE_NAME = 'user';
|
||||
|
||||
|
@ -6,12 +6,6 @@ use App\Models\ApiKey;
|
||||
|
||||
class AdminAcl
|
||||
{
|
||||
/**
|
||||
* Resource permission columns in the api_keys table begin
|
||||
* with this identifier.
|
||||
*/
|
||||
public const COLUMN_IDENTIFIER = 'r_';
|
||||
|
||||
/**
|
||||
* The different types of permissions available for API keys. This
|
||||
* implements a read/write/none permissions scheme for all endpoints.
|
||||
@ -22,28 +16,6 @@ class AdminAcl
|
||||
|
||||
public const WRITE = 2;
|
||||
|
||||
/**
|
||||
* Resources that are available on the API and can contain a permissions
|
||||
* set for each key. These are stored in the database as r_{resource}.
|
||||
*/
|
||||
public const RESOURCE_SERVERS = 'servers';
|
||||
|
||||
public const RESOURCE_NODES = 'nodes';
|
||||
|
||||
public const RESOURCE_ALLOCATIONS = 'allocations';
|
||||
|
||||
public const RESOURCE_USERS = 'users';
|
||||
|
||||
public const RESOURCE_EGGS = 'eggs';
|
||||
|
||||
public const RESOURCE_DATABASE_HOSTS = 'database_hosts';
|
||||
|
||||
public const RESOURCE_SERVER_DATABASES = 'server_databases';
|
||||
|
||||
public const RESOURCE_MOUNTS = 'mounts';
|
||||
|
||||
public const RESOURCE_ROLES = 'roles';
|
||||
|
||||
/**
|
||||
* Determine if an API key has permission to perform a specific read/write operation.
|
||||
*/
|
||||
@ -62,20 +34,14 @@ class AdminAcl
|
||||
*/
|
||||
public static function check(ApiKey $key, string $resource, int $action = self::READ): bool
|
||||
{
|
||||
return self::can(data_get($key, self::COLUMN_IDENTIFIER . $resource, self::NONE), $action);
|
||||
return self::can($key->getPermission($resource), $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all resource constants defined in this ACL.
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
* Returns a list of all possible permissions.
|
||||
*/
|
||||
public static function getResourceList(): array
|
||||
{
|
||||
$reflect = new \ReflectionClass(__CLASS__);
|
||||
|
||||
return collect($reflect->getConstants())->filter(function ($value, $key) {
|
||||
return substr($key, 0, 9) === 'RESOURCE_';
|
||||
})->values()->toArray();
|
||||
return ApiKey::getPermissionList();
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class KeyCreationService
|
||||
]);
|
||||
|
||||
if ($this->keyType === ApiKey::TYPE_APPLICATION) {
|
||||
$data = array_merge($data, $permissions);
|
||||
$data['permissions'] = array_merge($data['permissions'], $permissions);
|
||||
}
|
||||
|
||||
return ApiKey::query()->forceCreate($data);
|
||||
|
@ -4,6 +4,7 @@ namespace App\Services\Nodes;
|
||||
|
||||
use App\Models\ApiKey;
|
||||
use App\Models\Node;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Services\Api\KeyCreationService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@ -28,7 +29,7 @@ class NodeAutoDeployService
|
||||
/** @var ApiKey|null $key */
|
||||
$key = ApiKey::query()
|
||||
->where('key_type', ApiKey::TYPE_APPLICATION)
|
||||
->where('r_nodes', true)
|
||||
->whereJsonContains('permissions->' . Node::RESOURCE_NAME, AdminAcl::READ)
|
||||
->first();
|
||||
|
||||
// We couldn't find a key that exists for this user with only permission for
|
||||
@ -37,7 +38,7 @@ class NodeAutoDeployService
|
||||
$key = $this->keyCreationService->setKeyType(ApiKey::TYPE_APPLICATION)->handle([
|
||||
'memo' => 'Automatically generated node deployment key.',
|
||||
'user_id' => $request->user()->id,
|
||||
], ['r_nodes' => true]);
|
||||
], ['permissions' => [Node::RESOURCE_NAME => AdminAcl::READ]]);
|
||||
}
|
||||
|
||||
$token = $key->identifier . $key->token;
|
||||
|
@ -7,7 +7,6 @@ use App\Models\Server;
|
||||
use League\Fractal\Resource\Item;
|
||||
use App\Models\Allocation;
|
||||
use League\Fractal\Resource\NullResource;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
|
||||
class AllocationTransformer extends BaseTransformer
|
||||
{
|
||||
@ -46,7 +45,7 @@ class AllocationTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeNode(Allocation $allocation): Item|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_NODES)) {
|
||||
if (!$this->authorize(Node::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -64,7 +63,7 @@ class AllocationTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeServer(Allocation $allocation): Item|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_SERVERS) || !$allocation->server) {
|
||||
if (!$this->authorize(Server::RESOURCE_NAME) || !$allocation->server) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ use App\Models\DatabaseHost;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\NullResource;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
|
||||
class DatabaseHostTransformer extends BaseTransformer
|
||||
{
|
||||
@ -49,7 +48,7 @@ class DatabaseHostTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeDatabases(DatabaseHost $model): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_SERVER_DATABASES)) {
|
||||
if (!$this->authorize(Database::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -65,7 +64,7 @@ class DatabaseHostTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeNode(DatabaseHost $model): Item|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_NODES)) {
|
||||
if (!$this->authorize(Node::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ use App\Models\Server;
|
||||
use App\Models\EggVariable;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\NullResource;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
|
||||
class EggTransformer extends BaseTransformer
|
||||
{
|
||||
@ -83,7 +82,7 @@ class EggTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeServers(Egg $model): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_SERVERS)) {
|
||||
if (!$this->authorize(Server::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -99,7 +98,7 @@ class EggTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeVariables(Egg $model): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_EGGS)) {
|
||||
if (!$this->authorize(Egg::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,12 @@
|
||||
|
||||
namespace App\Transformers\Api\Application;
|
||||
|
||||
use App\Models\Egg;
|
||||
use App\Models\Mount;
|
||||
use App\Models\Node;
|
||||
use App\Models\Server;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\NullResource;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
|
||||
class MountTransformer extends BaseTransformer
|
||||
{
|
||||
@ -34,7 +36,7 @@ class MountTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeEggs(Mount $mount): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_EGGS)) {
|
||||
if (!$this->authorize(Egg::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -54,7 +56,7 @@ class MountTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeNodes(Mount $mount): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_NODES)) {
|
||||
if (!$this->authorize(Node::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -74,7 +76,7 @@ class MountTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeServers(Mount $mount): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_SERVERS)) {
|
||||
if (!$this->authorize(Server::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,10 @@
|
||||
namespace App\Transformers\Api\Application;
|
||||
|
||||
use App\Models\Node;
|
||||
use App\Models\Server;
|
||||
use App\Models\Allocation;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\NullResource;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
|
||||
class NodeTransformer extends BaseTransformer
|
||||
{
|
||||
@ -52,7 +53,7 @@ class NodeTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeAllocations(Node $node): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_ALLOCATIONS)) {
|
||||
if (!$this->authorize(Allocation::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -72,7 +73,7 @@ class NodeTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeServers(Node $node): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_SERVERS)) {
|
||||
if (!$this->authorize(Server::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ use App\Models\Database;
|
||||
use League\Fractal\Resource\Item;
|
||||
use App\Models\DatabaseHost;
|
||||
use League\Fractal\Resource\NullResource;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
|
||||
class ServerDatabaseTransformer extends BaseTransformer
|
||||
{
|
||||
@ -57,7 +56,7 @@ class ServerDatabaseTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeHost(Database $model): Item|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_DATABASE_HOSTS)) {
|
||||
if (!$this->authorize(DatabaseHost::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,14 @@
|
||||
namespace App\Transformers\Api\Application;
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Models\Node;
|
||||
use App\Models\User;
|
||||
use App\Models\Egg;
|
||||
use App\Models\Database;
|
||||
use App\Models\Allocation;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\NullResource;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Services\Servers\EnvironmentService;
|
||||
|
||||
class ServerTransformer extends BaseTransformer
|
||||
@ -97,7 +101,7 @@ class ServerTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeAllocations(Server $server): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_ALLOCATIONS)) {
|
||||
if (!$this->authorize(Allocation::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -113,7 +117,7 @@ class ServerTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeSubusers(Server $server): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_USERS)) {
|
||||
if (!$this->authorize(User::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -129,7 +133,7 @@ class ServerTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeUser(Server $server): Item|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_USERS)) {
|
||||
if (!$this->authorize(User::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -145,7 +149,7 @@ class ServerTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeEgg(Server $server): Item|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_EGGS)) {
|
||||
if (!$this->authorize(Egg::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -161,7 +165,7 @@ class ServerTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeVariables(Server $server): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_SERVERS)) {
|
||||
if (!$this->authorize(Server::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -177,7 +181,7 @@ class ServerTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeNode(Server $server): Item|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_NODES)) {
|
||||
if (!$this->authorize(Node::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -193,7 +197,7 @@ class ServerTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeDatabases(Server $server): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_SERVER_DATABASES)) {
|
||||
if (!$this->authorize(Database::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@ namespace App\Transformers\Api\Application;
|
||||
|
||||
use League\Fractal\Resource\Item;
|
||||
use App\Models\EggVariable;
|
||||
use App\Models\Egg;
|
||||
use League\Fractal\Resource\NullResource;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
|
||||
class ServerVariableTransformer extends BaseTransformer
|
||||
{
|
||||
@ -37,7 +37,7 @@ class ServerVariableTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeParent(EggVariable $variable): Item|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_EGGS)) {
|
||||
if (!$this->authorize(Egg::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,10 @@
|
||||
namespace App\Transformers\Api\Application;
|
||||
|
||||
use App\Models\Subuser;
|
||||
use App\Models\User;
|
||||
use App\Models\Server;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Resource\NullResource;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
|
||||
class SubuserTransformer extends BaseTransformer
|
||||
{
|
||||
@ -44,7 +45,7 @@ class SubuserTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeUser(Subuser $subuser): Item|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_USERS)) {
|
||||
if (!$this->authorize(User::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -60,7 +61,7 @@ class SubuserTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeServer(Subuser $subuser): Item|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_SERVERS)) {
|
||||
if (!$this->authorize(Server::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,9 @@ namespace App\Transformers\Api\Application;
|
||||
|
||||
use App\Models\Role;
|
||||
use App\Models\User;
|
||||
use App\Models\Server;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\NullResource;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
|
||||
class UserTransformer extends BaseTransformer
|
||||
{
|
||||
@ -55,7 +55,7 @@ class UserTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeServers(User $user): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_SERVERS)) {
|
||||
if (!$this->authorize(Server::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ class UserTransformer extends BaseTransformer
|
||||
*/
|
||||
public function includeRoles(User $user): Collection|NullResource
|
||||
{
|
||||
if (!$this->authorize(AdminAcl::RESOURCE_ROLES)) {
|
||||
if (!$this->authorize(Role::RESOURCE_NAME)) {
|
||||
return $this->null();
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ class ApiKeyFactory extends Factory
|
||||
'identifier' => ApiKey::generateTokenIdentifier(ApiKey::TYPE_APPLICATION),
|
||||
'token' => $token ?: $token = Str::random(ApiKey::KEY_LENGTH),
|
||||
'allowed_ips' => [],
|
||||
'permissions' => [],
|
||||
'memo' => 'Test Function Key',
|
||||
'created_at' => Carbon::now(),
|
||||
'updated_at' => Carbon::now(),
|
||||
|
@ -24,26 +24,26 @@ return new class extends Migration
|
||||
DB::transaction(function () {
|
||||
// api_keys_user_id_foreign
|
||||
DB::statement('ALTER TABLE api_keys RENAME TO _api_keys_old');
|
||||
DB::statement('CREATE TABLE api_keys
|
||||
("id" integer primary key autoincrement not null,
|
||||
"token" text not null,
|
||||
"allowed_ips" text not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"user_id" integer not null,
|
||||
"memo" text,
|
||||
"r_servers" integer not null default \'0\',
|
||||
"r_nodes" integer not null default \'0\',
|
||||
"r_allocations" integer not null default \'0\',
|
||||
"r_users" integer not null default \'0\',
|
||||
"r_eggs" integer not null default \'0\',
|
||||
"r_database_hosts" integer not null default \'0\',
|
||||
"r_server_databases" integer not null default \'0\',
|
||||
"identifier" varchar,
|
||||
"key_type" integer not null default \'0\',
|
||||
"last_used_at" datetime,
|
||||
DB::statement('CREATE TABLE api_keys
|
||||
("id" integer primary key autoincrement not null,
|
||||
"token" text not null,
|
||||
"allowed_ips" text not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"user_id" integer not null,
|
||||
"memo" text,
|
||||
"r_servers" integer not null default \'0\',
|
||||
"r_nodes" integer not null default \'0\',
|
||||
"r_allocations" integer not null default \'0\',
|
||||
"r_users" integer not null default \'0\',
|
||||
"r_eggs" integer not null default \'0\',
|
||||
"r_database_hosts" integer not null default \'0\',
|
||||
"r_server_databases" integer not null default \'0\',
|
||||
"identifier" varchar,
|
||||
"key_type" integer not null default \'0\',
|
||||
"last_used_at" datetime,
|
||||
"expires_at" datetime,
|
||||
"r_mounts" integer not null default \'0\',
|
||||
"r_mounts" integer not null default \'0\',
|
||||
foreign key("user_id") references "users"("id") on delete cascade)');
|
||||
DB::statement('INSERT INTO api_keys SELECT * FROM _api_keys_old');
|
||||
DB::statement('DROP TABLE _api_keys_old');
|
||||
@ -51,17 +51,17 @@ return new class extends Migration
|
||||
|
||||
// database_hosts_node_id_foreign
|
||||
DB::statement('ALTER TABLE database_hosts RENAME TO _database_hosts_old');
|
||||
DB::statement('CREATE TABLE database_hosts
|
||||
("id" integer primary key autoincrement not null,
|
||||
"name" varchar not null,
|
||||
"host" varchar not null,
|
||||
"port" integer not null,
|
||||
"username" varchar not null,
|
||||
"password" text not null,
|
||||
"max_databases" integer,
|
||||
"node_id" integer,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
DB::statement('CREATE TABLE database_hosts
|
||||
("id" integer primary key autoincrement not null,
|
||||
"name" varchar not null,
|
||||
"host" varchar not null,
|
||||
"port" integer not null,
|
||||
"username" varchar not null,
|
||||
"password" text not null,
|
||||
"max_databases" integer,
|
||||
"node_id" integer,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
foreign key("node_id") references "nodes"("id") on delete set null)');
|
||||
DB::statement('INSERT INTO database_hosts SELECT * FROM _database_hosts_old');
|
||||
DB::statement('DROP TABLE _database_hosts_old');
|
||||
@ -69,10 +69,10 @@ return new class extends Migration
|
||||
// mount_node_node_id_foreign
|
||||
// mount_node_mount_id_foreign
|
||||
DB::statement('ALTER TABLE mount_node RENAME TO _mount_node_old');
|
||||
DB::statement('CREATE TABLE mount_node
|
||||
("node_id" integer not null,
|
||||
"mount_id" integer not null,
|
||||
foreign key("node_id") references "nodes"("id") on delete cascade on update cascade,
|
||||
DB::statement('CREATE TABLE mount_node
|
||||
("node_id" integer not null,
|
||||
"mount_id" integer not null,
|
||||
foreign key("node_id") references "nodes"("id") on delete cascade on update cascade,
|
||||
foreign key("mount_id") references "mounts"("id") on delete cascade on update cascade)');
|
||||
DB::statement('INSERT INTO mount_node SELECT * FROM _mount_node_old');
|
||||
DB::statement('DROP TABLE _mount_node_old');
|
||||
@ -83,38 +83,38 @@ return new class extends Migration
|
||||
// servers_egg_id_foreign
|
||||
// servers_allocation_id_foreign
|
||||
DB::statement('ALTER TABLE servers RENAME TO _servers_old');
|
||||
DB::statement('CREATE TABLE servers
|
||||
("id" integer primary key autoincrement not null,
|
||||
"uuid" varchar not null,
|
||||
"uuid_short" varchar not null,
|
||||
"node_id" integer not null,
|
||||
"name" varchar not null,
|
||||
"owner_id" integer not null,
|
||||
"memory" integer not null,
|
||||
"swap" integer not null,
|
||||
"disk" integer not null,
|
||||
"io" integer not null,
|
||||
"cpu" integer not null,
|
||||
"egg_id" integer not null,
|
||||
"startup" text not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"allocation_id" integer not null,
|
||||
"image" varchar not null,
|
||||
"description" text not null,
|
||||
"skip_scripts" tinyint(1) not null default \'0\',
|
||||
"external_id" varchar,
|
||||
"database_limit" integer default \'0\',
|
||||
"allocation_limit" integer,
|
||||
"threads" varchar,
|
||||
"backup_limit" integer not null default \'0\',
|
||||
"status" varchar,
|
||||
"installed_at" datetime,
|
||||
"oom_killer" integer not null default \'0\',
|
||||
"docker_labels" text,
|
||||
foreign key("node_id") references "nodes"("id"),
|
||||
foreign key("owner_id") references "users"("id"),
|
||||
foreign key("egg_id") references "eggs"("id"),
|
||||
DB::statement('CREATE TABLE servers
|
||||
("id" integer primary key autoincrement not null,
|
||||
"uuid" varchar not null,
|
||||
"uuid_short" varchar not null,
|
||||
"node_id" integer not null,
|
||||
"name" varchar not null,
|
||||
"owner_id" integer not null,
|
||||
"memory" integer not null,
|
||||
"swap" integer not null,
|
||||
"disk" integer not null,
|
||||
"io" integer not null,
|
||||
"cpu" integer not null,
|
||||
"egg_id" integer not null,
|
||||
"startup" text not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"allocation_id" integer not null,
|
||||
"image" varchar not null,
|
||||
"description" text not null,
|
||||
"skip_scripts" tinyint(1) not null default \'0\',
|
||||
"external_id" varchar,
|
||||
"database_limit" integer default \'0\',
|
||||
"allocation_limit" integer,
|
||||
"threads" varchar,
|
||||
"backup_limit" integer not null default \'0\',
|
||||
"status" varchar,
|
||||
"installed_at" datetime,
|
||||
"oom_killer" integer not null default \'0\',
|
||||
"docker_labels" text,
|
||||
foreign key("node_id") references "nodes"("id"),
|
||||
foreign key("owner_id") references "users"("id"),
|
||||
foreign key("egg_id") references "eggs"("id"),
|
||||
foreign key("allocation_id") references "allocations"("id"))');
|
||||
DB::statement('INSERT INTO servers SELECT * FROM _servers_old');
|
||||
DB::statement('DROP TABLE _servers_old');
|
||||
@ -126,18 +126,18 @@ return new class extends Migration
|
||||
// databases_server_id_foreign
|
||||
// databases_database_host_id_foreign
|
||||
DB::statement('ALTER TABLE databases RENAME TO _databases_old');
|
||||
DB::statement('CREATE TABLE databases
|
||||
("id" integer primary key autoincrement not null,
|
||||
"server_id" integer not null,
|
||||
"database_host_id" integer not null,
|
||||
"database" varchar not null,
|
||||
"username" varchar not null,
|
||||
"remote" varchar not null default \'%\',
|
||||
"password" text not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"max_connections" integer default \'0\',
|
||||
foreign key("server_id") references "servers"("id"),
|
||||
DB::statement('CREATE TABLE databases
|
||||
("id" integer primary key autoincrement not null,
|
||||
"server_id" integer not null,
|
||||
"database_host_id" integer not null,
|
||||
"database" varchar not null,
|
||||
"username" varchar not null,
|
||||
"remote" varchar not null default \'%\',
|
||||
"password" text not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"max_connections" integer default \'0\',
|
||||
foreign key("server_id") references "servers"("id"),
|
||||
foreign key("database_host_id") references "database_hosts"("id"))');
|
||||
DB::statement('INSERT INTO databases SELECT * FROM _databases_old');
|
||||
DB::statement('DROP TABLE _databases_old');
|
||||
@ -147,16 +147,16 @@ return new class extends Migration
|
||||
// allocations_node_id_foreign
|
||||
// allocations_server_id_foreign
|
||||
DB::statement('ALTER TABLE allocations RENAME TO _allocations_old');
|
||||
DB::statement('CREATE TABLE allocations
|
||||
("id" integer primary key autoincrement not null,
|
||||
"node_id" integer not null,
|
||||
"ip" varchar not null,
|
||||
"port" integer not null,
|
||||
"server_id" integer,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"ip_alias" text,
|
||||
"notes" varchar,
|
||||
DB::statement('CREATE TABLE allocations
|
||||
("id" integer primary key autoincrement not null,
|
||||
"node_id" integer not null,
|
||||
"ip" varchar not null,
|
||||
"port" integer not null,
|
||||
"server_id" integer,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"ip_alias" text,
|
||||
"notes" varchar,
|
||||
foreign key("node_id") references "nodes"("id") on delete cascade,
|
||||
foreign key("server_id") references "servers"("id") on delete cascade on update set null)');
|
||||
DB::statement('INSERT INTO allocations SELECT * FROM _allocations_old');
|
||||
@ -166,32 +166,32 @@ return new class extends Migration
|
||||
// eggs_config_from_foreign
|
||||
// eggs_copy_script_from_foreign
|
||||
DB::statement('ALTER TABLE eggs RENAME TO _eggs_old');
|
||||
DB::statement('CREATE TABLE eggs
|
||||
("id" integer primary key autoincrement not null,
|
||||
"name" varchar not null,
|
||||
"description" text,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"startup" text,
|
||||
"config_from" integer,
|
||||
"config_stop" varchar,
|
||||
"config_logs" text,
|
||||
"config_startup" text,
|
||||
"config_files" text,
|
||||
"script_install" text,
|
||||
"script_is_privileged" tinyint(1) not null default \'1\',
|
||||
"script_entry" varchar not null default \'ash\',
|
||||
"script_container" varchar not null default \'alpine:3.4\',
|
||||
"copy_script_from" integer,
|
||||
"uuid" varchar not null,
|
||||
"author" varchar not null,
|
||||
"features" text,
|
||||
"docker_images" text,
|
||||
"update_url" text,
|
||||
"file_denylist" text,
|
||||
"force_outgoing_ip" tinyint(1) not null default \'0\',
|
||||
"tags" text not null,
|
||||
foreign key("config_from") references "eggs"("id") on delete set null,
|
||||
DB::statement('CREATE TABLE eggs
|
||||
("id" integer primary key autoincrement not null,
|
||||
"name" varchar not null,
|
||||
"description" text,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"startup" text,
|
||||
"config_from" integer,
|
||||
"config_stop" varchar,
|
||||
"config_logs" text,
|
||||
"config_startup" text,
|
||||
"config_files" text,
|
||||
"script_install" text,
|
||||
"script_is_privileged" tinyint(1) not null default \'1\',
|
||||
"script_entry" varchar not null default \'ash\',
|
||||
"script_container" varchar not null default \'alpine:3.4\',
|
||||
"copy_script_from" integer,
|
||||
"uuid" varchar not null,
|
||||
"author" varchar not null,
|
||||
"features" text,
|
||||
"docker_images" text,
|
||||
"update_url" text,
|
||||
"file_denylist" text,
|
||||
"force_outgoing_ip" tinyint(1) not null default \'0\',
|
||||
"tags" text not null,
|
||||
foreign key("config_from") references "eggs"("id") on delete set null,
|
||||
foreign key("copy_script_from") references "eggs"("id") on delete set null)');
|
||||
DB::statement('INSERT INTO eggs SELECT * FROM _eggs_old');
|
||||
DB::statement('DROP TABLE _eggs_old');
|
||||
@ -200,10 +200,10 @@ return new class extends Migration
|
||||
// egg_mount_mount_id_foreign
|
||||
// egg_mount_egg_id_foreign
|
||||
DB::statement('ALTER TABLE egg_mount RENAME TO _egg_mount_old');
|
||||
DB::statement('CREATE TABLE egg_mount
|
||||
("egg_id" integer not null,
|
||||
"mount_id" integer not null,
|
||||
foreign key("egg_id") references "eggs"("id") on delete cascade on update cascade,
|
||||
DB::statement('CREATE TABLE egg_mount
|
||||
("egg_id" integer not null,
|
||||
"mount_id" integer not null,
|
||||
foreign key("egg_id") references "eggs"("id") on delete cascade on update cascade,
|
||||
foreign key("mount_id") references "mounts"("id") on delete cascade on update cascade)');
|
||||
DB::statement('INSERT INTO egg_mount SELECT * FROM _egg_mount_old');
|
||||
DB::statement('DROP TABLE _egg_mount_old');
|
||||
@ -211,19 +211,19 @@ return new class extends Migration
|
||||
|
||||
// service_variables_egg_id_foreign
|
||||
DB::statement('ALTER TABLE egg_variables RENAME TO _egg_variables_old');
|
||||
DB::statement('CREATE TABLE egg_variables
|
||||
("id" integer primary key autoincrement not null,
|
||||
"egg_id" integer not null,
|
||||
"name" varchar not null,
|
||||
"description" text not null,
|
||||
"env_variable" varchar not null,
|
||||
"default_value" text not null,
|
||||
"user_viewable" integer not null,
|
||||
"user_editable" integer not null,
|
||||
"rules" text not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"sort" integer,
|
||||
DB::statement('CREATE TABLE egg_variables
|
||||
("id" integer primary key autoincrement not null,
|
||||
"egg_id" integer not null,
|
||||
"name" varchar not null,
|
||||
"description" text not null,
|
||||
"env_variable" varchar not null,
|
||||
"default_value" text not null,
|
||||
"user_viewable" integer not null,
|
||||
"user_editable" integer not null,
|
||||
"rules" text not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"sort" integer,
|
||||
foreign key("egg_id") references "eggs"("id") on delete cascade)');
|
||||
DB::statement('INSERT INTO egg_variables SELECT * FROM _egg_variables_old');
|
||||
DB::statement('DROP TABLE _egg_variables_old');
|
||||
@ -231,10 +231,10 @@ return new class extends Migration
|
||||
// mount_server_server_id_foreign
|
||||
// mount_server_mount_id_foreign
|
||||
DB::statement('ALTER TABLE mount_server RENAME TO _mount_server_old');
|
||||
DB::statement('CREATE TABLE mount_server
|
||||
("server_id" integer not null,
|
||||
"mount_id" integer not null,
|
||||
foreign key("server_id") references "servers"("id") on delete cascade on update cascade,
|
||||
DB::statement('CREATE TABLE mount_server
|
||||
("server_id" integer not null,
|
||||
"mount_id" integer not null,
|
||||
foreign key("server_id") references "servers"("id") on delete cascade on update cascade,
|
||||
foreign key("mount_id") references "mounts"("id") on delete cascade on update cascade)');
|
||||
DB::statement('INSERT INTO mount_server SELECT * FROM _mount_server_old');
|
||||
DB::statement('DROP TABLE _mount_server_old');
|
||||
@ -242,14 +242,14 @@ return new class extends Migration
|
||||
|
||||
// server_variables_variable_id_foreign
|
||||
DB::statement('ALTER TABLE server_variables RENAME TO _server_variables_old');
|
||||
DB::statement('CREATE TABLE server_variables
|
||||
("id" integer primary key autoincrement not null,
|
||||
"server_id" integer not null,
|
||||
"variable_id" integer not null,
|
||||
"variable_value" text not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
foreign key("server_id") references "servers"("id") on delete cascade,
|
||||
DB::statement('CREATE TABLE server_variables
|
||||
("id" integer primary key autoincrement not null,
|
||||
"server_id" integer not null,
|
||||
"variable_id" integer not null,
|
||||
"variable_value" text not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
foreign key("server_id") references "servers"("id") on delete cascade,
|
||||
foreign key("variable_id") references "egg_variables"("id") on delete cascade)');
|
||||
DB::statement('INSERT INTO server_variables SELECT * FROM _server_variables_old');
|
||||
DB::statement('DROP TABLE _server_variables_old');
|
||||
@ -257,14 +257,14 @@ return new class extends Migration
|
||||
// subusers_user_id_foreign
|
||||
// subusers_server_id_foreign
|
||||
DB::statement('ALTER TABLE subusers RENAME TO _subusers_old');
|
||||
DB::statement('CREATE TABLE subusers
|
||||
("id" integer primary key autoincrement not null,
|
||||
"user_id" integer not null,
|
||||
"server_id" integer not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"permissions" text,
|
||||
foreign key("user_id") references "users"("id") on delete cascade,
|
||||
DB::statement('CREATE TABLE subusers
|
||||
("id" integer primary key autoincrement not null,
|
||||
"user_id" integer not null,
|
||||
"server_id" integer not null,
|
||||
"created_at" datetime,
|
||||
"updated_at" datetime,
|
||||
"permissions" text,
|
||||
foreign key("user_id") references "users"("id") on delete cascade,
|
||||
foreign key("server_id") references "servers"("id") on delete cascade)');
|
||||
DB::statement('INSERT INTO subusers SELECT * FROM _subusers_old');
|
||||
DB::statement('DROP TABLE _subusers_old');
|
||||
|
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Allocation;
|
||||
use App\Models\ApiKey;
|
||||
use App\Models\Database;
|
||||
use App\Models\DatabaseHost;
|
||||
use App\Models\Egg;
|
||||
use App\Models\Mount;
|
||||
use App\Models\Node;
|
||||
use App\Models\Server;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('api_keys', function (Blueprint $table) {
|
||||
$table->json('permissions');
|
||||
});
|
||||
|
||||
foreach (ApiKey::query() as $apiKey) {
|
||||
$permissions = [
|
||||
Server::RESOURCE_NAME => intval($apiKey->r_servers ?? 0),
|
||||
Node::RESOURCE_NAME => intval($apiKey->r_nodes ?? 0),
|
||||
Allocation::RESOURCE_NAME => intval($apiKey->r_allocations ?? 0),
|
||||
User::RESOURCE_NAME => intval($apiKey->r_users ?? 0),
|
||||
Egg::RESOURCE_NAME => intval($apiKey->r_eggs ?? 0),
|
||||
DatabaseHost::RESOURCE_NAME => intval($apiKey->r_database_hosts ?? 0),
|
||||
Database::RESOURCE_NAME => intval($apiKey->r_server_databases ?? 0),
|
||||
Mount::RESOURCE_NAME => intval($apiKey->r_mounts ?? 0),
|
||||
];
|
||||
|
||||
DB::table('api_keys')
|
||||
->where('id', $apiKey->id)
|
||||
->update(['permissions' => $permissions]);
|
||||
}
|
||||
|
||||
Schema::table('api_keys', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'r_servers',
|
||||
'r_nodes',
|
||||
'r_allocations',
|
||||
'r_users',
|
||||
'r_eggs',
|
||||
'r_database_hosts',
|
||||
'r_server_databases',
|
||||
'r_mounts',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('api_keys', function (Blueprint $table) {
|
||||
$table->unsignedTinyInteger('r_servers')->default(0);
|
||||
$table->unsignedTinyInteger('r_nodes')->default(0);
|
||||
$table->unsignedTinyInteger('r_allocations')->default(0);
|
||||
$table->unsignedTinyInteger('r_users')->default(0);
|
||||
$table->unsignedTinyInteger('r_eggs')->default(0);
|
||||
$table->unsignedTinyInteger('r_database_hosts')->default(0);
|
||||
$table->unsignedTinyInteger('r_server_databases')->default(0);
|
||||
$table->unsignedTinyInteger('r_mounts')->default(0);
|
||||
});
|
||||
|
||||
foreach (ApiKey::query() as $apiKey) {
|
||||
DB::table('api_keys')
|
||||
->where('id', $apiKey->id)
|
||||
->update([
|
||||
'r_servers' => $apiKey->permissions[Server::RESOURCE_NAME],
|
||||
'r_nodes' => $apiKey->permissions[Node::RESOURCE_NAME],
|
||||
'r_allocations' => $apiKey->permissions[Allocation::RESOURCE_NAME],
|
||||
'r_users' => $apiKey->permissions[User::RESOURCE_NAME],
|
||||
'r_eggs' => $apiKey->permissions[Egg::RESOURCE_NAME],
|
||||
'r_database_hosts' => $apiKey->permissions[DatabaseHost::RESOURCE_NAME],
|
||||
'r_server_databases' => $apiKey->permissions[Database::RESOURCE_NAME],
|
||||
'r_mounts' => $apiKey->permissions[Mount::RESOURCE_NAME],
|
||||
]);
|
||||
}
|
||||
|
||||
Schema::table('api_keys', function (Blueprint $table) {
|
||||
$table->dropColumn('permissions');
|
||||
});
|
||||
}
|
||||
};
|
@ -2,10 +2,17 @@
|
||||
|
||||
namespace App\Tests\Integration\Api\Application;
|
||||
|
||||
use App\Models\Allocation;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\User;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use App\Models\ApiKey;
|
||||
use App\Models\Database;
|
||||
use App\Models\DatabaseHost;
|
||||
use App\Models\Egg;
|
||||
use App\Models\Mount;
|
||||
use App\Models\Node;
|
||||
use App\Models\Server;
|
||||
use App\Models\Role;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Tests\Integration\IntegrationTestCase;
|
||||
@ -79,18 +86,21 @@ abstract class ApplicationApiIntegrationTestCase extends IntegrationTestCase
|
||||
*/
|
||||
protected function createApiKey(User $user, array $permissions = []): ApiKey
|
||||
{
|
||||
return ApiKey::factory()->create(array_merge([
|
||||
return ApiKey::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'key_type' => ApiKey::TYPE_APPLICATION,
|
||||
'r_servers' => AdminAcl::READ | AdminAcl::WRITE,
|
||||
'r_nodes' => AdminAcl::READ | AdminAcl::WRITE,
|
||||
'r_allocations' => AdminAcl::READ | AdminAcl::WRITE,
|
||||
'r_users' => AdminAcl::READ | AdminAcl::WRITE,
|
||||
'r_eggs' => AdminAcl::READ | AdminAcl::WRITE,
|
||||
'r_database_hosts' => AdminAcl::READ | AdminAcl::WRITE,
|
||||
'r_server_databases' => AdminAcl::READ | AdminAcl::WRITE,
|
||||
'r_mounts' => AdminAcl::READ | AdminAcl::WRITE,
|
||||
], $permissions));
|
||||
'permissions' => array_merge([
|
||||
Server::RESOURCE_NAME => AdminAcl::READ | AdminAcl::WRITE,
|
||||
Node::RESOURCE_NAME => AdminAcl::READ | AdminAcl::WRITE,
|
||||
Allocation::RESOURCE_NAME => AdminAcl::READ | AdminAcl::WRITE,
|
||||
User::RESOURCE_NAME => AdminAcl::READ | AdminAcl::WRITE,
|
||||
Egg::RESOURCE_NAME => AdminAcl::READ | AdminAcl::WRITE,
|
||||
DatabaseHost::RESOURCE_NAME => AdminAcl::READ | AdminAcl::WRITE,
|
||||
Database::RESOURCE_NAME => AdminAcl::READ | AdminAcl::WRITE,
|
||||
Mount::RESOURCE_NAME => AdminAcl::READ | AdminAcl::WRITE,
|
||||
Role::RESOURCE_NAME => AdminAcl::READ | AdminAcl::WRITE,
|
||||
], $permissions),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Tests\Integration\Api\Application;
|
||||
|
||||
use App\Models\Egg;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Transformers\Api\Application\EggTransformer;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Arr;
|
||||
@ -111,7 +112,7 @@ class EggControllerTest extends ApplicationApiIntegrationTestCase
|
||||
public function testErrorReturnedIfNoPermission(): void
|
||||
{
|
||||
$egg = Egg::query()->findOrFail(1);
|
||||
$this->createNewDefaultApiKey($this->getApiUser(), ['r_eggs' => 0]);
|
||||
$this->createNewDefaultApiKey($this->getApiUser(), [Egg::RESOURCE_NAME => AdminAcl::NONE]);
|
||||
|
||||
$response = $this->getJson('/api/application/eggs');
|
||||
$this->assertAccessDeniedJson($response);
|
||||
|
@ -4,6 +4,7 @@ namespace App\Tests\Integration\Api\Application\Users;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use App\Models\User;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Tests\Integration\Api\Application\ApplicationApiIntegrationTestCase;
|
||||
|
||||
@ -62,7 +63,7 @@ class ExternalUserControllerTest extends ApplicationApiIntegrationTestCase
|
||||
public function testErrorReturnedIfNoPermission(): void
|
||||
{
|
||||
$user = User::factory()->create(['external_id' => Str::random()]);
|
||||
$this->createNewDefaultApiKey($this->getApiUser(), ['r_users' => 0]);
|
||||
$this->createNewDefaultApiKey($this->getApiUser(), [User::RESOURCE_NAME => AdminAcl::NONE]);
|
||||
|
||||
$response = $this->getJson('/api/application/users/external/' . $user->external_id);
|
||||
$this->assertAccessDeniedJson($response);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Tests\Integration\Api\Application\Users;
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
@ -152,7 +153,7 @@ class UserControllerTest extends ApplicationApiIntegrationTestCase
|
||||
*/
|
||||
public function testKeyWithoutPermissionCannotLoadRelationship(): void
|
||||
{
|
||||
$this->createNewDefaultApiKey($this->getApiUser(), ['r_servers' => 0]);
|
||||
$this->createNewDefaultApiKey($this->getApiUser(), [Server::RESOURCE_NAME => AdminAcl::NONE]);
|
||||
|
||||
$user = User::factory()->create();
|
||||
$this->createServerModel(['user_id' => $user->id]);
|
||||
@ -197,7 +198,7 @@ class UserControllerTest extends ApplicationApiIntegrationTestCase
|
||||
public function testErrorReturnedIfNoPermission(): void
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->createNewDefaultApiKey($this->getApiUser(), ['r_users' => 0]);
|
||||
$this->createNewDefaultApiKey($this->getApiUser(), [User::RESOURCE_NAME => AdminAcl::NONE]);
|
||||
|
||||
$response = $this->getJson('/api/application/users/' . $user->id);
|
||||
$this->assertAccessDeniedJson($response);
|
||||
@ -286,7 +287,7 @@ class UserControllerTest extends ApplicationApiIntegrationTestCase
|
||||
*/
|
||||
public function testApiKeyWithoutWritePermissions(string $method, string $url): void
|
||||
{
|
||||
$this->createNewDefaultApiKey($this->getApiUser(), ['r_users' => AdminAcl::READ]);
|
||||
$this->createNewDefaultApiKey($this->getApiUser(), [User::RESOURCE_NAME => AdminAcl::READ]);
|
||||
|
||||
if (str_contains($url, '{id}')) {
|
||||
$user = User::factory()->create();
|
||||
|
@ -5,6 +5,7 @@ namespace App\Tests\Unit\Services\Acl\Api;
|
||||
use App\Models\ApiKey;
|
||||
use App\Tests\TestCase;
|
||||
use App\Services\Acl\Api\AdminAcl;
|
||||
use App\Models\Server;
|
||||
|
||||
class AdminAclTest extends TestCase
|
||||
{
|
||||
@ -23,9 +24,11 @@ class AdminAclTest extends TestCase
|
||||
*/
|
||||
public function testCheck(): void
|
||||
{
|
||||
$model = ApiKey::factory()->make(['r_servers' => AdminAcl::READ | AdminAcl::WRITE]);
|
||||
$model = ApiKey::factory()->make(['permissions' => [
|
||||
Server::RESOURCE_NAME => AdminAcl::READ | AdminAcl::WRITE,
|
||||
]]);
|
||||
|
||||
$this->assertTrue(AdminAcl::check($model, AdminAcl::RESOURCE_SERVERS, AdminAcl::WRITE));
|
||||
$this->assertTrue(AdminAcl::check($model, Server::RESOURCE_NAME, AdminAcl::WRITE));
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user