Merge branch 'master' into rateLimits
This commit is contained in:
commit
a830eb4ea0
20
NEWS.md
20
NEWS.md
@ -1,13 +1,27 @@
|
||||
# Changelog
|
||||
|
||||
## 5.4.0
|
||||
## 5.4.1
|
||||
Released yyyy-mm-dd
|
||||
- Upgrades Windshaft to 4.5.6 ([Mapnik top metrics](https://github.com/CartoDB/Windshaft/pull/597), [AttributesBackend allows multiple features if all the attributes are the same](https://github.com/CartoDB/Windshaft/pull/602))
|
||||
- Upgrades camshaft to 0.61.8
|
||||
|
||||
|
||||
## 5.4.0
|
||||
Released 2018-03-15
|
||||
- Upgrades Windshaft to 4.5.7 ([Mapnik top metrics](https://github.com/CartoDB/Windshaft/pull/597), [AttributesBackend allows multiple features if all the attributes are the same](https://github.com/CartoDB/Windshaft/pull/602))
|
||||
- Implemented middleware to authorize users via new Api Key system
|
||||
- Keep the old authorization system as fallback
|
||||
- Aggregation widget: Remove NULL categories in 'count' aggregations too
|
||||
- Update request to 2.85.0
|
||||
- Update camshaft to 0.61.3 (Fixes duplicated cartodb_id in AOI)
|
||||
- Update camshaft to 0.61.4 (Fixes for AOI and Merge analyses)
|
||||
- Update windshaft to 4.6.0, which in turn updates @carto/mapnik to 3.6.2-carto.4 and related dependencies. It brings in a cache for rasterized symbols. See https://github.com/CartoDB/node-mapnik/blob/v3.6.2-carto/CHANGELOG.carto.md#362-carto4
|
||||
- PostGIS: Variables in postgis SQL queries must now additionally be wrapped in `!` (refs [#29](https://github.com/CartoDB/mapnik/issues/29), [mapnik/#3618](https://github.com/mapnik/mapnik/pull/3618)):
|
||||
```sql
|
||||
-- Before
|
||||
SELECT ... WHERE trait = @variable
|
||||
|
||||
-- Now
|
||||
SELECT ... WHERE trait = !@variable!
|
||||
```
|
||||
|
||||
## 5.3.1
|
||||
Released 2018-02-13
|
||||
|
@ -18,24 +18,24 @@ AnalysesController.prototype.register = function (app) {
|
||||
userMiddleware(),
|
||||
rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.ANALYSIS_CATALOG),
|
||||
this.prepareContext,
|
||||
this.createPGClient(),
|
||||
this.getDataFromQuery({ queryTemplate: catalogQueryTpl, key: 'catalog' }),
|
||||
this.getDataFromQuery({ queryTemplate: tablesQueryTpl, key: 'tables' }),
|
||||
this.prepareResponse(),
|
||||
this.setCacheControlHeader(),
|
||||
this.sendResponse(),
|
||||
this.unathorizedError()
|
||||
createPGClient(),
|
||||
getDataFromQuery({ queryTemplate: catalogQueryTpl, key: 'catalog' }),
|
||||
getDataFromQuery({ queryTemplate: tablesQueryTpl, key: 'tables' }),
|
||||
prepareResponse(),
|
||||
setCacheControlHeader(),
|
||||
sendResponse(),
|
||||
unauthorizedError()
|
||||
);
|
||||
};
|
||||
|
||||
AnalysesController.prototype.createPGClient = function () {
|
||||
function createPGClient () {
|
||||
return function createPGClientMiddleware (req, res, next) {
|
||||
res.locals.pg = new PSQL(dbParamsFromReqParams(res.locals));
|
||||
next();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
AnalysesController.prototype.getDataFromQuery = function ({ queryTemplate, key }) {
|
||||
function getDataFromQuery({ queryTemplate, key }) {
|
||||
const readOnlyTransactionOn = true;
|
||||
|
||||
return function getCatalogMiddleware(req, res, next) {
|
||||
@ -52,9 +52,9 @@ AnalysesController.prototype.getDataFromQuery = function ({ queryTemplate, key }
|
||||
next();
|
||||
}, readOnlyTransactionOn);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
AnalysesController.prototype.prepareResponse = function () {
|
||||
function prepareResponse () {
|
||||
return function prepareResponseMiddleware (req, res, next) {
|
||||
const { catalog, tables } = res.locals;
|
||||
|
||||
@ -95,16 +95,16 @@ AnalysesController.prototype.prepareResponse = function () {
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
AnalysesController.prototype.setCacheControlHeader = function () {
|
||||
function setCacheControlHeader () {
|
||||
return function setCacheControlHeaderMiddleware (req, res, next) {
|
||||
res.set('Cache-Control', 'public,max-age=10,must-revalidate');
|
||||
next();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
AnalysesController.prototype.sendResponse = function() {
|
||||
function sendResponse () {
|
||||
return function sendResponseMiddleware (req, res) {
|
||||
res.status(200);
|
||||
|
||||
@ -114,9 +114,9 @@ AnalysesController.prototype.sendResponse = function() {
|
||||
res.json(res.body);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
AnalysesController.prototype.unathorizedError = function () {
|
||||
function unauthorizedError () {
|
||||
return function unathorizedErrorMiddleware(err, req, res, next) {
|
||||
if (err.message.match(/permission\sdenied/)) {
|
||||
err = new Error('Unauthorized');
|
||||
@ -125,7 +125,7 @@ AnalysesController.prototype.unathorizedError = function () {
|
||||
|
||||
next(err);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const catalogQueryTpl = ctx => `
|
||||
SELECT analysis_def->>'type' as type, * FROM cdb_analysis_catalog WHERE username = '${ctx._username}'
|
||||
|
@ -52,57 +52,62 @@ function NamedMapsController(
|
||||
module.exports = NamedMapsController;
|
||||
|
||||
NamedMapsController.prototype.register = function(app) {
|
||||
const tileOptions = {
|
||||
label: 'NAMED_MAP_TILE'
|
||||
};
|
||||
const { base_url_mapconfig, base_url_templated } = app;
|
||||
|
||||
app.get(
|
||||
app.base_url_templated + '/:template_id/:layer/:z/:x/:y.(:format)',
|
||||
`${base_url_templated}/:template_id/:layer/:z/:x/:y.(:format)`,
|
||||
cors(),
|
||||
userMiddleware(),
|
||||
rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_TILES),
|
||||
this.prepareContext,
|
||||
this.getNamedMapProvider(tileOptions),
|
||||
this.getAffectedTables(),
|
||||
this.getTile(tileOptions),
|
||||
this.setSurrogateKey(),
|
||||
this.setCacheChannelHeader(),
|
||||
this.setLastModifiedHeader(),
|
||||
this.setCacheControlHeader(),
|
||||
this.setContentTypeHeader(),
|
||||
this.respond(),
|
||||
getNamedMapProvider({
|
||||
namedMapProviderCache: this.namedMapProviderCache,
|
||||
label: 'NAMED_MAP_TILE'
|
||||
}),
|
||||
getAffectedTables(),
|
||||
getTile({
|
||||
tileBackend: this.tileBackend,
|
||||
label: 'NAMED_MAP_TILE'
|
||||
}),
|
||||
setSurrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }),
|
||||
setCacheChannelHeader(),
|
||||
setLastModifiedHeader(),
|
||||
setCacheControlHeader(),
|
||||
setContentTypeHeader(),
|
||||
sendResponse(),
|
||||
vectorError()
|
||||
);
|
||||
|
||||
const staticOptions = {
|
||||
forcedFormat: 'png',
|
||||
label: 'STATIC_VIZ_MAP'
|
||||
};
|
||||
|
||||
app.get(
|
||||
app.base_url_mapconfig + '/static/named/:template_id/:width/:height.:format',
|
||||
`${base_url_mapconfig}/static/named/:template_id/:width/:height.:format`,
|
||||
cors(),
|
||||
userMiddleware(),
|
||||
rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.STATIC_NAMED),
|
||||
allowQueryParams(['layer', 'zoom', 'lon', 'lat', 'bbox']),
|
||||
this.prepareContext,
|
||||
this.getNamedMapProvider(staticOptions),
|
||||
this.getAffectedTables(),
|
||||
this.getTemplate(staticOptions),
|
||||
this.prepareLayerFilterFromPreviewLayers(staticOptions),
|
||||
this.getStaticImageOptions(),
|
||||
this.getImage(staticOptions),
|
||||
this.incrementMapViews(),
|
||||
this.setSurrogateKey(),
|
||||
this.setCacheChannelHeader(),
|
||||
this.setLastModifiedHeader(),
|
||||
this.setCacheControlHeader(),
|
||||
this.setContentTypeHeader(),
|
||||
this.respond()
|
||||
getNamedMapProvider({
|
||||
namedMapProviderCache: this.namedMapProviderCache,
|
||||
label: 'STATIC_VIZ_MAP', forcedFormat: 'png'
|
||||
}),
|
||||
getAffectedTables(),
|
||||
getTemplate({ label: 'STATIC_VIZ_MAP' }),
|
||||
prepareLayerFilterFromPreviewLayers({
|
||||
namedMapProviderCache: this.namedMapProviderCache,
|
||||
label: 'STATIC_VIZ_MAP'
|
||||
}),
|
||||
getStaticImageOptions({ tablesExtentApi: this.tablesExtentApi }),
|
||||
getImage({ previewBackend: this.previewBackend, label: 'STATIC_VIZ_MAP' }),
|
||||
incrementMapViews({ metadataBackend: this.metadataBackend }),
|
||||
setSurrogateKeyHeader({ surrogateKeysCache: this.surrogateKeysCache }),
|
||||
setCacheChannelHeader(),
|
||||
setLastModifiedHeader(),
|
||||
setCacheControlHeader(),
|
||||
setContentTypeHeader(),
|
||||
sendResponse()
|
||||
);
|
||||
};
|
||||
|
||||
NamedMapsController.prototype.getNamedMapProvider = function ({ label, forcedFormat = null }) {
|
||||
function getNamedMapProvider ({ namedMapProviderCache, label, forcedFormat = null }) {
|
||||
return function getNamedMapProviderMiddleware (req, res, next) {
|
||||
const { user } = res.locals;
|
||||
const { config, auth_token } = req.query;
|
||||
@ -115,7 +120,7 @@ NamedMapsController.prototype.getNamedMapProvider = function ({ label, forcedFor
|
||||
|
||||
const params = getRequestParams(res.locals);
|
||||
|
||||
this.namedMapProviderCache.get(user, template_id, config, auth_token, params, (err, namedMapProvider) => {
|
||||
namedMapProviderCache.get(user, template_id, config, auth_token, params, (err, namedMapProvider) => {
|
||||
if (err) {
|
||||
err.label = label;
|
||||
return next(err);
|
||||
@ -125,10 +130,10 @@ NamedMapsController.prototype.getNamedMapProvider = function ({ label, forcedFor
|
||||
|
||||
next();
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.getAffectedTables = function () {
|
||||
function getAffectedTables () {
|
||||
return function getAffectedTables (req, res, next) {
|
||||
const { namedMapProvider } = res.locals;
|
||||
|
||||
@ -143,10 +148,10 @@ NamedMapsController.prototype.getAffectedTables = function () {
|
||||
|
||||
next();
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.getTemplate = function ({ label }) {
|
||||
function getTemplate ({ label }) {
|
||||
return function getTemplateMiddleware (req, res, next) {
|
||||
const { namedMapProvider } = res.locals;
|
||||
|
||||
@ -161,9 +166,9 @@ NamedMapsController.prototype.getTemplate = function ({ label }) {
|
||||
next();
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.prepareLayerFilterFromPreviewLayers = function ({ label }) {
|
||||
function prepareLayerFilterFromPreviewLayers ({ namedMapProviderCache, label }) {
|
||||
return function prepareLayerFilterFromPreviewLayersMiddleware (req, res, next) {
|
||||
const { user, template } = res.locals;
|
||||
const { template_id } = req.params;
|
||||
@ -192,7 +197,7 @@ NamedMapsController.prototype.prepareLayerFilterFromPreviewLayers = function ({
|
||||
params.layer = layerVisibilityFilter.join(',');
|
||||
|
||||
// recreates the provider
|
||||
this.namedMapProviderCache.get(user, template_id, config, auth_token, params, (err, provider) => {
|
||||
namedMapProviderCache.get(user, template_id, config, auth_token, params, (err, provider) => {
|
||||
if (err) {
|
||||
err.label = label;
|
||||
return next(err);
|
||||
@ -202,14 +207,14 @@ NamedMapsController.prototype.prepareLayerFilterFromPreviewLayers = function ({
|
||||
|
||||
next();
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.getTile = function ({ label }) {
|
||||
function getTile ({ tileBackend, label }) {
|
||||
return function getTileMiddleware (req, res, next) {
|
||||
const { namedMapProvider } = res.locals;
|
||||
|
||||
this.tileBackend.getTile(namedMapProvider, req.params, (err, tile, headers, stats) => {
|
||||
tileBackend.getTile(namedMapProvider, req.params, (err, tile, headers, stats) => {
|
||||
req.profiler.add(stats);
|
||||
|
||||
if (err) {
|
||||
@ -223,10 +228,10 @@ NamedMapsController.prototype.getTile = function ({ label }) {
|
||||
|
||||
next();
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.getStaticImageOptions = function () {
|
||||
function getStaticImageOptions ({ tablesExtentApi }) {
|
||||
return function getStaticImageOptionsMiddleware(req, res, next) {
|
||||
const { user, namedMapProvider, template } = res.locals;
|
||||
|
||||
@ -250,7 +255,7 @@ NamedMapsController.prototype.getStaticImageOptions = function () {
|
||||
return next();
|
||||
}
|
||||
|
||||
this.tablesExtentApi.getBounds(user, affectedTables, (err, bounds) => {
|
||||
tablesExtentApi.getBounds(user, affectedTables, (err, bounds) => {
|
||||
if (err) {
|
||||
return next();
|
||||
}
|
||||
@ -260,8 +265,8 @@ NamedMapsController.prototype.getStaticImageOptions = function () {
|
||||
return next();
|
||||
});
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function getImageOptions (params, template) {
|
||||
const { zoom, lon, lat, bbox } = params;
|
||||
@ -328,7 +333,7 @@ function getImageOptionsFromBoundingBox (bbox = '') {
|
||||
}
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.getImage = function ({ label }) {
|
||||
function getImage({ previewBackend, label }) {
|
||||
return function getImageMiddleware (req, res, next) {
|
||||
const { imageOpts, namedMapProvider } = res.locals;
|
||||
const { zoom, center, bounds } = imageOpts;
|
||||
@ -341,7 +346,7 @@ NamedMapsController.prototype.getImage = function ({ label }) {
|
||||
const format = req.params.format === 'jpg' ? 'jpeg' : 'png';
|
||||
|
||||
if (zoom !== undefined && center) {
|
||||
return this.previewBackend.getImage(namedMapProvider, format, width, height, zoom, center,
|
||||
return previewBackend.getImage(namedMapProvider, format, width, height, zoom, center,
|
||||
(err, image, headers, stats) => {
|
||||
if (err) {
|
||||
err.label = label;
|
||||
@ -356,7 +361,7 @@ NamedMapsController.prototype.getImage = function ({ label }) {
|
||||
});
|
||||
}
|
||||
|
||||
this.previewBackend.getImage(namedMapProvider, format, width, height, bounds, (err, image, headers, stats) => {
|
||||
previewBackend.getImage(namedMapProvider, format, width, height, bounds, (err, image, headers, stats) => {
|
||||
if (err) {
|
||||
err.label = label;
|
||||
return next(err);
|
||||
@ -368,14 +373,14 @@ NamedMapsController.prototype.getImage = function ({ label }) {
|
||||
|
||||
next();
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function incrementMapViewsError (ctx) {
|
||||
return `ERROR: failed to increment mapview count for user '${ctx.user}': ${ctx.err}`;
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.incrementMapViews = function () {
|
||||
function incrementMapViews ({ metadataBackend }) {
|
||||
return function incrementMapViewsMiddleware(req, res, next) {
|
||||
const { user, namedMapProvider } = res.locals;
|
||||
|
||||
@ -387,7 +392,7 @@ NamedMapsController.prototype.incrementMapViews = function () {
|
||||
|
||||
const statTag = mapConfig.obj().stat_tag;
|
||||
|
||||
this.metadataBackend.incMapviewCount(user, statTag, (err) => {
|
||||
metadataBackend.incMapviewCount(user, statTag, (err) => {
|
||||
if (err) {
|
||||
global.logger.log(incrementMapViewsError({ user, err }));
|
||||
}
|
||||
@ -395,8 +400,8 @@ NamedMapsController.prototype.incrementMapViews = function () {
|
||||
next();
|
||||
});
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function templateZoomCenter(view) {
|
||||
if (view.zoom !== undefined && view.center) {
|
||||
@ -428,7 +433,22 @@ function templateBounds(view) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.setCacheChannelHeader = function () {
|
||||
function setSurrogateKeyHeader ({ surrogateKeysCache }) {
|
||||
return function setSurrogateKeyHeaderMiddleware(req, res, next) {
|
||||
const { user, namedMapProvider, affectedTablesAndLastUpdate } = res.locals;
|
||||
|
||||
surrogateKeysCache.tag(res, new NamedMapsCacheEntry(user, namedMapProvider.getTemplateName()));
|
||||
if (!affectedTablesAndLastUpdate || !!affectedTablesAndLastUpdate.tables) {
|
||||
if (affectedTablesAndLastUpdate.tables.length > 0) {
|
||||
surrogateKeysCache.tag(res, affectedTablesAndLastUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
function setCacheChannelHeader () {
|
||||
return function setCacheChannelHeaderMiddleware (req, res, next) {
|
||||
const { affectedTablesAndLastUpdate } = res.locals;
|
||||
|
||||
@ -438,24 +458,9 @@ NamedMapsController.prototype.setCacheChannelHeader = function () {
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.setSurrogateKey = function () {
|
||||
return function setSurrogateKeyMiddleware(req, res, next) {
|
||||
const { user, namedMapProvider, affectedTablesAndLastUpdate } = res.locals;
|
||||
|
||||
this.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(user, namedMapProvider.getTemplateName()));
|
||||
if (!affectedTablesAndLastUpdate || !!affectedTablesAndLastUpdate.tables) {
|
||||
if (affectedTablesAndLastUpdate.tables.length > 0) {
|
||||
this.surrogateKeysCache.tag(res, affectedTablesAndLastUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
NamedMapsController.prototype.setLastModifiedHeader = function () {
|
||||
function setLastModifiedHeader () {
|
||||
return function setLastModifiedHeaderMiddleware(req, res, next) {
|
||||
const { affectedTablesAndLastUpdate } = res.locals;
|
||||
|
||||
@ -472,9 +477,9 @@ NamedMapsController.prototype.setLastModifiedHeader = function () {
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.setCacheControlHeader = function () {
|
||||
function setCacheControlHeader () {
|
||||
return function setCacheControlHeaderMiddleware(req, res, next) {
|
||||
const { affectedTablesAndLastUpdate } = res.locals;
|
||||
|
||||
@ -487,9 +492,9 @@ NamedMapsController.prototype.setCacheControlHeader = function () {
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.setContentTypeHeader = function () {
|
||||
function setContentTypeHeader () {
|
||||
return function setContentTypeHeaderMiddleware(req, res, next) {
|
||||
const { headers = {} } = res.locals;
|
||||
|
||||
@ -497,10 +502,10 @@ NamedMapsController.prototype.setContentTypeHeader = function () {
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.respond = function () {
|
||||
return function respondMiddleware (req, res) {
|
||||
function sendResponse () {
|
||||
return function sendResponseMiddleware (req, res) {
|
||||
const { body, stats = {}, format } = res.locals;
|
||||
|
||||
req.profiler.done('render-' + format);
|
||||
@ -509,4 +514,4 @@ NamedMapsController.prototype.respond = function () {
|
||||
res.status(200);
|
||||
res.send(body);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -30,9 +30,10 @@ NamedMapsAdminController.prototype.register = function (app) {
|
||||
rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_CREATE),
|
||||
localsMiddleware(),
|
||||
credentialsMiddleware(),
|
||||
this.checkContentType('POST', 'POST TEMPLATE'),
|
||||
this.authorizedByAPIKey('create', 'POST TEMPLATE'),
|
||||
this.create()
|
||||
checkContentType({ action: 'POST', label: 'POST TEMPLATE' }),
|
||||
authorizedByAPIKey({ authApi: this.authApi, action: 'create', label: 'POST TEMPLATE' }),
|
||||
createTemplate({ templateMaps: this.templateMaps }),
|
||||
sendResponse()
|
||||
);
|
||||
|
||||
app.put(
|
||||
@ -42,9 +43,10 @@ NamedMapsAdminController.prototype.register = function (app) {
|
||||
rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_UPDATE),
|
||||
localsMiddleware(),
|
||||
credentialsMiddleware(),
|
||||
this.checkContentType('PUT', 'PUT TEMPLATE'),
|
||||
this.authorizedByAPIKey('update', 'PUT TEMPLATE'),
|
||||
this.update()
|
||||
checkContentType({ action: 'PUT', label: 'PUT TEMPLATE' }),
|
||||
authorizedByAPIKey({ authApi: this.authApi, action: 'update', label: 'PUT TEMPLATE' }),
|
||||
updateTemplate({ templateMaps: this.templateMaps }),
|
||||
sendResponse()
|
||||
);
|
||||
|
||||
app.get(
|
||||
@ -54,8 +56,9 @@ NamedMapsAdminController.prototype.register = function (app) {
|
||||
rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_GET),
|
||||
localsMiddleware(),
|
||||
credentialsMiddleware(),
|
||||
this.authorizedByAPIKey('get', 'GET TEMPLATE'),
|
||||
this.retrieve()
|
||||
authorizedByAPIKey({ authApi: this.authApi, action: 'get', label: 'GET TEMPLATE' }),
|
||||
retrieveTemplate({ templateMaps: this.templateMaps }),
|
||||
sendResponse()
|
||||
);
|
||||
|
||||
app.delete(
|
||||
@ -65,8 +68,9 @@ NamedMapsAdminController.prototype.register = function (app) {
|
||||
rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_DELETE),
|
||||
localsMiddleware(),
|
||||
credentialsMiddleware(),
|
||||
this.authorizedByAPIKey('delete', 'DELETE TEMPLATE'),
|
||||
this.destroy()
|
||||
authorizedByAPIKey({ authApi: this.authApi, action: 'delete', label: 'DELETE TEMPLATE' }),
|
||||
destroyTemplate({ templateMaps: this.templateMaps }),
|
||||
sendResponse()
|
||||
);
|
||||
|
||||
app.get(
|
||||
@ -76,8 +80,9 @@ NamedMapsAdminController.prototype.register = function (app) {
|
||||
rateLimit(this.userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_LIST),
|
||||
localsMiddleware(),
|
||||
credentialsMiddleware(),
|
||||
this.authorizedByAPIKey('list', 'GET TEMPLATE LIST'),
|
||||
this.list()
|
||||
authorizedByAPIKey({ authApi: this.authApi, action: 'list', label: 'GET TEMPLATE LIST' }),
|
||||
listTemplates({ templateMaps: this.templateMaps }),
|
||||
sendResponse()
|
||||
);
|
||||
|
||||
app.options(
|
||||
@ -86,10 +91,23 @@ NamedMapsAdminController.prototype.register = function (app) {
|
||||
);
|
||||
};
|
||||
|
||||
NamedMapsAdminController.prototype.authorizedByAPIKey = function (action, label) {
|
||||
function checkContentType ({ action, label }) {
|
||||
return function checkContentTypeMiddleware (req, res, next) {
|
||||
if (!req.is('application/json')) {
|
||||
const error = new Error(`template ${action} data must be of type application/json`);
|
||||
error.label = label;
|
||||
return next(error);
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
function authorizedByAPIKey ({ authApi, action, label }) {
|
||||
return function authorizedByAPIKeyMiddleware (req, res, next) {
|
||||
const { user } = res.locals;
|
||||
this.authApi.authorizedByAPIKey(user, res, (err, authenticated) => {
|
||||
|
||||
authApi.authorizedByAPIKey(user, res, (err, authenticated) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
@ -103,65 +121,52 @@ NamedMapsAdminController.prototype.authorizedByAPIKey = function (action, label)
|
||||
|
||||
next();
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
NamedMapsAdminController.prototype.checkContentType = function (action, label) {
|
||||
return function checkContentTypeMiddleware (req, res, next) {
|
||||
if (!req.is('application/json')) {
|
||||
const error = new Error(`template ${action} data must be of type application/json`);
|
||||
error.label = label;
|
||||
return next(error);
|
||||
}
|
||||
next();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsAdminController.prototype.create = function () {
|
||||
function createTemplate ({ templateMaps }) {
|
||||
return function createTemplateMiddleware (req, res, next) {
|
||||
const { user } = res.locals;
|
||||
const template = req.body;
|
||||
|
||||
this.templateMaps.addTemplate(user, template, (err, templateId) => {
|
||||
templateMaps.addTemplate(user, template, (err, templateId) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
res.status(200);
|
||||
res.body = { template_id: templateId };
|
||||
|
||||
const method = req.query.callback ? 'jsonp' : 'json';
|
||||
res[method]({ template_id: templateId });
|
||||
next();
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsAdminController.prototype.update = function () {
|
||||
function updateTemplate ({ templateMaps }) {
|
||||
return function updateTemplateMiddleware (req, res, next) {
|
||||
const { user } = res.locals;
|
||||
const template = req.body;
|
||||
const templateId = templateName(req.params.template_id);
|
||||
|
||||
this.templateMaps.updTemplate(user, templateId, template, (err) => {
|
||||
templateMaps.updTemplate(user, templateId, template, (err) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
res.status(200);
|
||||
res.body = { template_id: templateId };
|
||||
|
||||
const method = req.query.callback ? 'jsonp' : 'json';
|
||||
res[method]({ template_id: templateId });
|
||||
next();
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsAdminController.prototype.retrieve = function () {
|
||||
function retrieveTemplate ({ templateMaps }) {
|
||||
return function retrieveTemplateMiddleware (req, res, next) {
|
||||
req.profiler.start('windshaft-cartodb.get_template');
|
||||
|
||||
const { user } = res.locals;
|
||||
const templateId = templateName(req.params.template_id);
|
||||
|
||||
this.templateMaps.getTemplate(user, templateId, (err, template) => {
|
||||
templateMaps.getTemplate(user, templateId, (err, template) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
@ -175,49 +180,56 @@ NamedMapsAdminController.prototype.retrieve = function () {
|
||||
// so we remove it before returning to the user
|
||||
delete template.auth_id;
|
||||
|
||||
res.status(200);
|
||||
res.body = { template };
|
||||
|
||||
const method = req.query.callback ? 'jsonp' : 'json';
|
||||
res[method]({ template });
|
||||
next();
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsAdminController.prototype.destroy = function () {
|
||||
function destroyTemplate ({ templateMaps }) {
|
||||
return function destroyTemplateMiddleware (req, res, next) {
|
||||
req.profiler.start('windshaft-cartodb.delete_template');
|
||||
|
||||
const { user } = res.locals;
|
||||
const templateId = templateName(req.params.template_id);
|
||||
|
||||
this.templateMaps.delTemplate(user, templateId, (err/* , tpl_val */) => {
|
||||
templateMaps.delTemplate(user, templateId, (err/* , tpl_val */) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
res.status(204);
|
||||
res.statusCode = 204;
|
||||
res.body = '';
|
||||
|
||||
const method = req.query.callback ? 'jsonp' : 'json';
|
||||
res[method]('');
|
||||
next();
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
NamedMapsAdminController.prototype.list = function () {
|
||||
function listTemplates ({ templateMaps }) {
|
||||
return function listTemplatesMiddleware (req, res, next) {
|
||||
req.profiler.start('windshaft-cartodb.get_template_list');
|
||||
|
||||
const { user } = res.locals;
|
||||
|
||||
this.templateMaps.listTemplates(user, (err, templateIds) => {
|
||||
templateMaps.listTemplates(user, (err, templateIds) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
res.status(200);
|
||||
res.body = { template_ids: templateIds };
|
||||
|
||||
const method = req.query.callback ? 'jsonp' : 'json';
|
||||
res[method]({ template_ids: templateIds });
|
||||
next();
|
||||
});
|
||||
}.bind(this);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function sendResponse () {
|
||||
return function sendResponseMiddleware (req, res) {
|
||||
res.status(res.statusCode || 200);
|
||||
|
||||
const method = req.query.callback ? 'jsonp' : 'json';
|
||||
res[method](res.body);
|
||||
};
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "windshaft-cartodb",
|
||||
"version": "5.3.2",
|
||||
"version": "5.4.1",
|
||||
"description": "A map tile server for CartoDB",
|
||||
"keywords": [
|
||||
"cartodb"
|
||||
@ -26,7 +26,7 @@
|
||||
"dependencies": {
|
||||
"basic-auth": "^2.0.0",
|
||||
"body-parser": "^1.18.2",
|
||||
"camshaft": "0.61.3",
|
||||
"camshaft": "0.61.8",
|
||||
"cartodb-psql": "0.10.2",
|
||||
"cartodb-query-tables": "0.3.0",
|
||||
"cartodb-redis": "cartodb/node-cartodb-redis#rateLimits",
|
||||
@ -48,7 +48,7 @@
|
||||
"step-profiler": "~0.3.0",
|
||||
"turbo-carto": "0.20.2",
|
||||
"underscore": "~1.6.0",
|
||||
"windshaft": "4.5.6",
|
||||
"windshaft": "4.6.0",
|
||||
"yargs": "~5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 27 KiB |
54
yarn.lock
54
yarn.lock
@ -2,20 +2,20 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@carto/mapnik@3.6.2-carto.2", "@carto/mapnik@~3.6.2-carto.0":
|
||||
version "3.6.2-carto.2"
|
||||
resolved "https://registry.yarnpkg.com/@carto/mapnik/-/mapnik-3.6.2-carto.2.tgz#45a055fd2d39530a873ef9ce5a325baacc81c196"
|
||||
"@carto/mapnik@3.6.2-carto.4":
|
||||
version "3.6.2-carto.4"
|
||||
resolved "https://registry.yarnpkg.com/@carto/mapnik/-/mapnik-3.6.2-carto.4.tgz#54042a5dbea293c54e1bd286b32277694c5dc2d2"
|
||||
dependencies:
|
||||
mapnik-vector-tile "1.5.0"
|
||||
nan "~2.7.0"
|
||||
node-pre-gyp "~0.6.30"
|
||||
protozero "1.5.1"
|
||||
|
||||
"@carto/tilelive-bridge@cartodb/tilelive-bridge#2.5.1-cdb3":
|
||||
version "2.5.1-cdb3"
|
||||
resolved "https://codeload.github.com/cartodb/tilelive-bridge/tar.gz/e61c7752c033595a273dcd1d4b267252b174bd28"
|
||||
"@carto/tilelive-bridge@cartodb/tilelive-bridge#2.5.1-cdb4":
|
||||
version "2.5.1-cdb4"
|
||||
resolved "https://codeload.github.com/cartodb/tilelive-bridge/tar.gz/3eb554e5109199f50f457cec72ee288cffa5d6b3"
|
||||
dependencies:
|
||||
"@carto/mapnik" "3.6.2-carto.2"
|
||||
"@carto/mapnik" "3.6.2-carto.4"
|
||||
"@mapbox/sphericalmercator" "~1.0.1"
|
||||
mapnik-pool "~0.1.3"
|
||||
|
||||
@ -23,11 +23,11 @@
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/sphericalmercator/-/sphericalmercator-1.0.5.tgz#70237b9774095ed1cfdbcea7a8fd1fc82b2691f2"
|
||||
|
||||
abaculus@cartodb/abaculus#2.0.3-cdb2:
|
||||
version "2.0.3-cdb2"
|
||||
resolved "https://codeload.github.com/cartodb/abaculus/tar.gz/6468e0e3fddb2b23f60b9a3156117cff0307f6dc"
|
||||
abaculus@cartodb/abaculus#2.0.3-cdb5:
|
||||
version "2.0.3-cdb5"
|
||||
resolved "https://codeload.github.com/cartodb/abaculus/tar.gz/b899cbea04b3e6093aa3ef32331920acd5f839a1"
|
||||
dependencies:
|
||||
"@carto/mapnik" "~3.6.2-carto.0"
|
||||
"@carto/mapnik" "3.6.2-carto.4"
|
||||
d3-queue "^2.0.2"
|
||||
sphericalmercator "1.0.x"
|
||||
|
||||
@ -238,16 +238,16 @@ camelcase@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
|
||||
|
||||
camshaft@0.61.3:
|
||||
version "0.61.3"
|
||||
resolved "https://registry.yarnpkg.com/camshaft/-/camshaft-0.61.3.tgz#a1507f19e39dbf98940298ba1704b742741a5053"
|
||||
camshaft@0.61.8:
|
||||
version "0.61.8"
|
||||
resolved "https://registry.yarnpkg.com/camshaft/-/camshaft-0.61.8.tgz#75669c6c14791a93433e79a8892298e88cb0fce2"
|
||||
dependencies:
|
||||
async "^1.5.2"
|
||||
bunyan "1.8.1"
|
||||
cartodb-psql "^0.10.1"
|
||||
debug "^3.1.0"
|
||||
dot "^1.0.3"
|
||||
request "^2.69.0"
|
||||
request "2.85.0"
|
||||
|
||||
canvas@cartodb/node-canvas#1.6.2-cdb2:
|
||||
version "1.6.2-cdb2"
|
||||
@ -1912,7 +1912,7 @@ request@2.85.0:
|
||||
tunnel-agent "^0.6.0"
|
||||
uuid "^3.1.0"
|
||||
|
||||
request@2.x, request@^2.55.0, request@^2.69.0:
|
||||
request@2.x, request@^2.55.0:
|
||||
version "2.83.0"
|
||||
resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356"
|
||||
dependencies:
|
||||
@ -2239,11 +2239,11 @@ through@2:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
|
||||
tilelive-mapnik@cartodb/tilelive-mapnik#0.6.18-cdb7:
|
||||
version "0.6.18-cdb7"
|
||||
resolved "https://codeload.github.com/cartodb/tilelive-mapnik/tar.gz/488d2acd65c89cc5382d996eabe8dc1f5051ce0f"
|
||||
tilelive-mapnik@cartodb/tilelive-mapnik#0.6.18-cdb8:
|
||||
version "0.6.18-cdb8"
|
||||
resolved "https://codeload.github.com/cartodb/tilelive-mapnik/tar.gz/9cb4546c8fdd34ced0a41dbf70e143475b4e2067"
|
||||
dependencies:
|
||||
"@carto/mapnik" "3.6.2-carto.2"
|
||||
"@carto/mapnik" "3.6.2-carto.4"
|
||||
generic-pool "~2.4.0"
|
||||
mime "~1.6.0"
|
||||
sphericalmercator "~1.0.4"
|
||||
@ -2400,13 +2400,13 @@ window-size@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075"
|
||||
|
||||
windshaft@4.5.6:
|
||||
version "4.5.6"
|
||||
resolved "https://registry.yarnpkg.com/windshaft/-/windshaft-4.5.6.tgz#566c635f25e4dfc18b46cffe1b22b8c9626f8295"
|
||||
windshaft@4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/windshaft/-/windshaft-4.6.0.tgz#d9394aff73c0aa761207ad2b0f12d1c23ac41244"
|
||||
dependencies:
|
||||
"@carto/mapnik" "3.6.2-carto.2"
|
||||
"@carto/tilelive-bridge" cartodb/tilelive-bridge#2.5.1-cdb3
|
||||
abaculus cartodb/abaculus#2.0.3-cdb2
|
||||
"@carto/mapnik" "3.6.2-carto.4"
|
||||
"@carto/tilelive-bridge" cartodb/tilelive-bridge#2.5.1-cdb4
|
||||
abaculus cartodb/abaculus#2.0.3-cdb5
|
||||
canvas cartodb/node-canvas#1.6.2-cdb2
|
||||
carto cartodb/carto#0.15.1-cdb3
|
||||
cartodb-psql "^0.10.1"
|
||||
@ -2420,7 +2420,7 @@ windshaft@4.5.6:
|
||||
sphericalmercator "1.0.4"
|
||||
step "~0.0.6"
|
||||
tilelive "5.12.2"
|
||||
tilelive-mapnik cartodb/tilelive-mapnik#0.6.18-cdb7
|
||||
tilelive-mapnik cartodb/tilelive-mapnik#0.6.18-cdb8
|
||||
torque.js "~2.11.0"
|
||||
underscore "~1.6.0"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user