347 lines
12 KiB
PHP
347 lines
12 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Amministratore;
|
|
use App\Services\DistributionService;
|
|
use App\Services\MultiDatabaseService;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class DistributionController extends Controller
|
|
{
|
|
/**
|
|
* Health check del server per verifiche distribuzione
|
|
*/
|
|
public function health(): JsonResponse
|
|
{
|
|
try {
|
|
$health = [
|
|
'status' => 'ok',
|
|
'timestamp' => now()->toISOString(),
|
|
'version' => config('app.version', '1.0.0'),
|
|
'server' => config('app.url'),
|
|
'database' => [
|
|
'connection' => config('database.default'),
|
|
'status' => 'ok'
|
|
],
|
|
'storage' => [
|
|
'disk' => config('filesystems.default'),
|
|
'available' => true
|
|
],
|
|
'administrators_count' => Amministratore::count(),
|
|
'features' => [
|
|
'multi_database' => true,
|
|
'distribution' => true,
|
|
'migration' => true,
|
|
'backup' => true
|
|
]
|
|
];
|
|
|
|
// Test connessione database
|
|
try {
|
|
DB::connection()->getPdo();
|
|
} catch (\Exception $e) {
|
|
$health['database']['status'] = 'error';
|
|
$health['database']['error'] = $e->getMessage();
|
|
$health['status'] = 'degraded';
|
|
}
|
|
|
|
// Test storage
|
|
try {
|
|
Storage::disk()->exists('.');
|
|
} catch (\Exception $e) {
|
|
$health['storage']['available'] = false;
|
|
$health['storage']['error'] = $e->getMessage();
|
|
$health['status'] = 'degraded';
|
|
}
|
|
|
|
return response()->json($health);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'status' => 'error',
|
|
'error' => $e->getMessage(),
|
|
'timestamp' => now()->toISOString()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Importa archivio amministratore da altro server
|
|
*/
|
|
public function importAdministrator(Request $request): JsonResponse
|
|
{
|
|
try {
|
|
$request->validate([
|
|
'codice_amministratore' => 'required|string|size:8',
|
|
'source_server' => 'required|url',
|
|
'migration_token' => 'required|string',
|
|
'archive' => 'required|file|mimes:zip|max:1048576' // Max 1GB
|
|
]);
|
|
|
|
$codiceAmministratore = $request->input('codice_amministratore');
|
|
$sourceServer = $request->input('source_server');
|
|
$migrationToken = $request->input('migration_token');
|
|
|
|
Log::info("Inizio importazione amministratore {$codiceAmministratore} da {$sourceServer}");
|
|
|
|
// Verifica che l'amministratore non esista già
|
|
if (Amministratore::where('codice_amministratore', $codiceAmministratore)->exists()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'error' => 'Amministratore già presente su questo server'
|
|
], 409);
|
|
}
|
|
|
|
// Salva archivio temporaneo
|
|
$archive = $request->file('archive');
|
|
$tempPath = storage_path("app/temp/import_{$codiceAmministratore}_" . time() . ".zip");
|
|
|
|
if (!is_dir(dirname($tempPath))) {
|
|
mkdir(dirname($tempPath), 0755, true);
|
|
}
|
|
|
|
$archive->move(dirname($tempPath), basename($tempPath));
|
|
|
|
// Estrae archivio
|
|
$extractPath = storage_path("app/amministratori/{$codiceAmministratore}");
|
|
$zip = new \ZipArchive();
|
|
|
|
if ($zip->open($tempPath) !== TRUE) {
|
|
throw new \Exception('Impossibile aprire archivio ZIP');
|
|
}
|
|
|
|
$zip->extractTo($extractPath);
|
|
$zip->close();
|
|
|
|
// Rimuove file temporaneo
|
|
unlink($tempPath);
|
|
|
|
Log::info("Archivio amministratore {$codiceAmministratore} estratto in {$extractPath}");
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Archivio importato con successo',
|
|
'transfer_id' => uniqid('transfer_'),
|
|
'extracted_to' => $extractPath,
|
|
'imported_at' => now()->toISOString()
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error("Errore importazione amministratore: " . $e->getMessage());
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'error' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attiva amministratore dopo importazione
|
|
*/
|
|
public function activateAdministrator(Request $request): JsonResponse
|
|
{
|
|
try {
|
|
$request->validate([
|
|
'codice_amministratore' => 'required|string|size:8',
|
|
'activation_token' => 'required|string'
|
|
]);
|
|
|
|
$codiceAmministratore = $request->input('codice_amministratore');
|
|
|
|
Log::info("Attivazione amministratore {$codiceAmministratore}");
|
|
|
|
// Verifica che l'archivio sia stato importato
|
|
$archivePath = storage_path("app/amministratori/{$codiceAmministratore}");
|
|
if (!is_dir($archivePath)) {
|
|
throw new \Exception('Archivio amministratore non trovato. Importare prima l\'archivio.');
|
|
}
|
|
|
|
// Cerca metadata
|
|
$metadataPath = storage_path("app/migrations/metadata_{$codiceAmministratore}.json");
|
|
if (!file_exists($metadataPath)) {
|
|
throw new \Exception('Metadata migrazione non trovati');
|
|
}
|
|
|
|
$metadata = json_decode(file_get_contents($metadataPath), true);
|
|
|
|
// Crea record amministratore nel database
|
|
$amministratore = Amministratore::create([
|
|
'nome' => $metadata['amministratore']['nome'],
|
|
'cognome' => $metadata['amministratore']['cognome'],
|
|
'denominazione_studio' => $metadata['amministratore']['denominazione_studio'],
|
|
'codice_amministratore' => $codiceAmministratore,
|
|
'user_id' => 1, // TODO: gestire user associato
|
|
'database_attivo' => $metadata['amministratore']['database_name'],
|
|
'cartella_dati' => "amministratori/{$codiceAmministratore}",
|
|
'stato_sincronizzazione' => 'attivo',
|
|
'attivo' => true
|
|
]);
|
|
|
|
// Ripristina database se presente
|
|
$backupFiles = glob($archivePath . '/backup/database/*.sql');
|
|
if (!empty($backupFiles)) {
|
|
$latestBackup = end($backupFiles);
|
|
$this->restoreDatabase($amministratore, $latestBackup);
|
|
}
|
|
|
|
Log::info("Amministratore {$codiceAmministratore} attivato con successo");
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Amministratore attivato con successo',
|
|
'administrator_id' => $amministratore->id,
|
|
'database_restored' => !empty($backupFiles),
|
|
'activated_at' => now()->toISOString()
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error("Errore attivazione amministratore: " . $e->getMessage());
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'error' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sincronizza dati amministratore
|
|
*/
|
|
public function syncAdministrator(Request $request): JsonResponse
|
|
{
|
|
try {
|
|
$request->validate([
|
|
'codice_amministratore' => 'required|string|size:8',
|
|
'last_sync' => 'nullable|date',
|
|
'sync_token' => 'required|string'
|
|
]);
|
|
|
|
$codiceAmministratore = $request->input('codice_amministratore');
|
|
$lastSync = $request->input('last_sync');
|
|
|
|
$amministratore = Amministratore::where('codice_amministratore', $codiceAmministratore)->first();
|
|
|
|
if (!$amministratore) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'error' => 'Amministratore non trovato'
|
|
], 404);
|
|
}
|
|
|
|
// Simula sincronizzazione (da implementare logica specifica)
|
|
$changes = 0;
|
|
|
|
if ($lastSync) {
|
|
// Conta modifiche dalla data di ultima sincronizzazione
|
|
// TODO: implementare logica di tracking modifiche
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'changes' => $changes,
|
|
'last_sync' => $amministratore->updated_at,
|
|
'synced_at' => now()->toISOString()
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'error' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Esegue backup amministratore
|
|
*/
|
|
public function backupAdministrator(Request $request): JsonResponse
|
|
{
|
|
try {
|
|
$request->validate([
|
|
'codice_amministratore' => 'required|string|size:8',
|
|
'backup_token' => 'required|string'
|
|
]);
|
|
|
|
$codiceAmministratore = $request->input('codice_amministratore');
|
|
|
|
$amministratore = Amministratore::where('codice_amministratore', $codiceAmministratore)->first();
|
|
|
|
if (!$amministratore) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'error' => 'Amministratore non trovato'
|
|
], 404);
|
|
}
|
|
|
|
$backupResult = $amministratore->createDatabaseBackup();
|
|
|
|
if ($backupResult['success']) {
|
|
$amministratore->update(['ultimo_backup' => now()]);
|
|
}
|
|
|
|
return response()->json($backupResult);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'error' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ottiene informazioni routing per amministratore
|
|
*/
|
|
public function getAdministratorRouting(string $codice): JsonResponse
|
|
{
|
|
try {
|
|
$routingInfo = DistributionService::getAdministratorAccessUrl($codice);
|
|
return response()->json($routingInfo);
|
|
|
|
} catch (\Exception $e) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'error' => $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ripristina database da backup
|
|
*/
|
|
private function restoreDatabase(Amministratore $amministratore, string $backupPath): bool
|
|
{
|
|
try {
|
|
$dbName = $amministratore->getDatabaseName();
|
|
|
|
// Crea database se non esiste
|
|
DB::statement("CREATE DATABASE IF NOT EXISTS `{$dbName}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
|
|
|
// Ripristina da backup
|
|
$command = sprintf(
|
|
'mysql -h %s -u %s -p%s %s < %s',
|
|
env('DB_HOST', '127.0.0.1'),
|
|
env('DB_USERNAME'),
|
|
env('DB_PASSWORD'),
|
|
escapeshellarg($dbName),
|
|
escapeshellarg($backupPath)
|
|
);
|
|
|
|
exec($command, $output, $returnCode);
|
|
|
|
return $returnCode === 0;
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error("Errore ripristino database: " . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
}
|