diff --git a/lib/cartodb/controllers/layergroup.js b/lib/cartodb/controllers/layergroup.js index 9644aa06..f787c426 100644 --- a/lib/cartodb/controllers/layergroup.js +++ b/lib/cartodb/controllers/layergroup.js @@ -6,6 +6,7 @@ var BaseController = require('./base'); var cors = require('../middleware/cors'); var userMiddleware = require('../middleware/user'); +var layergroupTokenMiddleware = require('../middleware/layergroup-token'); var allowQueryParams = require('../middleware/allow-query-params'); var DataviewBackend = require('../backends/dataview'); @@ -52,29 +53,31 @@ module.exports = LayergroupController; LayergroupController.prototype.register = function(app) { app.get(app.base_url_mapconfig + - '/:token/:z/:x/:y@:scale_factor?x.:format', cors(), userMiddleware, + '/:token/:z/:x/:y@:scale_factor?x.:format', cors(), userMiddleware, layergroupTokenMiddleware, this.tile.bind(this)); app.get(app.base_url_mapconfig + - '/:token/:z/:x/:y.:format', cors(), userMiddleware, + '/:token/:z/:x/:y.:format', cors(), userMiddleware, layergroupTokenMiddleware, this.tile.bind(this)); app.get(app.base_url_mapconfig + - '/:token/:layer/:z/:x/:y.(:format)', cors(), userMiddleware, + '/:token/:layer/:z/:x/:y.(:format)', cors(), userMiddleware, layergroupTokenMiddleware, this.layer.bind(this)); app.get(app.base_url_mapconfig + - '/:token/:layer/attributes/:fid', cors(), userMiddleware, + '/:token/:layer/attributes/:fid', cors(), userMiddleware, layergroupTokenMiddleware, this.attributes.bind(this)); app.get(app.base_url_mapconfig + '/static/center/:token/:z/:lat/:lng/:width/:height.:format', cors(), userMiddleware, allowQueryParams(['layer']), + layergroupTokenMiddleware, this.center.bind(this)); app.get(app.base_url_mapconfig + '/static/bbox/:token/:west,:south,:east,:north/:width/:height.:format', cors(), userMiddleware, allowQueryParams(['layer']), + layergroupTokenMiddleware, this.bbox.bind(this)); // Undocumented/non-supported API endpoint methods. @@ -98,6 +101,7 @@ LayergroupController.prototype.register = function(app) { cors(), userMiddleware, allowQueryParams(allowedDataviewQueryParams), + layergroupTokenMiddleware, this.dataview.bind(this) ); @@ -106,6 +110,7 @@ LayergroupController.prototype.register = function(app) { cors(), userMiddleware, allowQueryParams(allowedDataviewQueryParams), + layergroupTokenMiddleware, this.dataview.bind(this) ); @@ -114,6 +119,7 @@ LayergroupController.prototype.register = function(app) { cors(), userMiddleware, allowQueryParams(allowedDataviewQueryParams), + layergroupTokenMiddleware, this.dataviewSearch.bind(this) ); @@ -122,11 +128,13 @@ LayergroupController.prototype.register = function(app) { cors(), userMiddleware, allowQueryParams(allowedDataviewQueryParams), + layergroupTokenMiddleware, this.dataviewSearch.bind(this) ); app.get(app.base_url_mapconfig + '/:token/analysis/node/:nodeId', cors(), userMiddleware, + layergroupTokenMiddleware, this.analysisNodeStatus.bind(this)); }; diff --git a/lib/cartodb/middleware/layergroup-token.js b/lib/cartodb/middleware/layergroup-token.js new file mode 100644 index 00000000..d9f7d214 --- /dev/null +++ b/lib/cartodb/middleware/layergroup-token.js @@ -0,0 +1,35 @@ +var LayergroupToken = require('../models/layergroup-token'); + +module.exports = function layergroupTokenMiddleware(req, res, next) { + if (!req.params.hasOwnProperty('token')) { + return next(); + } + + var user = req.context.user; + + var layergroupToken = LayergroupToken.parse(req.params.token); + req.params.token = layergroupToken.token; + req.params.cache_buster = layergroupToken.cacheBuster; + + if (layergroupToken.signer) { + req.params.signer = layergroupToken.signer; + if (!req.params.signer) { + req.params.signer = user; + } else if (req.params.signer !== user) { + var statusCode = 403; + if (req.query && req.query.callback) { + statusCode = 200; + } + var errorMessage = `Cannot use map signature of user "${req.params.signer}" on db of user "{${user}"`; + return res.status(statusCode).json({ + errors: [errorMessage], + errors_with_context: [{ + type: 'auth', + message: errorMessage + }] + }); + } + } + + return next(); +}; diff --git a/test/acceptance/ported/support/ported_server_options.js b/test/acceptance/ported/support/ported_server_options.js index d9af2d91..a2302288 100644 --- a/test/acceptance/ported/support/ported_server_options.js +++ b/test/acceptance/ported/support/ported_server_options.js @@ -1,6 +1,5 @@ var _ = require('underscore'); var serverOptions = require('../../../../lib/cartodb/server_options'); -var LayergroupToken = require('../../../../lib/cartodb/models/layergroup-token'); var mapnik = require('windshaft').mapnik; var OverviewsQueryRewriter = require('../../../../lib/cartodb/utils/overviews_query_rewriter'); var overviewsQueryRewriter = new OverviewsQueryRewriter({ @@ -56,9 +55,12 @@ module.exports = _.extend({}, serverOptions, { // this is in case you want to test sql parameters eg ...png?sql=select * from my_table limit 10 req.params = _.extend({}, req.params); - if (req.params.token) { - req.params.token = LayergroupToken.parse(req.params.token).token; - } + + // We don't want to inherit Date.now() `cache_buster` as it is the default value + // introduced by the middleware when no cache buster is found. + // We are only interested in the `token` for the ported tests. + delete req.params.cache_buster; + delete req.params.signer; _.extend(req.params, req.query); req.params.user = 'localhost';