cf9cf50286
A key made by mistake on a server that is being restored left no way back: key:import and the passphrase route refused because a key existed, and nothing removed it. As long as the key never protected anything (no location created or adopted with it, no location or run in the database), occ backup:key:import --replace-unused-key and occ backup:target:add --replace-unused-key replace it, after the new key was opened. A key that was used is never replaced, also after its location was removed. The refusal names the option, and all administrators are notified of a replacement.
100 lines
6.1 KiB
PHP
100 lines
6.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
// SPDX-FileCopyrightText: 2026 Dillard Blom
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
namespace OCA\NgBackup\Notification;
|
|
|
|
use OCA\NgBackup\AppInfo\Application;
|
|
use OCP\IURLGenerator;
|
|
use OCP\L10N\IFactory;
|
|
use OCP\Notification\INotification;
|
|
use OCP\Notification\INotifier;
|
|
use OCP\Notification\UnknownNotificationException;
|
|
|
|
final class Notifier implements INotifier {
|
|
public function __construct(
|
|
private IFactory $l10n,
|
|
private IURLGenerator $url,
|
|
) {
|
|
}
|
|
|
|
public function getID(): string {
|
|
return Application::APP_ID;
|
|
}
|
|
|
|
public function getName(): string {
|
|
return $this->l10n->get(Application::APP_ID)->t('NG Backup');
|
|
}
|
|
|
|
public function prepare(INotification $notification, string $languageCode): INotification {
|
|
if ($notification->getApp() !== Application::APP_ID) {
|
|
throw new UnknownNotificationException();
|
|
}
|
|
$l = $this->l10n->get(Application::APP_ID, $languageCode);
|
|
$p = $notification->getSubjectParameters();
|
|
switch ($notification->getSubject()) {
|
|
case 'run_failed':
|
|
$notification->setParsedSubject($p['kind'] === 'restore'
|
|
? $l->t('Restore from %s failed', [$p['target']])
|
|
: $l->t('Backup to %s failed', [$p['target']]));
|
|
$notification->setParsedMessage((string)($p['error'] ?? ''));
|
|
break;
|
|
case 'run_warnings':
|
|
$notification->setParsedSubject($l->t('Backup to %1$s finished with warnings: %2$s unreadable, %3$s changed while being read', [$p['target'], $p['unreadable'], $p['changing']]));
|
|
$notification->setParsedMessage($l->t('Unreadable files and folders are missing from this backup (check their permissions). Files that kept changing were saved as they were while being read. Examples: %s', [$p['examples'] ?? '']));
|
|
break;
|
|
case 'run_bad_names':
|
|
$notification->setParsedSubject($l->n('Backup to %s finished, but %n item is missing because of its name', 'Backup to %s finished, but %n items are missing because of their names', (int)$p['count'], [$p['target']]));
|
|
$notification->setParsedMessage($l->t('Names with a backslash or a control character, or that are not valid UTF-8, are not supported, so these files and folders are not in this backup. Rename them; the next backup includes them. Examples: %s', [$p['examples'] ?? '']));
|
|
break;
|
|
case 'quota_warning':
|
|
$notification->setParsedSubject($l->t('Backup location %1$s is at %2$s%% of its limit (%3$s of %4$s)', [$p['target'], $p['percent'], $p['used'], $p['limit']]));
|
|
$notification->setParsedMessage($l->t('Backups stop when the limit is reached. Raise the limit, or let the retention policy remove older backups.'));
|
|
break;
|
|
case 'backup_stale':
|
|
// 'never' was stored by 0.9.4 and earlier
|
|
$notification->setParsedSubject(in_array($p['since'] ?? '', ['', 'never'], true)
|
|
? $l->t('No successful backup to %s yet', [$p['target']])
|
|
: $l->t('No successful backup to %1$s since %2$s', [$p['target'], $p['since']]));
|
|
$notification->setParsedMessage($l->t('Check the backup settings and the server log.'));
|
|
break;
|
|
case 'schedule_off':
|
|
$notification->setParsedSubject($l->t('Backup location %s has no schedule', [$p['target']]));
|
|
$notification->setParsedMessage(($p['others'] ?? '') === '1'
|
|
? $l->t('No backups run to this location until it gets a schedule or someone starts one. If that is what you want, you can ignore this reminder.')
|
|
: $l->t('No location has a schedule, so no backups run at all unless someone starts one. Set a schedule under Backups.'));
|
|
break;
|
|
case 'security_event':
|
|
$who = (string)($p['actor'] ?? '');
|
|
$notification->setParsedSubject(match ($p['event'] ?? '') {
|
|
'kit_downloaded' => $l->t('%s downloaded the backup recovery kit', [$who]),
|
|
'key_replaced' => $l->t('%1$s replaced the unused backup key %2$s by the key of existing backups, %3$s; download and confirm the new recovery kit', [$who, $p['old'] ?? '', $p['new'] ?? '']),
|
|
'target_removed' => $l->t('%1$s removed backup location %2$s', [$who, $p['target'] ?? '']),
|
|
'target_changed' => $l->t('%1$s changed the connection settings of backup location %2$s', [$who, $p['target'] ?? '']),
|
|
'schedule_off' => $l->t('%1$s turned off the schedule of backup location %2$s', [$who, $p['target'] ?? '']),
|
|
'append_only_off' =>$l->t('%1$s turned off append-only for backup location %2$s', [$who, $p['target'] ?? '']),
|
|
'retention_changed' => $l->t('%1$s changed the backup retention to %2$s', [$who, $p['policy'] ?? '']),
|
|
'snapshots_forgotten' => $l->t('%1$s moved %2$s snapshots of %3$s to the trash; they are deleted permanently after %4$s unless restored', [$who, $p['count'] ?? '', $p['target'] ?? '', $p['until'] ?? '']),
|
|
'snapshot_untrashed' => $l->t('%1$s restored snapshot %2$s of %3$s from the trash', [$who, $p['snapshot'] ?? '', $p['target'] ?? '']),
|
|
'catalog_trusted' => $l->t('%1$s accepted an older state of backup location %2$s (catalog generation %3$s)', [$who, $p['target'] ?? '', $p['generation'] ?? '']),
|
|
'slot_added' => $l->t('%1$s added backup passphrase slot %2$s (%3$s); download and confirm the new recovery kit', [$who, $p['slot'] ?? '', $p['label'] ?? '']),
|
|
'slot_replaced' => $l->t('%1$s set a new passphrase for backup key slot %2$s (%3$s); download and confirm the new recovery kit', [$who, $p['slot'] ?? '', $p['label'] ?? '']),
|
|
'user_export_retention_changed' => $l->t('%1$s changed how many exports per user are kept to %2$s', [$who, $p['keep'] ?? '']),
|
|
'user_exports_forgotten' => $l->t('%1$s removed %2$s per-user exports from %3$s', [$who, $p['count'] ?? '', $p['target'] ?? '']),
|
|
'slot_removed' => $l->t('%1$s removed backup passphrase slot %2$s; download and confirm the new recovery kit', [$who, $p['slot'] ?? '']),
|
|
default => $l->t('NG Backup security event'),
|
|
});
|
|
$notification->setParsedMessage($l->t('If this was not you or another administrator, check who has admin access.'));
|
|
break;
|
|
default:
|
|
throw new UnknownNotificationException();
|
|
}
|
|
$notification->setLink($this->url->linkToRouteAbsolute('settings.AdminSettings.index', ['section' => 'ng_backup']));
|
|
$notification->setIcon($this->url->getAbsoluteURL($this->url->imagePath(Application::APP_ID, 'app-dark.svg')));
|
|
return $notification;
|
|
}
|
|
}
|