add allocation locking

This commit is contained in:
Boy132 2025-10-14 09:00:11 +02:00
parent d735e858a2
commit d81294a5a0
7 changed files with 86 additions and 7 deletions

View File

@ -60,16 +60,35 @@ class AllocationsRelationManager extends RelationManager
->action(fn (Allocation $allocation) => $this->getOwnerRecord()->update(['allocation_id' => $allocation->id]) && $this->deselectAllTableRecords()) ->action(fn (Allocation $allocation) => $this->getOwnerRecord()->update(['allocation_id' => $allocation->id]) && $this->deselectAllTableRecords())
->default(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id) ->default(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id)
->label(trans('admin/server.primary')), ->label(trans('admin/server.primary')),
IconColumn::make('is_locked')
->label(trans('admin/server.locked'))
->tooltip(trans('admin/server.locked_helper'))
->trueIcon('tabler-lock')
->falseIcon('tabler-lock-open'),
]) ])
->recordActions([ ->recordActions([
Action::make('make-primary') Action::make('make-primary')
->label(trans('admin/server.make_primary')) ->label(trans('admin/server.make_primary'))
->action(fn (Allocation $allocation) => $this->getOwnerRecord()->update(['allocation_id' => $allocation->id]) && $this->deselectAllTableRecords()) ->action(fn (Allocation $allocation) => $this->getOwnerRecord()->update(['allocation_id' => $allocation->id]) && $this->deselectAllTableRecords())
->hidden(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id), ->hidden(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id),
Action::make('lock')
->label(trans('admin/server.lock'))
->action(fn (Allocation $allocation) => $allocation->update(['is_locked' => true]) && $this->deselectAllTableRecords())
->hidden(fn (Allocation $allocation) => $allocation->is_locked),
Action::make('unlock')
->label(trans('admin/server.unlock'))
->action(fn (Allocation $allocation) => $allocation->update(['is_locked' => false]) && $this->deselectAllTableRecords())
->visible(fn (Allocation $allocation) => $allocation->is_locked),
DissociateAction::make() DissociateAction::make()
->after(function (Allocation $allocation) { ->after(function (Allocation $allocation) {
$allocation->update(['notes' => null]); $allocation->update([
$this->getOwnerRecord()->allocation_id && $this->getOwnerRecord()->update(['allocation_id' => $this->getOwnerRecord()->allocations()->first()?->id]); 'notes' => null,
'is_locked' => false,
]);
if (!$this->getOwnerRecord()->allocation_id) {
$this->getOwnerRecord()->update(['allocation_id' => $this->getOwnerRecord()->allocations()->first()?->id]);
}
}), }),
]) ])
->headerActions([ ->headerActions([
@ -116,13 +135,25 @@ class AllocationsRelationManager extends RelationManager
->recordSelectOptionsQuery(fn ($query) => $query->whereBelongsTo($this->getOwnerRecord()->node)->whereNull('server_id')) ->recordSelectOptionsQuery(fn ($query) => $query->whereBelongsTo($this->getOwnerRecord()->node)->whereNull('server_id'))
->recordSelectSearchColumns(['ip', 'port']) ->recordSelectSearchColumns(['ip', 'port'])
->label(trans('admin/server.add_allocation')) ->label(trans('admin/server.add_allocation'))
->after(fn (array $data) => !$this->getOwnerRecord()->allocation_id && $this->getOwnerRecord()->update(['allocation_id' => $data['recordId'][0]])), ->after(function (array $data) {
Allocation::whereIn('id', array_values(array_unique($data['recordId'])))->update(['is_locked' => true]);
if (!$this->getOwnerRecord()->allocation_id) {
$this->getOwnerRecord()->update(['allocation_id' => $data['recordId'][0]]);
}
}),
]) ])
->groupedBulkActions([ ->groupedBulkActions([
DissociateBulkAction::make() DissociateBulkAction::make()
->after(function () { ->after(function () {
Allocation::whereNull('server_id')->update(['notes' => null]); Allocation::whereNull('server_id')->update([
$this->getOwnerRecord()->allocation_id && $this->getOwnerRecord()->update(['allocation_id' => $this->getOwnerRecord()->allocations()->first()?->id]); 'notes' => null,
'is_locked' => false,
]);
if (!$this->getOwnerRecord()->allocation_id) {
$this->getOwnerRecord()->update(['allocation_id' => $this->getOwnerRecord()->allocations()->first()?->id]);
}
}), }),
]); ]);
} }

View File

