2013-05-11 20:44:25 +04:00
|
|
|
// # Ghost Module
|
2013-08-06 23:27:56 +04:00
|
|
|
// Defines core methods required to build the application
|
2013-05-11 20:44:25 +04:00
|
|
|
|
2013-08-06 23:27:56 +04:00
|
|
|
// Module dependencies
|
2013-11-20 17:58:52 +04:00
|
|
|
var config = require('./server/config'),
|
|
|
|
when = require('when'),
|
|
|
|
express = require('express'),
|
|
|
|
errors = require('./server/errorHandling'),
|
|
|
|
_ = require('underscore'),
|
|
|
|
url = require('url'),
|
|
|
|
models = require('./server/models'),
|
|
|
|
permissions = require('./server/permissions'),
|
|
|
|
uuid = require('node-uuid'),
|
2013-08-06 23:27:56 +04:00
|
|
|
|
|
|
|
// Variables
|
2013-06-25 15:43:15 +04:00
|
|
|
Ghost,
|
2013-11-28 06:45:01 +04:00
|
|
|
instance;
|
2013-06-25 15:43:15 +04:00
|
|
|
|
|
|
|
// ## Module Methods
|
|
|
|
/**
|
|
|
|
* @method Ghost
|
|
|
|
* @returns {*}
|
|
|
|
* @constructor
|
|
|
|
*/
|
|
|
|
Ghost = function () {
|
|
|
|
|
|
|
|
if (!instance) {
|
|
|
|
instance = this;
|
|
|
|
|
2013-08-03 19:11:16 +04:00
|
|
|
// Holds the persistent notifications
|
|
|
|
instance.notifications = [];
|
|
|
|
|
2013-08-24 04:02:01 +04:00
|
|
|
// Holds the dbhash (mainly used for cookie secret)
|
|
|
|
instance.dbHash = undefined;
|
|
|
|
|
2013-06-25 15:43:15 +04:00
|
|
|
_.extend(instance, {
|
|
|
|
// there's no management here to be sure this has loaded
|
2013-09-15 21:52:37 +04:00
|
|
|
settings: function (key) {
|
|
|
|
if (key) {
|
|
|
|
return instance.settingsCache[key].value;
|
|
|
|
}
|
|
|
|
return instance.settingsCache;
|
|
|
|
},
|
2013-06-25 15:43:15 +04:00
|
|
|
dataProvider: models,
|
2013-09-02 21:27:26 +04:00
|
|
|
blogGlobals: function () {
|
2013-11-20 17:58:52 +04:00
|
|
|
var localPath = url.parse(config().url).path;
|
2013-11-17 22:40:26 +04:00
|
|
|
|
|
|
|
// Remove trailing slash
|
|
|
|
if (localPath !== '/') {
|
|
|
|
localPath = localPath.replace(/\/$/, '');
|
|
|
|
}
|
|
|
|
|
2013-09-02 21:27:26 +04:00
|
|
|
/* this is a bit of a hack until we have a better way to combine settings and config
|
|
|
|
* this data is what becomes globally available to themes */
|
|
|
|
return {
|
2013-11-20 17:58:52 +04:00
|
|
|
url: config().url.replace(/\/$/, ''),
|
2013-11-17 22:40:26 +04:00
|
|
|
path: localPath,
|
2013-09-15 21:52:37 +04:00
|
|
|
title: instance.settings('title'),
|
|
|
|
description: instance.settings('description'),
|
|
|
|
logo: instance.settings('logo'),
|
|
|
|
cover: instance.settings('cover')
|
2013-09-02 21:27:26 +04:00
|
|
|
};
|
2013-11-28 06:45:01 +04:00
|
|
|
}
|
2013-06-25 15:43:15 +04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
return instance;
|
|
|
|
};
|
2013-06-16 20:14:01 +04:00
|
|
|
|
2013-08-06 23:27:56 +04:00
|
|
|
// Initialise the application
|
2013-06-25 15:43:15 +04:00
|
|
|
Ghost.prototype.init = function () {
|
|
|
|
var self = this;
|
2013-05-11 20:44:25 +04:00
|
|
|
|
2013-09-18 04:35:46 +04:00
|
|
|
function doFirstRun() {
|
|
|
|
var firstRunMessage = [
|
2013-09-24 07:37:36 +04:00
|
|
|
'Welcome to Ghost.',
|
|
|
|
'You\'re running under the <strong>',
|
2013-09-18 04:35:46 +04:00
|
|
|
process.env.NODE_ENV,
|
2013-09-24 07:37:36 +04:00
|
|
|
'</strong>environment.',
|
2013-09-18 04:35:46 +04:00
|
|
|
|
2013-09-24 07:37:36 +04:00
|
|
|
'Your URL is set to',
|
2013-11-20 17:58:52 +04:00
|
|
|
'<strong>' + config().url + '</strong>.',
|
2013-09-24 07:37:36 +04:00
|
|
|
'See <a href="http://docs.ghost.org/">http://docs.ghost.org</a> for instructions.'
|
2013-09-18 04:35:46 +04:00
|
|
|
];
|
|
|
|
|
|
|
|
self.notifications.push({
|
|
|
|
type: 'info',
|
|
|
|
message: firstRunMessage.join(' '),
|
|
|
|
status: 'persistent',
|
|
|
|
id: 'ghost-first-run'
|
|
|
|
});
|
|
|
|
return when.resolve();
|
|
|
|
}
|
2013-09-15 20:03:31 +04:00
|
|
|
|
2013-09-18 04:35:46 +04:00
|
|
|
function initDbHashAndFirstRun() {
|
2013-08-24 04:02:01 +04:00
|
|
|
return when(models.Settings.read('dbHash')).then(function (dbhash) {
|
|
|
|
// we already ran this, chill
|
|
|
|
self.dbHash = dbhash.attributes.value;
|
|
|
|
return dbhash.attributes.value;
|
|
|
|
}).otherwise(function (error) {
|
2013-10-31 22:02:34 +04:00
|
|
|
/*jslint unparam:true*/
|
2013-08-24 04:02:01 +04:00
|
|
|
// this is where all the "first run" functionality should go
|
|
|
|
var dbhash = uuid.v4();
|
2013-09-18 04:35:46 +04:00
|
|
|
return when(models.Settings.add({key: 'dbHash', value: dbhash, type: 'core'})).then(function () {
|
2013-08-24 04:02:01 +04:00
|
|
|
self.dbHash = dbhash;
|
|
|
|
return dbhash;
|
2013-09-18 04:35:46 +04:00
|
|
|
}).then(doFirstRun);
|
2013-08-24 04:02:01 +04:00
|
|
|
});
|
2013-09-18 04:35:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// ### Initialisation
|
|
|
|
return when.join(
|
|
|
|
// Initialise the models
|
2013-09-24 07:37:36 +04:00
|
|
|
self.dataProvider.init(),
|
2013-09-18 04:35:46 +04:00
|
|
|
// Calculate paths
|
2013-11-28 06:45:01 +04:00
|
|
|
config.paths.updatePaths()
|
2013-09-18 04:35:46 +04:00
|
|
|
).then(function () {
|
|
|
|
// Populate any missing default settings
|
|
|
|
return models.Settings.populateDefaults();
|
|
|
|
}).then(function () {
|
|
|
|
// Initialize the settings cache
|
|
|
|
return self.updateSettingsCache();
|
|
|
|
}).then(function () {
|
2013-11-20 17:58:52 +04:00
|
|
|
// Update path to activeTheme
|
|
|
|
config.paths.setActiveTheme(self);
|
2013-09-18 04:35:46 +04:00
|
|
|
return when.join(
|
|
|
|
// Check for or initialise a dbHash.
|
|
|
|
initDbHashAndFirstRun(),
|
|
|
|
// Initialize the permissions actions and objects
|
|
|
|
permissions.init()
|
|
|
|
);
|
|
|
|
}).otherwise(errors.logAndThrowError);
|
2013-06-25 15:43:15 +04:00
|
|
|
};
|
2013-05-11 20:44:25 +04:00
|
|
|
|
2013-08-06 23:27:56 +04:00
|
|
|
// Maintain the internal cache of the settings object
|
2013-06-25 15:43:15 +04:00
|
|
|
Ghost.prototype.updateSettingsCache = function (settings) {
|
|
|
|
var self = this;
|
2013-06-09 20:16:25 +04:00
|
|
|
|
2013-06-25 15:43:15 +04:00
|
|
|
settings = settings || {};
|
2013-06-09 20:16:25 +04:00
|
|
|
|
2013-06-25 15:43:15 +04:00
|
|
|
if (!_.isEmpty(settings)) {
|
2013-09-15 20:03:31 +04:00
|
|
|
_.map(settings, function (setting, key) {
|
|
|
|
self.settingsCache[key].value = setting.value;
|
|
|
|
});
|
2013-06-25 15:43:15 +04:00
|
|
|
} else {
|
|
|
|
// TODO: this should use api.browse
|
2013-09-15 20:03:31 +04:00
|
|
|
return when(models.Settings.findAll()).then(function (result) {
|
|
|
|
return when(self.readSettingsResult(result)).then(function (s) {
|
|
|
|
self.settingsCache = s;
|
2013-06-25 15:43:15 +04:00
|
|
|
});
|
2013-09-15 20:03:31 +04:00
|
|
|
});
|
2013-06-25 15:43:15 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-09-15 20:03:31 +04:00
|
|
|
Ghost.prototype.readSettingsResult = function (result) {
|
|
|
|
var settings = {};
|
|
|
|
return when(_.map(result.models, function (member) {
|
|
|
|
if (!settings.hasOwnProperty(member.attributes.key)) {
|
|
|
|
var val = {};
|
2013-09-15 21:52:37 +04:00
|
|
|
val.value = member.attributes.value;
|
|
|
|
val.type = member.attributes.type;
|
|
|
|
settings[member.attributes.key] = val;
|
2013-09-15 20:03:31 +04:00
|
|
|
}
|
|
|
|
})).then(function () {
|
2013-11-20 17:58:52 +04:00
|
|
|
return when(config.paths().availableThemes).then(function (themes) {
|
2013-09-15 20:03:31 +04:00
|
|
|
var themeKeys = Object.keys(themes),
|
|
|
|
res = [],
|
|
|
|
i,
|
|
|
|
item;
|
|
|
|
for (i = 0; i < themeKeys.length; i += 1) {
|
|
|
|
//do not include hidden files
|
|
|
|
if (themeKeys[i].indexOf('.') !== 0) {
|
|
|
|
item = {};
|
|
|
|
item.name = themeKeys[i];
|
|
|
|
//data about files currently not used
|
|
|
|
//item.details = themes[themeKeys[i]];
|
|
|
|
if (themeKeys[i] === settings.activeTheme.value) {
|
|
|
|
item.active = true;
|
|
|
|
}
|
|
|
|
res.push(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
settings.availableThemes = {};
|
|
|
|
settings.availableThemes.value = res;
|
|
|
|
settings.availableThemes.type = 'theme';
|
|
|
|
return settings;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2013-09-15 01:34:12 +04:00
|
|
|
module.exports = Ghost;
|