updated init with empty config fix, added site restore by verifying backup file
This commit is contained in:
parent
efb20eeeb3
commit
126361fca8
8 changed files with 248 additions and 56 deletions
|
@ -8,6 +8,7 @@ const auth = new Auth();
|
||||||
const utils = new Utils();
|
const utils = new Utils();
|
||||||
|
|
||||||
var backup_upload = multer().array('backup_upload');
|
var backup_upload = multer().array('backup_upload');
|
||||||
|
var backup_restore = multer().any();
|
||||||
|
|
||||||
/***
|
/***
|
||||||
CREATE BACK UP
|
CREATE BACK UP
|
||||||
|
@ -87,4 +88,20 @@ router.post('/restore', backup_upload, (req, res) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post('/init-restore', backup_restore, (req, res) => {
|
||||||
|
utils
|
||||||
|
.verifyBackup(req.files[0], req.body)
|
||||||
|
.then(response => {
|
||||||
|
res.json({
|
||||||
|
type: response.type,
|
||||||
|
message: response.message
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
res.json({
|
||||||
|
type: err.type,
|
||||||
|
message: err.message
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import * as DataEvent from '../../src/com/events/DataEvent';
|
import * as DataEvent from '../../src/com/events/DataEvent';
|
||||||
const bCrypt = require('bcrypt');
|
const bCrypt = require('bcrypt');
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
export default class Auth {
|
export default class Auth {
|
||||||
//--------------------------
|
//--------------------------
|
||||||
|
@ -64,6 +65,32 @@ export default class Auth {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
verifyCredentials(config, credentials) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var found = _.find(config, { handle: credentials.handle });
|
||||||
|
var response;
|
||||||
|
if (found) {
|
||||||
|
if (!this.isValidPassword(found, credentials.pass)) {
|
||||||
|
response = {
|
||||||
|
type: DataEvent.REQUEST_LAME,
|
||||||
|
message: 'CHECK YOUR PASSWORD'
|
||||||
|
};
|
||||||
|
reject(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
response = { type: DataEvent.REQUEST_GOOD, message: 'Backup Verified. Restoring' };
|
||||||
|
resolve(response);
|
||||||
|
} else {
|
||||||
|
response = { type: DataEvent.REQUEST_LAME, message: 'Handle not found, boss' };
|
||||||
|
reject(response);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isValidPassword(user, password) {
|
||||||
|
return bCrypt.compareSync(password, user.password);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to make sure received token matches
|
* Checks to make sure received token matches
|
||||||
* @parameter token: created token
|
* @parameter token: created token
|
||||||
|
|
|
@ -2,12 +2,15 @@ import Settings, { SETTINGS_FILE } from './Settings';
|
||||||
import Render from './Render';
|
import Render from './Render';
|
||||||
import StringUtils from '../../src/com/utils/StringUtils';
|
import StringUtils from '../../src/com/utils/StringUtils';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import Auth from '../data/Auth';
|
||||||
|
import DataEvent from '../../src/com/events/DataEvent';
|
||||||
const settings = new Settings();
|
const settings = new Settings();
|
||||||
const render = new Render();
|
const render = new Render();
|
||||||
const stringUtils = new StringUtils();
|
const stringUtils = new StringUtils();
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const AdmZip = require('adm-zip');
|
const AdmZip = require('adm-zip');
|
||||||
|
const auth = new Auth();
|
||||||
|
|
||||||
export default class Utils {
|
export default class Utils {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
@ -157,39 +160,87 @@ export default class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreBackup(file) {
|
restoreBackup(file) {
|
||||||
//var response;
|
var response;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
var zip = new AdmZip(file.buffer);
|
var zip = new AdmZip(file.buffer);
|
||||||
zip.extractEntryTo('settings/settings.json', 'site', false, true);
|
try {
|
||||||
zip.extractEntryTo('settings/folks.json', 'site', false, true);
|
zip.extractEntryTo('settings/settings.json', 'site', false, true);
|
||||||
zip.extractEntryTo('settings/tags.json', 'site', false, true);
|
zip.extractEntryTo('settings/folks.json', 'site', false, true);
|
||||||
zip.getEntries().forEach(function (entry) {
|
zip.extractEntryTo('settings/tags.json', 'site', false, true);
|
||||||
var entryName = entry.entryName;
|
zip.getEntries().forEach(function (entry) {
|
||||||
var list = entryName.split('/');
|
var entryName = entry.entryName;
|
||||||
if (list[0] === 'public') {
|
var list = entryName.split('/');
|
||||||
if (list[6]) {
|
if (list[0] === 'public') {
|
||||||
zip.extractEntryTo(
|
if (list[6]) {
|
||||||
entryName,
|
zip.extractEntryTo(
|
||||||
'public/assets/images/blog/' + list[4] + '/' + list[5],
|
entryName,
|
||||||
false,
|
'public/assets/images/blog/' + list[4] + '/' + list[5],
|
||||||
true
|
false,
|
||||||
);
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (list[0] === 'content') {
|
||||||
if (list[0] === 'content') {
|
if (list[4]) {
|
||||||
if (list[4]) {
|
zip.extractEntryTo(
|
||||||
zip.extractEntryTo(
|
entryName,
|
||||||
entryName,
|
'content/pages/' + list[2] + '/' + list[3],
|
||||||
'content/pages/' + list[2] + '/' + list[3],
|
false,
|
||||||
false,
|
true
|
||||||
true
|
);
|
||||||
);
|
}
|
||||||
|
zip.extractEntryTo('content/pages/index.md', 'content/pages', false, true);
|
||||||
}
|
}
|
||||||
zip.extractEntryTo('content/pages/index.md', 'content/pages', false, true);
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
|
} catch (error) {
|
||||||
|
response = {
|
||||||
|
type: error,
|
||||||
|
message: 'ERROR READING BACKUP'
|
||||||
|
};
|
||||||
|
reject(response);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyBackup(file, body) {
|
||||||
|
var response;
|
||||||
|
var zip = new AdmZip(file.buffer);
|
||||||
|
var credentials = { handle: body.restore_member_handle, pass: body.restore_member_pass };
|
||||||
|
var self = this;
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
let folks = JSON.parse(zip.readAsText('settings/folks.json'));
|
||||||
|
auth.verifyCredentials(folks, credentials)
|
||||||
|
.then(r => {
|
||||||
|
//resolve(r);
|
||||||
|
self.restoreBackup(file)
|
||||||
|
.then(() => {
|
||||||
|
response = {
|
||||||
|
type: '',
|
||||||
|
message: 'RESTORE COMPLETE'
|
||||||
|
};
|
||||||
|
resolve(response);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
response = {
|
||||||
|
type: 'error',
|
||||||
|
message: 'ERROR RESTORING BACKUP'
|
||||||
|
};
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
response = {
|
||||||
|
type: 'error',
|
||||||
|
message: 'ERROR READING BACKUP FILE'
|
||||||
|
};
|
||||||
|
|
||||||
|
reject(response);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,30 +2,52 @@ extends frame
|
||||||
block main-content
|
block main-content
|
||||||
#dash-index
|
#dash-index
|
||||||
#dash-index-wrapper
|
#dash-index-wrapper
|
||||||
.dash-init#dash-init
|
.dash-init#dash-init
|
||||||
|
br
|
||||||
|
form#init-form
|
||||||
|
h1 What up.
|
||||||
|
p Just fill these in and it'll get you started.
|
||||||
|
label What's your handle?
|
||||||
br
|
br
|
||||||
form#init-form
|
input.large(type='text', name='new_member_handle' id='new_member_handle', placeholder="What\'s your handle?")
|
||||||
h1 What up.
|
br
|
||||||
p Just fill these in and it'll get you started.
|
label Let's get that email
|
||||||
label What's your handle?
|
br
|
||||||
br
|
input.large(type='text', name='new_member_email' id='new_member_email', placeholder="Email Please")
|
||||||
input.large(type='text', name='new_member_handle' id='new_member_handle', placeholder="What\'s your handle?")
|
br
|
||||||
br
|
label Let's get a password
|
||||||
label Let's get that email
|
br
|
||||||
br
|
input.large(type='password', name='new_member_pass' id='new_member_pass', placeholder="Password Please")
|
||||||
input.large(type='text', name='new_member_email' id='new_member_email', placeholder="Email Please")
|
br
|
||||||
br
|
label And let's confirm that password
|
||||||
label Let's get a password
|
br
|
||||||
br
|
input.large(type='password', name='new_member_pass2' id='new_member_pass2', placeholder="Email Confirm")
|
||||||
input.large(type='password', name='new_member_pass' id='new_member_pass', placeholder="Password Please")
|
br
|
||||||
br
|
label And finally, a title
|
||||||
label And let's confirm that password
|
br
|
||||||
br
|
input.large(type='text', name='new_member_title' id='new_member_title', placeholder="Site Title Please")
|
||||||
input.large(type='password', name='new_member_pass2' id='new_member_pass2', placeholder="Email Confirm")
|
br
|
||||||
br
|
button#init-blog(data-action='blog-init' type='submit') SET IT UP
|
||||||
label And finally, a title
|
.option
|
||||||
br
|
button.init-option#init-switch-restore OR RESTORE FROM BACKUP
|
||||||
input.large(type='text', name='new_member_title' id='new_member_title', placeholder="Site Title Please")
|
|
||||||
br
|
.dash-restore#dash-restore
|
||||||
button#init-blog(data-action='blog-init' type='submit') SET IT UP
|
form#init-restore
|
||||||
|
h1 Restore backup.
|
||||||
|
p Let's verify your backup
|
||||||
|
label What's your handle?
|
||||||
|
br
|
||||||
|
input.large(type='text', name='restore_member_handle' id='restore_member_handle', placeholder="What\'s your handle?")
|
||||||
|
br
|
||||||
|
label Let's get a password
|
||||||
|
br
|
||||||
|
input.large(type='password', name='restore_member_pass' id='restore_member_pass', placeholder="Password Please")
|
||||||
|
br
|
||||||
|
label Backup File
|
||||||
|
br
|
||||||
|
input(id="backup-upload" type="file" name="backup-upload")
|
||||||
|
br
|
||||||
|
button#blog-restore(data-action='blog-restore' type='submit') RESTORE
|
||||||
|
.option
|
||||||
|
button.init-option#init-switch-fresh OR INSTALL FRESH SITE
|
||||||
|
|
||||||
|
|
9
init.js
9
init.js
|
@ -7,13 +7,18 @@
|
||||||
var app = require('./brain/app');
|
var app = require('./brain/app');
|
||||||
var debug = require('debug')('fipamo:server');
|
var debug = require('debug')('fipamo:server');
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
var config = require('./site/settings.json');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get port from environment and store in Express.
|
* Get port from environment and store in Express.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var port = normalizePort(process.env.PORT || config.global.port);
|
try {
|
||||||
|
var configPort = require('./site/settings.json').global.port;
|
||||||
|
} catch (err) {
|
||||||
|
console.log('settings.json not found, assuming this is a first run...');
|
||||||
|
}
|
||||||
|
|
||||||
|
var port = normalizePort(configPort || process.env.PORT || 2314);
|
||||||
app.set('port', port);
|
app.set('port', port);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import FipamoApi from '../libraries/FipamoAPI';
|
import FipamoApi from '../libraries/FipamoAPI';
|
||||||
|
import FipamoAdminAPI from '../libraries/FipamoAdminAPI';
|
||||||
import DataUitls from './utils/DataUtils';
|
import DataUitls from './utils/DataUtils';
|
||||||
import * as DataEvent from './events/DataEvent';
|
import * as DataEvent from './events/DataEvent';
|
||||||
import DashManager from './controllers/DashManager';
|
import DashManager from './controllers/DashManager';
|
||||||
import Notfications from './ui/Notifications';
|
import Notfications from './ui/Notifications';
|
||||||
|
|
||||||
const api = new FipamoApi();
|
const api = new FipamoApi();
|
||||||
|
const admin = new FipamoAdminAPI();
|
||||||
const data = new DataUitls();
|
const data = new DataUitls();
|
||||||
const notify = new Notfications();
|
const notify = new Notfications();
|
||||||
|
|
||||||
|
@ -21,6 +23,10 @@ export default class Base {
|
||||||
//--------------------------
|
//--------------------------
|
||||||
start() {
|
start() {
|
||||||
if (document.getElementById('dash-form') || document.getElementById('dash-init')) {
|
if (document.getElementById('dash-form') || document.getElementById('dash-init')) {
|
||||||
|
var options = document.getElementsByClassName('init-option');
|
||||||
|
for (let index = 0; index < options.length; index++) {
|
||||||
|
options[index].addEventListener('click', e => this.handleOptions(e));
|
||||||
|
}
|
||||||
if (document.getElementById('dash-form')) {
|
if (document.getElementById('dash-form')) {
|
||||||
document
|
document
|
||||||
.getElementById('login-btn')
|
.getElementById('login-btn')
|
||||||
|
@ -29,6 +35,9 @@ export default class Base {
|
||||||
document
|
document
|
||||||
.getElementById('init-blog')
|
.getElementById('init-blog')
|
||||||
.addEventListener('click', e => this.handleSetup(e));
|
.addEventListener('click', e => this.handleSetup(e));
|
||||||
|
document
|
||||||
|
.getElementById('blog-restore')
|
||||||
|
.addEventListener('click', e => this.handleRestore(e));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
new DashManager();
|
new DashManager();
|
||||||
|
@ -76,4 +85,43 @@ export default class Base {
|
||||||
notify.alert(err, false);
|
notify.alert(err, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
handleRestore(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
var form = document.getElementById('init-restore');
|
||||||
|
admin
|
||||||
|
.handleInitRestore(form)
|
||||||
|
.then(response => {
|
||||||
|
if (response.type === DataEvent.REQUEST_LAME) {
|
||||||
|
notify.alert(response.message, false);
|
||||||
|
} else {
|
||||||
|
notify.alert(response.message, true);
|
||||||
|
setTimeout(() => {
|
||||||
|
//window.location = '/@/dashboard';
|
||||||
|
}, 700);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
notify.alert(err, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
handleOptions(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
let init = document.getElementById('dash-init');
|
||||||
|
let restore = document.getElementById('dash-restore');
|
||||||
|
if (e.target.id === 'init-switch-restore') {
|
||||||
|
init.style.display = 'none';
|
||||||
|
init.style.visibility = 'hidden';
|
||||||
|
|
||||||
|
restore.style.display = 'block';
|
||||||
|
restore.style.visibility = 'visible';
|
||||||
|
} else {
|
||||||
|
init.style.display = 'block';
|
||||||
|
init.style.visibility = 'visible';
|
||||||
|
|
||||||
|
restore.style.display = 'none';
|
||||||
|
restore.style.visibility = 'hidden';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ export const API_NAV_SYNC = '/api/v1/settings/nav-sync';
|
||||||
export const API_CREATE_BACKUP = '/api/v1/backup/create';
|
export const API_CREATE_BACKUP = '/api/v1/backup/create';
|
||||||
export const API_DOWNLOAD_BACKUP = '/api/v1/backup/download';
|
export const API_DOWNLOAD_BACKUP = '/api/v1/backup/download';
|
||||||
export const API_RESTORE_BACKUP = '/api/v1/backup/restore';
|
export const API_RESTORE_BACKUP = '/api/v1/backup/restore';
|
||||||
|
export const API_INIT_RESTORE_BACKUP = '/api/v1/backup/init-restore';
|
||||||
export const API_SEND_MAIL = '/api/v1/mailer';
|
export const API_SEND_MAIL = '/api/v1/mailer';
|
||||||
import * as DataEvent from '../com/events/DataEvent';
|
import * as DataEvent from '../com/events/DataEvent';
|
||||||
export default class APIUtils {
|
export default class APIUtils {
|
||||||
|
@ -225,6 +226,24 @@ export default class APIUtils {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
handleInitRestore(form) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
var url, event, method, type, data;
|
||||||
|
|
||||||
|
url = API_INIT_RESTORE_BACKUP;
|
||||||
|
event = DataEvent.API_BACKUP_RESTORE;
|
||||||
|
method = REQUEST_TYPE_POST;
|
||||||
|
type = CONTENT_TYPE_FORM;
|
||||||
|
data = new FormData(form);
|
||||||
|
this._request(url, event, method, type, data)
|
||||||
|
.then(result => {
|
||||||
|
resolve(result);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
//--------------------------
|
//--------------------------
|
||||||
// private
|
// private
|
||||||
//--------------------------
|
//--------------------------
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
height 100%
|
height 100%
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
|
|
||||||
.dash-init
|
.dash-init, .dash-restore
|
||||||
width 100%
|
width 100%
|
||||||
max-width 900px
|
max-width 900px
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
|
@ -40,6 +40,9 @@
|
||||||
width 120px
|
width 120px
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
display block
|
display block
|
||||||
|
.dash-restore
|
||||||
|
display: none;
|
||||||
|
visibility hidden;
|
||||||
|
|
||||||
#dash-login
|
#dash-login
|
||||||
width 100%
|
width 100%
|
||||||
|
|
Loading…
Reference in a new issue