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 */ #[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 */ #[NoDiscard] public function getAllAppIds(): array { return ConnectedApp::pluck('id')->toArray(); } /** * Assign users to a role using spatie/laravel-permission. * * @throws Throwable when an error occurs during the assignment. */ public function assignUsersToRole(AssignUsersToRoleData $data): void { if (empty($data->userIds)) { return; } DB::transaction(function () use ($data): void { $role = Role::query()->findOrFail($data->roleId); $users = User::query()->whereIn('id', $data->userIds)->get(); /** @var User $user */ foreach ($users as $user) { if (! $user->hasRole($role)) { $user->assignRole($role); } } }); } /** * Remove a user from a role. * * @throws InvalidArgumentException when userId is invalid. * @throws Throwable when an error occurs during the removal. */ public function detachUserFromRole(int $roleId, int $userId): void { if ($userId <= 0) { throw new InvalidArgumentException('Invalid user id'); } DB::transaction(function () use ($roleId, $userId): void { $role = Role::query()->findOrFail($roleId); $user = User::query()->findOrFail($userId); $user->removeRole($role); }); } /** * Get all users assigned to a given role. * * @return DataCollection */ #[NoDiscard] public function getUsersForRole(int $roleId): DataCollection { $role = Role::query()->findOrFail($roleId); $users = User::query() ->select(['id', 'name', 'email']) ->role($role) ->orderBy('name') ->get(); return RoleUserData::collect( $users->map(fn (User $user): array => [ 'id' => $user->id, 'name' => $user->name, 'email' => $user->email, ])->all(), DataCollection::class, ); } /** * Search users for the select dropdown, returning only id and name. * * @return DataCollection */ #[NoDiscard] public function searchUsersForSelect(string $search = ''): DataCollection { $users = User::query() ->select(['id', 'name']) ->when($search, function ($query, $search): void { $query->where('name', 'like', '%'.$search.'%'); }) ->limit(50) ->orderBy('name') ->get(); return UserSelectData::collect($users, DataCollection::class); } }