diff --git a/lib/cartodb/controllers/template_maps.js b/lib/cartodb/controllers/template_maps.js index be2022a8..29026c41 100644 --- a/lib/cartodb/controllers/template_maps.js +++ b/lib/cartodb/controllers/template_maps.js @@ -1,4 +1,5 @@ var step = require('step'); +var assert = require('assert'); var _ = require('underscore'); var CdbRequest = require('../models/cdb_request'); @@ -42,34 +43,17 @@ TemplateMapsController.prototype.create = function(req, res) { self.serverOptions.authorizedByAPIKey(req, this); }, function addTemplate(err, authenticated) { - if ( err ) throw err; - if (authenticated !== 1) { - err = new Error("Only authenticated user can create templated maps"); - err.http_status = 403; - throw err; - } - if ( ! req.headers['content-type'] || req.headers['content-type'].split(';')[0] != 'application/json' ) - throw new Error('template POST data must be of type application/json'); + assert.ifError(err); + ifUnauthenticated(authenticated, 'Only authenticated users can get template maps'); + ifInvalidContentType(req, 'template POST data must be of type application/json'); var cfg = req.body; self.templateMaps.addTemplate(cdbuser, cfg, this); }, function prepareResponse(err, tpl_id){ - if ( err ) throw err; - // NOTE: might omit "cdbuser" if == dbowner ... - return { template_id: cdbuser + '@' + tpl_id }; + assert.ifError(err); + return { template_id: tpl_id }; }, - function finish(err, response){ - if (err){ - response = { error: ''+err }; - var statusCode = 400; - if ( ! _.isUndefined(err.http_status) ) { - statusCode = err.http_status; - } - self.app.sendError(res, response, statusCode, 'POST TEMPLATE', err); - } else { - self.app.sendResponse(res, [response, 200]); - } - } + finishFn(self.app, res, 'POST TEMPLATE') ); }; @@ -87,42 +71,20 @@ TemplateMapsController.prototype.update = function(req, res) { self.serverOptions.authorizedByAPIKey(req, this); }, function updateTemplate(err, authenticated) { - if ( err ) throw err; - if (authenticated !== 1) { - err = new Error("Only authenticated user can list templated maps"); - err.http_status = 403; - throw err; - } - if ( ! req.headers['content-type'] || req.headers['content-type'].split(';')[0] != 'application/json' ) - throw new Error('template PUT data must be of type application/json'); + assert.ifError(err); + ifUnauthenticated(authenticated, 'Only authenticated user can update templated maps'); + ifInvalidContentType(req, 'template PUT data must be of type application/json'); + template = req.body; - tpl_id = req.params.template_id.split('@'); - if ( tpl_id.length > 1 ) { - if ( tpl_id[0] != cdbuser ) { - err = new Error("Invalid template id '" + req.params.template_id + "' for user '" + cdbuser + "'"); - err.http_status = 404; - throw err; - } - tpl_id = tpl_id[1]; - } + tpl_id = templateName(req.params.template_id); self.templateMaps.updTemplate(cdbuser, tpl_id, template, this); }, function prepareResponse(err){ - if ( err ) throw err; - return { template_id: cdbuser + '@' + tpl_id }; + assert.ifError(err); + + return { template_id: tpl_id }; }, - function finish(err, response){ - if (err){ - var statusCode = 400; - response = { error: ''+err }; - if ( ! _.isUndefined(err.http_status) ) { - statusCode = err.http_status; - } - self.app.sendError(res, response, statusCode, 'PUT TEMPLATE', err); - } else { - self.app.sendResponse(res, [response, 200]); - } - } + finishFn(self.app, res, 'PUT TEMPLATE') ); }; @@ -143,25 +105,13 @@ TemplateMapsController.prototype.retrieve = function(req, res) { self.serverOptions.authorizedByAPIKey(req, this); }, function updateTemplate(err, authenticated) { - if ( err ) throw err; - if (authenticated !== 1) { - err = new Error("Only authenticated users can get template maps"); - err.http_status = 403; - throw err; - } - tpl_id = req.params.template_id.split('@'); - if ( tpl_id.length > 1 ) { - if ( tpl_id[0] != cdbuser ) { - var templateNotFoundErr = new Error("Cannot get template id '" + req.params.template_id + - "' for user '" + cdbuser + "'"); - templateNotFoundErr.http_status = 404; - throw templateNotFoundErr; - } - tpl_id = tpl_id[1]; - } + assert.ifError(err); + ifUnauthenticated(authenticated, 'Only authenticated users can get template maps'); + + tpl_id = templateName(req.params.template_id); self.templateMaps.getTemplate(cdbuser, tpl_id, this); }, - function prepareResponse(err, tpl_val){ + function prepareResponse(err, tpl_val) { if ( err ) throw err; if ( ! tpl_val ) { err = new Error("Cannot find template '" + tpl_id + "' of user '" + cdbuser + "'"); @@ -173,18 +123,7 @@ TemplateMapsController.prototype.retrieve = function(req, res) { delete tpl_val.auth_id; return { template: tpl_val }; }, - function finish(err, response){ - if (err){ - var statusCode = 400; - response = { error: ''+err }; - if ( ! _.isUndefined(err.http_status) ) { - statusCode = err.http_status; - } - self.app.sendError(res, response, statusCode, 'GET TEMPLATE', err); - } else { - self.app.sendResponse(res, [response, 200]); - } - } + finishFn(self.app, res, 'GET TEMPLATE') ); }; @@ -204,40 +143,17 @@ TemplateMapsController.prototype.destroy = function(req, res) { self.serverOptions.authorizedByAPIKey(req, this); }, function updateTemplate(err, authenticated) { - if ( err ) throw err; - if (authenticated !== 1) { - err = new Error("Only authenticated users can delete template maps"); - err.http_status = 403; - throw err; - } - tpl_id = req.params.template_id.split('@'); - if ( tpl_id.length > 1 ) { - if ( tpl_id[0] != cdbuser ) { - var templateNotFoundErr = new Error("Cannot find template id '" + req.params.template_id + - "' for user '" + cdbuser + "'"); - templateNotFoundErr.http_status = 404; - throw templateNotFoundErr; - } - tpl_id = tpl_id[1]; - } + assert.ifError(err); + ifUnauthenticated(authenticated, 'Only authenticated users can delete template maps'); + + tpl_id = templateName(req.params.template_id); self.templateMaps.delTemplate(cdbuser, tpl_id, this); }, function prepareResponse(err/*, tpl_val*/){ if ( err ) throw err; return { status: 'ok' }; }, - function finish(err, response){ - if (err){ - var statusCode = 400; - response = { error: ''+err }; - if ( ! _.isUndefined(err.http_status) ) { - statusCode = err.http_status; - } - self.app.sendError(res, response, statusCode, 'DELETE TEMPLATE', err); - } else { - self.app.sendResponse(res, ['', 204]); - } - } + finishFn(self.app, res, 'DELETE TEMPLATE', ['', 204]) ); }; @@ -256,32 +172,16 @@ TemplateMapsController.prototype.list = function(req, res) { self.serverOptions.authorizedByAPIKey(req, this); }, function listTemplates(err, authenticated) { - if ( err ) throw err; - if (authenticated !== 1) { - err = new Error("Only authenticated user can list templated maps"); - err.http_status = 403; - throw err; - } + assert.ifError(err); + ifUnauthenticated(authenticated, 'Only authenticated user can list templated maps'); + self.templateMaps.listTemplates(cdbuser, this); }, function prepareResponse(err, tpl_ids){ - if ( err ) throw err; - // NOTE: might omit "cbduser" if == dbowner ... - var ids = _.map(tpl_ids, function(id) { return cdbuser + '@' + id; }); - return { template_ids: ids }; + assert.ifError(err); + return { template_ids: tpl_ids }; }, - function finish(err, response){ - var statusCode = 200; - if (err){ - response = { error: ''+err }; - if ( ! _.isUndefined(err.http_status) ) { - statusCode = err.http_status; - } - self.app.sendError(res, response, statusCode, 'GET TEMPLATE LIST', err); - } else { - self.app.sendResponse(res, [response, statusCode]); - } - } + finishFn(self.app, res, 'GET TEMPLATE LIST') ); }; @@ -293,9 +193,8 @@ TemplateMapsController.prototype.instantiate = function(req, res) { } step( function() { - if ( ! req.headers['content-type'] || req.headers['content-type'].split(';')[0] != 'application/json') { - throw new Error('template POST data must be of type application/json, it is instead '); - } + ifInvalidContentType(req, 'template POST data must be of type application/json'); + self.instantiateTemplate(req, res, req.body, this); }, function(err, response) { self.finish_instantiation(err, response, res); @@ -350,17 +249,7 @@ TemplateMapsController.prototype.instantiateTemplate = function(req, res, templa var fakereq; // used for call to createLayergroup var cdbuser = cdbRequest.userByReq(req); // Format of template_id: []@ - var tpl_id = req.params.template_id.split('@'); - if ( tpl_id.length > 1 ) { - if ( tpl_id[0] && tpl_id[0] != cdbuser ) { - var err = new Error('Cannot instanciate map of user "' + tpl_id[0] + '" on database of user "' + cdbuser + - '"'); - err.http_status = 403; - callback(err); - return; - } - tpl_id = tpl_id[1]; - } + var tpl_id = templateName(req.params.template_id); var auth_token = req.query.auth_token; step( function getTemplate(){ @@ -468,3 +357,44 @@ TemplateMapsController.prototype.setDBParams = function(cdbuser, params, callbac } ); }; + +function finishFn(app, res, description, okResponse) { + return function finish(err, response){ + var statusCode = 200; + if (err) { + statusCode = 400; + response = { error: '' + err }; + if ( ! _.isUndefined(err.http_status) ) { + statusCode = err.http_status; + } + app.sendError(res, response, statusCode, description, err); + } else { + app.sendResponse(res, okResponse || [response, statusCode]); + } + }; +} + +function ifUnauthenticated(authenticated, description) { + if (authenticated !== 1) { + var err = new Error(description); + err.http_status = 403; + throw err; + } +} + +function ifInvalidContentType(req, description) { + if ( ! req.headers['content-type'] || req.headers['content-type'].split(';')[0] != 'application/json' ) { + throw new Error(description); + } +} + +function templateName(templateId) { + var templateIdTokens = templateId.split('@'); + var name = templateIdTokens[0]; + + if (templateIdTokens.length > 1) { + name = templateIdTokens[1]; + } + + return name; +} diff --git a/test/acceptance/cache/surrogate_keys_invalidation.js b/test/acceptance/cache/surrogate_keys_invalidation.js index 8b626701..b4f4a165 100644 --- a/test/acceptance/cache/surrogate_keys_invalidation.js +++ b/test/acceptance/cache/surrogate_keys_invalidation.js @@ -23,7 +23,7 @@ describe('templates surrogate keys', function() { var templateOwner = 'localhost', templateName = 'acceptance', - expectedTemplateId = templateOwner + '@' + templateName, + expectedTemplateId = templateName, template = { version: '0.0.1', name: templateName, diff --git a/test/acceptance/templates.js b/test/acceptance/templates.js index aaf3e6b0..829abd12 100644 --- a/test/acceptance/templates.js +++ b/test/acceptance/templates.js @@ -69,7 +69,7 @@ describe('template_api', function() { it("can add template, returning id", function(done) { var errors = []; - var expected_tpl_id = "localhost@acceptance1"; + var expected_tpl_id = "acceptance1"; var post_request_1 = { url: '/api/v1/map/named', method: 'POST', @@ -801,7 +801,7 @@ describe('template_api', function() { ); }); - it("can instanciate a template by id", function(done) { + it("can instanciate a template by id wadus", function(done) { // This map fetches data from a private table var template_acceptance2 = { @@ -880,12 +880,10 @@ describe('template_api', function() { function instanciateAuth(err, res) { if ( err ) throw err; - assert.equal(res.statusCode, 403, res.statusCode + ': ' + res.body); + assert.equal(res.statusCode, 404, res.statusCode + ': ' + res.body); var parsed = JSON.parse(res.body); - assert.ok(parsed.hasOwnProperty('error'), - "Missing 'error' from response body: " + res.body); - assert.ok(parsed.error.match(/cannot instanciate/i), - 'Unexpected error for forbidden instance : ' + parsed.error); + assert.ok(parsed.hasOwnProperty('error'), "Missing 'error' from response body: " + res.body); + assert.ok(parsed.error.match(/not found/i), 'Unexpected error for forbidden instance : ' + parsed.error); var post_request = { url: '/api/v1/map/named/' + tpl_id + '?auth_token=valid2', method: 'POST', @@ -1907,7 +1905,7 @@ describe('template_api', function() { var template_params = {}; var errors = []; - var expectedTemplateId = username + '@' + httpTemplateName; + var expectedTemplateId = httpTemplateName; var layergroupid; step( function createTemplate()