Add API limits configurable in settings.json

This commit is contained in:
Gaël Métais
2014-12-12 20:26:19 +01:00
parent 84faabca86
commit 0da2ad0c10
7 changed files with 202 additions and 152 deletions
-52
View File
@@ -1,52 +0,0 @@
var config = require('../../server_config/settings.json');
var jwt = require('jwt-simple');
var debug = require('debug')('authMiddleware');
var authMiddleware = function(req, res, next) {
'use strict';
if (req.path.indexOf('/api/') === 0) {
// Test if it's an authorized key
if (req.headers && req.headers['x-api-key'] && isApiKeyValid(req.headers['x-api-key'])) {
next();
return;
}
// Test if it's an authorized token
if (req.headers && req.headers['x-api-token'] && isTokenValid(req.headers['x-api-token'])) {
next();
return;
}
res.status(401).send('Unauthorized');
}
};
function isApiKeyValid(apiKey) {
return (config.authorizedKeys[apiKey]) ? true : false;
}
function isTokenValid(token) {
var data = null;
try {
data = jwt.decode(token, config.tokenSalt);
} catch(err) {
debug('Error while decoding token');
debug(err);
return false;
}
return data.expire &&
data.expire > Date.now() &&
data.application &&
config.authorizedApplications.indexOf(data.application) >= 0;
}
module.exports = authMiddleware;
@@ -0,0 +1,85 @@
var config = require('../../../server_config/settings.json');
var debug = require('debug')('apiLimitsMiddleware');
var apiLimitsMiddleware = function(req, res, next) {
'use strict';
debug('Entering API Limits Middleware with IP address %s', req.connection.remoteAddress);
if (req.path.indexOf('/api/') === 0 && !res.locals.hasApiKey) {
if (req.path === '/api/runs') {
if (!runsTable.accepts(req.connection.remoteAddress)) {
// Sorry :/
debug('Too many tests launched from IP address %s', req.connection.remoteAddress);
res.status(429).send('Too Many Requests');
return;
}
}
if (!callsTable.accepts(req.connection.remoteAddress)) {
// Sorry :/
debug('Too many API requests from IP address %s', req.connection.remoteAddress);
res.status(429).send('Too Many Requests');
return;
}
debug('Not blocked by the API limits');
// It's ok for the moment
}
next();
};
var RecordTable = function(maxPerDay) {
var table = {};
// Check if the user overpassed the limit and save its visit
this.accepts = function(ipAddress) {
if (table[ipAddress]) {
this.cleanEntry(ipAddress);
debug('%d visits in the last 24 hours', table[ipAddress].length);
if (table[ipAddress].length >= maxPerDay) {
return false;
} else {
table[ipAddress].push(Date.now());
}
} else {
table[ipAddress] = [];
table[ipAddress].push(Date.now());
}
return true;
};
// Clean the table for this guy
this.cleanEntry = function(ipAddress) {
table[ipAddress] = table[ipAddress].filter(function(date) {
return date > Date.now() - 1000*60*60*24;
});
};
// Clean the entire table once in a while
this.removeOld = function() {
for (var ipAddress in table) {
this.cleanEntry(ipAddress);
}
};
};
// Init the records tables
var runsTable = new RecordTable(config.maxAnonymousRunsPerDay);
var callsTable = new RecordTable(config.maxAnonymousCallsPerDay);
module.exports = apiLimitsMiddleware;
+42
View File
@@ -0,0 +1,42 @@
var config = require('../../../server_config/settings.json');
var debug = require('debug')('authMiddleware');
var authMiddleware = function(req, res, next) {
'use strict';
if (req.path.indexOf('/api/') === 0) {
if (req.headers && req.headers['x-api-key']) {
// Test if it's an authorized key
if (isApiKeyValid(req.headers['x-api-key'])) {
// Come in!
debug('Authorized key: %s', req.headers['x-api-key']);
res.locals.hasApiKey = true;
} else {
// Sorry :/
debug('Unauthorized key %s', req.headers['x-api-key']);
res.status(401).send('Unauthorized');
return;
}
} else {
debug('No authorization key');
// It's ok for the moment but you might be blocked by the apiLimitsMiddleware, dude
}
}
next();
};
function isApiKeyValid(apiKey) {
return (config.authorizedKeys[apiKey]) ? true : false;
}
module.exports = authMiddleware;