Skip to content

Commit

Permalink
feat: add button to delete all user data.
Browse files Browse the repository at this point in the history
  • Loading branch information
zicklag committed Dec 6, 2024
1 parent a533f2f commit c5d6e05
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/lib/billing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class BillingEngine {
const subscriptions = await this.getWeirdNerdSubscriptionInfo(rauthyId);
const activeSubscriptions = subscriptions.filter((x) => x.attributes.status == 'active');
if (activeSubscriptions.length != 1) {
throw 'More than one active subscription, not sure how to cancel.';
throw 'Could not find exactly one subscription, not sure how to cancel.';
}
const resp = await lemon.cancelSubscription(activeSubscriptions[0].id);
if (resp.error) {
Expand Down
7 changes: 7 additions & 0 deletions src/lib/leaf/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,13 @@ export async function setProfileById(rauthyId: string, profile: Profile): Promis
await linkVerifier.verify();
await setProfile(link, profile);
}
export async function deleteAllProfileDataById(rauthyId: string) {
const subspace = await usernames.subspaceByRauthyId(rauthyId);
const ents = await leafClient.list_entities(subspace_link(subspace));
for (const ent of ents) {
await leafClient.del_entity(ent);
}
}

export async function getProfiles(): Promise<
{ link: ExactLink; profile: Profile; username?: string }[]
Expand Down
4 changes: 2 additions & 2 deletions src/lib/usernames/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,10 @@ async function unset(username: string) {
const multi = redis.multi();

multi.del(usernameKey);
if (user.subspace == (await redis.hGet(subspaceKey, 'username'))) {
if (username == (await redis.hGet(subspaceKey, 'username'))) {
multi.hDel(subspaceKey, 'username');
}
if (user.rauthyId == (await redis.hGet(rauthyIdKey, 'username'))) {
if (username == (await redis.hGet(rauthyIdKey, 'username'))) {
multi.hDel(rauthyIdKey, 'username');
}

Expand Down
15 changes: 15 additions & 0 deletions src/routes/(app)/[username]/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { getModalStore, type ModalSettings } from '@skeletonlabs/skeleton';
import SetHandleModal from './components/ChangeHandleModal.svelte';
import ManageSubscriptionModal from './components/ManageSubscriptionModal.svelte';
import DeleteProfileModal from './components/DeleteProfileModal.svelte';
import { env } from '$env/dynamic/public';
const { data, children }: { children: Snippet; data: PageData } = $props();
Expand Down Expand Up @@ -37,6 +38,17 @@
}
}
});
const deleteProfileModal: ModalSettings = $derived({
type: 'component',
component: { ref: DeleteProfileModal },
async response(r) {
if ('error' in r) {
error = r.error;
} else {
error = null;
}
}
});
</script>

<div class="flex flex-row flex-wrap-reverse sm:flex-nowrap">
Expand Down Expand Up @@ -79,6 +91,9 @@
<button class="variant-ghost btn" onclick={() => modalStore.trigger(setHandleModal)}>
Change Handle
</button>
<button class="variant-ghost-error btn" onclick={() => modalStore.trigger(deleteProfileModal)}>
Delete Profile
</button>
</div>
</aside>
{/if}
Expand Down
45 changes: 45 additions & 0 deletions src/routes/(app)/[username]/components/DeleteProfileModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<script lang="ts">
import { getModalStore } from '@skeletonlabs/skeleton';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
const modalStore = getModalStore();
let username = $state('');
async function deleteProfile() {
await fetch(`/${$page.params.username}/settings/deleteProfile`, {
method: 'post'
});
await goto('/claim-username', { invalidateAll: true, replaceState: true });
modalStore.close();
}
</script>

{#if $modalStore[0]}
<div class="card flex flex-col justify-between space-y-4 p-4 shadow-xl">
<div>
<header class="text-2xl font-bold">Delete Profile Data</header>

<section class="p-2">
<div class="prose prose-invert">
<p>Are you sure that you want to delete all of your profile data permanently?</p>
<p>Type your full username to confirm deletion.</p>
</div>

<div class="my-2 flex flex-col gap-2">
<input class="input" bind:value={username} placeholder={$page.params.username} />

<button
class="variant-ghost-error btn"
disabled={username != $page.params.username}
onclick={deleteProfile}
>
Delete
</button>
</div>
</section>
</div>

<button class="variant-ghost btn" onclick={() => modalStore.close()}> Cancel </button>
</div>
{/if}
22 changes: 22 additions & 0 deletions src/routes/(app)/[username]/settings/deleteProfile/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { billing } from '$lib/billing';
import { deleteAllProfileDataById as deleteAllUserDataById } from '$lib/leaf/profile';
import { getSession } from '$lib/rauthy/server';
import { usernames } from '$lib/usernames';
import { type RequestHandler, error } from '@sveltejs/kit';

export const POST: RequestHandler = async ({ fetch, request }) => {
const { sessionInfo } = await getSession(fetch, request);
if (!sessionInfo) return error(404, 'Unauthorized');

// Cancel any billing subscription that might exist
try {
await billing.cancelBillingSubscription(sessionInfo.user_id);
} catch (_) {}

// Delete all user entities
await deleteAllUserDataById(sessionInfo.user_id);
const username = await usernames.getByRauthyId(sessionInfo.user_id);
if (username) await usernames.unset(username);

return new Response();
};

0 comments on commit c5d6e05

Please sign in to comment.