getDecryptedConfig(); return match ($repo->tipo) { 'webdav' => $this->buildWebDAV($config), 'google_drive' => $this->buildGoogleDrive($config), default => null, }; } catch (\Exception $e) { Log::error("StorageRepository: failed to build filesystem for repo #{$repo->id} ({$repo->nome}): " . $e->getMessage()); return null; } } public function testConnection(StorageRepository $repo): array { try { $config = $repo->getDecryptedConfig(); if ($repo->tipo === 'google_drive') { if (empty($config['client_id']) || empty($config['client_secret']) || empty($config['refresh_token'])) { return ['success' => false, 'message' => 'Configurazione incompleta: client_id, client_secret e refresh_token sono necessari per Google Drive.']; } } $filesystem = $this->buildFilesystem($repo); if (!$filesystem) { return ['success' => false, 'message' => 'Impossibile costruire il filesystem per questo tipo di repository.']; } $rootPath = $this->normalizePath('/'); $contents = $filesystem->listContents($rootPath, false)->toArray(); return ['success' => true, 'message' => 'Connessione riuscita. ' . count($contents) . ' elementi trovati nella root.']; } catch (\Exception $e) { Log::error("StorageRepository: test connection failed for repo #{$repo->id} ({$repo->nome}): " . $e->getMessage()); return ['success' => false, 'message' => 'Errore di connessione: ' . $e->getMessage()]; } } public function listContents(StorageRepository $repo, string $path = '/'): array { try { $config = $repo->getDecryptedConfig(); if ($repo->tipo === 'google_drive') { if (empty($config['client_id']) || empty($config['client_secret']) || empty($config['refresh_token'])) { Log::warning("StorageRepository: listContents failed for repo #{$repo->id} ({$repo->nome}): credenziali Google Drive mancanti"); return []; } } $filesystem = $this->buildFilesystem($repo); if (!$filesystem) { return []; } $normalizedPath = $this->normalizePath($path); $items = $filesystem->listContents($normalizedPath, false)->toArray(); $result = []; foreach ($items as $item) { $result[] = [ 'path' => $item->path(), 'type' => $item->type(), 'basename' => basename($item->path()), 'lastModified' => $item->lastModified(), 'fileSize' => $item->fileSize(), 'mimeType' => $item->mimeType(), ]; } usort($result, fn($a, $b) => $a['type'] === 'dir' && $b['type'] !== 'dir' ? -1 : ($b['type'] === 'dir' && $a['type'] !== 'dir' ? 1 : strcasecmp($a['basename'], $b['basename']))); return $result; } catch (\Exception $e) { Log::error("StorageRepository: listContents failed for repo #{$repo->id} path '{$path}': " . $e->getMessage()); return []; } } public function encryptSensitiveConfig(array $config, string $tipo, array $existingConfig = []): array { $sensitiveFields = match ($tipo) { 'webdav' => ['password'], 'google_drive' => ['client_secret', 'refresh_token'], default => [], }; foreach ($sensitiveFields as $field) { if (!empty($config[$field]) && !$this->isEncrypted($config[$field])) { $config[$field] = Crypt::encryptString($config[$field]); } elseif (empty($config[$field]) && !empty($existingConfig[$field])) { $config[$field] = $existingConfig[$field]; } } return $config; } private function normalizePath(string $path): string { $path = trim($path); if ($path === '' || $path === '\\') { return ''; } if ($path === '/') { return ''; } return ltrim($path, '/\\'); } private function isEncrypted(string $value): bool { return str_starts_with($value, 'ey') || str_contains($value, ':'); } private function buildWebDAV(array $config): ?Filesystem { $authType = match ($config['auth_type'] ?? 'basic') { 'basic' => WebDAVClient::AUTH_BASIC, 'digest' => WebDAVClient::AUTH_DIGEST, 'ntlm' => WebDAVClient::AUTH_NTLM, default => WebDAVClient::AUTH_BASIC, }; $client = new WebDAVClient([ 'baseUri' => rtrim($config['base_uri'] ?? '', '/') . '/', 'userName' => $config['username'] ?? '', 'password' => $config['password'] ?? '', 'authType' => $authType, ]); $root = ltrim($config['root'] ?? '/', '/'); $adapter = new WebDAVAdapter($client, $root); return new Filesystem($adapter); } private function buildGoogleDrive(array $config): ?Filesystem { if (empty($config['client_id']) || empty($config['client_secret']) || empty($config['refresh_token'])) { throw new \InvalidArgumentException('Google Drive richiede client_id, client_secret e refresh_token per l\'autenticazione.'); } $client = new \Google_Client(); $client->setClientId($config['client_id']); $client->setClientSecret($config['client_secret']); $client->refreshToken($config['refresh_token']); $client->addScope(\Google_Service_Drive::DRIVE); $service = new \Google_Service_Drive($client); $adapter = new GoogleDriveAdapter($service, $config['root_folder_id'] ?? 'root'); return new Filesystem($adapter); } }