diff --git a/apps/web/src/app.d.ts b/apps/web/src/app.d.ts index 3ba5e57..180fa66 100644 --- a/apps/web/src/app.d.ts +++ b/apps/web/src/app.d.ts @@ -4,7 +4,9 @@ import PocketBase from 'pocketbase'; declare global { namespace App { interface Locals { - pocketBase: PocketBase; + pb: PocketBase; + id: string; + email: string; } // interface Error {} // interface PageData {} diff --git a/apps/web/src/hooks.server.ts b/apps/web/src/hooks.server.ts index df29cc2..5932e62 100644 --- a/apps/web/src/hooks.server.ts +++ b/apps/web/src/hooks.server.ts @@ -1,22 +1,42 @@ -import { type Handle } from '@sveltejs/kit'; +import { redirect, type Handle } from '@sveltejs/kit'; import PocketBase from 'pocketbase'; -import { pb } from '$lib/pocketbase'; -import { PUBLIC_CLIENT_PB } from '$env/static/public'; +import { building } from '$app/environment'; +import { SERVER_PB } from '$env/static/private'; -/** @type {import('@sveltejs/kit').Handle} */ export const handle: Handle = async ({ event, resolve }) => { - event.locals.pocketBase = new PocketBase(PUBLIC_CLIENT_PB); + event.locals.id = ''; + event.locals.email = ''; + event.locals.pb = new PocketBase(SERVER_PB); - pb.set(event.locals.pocketBase); + const isAuth: boolean = event.url.pathname === '/auth'; + if (isAuth || building) { + event.cookies.set('pb_auth', '', { path: '/' }); + return await resolve(event); + } - event.locals.pocketBase.authStore.loadFromCookie(event.request.headers.get('cookie') ?? ''); + const pb_auth = event.request.headers.get('cookie') ?? ''; + event.locals.pb.authStore.loadFromCookie(pb_auth); + + if (!event.locals.pb.authStore.isValid) { + console.log('Session expired'); + throw redirect(303, '/auth'); + } + try { + const auth = await event.locals.pb + .collection('users') + .authRefresh<{ id: string; email: string }>(); + event.locals.id = auth.record.id; + event.locals.email = auth.record.email; + } catch (_) { + throw redirect(303, '/auth'); + } + + if (!event.locals.id) { + throw redirect(303, '/auth'); + } const response = await resolve(event); - - response.headers.set( - 'set-cookie', - event.locals.pocketBase.authStore.exportToCookie({ secure: false }) - ); - + const cookie = event.locals.pb.authStore.exportToCookie({ sameSite: 'lax' }); + response.headers.append('set-cookie', cookie); return response; -}; +}; \ No newline at end of file diff --git a/apps/web/src/lib/components/site/data-indicator.svelte b/apps/web/src/lib/components/site/data-indicator.svelte index 7e9deb1..6fdf8d1 100644 --- a/apps/web/src/lib/components/site/data-indicator.svelte +++ b/apps/web/src/lib/components/site/data-indicator.svelte @@ -12,7 +12,7 @@ {'{}'} - - + + diff --git a/apps/web/src/lib/components/site/icons/logo.svelte b/apps/web/src/lib/components/site/icons/logo.svelte index 60e545a..e595539 100644 --- a/apps/web/src/lib/components/site/icons/logo.svelte +++ b/apps/web/src/lib/components/site/icons/logo.svelte @@ -1,9 +1,9 @@ @@ -17,8 +17,8 @@ stroke-linecap="round" stroke-linejoin="round" > - - - - + + + + diff --git a/apps/web/src/lib/components/site/nav/user-nav.svelte b/apps/web/src/lib/components/site/nav/user-nav.svelte index 864e252..604ca3d 100644 --- a/apps/web/src/lib/components/site/nav/user-nav.svelte +++ b/apps/web/src/lib/components/site/nav/user-nav.svelte @@ -13,15 +13,15 @@
-

{user?.name}

+

{user?.name || user?.username}

{user?.email}

diff --git a/apps/web/src/lib/config/nav.ts b/apps/web/src/lib/config/nav.ts index 4867ff9..188a4ea 100644 --- a/apps/web/src/lib/config/nav.ts +++ b/apps/web/src/lib/config/nav.ts @@ -7,11 +7,6 @@ interface NavConfig { export const navConfig: NavConfig = { mainNav: [ - { - title: 'Home', - href: '/', - always: true - }, { title: 'Dashboard', href: '/dashboard', diff --git a/apps/web/src/routes/(auth)/+layout.server.ts b/apps/web/src/routes/(auth)/+layout.server.ts index 359b4bc..cfa5e18 100644 --- a/apps/web/src/routes/(auth)/+layout.server.ts +++ b/apps/web/src/routes/(auth)/+layout.server.ts @@ -2,7 +2,7 @@ import { redirect } from '@sveltejs/kit'; import type { LayoutServerLoad } from './$types'; export const load = (async ({ locals }) => { - if (locals.pocketBase.authStore.isValid) { + if (locals.pb.authStore.isValid) { throw redirect(303, '/'); } diff --git a/apps/web/src/routes/(auth)/auth/+page.server.ts b/apps/web/src/routes/(auth)/auth/+page.server.ts new file mode 100644 index 0000000..cf2133a --- /dev/null +++ b/apps/web/src/routes/(auth)/auth/+page.server.ts @@ -0,0 +1,14 @@ +import { redirect } from '@sveltejs/kit'; +import type { Actions } from './$types'; + +export const actions = { + default: async ({ request, cookies }) => { + const form = await request.formData(); + const token = form.get('token'); + if (!token || typeof token !== 'string') { + throw redirect(303, '/auth'); + } + cookies.set('pb_auth', JSON.stringify({ token: token }), { path: '/' }); + throw redirect(303, '/'); + } +} satisfies Actions; \ No newline at end of file diff --git a/apps/web/src/routes/(auth)/auth/+page.svelte b/apps/web/src/routes/(auth)/auth/+page.svelte new file mode 100644 index 0000000..3cd065e --- /dev/null +++ b/apps/web/src/routes/(auth)/auth/+page.svelte @@ -0,0 +1,29 @@ + + +
+ \ No newline at end of file diff --git a/apps/web/src/routes/(auth)/login/+page.server.ts b/apps/web/src/routes/(auth)/login/+page.server.ts deleted file mode 100644 index e09d7c9..0000000 --- a/apps/web/src/routes/(auth)/login/+page.server.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { error, redirect } from '@sveltejs/kit'; -import type { Actions } from './$types'; - -export const actions: Actions = { - login: async ({ request, locals }: { request: Request; locals: App.Locals }) => { - const body = Object.fromEntries(await request.formData()); - - try { - const email = body.email.toString(); - const password = body.password.toString(); - await locals.pocketBase.collection('users').authWithPassword(email, password); - if (!locals.pocketBase?.authStore?.model?.verified) { - locals.pocketBase.authStore.clear(); - return { - notVerified: true - }; - } - } catch (err) { - console.log('Error: ', err); - throw error(500, 'Something went wrong logging in'); - } - - throw redirect(303, '/'); - }, - // TODO: Implement Oauth2 Auth - oauth2: async ({ request, locals }: { request: Request; locals: App.Locals }) => { - const body = Object.fromEntries(await request.formData()); - const provider = body.provider.toString(); - await locals.pocketBase.collection('users').authWithOAuth2({ provider: provider }); - } -}; diff --git a/apps/web/src/routes/(auth)/login/+page.svelte b/apps/web/src/routes/(auth)/login/+page.svelte deleted file mode 100644 index 42a480b..0000000 --- a/apps/web/src/routes/(auth)/login/+page.svelte +++ /dev/null @@ -1,168 +0,0 @@ - - -
-
-
-

Log into your account

-

- Enter your email and password below to log into your account -

-
-
- { - isLoading = true; - }} - > -
-
- - -
-
- - -
- -
- {#if form?.notVerified} - - - You must verify your email before you can login. - - {/if} - -
{ - isLoading = true; - }} - > - {#if providers.length} -
-
- -
-
- Or continue with -
-
-
- -
- -
- {#if providers.length > 1} -
- -
- - - - - - Login Providers - {#each providersWithIcons as provider} - {#if provider.name !== currentProvider.name} - (currentProvider = provider)} - > - {#if provider.icon === undefined} - {provider.name} - {:else} - - {/if} - {provider.displayName} - - {/if} - {/each} - - -
-
- {/if} -
- {/if} -
-
-

- Don't have an account? Sign up.
- Forgot password? Reset password. -

-
-
diff --git a/apps/web/src/routes/(auth)/logout/+server.ts b/apps/web/src/routes/(auth)/logout/+server.ts index 44953cc..35e2806 100644 --- a/apps/web/src/routes/(auth)/logout/+server.ts +++ b/apps/web/src/routes/(auth)/logout/+server.ts @@ -2,5 +2,5 @@ import { redirect } from '@sveltejs/kit'; export const GET = ({ locals }: { locals: App.Locals }) => { locals.pocketBase.authStore.clear(); - throw redirect(303, '/login'); + throw redirect(303, '/'); }; diff --git a/apps/web/src/routes/(auth)/register/+page.server.ts b/apps/web/src/routes/(auth)/register/+page.server.ts deleted file mode 100644 index dc1dbdd..0000000 --- a/apps/web/src/routes/(auth)/register/+page.server.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { redirect } from '@sveltejs/kit'; - -export const actions = { - default: async ({ request, locals }: { request: Request; locals: App.Locals }) => { - if (locals.pocketBase.authStore.isValid) { - return; - } - - const formData = await request.formData(); - - const name = formData.get('name'); - const email = formData.get('email'); - const password = formData.get('password'); - - try { - if (typeof name !== 'string') { - throw new Error('Name must be a string'); - } - - if (name.length === 0) { - throw new Error('Please enter a valid name'); - } - - if (typeof email !== 'string') { - throw new Error('Email must be a string'); - } - - if (email.length < 5) { - throw new Error('Please enter a valid e-mail address'); - } - - if (typeof password !== 'string') { - throw new Error('Password must be a string'); - } - - if (password.length < 8) { - throw new Error('Password must be at least 8 characters in length'); - } - - if (password !== formData.get('passwordConfirm')) { - throw new Error('Passwords do not match'); - } - - await locals.pocketBase.collection('users').create({ - email, - password, - name, - passwordConfirm: password - }); - - await locals.pocketBase.collection('users').authWithPassword(email, password); - } catch (error) { - console.error(error); - - if (!(error instanceof Error)) { - return { - name, - email, - password, - error: 'Unknown error occured when signing up user' - }; - } - - return { error: error.message, name, email, password }; - } - - throw redirect(303, '/'); - } -}; diff --git a/apps/web/src/routes/(auth)/register/+page.svelte b/apps/web/src/routes/(auth)/register/+page.svelte deleted file mode 100644 index 98750f1..0000000 --- a/apps/web/src/routes/(auth)/register/+page.svelte +++ /dev/null @@ -1,95 +0,0 @@ - - -
-
-
-

Create your account

-

Enter your details below to create a new account

-
-
-
{ - isLoading = true; - }} - > -
-
- - -
-
- - -
-
- - -
-
- - -
- -
-
-
-
- -
-
- Or continue with -
-
- -
-

- Or sign in if you already have an account.
- Forgot password? Reset password. -

-
-
diff --git a/apps/web/src/routes/(auth)/reset-password/+page.server.ts b/apps/web/src/routes/(auth)/reset-password/+page.server.ts deleted file mode 100644 index 949e62b..0000000 --- a/apps/web/src/routes/(auth)/reset-password/+page.server.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { error } from '@sveltejs/kit'; - -export const actions = { - default: async ({ request, locals }: { request: Request; locals: App.Locals }) => { - const body = Object.fromEntries(await request.formData()); - - try { - const email = body.email.toString(); - await locals.pocketBase.collection('users').requestPasswordReset(email); - return { - success: true - }; - } catch (err) { - console.log('Error: ', err); - throw error(500, 'Something went wrong'); - } - } -}; diff --git a/apps/web/src/routes/(auth)/reset-password/+page.svelte b/apps/web/src/routes/(auth)/reset-password/+page.svelte deleted file mode 100644 index f81d318..0000000 --- a/apps/web/src/routes/(auth)/reset-password/+page.svelte +++ /dev/null @@ -1,64 +0,0 @@ - - -
-
-
-

Reset password

-

- We'll send you an email with a link to reset your password. -

-
-
-
{ - isLoading = true; - return async ({ update }) => { - isLoading = false; - update(); - }; - }} - > -
-
- - -
- -
- {#if form?.success} - - - An email has been sent to reset your password. - - {/if} -
-
-
-
diff --git a/apps/web/src/routes/(dashboard)/+layout.server.ts b/apps/web/src/routes/(dashboard)/+layout.server.ts index ec58979..f1d817e 100644 --- a/apps/web/src/routes/(dashboard)/+layout.server.ts +++ b/apps/web/src/routes/(dashboard)/+layout.server.ts @@ -1,7 +1,7 @@ import { redirect } from '@sveltejs/kit'; export const load = async ({ locals }: { locals: App.Locals }) => { - if (!locals.pocketBase.authStore.isValid) { + if (!locals.pb.authStore.isValid) { throw redirect(303, '/register'); } diff --git a/apps/web/src/routes/(dashboard)/settings/account/account-form.svelte b/apps/web/src/routes/(dashboard)/settings/account/account-form.svelte index 3432e6e..59fe75d 100644 --- a/apps/web/src/routes/(dashboard)/settings/account/account-form.svelte +++ b/apps/web/src/routes/(dashboard)/settings/account/account-form.svelte @@ -2,12 +2,6 @@ import { z } from 'zod'; export const accountFormSchema = z.object({ - name: z - .string({ - required_error: 'Required.' - }) - .min(2, 'Name must be at least 2 characters.') - .max(30, 'Name must not be longer than 30 characters') }); export type AccountFormSchema = typeof accountFormSchema; @@ -31,15 +25,5 @@ form={data} debug={dev ? true : false} > - - - Name - - - This is the name that will be displayed on your profile and in emails. - - - - Update account diff --git a/apps/web/src/routes/(dashboard)/settings/profile-form.svelte b/apps/web/src/routes/(dashboard)/settings/profile-form.svelte index d7ac350..688850a 100644 --- a/apps/web/src/routes/(dashboard)/settings/profile-form.svelte +++ b/apps/web/src/routes/(dashboard)/settings/profile-form.svelte @@ -1,6 +1,12 @@