From 85e985d13fe8c84e06c4aeea3c31ee92ef3cef30 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Sun, 8 Jan 2023 17:57:36 +0100 Subject: [PATCH] server: change data structure to track deletion completion --- .../1673201544000-deletion-progress.js | 18 ++++++++++++++++++ packages/backend/src/models/entities/user.ts | 8 ++++---- .../backend/src/models/repositories/user.ts | 2 +- .../remote/activitypub/kernel/delete/actor.ts | 2 +- .../api/endpoints/admin/accounts/delete.ts | 3 ++- .../server/api/endpoints/i/delete-account.ts | 2 +- .../backend/src/services/delete-account.ts | 2 +- 7 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 packages/backend/migration/1673201544000-deletion-progress.js diff --git a/packages/backend/migration/1673201544000-deletion-progress.js b/packages/backend/migration/1673201544000-deletion-progress.js new file mode 100644 index 000000000..90aa5cbf8 --- /dev/null +++ b/packages/backend/migration/1673201544000-deletion-progress.js @@ -0,0 +1,18 @@ +export class deletionProgress1673201544000 { + name = 'deletionProgress1673201544000'; + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "user" RENAME COLUMN "isDeleted" TO "isDeletedOld"`); + await queryRunner.query(`ALTER TABLE "user" ADD "isDeleted" integer`); + await queryRunner.query(`UPDATE "user" SET "isDeleted" = CASE WHEN "host" IS NULL THEN -1 ELSE 0 END WHERE "isDeletedOld"`); + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "isDeletedOld"`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "user" RENAME COLUMN "isDeleted" TO "isDeletedOld"`); + await queryRunner.query(`ALTER TABLE "user" ADD "isDeleted" boolean NOT NULL DEFAULT false`); + await queryRunner.query(`UPDATE "user" SET "isDeleted" = "isDeletedOld" IS NOT NULL`); + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "isDeletedOld"`); + } +} + diff --git a/packages/backend/src/models/entities/user.ts b/packages/backend/src/models/entities/user.ts index 0aee4c90b..374928fe1 100644 --- a/packages/backend/src/models/entities/user.ts +++ b/packages/backend/src/models/entities/user.ts @@ -163,11 +163,11 @@ export class User { // Indicates the user was deleted by an admin. // The users' data is not deleted from the database to keep them from reappearing. // A hard delete of the record may follow if we receive a matching Delete activity. - @Column('boolean', { - default: false, - comment: 'Whether the User is deleted.', + @Column('integer', { + nullable: true, + comment: 'How many delivery jobs are outstanding before the deletion is completed.', }) - public isDeleted: boolean; + public isDeleted: number | null; @Column('varchar', { length: 128, array: true, default: '{}', diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index fd308dcae..397ee2105 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -369,7 +369,7 @@ export const UserRepository = db.getRepository(User).extend({ autoAcceptFollowed: profile!.autoAcceptFollowed, noCrawle: profile!.noCrawle, isExplorable: user.isExplorable, - isDeleted: user.isDeleted, + isDeleted: user.isDeleted != null, hideOnlineStatus: user.hideOnlineStatus, hasUnreadSpecifiedNotes: NoteUnreads.count({ where: { userId: user.id, isSpecified: true }, diff --git a/packages/backend/src/remote/activitypub/kernel/delete/actor.ts b/packages/backend/src/remote/activitypub/kernel/delete/actor.ts index ea75a9739..f69d87d2c 100644 --- a/packages/backend/src/remote/activitypub/kernel/delete/actor.ts +++ b/packages/backend/src/remote/activitypub/kernel/delete/actor.ts @@ -16,7 +16,7 @@ export async function deleteActor(actor: CacheableRemoteUser, uri: string): Prom // anyway, the user is gone now so dont care return 'ok: gone'; } - if (user.isDeleted) { + if (user.isDeleted != null) { // the actual deletion already happened by an admin, just delete the record await Users.delete(actor.id); } else { diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts index 4f5ea5568..88065f81f 100644 --- a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts @@ -1,3 +1,4 @@ +import { IsNull } from 'typeorm'; import { Users } from '@/models/index.js'; import { ApiError } from '@/server/api/error.js'; import { deleteAccount } from '@/services/delete-account.js'; @@ -24,7 +25,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps) => { const user = await Users.findOneBy({ id: ps.userId, - isDeleted: false, + isDeleted: IsNull(), }); if (user == null) { diff --git a/packages/backend/src/server/api/endpoints/i/delete-account.ts b/packages/backend/src/server/api/endpoints/i/delete-account.ts index 5dae620ae..a77afc8be 100644 --- a/packages/backend/src/server/api/endpoints/i/delete-account.ts +++ b/packages/backend/src/server/api/endpoints/i/delete-account.ts @@ -27,7 +27,7 @@ export default define(meta, paramDef, async (ps, user) => { Users.findOneByOrFail({ id: user.id }), ]); - if (userDetailed.isDeleted) { + if (userDetailed.isDeleted != null) { return; } diff --git a/packages/backend/src/services/delete-account.ts b/packages/backend/src/services/delete-account.ts index 9c8d4c277..bf95b2bc0 100644 --- a/packages/backend/src/services/delete-account.ts +++ b/packages/backend/src/services/delete-account.ts @@ -8,7 +8,7 @@ export async function deleteAccount(user: { host: string | null; }): Promise { await Users.update(user.id, { - isDeleted: true, + isDeleted: -1, }); if (Users.isLocalUser(user)) {