UNPKG

punchcard-cms

Version:
334 lines (280 loc) 8.95 kB
'use strict'; /** * @fileoverview Applications routing functions * */ const config = require('config'); const _ = require('lodash'); const types = require('punchcard-content-types'); const uuid = require('uuid'); const database = require('../database'); const model = require('./model'); const utils = require('../utils'); /** * All Applications Landing page * @param {object} req - HTTP Request * @param {object} res - HTTP Response * * @returns {boolean} returns true */ const all = (req, res) => { const apps = req.app.get('applications-apps') || []; res.render('applications/all', { applications: apps, config: config.applications, structure: model.structure, }); return true; }; /** * Add a new Application * @param {object} req - HTTP Request * @param {object} res - HTTP Response * @param {object} next - Express callback * * @returns {promise} content-types promise * * TODO: Content-Types errors need to be vastly expanded to properly use promise catch for error * https://github.com/punchcard-cms/content-types/issues/112 */ const add = (req, res, next) => { const errors = _.get(req.session, 'form.applications.save.errors', {}); const values = _.get(req.session, 'form.applications.save.content', {}); const merged = req.app.get('applications-merged') || {}; _.unset(req.session, 'form.applications.save'); return types.only('applications', values, [merged], config).then(only => { return types.form(only, errors, config).then(form => { res.render('applications/add', { form, action: `/${config.applications.base}/${config.applications.actions.save}`, config: config.applications, structure: model.structure, button: config.applications.actions.save, }); }); }).catch(e => { const err = { message: e.message, safe: `/${config.applications.base}`, status: 500, }; return next(err); }); }; /** * View/edit an individual Application * @param {object} req - HTTP Request * @param {object} res - HTTP Response * @param {object} next - Express callback * * @returns {promise} resolves/rejects promise */ const one = (req, res, next) => { const id = _.get(req.session, 'form.applications.edit.id', null); const errors = _.get(req.session, 'form.applications.save.errors', {}); const values = _.get(req.session, 'form.applications.save.content', {}); const merged = req.app.get('applications-merged') || {}; let app = _.get(req.session, 'form.applications.edit.app', null); _.unset(req.session, 'form.applications.edit'); _.unset(req.session, 'form.applications.save'); // something went wrong on save: if (Object.keys(values).length > 0 && id) { // add the previous session data back in _.set(req.session, 'form.applications.edit', { id, }); // grab the edit form and inject errors and values from req.session return types.only('applications', values, [merged], config).then(only => { return types.form(only, errors, config).then(form => { res.render('applications/one', { form, action: `/${config.applications.base}/${config.applications.actions.save}`, config: config.applications, structure: model.structure, button: config.applications.actions.update, app, }); return true; }); }); } // grab the application from the database return database('applications').where({ id: req.params.id, }).then(rows => { // application not in database; send to 404 if (rows.length < 1) { const err = { message: config.applications.messages.missing.id.replace('%id', req.params.id), safe: `/${config.applications.base}`, status: 404, }; return next(err); } app = rows[0]; app.client = { id: app['client-id'], secret: app['client-secret'], }; // add session data for this application _.set(req.session, 'form.applications.edit', { id: rows[0].id, app, }); const data = { 'name': { 'text': { 'value': app.name, }, }, 'live-endpoint': { 'url': { 'value': app['live-endpoint'], }, }, 'updated-endpoint': { 'url': { 'value': app['updated-endpoint'], }, }, 'sunset-endpoint': { 'url': { 'value': app['sunset-endpoint'], }, }, }; return types.only('applications', data, [merged], config); }).then(only => { return types.form(only, null, config); }).then(form => { res.render('applications/one', { form, action: `/${config.applications.base}/${config.applications.actions.save}`, config: config.applications, button: config.applications.actions.update, app, }); return true; }).catch(e => { const err = { message: e.message, safe: `/${config.applications.base}`, status: 404, }; return next(err); }); }; /** * Create a new client secret * @param {object} req - HTTP Request * @param {object} res - HTTP Response * @param {object} next - Express callback * * @returns {promise} resolves/rejects promise */ const secret = (req, res, next) => { const id = _.get(req.session, 'form.applications.edit.id', null); const referrer = req.get('Referrer'); const data = { 'client-secret': uuid.v4(), }; if (!_.includes(referrer, `/${config.applications.base}/${id}`)) { const err = { message: 'Secret can only be changed from the application edit screen', safe: `/${config.applications.base}`, status: 500, }; return next(err); } return database('applications').where('id', '=', id).update(data).then(() => { res.redirect(`/${config.applications.base}/${id}`); return data['client-secret']; }).catch(e => { const err = { message: e.message, safe: `/${config.applications.base}`, status: 500, }; return next(err); }); }; /** * View/edit an individual Application * @param {object} req - HTTP Request * @param {object} res - HTTP Response * * @returns {promise} database promise */ const save = (req, res) => { const id = _.get(req.session, 'form.applications.edit.id', null); const referrer = (_.get(req.session, 'referrer') || req.get('Referrer')) || `/${config.applications.base}`; const merged = req.app.get('applications-merged') || {}; let apps = req.app.get('applications-apps') || []; // user hit delete button if (req.body.submit === config.applications.actions.delete && id) { return database('applications').where('id', '=', id).del().then(() => { _.unset(req.session, 'form.applications.edit'); _.unset(req.session, 'form.applications.save'); // remove this app from apps object apps = apps.filter(app => { if (app.id === id) { return false; } return true; }); // replace apps in the application's settings req.app.set('applications-apps', apps); res.redirect(`/${config.applications.base}`); return true; }); } // Validation const validated = types.form.validate(req.body, merged, 'save'); if (validated === true) { const data = { 'name': req.body['name--text'], 'live-endpoint': req.body['live-endpoint--url'], 'updated-endpoint': req.body['updated-endpoint--url'], 'sunset-endpoint': req.body['sunset-endpoint--url'], }; // `update` is for the Edit form if (req.body.submit === config.applications.actions.update && id) { return database('applications').where('id', '=', id).update(data).returning('*').then((updated) => { _.unset(req.session, 'form.applications.edit'); _.unset(req.session, 'form.applications.save'); // find this app in the request apps object const index = apps.findIndex(app => { return app.id === id; }); // update this app in the application's settings apps[index] = updated[0]; req.app.set('applications-apps', apps); res.redirect(`/${config.applications.base}`); return true; }); } // on add, create fresh id/secret data['client-id'] = uuid.v4(); data['client-secret'] = uuid.v4(); return database('applications').insert(data).returning('*').then((added) => { _.unset(req.session, 'form.applications.save'); // add this new app to the request's apps object apps.push(added[0]); req.app.set('applications-apps', apps); res.redirect(`/${config.applications.base}/${added[0].id}`); return true; }); } _.set(req.session, 'form.applications.save', { errors: validated, content: utils.format(req.body), }); return res.redirect(referrer); }; module.exports = { all, add, one, secret, save, };