From 11b93e34515135cb0c9ee6d80590adeb9e508e9c Mon Sep 17 00:00:00 2001 From: Ro Date: Mon, 17 Aug 2020 15:05:10 -0700 Subject: [PATCH] back up method restores public blog images, site settings and markdown pages --- brain/api/v1/settings.js | 47 ---------------------------- brain/app.js | 2 ++ brain/data/Utils.js | 43 +++++++++++++++++++++++-- brain/views/settings.pug | 5 ++- src/com/controllers/SettingsIndex.js | 17 ++++++---- src/com/events/DataEvent.js | 1 + src/libraries/FipamoAdminAPI.js | 35 +++++++++++++++------ src/styles/main/_settings.styl | 3 ++ 8 files changed, 86 insertions(+), 67 deletions(-) diff --git a/brain/api/v1/settings.js b/brain/api/v1/settings.js index 4e98eb0..080c726 100644 --- a/brain/api/v1/settings.js +++ b/brain/api/v1/settings.js @@ -4,7 +4,6 @@ import Render from '../../data/Render'; import Settings, { SETTINGS_FILE, SETTINGS_FOLKS } from '../../data/Settings'; import Navigation from '../../data/Navigation'; import Book from '../../data/Book'; -import Utils from '../../data/Utils'; const express = require('express'); const router = express.Router(); const multer = require('multer'); @@ -16,7 +15,6 @@ const render = new Render(); const book = new Book(); const settings = new Settings(); const nav = new Navigation(); -const utils = new Utils(); const uploadPath = './public/assets/images/user/' + moment().format('YYYY') + '/' + moment().format('MM'); @@ -208,51 +206,6 @@ router.post('/add-feature-background', background_upload, (req, res) => { } }); -/*** - CREATE BACK UP -*/ -router.post('/create-backup', (req, res) => { - auth.authCheck(req) - .then(() => { - utils - .createBackup() - .then(() => { - res.json({ - type: DataEvent.API_BACKUP_CREATE, - message: "You're backed up. Hi fives" - }); - }) - .catch(err => { - res.json({ - type: err.type, - message: err.message - }); - }); - }) - .catch(err => { - res.json({ - type: err.type, - message: err.message - }); - }); -}); - -router.get('/download-backup', (req, res) => { - if (req.session.user) { - var filePath = 'content/backup.zip'; // Or format the path using the `id` rest param - var fileName = 'backup.zip'; // The default name the browser will use - - res.download(filePath, fileName); - } else { - res.json({ - type: DataEvent.REQUEST_LAME, - message: "You're not logged in, champ" - }); - } - - //Move to route? -}); - module.exports = router; function getBookData() { diff --git a/brain/app.js b/brain/app.js index b4260b1..0d56a48 100644 --- a/brain/app.js +++ b/brain/app.js @@ -51,12 +51,14 @@ var pages = require('./api/v1/pages'); var setting = require('./api/v1/settings'); var mailer = require('./api/v1/mailer'); var auth = require('./api/v1/auth'); +var backup = require('./api/v1/backup'); // API PATHS app.use('/api/v1/page', pages); app.use('/api/v1/settings', setting); app.use('/api/v1/auth', auth); app.use('/api/v1/mailer', mailer); +app.use('/api/v1/backup', backup); // PAGES app.use('/@/dashboard', dash); app.use('/@/dashboard/page', page); diff --git a/brain/data/Utils.js b/brain/data/Utils.js index d70e2cb..962ea6f 100644 --- a/brain/data/Utils.js +++ b/brain/data/Utils.js @@ -136,12 +136,12 @@ export default class Utils { var response; return new Promise(resolve => { var zip = new AdmZip(); - zip.addLocalFolder('public', 'public/'); - zip.addLocalFolder('content/pages', 'pages/'); + zip.addLocalFolder('public/assets/images/blog', 'public/assets/images/blog'); + zip.addLocalFolder('content/pages', 'content/pages/'); zip.addLocalFile('site/folks.json', 'settings/'); zip.addLocalFile('site/settings.json', 'settings/'); zip.addLocalFile('site/tags.json', 'settings/'); - zip.writeZip('public/backup.zip'); + zip.writeZip('content/backup.zip'); fs.readJSON('site/settings.json').then(settings => { settings.global.last_backup = moment(Date.now()).format(); fs.writeJSON('site/settings.json', settings); @@ -155,4 +155,41 @@ export default class Utils { resolve(response); }); } + + restoreBackup(file) { + //var response; + return new Promise((resolve, reject) => { + var zip = new AdmZip(file.buffer); + zip.extractEntryTo('settings/settings.json', 'site', false, true); + zip.extractEntryTo('settings/folks.json', 'site', false, true); + zip.extractEntryTo('settings/tags.json', 'site', false, true); + zip.getEntries().forEach(function (entry) { + var entryName = entry.entryName; + var list = entryName.split('/'); + if (list[0] === 'public') { + if (list[6]) { + zip.extractEntryTo( + entryName, + 'public/assets/images/blog/' + list[4] + '/' + list[5], + false, + true + ); + } + } + if (list[0] === 'content') { + if (list[4]) { + zip.extractEntryTo( + entryName, + 'content/pages/' + list[2] + '/' + list[3], + false, + true + ); + } + zip.extractEntryTo('content/pages/index.md', 'content/pages', false, true); + } + }); + + resolve(); + }); + } } diff --git a/brain/views/settings.pug b/brain/views/settings.pug index 0d8286c..9b7c3e6 100644 --- a/brain/views/settings.pug +++ b/brain/views/settings.pug @@ -48,10 +48,13 @@ block main-content -if(settings.global.last_backup != null) .backup-meta | The last back up was created - a(href='/api/v1/settings/download-backup')= last_backup + a(href='/api/v1/backup/download')= last_backup + br -else br span No back ups. Frowny face. + button#restore-backup(for='backup-upload') RESTORE BACKUP + input(id="backup-upload" type="file" name="backup-upload") #util-2.column label MAINTENANCE #option-settings.columns diff --git a/src/com/controllers/SettingsIndex.js b/src/com/controllers/SettingsIndex.js index a2afefd..93016f4 100644 --- a/src/com/controllers/SettingsIndex.js +++ b/src/com/controllers/SettingsIndex.js @@ -42,6 +42,9 @@ export default class SettingsIndex { document.getElementById('background').addEventListener('click', () => { document.getElementById('background-upload').click(); }); + document.getElementById('restore-backup').addEventListener('click', () => { + document.getElementById('backup-upload').click(); + }); document.getElementById('avatar-upload').addEventListener( 'change', e => { @@ -56,6 +59,13 @@ export default class SettingsIndex { }, false ); + document.getElementById('backup-upload').addEventListener( + 'change', + e => { + self.handleBackup(e); + }, + false + ); //handle privacy toggle //document //.getElementById('privacy-toggle') @@ -81,7 +91,6 @@ export default class SettingsIndex { document .getElementById('create-backup') .addEventListener('click', e => this.handleBackup(e)); - document.getElementById('get-backup').addEventListener('click', e => this.handleBackup(e)); } //-------------------------- // event handlers @@ -177,12 +186,8 @@ export default class SettingsIndex { handleBackup(e) { e.preventDefault(); e.stopPropagation(); - let task; - e.target.id === 'create-backup' - ? (task = { task: 'create_backup' }) - : (task = { task: 'get_backup' }); admin - .handleBackup(task) + .handleBackup(e.target.id, e.target.files) .then(r => { notify.alert(r.message, true); }) diff --git a/src/com/events/DataEvent.js b/src/com/events/DataEvent.js index 2fe83f9..f053afb 100644 --- a/src/com/events/DataEvent.js +++ b/src/com/events/DataEvent.js @@ -29,6 +29,7 @@ export const API_PAGE_DELETE = 'erasingPage'; export const API_SETTINGS_WRITE = 'savingSettings'; export const API_BACKUP_CREATE = 'createBackup'; export const API_BACKUP_DOWNLOAD = 'downloadBackup'; +export const API_BACKUP_RESTORE = 'downloadBackup'; export const API_IMAGES_UPLOAD = 'uploadProfileImages'; export const API_RENDER_PAGES = 'renderPages'; export const API_INIT = 'blogInit'; diff --git a/src/libraries/FipamoAdminAPI.js b/src/libraries/FipamoAdminAPI.js index 1745e7c..694fd36 100644 --- a/src/libraries/FipamoAdminAPI.js +++ b/src/libraries/FipamoAdminAPI.js @@ -18,8 +18,9 @@ export const API_UPLOAD_AVATAR = '/api/v1/settings/add-avatar'; export const API_UPLOAD_BACKGROUND = '/api/v1/settings/add-feature-background'; export const API_PUBLISH_PAGES = '/api/v1/settings/publish-pages'; export const API_NAV_SYNC = '/api/v1/settings/nav-sync'; -export const API_CREATE_BACKUP = '/api/v1/settings/create-backup'; -export const API_DOWNLOAD_BACKUP = '/api/v1/settings/download-backup'; +export const API_CREATE_BACKUP = '/api/v1/backup/create'; +export const API_DOWNLOAD_BACKUP = '/api/v1/backup/download'; +export const API_RESTORE_BACKUP = '/api/v1/backup/restore'; export const API_SEND_MAIL = '/api/v1/mailer'; import * as DataEvent from '../com/events/DataEvent'; export default class APIUtils { @@ -190,19 +191,32 @@ export default class APIUtils { }); }); } - handleBackup(data) { + handleBackup(id, files) { return new Promise((resolve, reject) => { - var url, event, method; - if (data.task === 'create_backup') { + var url, event, method, type, data; + + if (id === 'create-backup') { url = API_CREATE_BACKUP; event = DataEvent.API_BACKUP_CREATE; method = REQUEST_TYPE_POST; + type = CONTENT_TYPE_JSON; + data = { task: 'create_backup' }; } else { - url = API_DOWNLOAD_BACKUP; - event = DataEvent.API_BACKUP_DOWNLOAD; - method = REQUEST_TYPE_GET; + url = API_RESTORE_BACKUP; + event = DataEvent.API_BACKUP_RESTORE; + method = REQUEST_TYPE_POST; + type = CONTENT_TYPE_FORM; + data = new FormData(); + for (var i = 0; i < files.length; i++) { + var file = files[i]; + // Check the file type. + if (!file.type.match('application.zip')) { + continue; + } + data.append('backup_upload', file, file.name); + } } - this._request(url, event, method, CONTENT_TYPE_JSON, data) + this._request(url, event, method, type, data) .then(result => { resolve(result); }) @@ -242,7 +256,8 @@ export default class APIUtils { eventType === DataEvent.API_SETTINGS_WRITE || eventType === DataEvent.API_PAGE_DELETE || eventType === DataEvent.API_RENDER_PAGES || - eventType === DataEvent.API_BACKUP_CREATE + eventType === DataEvent.API_BACKUP_CREATE || + eventType === DataEvent.API_BACKUP_RESTORE ) request.setRequestHeader('x-access-token', self.token); diff --git a/src/styles/main/_settings.styl b/src/styles/main/_settings.styl index a862ad7..a8910e7 100644 --- a/src/styles/main/_settings.styl +++ b/src/styles/main/_settings.styl @@ -74,6 +74,9 @@ margin 0 5px 10px 0 height 30px padding 10px + input#backup-upload + visibility hidden + display none .backup-meta background $primary - 60% color $white