fix email length check, add unenroll api+email system
This commit is contained in:
81
mod.ts
81
mod.ts
@@ -9,6 +9,13 @@ import dbClient from 'db/client.ts';
|
||||
const alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||
const nanoid = customAlphabet(alphabet, 20);
|
||||
|
||||
const discordHeaders = new Headers();
|
||||
discordHeaders.append('Content-Type', 'application/json');
|
||||
discordHeaders.append('Accept', 'application/json');
|
||||
|
||||
const zohoHeaders = new Headers(discordHeaders);
|
||||
let zohoAuthExpireDT = new Date().getTime();
|
||||
|
||||
const genericResponse = (status: StatusCode, customText = '') =>
|
||||
new Response(customText || STATUS_TEXT[status], { status: status, statusText: STATUS_TEXT[status] });
|
||||
|
||||
@@ -31,7 +38,7 @@ Deno.serve({ port: config.api.port }, async (req) => {
|
||||
if (userNameMatches.length === 0) {
|
||||
if (body.name.length < 4 || body.name.length > 20) return genericResponse(STATUS_CODE.BadRequest, `Name too ${body.name.length < 4 ? 'short' : 'long'}.`);
|
||||
if (body.pin.length < 4 || body.pin.length > 20) return genericResponse(STATUS_CODE.BadRequest, `PIN too ${body.pin.length < 4 ? 'short' : 'long'}.`);
|
||||
if (body.email.length > 20) return genericResponse(STATUS_CODE.BadRequest, `Email too long.`);
|
||||
if (body.email.length > 255) return genericResponse(STATUS_CODE.BadRequest, `Email too long.`);
|
||||
|
||||
const id = nanoid();
|
||||
|
||||
@@ -59,19 +66,87 @@ Deno.serve({ port: config.api.port }, async (req) => {
|
||||
if (loginMatch.length === 0) 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 deleteCode = loginMatch[0].deleteCode;
|
||||
|
||||
switch (req.method) {
|
||||
case 'POST':
|
||||
if (path === '/auth' || path === '/auth/') {
|
||||
return genericResponse(STATUS_CODE.OK, JSON.stringify({ id, hasEmail: email.length > 0 }));
|
||||
return genericResponse(STATUS_CODE.OK, JSON.stringify({ id, hasEmail }));
|
||||
}
|
||||
break;
|
||||
case 'PUT':
|
||||
break;
|
||||
case 'DELETE':
|
||||
if (path === '/unenroll' || '/unenroll/') {
|
||||
//
|
||||
if (!hasEmail || body.deleteCode.trim() === deleteCode) {
|
||||
let deleteFailure = false;
|
||||
|
||||
await dbClient.execute('DELETE FROM plans WHERE ownerId = ?', [id]).catch(() => {
|
||||
deleteFailure = true;
|
||||
});
|
||||
if (deleteFailure) return genericResponse(STATUS_CODE.InternalServerError, "Couldn't delete plans.");
|
||||
|
||||
await dbClient.execute('DELETE FROM users WHERE id = ?', [id]).catch(() => {
|
||||
deleteFailure = true;
|
||||
});
|
||||
if (deleteFailure) return genericResponse(STATUS_CODE.InternalServerError, "Couldn't delete user.");
|
||||
|
||||
return genericResponse(STATUS_CODE.OK, 'Deleted user and plans.');
|
||||
} else if (hasEmail && !deleteCode) {
|
||||
let updateFailure = false;
|
||||
|
||||
const newDeleteCode = nanoid();
|
||||
await dbClient.execute('UPDATE users SET deleteCode = ? WHERE id = ?', [newDeleteCode, id]).catch(() => {
|
||||
updateFailure = true;
|
||||
});
|
||||
if (updateFailure) return genericResponse(STATUS_CODE.InternalServerError, "Couldn't set deleteCode.");
|
||||
|
||||
const nowDT = new Date().getTime();
|
||||
let fetchFailed = false;
|
||||
if (zohoAuthExpireDT < nowDT) {
|
||||
const getNewAuthToken = await fetch(
|
||||
`https://accounts.zoho.com/oauth/v2/token?client_id=${config.email.clientId}&client_secret=${config.email.clientSecret}&grant_type=client_credentials&scope=ZohoMail.messages.CREATE`,
|
||||
{ method: 'POST' },
|
||||
).catch(() => {
|
||||
fetchFailed = true;
|
||||
});
|
||||
if (fetchFailed || !getNewAuthToken) return genericResponse(STATUS_CODE.InternalServerError, "Couldn't get auth token.");
|
||||
|
||||
const newAuthToken = await getNewAuthToken.json();
|
||||
zohoHeaders.set('Authorization', `Zoho-oauthtoken ${newAuthToken.access_token}`);
|
||||
zohoAuthExpireDT = nowDT + newAuthToken.expires_in * 1000 - 600000;
|
||||
}
|
||||
|
||||
const sendEmailReq = await fetch(`https://mail.zoho.com/api/accounts/${config.email.accountId}/messages`, {
|
||||
method: 'POST',
|
||||
headers: zohoHeaders,
|
||||
body: JSON.stringify({
|
||||
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.<br/><br/>Please use the following Delete Code to delete your account:<br/><br/>${newDeleteCode}`,
|
||||
}),
|
||||
}).catch(() => {
|
||||
fetchFailed = true;
|
||||
});
|
||||
if (fetchFailed || !sendEmailReq) return genericResponse(STATUS_CODE.InternalServerError, "Couldn't send email.");
|
||||
|
||||
const sentEmail = await sendEmailReq.json();
|
||||
if (sentEmail.status.code !== 200) return genericResponse(STATUS_CODE.InternalServerError, 'Failed to send email.');
|
||||
|
||||
const maskedEmail = `${email.slice(0, 2)}***@***${email.slice(-5)}`;
|
||||
fetch(config.discordWebhook, {
|
||||
method: 'POST',
|
||||
headers: discordHeaders,
|
||||
body: JSON.stringify({ content: `Delete code email has been sent to ${maskedEmail}` }),
|
||||
}).catch(() => {});
|
||||
return genericResponse(STATUS_CODE.PreconditionFailed, `Please resubmit with the confirmation code emailed to "${maskedEmail}".`);
|
||||
} else if (hasEmail && body.deleteCode !== deleteCode) {
|
||||
return genericResponse(STATUS_CODE.BadRequest, 'Invalid delete code.');
|
||||
} else {
|
||||
return genericResponse(STATUS_CODE.InternalServerError, 'How are you here?');
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user