From 4ca3f3c8ee5b3590e233d69c04d1b7e4a4f5d811 Mon Sep 17 00:00:00 2001 From: MartinBraquet Date: Wed, 29 Oct 2025 16:22:11 +0100 Subject: [PATCH] Delete auth user right away --- backend/api/src/delete-me.ts | 9 +- common/src/api/schema.ts | 4 +- web/components/notifications.tsx | 146 +++++++++++++++++++++++++++++++ web/lib/util/delete.ts | 4 +- 4 files changed, 150 insertions(+), 13 deletions(-) create mode 100644 web/components/notifications.tsx diff --git a/backend/api/src/delete-me.ts b/backend/api/src/delete-me.ts index 9183b523..12af1f69 100644 --- a/backend/api/src/delete-me.ts +++ b/backend/api/src/delete-me.ts @@ -4,18 +4,11 @@ import {createSupabaseDirectClient} from 'shared/supabase/init' import * as admin from "firebase-admin"; import {deleteUserFiles} from "shared/firebase-utils"; -export const deleteMe: APIHandler<'me/delete'> = async (body, auth) => { - const {username} = body +export const deleteMe: APIHandler<'me/delete'> = async (_, auth) => { const user = await getUser(auth.uid) if (!user) { throw new APIError(401, 'Your account was not found') } - if (user.username != username) { - throw new APIError( - 400, - `Incorrect username. You are logged in as ${user.username}. Are you sure you want to delete this account?` - ) - } const userId = user.id if (!userId) { throw new APIError(400, 'Invalid user ID') diff --git a/common/src/api/schema.ts b/common/src/api/schema.ts index 7918a912..f3d8b8f3 100644 --- a/common/src/api/schema.ts +++ b/common/src/api/schema.ts @@ -238,9 +238,7 @@ export const API = (_apiTypeCheck = { method: 'POST', authed: true, rateLimited: true, - props: z.object({ - username: z.string(), // just so you're sure - }), + props: z.object({}), summary: 'Delete the authenticated user account', tag: 'Users', }, diff --git a/web/components/notifications.tsx b/web/components/notifications.tsx new file mode 100644 index 00000000..85bc3076 --- /dev/null +++ b/web/components/notifications.tsx @@ -0,0 +1,146 @@ +import {usePersistentInMemoryState} from "web/hooks/use-persistent-in-memory-state"; +import { + notification_destination_types, + notification_preference, + notification_preferences +} from "common/user-notification-preferences"; +import {useCallback} from "react"; +import {debounce} from "lodash"; +import {api} from "web/lib/api"; +import {MultiSelectAnswers} from "web/components/answers/answer-compatibility-question-content"; +import {usePrivateUser} from "web/hooks/use-user"; + +export const NotificationSettings = () => { + const privateUser = usePrivateUser() + if (!privateUser) return null + + const [prefs, setPrefs] = + usePersistentInMemoryState( + privateUser.notificationPreferences, + 'notification-preferences' + ) + + const notificationTypes: { + type: notification_preference + question: string + }[] = [ + { + type: 'new_match', + question: + '... matches with you?', + }, + { + type: 'new_message', + question: '... sends you a new message?', + }, + // { + // type: 'new_profile_like', + // question: '... likes your profile?', + // }, + { + type: 'new_endorsement', + question: '... endorses you?', + }, + // { + // type: 'new_profile_ship', + // question: '... ships you?', + // }, + { + type: 'tagged_user', + question: '... mentions you?', + }, + // { + // type: 'on_new_follow', + // question: '... follows you?', + // }, + { + type: 'new_search_alerts', + question: 'Alerts from bookmarked searches?', + }, + { + type: 'opt_out_all', + question: + 'Opt out of all notifications? (You can always change this later)', + }, + ] + + return ( +
+
+

Where do you want to be notified when someone

+ {notificationTypes.map(({type, question}) => ( + { + setPrefs((prevPrefs) => ({...prevPrefs, [type]: selected})) + }} + /> + ))} +
+
+ ) +} + +const NotificationOption = (props: { + type: notification_preference + question: string + selected: notification_destination_types[] + onUpdate: (selected: notification_destination_types[]) => void +}) => { + const {type, question, selected, onUpdate} = props + + const getSelectedValues = (destinations: string[]) => { + const values: number[] = [] + if ((destinations ?? []).includes('email')) values.push(0) + if ((destinations ?? []).includes('browser')) values.push(1) + return values + } + + const setValue = async (value: number[]) => { + const newDestinations: notification_destination_types[] = [] + if (value.includes(0)) newDestinations.push('email') + if (value.includes(1)) newDestinations.push('browser') + + onUpdate(newDestinations) + save(selected, newDestinations) + } + + const save = useCallback( + debounce( + ( + oldDestinations: notification_destination_types[], + newDestinations: notification_destination_types[] + ) => { + // for each medium, if it changed, trigger a save + const mediums = ['email', 'browser'] as const + mediums.forEach((medium) => { + const wasEnabled = oldDestinations.includes(medium) + const isEnabled = newDestinations.includes(medium) + if (wasEnabled !== isEnabled) { + api('update-notif-settings', { + type, + medium, + enabled: isEnabled, + }) + } + }) + }, + 500 + ), + [] + ) + + return ( +
+
{question}
+ +
+ ) +} \ No newline at end of file diff --git a/web/lib/util/delete.ts b/web/lib/util/delete.ts index e2853fea..7d53b457 100644 --- a/web/lib/util/delete.ts +++ b/web/lib/util/delete.ts @@ -4,9 +4,9 @@ import {firebaseLogout} from "web/lib/firebase/users"; import posthog from "posthog-js"; import {clearUserCookie} from "web/components/auth-context"; -export async function deleteAccount(username: string) { +export async function deleteAccount() { track('delete account') - await api('me/delete', {username}) + await api('me/delete') await firebaseLogout() clearUserCookie() localStorage.clear()