Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Razvan Botea committed Oct 9, 2015
2 parents c38648d + e111000 commit b76cbaf
Show file tree
Hide file tree
Showing 23 changed files with 4,309 additions and 1,492 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ before_install:
before_script:
- telepat configure elasticsearch
- bash .travis/start.sh
- 'echo "script.disable_dynamic: false" | sudo tee -a /etc/elasticsearch/elasticsearch.yml'
- 'echo "script.groovy.sandbox.enable: true" | sudo tee -a /etc/elasticsearch/elasticsearch.yml'
after_script:
- codeclimate-test-reporter < coverage/lcov.info
node_js:
Expand Down
17 changes: 14 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# 0.2.5

* Fixed `/user/update` when updating password
* Further improved the tests, now each test has an ID displayed for easy lookup. Tests should run faster.
* Variable checks for message queue client and main database
* Added pagination support for subscribe requests
* Removed `tokenValidation` in object routes because `objectACL` was already doing that
* `/object/count` should now work
* Applications loaded on boot up are saved in Application object from telepat-models
* Fixed some minor bugs

# 0.2.4

* Implemented /admin/authorize and /admin/deauthorize to add/remove admins to an application
Expand All @@ -12,7 +23,7 @@
* Implemented mocha tests, added istanbul code coverage and integrated with travis CI
* Lots of bug fixes
* All update endpoints require patches
* Admin routes are sepparated in more than 1 file
* Admin routes are separated in more than 1 file
* Passwords are stored using bcrypt
* There's only one configuration file in the root folder. The example provided should be used. The original config file
was added to .gitignore
Expand All @@ -21,7 +32,7 @@ was added to .gitignore

* Fixed lots of bugs and server crashes
* User info is returned on login calls (user & admin)
* Sepparated user login and user register endpoints
* Separated user login and user register endpoints
* Admin endpoint for deleting users sends messages to aggregator to delete objects (1 message per object removed)
* Standardized /admin endpoints responses
* Each patch from /object/update is sent in 1 message to the aggregator
Expand All @@ -45,7 +56,7 @@ was added to .gitignore

* Application ID is verified if it exists in all requests that require it
* Standardized response of get context and get all contexts
* The npm package now requires the corect telepat-models module from the npm registry
* The npm package now requires the correct telepat-models module from the npm registry

# 0.1.4

Expand Down
77 changes: 36 additions & 41 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ if (validEnvVariables) {
messagingClient = mainConfiguration.message_queue;
}

if (!Models[mainDatabase]) {
console.log('Unable to load'.red+' "'+mainDatabase+'" main database: not found.\nAborting...');
process.exit(-1);
}

Models.Application.datasource = new Models.Datasource();
Models.Application.datasource.setMainDatabase(new Models[mainDatabase](mainConfiguration[mainDatabase]));

Expand All @@ -89,30 +94,25 @@ if(mainConfiguration.passwordSalt === undefined || mainConfiguration.passwordSal
}
app.set('password_salt', mainConfiguration.passwordSalt);

app.applications = {};

app.use(function(req, res, next) {
if (dbConnected)
return next();
res.type('application/json');
next(new Models.TelepatError(Models.TelepatError.errors.ServerNotAvailable));
});

