From 598b9fd7d60e2030998655c2aff40865bfb6a278 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Fri, 7 Mar 2025 22:28:55 +0100 Subject: [PATCH] Add delete account function --- assets/global.css | 4 ++++ pages/account/settings.vue | 27 ++++++++++++++++++++-- server/api/account.delete.ts | 43 ++++++++++++++++++++++++++++++++++++ server/api/account.patch.ts | 20 +++-------------- server/utils/schedule.ts | 21 ++++++++++++++++++ 5 files changed, 96 insertions(+), 19 deletions(-) create mode 100644 server/api/account.delete.ts create mode 100644 server/utils/schedule.ts diff --git a/assets/global.css b/assets/global.css index 8ce34a5..95d32af 100644 --- a/assets/global.css +++ b/assets/global.css @@ -58,6 +58,10 @@ button { font-size: inherit; } +fieldset { + padding-inline: 0.5rem; +} + label { display: block; } diff --git a/pages/account/settings.vue b/pages/account/settings.vue index 9fcbf3c..aba7fb6 100644 --- a/pages/account/settings.vue +++ b/pages/account/settings.vue @@ -6,6 +6,13 @@

+
+ Danger Zone + Delete my account and all data associated with it + +
@@ -15,8 +22,24 @@ definePageMeta({ }); const { data: session } = useAccountSession(); +const { refresh: sessionRefresh } = useAccountSession(); + +async function deleteAccount() { + try { + await $fetch.raw("/api/account", { + method: "DELETE", + }); + await sessionRefresh(); + await navigateTo("/"); + + } catch (err: any) { + alert(`Delete account failed: ${err.statusCode} ${err.statusMessage}`); + } +} - diff --git a/server/api/account.delete.ts b/server/api/account.delete.ts new file mode 100644 index 0000000..9530b6c --- /dev/null +++ b/server/api/account.delete.ts @@ -0,0 +1,43 @@ +import { + readAccounts, readSessions, readSubscriptions, + writeAccounts, writeSessions, writeSubscriptions, + } from "~/server/database"; + +export default defineEventHandler(async (event) => { + const accountSession = await requireAccountSession(event); + + let accounts = await readAccounts(); + const sessionAccount = accounts.find( + account => account.id === accountSession.accountId + ); + if (!sessionAccount) { + throw Error("Account does not exist"); + } + + // Remove sessions for this account + const removedSessionIds = new Set(); + let sessions = await readSessions(); + sessions = sessions.filter(session => { + if (session.accountId === accountSession.accountId) { + removedSessionIds.add(session.id); + return false; + } + return true; + }); + await writeSessions(sessions); + await deleteCookie(event, "session"); + + // Remove subscriptions for this account + let subscriptions = await readSubscriptions(); + subscriptions = subscriptions.filter( + subscription => !removedSessionIds.has(subscription.sessionId) + ); + await writeSubscriptions(subscriptions); + + // Remove the account + accounts = accounts.filter(account => account.id !== accountSession.accountId); + await writeAccounts(accounts); + + // Update Schedule counts. + await updateScheduleInterestedCounts(accounts); +}) diff --git a/server/api/account.patch.ts b/server/api/account.patch.ts index 5431e03..3b27cd8 100644 --- a/server/api/account.patch.ts +++ b/server/api/account.patch.ts @@ -1,6 +1,5 @@ import { Account } from "~/shared/types/account"; -import { readAccounts, readSchedule, writeAccounts, writeSchedule } from "~/server/database"; -import { broadcastUpdate } from "~/server/streams"; +import { readAccounts, writeAccounts } from "~/server/database"; export default defineEventHandler(async (event) => { const session = await requireAccountSession(event); @@ -28,19 +27,6 @@ export default defineEventHandler(async (event) => { } await writeAccounts(accounts); - const counts = new Map(); - for (const account of accounts) - if (account.interestedIds) - for (const id of account.interestedIds) - counts.set(id, (counts.get(id) ?? 0) + 1); - - const schedule = await readSchedule(); - for (const event of schedule.events) { - event.interested = counts.get(event.id); - for (const slot of event.slots) { - slot.interested = counts.get(slot.id); - } - } - await writeSchedule(schedule); - broadcastUpdate(schedule); + // Update Schedule counts. + await updateScheduleInterestedCounts(accounts); }) diff --git a/server/utils/schedule.ts b/server/utils/schedule.ts new file mode 100644 index 0000000..0653c1d --- /dev/null +++ b/server/utils/schedule.ts @@ -0,0 +1,21 @@ +import { Account } from '~/shared/types/account'; +import { readSchedule, writeSchedule } from '~/server/database'; +import { broadcastUpdate } from '~/server/streams'; + +export async function updateScheduleInterestedCounts(accounts: Account[]) { + const counts = new Map(); + for (const account of accounts) + if (account.interestedIds) + for (const id of account.interestedIds) + counts.set(id, (counts.get(id) ?? 0) + 1); + + const schedule = await readSchedule(); + for (const event of schedule.events) { + event.interested = counts.get(event.id); + for (const slot of event.slots) { + slot.interested = counts.get(slot.id); + } + } + await writeSchedule(schedule); + broadcastUpdate(schedule); +}