Add import/export and update system

Implement CSV/JSON import and export for domains, notification groups and tags (with masking for sensitive channel data), including size/format validation, in-memory CSV building, and logging. Add tag transfer and bulk transfer actions (admin-only). Introduce a new update system: Add UpdateController and UpdateService, migration 025_add_update_system_v1.1.3.sql, and installer changes to include the new migration and version handling; provide endpoints to check, apply, rollback and configure updates. Update helpers and UI bits: add getUpdateBadgeInfo in LayoutHelper, update notification icons/redirects, and add getMaxUploadSize in ViewHelper. Misc: add NotificationGroup::findByName, tweak .gitignore backups path, and update related views and routes.
This commit is contained in:
Hosteroid
2026-02-11 17:43:23 +02:00
parent 0c759cdd1d
commit 3688c8b71b
32 changed files with 4268 additions and 350 deletions

View File

@@ -22,6 +22,7 @@ use App\Models\Setting;
use App\Models\User;
use App\Services\WhoisService;
use App\Services\NotificationService;
use App\Services\UpdateService;
use Core\Database;
// Load environment variables
@@ -857,6 +858,42 @@ if ($stats['domains_with_notifications'] > 0) {
}
}
// Check for application updates (respects 6-hour cache) and notify admins if new version available
try {
$updateService = new UpdateService();
$updateResult = $updateService->checkForUpdate(false);
if (!empty($updateResult['error'])) {
logMessage("Update check skipped or failed: " . $updateResult['error']);
} elseif (!empty($updateResult['available'])) {
$currentVersion = $updateResult['current_version'];
$type = $updateResult['type'] ?? 'release';
$notifiedRelease = $settingModel->getValue('last_update_available_notified_release', '');
$notifiedHotfixSha = $settingModel->getValue('last_update_available_notified_hotfix_sha', '');
$shouldNotify = false;
if ($type === 'release') {
$latestVersion = $updateResult['latest_version'] ?? '';
if ($latestVersion !== '' && $latestVersion !== $notifiedRelease) {
$shouldNotify = true;
$settingModel->setValue('last_update_available_notified_release', $latestVersion);
}
} else {
$remoteSha = $updateResult['remote_sha'] ?? '';
if ($remoteSha !== '' && $remoteSha !== $notifiedHotfixSha) {
$shouldNotify = true;
$settingModel->setValue('last_update_available_notified_hotfix_sha', $remoteSha);
}
}
if ($shouldNotify) {
$label = ($type === 'release') ? ($updateResult['latest_version'] ?? 'latest') : 'hotfix';
$commitsBehind = $updateResult['commits_behind'] ?? null;
$notificationService->notifyAdminsUpdateAvailable($currentVersion, $label, $type, $commitsBehind);
logMessage("Update available (v{$currentVersion}{$label}): admins notified.");
}
}
} catch (\Throwable $e) {
logMessage("Update check error: " . $e->getMessage());
}
logMessage("==========================\n");
exit(0);