Skip to content

Commit

Permalink
skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbeletsky committed Mar 22, 2015
1 parent f80fce3 commit d7a3eca
Show file tree
Hide file tree
Showing 22 changed files with 368 additions and 1 deletion.
26 changes: 26 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
var express = require('express');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var morgan = require('morgan');
var cors = require('cors');

var middleware = require('./source/middleware');
var logger = require('./source/utils/logger');

var app = express();
var env = process.env.NODE_ENV || 'development';
var port = process.env.PORT || 3010;

morgan.format('custom', ':method :url :req[content-type] :req[content-length] HTTP/:http-version :status :res[content-length] - :response-time ms');
app.use(morgan('custom', {stream: logger.stream()}));

app.use(bodyParser.json());
app.use(methodOverride());
app.use(cors());

require('./source/api')(app);
app.use(middleware.errors());

app.listen(port, function () {
logger.info('editor-api listening on port ' + port + ' ' + env);
});
7 changes: 7 additions & 0 deletions config/development.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var config = {
logentries: {
token: null
}
};

module.exports = config;
6 changes: 6 additions & 0 deletions config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
var util = require('util');

var env = process.env.NODE_ENV || 'development';
var config = util.format('/%s.config.js', env);

module.exports = require(__dirname + config);
7 changes: 7 additions & 0 deletions config/production.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var config = {
logentries: {
token: null
}
};

module.exports = config;
7 changes: 7 additions & 0 deletions config/staging.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var config = {
logentries: {
token: null
}
};

module.exports = config;
7 changes: 7 additions & 0 deletions config/test.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var config = {
logentries: {
token: null
}
};

module.exports = config;
14 changes: 13 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"dependencies": {
"async": "^0.9.0",
"body-parser": "^1.9.0",
"colors": "^1.0.2",
"cors": "^2.4.2",
"express": "^4.9.5",
"method-override": "^2.2.0",
"moment": "^2.8.3",
"morgan": "^1.3.2",
"node-logentries": "^0.1.4",
"respawn": "^1.0.1"
},
"author": "alexander.beletsky@gmail.com",
"license": "ISC"
}
2 changes: 2 additions & 0 deletions source/api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module.exports = function (app) {
};
8 changes: 8 additions & 0 deletions source/middleware/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

function auth() {
return function (req, res, next) {
next();
};
}

module.exports = auth;
17 changes: 17 additions & 0 deletions source/middleware/checkId.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
function checkId(param) {
return function (req, res, next) {
var id = +req.query[param];

if (!id) {
return next({message: 'missing ' + param, status: 412});
}

if (req.user.id !== id) {
return next({message: 'wrong ' + param, status: 401});
}

next();
};
}

module.exports = checkId;
20 changes: 20 additions & 0 deletions source/middleware/errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
var util = require('util');
var logger = require('../utils/logger');

function errors(err, req, res, next) {
function includeStack(stack) {
return process.env.NODE_ENV === 'production' ? [] : stack;
}

return function (err, req, res, next) {
err = util.isError(err) ? {message: err.message, stack: includeStack(err.stack)} : err;
if (!err.status) {
err.status = 500;
}

logger.error(err);
return !err.logOnly && res.status(err.status).json(err);
};
}

module.exports = errors;
8 changes: 8 additions & 0 deletions source/middleware/guest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
function guest () {
return function _guest (req, res, next) {
req.guestAccess = true;
next ();
};
}

module.exports = guest;
13 changes: 13 additions & 0 deletions source/middleware/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {
validate: require('./validate'),
errors: require('./errors'),
access: {
auth: require('./auth'),
id: require('./checkId'),
guest: require('./guest')
},
db: {
// mysql: require('./mysql'),
// mongo: require('./mongo')
}
};
19 changes: 19 additions & 0 deletions source/middleware/mongo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
var mongo = require('mongojs');

function createConnection(config) {
var connection, collections = ['shifts', 'demands', 'plannings', 'vacations'];

if (!connection) {
connection = mongo.connect(config.connection, collections);
if (!connection) {
throw new Error('could not connect to ' + config.connection);
}
}

return function (req, res, next) {
req.mongo = connection;
next();
};
}

module.exports = createConnection;
15 changes: 15 additions & 0 deletions source/middleware/mysql.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function createConnection(config) {
return function (req, res, next) {
req.getConnection(function (err, mysql) {
if (err) {
return next(err);
}

req.mysql = mysql;

next();
});
};
}

