ci: trigga på master + formatfix inför Gitea Actions
CI / Typecheck, test & build (push) Failing after 2s
CI / Typecheck, test & build (push) Failing after 2s
This commit is contained in:
@@ -37,7 +37,10 @@ export async function buildErasurePlan(db: Database, userId: string): Promise<Er
|
||||
const bankImages = await db
|
||||
.select({ key: schema.aiTrainingBank.imageS3Key })
|
||||
.from(schema.aiTrainingBank)
|
||||
.innerJoin(schema.aiCorrections, eq(schema.aiTrainingBank.correctionId, schema.aiCorrections.id))
|
||||
.innerJoin(
|
||||
schema.aiCorrections,
|
||||
eq(schema.aiTrainingBank.correctionId, schema.aiCorrections.id),
|
||||
)
|
||||
.where(eq(schema.aiCorrections.userId, userId));
|
||||
for (const row of bankImages) {
|
||||
if (row.key) imageReferences.push(row.key);
|
||||
@@ -101,12 +104,7 @@ export async function buildErasurePlan(db: Database, userId: string): Promise<Er
|
||||
const draftRecipeImages = await db
|
||||
.select({ urls: schema.recipes.imageUrls })
|
||||
.from(schema.recipes)
|
||||
.where(
|
||||
and(
|
||||
eq(schema.recipes.creatorUserId, userId),
|
||||
ne(schema.recipes.status, "published"),
|
||||
),
|
||||
);
|
||||
.where(and(eq(schema.recipes.creatorUserId, userId), ne(schema.recipes.status, "published")));
|
||||
for (const row of draftRecipeImages) {
|
||||
for (const url of row.urls ?? []) {
|
||||
if (url) imageReferences.push(url);
|
||||
@@ -128,167 +126,261 @@ export async function eraseUser(db: Database, userId: string): Promise<ErasureLo
|
||||
.delete(schema.userCredentials)
|
||||
.where(eq(schema.userCredentials.userId, userId))
|
||||
.returning({ userId: schema.userCredentials.userId });
|
||||
if (credDel.length) log.push({ table: getTableName(schema.userCredentials), action: "delete", count: credDel.length });
|
||||
if (credDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.userCredentials),
|
||||
action: "delete",
|
||||
count: credDel.length,
|
||||
});
|
||||
|
||||
const adminTotpDel = await db
|
||||
.delete(schema.adminTotp)
|
||||
.where(eq(schema.adminTotp.userId, userId))
|
||||
.returning({ userId: schema.adminTotp.userId });
|
||||
if (adminTotpDel.length) log.push({ table: getTableName(schema.adminTotp), action: "delete", count: adminTotpDel.length });
|
||||
if (adminTotpDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.adminTotp),
|
||||
action: "delete",
|
||||
count: adminTotpDel.length,
|
||||
});
|
||||
|
||||
const emailTokensDel = await db
|
||||
.delete(schema.emailVerificationTokens)
|
||||
.where(eq(schema.emailVerificationTokens.userId, userId))
|
||||
.returning({ id: schema.emailVerificationTokens.id });
|
||||
if (emailTokensDel.length) log.push({ table: getTableName(schema.emailVerificationTokens), action: "delete", count: emailTokensDel.length });
|
||||
if (emailTokensDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.emailVerificationTokens),
|
||||
action: "delete",
|
||||
count: emailTokensDel.length,
|
||||
});
|
||||
|
||||
const pwTokensDel = await db
|
||||
.delete(schema.passwordResetTokens)
|
||||
.where(eq(schema.passwordResetTokens.userId, userId))
|
||||
.returning({ id: schema.passwordResetTokens.id });
|
||||
if (pwTokensDel.length) log.push({ table: getTableName(schema.passwordResetTokens), action: "delete", count: pwTokensDel.length });
|
||||
if (pwTokensDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.passwordResetTokens),
|
||||
action: "delete",
|
||||
count: pwTokensDel.length,
|
||||
});
|
||||
|
||||
const refreshDel = await db
|
||||
.delete(schema.refreshTokens)
|
||||
.where(eq(schema.refreshTokens.userId, userId))
|
||||
.returning({ id: schema.refreshTokens.id });
|
||||
if (refreshDel.length) log.push({ table: getTableName(schema.refreshTokens), action: "delete", count: refreshDel.length });
|
||||
if (refreshDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.refreshTokens),
|
||||
action: "delete",
|
||||
count: refreshDel.length,
|
||||
});
|
||||
|
||||
const consentsDel = await db
|
||||
.delete(schema.userConsents)
|
||||
.where(eq(schema.userConsents.userId, userId))
|
||||
.returning({ userId: schema.userConsents.userId });
|
||||
if (consentsDel.length) log.push({ table: getTableName(schema.userConsents), action: "delete", count: consentsDel.length });
|
||||
if (consentsDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.userConsents),
|
||||
action: "delete",
|
||||
count: consentsDel.length,
|
||||
});
|
||||
|
||||
const idemDel = await db
|
||||
.delete(schema.idempotencyKeys)
|
||||
.where(eq(schema.idempotencyKeys.userId, userId))
|
||||
.returning({ key: schema.idempotencyKeys.key });
|
||||
if (idemDel.length) log.push({ table: getTableName(schema.idempotencyKeys), action: "delete", count: idemDel.length });
|
||||
if (idemDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.idempotencyKeys),
|
||||
action: "delete",
|
||||
count: idemDel.length,
|
||||
});
|
||||
|
||||
const pushDel = await db
|
||||
.delete(schema.pushTokens)
|
||||
.where(eq(schema.pushTokens.userId, userId))
|
||||
.returning({ token: schema.pushTokens.token });
|
||||
if (pushDel.length) log.push({ table: getTableName(schema.pushTokens), action: "delete", count: pushDel.length });
|
||||
if (pushDel.length)
|
||||
log.push({ table: getTableName(schema.pushTokens), action: "delete", count: pushDel.length });
|
||||
|
||||
const notifDel = await db
|
||||
.delete(schema.notifications)
|
||||
.where(eq(schema.notifications.userId, userId))
|
||||
.returning({ id: schema.notifications.id });
|
||||
if (notifDel.length) log.push({ table: getTableName(schema.notifications), action: "delete", count: notifDel.length });
|
||||
if (notifDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.notifications),
|
||||
action: "delete",
|
||||
count: notifDel.length,
|
||||
});
|
||||
|
||||
const feedbackDel = await db
|
||||
.delete(schema.feedback)
|
||||
.where(eq(schema.feedback.userId, userId))
|
||||
.returning({ id: schema.feedback.id });
|
||||
if (feedbackDel.length) log.push({ table: getTableName(schema.feedback), action: "delete", count: feedbackDel.length });
|
||||
if (feedbackDel.length)
|
||||
log.push({ table: getTableName(schema.feedback), action: "delete", count: feedbackDel.length });
|
||||
|
||||
// ---- 2. Recipes ----
|
||||
const deletedRecipes = await db
|
||||
.delete(schema.recipes)
|
||||
.where(
|
||||
and(
|
||||
eq(schema.recipes.creatorUserId, userId),
|
||||
ne(schema.recipes.status, "published"),
|
||||
),
|
||||
)
|
||||
.where(and(eq(schema.recipes.creatorUserId, userId), ne(schema.recipes.status, "published")))
|
||||
.returning({ id: schema.recipes.id });
|
||||
if (deletedRecipes.length) log.push({ table: getTableName(schema.recipes), action: "delete", count: deletedRecipes.length });
|
||||
if (deletedRecipes.length)
|
||||
log.push({
|
||||
table: getTableName(schema.recipes),
|
||||
action: "delete",
|
||||
count: deletedRecipes.length,
|
||||
});
|
||||
|
||||
const anonymizedRecipes = await db
|
||||
.update(schema.recipes)
|
||||
.set({ creatorUserId: null, creatorDisplayName: null, updatedAt: new Date() })
|
||||
.where(
|
||||
and(
|
||||
eq(schema.recipes.creatorUserId, userId),
|
||||
eq(schema.recipes.status, "published"),
|
||||
),
|
||||
)
|
||||
.where(and(eq(schema.recipes.creatorUserId, userId), eq(schema.recipes.status, "published")))
|
||||
.returning({ id: schema.recipes.id });
|
||||
if (anonymizedRecipes.length) log.push({ table: getTableName(schema.recipes), action: "anonymize", count: anonymizedRecipes.length });
|
||||
if (anonymizedRecipes.length)
|
||||
log.push({
|
||||
table: getTableName(schema.recipes),
|
||||
action: "anonymize",
|
||||
count: anonymizedRecipes.length,
|
||||
});
|
||||
|
||||
const ratingsDel = await db
|
||||
.delete(schema.recipeRatings)
|
||||
.where(eq(schema.recipeRatings.userId, userId))
|
||||
.returning({ id: schema.recipeRatings.id });
|
||||
if (ratingsDel.length) log.push({ table: getTableName(schema.recipeRatings), action: "delete", count: ratingsDel.length });
|
||||
if (ratingsDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.recipeRatings),
|
||||
action: "delete",
|
||||
count: ratingsDel.length,
|
||||
});
|
||||
|
||||
const favoritesDel = await db
|
||||
.delete(schema.recipeFavorites)
|
||||
.where(eq(schema.recipeFavorites.userId, userId))
|
||||
.returning({ recipeId: schema.recipeFavorites.recipeId });
|
||||
if (favoritesDel.length) log.push({ table: getTableName(schema.recipeFavorites), action: "delete", count: favoritesDel.length });
|
||||
if (favoritesDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.recipeFavorites),
|
||||
action: "delete",
|
||||
count: favoritesDel.length,
|
||||
});
|
||||
|
||||
const cooksDel = await db
|
||||
.delete(schema.recipeCooks)
|
||||
.where(eq(schema.recipeCooks.userId, userId))
|
||||
.returning({ id: schema.recipeCooks.id });
|
||||
if (cooksDel.length) log.push({ table: getTableName(schema.recipeCooks), action: "delete", count: cooksDel.length });
|
||||
if (cooksDel.length)
|
||||
log.push({ table: getTableName(schema.recipeCooks), action: "delete", count: cooksDel.length });
|
||||
|
||||
const creatorStatsDel = await db
|
||||
.delete(schema.creatorStats)
|
||||
.where(eq(schema.creatorStats.userId, userId))
|
||||
.returning({ userId: schema.creatorStats.userId });
|
||||
if (creatorStatsDel.length) log.push({ table: getTableName(schema.creatorStats), action: "delete", count: creatorStatsDel.length });
|
||||
if (creatorStatsDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.creatorStats),
|
||||
action: "delete",
|
||||
count: creatorStatsDel.length,
|
||||
});
|
||||
|
||||
const followsDel = await db
|
||||
.delete(schema.creatorFollows)
|
||||
.where(
|
||||
or(eq(schema.creatorFollows.followerUserId, userId), eq(schema.creatorFollows.creatorUserId, userId)),
|
||||
or(
|
||||
eq(schema.creatorFollows.followerUserId, userId),
|
||||
eq(schema.creatorFollows.creatorUserId, userId),
|
||||
),
|
||||
)
|
||||
.returning({ followerUserId: schema.creatorFollows.followerUserId });
|
||||
if (followsDel.length) log.push({ table: getTableName(schema.creatorFollows), action: "delete", count: followsDel.length });
|
||||
if (followsDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.creatorFollows),
|
||||
action: "delete",
|
||||
count: followsDel.length,
|
||||
});
|
||||
|
||||
// ---- 3. Personal content ----
|
||||
const mealsDel = await db
|
||||
.delete(schema.meals)
|
||||
.where(eq(schema.meals.userId, userId))
|
||||
.returning({ id: schema.meals.id });
|
||||
if (mealsDel.length) log.push({ table: getTableName(schema.meals), action: "delete", count: mealsDel.length });
|
||||
if (mealsDel.length)
|
||||
log.push({ table: getTableName(schema.meals), action: "delete", count: mealsDel.length });
|
||||
|
||||
const foodMemDel = await db
|
||||
.delete(schema.foodMemories)
|
||||
.where(eq(schema.foodMemories.userId, userId))
|
||||
.returning({ id: schema.foodMemories.id });
|
||||
if (foodMemDel.length) log.push({ table: getTableName(schema.foodMemories), action: "delete", count: foodMemDel.length });
|
||||
if (foodMemDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.foodMemories),
|
||||
action: "delete",
|
||||
count: foodMemDel.length,
|
||||
});
|
||||
|
||||
const tasteDel = await db
|
||||
.delete(schema.tasteSignals)
|
||||
.where(eq(schema.tasteSignals.userId, userId))
|
||||
.returning({ id: schema.tasteSignals.id });
|
||||
if (tasteDel.length) log.push({ table: getTableName(schema.tasteSignals), action: "delete", count: tasteDel.length });
|
||||
if (tasteDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.tasteSignals),
|
||||
action: "delete",
|
||||
count: tasteDel.length,
|
||||
});
|
||||
|
||||
const memoryDel = await db
|
||||
.delete(schema.memoryItems)
|
||||
.where(eq(schema.memoryItems.userId, userId))
|
||||
.returning({ id: schema.memoryItems.id });
|
||||
if (memoryDel.length) log.push({ table: getTableName(schema.memoryItems), action: "delete", count: memoryDel.length });
|
||||
if (memoryDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.memoryItems),
|
||||
action: "delete",
|
||||
count: memoryDel.length,
|
||||
});
|
||||
|
||||
// ---- 4. AI / scans / training ----
|
||||
const aiCorrectionsDel = await db
|
||||
.delete(schema.aiCorrections)
|
||||
.where(eq(schema.aiCorrections.userId, userId))
|
||||
.returning({ id: schema.aiCorrections.id });
|
||||
if (aiCorrectionsDel.length) log.push({ table: getTableName(schema.aiCorrections), action: "delete", count: aiCorrectionsDel.length });
|
||||
if (aiCorrectionsDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.aiCorrections),
|
||||
action: "delete",
|
||||
count: aiCorrectionsDel.length,
|
||||
});
|
||||
|
||||
const scanJobsDel = await db
|
||||
.delete(schema.scanJobs)
|
||||
.where(eq(schema.scanJobs.userId, userId))
|
||||
.returning({ id: schema.scanJobs.id });
|
||||
if (scanJobsDel.length) log.push({ table: getTableName(schema.scanJobs), action: "delete", count: scanJobsDel.length });
|
||||
if (scanJobsDel.length)
|
||||
log.push({ table: getTableName(schema.scanJobs), action: "delete", count: scanJobsDel.length });
|
||||
|
||||
const aiUsageDel = await db
|
||||
.delete(schema.aiUsageCounters)
|
||||
.where(eq(schema.aiUsageCounters.userId, userId))
|
||||
.returning({ userId: schema.aiUsageCounters.userId });
|
||||
if (aiUsageDel.length) log.push({ table: getTableName(schema.aiUsageCounters), action: "delete", count: aiUsageDel.length });
|
||||
if (aiUsageDel.length)
|
||||
log.push({
|
||||
table: getTableName(schema.aiUsageCounters),
|
||||
action: "delete",
|
||||
count: aiUsageDel.length,
|
||||
});
|
||||
|
||||
const trialsDel = await db
|
||||
.delete(schema.trials)
|
||||
.where(eq(schema.trials.userId, userId))
|
||||
.returning({ userId: schema.trials.userId });
|
||||
if (trialsDel.length) log.push({ table: getTableName(schema.trials), action: "delete", count: trialsDel.length });
|
||||
if (trialsDel.length)
|
||||
log.push({ table: getTableName(schema.trials), action: "delete", count: trialsDel.length });
|
||||
|
||||
// ---- 5. Financial / subscriptions (pseudonymize) ----
|
||||
const subCountRow = await db
|
||||
@@ -299,7 +391,8 @@ export async function eraseUser(db: Database, userId: string): Promise<ErasureLo
|
||||
.select({ count: sql<number>`count(*)::int` })
|
||||
.from(schema.storeTransactions)
|
||||
.where(eq(schema.storeTransactions.userId, userId));
|
||||
const hasFinancialRecords = Number(subCountRow[0]?.count ?? 0) > 0 || Number(txCountRow[0]?.count ?? 0) > 0;
|
||||
const hasFinancialRecords =
|
||||
Number(subCountRow[0]?.count ?? 0) > 0 || Number(txCountRow[0]?.count ?? 0) > 0;
|
||||
|
||||
if (hasFinancialRecords) {
|
||||
const pseudonym = randomUUID();
|
||||
@@ -317,7 +410,12 @@ export async function eraseUser(db: Database, userId: string): Promise<ErasureLo
|
||||
.set({ userId: null, pseudonym, householdId: null, updatedAt: new Date() })
|
||||
.where(eq(schema.subscriptions.userId, userId))
|
||||
.returning({ id: schema.subscriptions.id });
|
||||
if (subPseud.length) log.push({ table: getTableName(schema.subscriptions), action: "pseudonymize", count: subPseud.length });
|
||||
if (subPseud.length)
|
||||
log.push({
|
||||
table: getTableName(schema.subscriptions),
|
||||
action: "pseudonymize",
|
||||
count: subPseud.length,
|
||||
});
|
||||
|
||||
const storePseud = await db
|
||||
.update(schema.storeTransactions)
|
||||
@@ -328,14 +426,24 @@ export async function eraseUser(db: Database, userId: string): Promise<ErasureLo
|
||||
})
|
||||
.where(eq(schema.storeTransactions.userId, userId))
|
||||
.returning({ id: schema.storeTransactions.id });
|
||||
if (storePseud.length) log.push({ table: getTableName(schema.storeTransactions), action: "pseudonymize", count: storePseud.length });
|
||||
if (storePseud.length)
|
||||
log.push({
|
||||
table: getTableName(schema.storeTransactions),
|
||||
action: "pseudonymize",
|
||||
count: storePseud.length,
|
||||
});
|
||||
|
||||
const eventPseud = await db
|
||||
.update(schema.subscriptionEvents)
|
||||
.set({ userId: null, pseudonym, payload: sql`jsonb_build_object('anonymized', true)` })
|
||||
.where(eq(schema.subscriptionEvents.userId, userId))
|
||||
.returning({ id: schema.subscriptionEvents.id });
|
||||
if (eventPseud.length) log.push({ table: getTableName(schema.subscriptionEvents), action: "pseudonymize", count: eventPseud.length });
|
||||
if (eventPseud.length)
|
||||
log.push({
|
||||
table: getTableName(schema.subscriptionEvents),
|
||||
action: "pseudonymize",
|
||||
count: eventPseud.length,
|
||||
});
|
||||
}
|
||||
|
||||
// ---- 6. Audit logs (anonymize actor, keep for retention) ----
|
||||
@@ -344,7 +452,12 @@ export async function eraseUser(db: Database, userId: string): Promise<ErasureLo
|
||||
.set({ actorUserId: null, ip: null, metadata: sql`jsonb_build_object('anonymized', true)` })
|
||||
.where(eq(schema.auditLogs.actorUserId, userId))
|
||||
.returning({ id: schema.auditLogs.id });
|
||||
if (auditAnon.length) log.push({ table: getTableName(schema.auditLogs), action: "anonymize", count: auditAnon.length });
|
||||
if (auditAnon.length)
|
||||
log.push({
|
||||
table: getTableName(schema.auditLogs),
|
||||
action: "anonymize",
|
||||
count: auditAnon.length,
|
||||
});
|
||||
|
||||
// ---- 7. Domain events (anonymize) ----
|
||||
const domainAnon = await db
|
||||
@@ -352,7 +465,12 @@ export async function eraseUser(db: Database, userId: string): Promise<ErasureLo
|
||||
.set({ userId: null, payload: sql`jsonb_build_object('anonymized', true)` })
|
||||
.where(eq(schema.domainEvents.userId, userId))
|
||||
.returning({ id: schema.domainEvents.id });
|
||||
if (domainAnon.length) log.push({ table: getTableName(schema.domainEvents), action: "anonymize", count: domainAnon.length });
|
||||
if (domainAnon.length)
|
||||
log.push({
|
||||
table: getTableName(schema.domainEvents),
|
||||
action: "anonymize",
|
||||
count: domainAnon.length,
|
||||
});
|
||||
|
||||
// ---- 8. Households ----
|
||||
// Remove memberships first; remember surviving households for receipt anonymization.
|
||||
@@ -366,7 +484,8 @@ export async function eraseUser(db: Database, userId: string): Promise<ErasureLo
|
||||
.delete(schema.households)
|
||||
.where(inArray(schema.households.id, plan.householdsToDelete))
|
||||
.returning({ id: schema.households.id });
|
||||
if (hhDel.length) log.push({ table: getTableName(schema.households), action: "delete", count: hhDel.length });
|
||||
if (hhDel.length)
|
||||
log.push({ table: getTableName(schema.households), action: "delete", count: hhDel.length });
|
||||
}
|
||||
|
||||
const survivingHouseholdIds = survivingHouseholds
|
||||
@@ -380,11 +499,20 @@ export async function eraseUser(db: Database, userId: string): Promise<ErasureLo
|
||||
.where(inArray(schema.receipts.householdId, survivingHouseholdIds))
|
||||
.returning({ id: schema.receipts.id });
|
||||
if (receiptAnon.length) {
|
||||
log.push({ table: getTableName(schema.receipts), action: "anonymize", count: receiptAnon.length });
|
||||
log.push({
|
||||
table: getTableName(schema.receipts),
|
||||
action: "anonymize",
|
||||
count: receiptAnon.length,
|
||||
});
|
||||
await db
|
||||
.update(schema.receiptLines)
|
||||
.set({ rawText: "" })
|
||||
.where(inArray(schema.receiptLines.receiptId, receiptAnon.map((r) => r.id)));
|
||||
.where(
|
||||
inArray(
|
||||
schema.receiptLines.receiptId,
|
||||
receiptAnon.map((r) => r.id),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Anonymize cooking sessions started by user in surviving households.
|
||||
@@ -393,7 +521,12 @@ export async function eraseUser(db: Database, userId: string): Promise<ErasureLo
|
||||
.set({ startedByUserId: null })
|
||||
.where(eq(schema.cookingSessions.startedByUserId, userId))
|
||||
.returning({ id: schema.cookingSessions.id });
|
||||
if (cookingAnon.length) log.push({ table: getTableName(schema.cookingSessions), action: "anonymize", count: cookingAnon.length });
|
||||
if (cookingAnon.length)
|
||||
log.push({
|
||||
table: getTableName(schema.cookingSessions),
|
||||
action: "anonymize",
|
||||
count: cookingAnon.length,
|
||||
});
|
||||
|
||||
// Anonymize household-level records that still reference the user.
|
||||
const conflictAnon = await db
|
||||
@@ -401,38 +534,61 @@ export async function eraseUser(db: Database, userId: string): Promise<ErasureLo
|
||||
.set({ resolvedByUserId: null })
|
||||
.where(eq(schema.inventoryConflicts.resolvedByUserId, userId))
|
||||
.returning({ id: schema.inventoryConflicts.id });
|
||||
if (conflictAnon.length) log.push({ table: getTableName(schema.inventoryConflicts), action: "anonymize", count: conflictAnon.length });
|
||||
if (conflictAnon.length)
|
||||
log.push({
|
||||
table: getTableName(schema.inventoryConflicts),
|
||||
action: "anonymize",
|
||||
count: conflictAnon.length,
|
||||
});
|
||||
|
||||
const transactionAnon = await db
|
||||
.update(schema.inventoryTransactions)
|
||||
.set({ actorUserId: null })
|
||||
.where(eq(schema.inventoryTransactions.actorUserId, userId))
|
||||
.returning({ id: schema.inventoryTransactions.id });
|
||||
if (transactionAnon.length) log.push({ table: getTableName(schema.inventoryTransactions), action: "anonymize", count: transactionAnon.length });
|
||||
if (transactionAnon.length)
|
||||
log.push({
|
||||
table: getTableName(schema.inventoryTransactions),
|
||||
action: "anonymize",
|
||||
count: transactionAnon.length,
|
||||
});
|
||||
|
||||
const mealBoxAnon = await db
|
||||
.update(schema.mealBoxes)
|
||||
.set({ reservedForUserId: null })
|
||||
.where(eq(schema.mealBoxes.reservedForUserId, userId))
|
||||
.returning({ id: schema.mealBoxes.id });
|
||||
if (mealBoxAnon.length) log.push({ table: getTableName(schema.mealBoxes), action: "anonymize", count: mealBoxAnon.length });
|
||||
if (mealBoxAnon.length)
|
||||
log.push({
|
||||
table: getTableName(schema.mealBoxes),
|
||||
action: "anonymize",
|
||||
count: mealBoxAnon.length,
|
||||
});
|
||||
|
||||
const shoppingAnon = await db
|
||||
.update(schema.shoppingListItems)
|
||||
.set({ addedByUserId: null })
|
||||
.where(eq(schema.shoppingListItems.addedByUserId, userId))
|
||||
.returning({ id: schema.shoppingListItems.id });
|
||||
if (shoppingAnon.length) log.push({ table: getTableName(schema.shoppingListItems), action: "anonymize", count: shoppingAnon.length });
|
||||
if (shoppingAnon.length)
|
||||
log.push({
|
||||
table: getTableName(schema.shoppingListItems),
|
||||
action: "anonymize",
|
||||
count: shoppingAnon.length,
|
||||
});
|
||||
}
|
||||
|
||||
// ---- 9. Analytics ----
|
||||
const analyticsDel = await deleteUserAnalyticsEvents(db, userId);
|
||||
if (analyticsDel > 0) log.push({ table: "analytics_events", action: "delete", count: analyticsDel });
|
||||
if (analyticsDel > 0)
|
||||
log.push({ table: "analytics_events", action: "delete", count: analyticsDel });
|
||||
|
||||
// ---- 10. Health/preferences/locale (delete) ----
|
||||
await db.delete(schema.userHealthProfiles).where(eq(schema.userHealthProfiles.userId, userId));
|
||||
await db.delete(schema.userPreferences).where(eq(schema.userPreferences.userId, userId));
|
||||
await db.delete(schema.userLocalePreferences).where(eq(schema.userLocalePreferences.userId, userId));
|
||||
await db
|
||||
.delete(schema.userLocalePreferences)
|
||||
.where(eq(schema.userLocalePreferences.userId, userId));
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user