115 lines
3.3 KiB
PHP
115 lines
3.3 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Holding;
|
|
|
|
use App\EmploymentAssignment;
|
|
use Illuminate\Database\Query\Builder;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class AssignmentQueryScopeService
|
|
{
|
|
public function __construct(protected ContextAssignmentService $contextAssignmentService) {}
|
|
|
|
public function activeAssignment(?\App\User $user = null): ?EmploymentAssignment
|
|
{
|
|
$user = $user ?? auth()->user();
|
|
|
|
if (! $user) {
|
|
return null;
|
|
}
|
|
|
|
return $this->contextAssignmentService->getActiveAssignment($user);
|
|
}
|
|
|
|
/**
|
|
* Apply holding assignment scopes to a query builder when RBAC is enabled.
|
|
*
|
|
* @param array<string, string> $columnMap e.g. ['holding_entity_id' => 'transactions.holding_entity_id', 'location_id' => 'transactions.location_id']
|
|
*/
|
|
public function applyToQuery(Builder $query, ?EmploymentAssignment $assignment = null, array $columnMap = []): Builder
|
|
{
|
|
if (! config('constants.enable_holding_context_rbac', false)) {
|
|
return $query;
|
|
}
|
|
|
|
$assignment = $assignment ?? $this->activeAssignment();
|
|
|
|
if (! $assignment || $assignment->scopes->isEmpty()) {
|
|
return $query;
|
|
}
|
|
|
|
foreach ($assignment->scopes as $scope) {
|
|
$column = $columnMap[$scope->scope_key] ?? $scope->scope_key;
|
|
|
|
if (! $this->columnResolvable($column)) {
|
|
continue;
|
|
}
|
|
|
|
if ($scope->scope_value === '*' || $scope->scope_value === null) {
|
|
continue;
|
|
}
|
|
|
|
$values = array_filter(array_map('trim', explode(',', (string) $scope->scope_value)));
|
|
|
|
if (empty($values)) {
|
|
continue;
|
|
}
|
|
|
|
$query->whereIn($column, $values);
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
|
|
public function allowedEntityIds(?EmploymentAssignment $assignment = null): ?array
|
|
{
|
|
if (! config('constants.enable_holding_context_rbac', false)) {
|
|
return null;
|
|
}
|
|
|
|
$assignment = $assignment ?? $this->activeAssignment();
|
|
|
|
if (! $assignment) {
|
|
return null;
|
|
}
|
|
|
|
$entityScope = $assignment->scopes->firstWhere('scope_key', 'holding_entity_id');
|
|
|
|
if (! $entityScope || $entityScope->scope_value === '*') {
|
|
return $assignment->entity_id ? [(int) $assignment->entity_id] : null;
|
|
}
|
|
|
|
return array_map('intval', array_filter(explode(',', (string) $entityScope->scope_value)));
|
|
}
|
|
|
|
public function allowedLocationIds(?EmploymentAssignment $assignment = null): ?array
|
|
{
|
|
if (! config('constants.enable_holding_context_rbac', false)) {
|
|
return null;
|
|
}
|
|
|
|
$assignment = $assignment ?? $this->activeAssignment();
|
|
|
|
if (! $assignment) {
|
|
return null;
|
|
}
|
|
|
|
$locationScope = $assignment->scopes->firstWhere('scope_key', 'location_id');
|
|
|
|
if (! $locationScope || $locationScope->scope_value === '*') {
|
|
return null;
|
|
}
|
|
|
|
return array_map('intval', array_filter(explode(',', (string) $locationScope->scope_value)));
|
|
}
|
|
|
|
protected function columnResolvable(string $column): bool
|
|
{
|
|
if (str_contains($column, '.')) {
|
|
return true;
|
|
}
|
|
|
|
return Schema::hasColumn('transactions', $column);
|
|
}
|
|
}
|