Skip to content

Commit

Permalink
feat: implement user registration
Browse files Browse the repository at this point in the history
  • Loading branch information
xynydev committed Oct 12, 2024
1 parent 2cd5cdd commit 90faeca
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 20 deletions.
12 changes: 6 additions & 6 deletions src/hooks.server.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { dev } from '$app/environment';

export async function handle({ event, resolve }) {
function setAssumeLoggedIn(value: boolean) {
event.cookies.set('assumeLoggedIn', value.toString(), {
function setStatus(value: string) {
event.cookies.set('status', value, {
path: '/',
httpOnly: false,
sameSite: 'strict',
Expand All @@ -20,7 +20,7 @@ export async function handle({ event, resolve }) {
})
});
if (res.ok) {
setAssumeLoggedIn(true);
setStatus('assumeLoggedIn');
} else {
const refreshToken = event.cookies.get('refreshToken');
if (refreshToken) {
Expand All @@ -46,14 +46,14 @@ export async function handle({ event, resolve }) {
secure: !dev,
maxAge: 60 * 60 * 24 * 30 // 30 days
});
setAssumeLoggedIn(true);
setStatus('assumeLoggedIn');
} else {
setAssumeLoggedIn(false);
setStatus('assumeLoggedOut');
}
}
}
} else {
setAssumeLoggedIn(false);
setStatus('assumeLoggedOut');
}
return await resolve(event);
}
2 changes: 1 addition & 1 deletion src/lib/components/custom/MobileMenu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<div class="flex flex-col gap-4">
<div class="grid gap-4 min-[400px]:grid-cols-2">
<span>
{#if cookies.assumeLoggedIn !== 'true'}
{#if cookies.status !== 'assumeLoggedIn'}
Sign in to start curating
{:else}
Logged in as <em>{cookies.username}</em>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/custom/SignInButton.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
let cookies = getCookies();
</script>

{#if cookies.assumeLoggedIn !== 'true'}
{#if cookies.status !== 'assumeLoggedIn'}
<Button href="/account" class="max-w-min px-6">
<RiUserLine class="mr-2 min-h-5 min-w-5 text-white dark:text-black" /> Sign In
</Button>
Expand Down
18 changes: 18 additions & 0 deletions src/lib/components/ui/tabs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Tabs as TabsPrimitive } from "bits-ui";
import Content from "./tabs-content.svelte";
import List from "./tabs-list.svelte";
import Trigger from "./tabs-trigger.svelte";

const Root = TabsPrimitive.Root;

export {
Root,
Content,
List,
Trigger,
//
Root as Tabs,
Content as TabsContent,
List as TabsList,
Trigger as TabsTrigger,
};
21 changes: 21 additions & 0 deletions src/lib/components/ui/tabs/tabs-content.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script lang="ts">
import { Tabs as TabsPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
type $$Props = TabsPrimitive.ContentProps;
let className: $$Props["class"] = undefined;
export let value: $$Props["value"];
export { className as class };
</script>

<TabsPrimitive.Content
class={cn(
"ring-offset-background focus-visible:ring-ring mt-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
className
)}
{value}
{...$$restProps}
>
<slot />
</TabsPrimitive.Content>
19 changes: 19 additions & 0 deletions src/lib/components/ui/tabs/tabs-list.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts">
import { Tabs as TabsPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
type $$Props = TabsPrimitive.ListProps;
let className: $$Props["class"] = undefined;
export { className as class };
</script>

<TabsPrimitive.List
class={cn(
"bg-muted text-muted-foreground inline-flex h-10 items-center justify-center rounded-md p-1",
className
)}
{...$$restProps}
>
<slot />
</TabsPrimitive.List>
23 changes: 23 additions & 0 deletions src/lib/components/ui/tabs/tabs-trigger.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts">
import { Tabs as TabsPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
type $$Props = TabsPrimitive.TriggerProps;
type $$Events = TabsPrimitive.TriggerEvents;
let className: $$Props["class"] = undefined;
export let value: $$Props["value"];
export { className as class };
</script>

<TabsPrimitive.Trigger
class={cn(
"ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm",
className
)}
{value}
{...$$restProps}
on:click
>
<slot />
</TabsPrimitive.Trigger>
70 changes: 67 additions & 3 deletions src/routes/(nosearch)/account/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { dev } from '$app/environment';

export const actions: Actions = {
login: async ({ request, cookies }) => {
// TODO implement login
const data = await request.formData();
const res = await fetch('https://api.mwmbl.org/api/v1/platform/token/pair', {
method: 'POST',
Expand Down Expand Up @@ -34,18 +33,83 @@ export const actions: Actions = {
secure: !dev,
maxAge: 60 * 60 * 24 // 30 days
});
cookies.set('assumeLoggedIn', 'true', {
cookies.set('status', 'assumeLoggedIn', {
path: '/',
httpOnly: false,
sameSite: 'strict',
secure: !dev,
maxAge: 60 * 60 * 24 // 1 day
});
},
register: async ({ request, cookies }) => {
const data = await request.formData();
const res = await fetch('https://api.mwmbl.org/api/v1/platform/register', {
method: 'POST',
body: JSON.stringify({
email: data.get('email'),
username: data.get('username'),
password: data.get('password')
})
});
const json = await res.json();
if (json.status === 'success') {
cookies.set('status', 'accountCreated', {
path: '/',
httpOnly: false,
sameSite: 'strict',
secure: !dev,
maxAge: 60 * 60 * 24 // 1 day
});
cookies.set('registrationMessage', json.message, {
path: '/',
httpOnly: false,
sameSite: 'strict',
secure: !dev,
maxAge: 60 * 60 * 24 // 1 day
});
} else {
cookies.set('status', 'accountCreationError', {
path: '/',
httpOnly: false,
sameSite: 'strict',
secure: !dev,
maxAge: 60 * 60 * 24 // 1 day
});
cookies.set('registrationMessage', json.message, {
path: '/',
httpOnly: false,
sameSite: 'strict',
secure: !dev,
maxAge: 60 * 60 * 24 // 1 day
});
}
},
logout: async ({ cookies }) => {
cookies.delete('refreshToken', { path: '/' });
cookies.delete('accessToken', { path: '/' });
cookies.delete('username', { path: '/' });
cookies.delete('assumeLoggedIn', { path: '/' });
cookies.delete('status', { path: '/' });
}
};

export async function load({ cookies }) {
const res = await fetch('https://api.mwmbl.org/api/v1/platform/protected', {
method: 'GET',
headers: {
Authorization: 'Bearer ' + cookies.get('accessToken')
}
});
const json = await res.json();

// the current API returns an error in JSON with the response code 200
// so we have to resort to doing this...
if (json.status === 'error') {
return {
awaitingEmailConfirmation: true
};
} else {
return {
awaitingEmailConfirmation: false
};
}
}
87 changes: 78 additions & 9 deletions src/routes/(nosearch)/account/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,22 +1,91 @@
<script>
import { Button } from '@/components/ui/button';
import * as Card from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { getCookies } from '@/cookies.svelte';
import * as Tabs from '@/components/ui/tabs';
import { getCookies } from '@/cookies.svelte';
const cookies = getCookies();
const { data } = $props();
</script>

<main class="flex w-full max-w-2xl flex-col gap-2 self-center px-6">
<h2 class="-mx-2 text-3xl">Account</h2>
<h2 class="-mx-2 text-3xl">
{#if cookies.status !== 'assumeLoggedIn'}
Sign in
{:else}
Logged in as {cookies.username}
{/if}
</h2>
<hr class="my-2" />
{#if cookies.assumeLoggedIn !== 'true'}
<form method="post" action="?/login" class="flex flex-col gap-2">
<Input type="text" name="username" placeholder="username" autocomplete="username"></Input>
<Input type="password" name="password" placeholder="Password" autocomplete="password"></Input>
<Button class="max-w-32" type="submit">Log in</Button>
</form>
{#if cookies.status !== 'assumeLoggedIn'}
{#if cookies.status === 'accountCreated'}
<Card.Root class="p-4 outline outline-green-100 dark:outline-green-900">
{cookies.registrationMessage.replaceAll('%20', ' ')}
</Card.Root>
{:else if cookies.status === 'accountCreationError'}
<Card.Root class="p-4 outline outline-red-100 dark:outline-red-900">
{cookies.registrationMessage.replaceAll('%20', ' ')}
</Card.Root>
{/if}
<Tabs.Root value="Log in" class="Log in">
<Tabs.List class="w-full rounded-2xl">
<Tabs.Trigger value="Log in" class="w-full rounded-xl">Log in</Tabs.Trigger>
<Tabs.Trigger value="Register" class="w-full rounded-xl">Register</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="Log in">
<div class="mb-2 text-unemphasized-2">Log in to an existing account.</div>
<form method="post" action="?/login" class="flex flex-col gap-2">
<Input
required
type="text"
name="username"
placeholder="Username"
autocomplete="username"
/>
<Input
required
type="password"
name="password"
placeholder="Password"
autocomplete="password"
/>
<Button class="max-w-32" type="submit">Log in</Button>
</form>
</Tabs.Content>
<Tabs.Content value="Register">
<div class="mb-2 text-unemphasized-2">Create a new account.</div>
<form method="post" action="?/register" class="flex flex-col gap-2">
<Input
required
type="text"
name="username"
placeholder="Username"
autocomplete="username"
/>
<Input required type="text" name="email" placeholder="Email" autocomplete="email" />
<Input
required
type="password"
name="password"
placeholder="Password"
autocomplete="password"
/>
<Button class="max-w-32" type="submit">Register</Button>
</form>
</Tabs.Content>
</Tabs.Root>
{:else}
Logged in as {cookies.username}.
{#if data.awaitingEmailConfirmation}
<Card.Root class="p-4 outline outline-red-100 dark:outline-red-900">
Awaiting email confirmation, please check your email address.
</Card.Root>
{:else}
<Card.Root class="p-4 outline outline-green-100 dark:outline-green-900">
Your email address has been confirmed. Nice!
</Card.Root>
{/if}
<form method="post" action="?/logout">
<Button class="max-w-32" type="submit">Log out</Button>
</form>
Expand Down

0 comments on commit 90faeca

Please sign in to comment.