feat: self-service deletion API, reactivate account page
This commit is contained in:
		
							parent
							
								
									8a2ffd7d69
								
							
						
					
					
						commit
						96725cc304
					
				
					 13 changed files with 183 additions and 17 deletions
				
			
		|  | @ -25,12 +25,14 @@ | |||
| 		{#if user.suspended} | ||||
| 			<strong>{$t("nav.suspended-account-hint")}</strong> | ||||
| 			<br /> | ||||
| 			<a href="/contact">{$t("nav.appeal-suspension-link")}</a> | ||||
| 			<a href="/settings">{$t("nav.delete-permanently-link")}</a> • | ||||
| 			<a href="/contact">{$t("nav.appeal-suspension-link")}</a> • | ||||
| 			<a href="/settings/export">{$t("nav.export-link")}</a> | ||||
| 		{:else} | ||||
| 			<strong>{$t("nav.deleted-account-hint")}</strong> | ||||
| 			<br /> | ||||
| 			<a href="/settings/reactivate">{$t("nav.reactivate-account-link")}</a> • | ||||
| 			<a href="/contact">{$t("nav.delete-permanently-link")}</a> | ||||
| 			<a href="/settings">{$t("nav.reactivate-or-delete-link")}</a> • | ||||
| 			<a href="/settings/export">{$t("nav.export-link")}</a> | ||||
| 		{/if} | ||||
| 	</div> | ||||
| {/if} | ||||
|  |  | |||
|  | @ -5,9 +5,11 @@ | |||
| 		"settings": "Settings", | ||||
| 		"suspended-account-hint": "Your account has been suspended. Your profile has been hidden and you will not be able to change any settings.", | ||||
| 		"appeal-suspension-link": "I want to appeal", | ||||
| 		"deleted-account-hint": "You have requested deletion of your account. If you want to reactivate it, click the link below.", | ||||
| 		"deleted-account-hint": "You have requested deletion of your account.", | ||||
| 		"reactivate-account-link": "Reactivate account", | ||||
| 		"delete-permanently-link": "I want my account deleted permanently" | ||||
| 		"delete-permanently-link": "I want my account deleted permanently", | ||||
| 		"reactivate-or-delete-link": "I want to reactivate my account or delete all my data", | ||||
| 		"export-link": "I want to export a copy of my data" | ||||
| 	}, | ||||
| 	"avatar-tooltip": "Avatar for {{name}}", | ||||
| 	"profile": { | ||||
|  | @ -155,7 +157,17 @@ | |||
| 		"flag-description-placeholder": "Description", | ||||
| 		"flag-name-placeholder": "Name", | ||||
| 		"flag-upload-success": "Successfully uploaded your flag! It may take a few seconds before it's saved.", | ||||
| 		"custom-preferences-title": "Custom preferences" | ||||
| 		"custom-preferences-title": "Custom preferences", | ||||
| 		"change-username-header": "Change your username", | ||||
| 		"force-delete-button": "Delete my account permanently", | ||||
| 		"force-delete-warning": "This is irreversible. Consider exporting a copy of your data before doing this.", | ||||
| 		"force-delete-explanation": "Your account is currently pending deletion. If you want your data deleted permanently, use the button below.", | ||||
| 		"reactivate-explanation": "Your account is currently pending deletion. If you want to cancel this and keep using your account, use the link below.", | ||||
| 		"reactivate-header": "Reactivate your account", | ||||
| 		"force-delete-header": "Permanently delete your account", | ||||
| 		"reactivate-button": "Reactivate my account", | ||||
| 		"reactivated-header": "Account reactivated", | ||||
| 		"reactivated-explanation": "Your account has been reactivated!" | ||||
| 	}, | ||||
| 	"yes": "Yes", | ||||
| 	"no": "No", | ||||
|  |  | |||
|  | @ -16,8 +16,6 @@ | |||
| 		data.member ? `/@${data.user.username}/${data.member.name}` : `/@${data.user.username}`, | ||||
| 	); | ||||
| 
 | ||||
| 	console.log(data.user, !!data.member); | ||||
| 
 | ||||
