194 lines
7.0 KiB
PHP
Executable File
194 lines
7.0 KiB
PHP
Executable File
<?php
|
|
namespace App\Services\Documenti;
|
|
|
|
use App\Models\Documento;
|
|
use App\Models\DocumentoStabile;
|
|
use App\Models\User;
|
|
use App\Support\StabileContext;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class DocumentoArchivioVisibilityService
|
|
{
|
|
public function scopeVisibleDocumenti(Builder $query, User $user): Builder
|
|
{
|
|
$activeStabile = StabileContext::getActiveStabile($user);
|
|
if ($activeStabile !== null) {
|
|
$query->where('stabile_id', (int) $activeStabile->id);
|
|
} elseif (! $user->hasAnyRole(['super-admin', 'admin'])) {
|
|
$allowedIds = StabileContext::accessibleStabili($user)
|
|
->pluck('id')
|
|
->map(fn($value): int => (int) $value)
|
|
->all();
|
|
|
|
if ($allowedIds === []) {
|
|
$query->whereRaw('1 = 0');
|
|
|
|
return $query;
|
|
}
|
|
|
|
$query->whereIn('stabile_id', $allowedIds);
|
|
}
|
|
|
|
return $query->where(function (Builder $documentQuery) use ($user): void {
|
|
$documentQuery->whereNull('cartella_archivio_id')
|
|
->where(function (Builder $baseVisibility) use ($user): void {
|
|
$this->applyVisibilityConstraint($baseVisibility, $user, 'documenti');
|
|
})
|
|
->orWhereHas('cartellaArchivio', function (Builder $folderQuery) use ($user): void {
|
|
$folderQuery->where('is_active', true);
|
|
$this->applyVisibilityConstraint($folderQuery, $user, 'documento_archivio_cartelle');
|
|
});
|
|
});
|
|
}
|
|
|
|
public function scopeVisibleCartelle(Builder $query, User $user, ?int $stabileId = null): Builder
|
|
{
|
|
if ($stabileId !== null && $stabileId > 0) {
|
|
$query->where('stabile_id', $stabileId);
|
|
} else {
|
|
$activeStabile = StabileContext::getActiveStabile($user);
|
|
if ($activeStabile !== null) {
|
|
$query->where('stabile_id', (int) $activeStabile->id);
|
|
} elseif (! $user->hasAnyRole(['super-admin', 'admin'])) {
|
|
$allowedIds = StabileContext::accessibleStabili($user)
|
|
->pluck('id')
|
|
->map(fn($value): int => (int) $value)
|
|
->all();
|
|
|
|
if ($allowedIds === []) {
|
|
$query->whereRaw('1 = 0');
|
|
|
|
return $query;
|
|
}
|
|
|
|
$query->whereIn('stabile_id', $allowedIds);
|
|
}
|
|
}
|
|
|
|
$query->where('is_active', true);
|
|
$this->applyVisibilityConstraint($query, $user, 'documento_archivio_cartelle');
|
|
|
|
return $query;
|
|
}
|
|
|
|
public function canAccessDocumento(User $user, Documento $documento): bool
|
|
{
|
|
return $this->scopeVisibleDocumenti(Documento::query()->whereKey($documento->getKey()), $user)->exists();
|
|
}
|
|
|
|
public function canAccessDocumentoStabile(User $user, DocumentoStabile $documentoStabile): bool
|
|
{
|
|
$allowedIds = StabileContext::accessibleStabili($user)
|
|
->pluck('id')
|
|
->map(fn($value): int => (int) $value)
|
|
->all();
|
|
|
|
return in_array((int) $documentoStabile->stabile_id, $allowedIds, true);
|
|
}
|
|
|
|
private function applyVisibilityConstraint(Builder $query, User $user, string $table): void
|
|
{
|
|
if (! $this->hasVisibilityColumn($table, 'visibility_scope')) {
|
|
return;
|
|
}
|
|
|
|
$canSeeInternalScopes = $this->canSeeInternalScopes($user);
|
|
|
|
$query->where(function (Builder $visibilityQuery) use ($table, $user, $canSeeInternalScopes): void {
|
|
if ($canSeeInternalScopes) {
|
|
$visibilityQuery->whereNull($table . '.visibility_scope')
|
|
->orWhere($table . '.visibility_scope', 'interno')
|
|
->orWhere($table . '.visibility_scope', 'studio');
|
|
}
|
|
|
|
$visibilityQuery->orWhere(function (Builder $restrictedQuery) use ($table, $user): void {
|
|
$restrictedQuery->where($table . '.visibility_scope', 'restricted');
|
|
$this->applyRestrictedAudienceConstraint($restrictedQuery, $user, $table);
|
|
});
|
|
});
|
|
}
|
|
|
|
private function applyRestrictedAudienceConstraint(Builder $query, User $user, string $table): void
|
|
{
|
|
$roles = $user->getRoleNames()->map(fn($role): string => (string) $role)->values()->all();
|
|
$groupLabels = $this->resolveAudienceGroupsForUser($user);
|
|
$userId = (int) $user->id;
|
|
$hasRolesColumn = $this->hasVisibilityColumn($table, 'visibility_roles');
|
|
$hasGroupsColumn = $this->hasVisibilityColumn($table, 'visibility_groups');
|
|
$hasAllowedUsersColumn = $this->hasVisibilityColumn($table, 'allowed_user_ids');
|
|
|
|
$query->where(function (Builder $matchQuery) use ($table, $roles, $groupLabels, $userId, $hasRolesColumn, $hasGroupsColumn, $hasAllowedUsersColumn): void {
|
|
$hasAudienceConstraint = false;
|
|
|
|
if ($hasRolesColumn && $roles !== []) {
|
|
foreach ($roles as $role) {
|
|
$matchQuery->orWhereJsonContains($table . '.visibility_roles', $role);
|
|
}
|
|
|
|
$hasAudienceConstraint = true;
|
|
}
|
|
|
|
if ($hasGroupsColumn && $groupLabels !== []) {
|
|
foreach ($groupLabels as $groupLabel) {
|
|
$matchQuery->orWhereJsonContains($table . '.visibility_groups', $groupLabel);
|
|
}
|
|
|
|
$hasAudienceConstraint = true;
|
|
}
|
|
|
|
if ($hasAllowedUsersColumn) {
|
|
$matchQuery->orWhereJsonContains($table . '.allowed_user_ids', $userId);
|
|
$hasAudienceConstraint = true;
|
|
}
|
|
|
|
if (! $hasAudienceConstraint) {
|
|
$matchQuery->whereRaw('1 = 0');
|
|
}
|
|
});
|
|
}
|
|
|
|
private function canSeeInternalScopes(User $user): bool
|
|
{
|
|
return $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']);
|
|
}
|
|
|
|
private function hasVisibilityColumn(string $table, string $column): bool
|
|
{
|
|
static $cache = [];
|
|
|
|
$cacheKey = $table . '.' . $column;
|
|
if (! array_key_exists($cacheKey, $cache)) {
|
|
$cache[$cacheKey] = Schema::hasColumn($table, $column);
|
|
}
|
|
|
|
return $cache[$cacheKey];
|
|
}
|
|
|
|
private function resolveAudienceGroupsForUser(User $user): array
|
|
{
|
|
$groups = [];
|
|
|
|
if ($user->hasAnyRole(['super-admin', 'admin', 'amministratore'])) {
|
|
$groups[] = 'Amministratore';
|
|
$groups[] = 'Studio completo';
|
|
}
|
|
|
|
if ($user->hasRole('collaboratore')) {
|
|
$groups[] = 'Collaboratori interni';
|
|
}
|
|
|
|
if ($user->hasRole('condomino')) {
|
|
$groups[] = 'Condomini';
|
|
$groups[] = 'Utenti portale';
|
|
}
|
|
|
|
if ($user->hasRole('inquilino')) {
|
|
$groups[] = 'Inquilini';
|
|
$groups[] = 'Utenti portale';
|
|
}
|
|
|
|
return array_values(array_unique($groups));
|
|
}
|
|
}
|