70 lines
1.9 KiB
PHP
70 lines
1.9 KiB
PHP
<?php
|
|
/**
|
|
* Secure File Proxy for Invoices
|
|
*/
|
|
|
|
use App\Core\Database;
|
|
use App\Middleware\AuthMiddleware;
|
|
|
|
// Helper to output error as an image for debugging
|
|
function outputErrorImage($message) {
|
|
header('Content-Type: image/png');
|
|
$im = imagecreatetruecolor(400, 100);
|
|
$bg = imagecolorallocate($im, 20, 20, 20);
|
|
$tc = imagecolorallocate($im, 255, 50, 50);
|
|
imagefilledrectangle($im, 0, 0, 400, 100, $bg);
|
|
imagestring($im, 5, 10, 40, $message, $tc);
|
|
imagepng($im);
|
|
imagedestroy($im);
|
|
exit;
|
|
}
|
|
|
|
// Extract token from header OR query string using helper
|
|
$token = input('token');
|
|
if (!$token) {
|
|
$headers = getallheaders();
|
|
$authHeader = $headers['Authorization'] ?? $headers['authorization'] ?? '';
|
|
if (preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
|
|
$token = $matches[1];
|
|
}
|
|
}
|
|
|
|
if (!$token) outputErrorImage('Forbidden: No token');
|
|
|
|
$decoded = \App\Core\JWT::decode($token, env('JWT_SECRET', ''));
|
|
if (!$decoded) outputErrorImage('Forbidden: Invalid token');
|
|
|
|
$db = Database::getInstance();
|
|
$id = input('id');
|
|
if (!$id) outputErrorImage('Forbidden: No ID');
|
|
|
|
$stmt = $db->prepare("SELECT tenant_id, original_file_path FROM invoices WHERE id = ?");
|
|
$stmt->execute([$id]);
|
|
$invoice = $stmt->fetch();
|
|
|
|
if (!$invoice) outputErrorImage('Error: Invoice not found');
|
|
|
|
// Authorization
|
|
if ($decoded['role'] !== 'super_admin' && $invoice['tenant_id'] !== $decoded['tenant_id']) {
|
|
outputErrorImage('Error: Unauthorized');
|
|
}
|
|
|
|
$filePath = $invoice['original_file_path'];
|
|
|
|
if (!file_exists($filePath)) {
|
|
outputErrorImage('Error: File missing on disk');
|
|
}
|
|
|
|
if (!is_readable($filePath)) {
|
|
outputErrorImage('Error: Permission denied');
|
|
}
|
|
|
|
$mime = mime_content_type($filePath);
|
|
if (!$mime) $mime = 'application/octet-stream';
|
|
|
|
header("Content-Type: $mime");
|
|
header("Content-Length: " . filesize($filePath));
|
|
header("Cache-Control: public, max-age=3600");
|
|
readfile($filePath);
|
|
exit;
|