diff --git a/app/Data/Role/AssignAppsToRoleData.php b/app/Data/Role/AssignAppsToRoleData.php index 9ac735c..32f0b22 100644 --- a/app/Data/Role/AssignAppsToRoleData.php +++ b/app/Data/Role/AssignAppsToRoleData.php @@ -10,7 +10,7 @@ final class AssignAppsToRoleData extends Data { public function __construct( public int $roleId, - public int $duration, + public string $validUpto, /** @var int[] */ public array $appIds ) {} diff --git a/app/Data/Role/RoleAppData.php b/app/Data/Role/RoleAppData.php index 3158bc3..2e76aa0 100644 --- a/app/Data/Role/RoleAppData.php +++ b/app/Data/Role/RoleAppData.php @@ -13,7 +13,7 @@ public function __construct( public int $id, public int $appId, public string $appName, - public int $duration, + public string $duration, ) {} /** diff --git a/app/Livewire/Forms/AssignAppToRoleForm.php b/app/Livewire/Forms/AssignAppToRoleForm.php index a2403c2..b1a20e1 100644 --- a/app/Livewire/Forms/AssignAppToRoleForm.php +++ b/app/Livewire/Forms/AssignAppToRoleForm.php @@ -15,13 +15,15 @@ class AssignAppToRoleForm extends Form ])] public array $appIds = []; - #[Validate('required|integer|min:1|max:3650')] - public int $duration = 30; + #[Validate('exclude_if:isUnlimited,true|required|date|after_or_equal:today')] + public ?string $validUpto = null; + + public bool $isUnlimited = false; public function reset(mixed ...$properties): void { $this->resetErrorBag(); parent::reset(...$properties); - $this->duration = 30; + $this->validUpto = null; } } diff --git a/app/Models/AppRole.php b/app/Models/AppRole.php index 4c2708e..a0f5368 100644 --- a/app/Models/AppRole.php +++ b/app/Models/AppRole.php @@ -12,7 +12,7 @@ * @property int $id * @property int $app_id * @property int $role_id - * @property int $duration Duration in days. + * @property string $duration Validity of the role */ #[Fillable(['app_id', 'role_id', 'duration'])] class AppRole extends Pivot diff --git a/app/Services/AppRoleService.php b/app/Services/AppRoleService.php index 2be1084..0571e22 100644 --- a/app/Services/AppRoleService.php +++ b/app/Services/AppRoleService.php @@ -30,22 +30,23 @@ public function assign(AssignAppsToRoleData $data): void if (empty($data->appIds)) { return; } - $role = Role::query()->findOrFail($data->roleId); + DB::transaction(function () use ($data): void { + $role = Role::query()->findOrFail($data->roleId); - $this->assignAppPermissionsRole($role, $data->appIds); + $this->assignAppPermissionsRole($role, $data->appIds); - $records = array_map(fn (int $appId) => [ - 'role_id' => $data->roleId, - 'app_id' => $appId, - 'duration' => $data->duration, - ], $data->appIds); - - AppRole::query()->upsert( - $records, - ['role_id', 'app_id'], - ['duration'] - ); + $records = array_map(fn (int $appId) => [ + 'role_id' => $data->roleId, + 'app_id' => $appId, + 'duration' => $data->validUpto, + ], $data->appIds); + AppRole::query()->upsert( + $records, + ['role_id', 'app_id'], + ['duration'] + ); + }); } /** diff --git a/database/migrations/2026_05_18_113635_app_roles.php b/database/migrations/2026_05_18_113635_app_roles.php index 26245c0..e694e2a 100644 --- a/database/migrations/2026_05_18_113635_app_roles.php +++ b/database/migrations/2026_05_18_113635_app_roles.php @@ -18,7 +18,7 @@ public function up(): void $table->id(); $table->foreignIdFor(ConnectedApp::class, 'app_id'); $table->foreignId('role_id')->comment('role_id from spatie roles table'); - $table->integer('duration')->comment('in days'); + $table->dateTime('duration'); $table->unique(['app_id', 'role_id']); }); } diff --git a/resources/views/pages/access-manager/roles-and-apps/⚡index.blade.php b/resources/views/pages/access-manager/roles-and-apps/⚡index.blade.php index f0ea531..86fe8ce 100644 --- a/resources/views/pages/access-manager/roles-and-apps/⚡index.blade.php +++ b/resources/views/pages/access-manager/roles-and-apps/⚡index.blade.php @@ -81,13 +81,11 @@ public function save(): void $this->attempt( action: function (): void { $role = $this->roleService->create(new CreateRoleData(name: $this->form->name)); - $this->appRoleService->assign( - new AssignAppsToRoleData( - roleId: $role->id, - duration: $this->form->duration, - appIds: $this->form->appIds - ) - ); + $this->appRoleService->assign(new AssignAppsToRoleData( + roleId: $role->id, + validUpto: $this->form->isUnlimited ? now()->addYears(15) : $this->form->validUpto, + appIds: $this->form->appIds, + )); $this->showCreateModal = false; $this->form->reset(); unset($this->getRoles); diff --git a/resources/views/pages/access-manager/roles-and-apps/⚡show.blade.php b/resources/views/pages/access-manager/roles-and-apps/⚡show.blade.php index 3a087b4..7b49cc9 100644 --- a/resources/views/pages/access-manager/roles-and-apps/⚡show.blade.php +++ b/resources/views/pages/access-manager/roles-and-apps/⚡show.blade.php @@ -7,6 +7,7 @@ use App\Models\Role; use App\Services\AppRoleService; use Livewire\Attributes\{Computed, Layout, Title}; +use Illuminate\Support\Carbon; use Livewire\Component; use Spatie\LaravelData\Attributes\DataCollectionOf; use Spatie\LaravelData\DataCollection; @@ -71,7 +72,7 @@ public function mount(int $id): void $this->appHeaders = TableHeader::collect([ new TableHeader(key: 'app_name', label: 'App'), - new TableHeader(key: 'duration', label: 'Duration (days)'), + new TableHeader(key: 'duration', label: 'Validity'), ], DataCollection::class); $this->userHeaders = TableHeader::collect([ @@ -118,7 +119,7 @@ public function openEditAppModal(int $assignmentId): void if ($assignment) { $this->assignForm->appIds = [$assignment['appId'] ?? $assignment['id']]; - $this->assignForm->duration = $assignment['duration']; + $this->assignForm->validUpto = $assignment['duration']; $this->editingAppName = $assignment['appName']; } @@ -160,12 +161,12 @@ public function assignApp(): void { $this->attempt( action: function (): void { + $this->assignForm->validate(); $this->appRoleService->assign(new AssignAppsToRoleData( roleId: $this->roleId, - duration: $this->assignForm->duration, + validUpto: $this->assignForm->isUnlimited ? now()->addYears(15) : $this->assignForm->validUpto, appIds: $this->assignForm->appIds, )); - $this->assignForm->reset(); $this->showAddAppModal = false; unset($this->apps); @@ -178,9 +179,10 @@ public function updateApp(): void { $this->attempt( action: function (): void { + $this->assignForm->validate(); $this->appRoleService->assign(new AssignAppsToRoleData( roleId: $this->roleId, - duration: $this->assignForm->duration, + validUpto: $this->assignForm->isUnlimited ? now()->addYears(15) : $this->assignForm->validUpto, appIds: $this->assignForm->appIds, )); @@ -275,7 +277,7 @@ class="btn-sm btn-ghost" - + Add App @@ -290,7 +292,7 @@ class="btn-sm btn-ghost" @endscope @scope('cell_duration', $row) - {{ $row['duration'] }} days + {{ Carbon::parse($row['duration'])->diffForHumans() }} @endscope @scope('actions', $row) @@ -358,27 +360,16 @@ class="btn-sm btn-error btn-soft btn-circle" @if(!$isEditingApp)
-
- -
- - -
-
- -
@else @@ -390,23 +381,34 @@ class="btn-sm btn-error btn-soft btn-circle" class="bg-gray-50 text-gray-500 cursor-not-allowed" /> @endif +
- +
+ +
+ + +
Cancel - {{ $isEditingApp ? 'Update Duration' : 'Assign Apps' }} diff --git a/resources/views/partials/head.blade.php b/resources/views/partials/head.blade.php index a6bdc44..3b539d9 100644 --- a/resources/views/partials/head.blade.php +++ b/resources/views/partials/head.blade.php @@ -1,5 +1,5 @@ - - + + {{ filled($title ?? null) ? $title.' - '.config('app.name', 'Laravel') : config('app.name', 'Laravel') }} @@ -13,3 +13,6 @@ @vite(['resources/css/app.css', 'resources/js/app.js']) @livewireStyles +{{--For date picker in maryui. Remove this if opt for native --}} +<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css"> +<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>