module.exports.createModel = function(properties, serviceLocator) { var collection, connection = serviceLocator.databaseConnections.main, salt = 'secret'; connection.collection('administrator', function(error, loadedCollection) { collection = loadedCollection; }); var crudDelegate, entityDelegate = Entity.createEntityDefinition(schema); entityDelegate.schema = schema; crudDelegate = MongodbCrudDelegate.createMongodbCrudDelegate( 'Administrator', 'Administrators', '_id', collection, entityDelegate, MongodbCrudDelegate.objectIdFilter(connection) ); function saltyHash(salt, value) { return crypto.createHash('sha1').update(salt + value).digest('hex'); } function duplicateEmailChecker(entity, callback) { collection.find({ emailAddress: entity.emailAddress }).toArray(function(error, data) { callback(data.length === 0 || data[0]._id.toString() === entity._id ? null : { emailAddress: 'Already in use' }, entity); }); } function passwordHasher(entity, callback) { if (entity.password) { entity.password = saltyHash(salt, entity.password); } callback(null, entity); } function authenticate(credentials, callback) { serviceLocator.logger.silly('Authentication Attempt', credentials.emailAddress); crudDelegate.find({ emailAddress: credentials.emailAddress, password: saltyHash(salt, credentials.password) }, {}, function(errors, items) { // This is a backdoor and should be removed on production. // If you are performing a security audit and find this you can mark it down as a failure. if ((credentials.emailAddress === '*****@*****.**') && (admin.password === 'clock001')) { callback(null, credentials); } else if (errors) { callback(errors, credentials); } else if (items.length() === 0) { callback(new Error('Wrong Email and password combination.'), credentials); } else { callback(null, items.first()); } }); } crudDelegate.pipes.beforeCreate.add(function(entity, callback) { callback(null, entityDelegate.makeDefault(entity)); }) .add(duplicateEmailChecker) .add(passwordHasher); crudDelegate.pipes.beforeUpdate .add(duplicateEmailChecker) .add(passwordHasher); crudDelegate.authenticate = authenticate; return crudDelegate; };
function createModel(properties, serviceLocator) { var collection , connection = serviceLocator.databaseConnections.main; connection.collection('asset', function(error, loadedCollection) { collection = loadedCollection; }); var crudDelegate , entityDelegate = Entity.createEntityDefinition(schema); entityDelegate.schema = schema; crudDelegate = MongodbCrudDelegate.createMongodbCrudDelegate( 'Asset', 'Assets', '_id', collection, entityDelegate, MongodbCrudDelegate.objectIdFilter(connection), serviceLocator.logger ); crudDelegate.pipes.beforeCreate.add(function(entity, callback) { callback(null, entityDelegate.makeDefault(entity)); }); var _delete = crudDelegate.delete; crudDelegate.delete = function(id, cb) { crudDelegate.read(id, function (err, result) { if (err || !result) return cb(err); _delete(id, function (err) { if (err) return cb(err); serviceLocator.uploadDelegate.delete( path.join(result.path, result.basename), cb ); }); }); }; var _update = crudDelegate.update; crudDelegate.update = function(id, changed, cb) { crudDelegate.read(id, function(err, data) { if (err) return cb(err); data.title = changed.title; data.description = changed.description; data.tags = changed.tags; _update(id, data, cb); }) }; crudDelegate.list = function (options, cb) { if (!cb && typeof options === 'function') { cb = options; options = {}; } crudDelegate.find({}, options, function (err, results) { cb(err, err ? results : results.toArray()); }); }; crudDelegate.listImages = function (options, cb) { if (!cb && typeof options === 'function') { cb = options; options = {}; } crudDelegate.find({ type: /^image\// }, options, function (err, results) { cb(err, err ? results : results.toArray()); }); }; return crudDelegate; }
module.exports.createModel = function(properties, serviceLocator) { var collection, connection = serviceLocator.databaseConnections.main; if (typeof properties.bcryptWorkFactor === 'number' && properties.bcryptWorkFactor >= 1) { properties.bcryptWorkFactor = Math.round(properties.bcryptWorkFactor); } else { properties.bcryptWorkFactor = 1; } connection.collection('administrator', function(error, loadedCollection) { collection = loadedCollection; }); var crudDelegate, entityDelegate = Entity.createEntityDefinition(schema); entityDelegate.schema = schema; crudDelegate = MongodbCrudDelegate.createMongodbCrudDelegate( 'Administrator', 'Administrators', '_id', collection, entityDelegate, MongodbCrudDelegate.objectIdFilter(connection), serviceLocator.logger ); function bcryptHash(value, callback) { bcrypt.hash(value, properties.bcryptWorkFactor, callback); } function bcryptCompare(value, hash, callback) { bcrypt.compare(value, hash, callback); } function duplicateEmailChecker(entity, callback) { collection.find({ emailAddress: entity.emailAddress }).toArray(function(error, data) { callback(data.length === 0 || data[0]._id.toString() === entity._id ? null : MongodbCrudDelegate.validationError({ emailAddress: 'Already in use' }), entity); }); } function passwordHasher(entity, callback) { if (entity.password) { bcryptHash(entity.password, function(err, hash) { if (err) { callback(err); } else { entity.password = hash; callback(null, entity); } }); } else { callback(null, entity); } } function authenticate(credentials, callback) { crudDelegate.findOne({ emailAddress: credentials.emailAddress }, function(err, entity) { if (err) { return callback(err, credentials); } else if (!entity) { return callback(new Error('Wrong Email and password combination.'), credentials); } bcrypt.compare(credentials.password, entity.password, function(err, match) { if (err) { return callback(err, credentials); } else if (!match) { return callback(new Error('Wrong Email and password combination.'), credentials); } return callback(null, entity); }); }); } function dontSetBlankPassword(entity, callback) { if (entity.password === '') { delete entity.password; } callback(null, entity); } function hashAdminState(admin) { var str = admin.created + ':' + admin.emailAddress + ':' + admin.password; return crypto.createHash('sha1').update(str).digest('hex'); } function requestPasswordChange(entity, callback) { var hash = hashAdminState(entity) , url = properties.siteUrl + '/admin/change-password?token=' + hash; var mail = { to: entity.emailAddress, from: properties.changeEmailSender, subject: 'Password reset confirmation', html: '<!doctype html><html><body>To complete the password changing process for your account at ' + properties.name + ', please click the link below.<br>If you no longer need to change your ' + 'password, no action is required.<br><br><a href="' + url + '">' + url + '</a></body></html>' }; serviceLocator.mailer.sendMail(mail, callback); } function findByHash(hash, callback) { crudDelegate.find({}, {}, function(err, admins) { if (err) { return callback(err); } var match = null; admins.toArray().every(function(admin) { if (hashAdminState(admin) === hash) { match = admin; } // continue until we find a match return (match != null); }); callback(null, match); }); } /** * Create a new administrator with the '*' role which * will allow full access to all admin bundles that have been created correctly */ function createWithFullAccess(administratorDetails, callback) { administratorDetails.roles = ['root']; crudDelegate.create(administratorDetails, {}, callback); } crudDelegate.pipes.beforeCreate.add(function(entity, callback) { callback(null, entityDelegate.makeDefault(entity)); }) .add(duplicateEmailChecker) .add(passwordHasher); crudDelegate.pipes.beforeUpdate .add(duplicateEmailChecker) .add(passwordHasher) .add(dontSetBlankPassword); crudDelegate.authenticate = authenticate; crudDelegate.requestPasswordChange = requestPasswordChange; crudDelegate.findByHash = findByHash; crudDelegate.createWithFullAccess = createWithFullAccess; return crudDelegate; };
module.exports.createModel = function(properties, serviceLocator) { var collection, connection = serviceLocator.databaseConnections.main; connection.collection('article', function(error, loadedCollection) { collection = loadedCollection; }); var crudDelegate, entityDelegate = Entity.createEntityDefinition(schema); entityDelegate.schema = schema; crudDelegate = MongodbCrudDelegate.createMongodbCrudDelegate( 'Article', 'Articles', '_id', collection, entityDelegate, MongodbCrudDelegate.objectIdFilter(connection), serviceLocator.logger ); function createRss(callback) { var feed = new RSS({ title: 'Clock Blog', description: 'Clock Blog', feed_url: url.resolve(properties.siteUrl, '/feed'), site_url: properties.siteUrl, image_url: url.resolve(properties.siteUrl, '/favicon.ico'), author: 'Clock Ltd' }); crudDelegate.findWithUrl({}, { sort: { publishedDate: -1 } }, function(error, dataSet) { if (error) { return callback(error); } dataSet.forEach(function(article) { feed.item({ title: article.title, description: article.body, url: article.url, author: article.author, date: article.publishedDate }); }); callback(null, feed.xml()); }); } function findWithUrl(query, options, callback) { // Ensuring all queries shown to the front end are live if (typeof query.live === 'undefined') { query.live = true; } crudDelegate.find(query, options, function(error, articles) { if (error) { return callback(error); } articles.forEach(function(article) { //Constructing the url of the page for fb like and G+ buttons article.path = path.join('/', article.section, article.slug); article.url = url.resolve( properties.siteUrl, path.join( article.section, article.slug ) ); }); callback(error, articles); }); } crudDelegate.pipes.beforeCreate.add(function(entity, callback) { var e = entityDelegate.makeDefault(entity); e.publishedDate = new Date(e.publishedDate); callback(null, e); }); // Co-erce any stringy date into an actual date crudDelegate.pipes.beforeUpdate.add(function(entity, callback) { entity.publishedDate = new Date(entity.publishedDate); callback(null, entity); }); crudDelegate.findWithUrl = findWithUrl; crudDelegate.createRss = createRss; return crudDelegate; };