singleloginsystem/app/Services/AppRoleService.php
= c680c1ae6e Feat: implement role and app management
- Added services (`RoleService`, `AppRoleService`, `AppsPermissionService`) to handle role creation, app assignments, and permissions.
- Introduced new Livewire forms for creating roles and assigning apps (`CreateRoleForm`, `AssignAppToRoleForm`).
- Built dynamic Blade views for role and app management, including modals and reusable components.
- Removed outdated `fluxui-development` skill documentation.
2026-05-19 11:13:35 +00:00

112 lines
3.0 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services;
use App\Data\Role\{AssignAppsToRoleData, RoleAppData};
use App\Models\{AppRole, ConnectedApp};
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException;
use NoDiscard;
use Spatie\LaravelData\DataCollection;
use Throwable;
final class AppRoleService
{
/**
* Assign connected apps to a role, updating the duration if already assigned.
*
* @throws Throwable when an error occurs during the assignment.
*/
public function assign(AssignAppsToRoleData $data): void
{
if (empty($data->appIds)) {
return;
}
$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']
);
}
/**
* Remove an app-role assignment.
*
* @throws InvalidArgumentException when id is invalid.
* @throws Throwable when an error occurs during the deletion.
*/
public function detach(int $id): void
{
if ($id <= 0) {
throw new InvalidArgumentException('Invalid id');
}
DB::transaction(function () use ($id): void {
AppRole::query()->findOrFail($id)->delete();
});
}
/**
* Get all apps assigned to a given role.
*
* @return DataCollection<int, RoleAppData>
*/
#[NoDiscard]
public function getAppsForRole(int $roleId): DataCollection
{
$assignments = AppRole::query()
->with('app:id,name')
->where('role_id', $roleId)
->orderBy('id')
->get(['id', 'app_id', 'role_id', 'duration']);
return RoleAppData::collect(
$assignments->map(fn (AppRole $row): array => [
'id' => $row->id,
'appId' => $row->app_id,
'appName' => $row->app->name,
'duration' => $row->duration,
])->all(),
DataCollection::class,
);
}
/**
* Search available apps for the select dropdown.
*/
#[NoDiscard]
public function searchAppsForSelect(string $search = ''): Collection
{
return ConnectedApp::query()
->select(['id', 'name'])
->when($search, function ($query, $search): void {
$query->where('name', 'like', '%'.$search.'%');
})
->limit(50) // Limit the results so the dropdown doesn't lag
->orderBy('name')
->get(['id', 'name']);
}
/**
* Get all connected app IDs for the "Select All" feature.
*
* @return array<int>
*/
#[NoDiscard]
public function getAllAppIds(): array
{
// Replace 'ConnectedApp' with your actual model name
return ConnectedApp::pluck('id')->toArray();
}
}