UNPKG

sheercms

Version:

Sheer Cliff CMS is a simple and powerful content management system (CMS) for Node JS.

354 lines (309 loc) 13.4 kB
var config = require("./lib/config"); var plugins = require("./lib/plugins"); var database = require('./lib/database'); var logger = require('./lib/logger'); var auth = require('./lib/auth'); var view = require('./lib/view'); var async = require("async"); var S = require('string'); var api = require('./lib/api'); var express = require('express'); var path_mod = require('path'); var utils = require('./lib/utilities'); var cache = api.cache; var constants = { version: "2014.01" }; var _paths = ["/cms/", "/static/"]; var _root = null; var _options = null; module.exports.api = api; module.exports.logger = logger; module.exports.setRoot = function(path) { _root = path; }; module.exports.getRoot = function() { return _root; }; // Adds the path prefix to the list of paths that are ignored by the CMS // module.exports.addIgnorePath = function(path) { if (path) { paths.push(_path.toLowerCase()); } }; module.exports.registerPlugin = function(key, plugin) { plugins.set(key, plugin); }; // Initialize the CMS, plugins, and database connection. // callback(err) module.exports.init = function(server, options, callback) { try { //var router = express.Router(); config.init(options, function(err) { if (err) { logger.error("Error initializing CMS: " + err + ". Stack: " + err.stack); if (callback) callback(err); } else { logger.init(); utils.ensureTempDir(function(err, created) { if (err) { logger.error("Error creating the ~/temp directory: " + err + ". Stack: " + err.stack); if (callback) callback(err); } else { database.connect(function (err) { if (err) { logger.error("Error initializing CMS: " + err + ". Stack: " + err.stack); if (callback) callback(err); } else { plugins.init(server, function (err) { if (err) { logger.error("Error initializing CMS: " + err + ". Stack: " + err.stack); if (callback) callback(err); } else { //static cms files server.use('/cms/static', express.static(path_mod.join(__dirname, 'static'))); //cms home page server.get('/cms', auth.authenticate, indexRoute); var arr = [ "./lib/setup/setup-index", "./lib/users/users-index", "./lib/groups/groups-index", "./lib/content/content-index", "./lib/templates/templates-index", "./lib/menus/menus-index", "./lib/logging/logging-index", "./lib/stats/stats-index", "./lib/cache/cache-index", "./lib/designer/designer-index", "./lib/packages/packages-index", "./lib/icons/icons-index", "./lib/types/types-index" ]; //now initialize each api group async.each(arr, function (key, done) { logger.info("Initializing: " + key); require(key).init(server, function (err) { if (err) done(err); else done(); }); }, function (err) { if (err) { logger.error("Error initializing CMS: " + err + "; stack=" + err.stack); callback(err); } else { //setup the rewrite route server.get('*', auth.loadUser, rewriteRoute); server.post('*', auth.loadUser, rewriteRoute); logger.info("Sheer Cliff CMS initialized."); callback(null); } }); } }); } }); } }); } }); } catch(e) { console.error("Error initializing CMS: " + e + ". stack: " + e.stack); callback(e); } }; function indexRoute(req, res, next){ var model = { browserTitle: "Sheer Cliff CMS", title: "SHEER CLIFF", version: '', //constants.version, scripts: [], styles: [], helloName: "", pageData: "" //JSON string }; //get the version from the package.json var pkg = require(__dirname + '/package.json'); model.version = pkg.version; model.helloName = S(req.user.firstName).isEmpty() ? req.user.username : req.user.firstName; var pageData = { user: req.user, isAdmin: api.users.isAdmin(req.user), menu: { selectedItem: null, items: [ { text: "Content", url: "#content" }, { text: "Media", url: "#media" }, { text: "Menus", url: "#menus" }, { text: "Tools", items: getToolMenuItems(req.user) } ] } }; model.pageData = JSON.stringify(pageData); //get the plugin resources var resources = api.plugins.getPluginResources(); if (resources) { if (resources.scripts) { for(var i = 0; i < resources.scripts.length; i++) model.scripts.push(resources.scripts[i]); } if (resources.styles) { for(var i = 0; i < resources.styles.length; i++) model.styles.push(resources.styles[i]); } } view.renderFile('index', model, function(err, output) { if (err) { logger.error(err); res.send("Error rendering 'index' view."); } else res.send(output); }); }; function getToolMenuItems(user) { var arr = []; if (api.users.isAdmin(user)) { arr.push(new MenuItem("Users & Roles", "#users")); arr.push(new MenuItem("Content Types", "#types")); arr.push(new MenuItem("Templates", "#templates")); arr.push(new MenuItem("Log Viewer", "#logs")); arr.push(new MenuItem("Caching", "#cache")); arr.push(new MenuItem("Packages", "#packages")); arr.push(new MenuItem("Data Statistics", "#stats")); } else { arr.push(new MenuItem("Caching", "#cache")); } return arr; } function MenuItem(text, url) { var self = this; self.text = text; self.url = url; } function rewriteRoute(req, res, next){ try { var url = req.url; logger.debug('Checking route in CMS: ' + url); //make sure this URL isn't the /cms/ or a static folder if (shouldProcessUrl(url) === false) return next(); checkInstall(url, function(err, installed) { if (installed !== true) { return res.redirect('/cms/setup'); } //create the context var r = { url: url, lowerUrl: utils.lowercaseUrl(url) }; //get the mode (preview, design, live) var qMode = req.query.cmsmode; if (qMode === 'preview' || qMode === 'design') { //set cookie and redirect to page without mode in query string res.cookie('cmsmode', qMode, {path: '/'}); var redirectUrl = utils.removeQueryStringParameter(url, 'cmsmode'); res.redirect(redirectUrl); return; } //get the cms mode from the cookie var cookieMode = req.cookies['cmsmode']; if (cookieMode && (cookieMode === 'preview' || cookieMode === 'design')) r.mode = cookieMode; else r.mode = 'live'; //validate the mode and user if (r.mode === 'preview' || r.mode === 'design') { if (req.user && api.users.isCMSUser(req.user)) { r.user = req.user; } else { //return 401 unauthorized request logger.warn('Unauthorized request to page: ' + req.url); res.clearCookie('cmsmode'); res.send(401, "Unauthorized request"); return; } } //clean up the URL and remove the query string var i = url.indexOf('?'); if (i === -1) r.cleanUrl = url.toLowerCase(); else r.cleanUrl = S(url).left(i).s; //determine the correct collection r.collection = (r.mode === 'preview' || r.mode === 'design') ? 'drafts' : 'published'; //see if there is output in the cache var cacheKey = r.collection === 'published' ? "output:" + r.lowerUrl : null; cache.get(cacheKey, function(err, result) { if (result) { if (result.mime && result.mime !== '') res.setHeader('content-type', result.mime); res.send(result.text); } else { //look up this page in the CMS api.content.getContent({url: r.cleanUrl, collection: r.collection}, function(err, item) { if (err) { res.send(500, 'Error retrieving the page for this URL.'); } else if (item) { //now render this page logger.debug("Found content item: " + r.cleanUrl); api.content.renderContent(req, res, r, item, function(err, text) { if (!err) { //if this template supports caching if (text && item.template && item.template.cacheSeconds && item.template.cacheSeconds > 0) { var mime = item.type ? item.type.mime : null; if (mime === '') mime = null; var obj = { mime: mime, text: text }; cache.set(cacheKey, obj, item.template.cacheSeconds); } } }); } else { logger.warn("Page not found: " + r.cleanUrl); next(); } }); } }); }); } catch(e) { logger.error(e); res.send(500, 'Error retrieving the page for this URL.'); } } function checkInstall(url, callback) { if (url && config.settings && config.settings.check_install === true && (url === '/' || url === '/cms')) { api.sysdocs.isInstalled(callback); } else callback(null, true); //true means already installed } function shouldProcessUrl (url) { if (url && _paths) { url = url.toLowerCase(); for(var i = 0; i < _paths.length; i++) { if (S(url).startsWith(_paths[i])) return false; } } return true; };