feat(frontend): working Discord login + signup
This commit is contained in:
parent
0e72097346
commit
c8b5b7e2c2
24 changed files with 287 additions and 119 deletions
17
frontend/src/routes/auth/login/+page.server.ts
Normal file
17
frontend/src/routes/auth/login/+page.server.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { apiFetch } from "$lib/api/fetch";
|
||||
import { PUBLIC_BASE_URL } from "$env/static/public";
|
||||
|
||||
export const load = async () => {
|
||||
const resp = await apiFetch<UrlsResponse>("/auth/urls", {
|
||||
method: "POST",
|
||||
body: {
|
||||
callback_domain: PUBLIC_BASE_URL,
|
||||
},
|
||||
});
|
||||
|
||||
return resp;
|
||||
};
|
||||
|
||||
interface UrlsResponse {
|
||||
discord: string;
|
||||
}
|
23
frontend/src/routes/auth/login/+page.svelte
Normal file
23
frontend/src/routes/auth/login/+page.svelte
Normal file
|
@ -0,0 +1,23 @@
|
|||
<script lang="ts">
|
||||
import type { PageData } from "./$types";
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Login - pronouns.cc</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="container">
|
||||
<h1>Log in or sign up</h1>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p>
|
||||
<a class="btn btn-primary" href={data.discord} role="button">Log in with Discord</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
35
frontend/src/routes/auth/login/discord/+page.server.ts
Normal file
35
frontend/src/routes/auth/login/discord/+page.server.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import type { APIError, MeUser } from "$lib/api/entities";
|
||||
import { apiFetch } from "$lib/api/fetch";
|
||||
import type { PageServerLoad, Actions } from "./$types";
|
||||
import { PUBLIC_BASE_URL } from "$env/static/public";
|
||||
|
||||
export const load = (async ({ locals, url }) => {
|
||||
try {
|
||||
const resp = await apiFetch<CallbackResponse>("/auth/discord/callback", {
|
||||
method: "POST",
|
||||
body: {
|
||||
callback_domain: PUBLIC_BASE_URL,
|
||||
code: url.searchParams.get("code"),
|
||||
state: url.searchParams.get("state"),
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
...resp,
|
||||
};
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
|
||||
return { error: e as APIError };
|
||||
}
|
||||
}) satisfies PageServerLoad;
|
||||
|
||||
interface CallbackResponse {
|
||||
has_account: boolean;
|
||||
token?: string;
|
||||
user?: MeUser;
|
||||
|
||||
discord?: string;
|
||||
ticket?: string;
|
||||
require_invite: boolean;
|
||||
}
|
95
frontend/src/routes/auth/login/discord/+page.svelte
Normal file
95
frontend/src/routes/auth/login/discord/+page.svelte
Normal file
|
@ -0,0 +1,95 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { Alert } from "sveltestrap";
|
||||
|
||||
import { goto } from "$app/navigation";
|
||||
import type { APIError, MeUser } from "$lib/api/entities";
|
||||
import { apiFetch } from "$lib/api/fetch";
|
||||
import { userStore } from "$lib/store";
|
||||
import type { PageData } from "./$types";
|
||||
|
||||
interface SignupResponse {
|
||||
user: MeUser;
|
||||
token: string;
|
||||
}
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
onMount(() => {
|
||||
if (data.token && data.user) {
|
||||
localStorage.setItem("pronouns-token", data.token);
|
||||
userStore.set(data.user);
|
||||
goto("/");
|
||||
}
|
||||
});
|
||||
|
||||
let username = "";
|
||||
let invite = "";
|
||||
|
||||
const signupForm = async () => {
|
||||
try {
|
||||
const resp = await apiFetch<SignupResponse>("/auth/discord/signup", {
|
||||
method: "POST",
|
||||
body: {
|
||||
ticket: data.ticket,
|
||||
username: username,
|
||||
invite_code: invite,
|
||||
},
|
||||
});
|
||||
|
||||
localStorage.setItem("pronouns-token", resp.token);
|
||||
userStore.set(resp.user);
|
||||
goto("/");
|
||||
} catch (e) {
|
||||
data.error = e as APIError;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Log in with Discord - pronouns.cc</title>
|
||||
</svelte:head>
|
||||
|
||||
<h1>Log in with Discord</h1>
|
||||
|
||||
{#if data.error}
|
||||
<Alert color="danger">
|
||||
<h4 class="alert-heading">An error occurred</h4>
|
||||
<b>{data.error.code}:</b>
|
||||
{data.error.message}
|
||||
</Alert>
|
||||
{/if}
|
||||
{#if data.ticket}
|
||||
<form on:submit|preventDefault={signupForm}>
|
||||
<div>
|
||||
<label for="discord">Discord username</label>
|
||||
<input id="discord" class="form-control" name="discord" disabled value={data.discord} />
|
||||
</div>
|
||||
<div>
|
||||
<label for="username">Username</label>
|
||||
<input id="username" class="form-control" name="username" bind:value={username} />
|
||||
</div>
|
||||
{#if data.require_invite}
|
||||
<div>
|
||||
<label for="invite">Invite code</label>
|
||||
<input
|
||||
id="invite"
|
||||
class="form-control"
|
||||
name="invite"
|
||||
bind:value={invite}
|
||||
aria-describedby="invite-help"
|
||||
/>
|
||||
<div id="invite-help" class="form-text">
|
||||
You currently need an invite code to sign up. You can get one from an existing user.
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="form-text">
|
||||
By signing up, you agree to the <a href="/page/tos">terms of service</a> and the
|
||||
<a href="/page/privacy">privacy policy</a>.
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Sign up</button>
|
||||
</form>
|
||||
{:else}
|
||||
Loading...
|
||||
{/if}
|
Loading…
Add table
Add a link
Reference in a new issue