2018-10-23 23:45:42 +08:00
|
|
|
'use strict';
|
|
|
|
|
2019-10-07 16:50:14 +08:00
|
|
|
const { templateName } = require('../../backends/template-maps');
|
2018-04-07 00:20:33 +08:00
|
|
|
const credentials = require('../middlewares/credentials');
|
|
|
|
const rateLimit = require('../middlewares/rate-limit');
|
2018-02-27 23:52:27 +08:00
|
|
|
const { RATE_LIMIT_ENDPOINTS_GROUPS } = rateLimit;
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2018-05-11 22:07:25 +08:00
|
|
|
module.exports = class AdminTemplateController {
|
|
|
|
/**
|
|
|
|
* @param {AuthBackend} authBackend
|
|
|
|
* @param {PgConnection} pgConnection
|
|
|
|
* @param {TemplateMaps} templateMaps
|
|
|
|
* @constructor
|
|
|
|
*/
|
|
|
|
constructor (authBackend, templateMaps, userLimitsBackend) {
|
|
|
|
this.authBackend = authBackend;
|
|
|
|
this.templateMaps = templateMaps;
|
|
|
|
this.userLimitsBackend = userLimitsBackend;
|
|
|
|
}
|
|
|
|
|
2019-10-04 18:22:23 +08:00
|
|
|
route (templateRouter) {
|
2018-05-11 22:07:25 +08:00
|
|
|
templateRouter.options(`/:template_id`);
|
|
|
|
|
|
|
|
templateRouter.post('/', this.middlewares({
|
|
|
|
action: 'create',
|
|
|
|
label: 'POST TEMPLATE',
|
|
|
|
rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_CREATE
|
|
|
|
}));
|
|
|
|
|
|
|
|
templateRouter.put('/:template_id', this.middlewares({
|
|
|
|
action: 'update',
|
|
|
|
label: 'PUT TEMPLATE',
|
|
|
|
rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_UPDATE
|
|
|
|
}));
|
|
|
|
|
|
|
|
templateRouter.get('/:template_id', this.middlewares({
|
|
|
|
action: 'get',
|
|
|
|
label: 'GET TEMPLATE',
|
|
|
|
rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_GET
|
|
|
|
}));
|
|
|
|
|
|
|
|
templateRouter.delete('/:template_id', this.middlewares({
|
|
|
|
action: 'delete',
|
|
|
|
label: 'DELETE TEMPLATE',
|
|
|
|
rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_DELETE
|
|
|
|
}));
|
|
|
|
|
|
|
|
templateRouter.get('/', this.middlewares({
|
|
|
|
action: 'list',
|
|
|
|
label: 'GET TEMPLATE LIST',
|
|
|
|
rateLimitGroup: RATE_LIMIT_ENDPOINTS_GROUPS.NAMED_LIST
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
middlewares ({ action, label, rateLimitGroup }) {
|
|
|
|
let template;
|
|
|
|
|
|
|
|
if (action === 'create') {
|
|
|
|
template = createTemplate;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action === 'update') {
|
|
|
|
template = updateTemplate;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action === 'get') {
|
|
|
|
template = retrieveTemplate;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action === 'delete') {
|
|
|
|
template = destroyTemplate;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action === 'list') {
|
|
|
|
template = listTemplates;
|
|
|
|
}
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2018-05-11 22:07:25 +08:00
|
|
|
return [
|
|
|
|
credentials(),
|
|
|
|
authorizedByAPIKey({ authBackend: this.authBackend, action, label }),
|
|
|
|
rateLimit(this.userLimitsBackend, rateLimitGroup),
|
|
|
|
checkContentType({ action: 'POST', label: 'POST TEMPLATE' }),
|
|
|
|
template({ templateMaps: this.templateMaps })
|
|
|
|
];
|
|
|
|
}
|
2015-07-08 19:11:57 +08:00
|
|
|
};
|
|
|
|
|
2018-05-11 22:07:25 +08:00
|
|
|
function checkContentType ({ label }) {
|
2018-03-13 20:12:18 +08:00
|
|
|
return function checkContentTypeMiddleware (req, res, next) {
|
2018-05-11 22:07:25 +08:00
|
|
|
if ((req.method === 'POST' || req.method === 'PUT') && !req.is('application/json')) {
|
|
|
|
const error = new Error(`${req.method} template data must be of type application/json`);
|
2018-03-13 20:12:18 +08:00
|
|
|
error.label = label;
|
|
|
|
return next(error);
|
|
|
|
}
|
2018-03-13 20:31:49 +08:00
|
|
|
|
2018-03-13 20:12:18 +08:00
|
|
|
next();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-04-10 00:08:56 +08:00
|
|
|
function authorizedByAPIKey ({ authBackend, action, label }) {
|
2017-12-29 22:19:52 +08:00
|
|
|
return function authorizedByAPIKeyMiddleware (req, res, next) {
|
|
|
|
const { user } = res.locals;
|
2018-03-13 20:12:18 +08:00
|
|
|
|
2018-04-10 22:15:49 +08:00
|
|
|
authBackend.authorizedByAPIKey(user, res, (err, authenticated, apikey) => {
|
2017-12-29 22:19:52 +08:00
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!authenticated) {
|
2018-05-07 21:44:44 +08:00
|
|
|
const error = new Error(`Only authenticated users can ${action} templated maps`);
|
2017-12-29 22:19:52 +08:00
|
|
|
error.http_status = 403;
|
|
|
|
error.label = label;
|
|
|
|
return next(error);
|
|
|
|
}
|
|
|
|
|
2018-04-06 21:26:11 +08:00
|
|
|
if (apikey.type !== 'master') {
|
|
|
|
const error = new Error('Forbidden');
|
|
|
|
error.type = 'auth';
|
|
|
|
error.subtype = 'api-key-does-not-grant-access';
|
|
|
|
error.http_status = 403;
|
|
|
|
|
|
|
|
return next(error);
|
|
|
|
}
|
|
|
|
|
2017-12-29 22:19:52 +08:00
|
|
|
next();
|
|
|
|
});
|
|
|
|
};
|
2018-03-13 20:12:18 +08:00
|
|
|
}
|
2017-12-29 22:19:52 +08:00
|
|
|
|
2018-03-15 00:31:37 +08:00
|
|
|
function createTemplate ({ templateMaps }) {
|
2017-12-29 23:15:48 +08:00
|
|
|
return function createTemplateMiddleware (req, res, next) {
|
2017-12-30 01:34:54 +08:00
|
|
|
const { user } = res.locals;
|
2017-12-29 23:30:42 +08:00
|
|
|
const template = req.body;
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2018-03-13 20:12:18 +08:00
|
|
|
templateMaps.addTemplate(user, template, (err, templateId) => {
|
2017-12-29 23:15:48 +08:00
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
2017-12-29 22:04:44 +08:00
|
|
|
|
2018-05-09 21:00:18 +08:00
|
|
|
res.statusCode = 200;
|
2018-03-13 20:31:49 +08:00
|
|
|
res.body = { template_id: templateId };
|
2017-12-29 22:04:44 +08:00
|
|
|
|
2018-03-13 20:31:49 +08:00
|
|
|
next();
|
2017-12-29 23:15:48 +08:00
|
|
|
});
|
2018-03-13 20:12:18 +08:00
|
|
|
};
|
|
|
|
}
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2018-03-15 00:31:37 +08:00
|
|
|
function updateTemplate ({ templateMaps }) {
|
2017-12-29 23:15:48 +08:00
|
|
|
return function updateTemplateMiddleware (req, res, next) {
|
2017-12-29 23:30:42 +08:00
|
|
|
const { user } = res.locals;
|
2017-12-29 23:15:48 +08:00
|
|
|
const template = req.body;
|
2017-12-29 23:30:42 +08:00
|
|
|
const templateId = templateName(req.params.template_id);
|
2016-03-11 18:06:51 +08:00
|
|
|
|
2018-03-13 20:12:18 +08:00
|
|
|
templateMaps.updTemplate(user, templateId, template, (err) => {
|
2017-12-29 23:15:48 +08:00
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2018-05-09 21:00:18 +08:00
|
|
|
res.statusCode = 200;
|
2018-03-13 20:31:49 +08:00
|
|
|
res.body = { template_id: templateId };
|
2017-12-29 22:04:44 +08:00
|
|
|
|
2018-03-13 20:31:49 +08:00
|
|
|
next();
|
2017-12-29 23:15:48 +08:00
|
|
|
});
|
2018-03-13 20:12:18 +08:00
|
|
|
};
|
|
|
|
}
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2018-03-15 00:31:37 +08:00
|
|
|
function retrieveTemplate ({ templateMaps }) {
|
2018-01-03 20:15:11 +08:00
|
|
|
return function retrieveTemplateMiddleware (req, res, next) {
|
2017-12-29 23:15:48 +08:00
|
|
|
req.profiler.start('windshaft-cartodb.get_template');
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2017-12-30 01:34:54 +08:00
|
|
|
const { user } = res.locals;
|
2017-12-29 23:30:42 +08:00
|
|
|
const templateId = templateName(req.params.template_id);
|
2017-12-29 22:17:29 +08:00
|
|
|
|
2018-03-13 20:12:18 +08:00
|
|
|
templateMaps.getTemplate(user, templateId, (err, template) => {
|
2017-12-29 23:15:48 +08:00
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
2017-12-29 22:17:29 +08:00
|
|
|
|
2017-12-29 23:30:42 +08:00
|
|
|
if (!template) {
|
2017-12-30 01:34:54 +08:00
|
|
|
const error = new Error(`Cannot find template '${templateId}' of user '${user}'`);
|
2017-12-29 23:15:48 +08:00
|
|
|
error.http_status = 404;
|
|
|
|
return next(error);
|
|
|
|
}
|
|
|
|
// auth_id was added by ourselves,
|
|
|
|
// so we remove it before returning to the user
|
2017-12-29 23:30:42 +08:00
|
|
|
delete template.auth_id;
|
2017-12-29 22:17:29 +08:00
|
|
|
|
2018-05-09 21:00:18 +08:00
|
|
|
res.statusCode = 200;
|
2018-03-13 20:31:49 +08:00
|
|
|
res.body = { template };
|
2017-12-29 22:17:29 +08:00
|
|
|
|
2018-03-13 20:31:49 +08:00
|
|
|
next();
|
2017-12-29 23:15:48 +08:00
|
|
|
});
|
2018-03-13 20:12:18 +08:00
|
|
|
};
|
|
|
|
}
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2018-03-15 00:31:37 +08:00
|
|
|
function destroyTemplate ({ templateMaps }) {
|
2017-12-29 23:15:48 +08:00
|
|
|
return function destroyTemplateMiddleware (req, res, next) {
|
|
|
|
req.profiler.start('windshaft-cartodb.delete_template');
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2017-12-29 23:30:42 +08:00
|
|
|
const { user } = res.locals;
|
|
|
|
const templateId = templateName(req.params.template_id);
|
2017-12-29 22:04:44 +08:00
|
|
|
|
2018-03-13 20:12:18 +08:00
|
|
|
templateMaps.delTemplate(user, templateId, (err/* , tpl_val */) => {
|
2017-12-29 23:15:48 +08:00
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
2017-12-29 22:17:29 +08:00
|
|
|
|
2018-03-13 20:31:49 +08:00
|
|
|
res.statusCode = 204;
|
|
|
|
res.body = '';
|
2017-12-29 22:17:29 +08:00
|
|
|
|
2018-03-13 20:31:49 +08:00
|
|
|
next();
|
2017-12-29 23:15:48 +08:00
|
|
|
});
|
2018-03-13 20:12:18 +08:00
|
|
|
};
|
|
|
|
}
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2018-03-15 00:31:37 +08:00
|
|
|
function listTemplates ({ templateMaps }) {
|
2017-12-29 23:15:48 +08:00
|
|
|
return function listTemplatesMiddleware (req, res, next) {
|
|
|
|
req.profiler.start('windshaft-cartodb.get_template_list');
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2017-12-29 23:30:42 +08:00
|
|
|
const { user } = res.locals;
|
2015-07-08 19:11:57 +08:00
|
|
|
|
2018-03-13 20:12:18 +08:00
|
|
|
templateMaps.listTemplates(user, (err, templateIds) => {
|
2017-12-29 23:15:48 +08:00
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
2017-12-29 22:04:44 +08:00
|
|
|
|
2018-05-09 21:00:18 +08:00
|
|
|
res.statusCode = 200;
|
2018-03-13 20:31:49 +08:00
|
|
|
res.body = { template_ids: templateIds };
|
2017-12-29 22:04:44 +08:00
|
|
|
|
2018-03-13 20:31:49 +08:00
|
|
|
next();
|
2017-12-29 23:15:48 +08:00
|
|
|
});
|
2018-03-13 20:12:18 +08:00
|
|
|
};
|
|
|
|
}
|