feat: add Clerk Auth (#43)

This commit is contained in:
Mostapha El Sabah 2025-01-04 21:24:47 -05:00 committed by GitHub
parent 1c5b37b24b
commit ed2e18310e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 152 additions and 248 deletions

View file

@ -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>

View file

@ -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 },
};
}

View file

@ -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;