UNPKG

periodicjs.ext.asyncadmin

Version:

An authentication extension for periodicjs that uses passport to authenticate user sessions.

845 lines (779 loc) 26.8 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: controller/admin.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: controller/admin.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>'use strict'; var async = require('async'), path = require('path'), marked = require('marked'), pluralize = require('pluralize'), capitalize = require('capitalize'), fs = require('fs-extra'), merge = require('utils-merge'), CoreExtension, CoreUtilities, CoreController, appSettings, appenvironment, mongoose, logger, adminPath, controllerOptions, Contenttype, Collection, Compilation, Item, User, Account, adminExtSettings, loginSettings; var healthcheck = function (req, res) { res.send({ status: 'okay' }); }; var admin_index = function (req, res) { // console.log('req._parsedUrl.pathname === \'/\'',) // console.log('adminExtSettings',adminExtSettings); if (adminExtSettings.settings.adminIndexRedirectPath &amp;&amp; adminExtSettings.settings.adminIndexRedirectPath !== 'dashboard' &amp;&amp; req._parsedUrl.pathname === '/') { res.redirect(path.join('/', adminExtSettings.settings.adminPath, adminExtSettings.settings.adminIndexRedirectPath)); } else { var viewtemplate = { viewname: 'p-admin/home/index', themefileext: appSettings.templatefileextension, extname: 'periodicjs.ext.asyncadmin' }, viewdata = { pagedata: { title: 'Admin', toplink: '&amp;raquo; Home', extensions: CoreUtilities.getAdminMenu() }, markdownpages: req.controllerData.markdownpages, contentcounts: req.controllerData.contentcounts, user: req.user }; CoreController.renderView(req, res, viewtemplate, viewdata); } }; var fixCodeMirrorSubmit = function (req, res, next) { if (req.body.genericdocjson) { req.controllerData = req.controllerData || {}; req.controllerData.skip_xss = true; req.controllerData.encryptFields = true; var jsonbody = JSON.parse(req.body.genericdocjson); delete req.body.genericdocjson; req.body = merge(req.body, jsonbody); if (!req.body.docid) { req.body.docid = req.body._id; } delete req.body._id; delete req.body.__v; delete req.body.format; } Object.keys(req.body).forEach(function (key) { if (req.body[key] === '!!--EMPTY--single--EMTPY--!!') { req.body[key] = null; } else if (req.body[key] === '!!--EMPTY--array--EMTPY--!!') { req.body[key] = []; } }); next(); }; var removePasswordFromAdvancedSubmit = function (req, res, next) { req.skippassword = true; next(); }; /** * load the markdown release data * @param {object} req * @param {object} res * @return {object} reponds with an error page or sends user to authenicated in resource */ var getMarkdownReleases = function (req, res, next) { var markdownpages = [], markdownfiles = []; req.controllerData = (req.controllerData) ? req.controllerData : {}; fs.readdir(path.join(process.cwd(), 'releases'), function (err, files) { if (err) { logger.error(err); req.controllerData.markdownpages = markdownpages; next(); } else { if (files.length > 0) { files.reverse(); // console.log('files', files); markdownfiles = files.slice(0, 9); } async.eachSeries( markdownfiles, function (file, cb) { fs.readFile(path.join(process.cwd(), 'releases', file), 'utf8', function (err, data) { markdownpages.push(marked(data)); cb(err); // console.log(data); //hello! }); }, function (err) { if (err) { logger.error(err); } req.controllerData.markdownpages = markdownpages; next(); }); } }); }; /** * does a query to get content counts for all content types * @param {object} req * @param {object} res * @return {object} reponds with an error page or sends user to authenicated in resource */ var getHomepageStats = function (req, res, next) { var databaseCountData = [], databaseFeedData = []; req.controllerData = (req.controllerData) ? req.controllerData : {}; async.parallel({ databaseFeed: function (cb) { async.each(Object.keys(mongoose.models), function (DBModel, asyncEachCB) { mongoose.model(DBModel).find({}).limit(5).sort({ updatedat: 'desc' }).exec(function (err, data_feed_results) { if (err) { asyncEachCB(err); } else { data_feed_results.forEach(function (data_result) { if (data_result.updatedat) { databaseFeedData.push(data_result); } }); // databaseFeedData[DBModel]=count; asyncEachCB(); } }); }, function (err) { databaseFeedData = databaseFeedData.sort(CoreUtilities.sortObject('desc', 'updatedat')); cb(err, databaseFeedData); }); }, databaseCount: function (cb) { async.each(Object.keys(mongoose.models), function (DBModel, asyncEachCB) { mongoose.model(DBModel).count({}, function (err, count) { if (err) { asyncEachCB(err); } else { databaseCountData.push({ collection: DBModel, count: count }); asyncEachCB(); } }); }, function (err) { cb(err, databaseCountData); }); }, extensions: function (cb) { CoreExtension.getExtensions({ periodicsettings: appSettings }, function (err, extensions) { if (err) { cb(err, null); } else { cb(null, extensions); } }); }, themes: function (cb) { var themedir = path.resolve(process.cwd(), 'content/themes/'), returnFiles = []; fs.readdir(themedir, function (err, files) { if (err) { cb(err, null); } else { if (files) { for (var x = 0; x &lt; files.length; x++) { if (files[x].match('periodicjs.theme')) { returnFiles.push({ themename: files[x], active: (files[x] === appSettings.theme) ? true : false }); } } } cb(null, returnFiles); } }); } }, function (err, results) { if (err) { logger.error(err); } // console.log('results.extensions', results.extensions); req.controllerData.contentcounts = results; next(); }); }; var loadExtensions = function (req, res, next) { req.controllerData = (req.controllerData) ? req.controllerData : {}; extensionsearch({ req: req, res: res, }, function (err, extdata) { if (err) { next(err); } else { req.controllerData = merge(req.controllerData, extdata); next(); } }); }; var extensions_index = function (req, res) { var viewtemplate = { viewname: 'p-admin/extensions/index', themefileext: appSettings.templatefileextension, extname: 'periodicjs.ext.asyncadmin' }, viewdata = merge({ pagedata: { title: 'Extensions', toplink: '&amp;raquo; Extension index', // headerjs: ['/extensions/periodicjs.ext.admin/js/settings.min.js'], extensions: CoreUtilities.getAdminMenu() }, user: req.user }, req.controllerData); /* themes: req.controllerData.themes, themesettings: req.controllerData.themesettings, appsettings: req.controllerData.appsettings, config: req.controllerData.config, */ CoreController.renderView(req, res, viewtemplate, viewdata); }; var themecmd = { search: function (options) { process.stdout.write('search all themes ' + options.q); return options; }, install: function (options) { console.log('install theme ' + options.n); } }; var extcmd = { search: function (options) { process.stdout.write('search all themes ' + options.q); return options; }, install: function (options) { console.log('install theme ' + options.n); } }; var themesearch = function (options, callback) { var req = options.req; var searchterm = req.query.search; var themedir = path.resolve(process.cwd(), 'content/themes/'), returnFiles = []; fs.readdir(themedir, function (err, files) { if (err) { callback(err, null); } else { if (files) { for (var x = 0; x &lt; files.length; x++) { if (files[x].match('periodicjs.theme') &amp;&amp; files[x].match(searchterm)) { returnFiles.push({ _id: files[x], name: files[x], themename: files[x], active: (files[x] === appSettings.theme) ? true : false, createdat: new Date(), updatedat: new Date() }); } } } callback(null, { themelimit: req.query.limit, themeoffset: req.query.offset || 0, themepage_current: 1, themepage_next: 1, themepage_prev: 1, themepages: 1, themes: returnFiles, themescount: returnFiles.length }); } }); }; var loadThemes = function (req, res, next) { req.controllerData = (req.controllerData) ? req.controllerData : {}; themesearch({ req: req, res: res, }, function (err, themedata) { if (err) { next(err); } else { req.controllerData = merge(req.controllerData, themedata); next(); } }); }; var themes_index = function (req, res) { var viewtemplate = { viewname: 'p-admin/themes/index', themefileext: appSettings.templatefileextension, extname: 'periodicjs.ext.asyncadmin' }, viewdata = merge({ pagedata: { title: 'Themes', toplink: '&amp;raquo; Theme index', // headerjs: ['/extensions/periodicjs.ext.admin/js/settings.min.js'], extensions: CoreUtilities.getAdminMenu() }, user: req.user }, req.controllerData); /* themes: req.controllerData.themes, themesettings: req.controllerData.themesettings, appsettings: req.controllerData.appsettings, config: req.controllerData.config, */ CoreController.renderView(req, res, viewtemplate, viewdata); }; var extensionsearch = function (options, callback) { var req = options.req; var searchterm = req.query.search; var returnExtensions = []; CoreExtension.getExtensions({ periodicsettings: appSettings }, function (err, extensions) { if (err) { callback(err, null); } else { for (var x = 0; x &lt; extensions.length; x++) { if (extensions[x].name.match('periodicjs.ext') &amp;&amp; extensions[x].name.match(searchterm)) { extensions[x]._id = extensions[x].name; extensions[x].createdat = extensions[x].date; extensions[x].updatedat = extensions[x].date; returnExtensions.push(extensions[x]); } } callback(null, { extensionlimit: req.query.limit, extensionoffset: req.query.offset || 0, extensionpage_current: 1, extensionpage_next: 1, extensionpage_prev: 1, extensionpages: 1, extensions: returnExtensions, extensionscount: returnExtensions.length }); } }); }; var checkDeleteUser = function (req, res, next) { var ObjectToUse = (req.user.entity === 'account') ? Account : User; if ((req.user.activated || req.user.accounttype || req.user.userroles) &amp;&amp; !ObjectToUse.hasPrivilege(req.user, 760)) { var err = new Error('EXT-UAC760: You don\'t have access to modify user access'); next(err); } else { next(); } }; var convert_user_to_account = function (req, res, next) { req.controllerData = req.controllerData || {}; req.skippassword = true; req.controllerData.checkuservalidation = { checkusername: false, checkemail: false, useComplexity: false, checkpassword: false }; req.body = req.controllerData.user.toJSON(); req.body._id = null; req.body.entitytype = 'account'; req.body._id = undefined; req.body.use_encrypted_password = true; delete req.body._id; // req.body = CoreUtilities.removeEmptyObjectValues(req.body); // console.log('convert_user_to_account req.body', req.body); next(); }; var ensureAccountUser = function (req, res, next) { // console.log('req.user',req.user); if (req.user.entitytype !== 'account') { next(new Error('EXT-UAC999: Only Extension Accounts are allow access')); } else { next(); } }; var checkUserValidation = function (req, res, next) { req.controllerData = (req.controllerData) ? req.controllerData : {}; // console.log('loginSettings', loginSettings); req.controllerData.checkuservalidation = loginSettings.new_user_validation; req.controllerData.checkuservalidation.useComplexity = loginSettings.complexitySettings.useComplexity; req.controllerData.checkuservalidation.complexity = loginSettings.complexitySettings.settings.weak; next(); }; /** * application settings and theme settings page * @param {object} req * @param {object} res * @return {object} reponds with an error page or sends user to authenicated in resource */ var settings_index = function (req, res) { var viewtemplate = { viewname: 'p-admin/settings/index', themefileext: appSettings.templatefileextension, extname: 'periodicjs.ext.asyncadmin' }, viewdata = { pagedata: { title: 'Application Settings', toplink: '&amp;raquo; Application Settings', // headerjs: ['/extensions/periodicjs.ext.admin/js/settings.min.js'], extensions: CoreUtilities.getAdminMenu() }, themesettings: req.controllerData.themesettings, appsettings: req.controllerData.appsettings, config: req.controllerData.config, user: req.user }; CoreController.renderView(req, res, viewtemplate, viewdata); }; /** * settings faq page * @param {object} req * @param {object} res * @return {object} reponds with an error page or sends user to authenicated in resource */ var settings_faq = function (req, res) { var viewtemplate = { viewname: 'p-admin/settings/faq', themefileext: appSettings.templatefileextension, extname: 'periodicjs.ext.asyncadmin' }, viewdata = { pagedata: { title: 'Application Quick Help', toplink: '&amp;raquo; FAQ', // headerjs: ['/extensions/periodicjs.ext.admin/js/settings.min.js'], extensions: CoreUtilities.getAdminMenu() }, user: req.user }; CoreController.renderView(req, res, viewtemplate, viewdata); }; var skip_population = function (req, res, next) { req.controllerData = (req.controllerData) ? req.controllerData : {}; req.controllerData.skip_population = true; next(); }; var revision_delete = function (req, res, next) { var entitytype = req.params.entitytype || req.query.entitytype || req.controllerData.entitytype || req.body.entitytype; var revisionindex = req.params.revisionindex; var updatedoc = { docid: req.params.id }; req.controllerData = (req.controllerData) ? req.controllerData : {}; req.controllerData.encryptFields = true; if (typeof req.controllerData[entitytype].toJSON === 'function') { updatedoc = merge(updatedoc, req.controllerData[entitytype].toJSON()); } else if (typeof req.controllerData[entitytype].toObject === 'function') { updatedoc = merge(updatedoc, req.controllerData[entitytype].toObject()); } else { updatedoc = merge(updatedoc, req.controllerData[entitytype]); } updatedoc.docid = req.params.id; delete updatedoc._id; delete updatedoc.__v; updatedoc.changes.splice(revisionindex, 1); req.saverevision = false; req.body = updatedoc; next(); }; var revision_revert = function (req, res, next) { var entitytype = req.params.entitytype || req.query.entitytype || req.controllerData.entitytype || req.body.entitytype; var revisionindex = req.params.revisionindex; var updatedoc = { docid: req.params.id }; req.controllerData = (req.controllerData) ? req.controllerData : {}; req.controllerData.encryptFields = true; if (typeof req.controllerData[entitytype].toJSON === 'function') { updatedoc = merge(updatedoc, req.controllerData[entitytype].toJSON()); } else if (typeof req.controllerData[entitytype].toObject === 'function') { updatedoc = merge(updatedoc, req.controllerData[entitytype].toObject()); } else { updatedoc = merge(updatedoc, req.controllerData[entitytype]); } updatedoc.docid = req.params.id; delete updatedoc._id; delete updatedoc.__v; updatedoc = merge(updatedoc, updatedoc.changes[revisionindex].changeset); // req.saverevision = false; req.body = updatedoc; // console.log('req.body ', req.body); // console.log('revisionindex ', revisionindex); next(); }; var get_entity_modifications = function (entityname) { var entity = entityname.toLowerCase(), plural_entity = pluralize.plural(entity); return { name: entity, //item plural_name: pluralize.plural(entity), //items capitalized_name: capitalize(entity), //Item capitalized_plural_name: capitalize(plural_entity) //Items }; }; var get_revision_page = function (options) { var entity = get_entity_modifications(options.entity); return function (req, res) { var pagetitle = (req.controllerData &amp;&amp; req.controllerData.revision_page_attribute_title) ? req.controllerData.revision_page_attribute_title : req.controllerData[entity.name].title || req.controllerData[entity.name].name || req.controllerData[entity.name]._id; var revision_view_file = (entity.plural_name === 'accounts') ? 'users' : entity.plural_name; var viewtemplate = { viewname: 'p-admin/' + revision_view_file + '/revisions', themefileext: appSettings.templatefileextension }, viewdata = merge(req.controllerData, { pagedata: { title: entity.capitalized_name + ' Revisions', pagetitle: pagetitle, toplink: '&amp;raquo; &lt;a href="/' + adminPath + '/content/' + entity.plural_name + '" class="async-admin-ajax-link">' + entity.capitalized_plural_name + '&lt;/a> &amp;raquo; ' + pagetitle + ' &amp;raquo; Revisions', extensions: CoreUtilities.getAdminMenu() }, entity: entity, user: req.user }); if (options.extname) { viewtemplate.extname = options.extname; } CoreController.renderView(req, res, viewtemplate, viewdata); }; }; var admin_search = function (resources) { var periodic = resources; return function (req, res) { req.body = req.body || {}; req.query = req.query || {}; req.controllerData = req.controllerData || {}; var search_entities = req.body.search_entities || req.query.search_entities || req.controllerData.search_entities || Object.keys(periodic.app.controller.extension.asyncadmin.search); if (!Array.isArray(search_entities)) { search_entities = search_entities.split(','); } // console.log('search_entities', search_entities); req.query.search = req.query['searchall-input'] || req.query.search; req.query.limit = (req.query.limit &amp;&amp; req.query.limit &lt; 200) ? req.query.limit : 25; var search_response_results = {}; async.each(search_entities, function (key, asyncForEachOfCallback) { // value({ periodic.app.controller.extension.asyncadmin.search[key]({ req: req, res: res }, function (err, search_response) { if (err) { return asyncForEachOfCallback(err); } else { search_response_results[key] = {}; search_response_results[key][key + 'limit'] = search_response[key + 'limit']; search_response_results[key][key + 'offset'] = search_response[key + 'offset']; search_response_results[key][key + 'page_current'] = search_response[key + 'page_current']; search_response_results[key][key + 'page_next'] = search_response[key + 'page_next']; search_response_results[key][key + 'page_prev'] = search_response[key + 'page_prev']; search_response_results[key][key + 'pages'] = search_response[key + 'pages']; search_response_results[key][pluralize(key)] = search_response[pluralize(key)]; asyncForEachOfCallback(); } }); }, function (err) { if (err) { CoreController.handleDocumentQueryErrorResponse({ err: err, res: res, req: req }); } else { // console.log('search_response_results',search_response_results); var viewtemplate = { viewname: 'p-admin/home/search', themefileext: appSettings.templatefileextension, extname: 'periodicjs.ext.asyncadmin' }, viewdata = { pagedata: { title: 'Admin', toplink: 'Search Results &amp;raquo; "' + req.query['searchall-input'] + '" ', extensions: CoreUtilities.getAdminMenu() }, search_results: search_response_results, search_entities: search_entities, user: req.user }; CoreController.renderView(req, res, viewtemplate, viewdata); } }); }; }; var get_entity_search = function (options) { var entityname = options.entity; return function (options, callback) { if (entityname === 'userrole' || entityname === 'userprivilege') { controllerOptions[entityname].searchfields = ['title', 'name']; } CoreController.controller_model_search_query({ req: options.req, res: options.res, orQuery: [], controllerOptions: controllerOptions[entityname], asyncCallback: callback }); }; }; /** * admin controller * @module authController * @{@link https://github.com/typesettin/periodic} * @author Yaw Joseph Etse * @copyright Copyright (c) 2014 Typesettin. All rights reserved. * @license MIT * @requires module:periodicjs.core.utilities * @requires module:periodicjs.core.controller * @requires module:periodicjs.core.extensions * @param {object} resources variable injection from current periodic instance with references to the active logger and mongo session * @return {object} */ var controller = function (resources) { logger = resources.logger; mongoose = resources.mongoose; appSettings = resources.settings; CoreController = resources.core.controller; CoreUtilities = resources.core.utilities; CoreExtension = resources.core.extension; Collection = mongoose.model('Collection'); Compilation = mongoose.model('Compilation'); Contenttype = mongoose.model('Contenttype'); Item = mongoose.model('Item'); User = mongoose.model('User'); // console.log('Item', typeof Item.schema.paths.content); // AppDBSetting = mongoose.model('Setting'); appenvironment = appSettings.application.environment; adminExtSettings = resources.app.controller.extension.asyncadmin.adminExtSettings; if (adminExtSettings.use_separate_accounts) { Account = mongoose.model('Account'); } loginSettings = resources.app.controller.extension.login.loginExtSettings; adminPath = resources.app.locals.adminPath; controllerOptions = resources.app.controller.native.ControllerSettings; return { healthcheck: healthcheck, get_entity_modifications: get_entity_modifications, get_revision_page: get_revision_page, user_revisions: get_revision_page({ entity: 'user', extname: 'periodicjs.ext.asyncadmin' }), account_revisions: get_revision_page({ entity: 'account', extname: 'periodicjs.ext.asyncadmin' }), ensureAccountUser: ensureAccountUser, depopulate: CoreController.depopulate, revision_delete: revision_delete, revision_revert: revision_revert, admin_index: admin_index, loadExtensions: loadExtensions, themes_index: themes_index, fixCodeMirrorSubmit: fixCodeMirrorSubmit, removePasswordFromAdvancedSubmit: removePasswordFromAdvancedSubmit, settings_index: settings_index, settings_faq: settings_faq, skip_population: skip_population, getMarkdownReleases: getMarkdownReleases, convert_user_to_account: convert_user_to_account, getHomepageStats: getHomepageStats, adminExtSettings: adminExtSettings, checkDeleteUser: checkDeleteUser, checkUserValidation: checkUserValidation, themesearch: themesearch, loadThemes: loadThemes, extensionsearch: extensionsearch, extensions_index: extensions_index, get_entity_search: get_entity_search, themecmd: themecmd, extcmd: extcmd, user_search: get_entity_search({ entity: 'user' }), account_search: get_entity_search({ entity: 'account' }), userrole_search: get_entity_search({ entity: 'userrole' }), userprivilege_search: get_entity_search({ entity: 'userprivilege' }), admin_search: admin_search(resources) }; }; module.exports = controller; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-authController.html">authController</a></li><li><a href="module-settingsController.html">settingsController</a></li><li><a href="module-userroleController.html">userroleController</a></li><li><a href="periodicjs.ext.module_admin.html">admin</a></li></ul><h3>Classes</h3><ul><li><a href="filterlist.html">filterlist</a></li><li><a href="sortlist.html">sortlist</a></li><li><a href="StylieTextEditor.html">StylieTextEditor</a></li><li><a href="tsdatalist.html">tsdatalist</a></li><li><a href="tsmedialist.html">tsmedialist</a></li><li><a href="tstagmanager.html">tstagmanager</a></li></ul><h3>Global</h3><ul><li><a href="global.html#get_edit_page">get_edit_page</a></li><li><a href="global.html#get_index_page">get_index_page</a></li><li><a href="global.html#get_new_page">get_new_page</a></li><li><a href="global.html#get_show_page">get_show_page</a></li><li><a href="global.html#getHomepageStats">getHomepageStats</a></li><li><a href="global.html#getMarkdownReleases">getMarkdownReleases</a></li><li><a href="global.html#index">index</a></li><li><a href="global.html#load_app_settings">load_app_settings</a></li><li><a href="global.html#load_extension_settings">load_extension_settings</a></li><li><a href="global.html#load_theme_settings">load_theme_settings</a></li><li><a href="global.html#restart_app">restart_app</a></li><li><a href="global.html#sendSettingEmail">sendSettingEmail</a></li><li><a href="global.html#settings_faq">settings_faq</a></li><li><a href="global.html#settings_index">settings_index</a></li><li><a href="global.html#show">show</a></li><li><a href="global.html#styleWindowResizeEventHandler">styleWindowResizeEventHandler</a></li><li><a href="global.html#update_app">update_app</a></li><li><a href="global.html#update_app_settings">update_app_settings</a></li><li><a href="global.html#update_config_json_files">update_config_json_files</a></li><li><a href="global.html#update_ext_filedata">update_ext_filedata</a></li><li><a href="global.html#update_theme_filedata">update_theme_filedata</a></li><li><a href="global.html#update_theme_settings">update_theme_settings</a></li><li><a href="global.html#userrole_new">userrole_new</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Wed Jun 15 2016 16:57:18 GMT-0400 (EDT) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>