From 483c3f5a284b46c0b26e3083a8805fa28f39215a Mon Sep 17 00:00:00 2001 From: Matthew White Date: Wed, 21 Dec 2022 19:34:23 -0500 Subject: [PATCH] Remove Google Drive backups See getodk/central#323. --- karma.conf.js | 1 - src/components/analytics/metrics-table.vue | 1 - src/components/backup/deprecation.vue | 78 ---- src/components/backup/list.vue | 146 ------ src/components/backup/status.vue | 503 --------------------- src/components/backup/terminate.vue | 147 ------ src/components/system/home.vue | 6 - src/config.js | 2 - src/locales/en.json5 | 5 +- src/request-data/backups.js | 21 - src/routes.js | 17 - src/util/load-async.js | 4 - test/components/audit/table.spec.js | 15 - test/components/backup/deprecation.spec.js | 37 -- test/components/backup/list.spec.js | 31 -- test/components/backup/status.spec.js | 214 --------- test/components/backup/terminate.spec.js | 72 --- test/components/system/home.spec.js | 22 +- test/data/audits.js | 36 -- test/data/configs.js | 7 +- test/router.spec.js | 17 - test/unit/request.spec.js | 16 +- test/util/http/data.js | 7 - transifex/strings_en.json | 117 +---- 24 files changed, 12 insertions(+), 1510 deletions(-) delete mode 100644 src/components/backup/deprecation.vue delete mode 100644 src/components/backup/list.vue delete mode 100644 src/components/backup/status.vue delete mode 100644 src/components/backup/terminate.vue delete mode 100644 src/request-data/backups.js delete mode 100644 test/components/backup/deprecation.spec.js delete mode 100644 test/components/backup/list.spec.js delete mode 100644 test/components/backup/status.spec.js delete mode 100644 test/components/backup/terminate.spec.js diff --git a/karma.conf.js b/karma.conf.js index 3f299be60..fc879f9e1 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -31,7 +31,6 @@ module.exports = (config) => { proxies: { '/fonts/': '/base/public/fonts/', '/blank.html': '/base/public/blank.html', - '/v1/backup': '/base/public/blank.html', '/test/files/': '/base/test/files/' }, preprocessors: { diff --git a/src/components/analytics/metrics-table.vue b/src/components/analytics/metrics-table.vue index 405cb76c9..6ab6358ba 100644 --- a/src/components/analytics/metrics-table.vue +++ b/src/components/analytics/metrics-table.vue @@ -76,7 +76,6 @@ export default { "num_unique_managers": "Number of unique Project Managers", "num_unique_viewers": "Number of unique Project Viewers", "num_unique_collectors": "Number of unique Data Collectors", - "backups_configured": "Backups configured", "database_size": "System database size", "uses_external_db": "Server uses an external database", "num_managers": "Number of Project Managers", diff --git a/src/components/backup/deprecation.vue b/src/components/backup/deprecation.vue deleted file mode 100644 index fc56742e1..000000000 --- a/src/components/backup/deprecation.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - -{ - "en": { - "text": "On January 31st, 2023, backups to Google Drive will stop working." - } -} - - - - -{ - "cs": { - "text": "31. ledna 2023 přestane fungovat zálohování na Disk Google." - }, - "fr": { - "text": "Le 31 janvier 2023, les sauvegardes sur Google Drive cesseront de fonctionner" - }, - "it": { - "text": "Il 31 gennaio 2023 i backup su Google Drive smetteranno di funzionare." - } -} - diff --git a/src/components/backup/list.vue b/src/components/backup/list.vue deleted file mode 100644 index 3ab1128b9..000000000 --- a/src/components/backup/list.vue +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - -{ - "en": { - // This is a title shown above a section of the page. - "auditsTitle": "Latest Backups", - "alert": { - "terminate": "Your automatic backups were terminated." - } - } -} - - - - -{ - "cs": { - "auditsTitle": "Nejnovější zálohy", - "alert": { - "terminate": "Vaše automatické zálohování je ukončeno." - } - }, - "de": { - "auditsTitle": "Letzte Sicherheitskopien" - }, - "es": { - "auditsTitle": "Últimas copias de seguridad" - }, - "fr": { - "auditsTitle": "Dernières Sauvegardes", - "alert": { - "terminate": "Vos sauvegardes automatiques ont été interrompues." - } - }, - "id": { - "auditsTitle": "Data Cadangan Terakhir" - }, - "it": { - "auditsTitle": "Ultimo backup", - "alert": { - "terminate": "I tuoi backup automatici sono stati interrotti." - } - }, - "ja": { - "auditsTitle": "最新のバックアップ" - }, - "sw": { - "auditsTitle": "Hifadhi Nakala za Hivi Punde" - } -} - diff --git a/src/components/backup/status.vue b/src/components/backup/status.vue deleted file mode 100644 index 98f53a398..000000000 --- a/src/components/backup/status.vue +++ /dev/null @@ -1,503 +0,0 @@ - - - - - - - - -{ - "en": { - "getHelp": { - "full": "If you are having trouble, please try the {forum}.", - "forum": "community forum" - }, - "notConfigured": [ - "Backups are not configured.", - "In earlier versions of ODK Central, it was possible to set up automatic backups to Google Drive. That feature has been deprecated, but there are other ways to back up the data on the server. We strongly recommend that all users back up their data." - ], - "neverRun": [ - "The configured backup has not yet run.", - "If you have configured backups within the last couple of days, this is normal. Otherwise, something has gone wrong.", - "In that case, the most likely fix is to restart the service." - ], - "somethingWentWrong": [ - "Something is wrong!", - { - "full": "The latest backup that completed successfully was {moreThanThreeDaysAgo}.", - "moreThanThreeDaysAgo": "more than three days ago" - }, - "The most likely fix is to restart the service." - ], - "success": [ - // This text is displayed if the latest backup attempt was successful. It indicates that the backup process is working. - "Backup is working.", - // {dateTime} shows the date and time at which the last backup completed, - // for example: "2020/01/01 01:23". It may show a formatted date like - // "2020/01/01", or it may use a word like "today", "yesterday", or - // "Sunday". {dateTime} is formatted in bold. - "The last backup completed successfully {dateTime}." - ], - "action": { - "download": "Download backup now", - "terminate": "Terminate" - }, - "alert": { - "download": "The backup is running now, and will be encrypted and downloaded to your computer. This may take a while. Once the download begins, you can leave this page." - } - } -} - - - - -{ - "cs": { - "getHelp": { - "full": "Pokud máte potíže, zkuste prosím {forum}.", - "forum": "komunitní fórum" - }, - "notConfigured": [ - "Zálohy nejsou nakonfigurovány.", - "V dřívějších verzích ODK Central bylo možné nastavit automatické zálohování na Disk Google. Tato funkce byla zrušena, ale existují jiné způsoby zálohování dat na serveru. Všem uživatelům důrazně doporučujeme, aby si svá data zálohovali." - ], - "neverRun": [ - "Nakonfigurované zálohování dosud nebylo spuštěno.", - "Pokud jste nakonfigurovali zálohování v posledních několika dnech, je to normální. Jinak se něco pokazilo.", - "V takovém případě je nejpravděpodobnější opravou restartování služby." - ], - "somethingWentWrong": [ - "Něco je špatně!", - { - "full": "Poslední úspěšná záloha byla {moreThanThreeDaysAgo}.", - "moreThanThreeDaysAgo": "před více než třemi dny" - }, - "Nejpravděpodobnější opravou je restartování služby." - ], - "success": [ - "Zálohování funguje.", - "Poslední záloha byla úspěšně dokončena {dateTime}." - ], - "action": { - "download": "Stáhnout zálohu hned", - "terminate": "Ukončit" - }, - "alert": { - "download": "Záloha nyní běží a bude šifrována a stažena do vašeho počítače. Může to chvíli trvat. Jakmile začne stahování, můžete tuto stránku opustit." - } - }, - "de": { - "getHelp": { - "full": "Wenn es nicht funktioniert, fragen Sie im {forum} nach.", - "forum": "Community-Forum" - }, - "notConfigured": [ - "Sicherungskopien sind nicht konfiguriert." - ], - "neverRun": [ - "Die konfigurierte Sicherung ist wurde noch nicht ausgeführt.", - "Wenn Sie die Sicherungen in den letzten Tagen konfiguriert haben, ist dies normal. Wenn nicht, ist irgendetwas schief gegangen." - ], - "somethingWentWrong": [ - "Irgendetwas hat da nicht geklappt.", - { - "full": "Die letzte vollständige Sicherung wurde {moreThanThreeDaysAgo} ausgeführt.", - "moreThanThreeDaysAgo": "vor mehr als drei Tagen." - } - ], - "success": [ - "Die Sicherung wird gerade erstellt.", - "Die letzte Sicherungskopie wurde erstellt: {dateTime}" - ], - "action": { - "download": "Backup jetzt herunterladen", - "terminate": "Beenden" - }, - "alert": { - "download": "Das Backup läuft jetzt und wird verschlüsselt und auf Ihren Computer geladen. Das wird eine Weile dauern. Sobald der Download begonnen hat, können Sie diese Seite verlassen." - } - }, - "es": { - "getHelp": { - "full": "Si tiene problemas, pruebe el {forum}.", - "forum": "foro de la comunidad" - }, - "notConfigured": [ - "Las copias de seguridad no están configuradas." - ], - "neverRun": [ - "La copia de seguridad configurada aún no se ha ejecutado.", - "Si ha configurado copias de seguridad en los últimos días, esto es normal. De lo contrario, algo ha salido mal." - ], - "somethingWentWrong": [ - "¡Algo está mal!", - { - "full": "La última copia de seguridad que se completó correctamente fue {moreThanThreeDaysAgo}.", - "moreThanThreeDaysAgo": "hace más de tres días" - } - ], - "success": [ - "La copia de seguridad está funcionando", - "Última copia de seguridad completada con éxito {dateTime}" - ], - "action": { - "download": "Descargar copia de seguridad ahora", - "terminate": "Terminar" - }, - "alert": { - "download": "La copia de seguridad se está ejecutando ahora y se cifrará y descargará en su computadora. Esto puede tardar un rato. Una vez que comience la descarga, puede salir de esta página" - } - }, - "fr": { - "getHelp": { - "full": "Si vous rencontrez des difficultés, merci de consulter le {forum}.", - "forum": "forum de la communauté" - }, - "notConfigured": [ - "Sauvegarde non configuré", - "Dans les versions précédentes d'ODK Central, il était possible de mettre en place des sauvegardes automatiques sur Google Drive. Cette fonctionnalité est dépréciée, mais il y a d'autres moyens de sauvegarder les données du serveur. Nous recommandons fortement à tous les utilisateurs de sauvegarder leurs données." - ], - "neverRun": [ - "La sauvegarde configurée n'a pas encore été lancée.", - "Si vous avez configuré des sauvegardes au cours des deux derniers jours, c'est normal. Sinon, quelque-chose s'est mal passé.", - "Dans ce cas, la solution la plus probable consiste à redémarrer le service." - ], - "somethingWentWrong": [ - "Quelque-chose ne va pas.", - { - "full": "La dernière sauvegarde correctement terminée était {moreThanThreeDaysAgo}.", - "moreThanThreeDaysAgo": "plus de trois jours auparavant." - }, - "La solution la plus probable consiste à redémarrer le service." - ], - "success": [ - "La sauvegarde fonctionne.", - "La dernière sauvegarde correctement exécutée {dateTime}." - ], - "action": { - "download": "Télécharger la sauvegarde maintenant", - "terminate": "Terminer" - }, - "alert": { - "download": "La sauvegarde est en cours, elle sera chiffrée et téléchargée sur votre ordinateur. Cela peut prendre un peu de temps. Une fois démarré le téléchargement, vous pourrez quitter cette page." - } - }, - "id": { - "getHelp": { - "full": "Apabila Anda memiliki kesulitan, silakan kunjungi {forum}.", - "forum": "Forum komunitas" - }, - "notConfigured": [ - "Data cadangan tidak terkonfigurasi." - ], - "neverRun": [ - "Data candangan yang dikonfigurasi belum berjalan.", - "Hal ini adalah normal ppabila Anda memiliki data cadangan yang telah dikonfigurasi dalam beberapa hari terakhir. Jika tidak, terjadi sebuah kesalahan." - ], - "somethingWentWrong": [ - "Terjadi kesalahan!", - { - "full": "Data cadangan terakhir yang sukses dibuat adalah {moreThanThreeDaysAgo}.", - "moreThanThreeDaysAgo": "lebih dari tiga hari yang lalu" - } - ], - "success": [ - "Data cadangan telah berfungsi.", - "Data cadangan terakhir telah sukses dibuat {dateTime}." - ], - "action": { - "download": "Unduh cadangan sekarang", - "terminate": "Putuskan" - }, - "alert": { - "download": "Pencadangan sedang berlangsung dan akan dienkripsi selanjutnya diunduh ke komputermu. Perlu waktu beberapa saat. Saat pengunduhan dimulai, kamu bisa meninggalkan laman ini." - } - }, - "it": { - "getHelp": { - "full": "Se hai problemi, consulta il {forum}.", - "forum": "forum comunitario" - }, - "notConfigured": [ - "I backup non sono configurati.", - "Nelle versioni precedenti di ODK Central era possibile impostare backup automatici su Google Drive. Questa funzionalità è stata deprecata, ma esistono altri modi per eseguire il backup dei dati sul server. Consigliamo vivamente a tutti gli utenti di eseguire il backup dei propri dati." - ], - "neverRun": [ - "Il backup configurato non è ancora stato eseguito.", - "Se hai configurato i backup negli ultimi due giorni, è normale. Altrimenti qualcosa è andato storto.", - "In tal caso, la soluzione più probabile è riavviare il servizio." - ], - "somethingWentWrong": [ - "Qualcosa non funziona!", - { - "full": "L'ultimo backup completato con successo è stato {moreThanThreeDaysAgo}.", - "moreThanThreeDaysAgo": "più di tre giorni fa" - }, - "La soluzione più probabile è riavviare il servizio." - ], - "success": [ - "Il Backup sta funzionando.", - "L'ultimo backup è stato completato con successo {dateTime}." - ], - "action": { - "download": "Scarica il backup ora", - "terminate": "Terminare" - }, - "alert": { - "download": "Il backup è ora in esecuzione e verrà crittografato e scaricato sul tuo computer. L'operazione potrebbe richiedere del tempo. Una volta avviato il download, puoi lasciare questa pagina." - } - }, - "ja": { - "getHelp": { - "full": "問題がある場合、{forum}を確認して下さい。", - "forum": "コミュニティーフォーラム" - }, - "notConfigured": [ - "バックアップは設定されていません。" - ], - "neverRun": [ - "設定されたバックアップは未実行です。", - "ここ数日の間にバックアップの設定をしたのならば、これは正常です。そうでない場合は、何か問題が起きています。" - ], - "somethingWentWrong": [ - "何か問題があります!", - { - "full": "最終のバックアップは、{moreThanThreeDaysAgo}に正常に完了しています。", - "moreThanThreeDaysAgo": "3日以上前" - } - ], - "success": [ - "バックアップしています。", - "{dateTime}に最新のバックアップは成功しています。" - ], - "action": { - "download": "今すぐバックアップをダウンロード", - "terminate": "停止" - }, - "alert": { - "download": "現在、バックアップが実行中です。バックアップデータは暗号化され、あなたのコンピュータにダウンロードされます。処理にしばらく時間がかかります。ダウンロードが始まると、このページを閉じても構いません。" - } - }, - "sw": { - "getHelp": { - "full": "Ikiwa unatatizika, tafadhali jaribu {forum}.", - "forum": "jamii forum" - }, - "notConfigured": [ - "Hifadhi rudufu hazijasanidiwa." - ], - "neverRun": [ - "Hifadhi rudufu iliyosanidiwa bado haijatekelezwa", - "Ikiwa umesanidi nakala rudufu ndani ya siku chache zilizopita, hii ni kawaida. Vinginevyo, kitu kimeenda vibaya." - ], - "somethingWentWrong": [ - "Kuna kitu hakiko sawa", - { - "full": "Hifadhi rudufu ya hivi punde iliyokamilika kwa ufanisi ilikuwa {moreThanThreeDaysAgo}.", - "moreThanThreeDaysAgo": "zaidi ya siku tatu zilizopita" - } - ], - "success": [ - "Hifadhi rudufu inafanya kazi.", - "Hifadhi rudufu ya mwisho ilikamilika {dateTime}." - ], - "action": { - "download": "Pakua nakala rudufu sasa", - "terminate": "Sitisha" - }, - "alert": { - "download": "Hifadhi rudufu inaendelea sasa, na itasimbwa kwa njia fiche na kupakuliwa kwenye kompyuta yako. Hii inaweza kuchukua muda. Mara tu upakuaji unapoanza, unaweza kuondoka kwenye ukurasa huu." - } - } -} - diff --git a/src/components/backup/terminate.vue b/src/components/backup/terminate.vue deleted file mode 100644 index 684b4bef1..000000000 --- a/src/components/backup/terminate.vue +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - -{ - "en": { - // This is the title at the top of a pop-up. - "title": "Terminate Automatic Backups", - "introduction": [ - "Are you sure you want to terminate your automatic backups?", - "If you terminate your automatic backups, you will not be able to start them again. Automatic backups are a deprecated feature, but there are other ways to back up the data on the server." - ] - } -} - - - - -{ - "cs": { - "title": "Ukončit automatické zálohování", - "introduction": [ - "Opravdu chcete ukončit automatické zálohování?", - "Pokud automatické zálohování ukončíte, nebude možné je znovu spustit. Automatické zálohování je zastaralá funkce, ale existují jiné způsoby zálohování dat na serveru." - ] - }, - "de": { - "title": "Automatische Sicherungskopien beenden", - "introduction": [ - "Sind Sie sicher, dass Sie die automatischen Sicherungskopien beenden möchten?" - ] - }, - "es": { - "title": "Terminar copias de seguridad automáticas", - "introduction": [ - "¿Está seguro que quiere terminar sus copias de seguridad automáticas?" - ] - }, - "fr": { - "title": "Terminer les Sauvegardes Automatiques", - "introduction": [ - "Êtes-vous sûr de vouloir mettre fin à vos sauvegardes automatiques ?", - "Si vous interrompez vos sauvegardes automatiques, vous ne pourrez plus les redémarrer. Les sauvegardes automatiques est une fonctionnalité dépréciée, mais il y a d'autres moyens de sauvegarder les données du serveur." - ] - }, - "id": { - "title": "Putuskan Data Cadangan Otomatis", - "introduction": [ - "Apakah Anda yakin ingin memutus data cadangan otomatis?" - ] - }, - "it": { - "title": "Termina i backup automatici", - "introduction": [ - "Sei sicuro di voler terminare i tuoi backup automatici?", - "Se interrompi i backup automatici, non sarai in grado di riavviarli. I backup automatici sono una funzionalità deprecata, ma esistono altri modi per eseguire il backup dei dati sul server." - ] - }, - "ja": { - "title": "自動バックアップの停止", - "introduction": [ - "自動バックアップを本当に停止しますか?" - ] - }, - "sw": { - "title": "Sitisha Hifadhi Nakala za Kiotomatiki", - "introduction": [ - "Je, una uhakika kuwa ungependa kusitisha hifadhi rudufu zako otomatiki?" - ] - } -} - diff --git a/src/components/system/home.vue b/src/components/system/home.vue index 136ab4ff3..9db7f15b5 100644 --- a/src/components/system/home.vue +++ b/src/components/system/home.vue @@ -25,12 +25,6 @@ except according to the terms contained in the LICENSE file. {{ $t('systemHome.tab.analytics') }} -
  • - - {{ $t('systemHome.tab.backups') }} - -
  • diff --git a/src/config.js b/src/config.js index 7bbb7b04d..8af8bf5b3 100644 --- a/src/config.js +++ b/src/config.js @@ -10,8 +10,6 @@ including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file. */ export default { - // `true` to allow navigation to /system/backups and `false` not to. - showsBackups: true, // `true` to allow navigation to /system/analytics and `false` not to. showsAnalytics: true, home: { diff --git a/src/locales/en.json5 b/src/locales/en.json5 index 593bbfe0b..7c0cfe894 100644 --- a/src/locales/en.json5 +++ b/src/locales/en.json5 @@ -31,10 +31,9 @@ } }, "systemHome": { - // This is the title of the page for managing backups, audit logs, and other system-level functions. + // This is the title of the page for audit logs and other system-level functions. "title": "System Management", "tab": { - "backups": "Backups", "audits": "Server Audit Logs", "analytics": "Usage Reporting" } @@ -95,8 +94,6 @@ }, // This is shown in the log of actions performed on the server. "analytics": "Report Usage", - // This is shown in the log of actions performed on the server. - "backup": "Backup", // This is shown in the log of actions performed on the server. It is a // type of action that can be taken on a Server Configuration. "config": { diff --git a/src/request-data/backups.js b/src/request-data/backups.js deleted file mode 100644 index df4421112..000000000 --- a/src/request-data/backups.js +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2022 ODK Central Developers -See the NOTICE file at the top-level directory of this distribution and at -https://github.com/getodk/central-frontend/blob/master/NOTICE. - -This file is part of ODK Central. It is subject to the license terms in -the LICENSE file found in the top-level directory of this distribution and at -https://www.apache.org/licenses/LICENSE-2.0. No part of ODK Central, -including this file, may be copied, modified, propagated, or distributed -except according to the terms contained in the LICENSE file. -*/ -import { noargs } from '../util/util'; -import { setupOption } from './util'; -import { useRequestData } from './index'; - -export default () => { - const { createResource } = useRequestData(); - const backupsConfig = createResource('backupsConfig', noargs(setupOption)); - const audits = createResource('audits'); - return { backupsConfig, audits }; -}; diff --git a/src/routes.js b/src/routes.js index 843c38b5c..eb6e05fb9 100644 --- a/src/routes.js +++ b/src/routes.js @@ -548,23 +548,6 @@ const routes = [ loading: 'page', key: () => '/system', children: [ - asyncRoute({ - path: 'backups', - component: 'BackupList', - loading: 'tab', - meta: { - validateData: { - currentUser: () => currentUser.can([ - 'config.read', - 'config.set', - 'backup.run', - 'audit.read' - ]) - }, - title: () => [i18n.t('systemHome.tab.backups'), i18n.t('systemHome.title')] - }, - beforeEnter: () => (config.showsBackups ? true : '/') - }), asyncRoute({ path: 'audits', component: 'AuditList', diff --git a/src/util/load-async.js b/src/util/load-async.js index d85afae00..6e218a825 100644 --- a/src/util/load-async.js +++ b/src/util/load-async.js @@ -55,10 +55,6 @@ const loaders = new Map() /* webpackChunkName: "component-audit-list" */ '../components/audit/list.vue' ))) - .set('BackupList', loader(() => import( - /* webpackChunkName: "component-backup-list" */ - '../components/backup/list.vue' - ))) .set('DatasetList', loader(() => import( /* webpackChunkName: "component-dataset-list" */ '../components/dataset/list.vue' diff --git a/test/components/audit/table.spec.js b/test/components/audit/table.spec.js index 636939e95..de8d7714d 100644 --- a/test/components/audit/table.spec.js +++ b/test/components/audit/table.spec.js @@ -345,21 +345,6 @@ describe('AuditTable', () => { testTarget(row, ''); }); - it('renders a backup audit correctly', () => { - testData.standardConfigs.createPast(1, { - key: 'backups', - value: { type: 'google' }, - setAt: ago({ days: 2 }).toISO() - }); - testData.standardAudits.createBackupAudit({ - success: true, - loggedAt: ago({ days: 1 }).toISO() - }); - const row = mountComponent(); - testType(row, ['Backup']); - testTarget(row, ''); - }); - it('renders an analytics audit correctly', () => { testData.extendedAudits.createPast(1, { action: 'analytics' }); const row = mountComponent(); diff --git a/test/components/backup/deprecation.spec.js b/test/components/backup/deprecation.spec.js deleted file mode 100644 index c67c6987e..000000000 --- a/test/components/backup/deprecation.spec.js +++ /dev/null @@ -1,37 +0,0 @@ -import BackupDeprecation from '../../../src/components/backup/deprecation.vue'; - -import useBackups from '../../../src/request-data/backups'; - -import testData from '../../data'; -import { mergeMountOptions, mount } from '../../util/lifecycle'; -import { mockResponse } from '../../util/axios'; -import { testRequestData } from '../../util/request-data'; - -const mountComponent = (options) => - mount(BackupDeprecation, mergeMountOptions(options, { - container: { requestData: testRequestData([useBackups]) } - })); - -describe('BackupDeprecation', () => { - it('renders if backups are configured', () => { - testData.standardConfigs.createPast(1, { - key: 'backups', - value: { type: 'google' } - }); - const component = mountComponent({ - container: { - requestData: { backupsConfig: testData.standardConfigs.forKey('backups') } - } - }); - component.find('*').exists().should.be.true(); - }); - - it('does not render if backups are not configured', () => { - const component = mountComponent({ - container: { - requestData: { backupsConfig: mockResponse.problem(404.1) } - } - }); - component.find('*').exists().should.be.false(); - }); -}); diff --git a/test/components/backup/list.spec.js b/test/components/backup/list.spec.js deleted file mode 100644 index c03843e44..000000000 --- a/test/components/backup/list.spec.js +++ /dev/null @@ -1,31 +0,0 @@ -import AuditTable from '../../../src/components/audit/table.vue'; - -import testData from '../../data'; -import { ago } from '../../../src/util/date-time'; -import { load } from '../../util/http'; -import { mockLogin } from '../../util/session'; - -describe('BackupList', () => { - beforeEach(mockLogin); - - it('sends the correct initial requests', () => - load('/system/backups', { root: false }).testRequests([ - { url: '/v1/config/backups' }, - { url: '/v1/audits?action=backup&limit=10' } - ])); - - it('renders a table if there are audit log entries', () => { - testData.extendedAudits.createBackupAudit({ - success: false, - loggedAt: ago({ days: 1 }).toISO() - }); - return load('/system/backups', { root: false }).then(component => { - component.findComponent(AuditTable).exists().should.be.true(); - }); - }); - - it('does not render a table if there are no audit log entries', () => - load('/system/backups', { root: false }).then(component => { - component.findComponent(AuditTable).exists().should.be.false(); - })); -}); diff --git a/test/components/backup/status.spec.js b/test/components/backup/status.spec.js deleted file mode 100644 index c46be2bed..000000000 --- a/test/components/backup/status.spec.js +++ /dev/null @@ -1,214 +0,0 @@ -import BackupStatus from '../../../src/components/backup/status.vue'; -import DateTime from '../../../src/components/date-time.vue'; -import Spinner from '../../../src/components/spinner.vue'; - -import useBackups from '../../../src/request-data/backups'; -import { ago } from '../../../src/util/date-time'; - -import testData from '../../data'; -import { load } from '../../util/http'; -import { mockLogin } from '../../util/session'; -import { mockResponse } from '../../util/axios'; -import { mount } from '../../util/lifecycle'; -import { testRequestData } from '../../util/request-data'; - -const mountComponent = () => { - const config = testData.standardConfigs.forKey('backups'); - return mount(BackupStatus, { - container: { - requestData: testRequestData([useBackups], { - backupsConfig: config != null ? config : mockResponse.problem(404.1), - audits: testData.standardAudits.sorted() - }) - } - }); -}; -const assertContent = (component, iconClass, title, buttonText) => { - component.get('#backup-status-icon').classes(iconClass).should.be.true(); - - const status = component.get('#backup-status'); - status.get('p').text().should.equal(title); - - if (buttonText == null) - status.find('button').exists().should.be.false(); - else - status.get('button').text().should.equal(buttonText); -}; - -describe('BackupStatus', () => { - beforeEach(mockLogin); - - it('renders correctly if backups are not configured', () => { - assertContent( - mountComponent(), - 'icon-question-circle', - 'Backups are not configured.', - null - ); - }); - - it('renders correctly if the latest recent attempt was a success', () => { - testData.standardConfigs.createPast(1, { - key: 'backups', - value: { type: 'google' }, - setAt: ago({ days: 4 }).toISO() - }); - testData.extendedAudits.createBackupAudit({ - success: true, - loggedAt: ago({ days: 2 }).toISO() - }); - const component = mountComponent(); - assertContent( - component, - 'icon-check-circle', - 'Backup is working.', - 'Terminate…' - ); - - const { loggedAt } = testData.extendedAudits.last(); - component.getComponent(DateTime).props().iso.should.equal(loggedAt); - }); - - it('renders correctly if the latest recent attempt was a failure', () => { - testData.standardConfigs.createPast(1, { - key: 'backups', - value: { type: 'google' }, - setAt: ago({ days: 2 }).toISO() - }); - testData.extendedAudits.createBackupAudit({ - success: false, - loggedAt: ago({ days: 1 }).toISO() - }); - assertContent( - mountComponent(), - 'icon-times-circle', - 'Something is wrong!', - 'Terminate…' - ); - }); - - describe('no recent attempt for the current config', () => { - it('renders correctly if the config was recently set up', () => { - testData.standardConfigs.createPast(1, { - key: 'backups', - value: { type: 'google' }, - setAt: ago({ days: 2 }).toISO() - }); - assertContent( - mountComponent(), - 'icon-check-circle', - 'The configured backup has not yet run.', - 'Terminate…' - ); - }); - - it('renders correctly if latest attempt was a recent failure for previous config', () => { - testData.standardConfigs.createPast(1, { - key: 'backups', - value: { type: 'google' }, - setAt: ago({ days: 1 }).toISO() - }); - testData.extendedAudits.createBackupAudit({ - success: false, - loggedAt: ago({ days: 2 }).toISO() - }); - assertContent( - mountComponent(), - 'icon-check-circle', - 'The configured backup has not yet run.', - 'Terminate…' - ); - }); - - it('renders correctly if the config was not recently set up', () => { - testData.standardConfigs.createPast(1, { - key: 'backups', - value: { type: 'google' }, - setAt: ago({ days: 4 }).toISO() - }); - assertContent( - mountComponent(), - 'icon-times-circle', - 'Something is wrong!', - 'Terminate…' - ); - }); - - it('renders correctly if latest non-recent attempt was a success', () => { - testData.standardConfigs.createPast(1, { - key: 'backups', - value: { type: 'google' }, - setAt: ago({ days: 5 }).toISO() - }); - testData.extendedAudits.createBackupAudit({ - success: true, - loggedAt: ago({ days: 4 }).toISO() - }); - assertContent( - mountComponent(), - 'icon-times-circle', - 'Something is wrong!', - 'Terminate…' - ); - }); - }); - - describe('download link', () => { - beforeEach(() => { - testData.standardConfigs.createPast(1, { - key: 'backups', - value: { type: 'google' }, - setAt: ago({ days: 1 }).toISO() - }); - }); - - it('renders the link if backups are configured', () => { - mountComponent().find('[href="/v1/backup"]').exists().should.be.true(); - }); - - describe('after the link is clicked', () => { - let defaultPrevented; - const handler = (event) => { - defaultPrevented = event.defaultPrevented; - event.preventDefault(); - }; - before(() => { - document.addEventListener('click', handler); - }); - after(() => { - document.removeEventListener('click', handler); - }); - - it('shows a success alert', async () => { - const app = await load('/system/backups', { attachTo: document.body }); - await app.get('#backup-status [href="/v1/backup"]').trigger('click'); - app.should.alert('success'); - }); - - it('disables the link', async () => { - const app = await load('/system/backups', { attachTo: document.body }); - const a = app.get('#backup-status [href="/v1/backup"]'); - await a.trigger('click'); - a.classes('disabled').should.be.true(); - }); - - it('prevents default if it is clicked again', async () => { - const app = await load('/system/backups', { attachTo: document.body }); - const a = app.get('#backup-status [href="/v1/backup"]'); - await a.trigger('click'); - defaultPrevented.should.be.false(); - a.trigger('click'); - defaultPrevented.should.be.true(); - }); - - it('shows a spinner', async () => { - const app = await load('/system/backups', { attachTo: document.body }); - const component = app.getComponent(BackupStatus); - const spinner = component.getComponent(Spinner); - spinner.props().state.should.be.false(); - await component.get('[href="/v1/backup"]').trigger('click'); - spinner.props().state.should.be.true(); - }); - }); - }); -}); diff --git a/test/components/backup/terminate.spec.js b/test/components/backup/terminate.spec.js deleted file mode 100644 index b38648b9e..000000000 --- a/test/components/backup/terminate.spec.js +++ /dev/null @@ -1,72 +0,0 @@ -import BackupTerminate from '../../../src/components/backup/terminate.vue'; - -import testData from '../../data'; -import { load, mockHttp } from '../../util/http'; -import { mockLogin } from '../../util/session'; - -describe('BackupTerminate', () => { - beforeEach(mockLogin); - - it('toggles the modal', () => { - testData.standardConfigs.createPast(1, { - key: 'backups', - value: { type: 'google' } - }); - return load('/system/backups', { root: false }).testModalToggles({ - modal: BackupTerminate, - show: '#backup-status button', - hide: '.btn-link' - }); - }); - - it('sends the correct request', () => - mockHttp() - .mount(BackupTerminate, { - props: { state: true } - }) - .request(modal => modal.get('.btn-danger').trigger('click')) - .respondWithProblem() - .testRequests([{ method: 'DELETE', url: '/v1/config/backups' }])); - - it('implements some standard button things', () => - mockHttp() - .mount(BackupTerminate, { - props: { state: true } - }) - .testStandardButton({ - button: '.btn-danger', - disabled: ['.btn-link'], - modal: true - })); - - describe('after a successful response', () => { - const submit = () => { - testData.standardConfigs.createPast(1, { - key: 'backups', - value: { type: 'google' } - }); - return load('/system/backups', { root: false }) - .complete() - .request(async (component) => { - await component.get('#backup-status button').trigger('click'); - return component.get('#backup-terminate .btn-danger').trigger('click'); - }) - .respondWithSuccess(); - }; - - it('hides the modal', async () => { - const component = await submit(); - component.getComponent(BackupTerminate).props().state.should.be.false(); - }); - - it('updates the backups status', async () => { - const component = await submit(); - component.vm.backupsConfig.isEmpty().should.be.true(); - }); - - it('shows a success alert', async () => { - const component = await submit(); - component.should.alert('success'); - }); - }); -}); diff --git a/test/components/system/home.spec.js b/test/components/system/home.spec.js index e62dc99d1..63ce7462a 100644 --- a/test/components/system/home.spec.js +++ b/test/components/system/home.spec.js @@ -16,17 +16,7 @@ describe('SystemHome', () => { }); const links = component.getComponent(PageHead).findAllComponents(RouterLinkStub); const to = links.map(link => link.props().to); - to.should.eql(['/system/audits', '/system/analytics', '/system/backups']); - }); - - it('hides the Backups tab if the showsBackups config is false', () => { - const component = mount(SystemHome, { - container: { - router: mockRouter('/system/audits'), - config: { showsBackups: false } - } - }); - component.get('#page-head-tabs li:last-child').should.be.hidden(); + to.should.eql(['/system/audits', '/system/analytics']); }); it('hides "Usage Reporting" tab if showsAnalytics config is false', () => { @@ -40,16 +30,6 @@ describe('SystemHome', () => { }); describe('active tab', () => { - it('activates correct tab after user navigates to .../backups', () => { - const component = mount(SystemHome, { - container: { router: mockRouter('/system/backups') } - }); - const links = component.getComponent(PageHead).findAllComponents(RouterLinkStub) - .filter(link => (link.element.closest('.active') != null)); - links.length.should.equal(1); - links[0].props().to.should.equal('/system/backups'); - }); - it('activates correct tab after user navigates to .../audits', () => { const component = mount(SystemHome, { container: { router: mockRouter('/system/audits') } diff --git a/test/data/audits.js b/test/data/audits.js index 5d6144dd3..5e8d9df89 100644 --- a/test/data/audits.js +++ b/test/data/audits.js @@ -4,7 +4,6 @@ import { dataStore, view } from './data-store'; import { extendedForms } from './forms'; import { extendedUsers } from './users'; import { fakePastDate, isBefore } from '../util/date-time'; -import { standardConfigs } from './configs'; import { toActor } from './actors'; const actionsWithDefaultActor = new Set([ @@ -68,38 +67,3 @@ export const standardAudits = view( auditsWithCreatedAt, omit(['actor', 'actee', 'createdAt']) ); - -function createBackupAudit({ success, configSetAt = undefined, loggedAt }) { - if (loggedAt == null) throw new Error('invalid loggedAt'); - - const details = { success }; - if (success) { - if (configSetAt != null) { - details.configSetAt = configSetAt; - } else { - const config = standardConfigs.forKey('backups'); - if (config == null) throw new Error('backups config not found'); - details.configSetAt = config.setAt; - } - - if (isBefore(loggedAt, details.configSetAt)) - throw new Error('invalid loggedAt'); - } else { - const error = new Error('error'); - details.stack = error.stack; - details.message = error.message; - } - - auditsWithCreatedAt.createPast(1, { - actor: null, - action: 'backup', - actee: null, - details, - loggedAt - }); - - return this; -} - -extendedAudits.createBackupAudit = createBackupAudit; -standardAudits.createBackupAudit = createBackupAudit; diff --git a/test/data/configs.js b/test/data/configs.js index abf4991f8..dd8e840ee 100644 --- a/test/data/configs.js +++ b/test/data/configs.js @@ -17,16 +17,11 @@ const configs = dataStore({ }) }); -const transforms = { - backups: ({ value, setAt }) => ({ ...value, setAt }) -}; - // eslint-disable-next-line import/prefer-default-export export const standardConfigs = view(configs, (config) => { const { createdAt, updatedAt, ...withSetAt } = config; withSetAt.setAt = updatedAt != null ? updatedAt : createdAt; - const transform = transforms[config.key]; - return transform != null ? transform(withSetAt) : withSetAt; + return withSetAt; }); standardConfigs.forKey = (key) => { diff --git a/test/router.spec.js b/test/router.spec.js index 3c3ba365e..6697f3c45 100644 --- a/test/router.spec.js +++ b/test/router.spec.js @@ -140,7 +140,6 @@ describe('createCentralRouter()', () => { '/users?x=y#z', '/users/2/edit', '/account/edit', - '/system/backups', '/system/audits', '/system/analytics', '/dl/foo.txt' @@ -398,7 +397,6 @@ describe('createCentralRouter()', () => { const paths = [ '/users', '/users/2/edit', - '/system/backups', '/system/audits', '/system/analytics' ]; @@ -1065,10 +1063,6 @@ describe('createCentralRouter()', () => { }); // System Management routes - it('shows static title for /system/backups', async () => { - await load('/system/backups'); - document.title.should.equal('Backups | System Management | ODK Central'); - }); it('shows static title for /system/audits', async () => { await load('/system/audits'); @@ -1100,17 +1094,6 @@ describe('createCentralRouter()', () => { describe('config', () => { beforeEach(mockLogin); - it('redirects user from /system/backups if showsBackups is false', () => { - const container = { - config: { showsBackups: false } - }; - return load('/system/backups', { container }, false) - .respondFor('/') - .afterResponses(app => { - app.vm.$route.path.should.equal('/'); - }); - }); - it('redirects user from /system/analytics if showsAnalytics is false', () => { const container = { config: { showsAnalytics: false } diff --git a/test/unit/request.spec.js b/test/unit/request.spec.js index 211754756..bf04182ef 100644 --- a/test/unit/request.spec.js +++ b/test/unit/request.spec.js @@ -298,29 +298,29 @@ describe('util/request', () => { }); it('audits', () => { - const path = apiPaths.audits({ action: 'backup' }); - path.should.equal('/v1/audits?action=backup'); + const path = apiPaths.audits({ action: 'nonverbose' }); + path.should.equal('/v1/audits?action=nonverbose'); }); it('audits?start', () => { const path = apiPaths.audits({ - action: 'backup', + action: 'nonverbose', start: '2020-01-01T00:00:00.000Z' }); - path.should.equal('/v1/audits?action=backup&start=2020-01-01T00%3A00%3A00.000Z'); + path.should.equal('/v1/audits?action=nonverbose&start=2020-01-01T00%3A00%3A00.000Z'); }); it('audits?end', () => { const path = apiPaths.audits({ - action: 'backup', + action: 'nonverbose', end: '2020-01-01T00:00:00.000Z' }); - path.should.equal('/v1/audits?action=backup&end=2020-01-01T00%3A00%3A00.000Z'); + path.should.equal('/v1/audits?action=nonverbose&end=2020-01-01T00%3A00%3A00.000Z'); }); it('audits?limit', () => { - const path = apiPaths.audits({ action: 'backup', limit: 10 }); - path.should.equal('/v1/audits?action=backup&limit=10'); + const path = apiPaths.audits({ action: 'nonverbose', limit: 10 }); + path.should.equal('/v1/audits?action=nonverbose&limit=10'); }); }); diff --git a/test/util/http/data.js b/test/util/http/data.js index 812f45fe6..ab72674e7 100644 --- a/test/util/http/data.js +++ b/test/util/http/data.js @@ -116,13 +116,6 @@ const responsesByComponent = { AccountEdit: componentResponses({ user: true }), SystemHome: [], - BackupList: componentResponses({ - backupsConfig: () => { - const config = testData.standardConfigs.forKey('backups'); - return config != null ? config : mockResponse.problem(404.1); - }, - audits: () => testData.standardAudits.sorted() - }), AuditList: componentResponses({ audits: true }), AnalyticsList: componentResponses({ analyticsConfig: () => { diff --git a/transifex/strings_en.json b/transifex/strings_en.json index 5872c2e64..27a79b144 100644 --- a/transifex/strings_en.json +++ b/transifex/strings_en.json @@ -60,13 +60,9 @@ "systemHome": { "title": { "string": "System Management", - "developer_comment": "This is the title of the page for managing backups, audit logs, and other system-level functions." + "developer_comment": "This is the title of the page for audit logs and other system-level functions." }, "tab": { - "backups": { - "string": "Backups", - "developer_comment": "This is the text of a navigation tab, which may also be shown as the page title (browser tab)." - }, "audits": { "string": "Server Audit Logs", "developer_comment": "This is the text of a navigation tab, which may also be shown as the page title (browser tab)." @@ -201,10 +197,6 @@ "string": "Report Usage", "developer_comment": "This is shown in the log of actions performed on the server." }, - "backup": { - "string": "Backup", - "developer_comment": "This is shown in the log of actions performed on the server." - }, "config": { "set": { "string": "Set", @@ -1020,9 +1012,6 @@ "num_unique_collectors": { "string": "Number of unique Data Collectors" }, - "backups_configured": { - "string": "Backups configured" - }, "database_size": { "string": "System database size" }, @@ -1213,110 +1202,6 @@ } } }, - "BackupDeprecation": { - "text": { - "string": "On January 31st, 2023, backups to Google Drive will stop working." - } - }, - "BackupList": { - "auditsTitle": { - "string": "Latest Backups", - "developer_comment": "This is a title shown above a section of the page." - }, - "alert": { - "terminate": { - "string": "Your automatic backups were terminated." - } - } - }, - "BackupStatus": { - "getHelp": { - "full": { - "string": "If you are having trouble, please try the {forum}.", - "developer_comment": "{forum} is a separate string that will be translated below. Its text will be formatted within ODK Central, for example, it might be bold or a link. Its text is:\n\ncommunity forum" - }, - "forum": { - "string": "community forum", - "developer_comment": "This text will be formatted within ODK Central, for example, it might be bold or a link. It will be inserted where {forum} is in the following text:\n\nIf you are having trouble, please try the {forum}." - } - }, - "notConfigured": { - "0": { - "string": "Backups are not configured." - }, - "1": { - "string": "In earlier versions of ODK Central, it was possible to set up automatic backups to Google Drive. That feature has been deprecated, but there are other ways to back up the data on the server. We strongly recommend that all users back up their data." - } - }, - "neverRun": { - "0": { - "string": "The configured backup has not yet run." - }, - "1": { - "string": "If you have configured backups within the last couple of days, this is normal. Otherwise, something has gone wrong." - }, - "2": { - "string": "In that case, the most likely fix is to restart the service." - } - }, - "somethingWentWrong": { - "0": { - "string": "Something is wrong!" - }, - "1": { - "full": { - "string": "The latest backup that completed successfully was {moreThanThreeDaysAgo}.", - "developer_comment": "{moreThanThreeDaysAgo} is a separate string that will be translated below. Its text will be formatted within ODK Central, for example, it might be bold or a link. Its text is:\n\nmore than three days ago" - }, - "moreThanThreeDaysAgo": { - "string": "more than three days ago", - "developer_comment": "This text will be formatted within ODK Central, for example, it might be bold or a link. It will be inserted where {moreThanThreeDaysAgo} is in the following text:\n\nThe latest backup that completed successfully was {moreThanThreeDaysAgo}." - } - }, - "2": { - "string": "The most likely fix is to restart the service." - } - }, - "success": { - "0": { - "string": "Backup is working.", - "developer_comment": "This text is displayed if the latest backup attempt was successful. It indicates that the backup process is working." - }, - "1": { - "string": "The last backup completed successfully {dateTime}.", - "developer_comment": "{dateTime} shows the date and time at which the last backup completed, for example: \"2020/01/01 01:23\". It may show a formatted date like \"2020/01/01\", or it may use a word like \"today\", \"yesterday\", or \"Sunday\". {dateTime} is formatted in bold." - } - }, - "action": { - "download": { - "string": "Download backup now", - "developer_comment": "This is the text for an action, for example, the text of a button." - }, - "terminate": { - "string": "Terminate", - "developer_comment": "This is the text for an action, for example, the text of a button." - } - }, - "alert": { - "download": { - "string": "The backup is running now, and will be encrypted and downloaded to your computer. This may take a while. Once the download begins, you can leave this page." - } - } - }, - "BackupTerminate": { - "title": { - "string": "Terminate Automatic Backups", - "developer_comment": "This is the title at the top of a pop-up." - }, - "introduction": { - "0": { - "string": "Are you sure you want to terminate your automatic backups?" - }, - "1": { - "string": "If you terminate your automatic backups, you will not be able to start them again. Automatic backups are a deprecated feature, but there are other ways to back up the data on the server." - } - } - }, "DatasetIntroduction": { "title": { "string": "Welcome to the Datasets preview!"