@ -73,15 +73,21 @@ class AllocationResource extends Resource
->action(fn (Allocation $allocation) => user()?->can(PERMISSION::ACTION_ALLOCATION_UPDATE, $server) && $server->update(['allocation_id' => $allocation->id])) ->action(fn (Allocation $allocation) => user()?->can(PERMISSION::ACTION_ALLOCATION_UPDATE, $server) && $server->update(['allocation_id' => $allocation->id]))
->default(fn (Allocation $allocation) => $allocation->id === $server->allocation_id) ->default(fn (Allocation $allocation) => $allocation->id === $server->allocation_id)
->label(trans('server/network.primary')), ->label(trans('server/network.primary')),
IconColumn::make('is_locked')
->label(trans('server/network.locked'))
->trueIcon('tabler-lock')
->falseIcon('tabler-lock-open'),
]) ])
->recordActions([ ->recordActions([
DetachAction::make() DetachAction::make()
->visible(fn (Allocation $allocation) => !$allocation->is_locked || user()?->can('update', $allocation->node))
->authorize(fn () => user()?->can(Permission::ACTION_ALLOCATION_DELETE, $server)) ->authorize(fn () => user()?->can(Permission::ACTION_ALLOCATION_DELETE, $server))
->label(trans('server/network.delete')) ->label(trans('server/network.delete'))
->icon('tabler-trash') ->icon('tabler-trash')
->action(function (Allocation $allocation) { ->action(function (Allocation $allocation) {
Allocation::query()->where('id', $allocation->id)->update([ Allocation::where('id', $allocation->id)->update([
'notes' => null, 'notes' => null,
'is_locked' => false,
'server_id' => null, 'server_id' => null,
]); ]);
@ -93,7 +99,7 @@ class AllocationResource extends Resource
->after(fn (Allocation $allocation) => $allocation->id === $server->allocation_id && $server->update(['allocation_id' => $server->allocations()->first()?->id])), ->after(fn (Allocation $allocation) => $allocation->id === $server->allocation_id && $server->update(['allocation_id' => $server->allocations()->first()?->id])),
]) ])
->toolbarActions([ ->toolbarActions([
Action::make('addAllocation') Action::make('add_allocation')
->hiddenLabel()->iconButton()->iconSize(IconSize::ExtraLarge) ->hiddenLabel()->iconButton()->iconSize(IconSize::ExtraLarge)
->icon(fn () => $server->allocations()->count() >= $server->allocation_limit ? 'tabler-network-off' : 'tabler-network') ->icon(fn () => $server->allocations()->count() >= $server->allocation_limit ? 'tabler-network-off' : 'tabler-network')
->authorize(fn () => user()?->can(Permission::ACTION_ALLOCATION_CREATE, $server)) ->authorize(fn () => user()?->can(Permission::ACTION_ALLOCATION_CREATE, $server))

View File

@ -29,6 +29,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
* @property string $address * @property string $address
* @property Server|null $server * @property Server|null $server
* @property Node $node * @property Node $node
* @property bool $is_locked
* *
* @method static AllocationFactory factory(...$parameters) * @method static AllocationFactory factory(...$parameters)
* @method static Builder|Allocation newModelQuery() * @method static Builder|Allocation newModelQuery()
@ -55,6 +56,10 @@ class Allocation extends Model
*/ */
public const RESOURCE_NAME = 'allocation'; public const RESOURCE_NAME = 'allocation';
protected $attributes = [
'is_locked' => false,
];
/** /**
* Fields that are not mass assignable. * Fields that are not mass assignable.
*/ */
@ -68,6 +73,7 @@ class Allocation extends Model
'ip_alias' => ['nullable', 'string'], 'ip_alias' => ['nullable', 'string'],
'server_id' => ['nullable', 'exists:servers,id'], 'server_id' => ['nullable', 'exists:servers,id'],
'notes' => ['nullable', 'string', 'max:256'], 'notes' => ['nullable', 'string', 'max:256'],
'is_locked' => ['boolean'],
]; ];
protected static function booted(): void protected static function booted(): void
@ -83,6 +89,7 @@ class Allocation extends Model
'node_id' => 'integer', 'node_id' => 'integer',
'port' => 'integer', 'port' => 'integer',
'server_id' => 'integer', 'server_id' => 'integer',
'is_locked' => 'bool',
]; ];
} }

View File

@ -191,6 +191,7 @@ class ServerCreationService
->get() ->get()
->each(function (Allocation $allocation) use ($server) { ->each(function (Allocation $allocation) use ($server) {
$allocation->server_id = $server->id; $allocation->server_id = $server->id;
$allocation->is_locked = true;
$allocation->save(); $allocation->save();
}); });
} }

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('allocations', function (Blueprint $table) {
$table->boolean('is_locked')->default(false);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('allocations', function (Blueprint $table) {
$table->dropColumn('is_locked');
});
}
};

View File

@ -13,6 +13,10 @@ return [
'ports' => 'Ports', 'ports' => 'Ports',
'alias' => 'Alias', 'alias' => 'Alias',
'alias_helper' => 'Optional display name to help you remember what these are.', 'alias_helper' => 'Optional display name to help you remember what these are.',
'locked' => 'Locked?',
'locked_helper' => 'Users won\'t be able to delete locked allocations',
'lock' => 'Lock',
'unlock' => 'Unlock',
'name' => 'Name', 'name' => 'Name',
'external_id' => 'External ID', 'external_id' => 'External ID',
'owner' => 'Owner', 'owner' => 'Owner',

View File

@ -12,4 +12,6 @@ return [
'primary' => 'Primary', 'primary' => 'Primary',
'make' => 'Make', 'make' => 'Make',
'delete' => 'Delete', 'delete' => 'Delete',
'locked' => 'Locked?',
'locked_helper' => 'Locked allocations can only be deleted by admins',
]; ];