From b3df1dd7a653909fb3f18ed7c0c91ffa347480fb Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Thu, 7 Jan 2021 21:36:56 +0200 Subject: feat: change mutation timestamp on every database mutation --- src/api/routes/admin/statsGET.js | 34 ------------------------------- src/api/routes/admin/userDemote.js | 3 ++- src/api/routes/admin/userDisable.js | 3 ++- src/api/routes/admin/userEnable.js | 3 ++- src/api/routes/albums/albumDELETE.js | 3 ++- src/api/routes/albums/albumPOST.js | 2 +- src/api/routes/albums/albumPurgeDELETE.js | 3 ++- src/api/routes/albums/albumZipGET.js | 3 ++- src/api/routes/albums/link/linkPOST.js | 2 +- src/api/routes/auth/registerPOST.js | 2 +- src/api/routes/files/albumAddPOST.js | 2 +- src/api/routes/files/albumDelPOST.js | 3 ++- src/api/routes/files/tagAddBatchPOST.js | 2 +- src/api/routes/files/tagAddPOST.js | 2 +- src/api/routes/files/tagDelPOST.js | 3 ++- src/api/routes/service/statsGET.js | 34 +++++++++++++++++++++++++++++++ src/api/routes/tags/tagDELETE.js | 3 ++- src/api/routes/tags/tagPOST.js | 2 +- src/api/structures/Database.js | 10 ++++++++- src/api/utils/Util.js | 9 ++++---- 20 files changed, 73 insertions(+), 55 deletions(-) delete mode 100644 src/api/routes/admin/statsGET.js create mode 100644 src/api/routes/service/statsGET.js (limited to 'src/api') diff --git a/src/api/routes/admin/statsGET.js b/src/api/routes/admin/statsGET.js deleted file mode 100644 index 388d4fa..0000000 --- a/src/api/routes/admin/statsGET.js +++ /dev/null @@ -1,34 +0,0 @@ -const Route = require('../../structures/Route'); -const StatsGenerator = require('../../utils/StatsGenerator'); - -// Thank you Bobby for the stats code https://github.com/BobbyWibowo/lolisafe/blob/safe.fiery.me/controllers/utilsController.js -class filesGET extends Route { - constructor() { - super('/admin/stats', 'get', { adminOnly: true }); - } - - async run(req, res, db) { - const cachedStats = await db('statistics') - .select('type', 'data', 'batchId') - .where('batchId', '=', db('statistics').max('batchId')); - - let stats = cachedStats.reduce((acc, { type, data }) => { - try { - acc[type] = JSON.parse(data); - } catch (e) { - console.error(e); - } - - return acc; - }, {}); - - stats = { ...stats, ...(await StatsGenerator.getMissingStats(db, Object.keys(stats))) }; - - return res.json(StatsGenerator.keyOrder.reduce((acc, k) => { - acc[k] = stats[k]; - return acc; - }, {})); - } -} - -module.exports = filesGET; diff --git a/src/api/routes/admin/userDemote.js b/src/api/routes/admin/userDemote.js index b430a48..6611d9f 100644 --- a/src/api/routes/admin/userDemote.js +++ b/src/api/routes/admin/userDemote.js @@ -14,7 +14,8 @@ class userDemote extends Route { try { await db.table('users') .where({ id }) - .update({ isAdmin: false }); + .update({ isAdmin: false }) + .wasMutated(); } catch (error) { return super.error(res, error); } diff --git a/src/api/routes/admin/userDisable.js b/src/api/routes/admin/userDisable.js index e39c811..a3dbb15 100644 --- a/src/api/routes/admin/userDisable.js +++ b/src/api/routes/admin/userDisable.js @@ -14,7 +14,8 @@ class userDisable extends Route { try { await db.table('users') .where({ id }) - .update({ enabled: false }); + .update({ enabled: false }) + .wasMutated(); } catch (error) { return super.error(res, error); } diff --git a/src/api/routes/admin/userEnable.js b/src/api/routes/admin/userEnable.js index cff622f..47a9dcb 100644 --- a/src/api/routes/admin/userEnable.js +++ b/src/api/routes/admin/userEnable.js @@ -14,7 +14,8 @@ class userEnable extends Route { try { await db.table('users') .where({ id }) - .update({ enabled: true }); + .update({ enabled: true }) + .wasMutated(); } catch (error) { return super.error(res, error); } diff --git a/src/api/routes/albums/albumDELETE.js b/src/api/routes/albums/albumDELETE.js index f9c22e6..8fd79ca 100644 --- a/src/api/routes/albums/albumDELETE.js +++ b/src/api/routes/albums/albumDELETE.js @@ -26,7 +26,8 @@ class albumDELETE extends Route { await db.table('albumsLinks').where({ albumId: id }).delete(); // Delete any album links created for this album - await db.table('links').where({ albumId: id }).delete(); + await db.table('links').where({ albumId: id }).delete() + .wasMutated(); return res.json({ message: 'The album was deleted successfully' }); } catch (error) { diff --git a/src/api/routes/albums/albumPOST.js b/src/api/routes/albums/albumPOST.js index 52352a1..ec94eb8 100644 --- a/src/api/routes/albums/albumPOST.js +++ b/src/api/routes/albums/albumPOST.js @@ -28,7 +28,7 @@ class albumPOST extends Route { editedAt: now }; - const dbRes = await db.table('albums').insert(insertObj); + const dbRes = await db.table('albums').insert(insertObj).wasMutated(); insertObj.id = dbRes.pop(); diff --git a/src/api/routes/albums/albumPurgeDELETE.js b/src/api/routes/albums/albumPurgeDELETE.js index a63eafc..ff48c33 100644 --- a/src/api/routes/albums/albumPurgeDELETE.js +++ b/src/api/routes/albums/albumPurgeDELETE.js @@ -18,7 +18,8 @@ class albumDELETE extends Route { try { await Util.deleteAllFilesFromAlbum(id); - await db.table('albums').where({ id }).delete(); + await db.table('albums').where({ id }).delete() + .wasMutated(); return res.json({ message: 'The album was deleted successfully' }); } catch (error) { return super.error(res, error); diff --git a/src/api/routes/albums/albumZipGET.js b/src/api/routes/albums/albumZipGET.js index c560cff..22b0b6f 100644 --- a/src/api/routes/albums/albumZipGET.js +++ b/src/api/routes/albums/albumZipGET.js @@ -74,7 +74,8 @@ class albumGET extends Route { Util.createZip(filesToZip, album); await db.table('albums') .where('id', link.albumId) - .update('zippedAt', db.fn.now()); + .update('zippedAt', db.fn.now()) + .wasMutated(); const filePath = path.join(__dirname, '../../../../', process.env.UPLOAD_FOLDER, 'zips', `${album.userId}-${album.id}.zip`); const fileName = `${process.env.SERVICE_NAME}-${identifier}.zip`; diff --git a/src/api/routes/albums/link/linkPOST.js b/src/api/routes/albums/link/linkPOST.js index 28e9dfe..42eac58 100644 --- a/src/api/routes/albums/link/linkPOST.js +++ b/src/api/routes/albums/link/linkPOST.js @@ -63,7 +63,7 @@ class linkPOST extends Route { expiresAt: null, views: 0 }; - await db.table('links').insert(insertObj); + await db.table('links').insert(insertObj).wasMutated(); return res.json({ message: 'The link was created successfully', diff --git a/src/api/routes/auth/registerPOST.js b/src/api/routes/auth/registerPOST.js index 54e683e..7b9eb3c 100644 --- a/src/api/routes/auth/registerPOST.js +++ b/src/api/routes/auth/registerPOST.js @@ -55,7 +55,7 @@ class registerPOST extends Route { editedAt: now, enabled: true, isAdmin: false - }); + }).wasMutated(); return res.json({ message: 'The account was created successfully' }); } } diff --git a/src/api/routes/files/albumAddPOST.js b/src/api/routes/files/albumAddPOST.js index 7b8acf7..645a6be 100644 --- a/src/api/routes/files/albumAddPOST.js +++ b/src/api/routes/files/albumAddPOST.js @@ -18,7 +18,7 @@ class albumAddPOST extends Route { try { await db.table('albumsFiles') - .insert({ fileId, albumId }); + .insert({ fileId, albumId }).wasMutated(); } catch (error) { return super.error(res, error); } diff --git a/src/api/routes/files/albumDelPOST.js b/src/api/routes/files/albumDelPOST.js index 8304163..63da791 100644 --- a/src/api/routes/files/albumDelPOST.js +++ b/src/api/routes/files/albumDelPOST.js @@ -19,7 +19,8 @@ class albumDelPOST extends Route { try { await db.table('albumsFiles') .where({ fileId, albumId }) - .delete(); + .delete() + .wasMutated(); } catch (error) { return super.error(res, error); } diff --git a/src/api/routes/files/tagAddBatchPOST.js b/src/api/routes/files/tagAddBatchPOST.js index 679945d..de41d8f 100644 --- a/src/api/routes/files/tagAddBatchPOST.js +++ b/src/api/routes/files/tagAddBatchPOST.js @@ -20,7 +20,7 @@ class tagAddBatchPOST extends Route { try { const tag = await db.table('tags').where({ name: tagName, userId: user.id }).first(); if (!tag) throw new Error('Tag doesn\'t exist in the database'); - await db.table('fileTags').insert({ fileId, tagId: tag.id }); + await db.table('fileTags').insert({ fileId, tagId: tag.id }).wasMutated(); addedTags.push(tag); } catch (e) { diff --git a/src/api/routes/files/tagAddPOST.js b/src/api/routes/files/tagAddPOST.js index 2bbfa07..0a0ab42 100644 --- a/src/api/routes/files/tagAddPOST.js +++ b/src/api/routes/files/tagAddPOST.js @@ -20,7 +20,7 @@ class tagAddPOST extends Route { if (!tag) return res.status(400).json({ message: 'Tag doesn\'t exist. ' }); try { - await db.table('fileTags').insert({ fileId, tagId: tag.id }); + await db.table('fileTags').insert({ fileId, tagId: tag.id }).wasMutated(); } catch (error) { return super.error(res, error); } diff --git a/src/api/routes/files/tagDelPOST.js b/src/api/routes/files/tagDelPOST.js index ac0bfe4..78e461b 100644 --- a/src/api/routes/files/tagDelPOST.js +++ b/src/api/routes/files/tagDelPOST.js @@ -22,7 +22,8 @@ class tagDelPost extends Route { try { await db.table('fileTags') .where({ fileId, tagId: tag.id }) - .delete(); + .delete() + .wasMutated(); } catch (error) { return super.error(res, error); } diff --git a/src/api/routes/service/statsGET.js b/src/api/routes/service/statsGET.js new file mode 100644 index 0000000..d6fa69e --- /dev/null +++ b/src/api/routes/service/statsGET.js @@ -0,0 +1,34 @@ +const Route = require('../../structures/Route'); +const StatsGenerator = require('../../utils/StatsGenerator'); + +// Thank you Bobby for the stats code https://github.com/BobbyWibowo/lolisafe/blob/safe.fiery.me/controllers/utilsController.js +class filesGET extends Route { + constructor() { + super('/service/statistics', 'get', { adminOnly: true }); + } + + async run(req, res, db) { + const cachedStats = await db('statistics') + .select('type', 'data', 'batchId') + .where('batchId', '=', db('statistics').max('batchId')); + + let stats = cachedStats.reduce((acc, { type, data }) => { + try { + acc[type] = JSON.parse(data); + } catch (e) { + console.error(e); + } + + return acc; + }, {}); + + stats = { ...stats, ...(await StatsGenerator.getMissingStats(db, Object.keys(stats))) }; + + return res.json(StatsGenerator.keyOrder.reduce((acc, k) => { + acc[k] = stats[k]; + return acc; + }, {})); + } +} + +module.exports = filesGET; diff --git a/src/api/routes/tags/tagDELETE.js b/src/api/routes/tags/tagDELETE.js index cf74029..733fabf 100644 --- a/src/api/routes/tags/tagDELETE.js +++ b/src/api/routes/tags/tagDELETE.js @@ -26,7 +26,8 @@ class tagDELETE extends Route { /* Delete the tag */ - await db.table('tags').where({ id }).delete(); + await db.table('tags').where({ id }).delete() + .wasMutated(); return res.json({ message: 'The tag was deleted successfully', data: tag }); } catch (error) { return super.error(res, error); diff --git a/src/api/routes/tags/tagPOST.js b/src/api/routes/tags/tagPOST.js index 89b296d..5430de9 100644 --- a/src/api/routes/tags/tagPOST.js +++ b/src/api/routes/tags/tagPOST.js @@ -25,7 +25,7 @@ class tagPOST extends Route { editedAt: now }; - const dbRes = await db.table('tags').insert(insertObj); + const dbRes = await db.table('tags').insert(insertObj).wasMutated(); insertObj.id = dbRes.pop(); diff --git a/src/api/structures/Database.js b/src/api/structures/Database.js index 3b256d3..5818452 100644 --- a/src/api/structures/Database.js +++ b/src/api/structures/Database.js @@ -1,5 +1,13 @@ const nodePath = require('path'); -const db = require('knex')({ +const Knex = require('knex'); + +// eslint-disable-next-line func-names +Knex.QueryBuilder.extend('wasMutated', function() { + this.client.config.userParams.lastMutationTime = Date.now(); + return this; +}); + +const db = Knex({ client: process.env.DB_CLIENT, connection: { host: process.env.DB_HOST, diff --git a/src/api/utils/Util.js b/src/api/utils/Util.js index 8eafcff..658ac61 100644 --- a/src/api/utils/Util.js +++ b/src/api/utils/Util.js @@ -99,7 +99,8 @@ class Util { await db .table('files') .where('name', filename) - .delete(); + .delete() + .wasMutated(); } } catch (error) { log.error(`There was an error removing the file < ${filename} >`); @@ -257,9 +258,9 @@ class Util { let fileId; if (process.env.DB_CLIENT === 'sqlite3') { - fileId = await db.table('files').insert(data); + fileId = await db.table('files').insert(data).wasMutated(); } else { - fileId = await db.table('files').insert(data, 'id'); + fileId = await db.table('files').insert(data, 'id').wasMutated(); } return { @@ -273,7 +274,7 @@ class Util { const now = moment.utc().toDate(); try { - await db.table('albumsFiles').insert({ albumId, fileId: insertedId[0] }); + await db.table('albumsFiles').insert({ albumId, fileId: insertedId[0] }).wasMutated(); await db.table('albums').where('id', albumId).update('editedAt', now); } catch (error) { console.error(error); -- cgit v1.2.3