Merge branch 'develop'
This commit is contained in:
commit
639eea00cc
8
Makefile
Normal file
8
Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
all:
|
||||
npm install
|
||||
|
||||
clean:
|
||||
rm -rf node_modules/*
|
||||
|
||||
check:
|
||||
npm test
|
@ -9,7 +9,8 @@ Provides a nodejs based API for running SQL queries against CartoDB.
|
||||
|
||||
core requirements
|
||||
-------------
|
||||
* postgres
|
||||
* postgres 9.0+
|
||||
* cartodb 0.9.5+ (for CDB_QueryTables)
|
||||
* redis
|
||||
* node > v0.4.8 && < v0.9.0
|
||||
* npm
|
||||
|
@ -37,7 +37,7 @@ app.all('/api/v1/sql.:f', function(req, res) { handleQuery(req, res) } );
|
||||
app.get('/api/v1/cachestatus', function(req, res) { handleCacheStatus(req, res) } );
|
||||
|
||||
// request handlers
|
||||
function handleQuery(req, res){
|
||||
function handleQuery(req, res) {
|
||||
|
||||
// extract input
|
||||
var body = (req.body) ? req.body : {};
|
||||
@ -50,8 +50,8 @@ function handleQuery(req, res){
|
||||
var dp = req.query.dp;
|
||||
|
||||
// sanitize and apply defaults to input
|
||||
dp = (dp === "" || _.isUndefined(dp)) ? '6' : dp;
|
||||
format = (format === "" || _.isUndefined(format)) ? null : format;
|
||||
dp = (dp === "" || _.isUndefined(dp)) ? '6' : dp;
|
||||
format = (format === "" || _.isUndefined(format)) ? null : format.toLowerCase();
|
||||
sql = (sql === "" || _.isUndefined(sql)) ? null : sql;
|
||||
database = (database === "" || _.isUndefined(database)) ? null : database;
|
||||
limit = (_.isNumber(limit)) ? limit : null;
|
||||
@ -75,12 +75,18 @@ function handleQuery(req, res){
|
||||
// 4. Run query with r/w or public user
|
||||
// 5. package results and send back
|
||||
Step(
|
||||
function getDatabaseName(){
|
||||
Meta.getDatabase(req, this);
|
||||
function getDatabaseName() {
|
||||
if (_.isNull(database)) {
|
||||
Meta.getDatabase(req, this);
|
||||
} else {
|
||||
// database hardcoded in query string (deprecated??): don't use redis
|
||||
return database;
|
||||
}
|
||||
},
|
||||
function setDBGetUser(err, data) {
|
||||
if (err) throw err;
|
||||
database = (data == "" || _.isNull(data) || _.isUndefined(data)) ? database : data;
|
||||
|
||||
database = (data === "" || _.isNull(data) || _.isUndefined(data)) ? database : data;
|
||||
|
||||
// If the database could not be found, the user is non-existant
|
||||
if (_.isNull(database)) {
|
||||
@ -152,11 +158,17 @@ function handleQuery(req, res){
|
||||
toCSV(result, res, this);
|
||||
} else {
|
||||
var end = new Date().getTime();
|
||||
return {
|
||||
'time' : ((end - start)/1000),
|
||||
'total_rows': result.rows.length,
|
||||
'rows' : result.rows
|
||||
};
|
||||
|
||||
var json_result = {'time' : (end - start)/1000};
|
||||
|
||||
if (result.command === 'SELECT') {
|
||||
json_result.total_rows = result.rows.length;
|
||||
json_result.rows = result.rows;
|
||||
} else {
|
||||
json_result.total_rows = result.rowCount;
|
||||
}
|
||||
|
||||
return json_result;
|
||||
}
|
||||
},
|
||||
function sendResults(err, out){
|
||||
|
@ -9,7 +9,8 @@ var RedisPool = require("./redis_pool")
|
||||
var oAuth = function(){
|
||||
var me = {
|
||||
oauth_database: 3,
|
||||
oauth_user_key: "rails:oauth_access_tokens:<%= oauth_access_key %>"
|
||||
oauth_user_key: "rails:oauth_access_tokens:<%= oauth_access_key %>",
|
||||
is_oauth_request: true
|
||||
};
|
||||
|
||||
// oauth token cases:
|
||||
@ -76,11 +77,21 @@ var oAuth = function(){
|
||||
},
|
||||
function getOAuthHash(err, data){
|
||||
if (err) throw err;
|
||||
passed_tokens = data;
|
||||
that.getOAuthHash(passed_tokens.oauth_token, this);
|
||||
|
||||
// this is oauth request only if oauth headers are present
|
||||
this.is_oauth_request = !_.isEmpty(data);
|
||||
|
||||
if (this.is_oauth_request) {
|
||||
passed_tokens = data;
|
||||
that.getOAuthHash(passed_tokens.oauth_token, this);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
function regenerateSignature(err, data){
|
||||
if (err) throw err;
|
||||
if (!this.is_oauth_request) return null;
|
||||
|
||||
ohash = data;
|
||||
var consumer = OAuthUtil.createConsumer(ohash.consumer_key, ohash.consumer_secret);
|
||||
var access_token = OAuthUtil.createToken(ohash.access_token_token, ohash.access_token_secret);
|
||||
@ -110,6 +121,7 @@ var oAuth = function(){
|
||||
},
|
||||
function checkSignature(err, data){
|
||||
if (err) throw err;
|
||||
|
||||
//console.log(data + " should equal the provided signature: " + signature);
|
||||
callback(err, (signature === data && !_.isUndefined(data)) ? ohash.user_id : null);
|
||||
}
|
||||
|
@ -47,10 +47,11 @@ var PSQL = function(user_id, db, limit, offset){
|
||||
if (that.client) {
|
||||
return callback(null, that.client);
|
||||
} else {
|
||||
pg.connect(conString, function(err, client){
|
||||
that.client = client;
|
||||
return callback(err, client);
|
||||
});
|
||||
var err = null;
|
||||
var client = new pg.Client(conString);
|
||||
client.connect();
|
||||
that.client = client;
|
||||
return callback(err, client);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,7 @@ module.exports.db_user = 'test_cartodb_user_<%= user_id %>';
|
||||
module.exports.db_host = 'localhost';
|
||||
module.exports.db_port = '5432';
|
||||
module.exports.redis_host = '127.0.0.1';
|
||||
module.exports.redis_port = 6379;
|
||||
module.exports.redis_port = 6333;
|
||||
module.exports.redisPool = 50;
|
||||
module.exports.redisIdleTimeoutMillis = 1;
|
||||
module.exports.redisReapIntervalMillis = 1;
|
||||
|
106
npm-shrinkwrap.json
generated
Normal file
106
npm-shrinkwrap.json
generated
Normal file
@ -0,0 +1,106 @@
|
||||
{
|
||||
"name": "cartodb_api",
|
||||
"version": "0.0.4",
|
||||
"dependencies": {
|
||||
"cluster": {
|
||||
"version": "0.6.4",
|
||||
"dependencies": {
|
||||
"log": {
|
||||
"version": "1.3.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"express": {
|
||||
"version": "2.5.11",
|
||||
"dependencies": {
|
||||
"connect": {
|
||||
"version": "1.9.2",
|
||||
"dependencies": {
|
||||
"formidable": {
|
||||
"version": "1.0.11"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.2.4"
|
||||
},
|
||||
"qs": {
|
||||
"version": "0.4.2"
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.3.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.1.7"
|
||||
},
|
||||
"underscore.string": {
|
||||
"version": "1.1.5",
|
||||
"dependencies": {
|
||||
"underscore": {
|
||||
"version": "1.1.6"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pg": {
|
||||
"version": "0.6.14",
|
||||
"dependencies": {
|
||||
"generic-pool": {
|
||||
"version": "1.0.9"
|
||||
}
|
||||
}
|
||||
},
|
||||
"generic-pool": {
|
||||
"version": "1.0.12"
|
||||
},
|
||||
"redis": {
|
||||
"version": "0.7.1"
|
||||
},
|
||||
"hiredis": {
|
||||
"version": "0.1.14"
|
||||
},
|
||||
"step": {
|
||||
"version": "0.0.5"
|
||||
},
|
||||
"oauth-client": {
|
||||
"version": "0.2.0",
|
||||
"dependencies": {
|
||||
"node-uuid": {
|
||||
"version": "1.1.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"node-uuid": {
|
||||
"version": "1.3.3"
|
||||
},
|
||||
"csv": {
|
||||
"version": "0.0.13"
|
||||
},
|
||||
"mocha": {
|
||||
"version": "1.2.1",
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "0.6.1"
|
||||
},
|
||||
"growl": {
|
||||
"version": "1.5.1"
|
||||
},
|
||||
"jade": {
|
||||
"version": "0.26.3",
|
||||
"dependencies": {
|
||||
"mkdirp": {
|
||||
"version": "0.3.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"diff": {
|
||||
"version": "1.0.2"
|
||||
},
|
||||
"debug": {
|
||||
"version": "0.7.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
10
package.json
10
package.json
@ -10,7 +10,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"cluster": "0.6.4",
|
||||
"express": "2.5.8",
|
||||
"express": "~2.5.11",
|
||||
"underscore" : "1.1.x",
|
||||
"underscore.string": "1.1.5",
|
||||
"pg": "0.6.14",
|
||||
@ -20,14 +20,14 @@
|
||||
"step": "0.0.x",
|
||||
"oauth-client": "0.2.0",
|
||||
"node-uuid":"1.3.3",
|
||||
"zlib":"1.0.5",
|
||||
"csv":"0.0.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"expresso": "0.8.x"
|
||||
"mocha": "1.2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"unit": "expresso ./test/unit/* | sh",
|
||||
"acceptance": "expresso ./test/acceptance/* | sh"
|
||||
"test": "test/run_tests.sh"
|
||||
},
|
||||
"engines": { "node": ">= 0.4.1 < 0.7.0" }
|
||||
"engines": { "node": ">= 0.4.1 < 0.9" }
|
||||
}
|
||||
|
@ -2,17 +2,20 @@ cartodb-sql-api tests
|
||||
---------------------
|
||||
Tests require you create a test database and set some redis keys before,
|
||||
you can execute prepare_db.sh script, it will create database, users
|
||||
and redis stuff for you. Be sure postgres and redis are running
|
||||
and redis stuff for you. Be sure postgres and redis are running.
|
||||
|
||||
> cd test && ./prepare_db.sh
|
||||
|
||||
Note that "make check" from top-level dir will try to do everything
|
||||
needed to prepare & run the tests.
|
||||
|
||||
|
||||
Acceptance tests (need ctrl-C to exit)
|
||||
--------------------------------------
|
||||
> expresso test/acceptance/app.test.js
|
||||
> expresso test/acceptance/app.auth.test.js
|
||||
> mocha -u tdd test/acceptance/app.test.js
|
||||
> mocha -u tdd test/acceptance/app.auth.test.js
|
||||
|
||||
|
||||
Unit tests (need ctrl-C to exit)
|
||||
Unit tests
|
||||
--------------------------------
|
||||
> expresso test/unit/*.js (or run the tests individually)
|
||||
> mocha -u tdd test/unit/*.js (or run the tests individually)
|
||||
|
@ -1,32 +1,37 @@
|
||||
require('../helper');
|
||||
require('../support/assert');
|
||||
|
||||
var app = require(global.settings.app_root + '/app/controllers/app')
|
||||
, assert = require('assert')
|
||||
, tests = module.exports = {}
|
||||
, querystring = require('querystring');
|
||||
|
||||
tests['valid api key should allow insert in protected tables'] = function(){
|
||||
suite('app.auth', function() {
|
||||
|
||||
test('valid api key should allow insert in protected tables', function(done){
|
||||
assert.response(app, {
|
||||
// view prepare_db.sh to see where to set api_key
|
||||
url: "/api/v1/sql?api_key=1234&q=INSERT%20INTO%20private_table%20(name)%20VALUES%20('test')",
|
||||
|
||||
headers: {host: 'vizzuality.localhost.lan:8080' },
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 200
|
||||
},{}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
done();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
tests['invalid api key should NOT allow insert in protected tables'] = function(){
|
||||
test('invalid api key should NOT allow insert in protected tables', function(done){
|
||||
assert.response(app, {
|
||||
// view prepare_db.sh to see where to set api_key
|
||||
url: "/api/v1/sql?api_key=RAMBO&q=INSERT%20INTO%20private_table%20(name)%20VALUES%20('test')",
|
||||
url: "/api/v1/sql?api_key=RAMBO&q=INSERT%20INTO%20private_table%20(name)%20VALUES%20('RAMBO')",
|
||||
|
||||
headers: {host: 'vizzuality.cartodb.com' },
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 400
|
||||
});
|
||||
}
|
||||
}, function() { done(); });
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
@ -12,6 +12,7 @@
|
||||
*
|
||||
*/
|
||||
require('../helper');
|
||||
require('../support/assert');
|
||||
|
||||
var app = require(global.settings.app_root + '/app/controllers/app')
|
||||
, assert = require('assert')
|
||||
@ -21,71 +22,86 @@ var app = require(global.settings.app_root + '/app/controllers/app')
|
||||
// allow lots of emitters to be set to silence warning
|
||||
app.setMaxListeners(0);
|
||||
|
||||
suite('app.test', function() {
|
||||
|
||||
var real_oauth_header = 'OAuth realm="http://vizzuality.testhost.lan/",oauth_consumer_key="fZeNGv5iYayvItgDYHUbot1Ukb5rVyX6QAg8GaY2",oauth_token="l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR",oauth_signature_method="HMAC-SHA1", oauth_signature="o4hx4hWP6KtLyFwggnYB4yPK8xI%3D",oauth_timestamp="1313581372",oauth_nonce="W0zUmvyC4eVL8cBd4YwlH1nnPTbxW0QBYcWkXTwe4",oauth_version="1.0"';
|
||||
|
||||
// use dec_sep for internationalization
|
||||
var checkDecimals = function(x, dec_sep){
|
||||
var tmp='' + x;
|
||||
if (tmp.indexOf(dec_sep)>-1)
|
||||
return tmp.length-tmp.indexOf(dec_sep)-1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
tests['GET /api/v1/sql'] = function(){
|
||||
test('GET /api/v1/sql', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql',
|
||||
method: 'GET'
|
||||
},{
|
||||
body: '{"error":["You must indicate a sql query"]}',
|
||||
status: 400
|
||||
}, function(res) {
|
||||
assert.deepEqual(JSON.parse(res.body), {"error":["You must indicate a sql query"]});
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
tests['GET /api/v1/sql with SQL parameter on SELECT only. No oAuth included '] = function(){
|
||||
test('GET /api/v1/sql with SQL parameter on SELECT only. No oAuth included ', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&database=cartodb_test_user_1_db',
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 200
|
||||
},{ }, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
tests['GET /api/v1/sql with SQL parameter on SELECT only. no database param, just id using headers'] = function(){
|
||||
test('GET /api/v1/sql with SQL parameter on SELECT only. no database param, just id using headers', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4',
|
||||
headers: {host: 'vizzuality.cartodb.com'},
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 200
|
||||
},{ }, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
tests['POST /api/v1/sql with SQL parameter on SELECT only. no database param, just id using headers'] = function(){
|
||||
test('POST /api/v1/sql with SQL parameter on SELECT only. no database param, just id using headers', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql',
|
||||
data: querystring.stringify({q: "SELECT * FROM untitle_table_4"}),
|
||||
headers: {host: 'vizzuality.cartodb.com', 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
method: 'POST'
|
||||
},{
|
||||
status: 200
|
||||
},{ }, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['GET /api/v1/sql with SQL parameter on INSERT only. oAuth not used, so public user - should fail'] = function(){
|
||||
test('GET /api/v1/sql with SQL parameter on INSERT only. oAuth not used, so public user - should fail', function(){
|
||||
assert.response(app, {
|
||||
url: "/api/v1/sql?q=INSERT%20INTO%20untitle_table_4%20(id)%20VALUES%20(1)&database=cartodb_dev_user_1_db",
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 400
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['GET /api/v1/sql with SQL parameter on DROP DATABASE only. oAuth not used, so public user - should fail'] = function(){
|
||||
test('GET /api/v1/sql with SQL parameter on DROP DATABASE only. oAuth not used, so public user - should fail', function(){
|
||||
assert.response(app, {
|
||||
url: "/api/v1/sql?q=DROP%20TABLE%20untitle_table_4&database=cartodb_dev_user_1_db",
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 400
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['GET /api/v1/sql with SQL parameter on INSERT only. header based db - should fail'] = function(){
|
||||
test('GET /api/v1/sql with SQL parameter on INSERT only. header based db - should fail', function(){
|
||||
assert.response(app, {
|
||||
url: "/api/v1/sql?q=INSERT%20INTO%20untitle_table_4%20(id)%20VALUES%20(1)",
|
||||
headers: {host: 'vizzuality.cartodb.com'},
|
||||
@ -93,9 +109,9 @@ tests['GET /api/v1/sql with SQL parameter on INSERT only. header based db - shou
|
||||
},{
|
||||
status: 400
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['GET /api/v1/sql with SQL parameter on DROP DATABASE only.header based db - should fail'] = function(){
|
||||
test('GET /api/v1/sql with SQL parameter on DROP DATABASE only.header based db - should fail', function(){
|
||||
assert.response(app, {
|
||||
url: "/api/v1/sql?q=DROP%20TABLE%20untitle_table_4",
|
||||
headers: {host: 'vizzuality.cartodb.com'},
|
||||
@ -103,35 +119,35 @@ tests['GET /api/v1/sql with SQL parameter on DROP DATABASE only.header based db
|
||||
},{
|
||||
status: 400
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['GET /api/v1/sql with SQL parameter and geojson format, ensuring content-disposition set to geojson'] = function(){
|
||||
test('GET /api/v1/sql with SQL parameter and geojson format, ensuring content-disposition set to geojson', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=geojson',
|
||||
headers: {host: 'vizzuality.cartodb.com'},
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 200
|
||||
}, function(res){
|
||||
},{ }, function(res){
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var cd = res.header('Content-Disposition');
|
||||
assert.equal(true, /filename=cartodb-query.geojson/gi.test(cd));
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['GET /api/v1/sql with SQL parameter and no format, ensuring content-disposition set to json'] = function(){
|
||||
test('GET /api/v1/sql with SQL parameter and no format, ensuring content-disposition set to json', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4',
|
||||
headers: {host: 'vizzuality.cartodb.com'},
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 200
|
||||
}, function(res){
|
||||
},{ }, function(res){
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var cd = res.header('Content-Disposition');
|
||||
assert.equal(true, /filename=cartodb-query.json/gi.test(cd));
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['GET /api/v1/sql ensure cross domain set on errors'] = function(){
|
||||
test('GET /api/v1/sql ensure cross domain set on errors', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql?q=SELECT%20*gadfgadfg%20FROM%20untitle_table_4',
|
||||
headers: {host: 'vizzuality.cartodb.com'},
|
||||
@ -141,72 +157,73 @@ tests['GET /api/v1/sql ensure cross domain set on errors'] = function(){
|
||||
}, function(res){
|
||||
var cd = res.header('Access-Control-Allow-Origin');
|
||||
assert.equal(cd, '*');
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['GET /api/v1/sql as geojson limiting decimal places'] = function(){
|
||||
test('GET /api/v1/sql as geojson limiting decimal places', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=geojson&dp=1',
|
||||
headers: {host: 'vizzuality.cartodb.com'},
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 200
|
||||
}, function(res){
|
||||
},{ }, function(res){
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var result = JSON.parse(res.body);
|
||||
assert.equal(1, checkDecimals(result.features[0].geometry.coordinates[0], '.'));
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['GET /api/v1/sql as geojson with default dp as 6'] = function(){
|
||||
test('GET /api/v1/sql as geojson with default dp as 6', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=geojson',
|
||||
headers: {host: 'vizzuality.cartodb.com'},
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 200
|
||||
}, function(res){
|
||||
},{ }, function(res){
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var result = JSON.parse(res.body);
|
||||
assert.equal(6, checkDecimals(result.features[0].geometry.coordinates[0], '.'));
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['GET /api/v1/sql as csv'] = function(){
|
||||
test('GET /api/v1/sql as csv', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql?q=SELECT%20cartodb_id,ST_AsEWKT(the_geom)%20as%20geom%20FROM%20untitle_table_4%20LIMIT%201&format=csv',
|
||||
headers: {host: 'vizzuality.cartodb.com'},
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 200
|
||||
}, function(res){
|
||||
},{ }, function(res){
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var body = "cartodb_id,geom\r\n1,SRID=4326;POINT(-3.699732 40.423012)";
|
||||
assert.equal(body, res.body);
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['GET /api/v1/sql as csv, properly escaped'] = function(){
|
||||
test('GET /api/v1/sql as csv, properly escaped', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql?q=SELECT%20cartodb_id,%20address%20FROM%20untitle_table_4%20LIMIT%201&format=csv',
|
||||
headers: {host: 'vizzuality.cartodb.com'},
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 200
|
||||
}, function(res){
|
||||
},{ }, function(res){
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var body = 'cartodb_id,address\r\n1,"Calle de Pérez Galdós 9, Madrid, Spain"';
|
||||
assert.equal(body, res.body);
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['cannot GET system tables'] = function(){
|
||||
test('cannot GET system tables', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql?q=SELECT%20*%20FROM%20pg_attribute',
|
||||
headers: {host: 'vizzuality.cartodb.com'},
|
||||
method: 'GET'
|
||||
},{
|
||||
status: 403
|
||||
});
|
||||
};
|
||||
}, function() { done(); });
|
||||
});
|
||||
|
||||
tests['GET decent error if domain is incorrect'] = function(){
|
||||
test('GET decent error if domain is incorrect', function(done){
|
||||
assert.response(app, {
|
||||
url: '/api/v1/sql?q=SELECT%20*%20FROM%20untitle_table_4&format=geojson',
|
||||
headers: {host: 'vizzualinot.cartodb.com'},
|
||||
@ -216,14 +233,8 @@ tests['GET decent error if domain is incorrect'] = function(){
|
||||
}, function(res){
|
||||
var result = JSON.parse(res.body);
|
||||
assert.equal(result.error[0],"Sorry, we can't find this CartoDB. Please check that you have entered the correct domain.");
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
// use dec_sep for internationalization
|
||||
function checkDecimals(x, dec_sep){
|
||||
tmp='' + x;
|
||||
if (tmp.indexOf(dec_sep)>-1)
|
||||
return tmp.length-tmp.indexOf(dec_sep)-1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
@ -1,22 +1,51 @@
|
||||
#!/bin/sh
|
||||
# this script prepare database and redis instance to run accpetance test
|
||||
#!/bin/sh
|
||||
|
||||
echo "preparing redis..."
|
||||
echo "HSET rails:users:vizzuality id 1" | redis-cli -n 5
|
||||
echo "HSET rails:users:vizzuality database_name cartodb_test_user_1_db" | redis-cli -n 5
|
||||
echo "SADD rails:users:vizzuality:map_key 1234" | redis-cli -n 5
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR consumer_key fZeNGv5iYayvItgDYHUbot1Ukb5rVyX6QAg8GaY2" | redis-cli -n 3
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR consumer_secret IBLCvPEefxbIiGZhGlakYV4eM8AbVSwsHxwEYpzx" | redis-cli -n 3
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR access_token_token l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR" | redis-cli -n 3
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR access_token_secret 22zBIek567fMDEebzfnSdGe8peMFVFqAreOENaDK" | redis-cli -n 3
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR user_id 1" | redis-cli -n 3
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR time sometime" | redis-cli -n 3
|
||||
# this script prepare database and redis instance to run acceptance test
|
||||
#
|
||||
# NOTE: assumes existance of a "template_postgis" loaded with
|
||||
# compatible version of postgis (legacy.sql included)
|
||||
|
||||
# This is where postgresql connection parameters are read from
|
||||
TESTENV=../config/environments/test.js
|
||||
|
||||
|
||||
# Extract postgres configuration
|
||||
#PGUSER=`grep \.db_user ${TESTENV} | sed "s/.*= *'\([^']*\)'.*/\1/"`
|
||||
#echo "PGUSER: [$PGUSER]"
|
||||
PGHOST=`grep \.db_host ${TESTENV} | sed "s/.*= *'\([^']*\)'.*/\1/"`
|
||||
echo "PGHOST: [$PGHOST]"
|
||||
PGPORT=`grep \.db_port ${TESTENV} | sed "s/.*=[\t ]*'\([^']*\)'.*/\1/"`
|
||||
echo "PGPORT: [$PGPORT]"
|
||||
|
||||
|
||||
TEST_DB="cartodb_test_user_1_db"
|
||||
REDIS_PORT=6333 # TODO: read from environment file
|
||||
|
||||
export PGHOST PGPORT
|
||||
|
||||
die() {
|
||||
msg=$1
|
||||
echo "${msg}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "preparing postgres..."
|
||||
dropdb -Upostgres -hlocalhost cartodb_test_user_1_db
|
||||
createdb -Upostgres -hlocalhost -Ttemplate_postgis -Opostgres -EUTF8 cartodb_test_user_1_db
|
||||
psql -Upostgres -hlocalhost cartodb_test_user_1_db < test.sql
|
||||
dropdb ${TEST_DB} 2> /dev/null # error expected if doesn't exist
|
||||
createdb -Ttemplate_postgis -EUTF8 ${TEST_DB} || die "Could not create test database"
|
||||
psql -f test.sql ${TEST_DB}
|
||||
|
||||
echo "preparing redis..."
|
||||
echo "HSET rails:users:vizzuality id 1" | redis-cli -p ${REDIS_PORT} -n 5
|
||||
echo "HSET rails:users:vizzuality database_name ${TEST_DB}" | redis-cli -p ${REDIS_PORT} -n 5
|
||||
echo "SADD rails:users:vizzuality:map_key 1234" | redis-cli -p ${REDIS_PORT} -n 5
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR consumer_key fZeNGv5iYayvItgDYHUbot1Ukb5rVyX6QAg8GaY2" | redis-cli -p ${REDIS_PORT} -n 3
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR consumer_secret IBLCvPEefxbIiGZhGlakYV4eM8AbVSwsHxwEYpzx" | redis-cli -p ${REDIS_PORT} -n 3
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR access_token_token l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR" | redis-cli -p ${REDIS_PORT} -n 3
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR access_token_secret 22zBIek567fMDEebzfnSdGe8peMFVFqAreOENaDK" | redis-cli -p ${REDIS_PORT} -n 3
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR user_id 1" | redis-cli -p ${REDIS_PORT} -n 3
|
||||
echo "hset rails:oauth_access_tokens:l0lPbtP68ao8NfStCiA3V3neqfM03JKhToxhUQTR time sometime" | redis-cli -p ${REDIS_PORT} -n 3
|
||||
|
||||
|
||||
|
||||
echo "ok, you can run test now"
|
||||
|
45
test/run_tests.sh
Executable file
45
test/run_tests.sh
Executable file
@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Must match redis_port in config/environments/test.js
|
||||
# TODO: read from there
|
||||
REDIS_PORT=6333
|
||||
|
||||
cleanup() {
|
||||
echo "Cleaning up"
|
||||
kill ${PID_REDIS}
|
||||
}
|
||||
|
||||
cleanup_and_exit() {
|
||||
cleanup
|
||||
exit
|
||||
}
|
||||
|
||||
die() {
|
||||
msg=$1
|
||||
echo "${msg}" >&2
|
||||
cleanup
|
||||
exit 1
|
||||
}
|
||||
|
||||
trap 'cleanup_and_exit' 1 2 3 5 9 13
|
||||
|
||||
echo "Starting redis on port ${REDIS_PORT}"
|
||||
echo "port ${REDIS_PORT}" | redis-server - > test/test.log &
|
||||
PID_REDIS=$!
|
||||
|
||||
echo "Preparing the environment"
|
||||
cd test; sh prepare_db.sh >> test.log || die "database preparation failure (see test.log)"; cd -;
|
||||
|
||||
PATH=node_modules/.bin/:$PATH
|
||||
|
||||
echo "Running tests"
|
||||
mocha -u tdd \
|
||||
test/unit/redis_pool.test.js \
|
||||
test/unit/metadata.test.js \
|
||||
test/unit/oauth.test.js \
|
||||
test/unit/psql.test.js \
|
||||
test/acceptance/app.test.js \
|
||||
test/acceptance/app.auth.test.js
|
||||
|
||||
|
||||
cleanup
|
201
test/support/assert.js
Normal file
201
test/support/assert.js
Normal file
@ -0,0 +1,201 @@
|
||||
// Cribbed from the ever prolific Konstantin Kaefer
|
||||
// https://github.com/mapbox/tilelive-mapnik/blob/master/test/support/assert.js
|
||||
|
||||
var fs = require('fs');
|
||||
var http = require('http');
|
||||
var path = require('path');
|
||||
var exec = require('child_process').exec;
|
||||
|
||||
var assert = module.exports = exports = require('assert');
|
||||
|
||||
assert.imageEqualsFile = function(buffer, file_b, callback) {
|
||||
if (!callback) callback = function(err) { if (err) throw err; };
|
||||
file_b = path.resolve(file_b);
|
||||
var file_a = '/tmp/' + (Math.random() * 1e16);
|
||||
var err = fs.writeFileSync(file_a, buffer, 'binary');
|
||||
if (err) throw err;
|
||||
|
||||
exec('compare -metric PSNR "' + file_a + '" "' +
|
||||
file_b + '" /dev/null', function(err, stdout, stderr) {
|
||||
if (err) {
|
||||
fs.unlinkSync(file_a);
|
||||
callback(err);
|
||||
} else {
|
||||
stderr = stderr.trim();
|
||||
if (stderr === 'inf') {
|
||||
fs.unlinkSync(file_a);
|
||||
callback(null);
|
||||
} else {
|
||||
var similarity = parseFloat(stderr);
|
||||
var err = new Error('Images not equal(' + similarity + '): ' +
|
||||
file_a + ' ' + file_b);
|
||||
err.similarity = similarity;
|
||||
callback(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Assert response from `server` with
|
||||
* the given `req` object and `res` assertions object.
|
||||
*
|
||||
* @param {Server} server
|
||||
* @param {Object} req
|
||||
* @param {Object|Function} res
|
||||
* @param {String} msg
|
||||
*/
|
||||
assert.response = function(server, req, res, msg){
|
||||
var port = 5555;
|
||||
function check(){
|
||||
try {
|
||||
server.__port = server.address().port;
|
||||
server.__listening = true;
|
||||
} catch (err) {
|
||||
process.nextTick(check);
|
||||
return;
|
||||
}
|
||||
if (server.__deferred) {
|
||||
server.__deferred.forEach(function(args){
|
||||
assert.response.apply(assert, args);
|
||||
});
|
||||
server.__deferred = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the server is ready or defer
|
||||
if (!server.fd) {
|
||||
server.__deferred = server.__deferred || [];
|
||||
server.listen(server.__port = port++, '127.0.0.1', check);
|
||||
} else if (!server.__port) {
|
||||
server.__deferred = server.__deferred || [];
|
||||
process.nextTick(check);
|
||||
}
|
||||
|
||||
// The socket was created but is not yet listening, so keep deferring
|
||||
if (!server.__listening) {
|
||||
server.__deferred.push(arguments);
|
||||
return;
|
||||
}
|
||||
|
||||
// Callback as third or fourth arg
|
||||
var callback = typeof res === 'function'
|
||||
? res
|
||||
: typeof msg === 'function'
|
||||
? msg
|
||||
: function(){};
|
||||
|
||||
// Default messate to test title
|
||||
if (typeof msg === 'function') msg = null;
|
||||
msg = msg || assert.testTitle;
|
||||
msg += '. ';
|
||||
|
||||
// Pending responses
|
||||
server.__pending = server.__pending || 0;
|
||||
server.__pending++;
|
||||
|
||||
// Create client
|
||||
if (!server.fd) {
|
||||
server.listen(server.__port = port++, '127.0.0.1', issue);
|
||||
} else {
|
||||
issue();
|
||||
}
|
||||
|
||||
function issue(){
|
||||
|
||||
// Issue request
|
||||
var timer,
|
||||
method = req.method || 'GET',
|
||||
status = res.status || res.statusCode,
|
||||
data = req.data || req.body,
|
||||
requestTimeout = req.timeout || 0,
|
||||
encoding = req.encoding || 'utf8';
|
||||
|
||||
var request = http.request({
|
||||
host: '127.0.0.1',
|
||||
port: server.__port,
|
||||
path: req.url,
|
||||
method: method,
|
||||
headers: req.headers,
|
||||
agent: false
|
||||
});
|
||||
|
||||
var check = function() {
|
||||
if (--server.__pending === 0) {
|
||||
server.close();
|
||||
server.__listening = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Timeout
|
||||
if (requestTimeout) {
|
||||
timer = setTimeout(function(){
|
||||
check();
|
||||
delete req.timeout;
|
||||
assert.fail(msg + 'Request timed out after ' + requestTimeout + 'ms.');
|
||||
}, requestTimeout);
|
||||
}
|
||||
|
||||
if (data) request.write(data);
|
||||
|
||||
request.on('response', function(response){
|
||||
response.body = '';
|
||||
response.setEncoding(encoding);
|
||||
response.on('data', function(chunk){ response.body += chunk; });
|
||||
response.on('end', function(){
|
||||
if (timer) clearTimeout(timer);
|
||||
|
||||
// Assert response body
|
||||
if (res.body !== undefined) {
|
||||
var eql = res.body instanceof RegExp
|
||||
? res.body.test(response.body)
|
||||
: res.body === response.body;
|
||||
assert.ok(
|
||||
eql,
|
||||
msg + 'Invalid response body.\n'
|
||||
+ ' Expected: ' + res.body + '\n'
|
||||
+ ' Got: ' + response.body
|
||||
);
|
||||
}
|
||||
|
||||
// Assert response status
|
||||
if (typeof status === 'number') {
|
||||
assert.equal(
|
||||
response.statusCode,
|
||||
status,
|
||||
msg + 'Invalid response status code.\n'
|
||||
+ ' Expected: [green]{' + status + '}\n'
|
||||
+ ' Got: [red]{' + response.statusCode + '}'
|
||||
);
|
||||
}
|
||||
|
||||
// Assert response headers
|
||||
if (res.headers) {
|
||||
var keys = Object.keys(res.headers);
|
||||
for (var i = 0, len = keys.length; i < len; ++i) {
|
||||
var name = keys[i],
|
||||
actual = response.headers[name.toLowerCase()],
|
||||
expected = res.headers[name],
|
||||
eql = expected instanceof RegExp
|
||||
? expected.test(actual)
|
||||
: expected == actual;
|
||||
assert.ok(
|
||||
eql,
|
||||
msg + 'Invalid response header [bold]{' + name + '}.\n'
|
||||
+ ' Expected: [green]{' + expected + '}\n'
|
||||
+ ' Got: [red]{' + actual + '}'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Callback
|
||||
callback(response);
|
||||
check();
|
||||
});
|
||||
});
|
||||
|
||||
request.end();
|
||||
}
|
||||
};
|
||||
|
@ -6,18 +6,24 @@ var _ = require('underscore')
|
||||
, assert = require('assert')
|
||||
, tests = module.exports = {};
|
||||
|
||||
tests['test can retrieve database name from header and redis'] = function(){
|
||||
suite('metadata', function() {
|
||||
|
||||
test('test can retrieve database name from header and redis', function(done){
|
||||
var req = {headers: {host: 'vizzuality.cartodb.com'}};
|
||||
|
||||
MetaData.getDatabase(req, function(err, data){
|
||||
assert.equal(data, 'cartodb_test_user_1_db');
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['test can retrieve id from header and redis'] = function(){
|
||||
test('test can retrieve id from header and redis', function(done){
|
||||
var req = {headers: {host: 'vizzuality.cartodb.com'}};
|
||||
|
||||
MetaData.getId(req, function(err, data){
|
||||
assert.equal(data, '1');
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -19,49 +19,53 @@ var _ = require('underscore')
|
||||
, oauth_header_tokens = 'oauth_consumer_key="dpf43f3p2l4k3l03",oauth_token="nnch734d00sl2jdk",oauth_signature_method="HMAC-SHA1", oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D",oauth_timestamp="1191242096",oauth_nonce="kllo9940pd9333jh",oauth_version="1.0"'
|
||||
, full_oauth_header = 'OAuth realm="http://photos.example.net/"' + oauth_header_tokens;
|
||||
|
||||
tests['test database number'] = function(){
|
||||
suite('oauth', function() {
|
||||
|
||||
test('test database number', function(){
|
||||
assert.equal(oAuth.oauth_database, 3);
|
||||
};
|
||||
});
|
||||
|
||||
tests['test oauth database key'] = function(){
|
||||
test('test oauth database key', function(){
|
||||
assert.equal(oAuth.oauth_user_key, "rails:oauth_access_tokens:<%= oauth_access_key %>");
|
||||
};
|
||||
});
|
||||
|
||||
tests['test parse tokens from full headers does not raise exception'] = function(){
|
||||
test('test parse tokens from full headers does not raise exception', function(){
|
||||
var req = {query:{}, headers:{authorization:full_oauth_header}};
|
||||
assert.doesNotThrow(function(){ oAuth.parseTokens(req) }, /incomplete oauth tokens in request/);
|
||||
};
|
||||
});
|
||||
|
||||
tests['test parse all normal tokens raises no exception'] = function(){
|
||||
test('test parse all normal tokens raises no exception', function(){
|
||||
var req = {query:oauth_data, headers:{}};
|
||||
assert.doesNotThrow(function(){ oAuth.parseTokens(req) }, /incomplete oauth tokens in request/);
|
||||
};
|
||||
});
|
||||
|
||||
tests['test headers take presedence over query parameters'] = function(){
|
||||
test('test headers take presedence over query parameters', function(){
|
||||
var req = {query:{oauth_signature_method: "MY_HASH"}, headers:{authorization:full_oauth_header}};
|
||||
var tokens = oAuth.parseTokens(req);
|
||||
assert.equal(tokens.oauth_signature_method, "HMAC-SHA1");
|
||||
};
|
||||
});
|
||||
|
||||
tests['test can access oauth hash for a user based on access token (oauth_token)'] = function(){
|
||||
test('test can access oauth hash for a user based on access token (oauth_token)', function(done){
|
||||
var req = {query:{}, headers:{authorization:real_oauth_header}};
|
||||
var tokens = oAuth.parseTokens(req);
|
||||
|
||||
oAuth.getOAuthHash(tokens.oauth_token, function(err, data){
|
||||
assert.equal(tokens.oauth_consumer_key, data.consumer_key);
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['test non existant oauth hash for a user based on oauth_token returns empty hash'] = function(){
|
||||
test('test non existant oauth hash for a user based on oauth_token returns empty hash', function(done){
|
||||
var req = {query:{}, headers:{authorization:full_oauth_header}};
|
||||
var tokens = oAuth.parseTokens(req);
|
||||
|
||||
oAuth.getOAuthHash(tokens.oauth_token, function(err, data){
|
||||
assert.eql(data, {});
|
||||
assert.deepEqual(data, {});
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
tests['can return user for verified signature'] = function(){
|
||||
test('can return user for verified signature', function(done){
|
||||
var req = {query:{},
|
||||
headers:{authorization:real_oauth_header, host: 'vizzuality.testhost.lan' },
|
||||
method: 'GET',
|
||||
@ -69,11 +73,12 @@ tests['can return user for verified signature'] = function(){
|
||||
};
|
||||
|
||||
oAuth.verifyRequest(req, function(err, data){
|
||||
assert.eql(data, 1);
|
||||
assert.equal(data, 1);
|
||||
done();
|
||||
}, true);
|
||||
};
|
||||
});
|
||||
|
||||
tests['returns null user for unverified signatures'] = function(){
|
||||
test('returns null user for unverified signatures', function(done){
|
||||
var req = {query:{},
|
||||
headers:{authorization:real_oauth_header, host: 'vizzuality.testyhost.lan' },
|
||||
method: 'GET',
|
||||
@ -81,11 +86,12 @@ tests['returns null user for unverified signatures'] = function(){
|
||||
};
|
||||
|
||||
oAuth.verifyRequest(req, function(err, data){
|
||||
assert.eql(data, null);
|
||||
assert.equal(data, null);
|
||||
done();
|
||||
}, true);
|
||||
};
|
||||
});
|
||||
|
||||
tests['returns null user for no oauth'] = function(){
|
||||
test('returns null user for no oauth', function(done){
|
||||
var req = {
|
||||
query:{},
|
||||
headers:{},
|
||||
@ -94,6 +100,9 @@ tests['returns null user for no oauth'] = function(){
|
||||
};
|
||||
|
||||
oAuth.verifyRequest(req,function(err,data){
|
||||
assert.eql(data, null);
|
||||
assert.equal(data, null);
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -4,89 +4,96 @@ var _ = require('underscore')
|
||||
, PSQL = require('../../app/models/psql')
|
||||
, assert = require('assert');
|
||||
|
||||
exports['test throws error if no args passed to constructor'] = function(){
|
||||
suite('psql', function() {
|
||||
|
||||
test('test throws error if no args passed to constructor', function(){
|
||||
var msg;
|
||||
try{
|
||||
var pg = new PSQL();
|
||||
} catch (err){
|
||||
assert.equal(err.message, "Incorrect access parameters. If you are accessing via OAuth, please check your tokens are correct. For public users, please ensure your table is published.");
|
||||
msg = err.message;
|
||||
}
|
||||
};
|
||||
assert.equal(msg, "Incorrect access parameters. If you are accessing via OAuth, please check your tokens are correct. For public users, please ensure your table is published.");
|
||||
});
|
||||
|
||||
exports['test instantiate with just user constructor'] = function(){
|
||||
test('test instantiate with just user constructor', function(){
|
||||
var pg = new PSQL("1", null);
|
||||
assert.equal(pg.user_id, "1");
|
||||
};
|
||||
});
|
||||
|
||||
exports['test instantiate with just db constructor'] = function(){
|
||||
test('test instantiate with just db constructor', function(){
|
||||
var pg = new PSQL(null, 'my_database');
|
||||
assert.equal(pg.db, "my_database");
|
||||
};
|
||||
});
|
||||
|
||||
exports['test username returns default user if not set'] = function(){
|
||||
test('test username returns default user if not set', function(){
|
||||
var pg = new PSQL(null, 'my_database');
|
||||
assert.equal(pg.username(), "publicuser");
|
||||
};
|
||||
});
|
||||
|
||||
exports['test username returns interpolated user if set'] = function(){
|
||||
test('test username returns interpolated user if set', function(){
|
||||
var pg = new PSQL('simon', 'my_database');
|
||||
assert.equal(pg.username(), "test_cartodb_user_simon");
|
||||
};
|
||||
});
|
||||
|
||||
exports['test username returns default db if user not set'] = function(){
|
||||
test('test username returns default db if user not set', function(){
|
||||
var pg = new PSQL(null, 'my_database');
|
||||
assert.equal(pg.database(), "my_database");
|
||||
};
|
||||
});
|
||||
|
||||
exports['test username returns interpolated db if user set'] = function(){
|
||||
test('test username returns interpolated db if user set', function(){
|
||||
var pg = new PSQL('simon');
|
||||
assert.equal(pg.database(), "cartodb_test_user_simon_db");
|
||||
};
|
||||
});
|
||||
|
||||
exports['test private user can execute SELECTS on db'] = function(){
|
||||
test('test private user can execute SELECTS on db', function(done){
|
||||
var pg = new PSQL('1');
|
||||
var sql = "SELECT 1 as test_sum";
|
||||
pg.query(sql, function(err, result){
|
||||
assert.equal(result.rows[0].test_sum, 1);
|
||||
pg.end();
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
exports['test private user can execute CREATE on db'] = function(){
|
||||
test('test private user can execute CREATE on db', function(done){
|
||||
var pg = new PSQL('1');
|
||||
var sql = "DROP TABLE IF EXISTS distributors; CREATE TABLE distributors (id integer, name varchar(40), UNIQUE(name))";
|
||||
pg.query(sql, function(err, result){
|
||||
assert.isNull(err);
|
||||
assert.ok(_.isNull(err));
|
||||
pg.end();
|
||||
done();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
exports['test private user can execute INSERT on db'] = function(){
|
||||
test('test private user can execute INSERT on db', function(done){
|
||||
var pg = new PSQL('1');
|
||||
var sql = "DROP TABLE IF EXISTS distributors1; CREATE TABLE distributors1 (id integer, name varchar(40), UNIQUE(name))";
|
||||
pg.query(sql, function(err, result){
|
||||
sql = "INSERT INTO distributors1 (id, name) VALUES (1, 'fish')";
|
||||
pg.query(sql,function(err, result){
|
||||
assert.eql(result.rows, []);
|
||||
assert.deepEqual(result.rows, []);
|
||||
pg.end();
|
||||
done();
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
exports['test publicuser can execute SELECT on enabled tables'] = function(){
|
||||
test('test publicuser can execute SELECT on enabled tables', function(done){
|
||||
var pg = new PSQL("1");
|
||||
var sql = "DROP TABLE IF EXISTS distributors2; CREATE TABLE distributors2 (id integer, name varchar(40), UNIQUE(name)); GRANT SELECT ON distributors2 TO publicuser;";
|
||||
pg.query(sql, function(err, result){
|
||||
pg.end();
|
||||
|
||||
pg = new PSQL(null, 'cartodb_test_user_1_db');
|
||||
pg.query("SELECT count(*) FROM distributors2", function(err, result){
|
||||
assert.equal(result.rows[0].count, 0);
|
||||
pg.end();
|
||||
done();
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
exports['test publicuser cannot execute INSERT on db'] = function(){
|
||||
test('test publicuser cannot execute INSERT on db', function(done){
|
||||
var pg = new PSQL("1");
|
||||
var sql = "DROP TABLE IF EXISTS distributors3; CREATE TABLE distributors3 (id integer, name varchar(40), UNIQUE(name)); GRANT SELECT ON distributors3 TO publicuser;";
|
||||
pg.query(sql, function(err, result){
|
||||
@ -94,8 +101,11 @@ exports['test publicuser cannot execute INSERT on db'] = function(){
|
||||
|
||||
pg = new PSQL(null, 'cartodb_test_user_1_db'); //anonymous user
|
||||
pg.query("INSERT INTO distributors3 (id, name) VALUES (1, 'fishy')", function(err, result){
|
||||
assert.eql(err.message, 'permission denied for relation distributors3');
|
||||
assert.equal(err.message, 'permission denied for relation distributors3');
|
||||
pg.end();
|
||||
done();
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -3,41 +3,47 @@ var _ = require('underscore')
|
||||
, redis_pool = require('../../app/models/redis_pool')
|
||||
, assert = require('assert');
|
||||
|
||||
exports['test truth'] = function(){
|
||||
suite('redis_pool', function() {
|
||||
|
||||
test('test truth', function(){
|
||||
assert.ok(true, 'it is');
|
||||
};
|
||||
});
|
||||
|
||||
exports['test can instantiate a RedisPool object'] = function(){
|
||||
test('test can instantiate a RedisPool object', function(){
|
||||
assert.ok(redis_pool);
|
||||
};
|
||||
});
|
||||
|
||||
exports['test pool object has an aquire function'] = function(){
|
||||
assert.includes(_.functions(redis_pool), 'acquire');
|
||||
};
|
||||
test('test pool object has an aquire function', function(){
|
||||
assert.ok(_.includes(_.functions(redis_pool), 'acquire'));
|
||||
});
|
||||
|
||||
exports['test calling aquire returns a redis client object that can get/set'] = function(beforeExit){
|
||||
test('test calling aquire returns a redis client object that can get/set', function(done){
|
||||
redis_pool.acquire(0, function(client){
|
||||
client.set("key","value");
|
||||
client.get("key", function(err,data){
|
||||
assert.eql(data, "value");
|
||||
assert.equal(data, "value");
|
||||
redis_pool.release(0, client);
|
||||
done();
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
exports['test calling aquire on another DB returns a redis client object that can get/set'] = function(beforeExit){
|
||||
test('test calling aquire on another DB returns a redis client object that can get/set', function(done){
|
||||
redis_pool.acquire("MYDATABASE", function(client){
|
||||
client.set("key","value");
|
||||
client.get("key", function(err,data){
|
||||
assert.eql(data, "value");
|
||||
assert.equal(data, "value");
|
||||
redis_pool.release("MYDATABASE", client);
|
||||
redis_pool.acquire("MYDATABASE", function(client){
|
||||
client.get("key", function(err,data){
|
||||
assert.equal(data, "value");
|
||||
redis_pool.release("MYDATABASE", client);
|
||||
done();
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
redis_pool.acquire("MYDATABASE", function(client){
|
||||
client.get("key", function(err,data){
|
||||
assert.eql(data, "value");
|
||||
redis_pool.release("MYDATABASE", client);
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user