Files
cloudron-box/src/eventlogdb.js

172 lines
6.3 KiB
JavaScript
Raw Normal View History

2016-04-29 23:37:54 -07:00
'use strict';
exports = module.exports = {
get: get,
getAllPaged: getAllPaged,
getByCreationTime: getByCreationTime,
2016-04-29 23:37:54 -07:00
add: add,
upsert: upsert,
2016-04-29 23:37:54 -07:00
count: count,
2016-07-25 12:36:43 -07:00
delByCreationTime: delByCreationTime,
2016-04-29 23:37:54 -07:00
_clear: clear
};
var assert = require('assert'),
async = require('async'),
BoxError = require('./boxerror.js'),
2016-04-29 23:37:54 -07:00
database = require('./database.js'),
mysql = require('mysql'),
2016-07-25 12:36:43 -07:00
safe = require('safetydance'),
util = require('util');
2016-04-29 23:37:54 -07:00
2019-02-05 09:24:16 -08:00
var EVENTLOG_FIELDS = [ 'id', 'action', 'source', 'data', 'creationTime' ].join(',');
2016-04-29 23:37:54 -07:00
function postProcess(eventLog) {
// usually we have sourceJson and dataJson, however since this used to be the JSON data type, we don't
2016-04-30 12:41:27 -07:00
eventLog.source = safe.JSON.parse(eventLog.source);
2016-04-30 09:51:23 -07:00
eventLog.data = safe.JSON.parse(eventLog.data);
2016-04-29 23:37:54 -07:00
return eventLog;
}
function get(eventId, callback) {
assert.strictEqual(typeof eventId, 'string');
assert.strictEqual(typeof callback, 'function');
2019-02-05 09:24:16 -08:00
database.query('SELECT ' + EVENTLOG_FIELDS + ' FROM eventlog WHERE id = ?', [ eventId ], function (error, result) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
if (result.length === 0) return callback(new BoxError(BoxError.NOT_FOUND));
2016-04-29 23:37:54 -07:00
callback(null, postProcess(result[0]));
});
}
function getAllPaged(actions, search, page, perPage, callback) {
assert(Array.isArray(actions));
assert(typeof search === 'string' || search === null);
assert.strictEqual(typeof page, 'number');
assert.strictEqual(typeof perPage, 'number');
assert.strictEqual(typeof callback, 'function');
var data = [];
2019-02-05 09:24:16 -08:00
var query = 'SELECT ' + EVENTLOG_FIELDS + ' FROM eventlog';
if (actions.length || search) query += ' WHERE';
2016-11-28 16:02:18 +01:00
if (search) query += ' (source LIKE ' + mysql.escape('%' + search + '%') + ' OR data LIKE ' + mysql.escape('%' + search + '%') + ')';
if (actions.length && search) query += ' AND ( ';
actions.forEach(function (action, i) {
query += ' (action LIKE ' + mysql.escape(`%${action}%`) + ') ';
if (i < actions.length-1) query += ' OR ';
});
if (actions.length && search) query += ' ) ';
query += ' ORDER BY creationTime DESC LIMIT ?,?';
data.push((page-1)*perPage);
data.push(perPage);
database.query(query, data, function (error, results) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2017-07-21 16:13:44 +02:00
results.forEach(postProcess);
callback(null, results);
});
}
function getByCreationTime(creationTime, callback) {
assert(util.isDate(creationTime));
2017-07-21 16:13:44 +02:00
assert.strictEqual(typeof callback, 'function');
2019-02-05 09:24:16 -08:00
var query = 'SELECT ' + EVENTLOG_FIELDS + ' FROM eventlog WHERE creationTime >= ? ORDER BY creationTime DESC';
database.query(query, [ creationTime ], function (error, results) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
results.forEach(postProcess);
callback(null, results);
});
}
2016-04-30 12:41:27 -07:00
function add(id, action, source, data, callback) {
2016-04-29 23:37:54 -07:00
assert.strictEqual(typeof id, 'string');
assert.strictEqual(typeof action, 'string');
2016-04-30 12:41:27 -07:00
assert.strictEqual(typeof source, 'object');
2016-04-29 23:37:54 -07:00
assert.strictEqual(typeof data, 'object');
assert.strictEqual(typeof callback, 'function');
2016-04-30 12:41:27 -07:00
database.query('INSERT INTO eventlog (id, action, source, data) VALUES (?, ?, ?, ?)', [ id, action, JSON.stringify(source), JSON.stringify(data) ], function (error, result) {
if (error && error.code === 'ER_DUP_ENTRY') return callback(new BoxError(BoxError.ALREADY_EXISTS, error));
if (error || result.affectedRows !== 1) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2016-04-29 23:37:54 -07:00
callback(null, id);
});
}
// id is only used if we didn't do an update but insert instead
function upsert(id, action, source, data, callback) {
assert.strictEqual(typeof id, 'string');
assert.strictEqual(typeof action, 'string');
assert.strictEqual(typeof source, 'object');
assert.strictEqual(typeof data, 'object');
assert.strictEqual(typeof callback, 'function');
// can't do a real sql upsert, for frequent eventlog entries we only have to do 2 queries once a day
var queries = [{
query: 'UPDATE eventlog SET creationTime=NOW(), data=? WHERE action = ? AND source LIKE ? AND DATE(creationTime)=CURDATE()',
args: [ JSON.stringify(data), action, JSON.stringify(source) ]
}, {
2019-02-05 09:24:16 -08:00
query: 'SELECT ' + EVENTLOG_FIELDS + ' FROM eventlog WHERE action = ? AND source LIKE ? AND DATE(creationTime)=CURDATE()',
args: [ action, JSON.stringify(source) ]
}];
database.transaction(queries, function (error, result) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
if (result[0].affectedRows >= 1) return callback(null, result[1][0].id);
// no existing eventlog found, create one
add(id, action, source, data, callback);
2016-04-29 23:37:54 -07:00
});
}
function count(callback) {
assert.strictEqual(typeof callback, 'function');
database.query('SELECT COUNT(*) AS total FROM eventlog', function (error, result) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2016-04-29 23:37:54 -07:00
return callback(null, result[0].total);
});
}
function clear(callback) {
database.query('DELETE FROM eventlog', function (error) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2016-04-29 23:37:54 -07:00
2019-03-22 14:26:25 -07:00
callback(null);
2016-04-29 23:37:54 -07:00
});
}
2016-04-30 09:51:23 -07:00
function delByCreationTime(creationTime, callback) {
2016-07-25 12:36:43 -07:00
assert(util.isDate(creationTime));
assert.strictEqual(typeof callback, 'function');
2019-03-22 14:26:25 -07:00
// remove notifications that reference the events as well
database.query('SELECT * FROM eventlog WHERE creationTime <= ?', [ creationTime ], function (error, result) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2016-07-25 12:36:43 -07:00
2019-03-22 14:26:25 -07:00
async.eachSeries(result, function (item, iteratorCallback) {
async.series([
database.query.bind(null, 'DELETE FROM notifications WHERE eventId=?', [ item.id ]),
database.query.bind(null, 'DELETE FROM eventlog WHERE id=?', [ item.id ])
], iteratorCallback);
}, function (error) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2019-03-22 14:26:25 -07:00
callback(null);
});
2016-07-25 12:36:43 -07:00
});
}