var loadApplications = function() {
Models.Application.getAll(function(err, results) {
var loadApplications = function(callback) {
Models.Application.loadAllApplications(function(err) {
if (err) {
console.log('Fatal error: '.red+' in retrieving all aplications', err);
process.exit(-1);
}

async.each(results, function(item, c){
app.applications[item.id] = item;
c();
});
callback();
});
};

var linkMiddlewaresAndRoutes = function() {
var linkMiddlewaresAndRoutes = function(callback) {
app.use(security.corsValidation);
app.use(security.contentTypeValidation);
app.use(logger('dev'));
Expand All @@ -123,9 +123,10 @@ var linkMiddlewaresAndRoutes = function() {
app.use('/user', userRoute);
app.use('/context', contextRoute);
app.use('/device', deviceRoute);
callback();
};

var linkErrorHandlingMiddlewares = function() {
var linkErrorHandlingMiddlewares = function(callback) {
// error handlers
// catch 404 and forward to error handler
app.use(function(req, res, next) {
Expand All @@ -149,30 +150,35 @@ var linkErrorHandlingMiddlewares = function() {

res.json(responseBody).end();
});
callback();
};

var monitorUsrSignals = function() {
var monitorUsrSignals = function(callback) {
//signal sent by nodemon when restarting the server
process.on('SIGUSR2', function() {
app.kafkaClient.close();
});
callback();
};

var OnServicesConnect = function() {
dbConnected = true;
loadApplications();
linkMiddlewaresAndRoutes();
linkErrorHandlingMiddlewares();
monitorUsrSignals();
async.series([
loadApplications,
linkMiddlewaresAndRoutes,
linkErrorHandlingMiddlewares,
monitorUsrSignals
], function() {
dbConnected = true;
});
};

async.waterfall([
function DataBucket(callback) {
function(callback) {
Models.Application.datasource.dataStorage.onReady(function() {
callback();
});
},
function RedisClient(callback) {
function(callback) {
if (Models.Application.redisClient)
Models.Application.redisClient = null;

Expand All @@ -186,33 +192,22 @@ async.waterfall([
callback();
});
},
function Kafka(callback) {
function(callback) {
console.log('Waiting for Messaging Client connection...');

var kafkaConfiguration = mainConfiguration[messagingClient];
var clientConfiguration = mainConfiguration[messagingClient];

app.messagingClient = new Models[messagingClient](kafkaConfiguration, 'telepat-api');
app.messagingClient.on('ready', function() {
console.log(('Connected to Messaging Client '+messagingClient).green);
callback();
});
app.messagingClient.on('error', function(err) {
console.log('Messaging client not available.'.red+' Trying to reconnect.'+err);
});

/*app.kafkaClient = new kafka.Client(app.kafkaConfig.host+':'+app.kafkaConfig.port+'/',
app.kafkaConfig.clientName);
app.kafkaClient.on('ready', function() {
console.log('Client connected to Zookeeper.'.green);
app.kafkaProducer = new kafka.HighLevelProducer(app.kafkaClient);
app.kafkaProducer.on('error', function() {});
if (!Models[messagingClient]) {
console.log('Unable to load'.red+' "'+messagingClient+'" messaging queue: not found. Aborting...');
process.exit(-1);
}

callback();
});
app.kafkaClient.on('error', function() {
console.log('Kafka broker not available.'.red+' Trying to reconnect.');
});*/
clientConfiguration = clientConfiguration || {broadcast: false};
/**
* @type {MessagingClient}
*/
app.messagingClient = new Models[messagingClient](clientConfiguration, 'telepat-api');
app.messagingClient.onReady(callback);
}
], OnServicesConnect);

Expand Down
9 changes: 7 additions & 2 deletions config.example.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"main_database": "ElasticSearch",
"message_queue": "Kafka",
"message_queue": "kafka",
"ElasticSearch": {
"host": "hostname",
"port": 9200,
Expand All @@ -10,9 +10,14 @@
"host": "10.0.0.1",
"port": 6379
},
"Kafka": {
"kafka": {
"host": "10.0.0.2",
"port": 2181
},
"amqp": {
"host": "10.0.0.4",
"user": "telepat",
"password": "password"
},
"password_salt": "$2a$10$N9qo8uLOickgx2ZMRZoMye"
}
39 changes: 20 additions & 19 deletions controllers/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ var userRoute = require('./admin/user');
var security = require('./security');
var Models = require('telepat-models');

var unless = function(paths, middleware) {
return function(req, res, next) {
var excluded = false;
for (var i=0; i<paths.length; i++) {
if (paths[i] === req.path) {
excluded = true;
}
}
if (excluded) {
return next();
} else {
return middleware(req, res, next);
}
};
};
/* var unless = function(paths, middleware) {
return function(req, res, next) {
var excluded = false;
for (var i=0; i<paths.length; i++) {
if (paths[i] === req.path) {
excluded = true;
}
}
if (excluded) {
return next();
} else {
return middleware(req, res, next);
}
};
};*/

router.use('/', adminRoute);
router.use('/app', appRoute);
Expand All @@ -40,7 +40,7 @@ router.use('/contexts',
security.adminAppValidation);
/**
* @api {get} /admin/contexts GetContexts
* @apiDescription Get all contexsts
* @apiDescription Get all contexts
* @apiName AdminGetContexts
* @apiGroup Admin
* @apiVersion 0.2.3
Expand Down Expand Up @@ -133,7 +133,7 @@ router.use('/users',
security.adminAppValidation);
/**
* @api {get} /admin/users GetAppusers
* @apiDescription Gets all users of the app
* @apiDescription Gets all users of the application
* @apiName AdminGetUsers
* @apiGroup Admin
* @apiVersion 0.2.3
Expand All @@ -155,8 +155,9 @@ router.use('/users',
*
*/

router.get('/users', function(req, res, next) {
Models.User.getAll(req._telepat.applicationId, function(err, results) {
router.post('/users', function(req, res, next) {
var page = req.body.page ? req.body.page : 1;
Models.User.getAll(req._telepat.applicationId, page, function(err, results) {
if (err) return next(err);

results.forEach(function(item, index, originalArray) {
Expand Down
10 changes: 5 additions & 5 deletions controllers/admin/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ router.post('/login', function (req, res, next) {
*
* @apiHeader {String} Content-type application/json
*
* @apiParam {String} email (REQUIRED) Admin e-mail
* @apiParam {String} email (REQUIRED) Admin email
* @apiParam {String} password (REQUIRED) The password
* @apiParam {String} name Real name of the admin
*
Expand Down Expand Up @@ -164,7 +164,7 @@ router.use('/update', security.tokenValidation);
/**
* @api {post} /admin/update Update
* @apiDescription Updates the currently logged admin.
Every property in the request body is used to udpate the admin.
Every property in the request body is used to update the admin.
* @apiName AdminUpdate
* @apiGroup Admin
* @apiVersion 0.2.3
Expand Down Expand Up @@ -281,9 +281,9 @@ router.use('/apps', security.tokenValidation);
*/
router.get('/apps', function (req, res, next) {
var adminApps = [];
async.each(Object.keys(app.applications), function(applicationId, c){
if (app.applications[applicationId].admins.indexOf(req.user.id) !== -1)
adminApps.push(app.applications[applicationId]);
async.each(Object.keys(Models.Application.loadedAppModels), function(applicationId, c){
if (Models.Application.loadedAppModels[applicationId].admins.indexOf(req.user.id) !== -1)
adminApps.push(Models.Application.loadedAppModels[applicationId]);
c();
}, function(err) {
if (err) return next(err);
Expand Down
Loading

0 comments on commit b76cbaf

Please sign in to comment.