Skip to content

Commit

Permalink
feat[LUCIA]: Setup auth
Browse files Browse the repository at this point in the history
Bug: need to fix react cache and remove auth package from the packages
  • Loading branch information
parazeeknova committed Oct 5, 2024
1 parent 17d1535 commit 122588c
Show file tree
Hide file tree
Showing 7 changed files with 598 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@
},
"[dockerfile]": {
"editor.defaultFormatter": "ms-azuretools.vscode-docker"
},
"[prisma]": {
"editor.defaultFormatter": "Prisma.prisma"
}
}
79 changes: 79 additions & 0 deletions packages/auth/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { PrismaAdapter } from "@lucia-auth/adapter-prisma";
import prisma from "@zephyr/db/prisma";
import { Lucia, type Session, type User } from "lucia";
import { cookies } from "next/headers";
import { cache } from "react";

const adapter = new PrismaAdapter(prisma.session, prisma.user);

export const lucia = new Lucia(adapter, {
sessionCookie: {
expires: false,
attributes: {
secure: process.env.NODE_ENV === "production"
}
},
getUserAttributes(databaseUserAttributes) {
return {
id: databaseUserAttributes.id,
username: databaseUserAttributes.username,
displayName: databaseUserAttributes.displayName,
avatarUrl: databaseUserAttributes.avatarUrl,
googleId: databaseUserAttributes.googleId
};
}
});

declare module "lucia" {
interface Register {
Lucia: typeof lucia;
DatabaseUserAttributes: DatabaseUserAttributes;
}
}

interface DatabaseUserAttributes {
id: string;
username: string;
displayName: string;
avatarUrl: string | null;
googleId: string | null;
}

export const validateRequest = cache(
async (): Promise<
{ user: User; session: Session } | { user: null; session: null }
> => {
const sessionId = cookies().get(lucia.sessionCookieName)?.value ?? null;

if (!sessionId) {
return {
user: null,
session: null
};
}

const result = await lucia.validateSession(sessionId);

try {
// biome-ignore lint/complexity/useOptionalChain: <explanation>
if (result.session && result.session.fresh) {
const sessionCookie = lucia.createSessionCookie(result.session.id);
cookies().set(
sessionCookie.name,
sessionCookie.value,
sessionCookie.attributes
);
}
if (!result.session) {
const sessionCookie = lucia.createBlankSessionCookie();
cookies().set(
sessionCookie.name,
sessionCookie.value,
sessionCookie.attributes
);
}
} catch {}

return result;
}
);
21 changes: 21 additions & 0 deletions packages/auth/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@zephyr/auth",
"version": "0.0.1",
"license": "AGPL-3.0",
"private": true,
"dependencies": {
"@lucia-auth/adapter-prisma": "^4.0.1",
"@zephyr/db": "workspace:*",
"i": "^0.3.7",
"lucia": "^3.2.0",
"next": "15.0.0-rc.0"
},
"devDependencies": {
"@types/node": "^22.7.4",
"@types/react": "^18.3.11",
"@zephyr/config": "workspace:*",
"react": "19.0.0-rc-459fd418-20241001",
"ts-node": "^10.9.2",
"typescript": "^5.6.2"
}
}
9 changes: 9 additions & 0 deletions packages/auth/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "@zephyr/config/base.tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"noEmit": false,
"outDir": "dist",
"baseUrl": "."
}
}
File renamed without changes.
59 changes: 56 additions & 3 deletions packages/db/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,65 @@
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
provider = "prisma-client-js"
provider = "prisma-client-js"
previewFeatures = ["fullTextSearch"]
}

datasource db {
provider = "postgresql"
url = env("POSTGRES_PRISMA_URL") // uses connection pooling
provider = "postgresql"
url = env("POSTGRES_PRISMA_URL") // uses connection pooling
directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection
}

// User model
model User {
id String @id
username String @unique
displayName String
email String? @unique
passwordHash String?
googleId String? @unique
avatarUrl String?
bio String?
sessions Session[]
posts Post[]
following Follow[] @relation("Following")
followers Follow[] @relation("Followers")
createdAt DateTime @default(now())
@@map("users")
}

// Session model
model Session {
id String @id
userId String
expiresAt DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("sessions")
}

// Follow model
model Follow {
followerId String
follower User @relation("Following", fields: [followerId], references: [id], onDelete: Cascade)
followingId String
following User @relation("Followers", fields: [followingId], references: [id], onDelete: Cascade)
@@unique([followerId, followingId])
@@map("follows")
}

// Post model
model Post {
id String @id @default(cuid())
content String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@map("posts")
}
Loading

0 comments on commit 122588c

Please sign in to comment.