module.exports = createConnection;
26 changes: 26 additions & 0 deletions source/middleware/validate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
var schemas = require('../models/schemas');

module.exports = {
body: function (schema) {
return function (req, res, next) {
var result = schemas.validate(req.body, schema);

if (!result.valid) {
return res.status(412).json(result.errors);
}

next();
};
},
id: function (param) {
return function (req, res, next) {
var result = schemas.validateId(req.params[param]);

if (!result.valid) {
return res.status(412).json(result.errors);
}

next();
};
}
};
Empty file added source/models/schemas/index.js
Empty file.
11 changes: 11 additions & 0 deletions source/utils/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var middleware = require('../middleware');

function applyAuthentication(app, routesToSecure) {
routesToSecure.forEach(function (route) {
app.all(route + '/*', middleware.access.auth());
});

return app;
}

module.exports = applyAuthentication;
13 changes: 13 additions & 0 deletions source/utils/keys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function createKeyDrivers(region) {
return region + ':drivers';
}

function createKeyFromAddress(region, address) {
address = address.replace(/[, \.]+/g, ':').toLowerCase();
return region + ':addresses:' + address;
}

module.exports = {
address: createKeyFromAddress,
drivers: createKeyDrivers
};
88 changes: 88 additions & 0 deletions source/utils/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
require('colors');

var util = require('util');
var moment = require('moment');
var logentries = require('node-logentries');
var config = require('../../config');
var stub = require('./stub');

var log = logentries.logger({
token: config.logentries.token,
printerror: false
});

log.level('debug');

var logger = {
success: function (message) {
message = typeof message === 'string' ? message : JSON.stringify(message);
console.log(this.timestamptMessage(util.format('SUCCESS: %s', message)).green);
log.log('info', message);
},

warning: function (message) {
message = typeof message === 'string' ? message : JSON.stringify(message);
console.log(this.timestamptMessage(util.format('WARNING: %s', message)).yellow);
log.log('warning', message);
},

error: function (message) {
message = typeof message === 'string' ? message : JSON.stringify(message);
console.log(this.timestamptMessage(util.format('ERROR: %s', message)).red);
log.log('err', message);
},

fatal: function (message) {
message = typeof message === 'string' ? message : JSON.stringify(message);
console.log(this.timestamptMessage(util.format('ERROR: %s', message)).red);
log.log('emerg', message);
},

info: function (message) {
message = typeof message === 'string' ? message : JSON.stringify(message);
console.log(this.timestamptMessage(message));
log.log('info', message);
},

connector: function (name) {
var me = this;

return {
info: function (message) {
me.info('connector ' + name + ': ' + message);
},
warning: function (message) {
me.warning('connector ' + name + ': ' + message);
},
error: function (message) {
me.error('connector ' + name + ': ' + message);
},
success: function (message) {
me.success('connector ' + name + ': ' + message);
}
};
},

timestamptMessage: function (message) {
return util.format('[%s] %s', moment(), message);
},

stream: function () {
var me = this;

return {
write: function (message) {
me.info(message.replace('\n', ''));
}
};
}
};

module.exports = (function () {
var env = process.env.NODE_ENV || 'development';
if (env === 'test') {
return stub(logger, ['stream']);
}

return logger;
})();
11 changes: 11 additions & 0 deletions source/utils/stub.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function stub(obj, skip) {
Object.keys(obj).forEach(function (key) {
if (typeof obj[key] === 'function' && skip.indexOf(key) < 0) {
obj[key] = function () {};
}
});

return obj;
}

module.exports = stub;
44 changes: 44 additions & 0 deletions source/utils/tenancy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
var util = require('util');
var _ = require('underscore');

var tenantFields = [
'id',
'firstname',
'lastname',
'email',
'countryCode',
'city',
'salesforceAccountID',
'workCapacity',
'isFulltimeEmployed'
];

function removeTenant(result) {
return _.omit(result, 'user');
}

function wrapCallback(callback) {
return function (err, results) {
if (err) {
return callback(err);
}

return util.isArray(results) ? callback(null, results.map(removeTenant)) : callback(null, removeTenant(results));
};
}

function tenancy(user, data) {
if (typeof user === 'function') {
return wrapCallback(user);
}

return _.extend(data, {user: _.pick(user, tenantFields)});
}

tenancy.query = function (user, query) {
return _.extend(query, {'user.id': user.id});
};

tenancy.fields = tenantFields;

module.exports = tenancy;

0 comments on commit d7a3eca

Please sign in to comment.