Added remove route

Signed-off-by: Defman21 <i@defman.me>
This commit is contained in:
Defman21 2016-07-21 23:03:33 +03:00
parent 0209375865
commit eb0f868f75
No known key found for this signature in database
GPG Key ID: AF04C6EC908CFF53
6 changed files with 141 additions and 10 deletions

View File

@ -47,6 +47,20 @@ DocumentHandler.prototype.handleRawGet = function(key, response, skipExpire) {
}, skipExpire);
};
DocumentHandler.prototype.handleDelete = function (key, secret, response) {
this.store.remove(key, secret, function (ret) {
if (ret) {
winston.verbose('removed document', { key: key });
response.writeHead(200, { 'content-type': 'application/json' });
response.end(JSON.stringify({ message: "Removed document " + key }));
} else {
winston.warn('invalid secret or document not found', { key: key, secret: secret });
response.writeHead(404, { 'content-type': 'application/json' });
response.end(JSON.stringify({ message: 'Document not found.' }));
}
});
};
// Handle adding a new Document
DocumentHandler.prototype.handlePost = function (request, response) {
var _this = this;
@ -67,11 +81,11 @@ DocumentHandler.prototype.handlePost = function (request, response) {
}
// And then save if we should
_this.chooseKey(function (key) {
_this.store.set(key, buffer, function (res) {
_this.store.set(key, buffer, function (res, secret) {
if (res) {
winston.verbose('added document', { key: key });
winston.verbose('added document', { key: key, secret: secret });
response.writeHead(200, { 'content-type': 'application/json' });
response.end(JSON.stringify({ key: key }));
response.end(JSON.stringify({ key: key, secret: secret }));
}
else {
winston.verbose('error adding document');

View File

@ -12,6 +12,11 @@ var FileDocumentStore = function(options) {
this.expire = options.expire;
};
// Generate secret (10 chars)
FileDocumentStore.secret = function() {
return Math.random().toString(24).slice(-10);
};
// Generate md5 of a string
FileDocumentStore.md5 = function(str) {
var md5sum = crypto.createHash('md5');
@ -25,13 +30,17 @@ FileDocumentStore.prototype.set = function(key, data, callback, skipExpire) {
try {
var _this = this;
fs.mkdir(this.basePath, '700', function() {
var sc = FileDocumentStore.secret();
var fn = _this.basePath + '/' + FileDocumentStore.md5(key);
var sfn = fn + "-" + sc;
fs.writeFile(fn, data, 'utf8', function(err) {
if (err) {
callback(false);
}
else {
callback(true);
fs.writeFile(sfn, "A validation file for " + fn, 'utf8', function (err) {
if (!err) callback(true, sc);
});
if (_this.expire && !skipExpire) {
winston.warn('file store cannot set expirations on keys');
}
@ -43,6 +52,27 @@ FileDocumentStore.prototype.set = function(key, data, callback, skipExpire) {
}
};
FileDocumentStore.prototype.remove = function(str, key, callback) {
var file = FileDocumentStore.md5(str);
var kfn = key;
fs.exists(this.basePath + "/" + file + "-" + kfn, function(exists) {
if (exists) {
try {
fs.unlink(this.basePath + "/" + file, function() {
fs.unlink(this.basePath + "/" + file + "-" + kfn, function() {
callback(true);
});
});
} catch(err) {
callback(false);
}
}
else {
callback(false);
}
});
};
// Get data from a file from key
FileDocumentStore.prototype.get = function(key, callback, skipExpire) {
var _this = this;

View File

@ -8,7 +8,9 @@ var MemcachedDocumentStore = function(options) {
MemcachedDocumentStore.connect(options);
}
};
MemcachedDocumentStore.secret = function() {
return Math.random().toString(24).slice(-10);
};
// Create a connection
MemcachedDocumentStore.connect = function(options) {
var host = options.host || '127.0.0.1';
@ -27,7 +29,17 @@ MemcachedDocumentStore.connect = function(options) {
MemcachedDocumentStore.prototype.set =
function(key, data, callback, skipExpire) {
MemcachedDocumentStore.client.set(key, data, function(err, reply) {
err ? callback(false) : callback(true);
if (!err) {
var sc = MemcachedDocumentStore.secret();
MemcachedDocumentStore.client.set(key + "-" + sc, "", function(err, reply) {
if (!err) {
callback(true, sc);
}
});
}
else {
callback(false);
}
}, skipExpire ? 0 : this.expire);
};
@ -42,4 +54,21 @@ MemcachedDocumentStore.prototype.get = function(key, callback, skipExpire) {
});
};
MemcachedDocumentStore.prototype.remove = function(key, secret, callback) {
MemcachedDocumentStore.client.get(key + "-" + secret, function(err, reply) {
if (!err) {
MemcachedDocumentStore.client.del(key, function(err, reply) {
if (err) return callback(false);
MemcachedDocumentStore.client.del(key + "-" + secret, function(err, reply) {
if (err) return callback(false);
callback(reply);
});
});
}
else {
callback(false);
}
});
};
module.exports = MemcachedDocumentStore;

View File

@ -9,6 +9,7 @@ var winston = require('winston');
var PostgresDocumentStore = function (options) {
this.expireJS = options.expire;
this.connectionUrl = process.env.DATABASE_URL || options.connectionUrl;
this.secret = () => Math.random().toString(24).slice(-10);
};
PostgresDocumentStore.prototype = {
@ -19,16 +20,18 @@ PostgresDocumentStore.prototype = {
var that = this;
this.safeConnect(function (err, client, done) {
if (err) { return callback(false); }
client.query('INSERT INTO entries (key, value, expiration) VALUES ($1, $2, $3)', [
var sc = that.secret();
client.query('INSERT INTO entries (key, value, expiration, secret) VALUES ($1, $2, $3, $4)', [
key,
data,
that.expireJS && !skipExpire ? that.expireJS + now : null
that.expireJS && !skipExpire ? that.expireJS + now : null,
sc
], function (err, result) {
if (err) {
winston.error('error persisting value to postgres', { error: err });
return callback(false);
}
callback(true);
callback(true, sc);
done();
});
});
@ -62,6 +65,32 @@ PostgresDocumentStore.prototype = {
});
},
remove: function (key, secret, callback) {
var now = Math.floor(new Date().getTime() / 1000);
this.safeConnect(function (err, client, done) {
if (err) { return callback(false); }
client.query('SELECT id,value,expiration,secret from entries where KEY = $1 and (expiration IS NULL or expiration > $2)', [key, now], function (err, result) {
if (err) {
winston.error('error retrieving value from postgres', { error: err });
return callback(false);
}
if (result.rows[0].secret == secret) {
client.query("DELETE FROM entries where KEY = $1", [key], function (err, result) {
if (err) {
winston.error('error removing an item from postgres', { error: err });
return callback(false);
}
else {
callback(true);
done();
}
});
}
done();
});
});
},
// A connection wrapper
safeConnect: function (callback) {
postgres.connect(this.connectionUrl, function (err, client, done) {

View File

@ -43,6 +43,11 @@ RedisDocumentStore.connect = function(options) {
});
};
// Generate secret (10 chars)
RedisDocumentStore.secret = function() {
return Math.random().toString(24).slice(-10);
};
// Save file in a key
RedisDocumentStore.prototype.set = function(key, data, callback, skipExpire) {
var _this = this;
@ -54,7 +59,11 @@ RedisDocumentStore.prototype.set = function(key, data, callback, skipExpire) {
if (!skipExpire) {
_this.setExpiration(key);
}
callback(true);
var sc = RedisDocumentStore.secret();
RedisDocumentStore.client.set(key + '-' + sc, "", function(err, reply) {
if (err) return callback(false);
callback(true, sc);
});
}
});
};
@ -81,4 +90,21 @@ RedisDocumentStore.prototype.get = function(key, callback, skipExpire) {
});
};
RedisDocumentStore.prototype.remove = function(key, secret, callback) {
RedisDocumentStore.client.get(key + "-" + secret, function(err, reply) {
if (!err) {
RedisDocumentStore.client.del(key, function(err, reply) {
if (err) return callback(false);
RedisDocumentStore.client.del(key + "-" + secret, function(err, reply) {
if (err) return callback(false);
callback(reply);
});
});
}
else {
callback(false);
}
});
};
module.exports = RedisDocumentStore;

View File

@ -131,6 +131,9 @@ app.use(route(function(router) {
skipExpire
);
});
router.get('/documents/:id/remove/:secret', function(request, response, next) {
return documentHandler.handleDelete(request.params.id, request.params.secret, response);
});
}));
// Otherwise, try to match static files