diff --git a/src/lib/server/db.ts b/src/lib/server/db.ts index f58da26..b258f5c 100644 --- a/src/lib/server/db.ts +++ b/src/lib/server/db.ts @@ -25,7 +25,7 @@ async function deleteHouseholdInvite(req: { id: number }, user: User) { const invite = await findHouseholdInvite(id); if (!invite || invite.targetPhone !== user.phone) { throw error(401, { - message: "You can't delete a household invite tht wsan't issued to you" + message: "You can't delete a household invite that wsan't issued to you" }); } @@ -836,6 +836,37 @@ async function sendSched( ]); } +async function deleteUser(user: User) { + const userToDelete = await prisma.user.findUnique({ + where: { + phone: user.phone + } + }); + + if (!userToDelete) { + throw error(400, { + message: "Can't delete another user" + }); + } + + // delete their household if they're the last member of their household + if (user.householdId) { + const householdUsers = await prisma.user.findMany({ + where: { + householdId: user.householdId + } + }); + if (householdUsers.length === 1) await deleteHousehold(user); + } + + // delete the user + await prisma.user.delete({ + where: { + phone: user.phone + } + }); +} + export { sendSched, sendFaqLinks, @@ -853,5 +884,6 @@ export { saveKid, deleteKid, deleteHousehold, - removeHouseholdAdult + removeHouseholdAdult, + deleteUser }; diff --git a/src/routes/db/+server.ts b/src/routes/db/+server.ts index a7fc3be..b78c618 100644 --- a/src/routes/db/+server.ts +++ b/src/routes/db/+server.ts @@ -17,7 +17,8 @@ import { deleteHousehold, removeHouseholdAdult, sendFaqLinks, - sendSched + sendSched, + deleteUser } from '$lib/server/db'; import { getHousehold, getProfileFromSession, getUserAttrsInHousehold } from '$lib/server/shared'; @@ -95,7 +96,7 @@ export async function POST({ await deleteHouseholdInvite(req, user); } else { throw error(400, { - message: `The request type ${req.type} isn't supported` + message: `The request type ${req.type} isn't supported in /db POST req` }); } @@ -117,6 +118,12 @@ export async function DELETE({ if (req.type === 'householdChild') await deleteKid(req, user); else if (req.type === 'household') await deleteHousehold(user); + else if (req.type === 'user') await deleteUser(user); + else { + throw error(400, { + message: `The request type ${req.type} isn't supported in /db DELETE req` + }); + } return json('success'); } diff --git a/src/routes/household/+page.svelte b/src/routes/household/+page.svelte index 8d31536..ec62d26 100644 --- a/src/routes/household/+page.svelte +++ b/src/routes/household/+page.svelte @@ -12,7 +12,8 @@ enum ModalReason { DISCONNECT_ADULT, - DELETE_HOUSEHOLD + DELETE_HOUSEHOLD, + DELETE_ACCOUNT } let phoneInput: object; @@ -182,6 +183,14 @@ modalText.heading = 'Delete Household'; modalText.content = "Are you sure that you'd like to delete your household? This will delete all basic household info and associated children but leave all adult users' accounts intact."; + break; + case ModalReason.DELETE_ACCOUNT: + modalText.heading = 'Delete Account'; + modalText.content = + "Are you sure that you'd like to delete your account? If you are the last adult in your household, this will delete all basic household info and associated children. Otherwise, the household's info and other adult users' accounts will remain intact. Additionally, we'll delete your profile info, but keep track of your phone permission settings."; + break; + default: + throw new Error(`Undefined modal reason type ${type}`); } modalReason = type; showModal = true; @@ -261,6 +270,23 @@ function smsInviteEncoded(msg: string) { return `sms:${inviteesPhone}?&body=${encodeURIComponent(msg)}`; } + + async function deleteAcc() { + const response = await writeReq( + '/db', + { + type: 'user' + }, + 'DELETE' + ); + if (response.status == 200) { + document.cookie = 'session=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; + await goto('/'); + location.reload(); + } else { + window.alert('Something went wrong with deleting the account'); + } + }
@@ -346,7 +372,7 @@ {/key} -

{modalText.heading}

+

{modalText.heading}

{modalText.content}

@@ -355,6 +381,7 @@ on:click={async () => { if (modalReason === ModalReason.DISCONNECT_ADULT) disconnectAdult(); else if (modalReason === ModalReason.DELETE_HOUSEHOLD) deleteHousehold(); + else if (modalReason === ModalReason.DELETE_ACCOUNT) deleteAcc(); dialog.close(); }} > @@ -468,6 +495,10 @@ >Delete Household {/if} +
@@ -558,7 +589,7 @@ display: flex; flex-direction: column; margin: 3rem 3rem 4rem; - gap: 20px; + gap: 2rem; } .important-delete-btn { diff --git a/tests/db.spec.ts b/tests/db.spec.ts index cf0cfcf..d34387a 100644 --- a/tests/db.spec.ts +++ b/tests/db.spec.ts @@ -32,6 +32,7 @@ that info is derived from the session cookie - User 2 fails to issue invitations for others to join User 3's household - User 2 fails to alter User 1's schedule - User 2 fails to issue friend reqs to others from User 3's household +- User 6 fails to delete another user */ test("User 4 fails to accept friend request on User 3's behalf", async ({ page, context }) => { @@ -149,7 +150,7 @@ test("User 4 fails to decline household invite on User 2's behalf", async ({ pag } }); const { message } = await res.json(); - expect(message).toEqual("You can't delete a household invite tht wsan't issued to you"); + expect(message).toEqual("You can't delete a household invite that wsan't issued to you"); expect(res.status()).toEqual(401); await page.close(); });