Files
SGF/app/Modules/Services/ServiceAccess.php
T

53 lines
3.9 KiB
PHP

<?php
namespace App\Modules\Services;
use App\Modules\Identity\Services\Audit;
use App\Modules\Identity\Services\Permissions;
use App\Shared\Context\CompanyContext;
use Illuminate\Support\Facades\DB;
final class ServiceAccess
{
public function __construct(private ServiceWorkflow $workflow, private CompanyContext $context, private Permissions $permissions) {}
public function listing(string $area, int $actor): array
{
$scope = $this->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]);
});
}
}