<commit_before>'use strict';

/*
 * @fileoverview Content system routing
 *
 */
const config = require('config');
const types = require('punchcard-content-types');
const multipart = require('connect-multiparty');
const uuid = require('uuid');
const _ = require('lodash');
const isUUID = require('validator/lib/isUUID');

const utils = require('../utils');
const database = require('../database');
const workflows = require('../workflows');
const schedule = require('../schedule');
const storage = require('../storage');

const multipartMiddleware = multipart();

/*
 * Content Route Resolution
 *
 * @param {object} application - Express Application
 * @returns {object} - Configured Express Application
 */
const routes = application => {
  return new Promise(resolve => {
    const app = application;
    const references = app.get('references');

    /*
     * @name Content Home Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
    */
    app.get(`/${config.content.base}`, (req, res) => {
      res.render('content/home', {
        content: {
          home: config.content.home,
          base: config.content.base,
          types: req.content.types,
        },
      });
    });

    /*
     * @name Individual Content Type Landing Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type`, (req, res) => {
      return database
        .distinct(database.raw('ON (id) id'))
        .select('*')
        .from(`content-type--${req.content.type.id}`)
        .orderBy('id', 'DESC')
        .orderBy('revision', 'DESC').then(rws => {
          // add itentifier to each row
          const rows = utils.routes.identifier(rws, req.content.type);

          res.render('content/landing', {
            title: config.content.base,
            content: rows,
            type: req.content.type,
            config: config.content,
          });
        });
    });

    /*
     * @name Individual Content Type Add Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/${config.content.actions.add}`, (req, res, next) => {
      const errors = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].errors`, {});
      const values = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].content`, {});

      _.unset(req.session, 'form.content.add');

      const steps = _.cloneDeep(req.content.workflow).steps.reverse();
      const step = steps[steps.length - 1];

      return utils.fill(req.content.types, req.content.type, references, database).then(ct => {
        return types.only(req.params.type.toLowerCase(), values, [ct], config).then(merged => {
          return types.form(merged, errors, config).then(form => {
            res.render('content/add', {
              form,
              action: `/${config.content.base}/${req.params.type.toLowerCase()}/${config.content.actions.save}`,
              type: ct,
              config: config.content,
              step,
            });
          });
        }).catch(e => {
          next(e);
        });
      });
    });

    /*
     * @name Individual Piece of Content
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id`, (req, res, next) => {
      return database
        .select('*')
        .from(`content-type--${req.content.type.id}`)
        .where('id', req.params.id)
        .orderBy('revision', 'DESC').then(rws => {
          if (rws.length < 1) {
            const err = {
              message: config.content.messages.missing.id.replace('%type', req.params.type).replace('%id', req.params.id),
              safe: `/${config.content.base}/${req.params.type}`,
              status: 404,
            };

            return next(err);
          }

          // add itentifier to each row
          const rows = utils.routes.identifier(rws, req.content.type);

          res.render('content/content', {
            title: config.content.messages.content.title.replace('%id', req.params.id),
            content: rows,
            type: req.content.type,
            workflow: _.cloneDeep(req.content.workflow).steps.reverse(),
            config: config.content,
          });

          return true;
        });
    });

    /*
     * @name Specific revision of an Individual Piece of Content
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id/:revision`, (req, res, next) => {
      return database
        .select('*')
        .from(`content-type--${req.content.type.id}`)
        .where('revision', req.params.revision)
        .orderBy('revision', 'DESC').then(rws => {
          if (rws.length < 1) {
            const err = {
              message: config.content.messages.missing.revision.replace('%revision', req.params.revision).replace('%type', req.params.type).replace('%id', req.params.id),
              safe: `/${config.content.base}/${req.params.type}`,
              status: 404,
            };

            return next(err);
          }

          // add itentifier to each row
          const rows = utils.routes.identifier(rws, req.content.type);

          res.render('content/content', {
            title: config.content.messages.revisions.title.replace('%revision', req.params.revision).replace('%id', req.params.id),
            content: rows,
            type: req.content.type,
            config: config.content,
          });

          return true;
        });
    });

    /*
     * @name Individual Content Type Edit Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id/:revision/${config.content.actions.edit}`, (req, res, next) => {
      const errors = _.get(req.session, `form.content.edit[${req.params.type.toLowerCase()}].errors`, {});
      const id = (_.get(req.session, `form.content.edit[${req.params.type.toLowerCase()}].id`) || _.get(req, 'params.id'));
      const revision = (_.get(req.session, `form.content.edit[${req.params.type.toLowerCase()}].revision`) || _.get(req, 'params.revision'));
      const values = _.get(req.session, `form.content.edit[${req.params.type.toLowerCase()}].content`, {});
      let data = {};

      const steps = _.cloneDeep(req.content.workflow).steps.reverse();

      // new revision, re-start workflow process
      const step = steps[steps.length - 1];

      _.unset(req.session, 'form.content.edit');

      // something went wrong on save:
      if (Object.keys(values).length > 0) {
        // add the previous session data back in
        _.set(req.session, 'form.content.edit', {<commit_msg>:art: Clean up _.get default<commit_after>'use strict';

/*
 * @fileoverview Content system routing
 *
 */
const config = require('config');
const types = require('punchcard-content-types');
const multipart = require('connect-multiparty');
const uuid = require('uuid');
const _ = require('lodash');
const isUUID = require('validator/lib/isUUID');

const utils = require('../utils');
const database = require('../database');
const workflows = require('../workflows');
const schedule = require('../schedule');
const storage = require('../storage');

const multipartMiddleware = multipart();

/*
 * Content Route Resolution
 *
 * @param {object} application - Express Application
 * @returns {object} - Configured Express Application
 */
const routes = application => {
  return new Promise(resolve => {
    const app = application;
    const references = app.get('references');

    /*
     * @name Content Home Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
    */
    app.get(`/${config.content.base}`, (req, res) => {
      res.render('content/home', {
        content: {
          home: config.content.home,
          base: config.content.base,
          types: req.content.types,
        },
      });
    });

    /*
     * @name Individual Content Type Landing Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type`, (req, res) => {
      return database
        .distinct(database.raw('ON (id) id'))
        .select('*')
        .from(`content-type--${req.content.type.id}`)
        .orderBy('id', 'DESC')
        .orderBy('revision', 'DESC').then(rws => {
          // add itentifier to each row
          const rows = utils.routes.identifier(rws, req.content.type);

          res.render('content/landing', {
            title: config.content.base,
            content: rows,
            type: req.content.type,
            config: config.content,
          });
        });
    });

    /*
     * @name Individual Content Type Add Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/${config.content.actions.add}`, (req, res, next) => {
      const errors = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].errors`, {});
      const values = _.get(req.session, `form.content.add[${req.params.type.toLowerCase()}].content`, {});

      _.unset(req.session, 'form.content.add');

      const steps = _.cloneDeep(req.content.workflow).steps.reverse();
      const step = steps[steps.length - 1];

      return utils.fill(req.content.types, req.content.type, references, database).then(ct => {
        return types.only(req.params.type.toLowerCase(), values, [ct], config).then(merged => {
          return types.form(merged, errors, config).then(form => {
            res.render('content/add', {
              form,
              action: `/${config.content.base}/${req.params.type.toLowerCase()}/${config.content.actions.save}`,
              type: ct,
              config: config.content,
              step,
            });
          });
        }).catch(e => {
          next(e);
        });
      });
    });

    /*
     * @name Individual Piece of Content
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id`, (req, res, next) => {
      return database
        .select('*')
        .from(`content-type--${req.content.type.id}`)
        .where('id', req.params.id)
        .orderBy('revision', 'DESC').then(rws => {
          if (rws.length < 1) {
            const err = {
              message: config.content.messages.missing.id.replace('%type', req.params.type).replace('%id', req.params.id),
              safe: `/${config.content.base}/${req.params.type}`,
              status: 404,
            };

            return next(err);
          }

          // add itentifier to each row
          const rows = utils.routes.identifier(rws, req.content.type);

          res.render('content/content', {
            title: config.content.messages.content.title.replace('%id', req.params.id),
            content: rows,
            type: req.content.type,
            workflow: _.cloneDeep(req.content.workflow).steps.reverse(),
            config: config.content,
          });

          return true;
        });
    });

    /*
     * @name Specific revision of an Individual Piece of Content
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id/:revision`, (req, res, next) => {
      return database
        .select('*')
        .from(`content-type--${req.content.type.id}`)
        .where('revision', req.params.revision)
        .orderBy('revision', 'DESC').then(rws => {
          if (rws.length < 1) {
            const err = {
              message: config.content.messages.missing.revision.replace('%revision', req.params.revision).replace('%type', req.params.type).replace('%id', req.params.id),
              safe: `/${config.content.base}/${req.params.type}`,
              status: 404,
            };

            return next(err);
          }

          // add itentifier to each row
          const rows = utils.routes.identifier(rws, req.content.type);

          res.render('content/content', {
            title: config.content.messages.revisions.title.replace('%revision', req.params.revision).replace('%id', req.params.id),
            content: rows,
            type: req.content.type,
            config: config.content,
          });

          return true;
        });
    });

    /*
     * @name Individual Content Type Edit Page
     *
     * @param {object} req - HTTP Request
     * @param {object} res - HTTP Response
     * @param {object} next - Express callback
    */
    app.get(`/${config.content.base}/:type/:id/:revision/${config.content.actions.edit}`, (req, res, next) => {
      const errors = _.get(req.session, `form.content.edit[${req.params.type.toLowerCase()}].errors`, {});
      const id = _.get(req.session, `form.content.edit[${req.params.type.toLowerCase()}].id`, _.get(req, 'params.id'));
      const revision = _.get(req.session, `form.content.edit[${req.params.type.toLowerCase()}].revision`, _.get(req, 'params.revision'));
      const values = _.get(req.session, `form.content.edit[${req.params.type.toLowerCase()}].content`, {});
      let data = {};

      const steps = _.cloneDeep(req.content.workflow).steps.reverse();

      // new revision, re-start workflow process
      const step = steps[steps.length - 1];

      _.unset(req.session, 'form.content.edit');

      // something went wrong on save:
      if (Object.keys(values).length > 0) {
        // add the previous session data back in
        _.set(req.session, 'form.content.edit', {
{'fraction_non_alphanumeric': 0.16863677694621249, 'fraction_numerical': 0.0015387843603553192, 'mean_word_length': 2.2202702702702704, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7518730', 'n_tokens_mistral': 4193, 'n_tokens_neox': 4208, 'n_words': 870}