From 8cd38071001697d4ce029a39514f280e572b0c2c Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 8 Jul 2015 13:11:57 +0200 Subject: [PATCH] Split named maps administration from instantiation/usage --- lib/cartodb/controllers/named_maps.js | 189 +----------------- lib/cartodb/controllers/named_maps_admin.js | 210 ++++++++++++++++++++ lib/cartodb/server.js | 5 +- 3 files changed, 216 insertions(+), 188 deletions(-) create mode 100644 lib/cartodb/controllers/named_maps_admin.js diff --git a/lib/cartodb/controllers/named_maps.js b/lib/cartodb/controllers/named_maps.js index a428bc5c..2806d4dd 100644 --- a/lib/cartodb/controllers/named_maps.js +++ b/lib/cartodb/controllers/named_maps.js @@ -5,10 +5,9 @@ var templateName = require('../backends/template_maps').templateName; var CdbRequest = require('../models/cdb_request'); var NamedMapsCacheEntry = require('../cache/model/named_maps_entry'); -function NamedMapsController(app, serverOptions, templateMaps, metadataBackend, mapBackend, templateBaseUrl, - surrogateKeysCache, layergroupRequestDecorator) { +function NamedMapsController(app, templateMaps, metadataBackend, mapBackend, templateBaseUrl, surrogateKeysCache, + layergroupRequestDecorator) { this.app = app; - this.serverOptions = serverOptions; this.templateMaps = templateMaps; this.metadataBackend = metadataBackend; this.mapBackend = mapBackend; @@ -24,11 +23,6 @@ var cdbRequest = new CdbRequest(); NamedMapsController.prototype.register = function(app) { app.get(this.templateBaseUrl + '/:template_id/:layer/:z/:x/:y.:format', this.tile.bind(this)); app.get(this.templateBaseUrl + '/:template_id/jsonp', this.jsonp.bind(this)); - app.post(this.templateBaseUrl, this.create.bind(this)); - app.put(this.templateBaseUrl + '/:template_id', this.update.bind(this)); - app.get(this.templateBaseUrl + '/:template_id', this.retrieve.bind(this)); - app.del(this.templateBaseUrl + '/:template_id', this.destroy.bind(this)); - app.get(this.templateBaseUrl, this.list.bind(this)); app.options(this.templateBaseUrl + '/:template_id', this.options.bind(this)); app.post(this.templateBaseUrl + '/:template_id', this.instantiate.bind(this)); }; @@ -161,161 +155,6 @@ NamedMapsController.prototype.tile = function(req, res) { ); }; -// Add a template -NamedMapsController.prototype.create = function(req, res) { - var self = this; - - this.app.doCORS(res); - - var cdbuser = cdbRequest.userByReq(req); - - step( - function checkPerms(){ - self.app.authorizedByAPIKey(cdbuser, req, this); - }, - function addTemplate(err, authenticated) { - 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){ - assert.ifError(err); - return { template_id: tpl_id }; - }, - finishFn(self.app, res, 'POST TEMPLATE') - ); -}; - -// Update a template -NamedMapsController.prototype.update = function(req, res) { - var self = this; - - this.app.doCORS(res); - - var cdbuser = cdbRequest.userByReq(req); - var template; - var tpl_id; - step( - function checkPerms(){ - self.app.authorizedByAPIKey(cdbuser, req, this); - }, - function updateTemplate(err, authenticated) { - 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 = templateName(req.params.template_id); - self.templateMaps.updTemplate(cdbuser, tpl_id, template, this); - }, - function prepareResponse(err){ - assert.ifError(err); - - return { template_id: tpl_id }; - }, - finishFn(self.app, res, 'PUT TEMPLATE') - ); -}; - -// Get a specific template -NamedMapsController.prototype.retrieve = function(req, res) { - var self = this; - - if (req.profiler) { - req.profiler.start('windshaft-cartodb.get_template'); - } - - this.app.doCORS(res); - - var cdbuser = cdbRequest.userByReq(req); - var tpl_id; - step( - function checkPerms(){ - self.app.authorizedByAPIKey(cdbuser, req, this); - }, - function getTemplate(err, authenticated) { - 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) { - if ( err ) throw err; - if ( ! tpl_val ) { - err = new Error("Cannot find template '" + tpl_id + "' of user '" + cdbuser + "'"); - err.http_status = 404; - throw err; - } - // auth_id was added by ourselves, - // so we remove it before returning to the user - delete tpl_val.auth_id; - return { template: tpl_val }; - }, - finishFn(self.app, res, 'GET TEMPLATE') - ); -}; - -// Delete a specific template -NamedMapsController.prototype.destroy = function(req, res) { - var self = this; - - if (req.profiler) { - req.profiler.start('windshaft-cartodb.delete_template'); - } - this.app.doCORS(res); - - var cdbuser = cdbRequest.userByReq(req); - var tpl_id; - step( - function checkPerms(){ - self.app.authorizedByAPIKey(cdbuser, req, this); - }, - function deleteTemplate(err, authenticated) { - 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' }; - }, - finishFn(self.app, res, 'DELETE TEMPLATE', ['', 204]) - ); -}; - -// Get a list of owned templates -NamedMapsController.prototype.list = function(req, res) { - var self = this; - if ( req.profiler ) { - req.profiler.start('windshaft-cartodb.get_template_list'); - } - this.app.doCORS(res); - - var cdbuser = cdbRequest.userByReq(req); - - step( - function checkPerms(){ - self.app.authorizedByAPIKey(cdbuser, req, this); - }, - function listTemplates(err, authenticated) { - assert.ifError(err); - ifUnauthenticated(authenticated, 'Only authenticated user can list templated maps'); - - self.templateMaps.listTemplates(cdbuser, this); - }, - function prepareResponse(err, tpl_ids){ - assert.ifError(err); - return { template_ids: tpl_ids }; - }, - finishFn(self.app, res, 'GET TEMPLATE LIST') - ); -}; - NamedMapsController.prototype.instantiate = function(req, res) { var self = this; @@ -473,30 +312,6 @@ NamedMapsController.prototype.finish_instantiation = function(err, response, res } }; -function finishFn(app, res, description, okResponse) { - return function finish(err, response){ - var statusCode = 200; - if (err) { - statusCode = 400; - response = { errors: ['' + 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) { - 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); diff --git a/lib/cartodb/controllers/named_maps_admin.js b/lib/cartodb/controllers/named_maps_admin.js new file mode 100644 index 00000000..4fd639b1 --- /dev/null +++ b/lib/cartodb/controllers/named_maps_admin.js @@ -0,0 +1,210 @@ +var step = require('step'); +var assert = require('assert'); +var _ = require('underscore'); +var templateName = require('../backends/template_maps').templateName; +var CdbRequest = require('../models/cdb_request'); + + +function NamedMapsAdminController(app, templateMaps, templateBaseUrl) { + this.app = app; + this.templateMaps = templateMaps; + this.templateBaseUrl = templateBaseUrl; +} + +module.exports = NamedMapsAdminController; + +var cdbRequest = new CdbRequest(); + +NamedMapsAdminController.prototype.register = function(app) { + app.post(this.templateBaseUrl, this.create.bind(this)); + app.put(this.templateBaseUrl + '/:template_id', this.update.bind(this)); + app.get(this.templateBaseUrl + '/:template_id', this.retrieve.bind(this)); + app.del(this.templateBaseUrl + '/:template_id', this.destroy.bind(this)); + app.get(this.templateBaseUrl, this.list.bind(this)); + app.options(this.templateBaseUrl + '/:template_id', this.options.bind(this)); +}; + +NamedMapsAdminController.prototype.create = function(req, res) { + var self = this; + + this.app.doCORS(res); + + var cdbuser = cdbRequest.userByReq(req); + + step( + function checkPerms(){ + self.app.authorizedByAPIKey(cdbuser, req, this); + }, + function addTemplate(err, authenticated) { + 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){ + assert.ifError(err); + return { template_id: tpl_id }; + }, + finishFn(self.app, res, 'POST TEMPLATE') + ); +}; + +NamedMapsAdminController.prototype.update = function(req, res) { + var self = this; + + this.app.doCORS(res); + + var cdbuser = cdbRequest.userByReq(req); + var template; + var tpl_id; + step( + function checkPerms(){ + self.app.authorizedByAPIKey(cdbuser, req, this); + }, + function updateTemplate(err, authenticated) { + 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 = templateName(req.params.template_id); + self.templateMaps.updTemplate(cdbuser, tpl_id, template, this); + }, + function prepareResponse(err){ + assert.ifError(err); + + return { template_id: tpl_id }; + }, + finishFn(self.app, res, 'PUT TEMPLATE') + ); +}; + +NamedMapsAdminController.prototype.retrieve = function(req, res) { + var self = this; + + if (req.profiler) { + req.profiler.start('windshaft-cartodb.get_template'); + } + + this.app.doCORS(res); + + var cdbuser = cdbRequest.userByReq(req); + var tpl_id; + step( + function checkPerms(){ + self.app.authorizedByAPIKey(cdbuser, req, this); + }, + function getTemplate(err, authenticated) { + 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) { + if ( err ) throw err; + if ( ! tpl_val ) { + err = new Error("Cannot find template '" + tpl_id + "' of user '" + cdbuser + "'"); + err.http_status = 404; + throw err; + } + // auth_id was added by ourselves, + // so we remove it before returning to the user + delete tpl_val.auth_id; + return { template: tpl_val }; + }, + finishFn(self.app, res, 'GET TEMPLATE') + ); +}; + +NamedMapsAdminController.prototype.destroy = function(req, res) { + var self = this; + + if (req.profiler) { + req.profiler.start('windshaft-cartodb.delete_template'); + } + this.app.doCORS(res); + + var cdbuser = cdbRequest.userByReq(req); + var tpl_id; + step( + function checkPerms(){ + self.app.authorizedByAPIKey(cdbuser, req, this); + }, + function deleteTemplate(err, authenticated) { + 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' }; + }, + finishFn(self.app, res, 'DELETE TEMPLATE', ['', 204]) + ); +}; + +NamedMapsAdminController.prototype.list = function(req, res) { + var self = this; + if ( req.profiler ) { + req.profiler.start('windshaft-cartodb.get_template_list'); + } + this.app.doCORS(res); + + var cdbuser = cdbRequest.userByReq(req); + + step( + function checkPerms(){ + self.app.authorizedByAPIKey(cdbuser, req, this); + }, + function listTemplates(err, authenticated) { + assert.ifError(err); + ifUnauthenticated(authenticated, 'Only authenticated user can list templated maps'); + + self.templateMaps.listTemplates(cdbuser, this); + }, + function prepareResponse(err, tpl_ids){ + assert.ifError(err); + return { template_ids: tpl_ids }; + }, + finishFn(self.app, res, 'GET TEMPLATE LIST') + ); +}; + +NamedMapsAdminController.prototype.options = function(req, res, next) { + this.app.doCORS(res, "Content-Type"); + return next(); +}; + +function finishFn(app, res, description, okResponse) { + return function finish(err, response){ + var statusCode = 200; + if (err) { + statusCode = 400; + response = { errors: ['' + 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) { + 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); + } +} diff --git a/lib/cartodb/server.js b/lib/cartodb/server.js index 390612fc..00cd3390 100644 --- a/lib/cartodb/server.js +++ b/lib/cartodb/server.js @@ -318,7 +318,6 @@ module.exports = function(serverOptions) { var NamedMapsController = require('./controllers/named_maps'), namedMapsController = new NamedMapsController( app, - serverOptions, templateMaps, metadataBackend, mapBackend, @@ -328,6 +327,10 @@ module.exports = function(serverOptions) { ); namedMapsController.register(app); + var NamedMapsAdminController = require('./controllers/named_maps_admin'), + namedMapsAdminController = new NamedMapsAdminController(app, templateMaps, template_baseurl); + namedMapsAdminController.register(app); + var TablesExtentApi = require('./api/tables_extent_api'); var tablesExtentApi = new TablesExtentApi(pgQueryRunner);