From f606a7825f1e3746669e39d0b9b2307c7541d8a4 Mon Sep 17 00:00:00 2001 From: David Mehren Date: Sun, 6 Nov 2022 21:50:08 +0100 Subject: [PATCH] refactor(migrations): move cleanup code into migration We cannot execute the cleanup script as a subprocess with sqlite, as we now wrap the migrations in a SAVEPOINT, which blocks a second process. This moves the cleanup code into the migration file, so it can be executed in-process. Signed-off-by: David Mehren --- bin/cleanup | 103 +-------------- .../20200321153000-fix-account-deletion.js | 123 ++++++++++++++++-- 2 files changed, 112 insertions(+), 114 deletions(-) diff --git a/bin/cleanup b/bin/cleanup index edf72bf20..3683269c3 100755 --- a/bin/cleanup +++ b/bin/cleanup @@ -1,104 +1,7 @@ #!/usr/bin/env node -const logger = require('../lib/logger') -const models = require('../lib/models') +const cleanup = require('../lib/migrations/20200321153000-fix-account-deletion').cleanup -logger.info('Cleaning up notes that should already have been removed. Sorry.') - -async function cleanup () { - await models.Note.findAll({ - include: [{ - model: models.User, - as: 'owner', - attributes: ['id'] - }], - attributes: ['id', 'ownerId'] - }).then(async function (notes) { - for (let i = 0, noteCount = notes.length; i < noteCount; i++) { - const item = notes[i] - if (item.ownerId != null && !item.owner) { - await models.Note.destroy({ - where: { - id: item.id - } - }) - await models.Revision.destroy({ - where: { - noteId: item.id - } - }) - await models.Author.destroy({ - where: { - noteId: item.id - } - }) - logger.info(`Deleted note ${item.id} from user ${item.ownerId}`) - } - } - }) - await models.Author.findAll({ - include: [{ - model: models.User, - as: 'user', - attributes: ['id'] - }], - attributes: ['id', 'userId'] - }).then(async function (authors) { - for (let i = 0, authorCount = authors.length; i < authorCount; i++) { - const item = authors[i] - if (item.userId != null && !item.user) { - await models.Author.destroy({ - where: { - id: item.id - } - }) - logger.info(`Deleted authorship ${item.id} from user ${item.userId}`) - } - } - }) - - await models.Author.findAll({ - include: [{ - model: models.Note, - as: 'note', - attributes: ['id'] - }], - attributes: ['id', 'noteId'] - }).then(async function (authors) { - for (let i = 0, authorCount = authors.length; i < authorCount; i++) { - const item = authors[i] - if (item.noteId != null && !item.note) { - await models.Author.destroy({ - where: { - id: item.id - } - }) - logger.info(`Deleted authorship ${item.id} from note ${item.noteId}`) - } - } - }) - - await models.Revision.findAll({ - include: [{ - model: models.Note, - as: 'note', - attributes: ['id'] - }], - attributes: ['id', 'noteId'] - }).then(async function (revisions) { - for (let i = 0, revisionCount = revisions.length; i < revisionCount; i++) { - const item = revisions[i] - if (item.noteId != null && !item.note) { - await models.Revision.destroy({ - where: { - id: item.id - } - }) - logger.info(`Deleted revision ${item.id} from note ${item.userId}`) - } - } - }) +cleanup().then(() => { process.exit(0) -} - -cleanup() +}) diff --git a/lib/migrations/20200321153000-fix-account-deletion.js b/lib/migrations/20200321153000-fix-account-deletion.js index 6e51f04cf..d1296a085 100644 --- a/lib/migrations/20200321153000-fix-account-deletion.js +++ b/lib/migrations/20200321153000-fix-account-deletion.js @@ -1,20 +1,115 @@ 'use strict' -const { spawnSync } = require('child_process') -const path = require('path') + +const logger = require('../../lib/logger') +const models = require('../../lib/models') + module.exports = { + cleanup: async function () { + logger.info('Cleaning up notes that should already have been removed. Sorry.') + await models.Note.findAll({ + include: [{ + model: models.User, + as: 'owner', + attributes: ['id'] + }], + attributes: ['id', 'ownerId'] + }).then(async function (notes) { + for (let i = 0, noteCount = notes.length; i < noteCount; i++) { + const item = notes[i] + if (item.ownerId != null && !item.owner) { + await models.Note.destroy({ + where: { + id: item.id + } + }) + await models.Revision.destroy({ + where: { + noteId: item.id + } + }) + await models.Author.destroy({ + where: { + noteId: item.id + } + }) + logger.info(`Deleted note ${item.id} from user ${item.ownerId}`) + } + } + }) + await models.Author.findAll({ + include: [{ + model: models.User, + as: 'user', + attributes: ['id'] + }], + attributes: ['id', 'userId'] + }).then(async function (authors) { + for (let i = 0, authorCount = authors.length; i < authorCount; i++) { + const item = authors[i] + if (item.userId != null && !item.user) { + await models.Author.destroy({ + where: { + id: item.id + } + }) + logger.info(`Deleted authorship ${item.id} from user ${item.userId}`) + } + } + }) + + await models.Author.findAll({ + include: [{ + model: models.Note, + as: 'note', + attributes: ['id'] + }], + attributes: ['id', 'noteId'] + }).then(async function (authors) { + for (let i = 0, authorCount = authors.length; i < authorCount; i++) { + const item = authors[i] + if (item.noteId != null && !item.note) { + await models.Author.destroy({ + where: { + id: item.id + } + }) + logger.info(`Deleted authorship ${item.id} from note ${item.noteId}`) + } + } + }) + + await models.Revision.findAll({ + include: [{ + model: models.Note, + as: 'note', + attributes: ['id'] + }], + attributes: ['id', 'noteId'] + }).then(async function (revisions) { + for (let i = 0, revisionCount = revisions.length; i < revisionCount; i++) { + const item = revisions[i] + if (item.noteId != null && !item.note) { + await models.Revision.destroy({ + where: { + id: item.id + } + }) + logger.info(`Deleted revision ${item.id} from note ${item.userId}`) + } + } + }) + }, up: function (queryInterface, Sequelize) { - const cleanup = spawnSync(process.argv[0], ['./bin/cleanup'], { cwd: path.resolve(__dirname, '../../') }) - if (cleanup.status !== 0) { - throw new Error('Unable to cleanup') - } - return queryInterface.addConstraint('Notes', ['ownerId'], { - type: 'foreign key', - name: 'Notes_owner_fkey', - references: { - table: 'Users', - field: 'id' - }, - onDelete: 'cascade' + return this.cleanup().then(function () { + return queryInterface.addConstraint('Notes', ['ownerId'], { + type: 'foreign key', + name: 'Notes_owner_fkey', + references: { + table: 'Users', + field: 'id' + }, + onDelete: 'cascade' + }) }).then(function () { return queryInterface.addConstraint('Revisions', ['noteId'], { type: 'foreign key',