forked from projects/fipamo
cleaned up auth in api calls, added page delete, moved edit page methods to Book data class
This commit is contained in:
parent
0f6ce7c3d8
commit
7b6af21c77
10 changed files with 261 additions and 130 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -16,3 +16,4 @@ brain/models/_backup/
|
|||
*.DS_Store
|
||||
/forfipamo
|
||||
site-settings.json
|
||||
.nova/
|
|
@ -31,117 +31,89 @@ var post_upload = multer({
|
|||
storage: storage
|
||||
}).array('post_image');
|
||||
|
||||
/***
|
||||
Retrieve Pages
|
||||
*/
|
||||
/**
|
||||
* Retrives list of Pages
|
||||
* @public
|
||||
*/
|
||||
router.get('/', (req, res) => {
|
||||
book.getPage().then(result => {
|
||||
res.json(result);
|
||||
});
|
||||
});
|
||||
|
||||
/***
|
||||
Update Page
|
||||
*/
|
||||
/**
|
||||
* Add/Update Page
|
||||
*/
|
||||
router.post('/write/:task?', feature_upload, (req, res) => {
|
||||
if (req.session.user) {
|
||||
//Get enctrypted hashed token from header request
|
||||
let hash = req.headers['x-access-token'];
|
||||
//Checks if token is a proper hash, if not reject
|
||||
if (!isTokenValid(req.session.token, hash)) {
|
||||
res.json({
|
||||
type: DataEvent.API_REQUEST_LAME,
|
||||
message: 'Invalid Token. Auth Blocked'
|
||||
});
|
||||
} else {
|
||||
//console.log('TOKEN IS GOOD');
|
||||
var member = req.session.user;
|
||||
jwt.verify(req.session.token, member.key, function(err, decoded) {
|
||||
if (err) {
|
||||
console('NOPE', err);
|
||||
authCheck(req)
|
||||
.then(() => {
|
||||
let body = _.mapValues(req.body);
|
||||
let feature = '';
|
||||
let task = '';
|
||||
req.params.task === 'new'
|
||||
? (task = DataEvent.API_PAGE_CREATE)
|
||||
: (task = DataEvent.API_PAGE_WRITE);
|
||||
if (req.files.length > 0) {
|
||||
var path = req.files[0].path;
|
||||
feature = '/' + path.substring(7, path.length);
|
||||
} else {
|
||||
var url = body.feature_image;
|
||||
url != null || url != undefined || url != ''
|
||||
? (feature = url.substring(21, url.length))
|
||||
: (feature = '');
|
||||
}
|
||||
console.log('YUP', decoded);
|
||||
body.feature = feature;
|
||||
body.deleted = false;
|
||||
book.editPage(body, body.page_uuid, task, req.session.user)
|
||||
.then(result => {
|
||||
if (result.type === DataEvent.PAGE_CREATE) {
|
||||
fs.readJSON('site/settings.json').then(settings => {
|
||||
settings.library_stats.current_index = ++settings.library_stats
|
||||
.current_index;
|
||||
settings.library_stats.total_pages = ++settings.library_stats
|
||||
.total_pages;
|
||||
fs.writeJSON('site/settings.json', settings);
|
||||
});
|
||||
}
|
||||
res.json(result);
|
||||
})
|
||||
.catch(err => {
|
||||
res.json(err);
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
res.json(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var feature = '';
|
||||
if (req.files.length > 0) {
|
||||
var path = req.files[0].path;
|
||||
feature = '/' + path.substring(7, path.length);
|
||||
} else {
|
||||
var url = req.body.feature_image;
|
||||
url != null || url != undefined || url != ''
|
||||
? (feature = url.substring(21, url.length))
|
||||
: (feature = '');
|
||||
}
|
||||
|
||||
var pageWrite =
|
||||
'---\n' +
|
||||
'id: ' +
|
||||
req.body.page_id +
|
||||
'\n' +
|
||||
'uuid: ' +
|
||||
req.body.page_uuid +
|
||||
'\n' +
|
||||
'title: ' +
|
||||
req.body.title +
|
||||
'\n' +
|
||||
'feature: ' +
|
||||
feature +
|
||||
'\n' +
|
||||
'layout: ' +
|
||||
'page' +
|
||||
'\n' +
|
||||
'tags: ' +
|
||||
req.body.tags +
|
||||
'\n' +
|
||||
'author: ' +
|
||||
req.session.user.handle +
|
||||
'\n' +
|
||||
'created: ' +
|
||||
moment(req.body.created).format() +
|
||||
'\n' +
|
||||
'updated: ' +
|
||||
moment(Date.now()).format() +
|
||||
'\n' +
|
||||
'menu: ' +
|
||||
req.body.pinToMenu +
|
||||
'\n' +
|
||||
'featured: ' +
|
||||
req.body.featureStatus +
|
||||
'\n' +
|
||||
'published: ' +
|
||||
req.body.publishedStatus +
|
||||
'\n' +
|
||||
'slug: ' +
|
||||
req.body.slug +
|
||||
'\n' +
|
||||
'---\n\n' +
|
||||
req.body.content;
|
||||
fs.writeFile('content/pages/' + req.body.slug + '.md', pageWrite, err => {
|
||||
// throws an error, you could also catch it here
|
||||
if (err) res.json({ type: DataEvent.PAGE_ERROR, message: err });
|
||||
|
||||
// success case, the file was saved
|
||||
if (req.params.task === 'new') {
|
||||
// if new file, update settings index and page count
|
||||
fs.readJSON('site/settings.json').then(settings => {
|
||||
settings.library_stats.current_index = ++settings.library_stats.current_index;
|
||||
settings.library_stats.total_pages = ++settings.library_stats.total_pages;
|
||||
fs.writeJSON('site/settings.json', settings);
|
||||
});
|
||||
res.json({
|
||||
type: DataEvent.PAGE_ADDED,
|
||||
message: 'New Page Created',
|
||||
id: req.body.page_uuid
|
||||
});
|
||||
} else {
|
||||
res.json({ type: DataEvent.PAGE_UPDATED, message: 'Page saved, boss' });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Soft deletes Page
|
||||
*/
|
||||
|
||||
router.post('/delete', (req, res) => {
|
||||
if (req.session.user) {
|
||||
authCheck(req)
|
||||
.then(() => {
|
||||
book.editPage([], req.body.id, DataEvent.API_PAGE_DELETE, req.session.user)
|
||||
.then(result => {
|
||||
res.json(result);
|
||||
})
|
||||
.catch(err => {
|
||||
res.json(err);
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
res.json(err);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Uploads image from a Page content
|
||||
*/
|
||||
|
||||
router.post('/add-post-image', post_upload, function(req, res) {
|
||||
//console.log(req.body);
|
||||
var image = req.files[0].path;
|
||||
|
@ -157,3 +129,39 @@ module.exports = router;
|
|||
function isTokenValid(token, hashedToken) {
|
||||
return bCrypt.compareSync(token, hashedToken);
|
||||
}
|
||||
|
||||
function authCheck(req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let hash = req.headers['x-access-token'];
|
||||
let response = [];
|
||||
//Checks if token is a proper hash, if not reject
|
||||
if (!isTokenValid(req.session.token, hash)) {
|
||||
response = {
|
||||
status: false,
|
||||
type: DataEvent.API_REQUEST_LAME,
|
||||
message: 'No Token Present. Auth Blocked'
|
||||
};
|
||||
reject(response);
|
||||
//res.json();
|
||||
} else {
|
||||
var member = req.session.user;
|
||||
jwt.verify(req.session.token, member.key, function(err, decoded) {
|
||||
if (err) {
|
||||
response = {
|
||||
status: false,
|
||||
type: DataEvent.API_REQUEST_LAME,
|
||||
message: 'Invalid Token. Auth Blocked'
|
||||
};
|
||||
reject(response);
|
||||
}
|
||||
response = {
|
||||
status: true,
|
||||
type: DataEvent.API_REQUEST_GOOD,
|
||||
message: 'Token Verified',
|
||||
token: decoded
|
||||
};
|
||||
resolve(response);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ import fh from 'filehound';
|
|||
import fs from 'fs-extra';
|
||||
import metadataParser from 'markdown-yaml-metadata-parser';
|
||||
import _ from 'lodash';
|
||||
import * as DataEvent from '../../src/com/events/DataEvent';
|
||||
const moment = require('moment');
|
||||
|
||||
export default class Pages {
|
||||
//--------------------------
|
||||
|
@ -13,6 +15,10 @@ export default class Pages {
|
|||
//--------------------------
|
||||
start() {}
|
||||
|
||||
/**
|
||||
* Retrieves single page or pages
|
||||
* @parameter id: optional id if requesting a single Page
|
||||
*/
|
||||
getPage(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fh.create()
|
||||
|
@ -47,6 +53,116 @@ export default class Pages {
|
|||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Edits single page based on id and task
|
||||
* @parameter id: id of page being edited
|
||||
* @parameter task: type of task being performed
|
||||
*/
|
||||
editPage(body, id, task, user) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let self = this;
|
||||
let response = [];
|
||||
switch (task) {
|
||||
case DataEvent.API_PAGE_CREATE:
|
||||
case DataEvent.API_PAGE_WRITE:
|
||||
var pageWrite =
|
||||
'---\n' +
|
||||
'id: ' +
|
||||
body.id +
|
||||
'\n' +
|
||||
'uuid: ' +
|
||||
body.uuid +
|
||||
'\n' +
|
||||
'title: ' +
|
||||
body.title +
|
||||
'\n' +
|
||||
'feature: ' +
|
||||
body.feature +
|
||||
'\n' +
|
||||
'layout: ' +
|
||||
'page' +
|
||||
'\n' +
|
||||
'tags: ' +
|
||||
body.tags +
|
||||
'\n' +
|
||||
'author: ' +
|
||||
user.handle +
|
||||
'\n' +
|
||||
'created: ' +
|
||||
moment(body.created).format() +
|
||||
'\n' +
|
||||
'updated: ' +
|
||||
moment(Date.now()).format() +
|
||||
'\n' +
|
||||
'deleted: ' +
|
||||
body.deleted +
|
||||
'\n' +
|
||||
'menu: ' +
|
||||
body.menu +
|
||||
'\n' +
|
||||
'featured: ' +
|
||||
body.featured +
|
||||
'\n' +
|
||||
'published: ' +
|
||||
body.published +
|
||||
'\n' +
|
||||
'slug: ' +
|
||||
body.slug +
|
||||
'\n' +
|
||||
'---\n' +
|
||||
body.content;
|
||||
fs.writeFile('content/pages/' + body.slug + '.md', pageWrite, err => {
|
||||
// throws an error, you could also catch it here
|
||||
|
||||
if (err) {
|
||||
response = { type: DataEvent.PAGE_ERROR, message: err };
|
||||
reject(response);
|
||||
}
|
||||
|
||||
// success case, the file was saved
|
||||
if (task === DataEvent.API_PAGE_CREATE) {
|
||||
// if new file, update settings index and page count
|
||||
response = {
|
||||
type: DataEvent.PAGE_ADDED,
|
||||
message: 'New Page Created',
|
||||
id: body.page_uuid
|
||||
};
|
||||
} else {
|
||||
response = {
|
||||
type: DataEvent.PAGE_UPDATED,
|
||||
message: 'Page saved, boss'
|
||||
};
|
||||
resolve(response);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case DataEvent.API_PAGE_DELETE:
|
||||
this.getPage(id)
|
||||
.then(page => {
|
||||
let body = _.mapValues(page.metadata);
|
||||
body.content = page.content;
|
||||
body.deleted = moment(Date.now()).format();
|
||||
self.editPage(body, body.uuid, DataEvent.API_PAGE_WRITE, user)
|
||||
.then(() => {
|
||||
response = {
|
||||
type: DataEvent.PAGE_DELETED,
|
||||
message: 'Page deleted, sport'
|
||||
};
|
||||
resolve(response);
|
||||
})
|
||||
.catch(err => {
|
||||
response = { type: DataEvent.PAGE_ERROR, message: err };
|
||||
reject(response);
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
response = { type: DataEvent.PAGE_ERROR, message: err };
|
||||
reject(response);
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
//--------------------------
|
||||
// event handlers
|
||||
//--------------------------
|
||||
|
|
|
@ -18,7 +18,7 @@ router.get('/list/:filter?/:page?', function(req, res) {
|
|||
if (filter == '' || filter == null) filter = 'all';
|
||||
if (req.session.user) {
|
||||
book.getPage()
|
||||
.then(function(pages) {
|
||||
.then(pages => {
|
||||
pages.sort((a, b) => parseFloat(b.metadata.id) - parseFloat(a.metadata.id));
|
||||
let all = [];
|
||||
let deleted = [];
|
||||
|
@ -27,7 +27,10 @@ router.get('/list/:filter?/:page?', function(req, res) {
|
|||
let featured = [];
|
||||
for (let index = 0; index < pages.length; index++) {
|
||||
let item = pages[index].metadata;
|
||||
if (typeof item.deleted == 'undefined' || item.deleted == false) {
|
||||
if (
|
||||
typeof item.deleted === 'undefined' ||
|
||||
(item.deleted === false && item.layout === 'page')
|
||||
) {
|
||||
all.push(pages[index].metadata);
|
||||
if (item.published == true) published.push(pages[index].metadata);
|
||||
if (item.menu == true) menu.push(pages[index].metadata);
|
||||
|
|
|
@ -14,7 +14,6 @@ router.get('/', function(req, res) {
|
|||
.catch(() => {
|
||||
//console.error(err)
|
||||
});
|
||||
|
||||
loadThemes().then(themes => {
|
||||
if (req.session.user) {
|
||||
let memberInfo = [];
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
"stop": "pm2 stop init.js",
|
||||
"dev": "nodemon -r esm init.js --ignore node_modules/ -e js",
|
||||
"debug": "nodemon inspect -r esm init.js --ignore node_modules/ -e js",
|
||||
"prettier-watch": "npx onchange '**/*.js' -- npx prettier --write {{changed}}",
|
||||
"watch-front": "stylus -w -m -o themes/$npm_package_theme/assets/css themes/$npm_package_theme/src/styles/base.styl & parcel watch themes/$npm_package_theme/src/com/Start.js --out-dir themes/$npm_package_theme/assets/js --out-file start.min.js --public-url /$npm_package_theme/assets/js",
|
||||
"build-front-kit": "uglifyjs node_modules/scramble-text/dist/ScrambleText.min.js node_modules/animejs/anime.min.js node_modules/reframe.js/dist/reframe.min.js -c -o themes/$npm_package_theme/assets/js/toolkit.min.js",
|
||||
"watch-back": "stylus -w -m -o public/assets/css src/styles/dash.styl & parcel watch src/com/Start.js --out-dir public/assets/scripts --out-file dash.min.js --public-url /assets/scripts",
|
||||
|
|
|
@ -19,11 +19,11 @@ export default class PostActions {
|
|||
html = html.replace(/<\/?span[^>]*>/g, ''); //removes highightjs styling
|
||||
html = html.replace(/<\/?br[^>]*>/g, '\n'); //convert back to encoded line break for storage
|
||||
pageInfo.append(
|
||||
'page_id',
|
||||
'id',
|
||||
document.getElementById('post-edit-index').getAttribute('data-index')
|
||||
);
|
||||
pageInfo.append(
|
||||
'page_uuid',
|
||||
'uuid',
|
||||
document.getElementById('post-edit-index').getAttribute('data-uuid')
|
||||
);
|
||||
pageInfo.append('content', html);
|
||||
|
@ -38,15 +38,15 @@ export default class PostActions {
|
|||
);
|
||||
pageInfo.append('tags', document.getElementById('post_tags').value);
|
||||
pageInfo.append(
|
||||
'pinToMenu',
|
||||
'menu',
|
||||
document.getElementById('option-menu-pin').getAttribute('data-active')
|
||||
);
|
||||
pageInfo.append(
|
||||
'featureStatus',
|
||||
'featured',
|
||||
document.getElementById('option-feature').getAttribute('data-active')
|
||||
);
|
||||
pageInfo.append(
|
||||
'publishedStatus',
|
||||
'published',
|
||||
document.getElementById('option-published').getAttribute('data-active')
|
||||
);
|
||||
if (image != null || image != undefined) {
|
||||
|
@ -68,19 +68,6 @@ export default class PostActions {
|
|||
}
|
||||
deletePost(id, body) {
|
||||
let self = this;
|
||||
body.deleted = new Date().toString();
|
||||
return new Promise(function(resolve, reject) {
|
||||
self.dbUtils
|
||||
.archivePost(id, body)
|
||||
.then(response => {
|
||||
//console.log(response);
|
||||
resolve(response);
|
||||
})
|
||||
.catch(err => {
|
||||
//console.log(err);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
updateNav(add, id, post) {
|
||||
api.request('/api/settings/nav', DataEvent.SETTINGS_LOADED)
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
//TOOLS
|
||||
import ApiUtils, { REQUEST_TYPE_POST, CONTENT_TYPE_FORM } from '../utils/APIUtils';
|
||||
import ApiUtils, {
|
||||
REQUEST_TYPE_POST,
|
||||
CONTENT_TYPE_FORM,
|
||||
CONTENT_TYPE_JSON
|
||||
} from '../utils/APIUtils';
|
||||
import * as DataEvent from '../events/DataEvent';
|
||||
import PageActions from '../actions/PageActions';
|
||||
import * as EditorEvent from '../events/EditorEvent';
|
||||
|
@ -17,9 +21,11 @@ export default class PostEditor {
|
|||
this.urlPieces = document.URL.split('/');
|
||||
this.post = [];
|
||||
this.postID = null;
|
||||
this.postUUID = null;
|
||||
api.authStatus();
|
||||
if (document.getElementById('post-edit-index').getAttribute('data-index')) {
|
||||
this.postID = document.getElementById('post-edit-index').getAttribute('data-index');
|
||||
this.postUUID = document.getElementById('post-edit-index').getAttribute('data-uuid');
|
||||
}
|
||||
if (document.getElementById('edit-post-text')) {
|
||||
this.editor = new TextEditor(
|
||||
|
@ -156,14 +162,21 @@ export default class PostEditor {
|
|||
break;
|
||||
case EditorEvent.EDITOR_DELETE:
|
||||
if (confirm("AYE! You know you're deleting this post, right?")) {
|
||||
new PageActions()
|
||||
.deletePost(this.postID, this.post)
|
||||
let id = { id: this.postUUID };
|
||||
api.request(
|
||||
'/api/v1/page/delete',
|
||||
DataEvent.API_PAGE_DELETE,
|
||||
REQUEST_TYPE_POST,
|
||||
CONTENT_TYPE_JSON,
|
||||
id
|
||||
)
|
||||
.then(() => {
|
||||
setTimeout(() => {
|
||||
window.location = '/@/dashboard/posts/';
|
||||
}, 100);
|
||||
console.log('DELETED');
|
||||
window.location = '/@/dashboard/page/list/';
|
||||
})
|
||||
.catch(() => {});
|
||||
.catch(err => {
|
||||
notify.alert(err, false);
|
||||
});
|
||||
} else {
|
||||
// Do nothing!
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
export const REQUEST_GOOD = 'requestGood';
|
||||
export const REQUEST_LAME = 'requestLame';
|
||||
export const API_REQUEST_GOOD = 'apiUseNotAuthorized';
|
||||
export const API_REQUEST_LAME = 'apiUseAuthorized';
|
||||
export const API_REQUEST_GOOD = 'apiUseAuthorized';
|
||||
export const API_REQUEST_LAME = 'apiUseNotAuthorized';
|
||||
export const IMG_REQUEST_GOOD = 'imgRequestGood';
|
||||
export const IMG_REQUEST_LAME = 'imgRequestLame';
|
||||
export const SETTINGS_LOADED = 'settingsLoaded';
|
||||
|
@ -17,6 +17,8 @@ export const AVATAR_UPLOADED = 'avatarUploaded';
|
|||
export const SITE_BACKGROUND_UPLOADED = 'siteBackgroundUploaded';
|
||||
export const UPLOAD_PROGRESS = 'uploadProgress';
|
||||
export const API_PAGE_WRITE = 'writingItDown';
|
||||
export const API_PAGE_CREATE = 'writingNewEntry';
|
||||
export const API_PAGE_DELETE = 'erasingPage';
|
||||
export const API_SETTINGS_WRITE = 'savingSettings';
|
||||
export const API_IMAGES_UPLOAD = 'uploadProfileImages';
|
||||
class DataEvent {
|
||||
|
|
|
@ -55,7 +55,8 @@ export default class APIUtils {
|
|||
if (
|
||||
eventType === DataEvent.API_PAGE_WRITE ||
|
||||
eventType === DataEvent.API_IMAGES_UPLOAD ||
|
||||
eventType === DataEvent.API_SETTINGS_WRITE
|
||||
eventType === DataEvent.API_SETTINGS_WRITE ||
|
||||
eventType === DataEvent.API_PAGE_DELETE
|
||||
)
|
||||
request.setRequestHeader('x-access-token', self.token);
|
||||
switch (contentType) {
|
||||
|
|
Loading…
Reference in a new issue