ultimatepos/app/Services/Holding/AssignmentQueryScopeService.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);
}
}