From ed1873babebcc8f8b52a41bddd3b1c8e403cf095 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Wed, 29 Dec 2021 14:25:01 +0200 Subject: [PATCH] App can now go into maintenance mode locking out routing --- app/imports/constants/MAINTENANCE_MODE.js | 18 ++++++++- app/imports/ui/pages/Admin.vue | 28 ++++++++------ app/imports/ui/pages/Maintenance.vue | 43 ++++++++++++++++++++++ app/imports/ui/router.js | 45 +++++++++++++++-------- app/public/sw.js | 4 +- app/server/main.js | 1 + 6 files changed, 109 insertions(+), 30 deletions(-) create mode 100644 app/imports/ui/pages/Maintenance.vue diff --git a/app/imports/constants/MAINTENANCE_MODE.js b/app/imports/constants/MAINTENANCE_MODE.js index 7f676034..f81e01e4 100644 --- a/app/imports/constants/MAINTENANCE_MODE.js +++ b/app/imports/constants/MAINTENANCE_MODE.js @@ -1,3 +1,19 @@ -const MAINTENANCE_MODE = Meteor.settings?.public?.maintenanceMode || false; +import { Migrations } from 'meteor/percolate:migrations'; +import SCHEMA_VERSION from '/imports/constants/SCHEMA_VERSION.js'; +if (Meteor.isServer){ + Meteor.startup(()=>{ + const dbVersion = Migrations.getVersion(); + if ( + !Meteor.settings.public.maintenanceMode && + SCHEMA_VERSION !== dbVersion + ){ + Meteor.settings.public.maintenanceMode = { + reason: 'App data needs to be migrated to the latest version' + }; + } + }); +} + +const MAINTENANCE_MODE = Meteor.settings.public.maintenanceMode; export default MAINTENANCE_MODE; diff --git a/app/imports/ui/pages/Admin.vue b/app/imports/ui/pages/Admin.vue index e905052a..6dec5875 100644 --- a/app/imports/ui/pages/Admin.vue +++ b/app/imports/ui/pages/Admin.vue @@ -4,7 +4,13 @@ -

Database version: {{ versions && versions.dbVersion }}

+

Current database version: {{ versions && versions.dbVersion }}

+

+ Database is up to date with latest version +

+

+ Expected database version: {{ schemaVersion }} +

Git version: {{ versions && versions.gitVersion }}

mdi-refresh - +
- Migrate + Migrate to database version {{ schemaVersion }} import getVersion from '/imports/migrations/methods/getVersion.js'; import migrateTo from '/imports/migrations/methods/migrateTo.js'; +import SCHEMA_VERSION from '/imports/constants/SCHEMA_VERSION.js'; export default { data(){return { @@ -54,25 +59,24 @@ export default { versionError: undefined, migrateError: undefined, loadingMigration: false, + schemaVersion: SCHEMA_VERSION, }}, mounted(){ this.refreshVersions(); }, methods: { refreshVersions(){ + this.loadingVersion = true; getVersion.call((error, result) => { + this.loadingVersion = false; this.versionError = error; this.versions = result; }); }, migrate(){ - let version = this.migrationInput; - if (Number.isFinite(+version)){ - version = +version; - } this.loadingMigration = true; migrateTo.call({ - version, + version: SCHEMA_VERSION, }, error => { this.loadingMigration = false; this.migrateError = error; diff --git a/app/imports/ui/pages/Maintenance.vue b/app/imports/ui/pages/Maintenance.vue new file mode 100644 index 00000000..52e63fd8 --- /dev/null +++ b/app/imports/ui/pages/Maintenance.vue @@ -0,0 +1,43 @@ + + + diff --git a/app/imports/ui/router.js b/app/imports/ui/router.js index 6915257a..30bd9540 100644 --- a/app/imports/ui/router.js +++ b/app/imports/ui/router.js @@ -1,6 +1,6 @@ import { RouterFactory, nativeScrollBehavior } from 'meteor/akryum:vue-router2'; import { acceptInviteToken } from '/imports/api/users/Invites.js'; - +import MAINTENANCE_MODE from '/imports/constants/MAINTENANCE_MODE.js'; // Components const Home = () => import('/imports/ui/pages/Home.vue'); const About = () => import('/imports/ui/pages/About.vue'); @@ -26,6 +26,8 @@ const Tabletop = () => import('/imports/ui/pages/Tabletop.vue'); const TabletopToolbar = () => import('/imports/ui/tabletop/TabletopToolbar.vue'); const TabletopRightDrawer = () => import('/imports/ui/tabletop/TabletopRightDrawer.vue'); const Admin = () => import('/imports/ui/pages/Admin.vue'); +const Maintenance = () => import('/imports/ui/pages/Maintenance.vue'); + // Not found const NotFound = () => import('/imports/ui/pages/NotFound.vue'); @@ -92,8 +94,8 @@ function claimInvite(to, from, next){ }); } -RouterFactory.configure(factory => { - factory.addRoutes([{ +RouterFactory.configure(router => { + router.addRoutes([{ path: '/', name: 'home', components: { @@ -249,29 +251,40 @@ RouterFactory.configure(factory => { name: 'admin', component: Admin, beforeEnter: ensureAdmin, + },{ + path: '/maintenance', + name: 'maintenance', + component: Maintenance, }, ]); }); // Not found route has lowest priority -RouterFactory.configure(factory => { - factory.addRoute({ +RouterFactory.configure(router => { + router.addRoute({ path: '*', component: NotFound, }); }, -1); +function redirectIfMaintenance(to, from, next){ + if (!MAINTENANCE_MODE) return next(); + console.log(to); + if (to?.path === '/admin' || to?.path === '/maintenance') return next(); + Tracker.autorun((computation) => { + if (userSubscription.ready()){ + computation.stop(); + const user = Meteor.user(); + if (user && user.roles && user.roles.includes('admin')){ + next({name: 'admin'}) + } else { + next({name: 'maintenance'}); + } + } + }); +} + // Create the router instance const router = routerFactory.create(); -router.beforeEach((to, from, next) => { - let user = Meteor.user(); - if ( - to.path === '/sign-in' || - (user && user.roles && user.roles.includes('admin')) - ){ - next(); - } else { - next(); - } -}); +router.beforeEach(redirectIfMaintenance); export default router; diff --git a/app/public/sw.js b/app/public/sw.js index 2294ca69..65fc3e90 100644 --- a/app/public/sw.js +++ b/app/public/sw.js @@ -56,7 +56,9 @@ self.addEventListener('fetch', (event) => { }))); } - caches.open(version).then(cache => cache.put(event.request, clonedResponse)); + if (event.request.method !== 'POST') { + caches.open(version).then(cache => cache.put(event.request, clonedResponse)); + } } return response; }).catch(() => { diff --git a/app/server/main.js b/app/server/main.js index 1a52b852..1e4a15c4 100644 --- a/app/server/main.js +++ b/app/server/main.js @@ -9,3 +9,4 @@ import '/imports/api/parenting/organizeMethods.js'; import '/imports/api/users/patreon/updatePatreonOnLogin.js'; import '/imports/migrations/server/index.js'; import '/imports/migrations/methods/index.js' +import '/imports/constants/MAINTENANCE_MODE.js';