Merge pull request #1016 from CartoDB/remove-step-template-maps

Remove step template maps
This commit is contained in:
Daniel G. Aubert 2018-08-02 15:02:59 +02:00 committed by GitHub
commit dfa057d979
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,7 +1,5 @@
var assert = require('assert');
var crypto = require('crypto'); var crypto = require('crypto');
var debug = require('debug')('windshaft:templates'); var debug = require('debug')('windshaft:templates');
var step = require('step');
var _ = require('underscore'); var _ = require('underscore');
var dot = require('dot'); var dot = require('dot');
@ -69,27 +67,19 @@ TemplateMaps.prototype._userTemplateLimit = function() {
* @param callback - function to pass results too. * @param callback - function to pass results too.
*/ */
TemplateMaps.prototype._redisCmd = function(redisFunc, redisArgs, callback) { TemplateMaps.prototype._redisCmd = function(redisFunc, redisArgs, callback) {
var redisClient; this.redis_pool.acquire(this.db_signatures, (err, redisClient) => {
var that = this; if (err) {
var db = that.db_signatures; return callback(err);
}
step( redisClient[redisFunc.toUpperCase()](...redisArgs, (err, data) => {
function getRedisClient() { this.redis_pool.release(this.db_signatures, redisClient);
that.redis_pool.acquire(db, this); if (err) {
}, return callback(err);
function executeQuery(err, data) { }
assert.ifError(err); return callback(null, data);
redisClient = data; });
redisArgs.push(this); });
redisClient[redisFunc.toUpperCase()].apply(redisClient, redisArgs);
},
function releaseRedisClient(err, data) {
if ( ! _.isUndefined(redisClient) ) {
that.redis_pool.release(db, redisClient);
}
callback(err, data);
}
);
}; };
var _reValidNameIdentifier = /^[a-z0-9][0-9a-z_\-]*$/i; var _reValidNameIdentifier = /^[a-z0-9][0-9a-z_\-]*$/i;
@ -184,6 +174,37 @@ function templateDefaults(template) {
}); });
} }
/**
* Checks if the if the user reaches the templetes limit
*
* @param userTemplatesKey user templat key in Redis
* @param owner cartodb username of the template owner
* @param callback returns error if the user reaches the limit
*/
TemplateMaps.prototype._checkUserTemplatesLimit = function(userTemplatesKey, owner, callback) {
const limit = this._userTemplateLimit();
if(!limit) {
return callback();
}
this._redisCmd('HLEN', [userTemplatesKey], (err, numberOfTemplates) => {
if (err) {
return callback(err);
}
if (numberOfTemplates >= limit) {
const limitReachedError = new Error(
`User '${owner}' reached limit on number of templates (${numberOfTemplates}/${limit})`
);
limitReachedError.http_status = 409;
return callback(limitReachedError);
}
return callback();
});
};
//--------------- PUBLIC API ------------------------------------- //--------------- PUBLIC API -------------------------------------
// Add a template // Add a template
@ -199,52 +220,41 @@ function templateDefaults(template) {
// Return template identifier (only valid for given user) // Return template identifier (only valid for given user)
// //
TemplateMaps.prototype.addTemplate = function(owner, template, callback) { TemplateMaps.prototype.addTemplate = function(owner, template, callback) {
var self = this;
template = templateDefaults(template); template = templateDefaults(template);
var invalidError = this._checkInvalidTemplate(template); var invalidError = this._checkInvalidTemplate(template);
if ( invalidError ) { if (invalidError) {
return callback(invalidError); return callback(invalidError);
} }
var templateName = template.name; var userTemplatesKey = this.key_usr_tpl({ owner });
var userTemplatesKey = this.key_usr_tpl({ owner:owner });
var limit = this._userTemplateLimit();
step( this._checkUserTemplatesLimit(userTemplatesKey, owner, err => {
function checkLimit() { if (err) {
if ( ! limit ) { return callback(err);
return 0;
}
self._redisCmd('HLEN', [ userTemplatesKey ], this);
},
function installTemplateIfDoesNotExist(err, numberOfTemplates) {
assert.ifError(err);
if ( limit && numberOfTemplates >= limit ) {
var limitReachedError = new Error("User '" + owner + "' reached limit on number of templates (" +
numberOfTemplates + "/" + limit + ")");
limitReachedError.http_status = 409;
throw limitReachedError;
}
self._redisCmd('HSETNX', [ userTemplatesKey, templateName, JSON.stringify(template) ], this);
},
function validateInstallation(err, wasSet) {
assert.ifError(err);
if ( ! wasSet ) {
throw new Error("Template '" + templateName + "' of user '" + owner + "' already exists");
}
return true;
},
function finish(err) {
if (!err) {
self.emit('add', owner, templateName, template);
}
callback(err, templateName, template);
} }
);
let templateString;
try {
templateString = JSON.stringify(template);
} catch (error) {
return callback(error);
}
this._redisCmd('HSETNX', [userTemplatesKey, template.name, templateString], (err, wasSet) => {
if (err) {
return callback(err);
}
if (!wasSet) {
var templateExistsError = new Error(`Template '${template.name}' of user '${owner}' already exists`);
return callback(templateExistsError);
}
this.emit('add', owner, template.name, template);
return callback(null, template.name, template);
});
});
}; };
// Delete a template // Delete a template
@ -257,26 +267,18 @@ TemplateMaps.prototype.addTemplate = function(owner, template, callback) {
// @param callback function(err) // @param callback function(err)
// //
TemplateMaps.prototype.delTemplate = function(owner, tpl_id, callback) { TemplateMaps.prototype.delTemplate = function(owner, tpl_id, callback) {
var self = this; this._redisCmd('HDEL', [ this.key_usr_tpl({ owner:owner }), tpl_id ], (err, deleted) => {
step( if (err) {
function deleteTemplate() { return callback(err);
self._redisCmd('HDEL', [ self.key_usr_tpl({ owner:owner }), tpl_id ], this);
},
function handleDeletion(err, deleted) {
assert.ifError(err);
if (!deleted) {
throw new Error("Template '" + tpl_id + "' of user '" + owner + "' does not exist");
}
return true;
},
function finish(err) {
if (!err) {
self.emit('delete', owner, tpl_id);
}
callback(err);
} }
);
if (!deleted) {
return callback(new Error(`Template '${tpl_id}' of user '${owner}' does not exist`));
}
this.emit('delete', owner, tpl_id);
return callback();
});
}; };
// Update a template // Update a template
@ -296,56 +298,58 @@ TemplateMaps.prototype.delTemplate = function(owner, tpl_id, callback) {
// @param callback function(err) // @param callback function(err)
// //
TemplateMaps.prototype.updTemplate = function(owner, tpl_id, template, callback) { TemplateMaps.prototype.updTemplate = function(owner, tpl_id, template, callback) {
var self = this;
template = templateDefaults(template); template = templateDefaults(template);
var invalidError = this._checkInvalidTemplate(template); var invalidError = this._checkInvalidTemplate(template);
if (invalidError) {
if ( invalidError ) {
return callback(invalidError); return callback(invalidError);
} }
var templateName = template.name; if (tpl_id !== template.name) {
return callback(new Error(`Cannot update name of a map template ('${tpl_id}' != '${template.name}')`));
if ( tpl_id !== templateName ) {
return callback(new Error("Cannot update name of a map template ('" + tpl_id + "' != '" + templateName + "')"));
} }
var userTemplatesKey = this.key_usr_tpl({ owner:owner }); var userTemplatesKey = this.key_usr_tpl({ owner });
var previousTemplate = null; this._redisCmd('HGET', [userTemplatesKey, tpl_id], (err, beforeUpdateTemplate) => {
if (err) {
return callback(err);
}
step( if (!beforeUpdateTemplate) {
function getExistingTemplate() { return callback(new Error(`Template '${tpl_id}' of user '${owner}' does not exist`));
self._redisCmd('HGET', [ userTemplatesKey, tpl_id ], this); }
},
function updateTemplate(err, _currentTemplate) { let templateString;
assert.ifError(err); try {
if (!_currentTemplate) { templateString = JSON.stringify(template);
throw new Error("Template '" + tpl_id + "' of user '" + owner + "' does not exist"); } catch (error) {
return callback(error);
}
this._redisCmd('HSET', [userTemplatesKey, template.name, templateString], (err, didSetNewField) => {
if (err) {
return callback(err);
} }
previousTemplate = _currentTemplate;
self._redisCmd('HSET', [ userTemplatesKey, templateName, JSON.stringify(template) ], this);
},
function handleTemplateUpdate(err, didSetNewField) {
assert.ifError(err);
if (didSetNewField) { if (didSetNewField) {
debug('New template created on update operation'); debug('New template created on update operation');
} }
return true;
}, let beforeUpdateTemplateObject;
function finish(err) { try {
if (!err) { beforeUpdateTemplateObject = JSON.parse(beforeUpdateTemplate);
if (self.fingerPrint(JSON.parse(previousTemplate)) !== self.fingerPrint(template)) { } catch (error) {
self.emit('update', owner, templateName, template); return callback(error);
}
} }
callback(err, template); if (this.fingerPrint(beforeUpdateTemplateObject) !== this.fingerPrint(template)) {
} this.emit('update', owner, template.name, template);
); }
return callback(null, template);
});
});
}; };
// List user templates // List user templates
@ -370,19 +374,20 @@ TemplateMaps.prototype.listTemplates = function(owner, callback) {
// Return full template definition // Return full template definition
// //
TemplateMaps.prototype.getTemplate = function(owner, tpl_id, callback) { TemplateMaps.prototype.getTemplate = function(owner, tpl_id, callback) {
var self = this; this._redisCmd('HGET', [this.key_usr_tpl({owner:owner}), tpl_id], (err, template) => {
step( if (err) {
function getTemplate() { return callback(err);
self._redisCmd('HGET', [ self.key_usr_tpl({owner:owner}), tpl_id ], this);
},
function parseTemplate(err, tpl_val) {
assert.ifError(err);
return JSON.parse(tpl_val);
},
function finish(err, tpl) {
callback(err, tpl);
} }
);
let templateObject;
try {
templateObject = JSON.parse(template);
} catch (error) {
return callback(error);
}
return callback(null, templateObject);
});
}; };
TemplateMaps.prototype.isAuthorized = function(template, authTokens) { TemplateMaps.prototype.isAuthorized = function(template, authTokens) {