feat: add Clerk Auth (#43)
This commit is contained in:
parent
1c5b37b24b
commit
ed2e18310e
17 changed files with 152 additions and 248 deletions
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { messages } from '$lib/i18n';
|
||||
import SignOutButton from 'clerk-sveltekit/client/SignOutButton.svelte';
|
||||
|
||||
let { title, username }: { title: string; username: string } = $props();
|
||||
|
||||
|
|
@ -10,6 +11,7 @@
|
|||
<h2 class="prose prose-xl">Hestia</h2>
|
||||
<h1 class="prose prose-2xl">{title}</h1>
|
||||
<p class="prose prose-lg">{message}</p>
|
||||
<SignOutButton />
|
||||
</header>
|
||||
|
||||
<style>
|
||||
|
|
|
|||
|
|
@ -1,22 +1,55 @@
|
|||
import { redirect, type ServerLoadEvent } from '@sveltejs/kit';
|
||||
import dayjs from 'dayjs';
|
||||
import { prisma } from '../prisma';
|
||||
import { createClerkClient } from '@clerk/backend';
|
||||
import { CLERK_SECRET_KEY } from '$env/static/private';
|
||||
import { clerkClient } from 'clerk-sveltekit/server';
|
||||
import { logger } from '$lib/server/logger';
|
||||
|
||||
export async function validateSession(event: ServerLoadEvent) {
|
||||
const sessionId = event.cookies.get('auth_session');
|
||||
if (!sessionId) {
|
||||
redirect(302, '/login');
|
||||
const clerkSessionClient = createClerkClient({
|
||||
secretKey: CLERK_SECRET_KEY,
|
||||
});
|
||||
|
||||
export async function validateSession({ locals }: ServerLoadEvent) {
|
||||
if (!locals.auth.userId || !locals.auth.sessionId) {
|
||||
return redirect(307, '/login');
|
||||
}
|
||||
const session = await prisma.session.findUnique({
|
||||
where: { id: sessionId },
|
||||
include: { user: true },
|
||||
|
||||
if (!locals.auth.orgId && locals.auth.sessionId) {
|
||||
// Sign out the user if they are not associated with an organization
|
||||
await clerkSessionClient.sessions.revokeSession(locals.auth.sessionId);
|
||||
return redirect(307, '/login');
|
||||
}
|
||||
|
||||
const clerkUser = await clerkClient.users.getUser(locals.auth.userId);
|
||||
|
||||
let user = await prisma.user.findFirst({
|
||||
where: {
|
||||
clerkId: clerkUser.id,
|
||||
},
|
||||
});
|
||||
if (!session || !session.user) {
|
||||
redirect(302, '/login');
|
||||
|
||||
if (!user) {
|
||||
if (clerkUser.emailAddresses.length === 0) {
|
||||
logger.error('User has no email address');
|
||||
await clerkSessionClient.sessions.revokeSession(locals.auth.sessionId);
|
||||
|
||||
return redirect(307, '/login');
|
||||
}
|
||||
|
||||
user = await prisma.user.create({
|
||||
data: {
|
||||
clerkId: clerkUser.id,
|
||||
email: clerkUser.emailAddresses[0].emailAddress,
|
||||
name: clerkUser.fullName ?? '',
|
||||
},
|
||||
});
|
||||
|
||||
if (clerkUser.fullName === null) {
|
||||
logger.error('User has no name');
|
||||
}
|
||||
}
|
||||
const expiry = session.expiresAt;
|
||||
if (dayjs(expiry).isBefore(dayjs())) {
|
||||
redirect(302, '/login');
|
||||
}
|
||||
return session;
|
||||
|
||||
return {
|
||||
user: { name: user.name },
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
import { Lucia } from 'lucia';
|
||||
import { PrismaAdapter } from '@lucia-auth/adapter-prisma';
|
||||
import { prisma } from '$lib/server/prisma';
|
||||
|
||||
const adapter = new PrismaAdapter(prisma.session, prisma.user);
|
||||
// expect error (see next section)
|
||||
export const auth = new Lucia(adapter, {
|
||||
sessionCookie: {
|
||||
attributes: {
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
},
|
||||
},
|
||||
getUserAttributes: (attributes) => {
|
||||
return {
|
||||
email: attributes.email,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
declare module 'lucia' {
|
||||
interface Register {
|
||||
Lucia: typeof Lucia;
|
||||
DatabaseUserAttributes: DatabaseUserAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
interface DatabaseUserAttributes {
|
||||
email: string;
|
||||
}
|
||||
|
||||
export type Auth = typeof auth;
|
||||
Loading…
Add table
Add a link
Reference in a new issue