diff --git a/mod.ts b/mod.ts
index 1e9b4d6..501a39f 100644
--- a/mod.ts
+++ b/mod.ts
@@ -131,13 +131,14 @@ Deno.serve({ port: config.api.port }, async (req) => {
if (!(await verify(body.pin, loginMatch[0].hash))) return genericResponse(STATUS_CODE.Forbidden, 'Invalid name/PIN combination.');
const id = loginMatch[0].id;
const email = loginMatch[0].email;
- const hasEmail = email.length > 0;
+ const hasEmail = (email ?? '').length > 0;
const deleteCode = loginMatch[0].deleteCode;
+ const deleteCodeSet = (deleteCode ?? '').length > 0;
switch (req.method) {
case 'POST':
if (path === '/auth') {
- return genericResponse(STATUS_CODE.OK, JSON.stringify({ id, hasEmail }));
+ return genericResponse(STATUS_CODE.OK, JSON.stringify({ id, hasEmail, deleteCodeSet }));
} else if (path === '/create') {
if (body.planName.trim().length > 200) return genericResponse(STATUS_CODE.BadRequest, 'Name too long.');
if (body.folder.trim() && body.folder.trim().length > 200) return genericResponse(STATUS_CODE.BadRequest, 'Folder name too long.');
@@ -258,7 +259,7 @@ Deno.serve({ port: config.api.port }, async (req) => {
fromAddress: config.email.address,
toAddress: email,
subject: 'XIVPlan+DB Delete Code',
- content: `Notice: account deletion is permanent and will delete all plans saved under your account.
Please use the following Delete Code to delete your account:
${newDeleteCode}`,
+ content: `Notice: Account deletion is permanent and will permanently delete all plans saved under your account.
Please use the following Delete Code to delete your account:
${newDeleteCode}`,
}),
}).catch(() => {
failed = true;
diff --git a/ssr/buildHome.ts b/ssr/buildHome.ts
index 9b15089..cbae338 100644
--- a/ssr/buildHome.ts
+++ b/ssr/buildHome.ts
@@ -61,6 +61,22 @@ const link=\`${config.api.publicDomain}share#\${planId}\`;
try{await navigator.clipboard.writeText(link);alert('Link copied to clipboard');}
catch (error){prompt('Failed to copy to clipboard, please select and copy the link below:',link);}
}
+function deleteAccount(){
+const userName=prompt('Please enter your username:')
+if(!userName.trim()){return;}
+const userPin=prompt('Please enter your PIN:');
+if(!userPin.trim()){return;}
+if(!confirm('Are you sure you want to delete your account? This is permanent and irreversible, and will delete all plans saved to your account as well.')){return;}
+fetch('/api/auth',{method:'POST',body:JSON.stringify({name:userName.trim(),pin:userPin.trim()})})
+.catch((e)=>{e.text().then((text)=>{alert(text);});})
+.then((r) => {if(r.status===200){r.json().then((j)=>{
+let deleteCode='';if(j.hasEmail&&j.deleteCodeSet)deleteCode=prompt('Please enter the Delete Code emailed to you (if you don\'t see it, please check your spam folder):');
+if(j.hasEmail&&j.deleteCodeSet&&!deleteCode){alert('Delete code required.');return;}
+fetch('/api/unenroll',{method:'DELETE',body:JSON.stringify({name:userName.trim(),pin:userPin.trim(),deleteCode:deleteCode.trim()})})
+.catch((e)=>{e.text().then((text)=>{alert(text);});})
+.then((r) => {if(r.status===200){alert('Account and plans deleted.');window.location.reload();}else{r.text().then((text)=>{alert(text);});}});
+});}else{r.text().then((text)=>{alert(text);});}});
+}
This is a very basic management page. Please excuse the number of alert/prompts that will come up when you click on things as it was the quickest way to build it out.
Please note: anything modifying data will require you to enter your PIN again as both the web view you are looking at and server behind it are completely stateless for simplicity.
@@ -74,5 +90,6 @@ ${plans.map((plan) => makePlanItem(plan, false)).join('')}