| 	let reasons = $derived.by(() => { | ||||
| 		const reasons = []; | ||||
| 		for (const value of Object.values(ReportReason)) { | ||||
|  |  | |||
|  | @ -18,9 +18,37 @@ | |||
| 
 | ||||
| <h3>{$t("settings.general-information-tab")}</h3> | ||||
| 
 | ||||
| {#if data.user.deleted} | ||||
| 	<div class="row mb-3"> | ||||
| 		{#if !data.user.suspended} | ||||
| 			<div class="col-md"> | ||||
| 				<h4>{$t("settings.reactivate-header")}</h4> | ||||
| 				<p> | ||||
| 					{$t("settings.reactivate-explanation")} | ||||
| 				</p> | ||||
| 				<a href="/settings/reactivate" class="btn btn-success"> | ||||
| 					{$t("settings.reactivate-button")} | ||||
| 				</a> | ||||
| 			</div> | ||||
| 		{/if} | ||||
| 		<div class="col-md"> | ||||
| 			<h4>{$t("settings.force-delete-header")}</h4> | ||||
| 			<p> | ||||
| 				{$t("settings.force-delete-explanation")} | ||||
| 				<strong> | ||||
| 					{$t("settings.force-delete-warning")} | ||||
| 				</strong> | ||||
| 			</p> | ||||
| 			<a href="/settings/force-delete" class="btn btn-danger"> | ||||
| 				{$t("settings.force-delete-button")} | ||||
| 			</a> | ||||
| 		</div> | ||||
| 	</div> | ||||
| {/if} | ||||
| 
 | ||||
| <div class="row mb-3"> | ||||
| 	<div class="col-md-9"> | ||||
| 		<h5>Change your username</h5> | ||||
| 		<h5>{$t("settings.change-username-header")}</h5> | ||||
| 		<form method="POST" action="?/changeUsername" use:enhance> | ||||
| 			<FormGroup class="mb-3"> | ||||
| 				<InputGroup class="m-1 mt-3 w-md-75"> | ||||
|  | @ -80,6 +108,13 @@ | |||
| 	<a class="btn btn-danger" href="/settings/force-log-out">{$t("settings.force-log-out-button")}</a> | ||||
| </div> | ||||
| 
 | ||||
| {#if !data.user.deleted} | ||||
| 	<div class="mb-3"> | ||||
| 		<h4>Delete your account</h4> | ||||
| 		<p></p> | ||||
| 	</div> | ||||
| {/if} | ||||
| 
 | ||||
| <div> | ||||
| 	<h4>{$t("settings.table-title")}</h4> | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,23 @@ | |||
| import { fastRequest } from "$api"; | ||||
| import ApiError, { ErrorCode } from "$api/error"; | ||||
| import { redirect } from "@sveltejs/kit"; | ||||
| 
 | ||||
| export const load = async ({ parent, fetch, cookies }) => { | ||||
| 	const { meUser } = await parent(); | ||||
| 	if (!meUser) redirect(303, "/"); | ||||
| 
 | ||||
| 	if (meUser.suspended || !meUser.deleted) | ||||
| 		throw new ApiError({ | ||||
| 			message: "You cannot use this page.", | ||||
| 			status: 403, | ||||
| 			code: ErrorCode.Forbidden, | ||||
| 		}); | ||||
| 
 | ||||
| 	await fastRequest("POST", "/self-delete/undelete", { | ||||
| 		fetch, | ||||
| 		cookies, | ||||
| 		isInternal: true, | ||||
| 	}); | ||||
| 
 | ||||
| 	return { user: meUser! }; | ||||
| }; | ||||
|  | @ -0,0 +1,20 @@ | |||
| <script lang="ts"> | ||||
| 	import { t } from "$lib/i18n"; | ||||
| 	import type { PageData } from "./$types"; | ||||
| 
 | ||||
| 	type Props = { data: PageData }; | ||||
| 	let { data }: Props = $props(); | ||||
| </script> | ||||
| 
 | ||||
| <div class="w-lg-75 mx-auto"> | ||||
| 	<h3>{$t("settings.reactivated-header")}</h3> | ||||
| 
 | ||||
| 	<p>{$t("settings.reactivated-explanation")}</p> | ||||
| 
 | ||||
| 	<div class="btn-group"> | ||||
| 		<a href="/settings" class="btn btn-primary">{$t("edit-profile.back-to-settings-tab")}</a> | ||||
| 		<a href="/@{data.user.username}" class="btn btn-secondary"> | ||||
| 			{$t("error.back-to-profile-button")} | ||||
| 		</a> | ||||
| 	</div> | ||||
| </div> | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue