feat: offer fediverse login on login page

This commit is contained in:
Sam 2023-03-16 16:39:53 +01:00
parent cf424d3ae4
commit c6484ef066
No known key found for this signature in database
GPG Key ID: B4EF20DDE721CAA1
5 changed files with 83 additions and 13 deletions

View File

@ -1,7 +1,53 @@
<script lang="ts"> <script lang="ts">
import { goto } from "$app/navigation";
import type { APIError } from "$lib/api/entities";
import { apiFetch } from "$lib/api/fetch";
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
import { userStore } from "$lib/store";
import { addToast } from "$lib/toast";
import { onMount } from "svelte";
import {
Button,
Icon,
Input,
ListGroup,
ListGroupItem,
Modal,
ModalBody,
ModalFooter,
} from "sveltestrap";
import type { PageData } from "./$types"; import type { PageData } from "./$types";
export let data: PageData; export let data: PageData;
let error: APIError | null = null;
let instance = "";
let fediDisabled = false;
let modalOpen = false;
let toggleModal = () => (modalOpen = !modalOpen);
onMount(() => {
if ($userStore) {
addToast({ header: "Error", body: "You are already logged in." });
goto("/");
}
});
const fediLogin = async () => {
fediDisabled = true;
try {
const resp = await apiFetch<{ url: string }>(
`/auth/urls/fediverse?instance=${encodeURIComponent(instance)}`,
{},
);
window.location.assign(resp.url);
} catch (e) {
error = e as APIError;
} finally {
fediDisabled = false;
}
};
</script> </script>
<svelte:head> <svelte:head>
@ -11,13 +57,35 @@
<div class="container"> <div class="container">
<h1>Log in or sign up</h1> <h1>Log in or sign up</h1>
<div class="row"> <div class="row">
<div class="col"> <div class="col-md-4">
<p> <ListGroup>
<a class="btn btn-primary" href={data.discord} role="button">Log in with Discord</a> <ListGroupItem tag="button" on:click={toggleModal}>
</p> <Icon name="mastodon" /> Log in with Fediverse
</ListGroupItem>
<ListGroupItem tag="a" href={data.discord}>
<Icon name="discord" /> Log in with Discord
</ListGroupItem>
</ListGroup>
<Modal header="Pick an instance" isOpen={modalOpen} toggle={toggleModal}>
<ModalBody>
<Input placeholder="Instance (e.g. mastodon.social)" bind:value={instance} />
{#if error}
<div class="mt-2">
<ErrorAlert {error} />
</div>
{/if}
</ModalBody>
<ModalFooter>
<Button color="primary" disabled={fediDisabled || instance === ""} on:click={fediLogin}
>Fediverse login</Button
>
</ModalFooter>
</Modal>
</div> </div>
<div class="col"> <div class="col-md">
<p>
<b>Choose an authentication provider to get started.</b> You can add more providers later.
</p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -8,6 +8,7 @@
import { userStore } from "$lib/store"; import { userStore } from "$lib/store";
import type { PageData } from "./$types"; import type { PageData } from "./$types";
import ErrorAlert from "$lib/components/ErrorAlert.svelte"; import ErrorAlert from "$lib/components/ErrorAlert.svelte";
import { addToast } from "$lib/toast";
interface SignupResponse { interface SignupResponse {
user: MeUser; user: MeUser;
@ -21,6 +22,7 @@
localStorage.setItem("pronouns-token", data.token); localStorage.setItem("pronouns-token", data.token);
localStorage.setItem("pronouns-user", JSON.stringify(data.user)); localStorage.setItem("pronouns-user", JSON.stringify(data.user));
userStore.set(data.user); userStore.set(data.user);
addToast({ header: "Logged in", body: "Successfully logged in!" });
goto("/"); goto("/");
} }
}); });
@ -42,6 +44,7 @@
localStorage.setItem("pronouns-token", resp.token); localStorage.setItem("pronouns-token", resp.token);
localStorage.setItem("pronouns-user", JSON.stringify(resp.user)); localStorage.setItem("pronouns-user", JSON.stringify(resp.user));
userStore.set(resp.user); userStore.set(resp.user);
addToast({ header: "Welcome!", body: "Signed up successfully!" });
goto("/"); goto("/");
} catch (e) { } catch (e) {
data.error = e as APIError; data.error = e as APIError;

View File

@ -33,6 +33,7 @@
const MAX_AVATAR_BYTES = 1_000_000; const MAX_AVATAR_BYTES = 1_000_000;
if (!$userStore) { if (!$userStore) {
addToast({ header: "Error", body: "You are not logged in." });
goto("/"); goto("/");
} }
@ -55,16 +56,9 @@
let modified = false; let modified = false;
$: redirectIfNoAuth($userStore);
$: modified = isModified(bio, display_name, links, names, pronouns, fields, avatar); $: modified = isModified(bio, display_name, links, names, pronouns, fields, avatar);
$: getAvatar(avatar_files).then((b64) => (avatar = b64)); $: getAvatar(avatar_files).then((b64) => (avatar = b64));
const redirectIfNoAuth = (user: MeUser | null) => {
if (!user) {
goto("/");
}
};
const isModified = ( const isModified = (
bio: string, bio: string,
display_name: string, display_name: string,

View File

@ -4,6 +4,7 @@
import { Button, ListGroup, ListGroupItem, Modal, ModalBody, ModalFooter } from "sveltestrap"; import { Button, ListGroup, ListGroupItem, Modal, ModalBody, ModalFooter } from "sveltestrap";
import { userStore } from "$lib/store"; import { userStore } from "$lib/store";
import { goto } from "$app/navigation"; import { goto } from "$app/navigation";
import { addToast } from "$lib/toast";
export let data: LayoutData; export let data: LayoutData;
@ -15,6 +16,8 @@
localStorage.removeItem("pronouns-token"); localStorage.removeItem("pronouns-token");
localStorage.removeItem("pronouns-user"); localStorage.removeItem("pronouns-user");
toggle(); toggle();
addToast({ header: "Logged out", body: "Successfully logged out!" });
goto("/"); goto("/");
}; };
</script> </script>

View File

@ -5,6 +5,7 @@
import ErrorAlert from "$lib/components/ErrorAlert.svelte"; import ErrorAlert from "$lib/components/ErrorAlert.svelte";
import FallbackImage from "$lib/components/FallbackImage.svelte"; import FallbackImage from "$lib/components/FallbackImage.svelte";
import { userStore } from "$lib/store"; import { userStore } from "$lib/store";
import { addToast } from "$lib/toast";
import { Button, Icon, Modal, ModalBody, ModalFooter, ModalHeader, Table } from "sveltestrap"; import { Button, Icon, Modal, ModalBody, ModalFooter, ModalHeader, Table } from "sveltestrap";
import type { PageData } from "./$types"; import type { PageData } from "./$types";
@ -39,6 +40,7 @@
localStorage.removeItem("pronouns-token"); localStorage.removeItem("pronouns-token");
localStorage.removeItem("pronouns-user"); localStorage.removeItem("pronouns-user");
toggleDeleteOpen(); toggleDeleteOpen();
addToast({ header: "Deleted account", body: "Your account is now pending deletion." });
goto("/"); goto("/");
} catch (e) { } catch (e) {
deleteUsername = ""; deleteUsername = "";