half login flow is working

This commit is contained in:
c0repwn3r 2023-02-21 12:11:28 -05:00
parent 0c1e843f08
commit f72cee6774
Signed by: core
GPG Key ID: FDBF740DADDCEECF
4 changed files with 116 additions and 3 deletions

22
tfweb/src/lib/cookie.ts Normal file
View File

@ -0,0 +1,22 @@
export function setCookie(name: string, value: string, expires: number) {
const d = new Date();
d.setTime(d.getTime() + expires);
const expires_at = "expires="+ d.toUTCString();
document.cookie = name + "=" + value + ";" + expires_at + ";path=/";
}
function getCookie(name: string): string {
const name_with_equals = name + "=";
const decodedCookie = decodeURIComponent(document.cookie);
const ca = decodedCookie.split(';');
for(let i = 0; i <ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name_with_equals) == 0) {
return c.substring(name_with_equals.length, c.length);
}
}
return "";
}

View File

@ -16,6 +16,8 @@
"prompt": "What's your email?",
"actionButtonText": "Log in",
"createaccount": "create an account",
"sentMagicLink": "Check your email!",
"magicLinkExplainer": "We sent you a link, click on it to continue logging in.",
"apierror": {
"authorization was provided but it is expired or invalid": "User does not exist, maybe consider creating an account?",
"xhrerror": "unable to contact server, please try again later"
@ -34,6 +36,16 @@
"magiclink": {
"loadtitle": "Verifying magic link...",
"loadsubtitle": "Hang on while we check this link."
"loadsubtitle": "Hang on while we check this link.",
"failed": "Unable to verify magic link",
"finished": "Magic link verified!",
"redirecting": "Redirecting...",
"missing_email": "Your request didn't contain your email. Make sure you have the entire link.",
"missing_token": "Your request didn't contain your auth token. Make sure you have the entire link.",
"tryAgain": "Try logging in again?",
"apierror": {
"unable to parse the request body, is it properly formatted?": "There was an error processing your request, please try again later.",
"this token is invalid - no rows returned by a query that expected to return at least one row": "This token is invalid or has expired."
}
}
}

View File

@ -64,7 +64,7 @@
<form class="mt-5" action="#" method="POST" on:submit|preventDefault={generateMagicLink}>
<div class="-space-y-px rounded-md shadow-sm">
<label for="email" class="sr-only">{t('login.prompt')}</label>
<input id="email"
<input bind:value={email} id="email"
class="dark:bg-slate-500 bg-gray-200 w-full rounded px-3 py-2 focus:outline-none focus:ring-purple-500 appearance-none">
{#if hasError}
<span class="text-red-600 text-sm">{error}</span>

View File

@ -1,8 +1,78 @@
<script lang="ts">
import {t} from "$lib/i18n";
import {API_ROOT} from "$lib/config";
import {onMount} from "svelte";
import {setCookie} from "$lib/cookie";
let isLoading = true;
let hasError = false;
let error = "";
onMount(() => {
// content loaded - start checking the api
const urlParams = new URLSearchParams(window.location.search);
if (!urlParams.has("email")) {
error = t('magiclink.missing_email');
hasError = true;
isLoading = false;
return;
} else if (!urlParams.has("token")) {
error = t('magiclink.missing_token');
hasError = true;
isLoading = false;
return;
}
let token = urlParams.get("token");
let xhr = new XMLHttpRequest();
xhr.timeout = 10000;
xhr.open('POST', `${API_ROOT}/v1/auth/verify-magic-link`);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify({
magicLinkToken: token
}));
xhr.ontimeout = () => {
hasError = true;
error = t('magiclink.apierror.timeout');
isLoading = false;
};
xhr.onload = () => {
if (xhr.status != 200) {
// error
hasError = true;
const rawerror = JSON.parse(xhr.responseText).errors[0].message;
error = t(`magiclink.apierror.${rawerror}`);
isLoading = false;
} else {
let resp = JSON.parse(xhr.responseText);
if (resp.data === undefined || resp.data.sessionToken === undefined) {
error = t("magiclink.apierror.badresponse");
hasError = true;
isLoading = false;
return;
}
let sess = resp.data.sessionToken;
// Set a really, really long expiry date. We will remove it when the server starts giving us unauthorized errors, but we don't know ahead of time what the server's expiration time is.
setCookie("sessionToken", sess, (86400 * 365));
isLoading = false;
hasError = false;
}
};
xhr.onerror = () => {
hasError = true;
error = t('magiclink.apierror.xhrerror');
isLoading = false;
};
});
</script>
<div class="flex in-h-full items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
@ -10,8 +80,17 @@
{#if isLoading}
<div>
<h1 class="font-semibold text-2xl">{t('magiclink.loadtitle')}</h1>
<h2 class="ftext-sm">{t('magiclink.loadsubtitle')}</h2>
<h2 class="text-sm">{t('magiclink.loadsubtitle')}</h2>
</div>
{:else}
{#if hasError}
<h1 class="font-semibold text-2xl">{t('magiclink.failed')}</h1>
<h2 class="text-sm">{error}</h2>
<a class="text-xs font-bold text-purple-400 dark:text-purple-600" href="/auth/login">{t('magiclink.tryAgain')}</a>
{:else}
<h1 class="font-semibold text-2xl">{t('magiclink.finished')}</h1>
<h2 class="text-sm">{t('magiclink.redirecting')}</h2>
{/if}
{/if}
</div>
</div>