delete associated notes on account deletion
This commit is contained in:
parent
494243cba8
commit
91762bb8ca
1 changed files with 112 additions and 21 deletions
|
@ -1,6 +1,20 @@
|
||||||
import type Bull from "bull";
|
import type Bull from "bull";
|
||||||
import { queueLogger } from "../../logger.js";
|
import { queueLogger } from "../../logger.js";
|
||||||
import { DriveFiles, Notes, UserProfiles, Users } from "@/models/index.js";
|
import {
|
||||||
|
ChannelNotePinings,
|
||||||
|
ClipNotes,
|
||||||
|
DriveFiles,
|
||||||
|
MutedNotes,
|
||||||
|
NoteFavorites,
|
||||||
|
NoteUnreads,
|
||||||
|
NoteWatchings,
|
||||||
|
Notes,
|
||||||
|
PromoNotes,
|
||||||
|
PromoReads,
|
||||||
|
UserNotePinings,
|
||||||
|
UserProfiles,
|
||||||
|
Users,
|
||||||
|
} from "@/models/index.js";
|
||||||
import type { DbUserDeleteJobData } from "@/queue/types.js";
|
import type { DbUserDeleteJobData } from "@/queue/types.js";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type { Note } from "@/models/entities/note.js";
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||||
|
@ -8,8 +22,14 @@ import { MoreThan } from "typeorm";
|
||||||
import { deleteFileSync } from "@/services/drive/delete-file.js";
|
import { deleteFileSync } from "@/services/drive/delete-file.js";
|
||||||
import { sendEmail } from "@/services/send-email.js";
|
import { sendEmail } from "@/services/send-email.js";
|
||||||
import meilisearch from "@/db/meilisearch.js";
|
import meilisearch from "@/db/meilisearch.js";
|
||||||
import { acctToUserIdCache, userByIdCache, userDenormalizedCache } from "@/services/user-cache.js";
|
import { userByIdCache, userDenormalizedCache } from "@/services/user-cache.js";
|
||||||
import config from "@/config/index.js";
|
import {
|
||||||
|
parseHomeTimeline,
|
||||||
|
parseScyllaNote,
|
||||||
|
prepared,
|
||||||
|
scyllaClient,
|
||||||
|
} from "@/db/scylla.js";
|
||||||
|
import type { Client } from "cassandra-driver";
|
||||||
|
|
||||||
const logger = queueLogger.createSubLogger("delete-account");
|
const logger = queueLogger.createSubLogger("delete-account");
|
||||||
|
|
||||||
|
@ -25,30 +45,101 @@ export async function deleteAccount(
|
||||||
// Delete notes
|
// Delete notes
|
||||||
let cursor: Note["id"] | null = null;
|
let cursor: Note["id"] | null = null;
|
||||||
|
|
||||||
while (true) {
|
if (scyllaClient) {
|
||||||
const notes = (await Notes.find({
|
scyllaClient.eachRow(
|
||||||
where: {
|
prepared.note.select.byUserId,
|
||||||
userId: user.id,
|
[user.id],
|
||||||
...(cursor ? { id: MoreThan(cursor) } : {}),
|
{ prepare: true },
|
||||||
|
(_, row) => {
|
||||||
|
const client = scyllaClient as Client;
|
||||||
|
const note = parseScyllaNote(row);
|
||||||
|
const noteDeleteParams = [
|
||||||
|
note.createdAt,
|
||||||
|
note.createdAt,
|
||||||
|
note.userId,
|
||||||
|
note.userHost ?? "local",
|
||||||
|
note.visibility,
|
||||||
|
] as [Date, Date, string, string, string];
|
||||||
|
client.execute(prepared.note.delete, noteDeleteParams, {
|
||||||
|
prepare: true,
|
||||||
|
});
|
||||||
|
client.eachRow(
|
||||||
|
prepared.homeTimeline.select.byId,
|
||||||
|
[note.id],
|
||||||
|
{
|
||||||
|
prepare: true,
|
||||||
|
},
|
||||||
|
(_, row) => {
|
||||||
|
const timeline = parseHomeTimeline(row);
|
||||||
|
client.execute(
|
||||||
|
prepared.homeTimeline.delete,
|
||||||
|
[
|
||||||
|
timeline.feedUserId,
|
||||||
|
timeline.createdAtDate,
|
||||||
|
timeline.createdAt,
|
||||||
|
timeline.userId,
|
||||||
|
],
|
||||||
|
{ prepare: true },
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (meilisearch) {
|
||||||
|
meilisearch.deleteNotes([note]);
|
||||||
|
}
|
||||||
|
ChannelNotePinings.delete({
|
||||||
|
noteId: note.id,
|
||||||
|
});
|
||||||
|
ClipNotes.delete({
|
||||||
|
noteId: note.id,
|
||||||
|
});
|
||||||
|
MutedNotes.delete({
|
||||||
|
noteId: note.id,
|
||||||
|
});
|
||||||
|
NoteFavorites.delete({
|
||||||
|
noteId: note.id,
|
||||||
|
});
|
||||||
|
NoteUnreads.delete({
|
||||||
|
noteId: note.id,
|
||||||
|
});
|
||||||
|
NoteWatchings.delete({
|
||||||
|
noteId: note.id,
|
||||||
|
});
|
||||||
|
PromoNotes.delete({
|
||||||
|
noteId: note.id,
|
||||||
|
});
|
||||||
|
PromoReads.delete({
|
||||||
|
noteId: note.id,
|
||||||
|
});
|
||||||
|
UserNotePinings.delete({
|
||||||
|
noteId: note.id,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
take: 10,
|
);
|
||||||
order: {
|
} else {
|
||||||
id: 1,
|
while (true) {
|
||||||
},
|
const notes = (await Notes.find({
|
||||||
})) as Note[];
|
where: {
|
||||||
|
userId: user.id,
|
||||||
|
...(cursor ? { id: MoreThan(cursor) } : {}),
|
||||||
|
},
|
||||||
|
take: 10,
|
||||||
|
order: {
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
})) as Note[];
|
||||||
|
|
||||||
if (notes.length === 0) {
|
if (notes.length === 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor = notes[notes.length - 1].id;
|
cursor = notes[notes.length - 1].id;
|
||||||
|
|
||||||
await Notes.delete(notes.map((note) => note.id));
|
await Notes.delete(notes.map((note) => note.id));
|
||||||
if (meilisearch) {
|
if (meilisearch) {
|
||||||
await meilisearch.deleteNotes(notes);
|
await meilisearch.deleteNotes(notes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.succ("All of notes deleted");
|
logger.succ("All of notes deleted");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue