authorize('viewAny', Role::class); $query = Role::query(); if ($request->has('orderByField')) { $query->orderBy($request['orderByField'], $request['orderBy']); } if ($request->company_id) { $query->where('scope', $request->company_id); } return RoleResource::collection($query->get()); } /** * Define a role and settle its abilities in one go. */ public function store(RoleRequest $request) { $this->authorize('create', Role::class); $role = Role::query()->create($request->getRolePayload()); $this->writeCatalogGrants($role, $request->abilities); return RoleResource::make($role); } /** * One role with its current grants. */ public function show(Role $role) { $this->authorize('view', $role); return RoleResource::make($role); } /** * Rename a role and rewrite its grants. */ public function update(RoleRequest $request, Role $role) { $this->authorize('update', $role); $role->fill($request->getRolePayload())->save(); $this->writeCatalogGrants($role, $request->abilities); return RoleResource::make($role); } /** * Drop a role, unless somebody in this company still holds it. */ public function destroy(Role $role) { $this->authorize('delete', $role); if (User::whereIs($role->name)->exists()) { return respondJson(self::IN_USE_ERROR, self::IN_USE_MESSAGE); } $role->delete(); return response()->json(['success' => true]); } /** * Walk the whole ability catalog and make the role match the submission. * * The submission is read as a set of names: a catalog entry named in it is * granted, every other entry is revoked, so a role never keeps a grant the * caller left out. Names that match no catalog entry are simply never * looked at. */ private function writeCatalogGrants($role, $submitted): void { $wanted = array_column($submitted, 'ability'); foreach (config('abilities.abilities') as $entry) { if (in_array($entry['ability'], $wanted)) { BouncerFacade::allow($role)->to($entry['ability'], $entry['model']); continue; } BouncerFacade::disallow($role)->to($entry['ability'], $entry['model']); } } }