Laravel 13 + Livewire/Volt app for managing client organizations, documents, passwords, flexible assets, virtual machines, contacts, domains, todos, shortcuts, and role-based user administration.
73 lines
2.4 KiB
PHP
73 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Document;
|
|
use Firebase\JWT\JWT;
|
|
use Firebase\JWT\Key;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
|
|
class OnlyOfficeController extends Controller
|
|
{
|
|
public function download(Request $request, Document $document): StreamedResponse
|
|
{
|
|
// Relative signature: the download URL is built with a host the document
|
|
// server can reach (host.docker.internal, ...), which may differ from
|
|
// the host the browser/this server sees — only path+query are signed.
|
|
abort_unless($request->hasValidRelativeSignature(), 403);
|
|
abort_unless($document->isOffice() && $document->file_path, 404);
|
|
|
|
return Storage::response($document->file_path);
|
|
}
|
|
|
|
public function callback(Request $request, Document $document): JsonResponse
|
|
{
|
|
abort_unless($document->isOffice(), 404);
|
|
|
|
$payload = $this->verifiedPayload($request);
|
|
|
|
// OnlyOffice callback statuses: 2 = ready to save, 6 = force-saved while editing.
|
|
if (in_array($payload['status'] ?? null, [2, 6], true) && filled($payload['url'] ?? null)) {
|
|
$response = Http::get($payload['url']);
|
|
abort_unless($response->successful(), 502);
|
|
|
|
Storage::put($document->file_path, $response->body());
|
|
|
|
$document->increment('current_version');
|
|
$document->update(['office_key' => Str::random(20)]);
|
|
|
|
$document->versions()->create([
|
|
'version' => $document->current_version,
|
|
'created_by' => $payload['users'][0] ?? null,
|
|
]);
|
|
}
|
|
|
|
return response()->json(['error' => 0]);
|
|
}
|
|
|
|
protected function verifiedPayload(Request $request): array
|
|
{
|
|
$secret = config('onlyoffice.jwt_secret');
|
|
|
|
if (blank($secret)) {
|
|
return $request->all();
|
|
}
|
|
|
|
$token = $request->bearerToken()
|
|
?? $request->input('token')
|
|
?? str($request->header('Authorization', ''))->after('Bearer ')->toString();
|
|
|
|
abort_if(blank($token), SymfonyResponse::HTTP_UNAUTHORIZED);
|
|
|
|
$decoded = JWT::decode($token, new Key($secret, 'HS256'));
|
|
|
|
return (array) ($decoded->payload ?? $decoded);
|
|
}
|
|
}
|