diff --git a/client/components/tables/BackupsTable.vue b/client/components/tables/BackupsTable.vue index eb16dadb..98f017ad 100644 --- a/client/components/tables/BackupsTable.vue +++ b/client/components/tables/BackupsTable.vue @@ -64,13 +64,11 @@ export default { showConfirmApply: false, selectedBackup: null, isBackingUp: false, - processing: false + processing: false, + backups: [] } }, computed: { - backups() { - return this.$store.state.backups || [] - }, userToken() { return this.$store.getters['user/getToken'] } @@ -96,9 +94,8 @@ export default { this.processing = true this.$axios .$delete(`/api/backups/${backup.id}`) - .then((backups) => { - console.log('Backup deleted', backups) - this.$store.commit('setBackups', backups) + .then((data) => { + this.setBackups(data.backups || []) this.$toast.success(this.$strings.ToastBackupDeleteSuccess) this.processing = false }) @@ -117,10 +114,10 @@ export default { this.isBackingUp = true this.$axios .$post('/api/backups') - .then((backups) => { + .then((data) => { this.isBackingUp = false this.$toast.success(this.$strings.ToastBackupCreateSuccess) - this.$store.commit('setBackups', backups) + this.setBackups(data.backups || []) }) .catch((error) => { this.isBackingUp = false @@ -136,9 +133,8 @@ export default { this.$axios .$post('/api/backups/upload', form) - .then((result) => { - console.log('Upload backup result', result) - this.$store.commit('setBackups', result) + .then((data) => { + this.setBackups(data.backups || []) this.$toast.success(this.$strings.ToastBackupUploadSuccess) this.processing = false }) @@ -148,9 +144,29 @@ export default { this.$toast.error(errorMessage) this.processing = false }) + }, + setBackups(backups) { + backups.sort((a, b) => b.createdAt - a.createdAt) + this.backups = backups + }, + loadBackups() { + this.processing = true + this.$axios + .$get('/api/backups') + .then((data) => { + this.setBackups(data.backups || []) + }) + .catch((error) => { + console.error('Failed to load backups', error) + this.$toast.error('Failed to load backups') + }) + .finally(() => { + this.processing = false + }) } }, mounted() { + this.loadBackups() if (this.$route.query.backup) { this.$toast.success('Backup applied successfully') this.$router.replace('/config') diff --git a/client/layouts/default.vue b/client/layouts/default.vue index 4d9d1438..8fbfa1f5 100644 --- a/client/layouts/default.vue +++ b/client/layouts/default.vue @@ -132,9 +132,6 @@ export default { } }) - if (payload.backups && payload.backups.length) { - this.$store.commit('setBackups', payload.backups) - } if (payload.usersOnline) { this.$store.commit('users/resetUsers') payload.usersOnline.forEach((user) => { diff --git a/client/store/index.js b/client/store/index.js index 4ddb5a3c..9b27abd4 100644 --- a/client/store/index.js +++ b/client/store/index.js @@ -21,7 +21,6 @@ export const state = () => ({ processingBatch: false, previousPath: '/', showExperimentalFeatures: false, - backups: [], bookshelfBookIds: [], openModal: null, innerModalOpen: false, @@ -245,9 +244,6 @@ export const mutations = { state.showExperimentalFeatures = val localStorage.setItem('experimental', val ? 1 : 0) }, - setBackups(state, val) { - state.backups = val.sort((a, b) => b.createdAt - a.createdAt) - }, setOpenModal(state, val) { state.openModal = val }, diff --git a/server/Server.js b/server/Server.js index 7983809f..ed095a10 100644 --- a/server/Server.js +++ b/server/Server.js @@ -473,15 +473,14 @@ class Server { await this.db.updateEntity('user', user) const initialPayload = { - metadataPath: global.MetadataPath, - configPath: global.ConfigPath, - user: client.user.toJSONForBrowser(), - librariesScanning: this.scanner.librariesScanning, - backups: (this.backupManager.backups || []).map(b => b.toJSON()) + userId: client.user.id, + username: client.user.username, + librariesScanning: this.scanner.librariesScanning } - if (user.type === 'root') { + if (user.isAdminOrUp) { initialPayload.usersOnline = this.getUsersOnline() } + client.socket.emit('init', initialPayload) } diff --git a/server/controllers/BackupController.js b/server/controllers/BackupController.js index 79b07fd1..7ee482a9 100644 --- a/server/controllers/BackupController.js +++ b/server/controllers/BackupController.js @@ -3,32 +3,29 @@ const Logger = require('../Logger') class BackupController { constructor() { } - async create(req, res) { - if (!req.user.isAdminOrUp) { - Logger.error(`[BackupController] Non-admin user attempting to craete backup`, req.user) - return res.sendStatus(403) - } + getAll(req, res) { + res.json({ + backups: this.backupManager.backups.map(b => b.toJSON()) + }) + } + + create(req, res) { this.backupManager.requestCreateBackup(res) } async delete(req, res) { - if (!req.user.isAdminOrUp) { - Logger.error(`[BackupController] Non-admin user attempting to delete backup`, req.user) - return res.sendStatus(403) - } var backup = this.backupManager.backups.find(b => b.id === req.params.id) if (!backup) { return res.sendStatus(404) } await this.backupManager.removeBackup(backup) - res.json(this.backupManager.backups.map(b => b.toJSON())) + + res.json({ + backups: this.backupManager.backups.map(b => b.toJSON()) + }) } async upload(req, res) { - if (!req.user.isAdminOrUp) { - Logger.error(`[BackupController] Non-admin user attempting to upload backup`, req.user) - return res.sendStatus(403) - } if (!req.files.file) { Logger.error('[BackupController] Upload backup invalid') return res.sendStatus(500) @@ -37,10 +34,6 @@ class BackupController { } async apply(req, res) { - if (!req.user.isAdminOrUp) { - Logger.error(`[BackupController] Non-admin user attempting to apply backup`, req.user) - return res.sendStatus(403) - } var backup = this.backupManager.backups.find(b => b.id === req.params.id) if (!backup) { return res.sendStatus(404) @@ -48,5 +41,13 @@ class BackupController { await this.backupManager.requestApplyBackup(backup) res.sendStatus(200) } + + middleware(req, res, next) { + if (!req.user.isAdminOrUp) { + Logger.error(`[BackupController] Non-admin user attempting to access backups`, req.user) + return res.sendStatus(403) + } + next() + } } module.exports = new BackupController() \ No newline at end of file diff --git a/server/managers/BackupManager.js b/server/managers/BackupManager.js index 01f05b90..00654f86 100644 --- a/server/managers/BackupManager.js +++ b/server/managers/BackupManager.js @@ -106,13 +106,20 @@ class BackupManager { this.backups.push(backup) } - return res.json(this.backups.map(b => b.toJSON())) + res.json({ + backups: this.backups.map(b => b.toJSON()) + }) } async requestCreateBackup(res) { var backupSuccess = await this.runBackup() - if (backupSuccess) res.json(this.backups.map(b => b.toJSON())) - else res.sendStatus(500) + if (backupSuccess) { + res.json({ + backups: this.backups.map(b => b.toJSON()) + }) + } else { + res.sendStatus(500) + } } async requestApplyBackup(backup) { diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index d296cf50..dd654748 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -163,10 +163,11 @@ class ApiRouter { // // Backup Routes // - this.router.post('/backups', BackupController.create.bind(this)) - this.router.delete('/backups/:id', BackupController.delete.bind(this)) - this.router.get('/backups/:id/apply', BackupController.apply.bind(this)) - this.router.post('/backups/upload', BackupController.upload.bind(this)) + this.router.get('/backups', BackupController.middleware.bind(this), BackupController.getAll.bind(this)) + this.router.post('/backups', BackupController.middleware.bind(this), BackupController.create.bind(this)) + this.router.delete('/backups/:id', BackupController.middleware.bind(this), BackupController.delete.bind(this)) + this.router.get('/backups/:id/apply', BackupController.middleware.bind(this), BackupController.apply.bind(this)) + this.router.post('/backups/upload', BackupController.middleware.bind(this), BackupController.upload.bind(this)) // // File System Routes