workflow->scope($area, $actor, 'manage'); $grants = DB::table('permission_grants as g')->join('users as u', 'u.id', '=', 'g.user_id')->where('g.tenant_id', $scope['tenant_id'])->where('g.company_id', $scope['company_id'])->where('g.unit_id', $scope['unit_id'])->whereIn('g.permission', array_map(fn ($action) => "$area.$action", ServicePermissions::ACTIONS)) ->orderBy('u.name')->get(['g.id','g.permission','g.unit_id','u.name','u.email']); $actions = array_values(array_filter(ServicePermissions::ACTIONS, fn ($action) => $this->permissions->has($actor, $scope['tenant_id'], $scope['company_id'], "$area.$action", $scope['unit_id']))); return ['grants' => $grants, 'actions' => $actions, 'scope' => $scope]; } public function change(string $area, int $actor, array $input): void { $scope = $this->workflow->scope($area, $actor, 'manage'); $selected = $this->context->unitId(); DB::transaction(function () use ($area, $actor, $input, $scope, $selected): void { DB::table('companies')->where('id', $scope['company_id'])->lockForUpdate()->firstOrFail(); $this->context->selectFor($actor, $scope['tenant_id'], $scope['company_id'], $selected); $this->workflow->scope($area, $actor, 'manage'); $permission = "$area.".$input['action']; abort_unless(in_array($input['action'], ServicePermissions::ACTIONS, true), 422); $this->permissions->require($actor, $scope['tenant_id'], $scope['company_id'], $permission, $scope['unit_id']); $target = DB::table('users')->where('email', mb_strtolower($input['email']))->first(['id']); abort_unless($target, 422, 'Utilizador inexistente; nenhuma conta é criada por concessão.'); $this->permissions->require($target->id, $scope['tenant_id'], $scope['company_id'], 'company.view'); if ($scope['unit_id']) { $this->permissions->require($target->id, $scope['tenant_id'], $scope['company_id'], 'unit.view', $scope['unit_id']); } $query = DB::table('permission_grants')->where('tenant_id', $scope['tenant_id'])->where('company_id', $scope['company_id'])->where('unit_id', $scope['unit_id'])->where('user_id', $target->id); if ($input['grant']) { if ($input['action'] !== 'view') { $this->permissions->require($target->id, $scope['tenant_id'], $scope['company_id'], "$area.view", $scope['unit_id']); } DB::table('permission_grants')->insertOrIgnore($scope + ['user_id' => $target->id, 'permission' => $permission, 'created_at' => now(), 'updated_at' => now()]); $changed = [['permission' => $permission, 'unit_id' => $scope['unit_id']]]; } else { $query->whereIn('permission', $input['action'] === 'view' ? array_map(fn ($action) => "$area.$action", ServicePermissions::ACTIONS) : [$permission]); $changed = $query->get(['permission','unit_id'])->map(fn ($row) => (array) $row)->all(); foreach ($changed as $row) { $this->permissions->require($actor, $scope['tenant_id'], $scope['company_id'], $row['permission'], $scope['unit_id']); } $query->delete(); } Audit::record($input['grant'] ? 'a.access.granted' : 'a.access.revoked', $actor, $scope['tenant_id'], $scope['company_id'], $scope['unit_id'], $target->id, ['permission' => $permission, 'reason' => $input['reason'], 'grants' => $changed]); }); } }