sheercms
Version:
Sheer Cliff CMS is a simple and powerful content management system (CMS) for Node JS.
354 lines (309 loc) • 13.4 kB
JavaScript
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;
};