netgescon-day0/app/Http/Controllers/Admin/TicketAttachmentViewController.php

126 lines
4.2 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Fornitore;
use App\Models\FornitoreDipendente;
use App\Models\TicketAttachment;
use App\Models\User;
use App\Support\StabileContext;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class TicketAttachmentViewController extends Controller
{
public function show(TicketAttachment $attachment): BinaryFileResponse
{
$user = Auth::user();
if (! $user instanceof User) {
abort(403);
}
if (! $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore', 'fornitore'])) {
abort(403);
}
$ticket = $attachment->ticket;
if (! $ticket) {
abort(404);
}
if ($user->hasRole('fornitore')) {
$this->authorizeSupplierAttachment($user, $attachment);
} else {
$stabileId = StabileContext::resolveActiveStabileId($user);
if (! $stabileId || (int) $ticket->stabile_id !== (int) $stabileId) {
abort(403);
}
}
$disk = Storage::disk('public');
$path = (string) $attachment->file_path;
if (! $disk->exists($path)) {
abort(404);
}
$absolutePath = $disk->path($path);
$mime = $attachment->resolvedMimeType();
return response()->file($absolutePath, [
'Content-Type' => $mime,
'Cache-Control' => 'private, max-age=300',
'Content-Disposition' => 'inline; filename="' . addslashes((string) ($attachment->original_file_name ?: basename($path))) . '"',
]);
}
protected function authorizeSupplierAttachment(User $user, TicketAttachment $attachment): void
{
$fornitoreIds = [];
$currentSupplier = $this->resolveCurrentUserSupplier($user);
if ($currentSupplier instanceof Fornitore) {
$fornitoreIds[] = (int) $currentSupplier->id;
}
$dipendente = $this->resolveCollaboratoreForUser($user, $currentSupplier?->id);
if ($dipendente instanceof FornitoreDipendente) {
$fornitoreIds[] = (int) $dipendente->fornitore_id;
if ((int) ($dipendente->fornitore_esterno_id ?? 0) > 0) {
$fornitoreIds[] = (int) $dipendente->fornitore_esterno_id;
}
}
$fornitoreIds = array_values(array_unique(array_filter($fornitoreIds)));
abort_if($fornitoreIds === [], 403);
$ticket = $attachment->ticket;
abort_unless($ticket, 404);
if (in_array((int) ($ticket->assegnato_a_fornitore_id ?? 0), $fornitoreIds, true)) {
return;
}
$hasIntervento = $ticket->interventi()
->whereIn('fornitore_id', $fornitoreIds)
->exists();
abort_unless($hasIntervento, 403);
}
protected function resolveCurrentUserSupplier(User $user): ?Fornitore
{
$email = mb_strtolower(trim((string) $user->email));
if ($email === '') {
return null;
}
return Fornitore::query()
->whereRaw('LOWER(email) = ?', [$email])
->withCount(['ticketInterventi', 'dipendenti'])
->orderByDesc('ticket_interventi_count')
->orderByDesc('dipendenti_count')
->orderByDesc('id')
->first();
}
protected function resolveCollaboratoreForUser(User $user, ?int $currentSupplierId = null): ?FornitoreDipendente
{
return FornitoreDipendente::query()
->where('attivo', true)
->where(function ($builder) use ($user, $currentSupplierId): void {
$builder->where('user_id', (int) $user->id)
->orWhereRaw('LOWER(email) = ?', [mb_strtolower((string) $user->email)]);
if (($currentSupplierId ?? 0) > 0) {
$builder->orWhere('fornitore_esterno_id', (int) $currentSupplierId);
}
})
->orderByRaw('CASE WHEN user_id = ? THEN 0 ELSE 1 END', [(int) $user->id])
->orderByRaw('CASE WHEN fornitore_esterno_id IS NULL THEN 1 ELSE 0 END')
->orderByDesc('id')
->first();
}
}