User reports (#3232)

This commit is contained in:
Kalle
2026-07-18 12:46:07 +03:00
committed by GitHub
parent 7d1e680a74
commit ef0d32ef18
65 changed files with 879 additions and 11 deletions

View File

@@ -94,6 +94,35 @@ export function migrate(args: { newUserId: number; oldUserId: number }) {
.set({ userId: args.oldUserId })
.execute();
// reports between the two merged accounts would become self-reports
await trx
.deleteFrom("UserReport")
.where((eb) =>
eb.or([
eb.and([
eb("reporterUserId", "=", args.newUserId),
eb("reportedUserId", "=", args.oldUserId),
]),
eb.and([
eb("reporterUserId", "=", args.oldUserId),
eb("reportedUserId", "=", args.newUserId),
]),
]),
)
.execute();
await deleteOlderCollidingUserReports(trx, args, "reporterUserId");
await deleteOlderCollidingUserReports(trx, args, "reportedUserId");
await trx
.updateTable("UserReport")
.where("reporterUserId", "=", args.newUserId)
.set({ reporterUserId: args.oldUserId })
.execute();
await trx
.updateTable("UserReport")
.where("reportedUserId", "=", args.newUserId)
.set({ reportedUserId: args.oldUserId })
.execute();
// special case: delete same team membership to avoid unique constraint violation
await trx
.deleteFrom("AllTeamMember")
@@ -141,6 +170,47 @@ export function migrate(args: { newUserId: number; oldUserId: number }) {
});
}
/**
* Merging accounts can collide on the one-report-per-pair unique index; the newer
* report (by `createdAt`, id as tie-breaker) wins and the other row is dropped.
*/
function deleteOlderCollidingUserReports(
trx: Transaction<DB>,
args: { newUserId: number; oldUserId: number },
column: "reporterUserId" | "reportedUserId",
) {
const otherColumn =
column === "reporterUserId" ? "reportedUserId" : "reporterUserId";
return trx
.deleteFrom("UserReport")
.where(column, "in", [args.newUserId, args.oldUserId])
.where((eb) =>
eb.exists(
eb
.selectFrom("UserReport as newer")
.select("newer.id")
.where(`newer.${column}`, "in", [args.newUserId, args.oldUserId])
.whereRef(`newer.${otherColumn}`, "=", `UserReport.${otherColumn}`)
.whereRef("newer.id", "!=", "UserReport.id")
.where((inner) =>
inner.or([
inner("newer.createdAt", ">", inner.ref("UserReport.createdAt")),
inner.and([
inner(
"newer.createdAt",
"=",
inner.ref("UserReport.createdAt"),
),
inner("newer.id", ">", inner.ref("UserReport.id")),
]),
]),
),
),
)
.execute();
}
async function validateMigration(
trx: Transaction<DB>,
args: { newUserId: number; oldUserId: number },