示例#1
0
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;
};
示例#2
0
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;
}
示例#3
0
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;
};
示例#4
0
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;
};