From 6061506f2ea0b5023d931cefa7d36d69ee02c320 Mon Sep 17 00:00:00 2001 From: Marcel <65048232+dromzeh@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:31:43 +0100 Subject: [PATCH] relocate prisma and lucia config --- package.json | 9 +- pnpm-lock.yaml | 54 +++++++++++- prisma/schema.prisma | 189 +++++++++++++++++++++++++++++++++++++++++ src/lib/auth/lucia.ts | 37 ++++++++ src/lib/auth/prisma.ts | 9 ++ src/lucia.d.ts | 18 ++++ 6 files changed, 312 insertions(+), 4 deletions(-) create mode 100644 prisma/schema.prisma create mode 100644 src/lib/auth/lucia.ts create mode 100644 src/lib/auth/prisma.ts create mode 100644 src/lucia.d.ts diff --git a/package.json b/package.json index e12f89e4..7a431bc4 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,14 @@ "name": "wanderer-moe-api", "version": "1.0.1b", "scripts": { - "prettier": "prettier --write .", + "prettier:fmt": "prettier --write .", "dev": "wrangler dev --remote", "publish": "wrangler publish --minify", "lint": "eslint . --ext .ts", "prettier:check": "prettier --check .", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "prisma:generate": "prisma generate", + "prisma:push": "prisma db push" }, "devDependencies": { "@cloudflare/workers-types": "^4.20230710.1", @@ -19,11 +21,14 @@ }, "private": true, "dependencies": { + "@lucia-auth/adapter-prisma": "^3.0.0", "@planetscale/database": "^1.8.0", "@prisma/client": "^5.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0", "itty-router": "^4.0.14", + "lucia": "^2.0.0", "prettier": "^3.0.0", + "prisma": "^5.1.0", "render2": "^1.2.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ba6392b0..c52558db 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,21 +5,30 @@ settings: excludeLinksFromLockfile: false dependencies: + "@lucia-auth/adapter-prisma": + specifier: ^3.0.0 + version: 3.0.0(@prisma/client@5.0.0)(lucia@2.0.0) "@planetscale/database": specifier: ^1.8.0 version: 1.8.0 "@prisma/client": specifier: ^5.0.0 - version: 5.0.0 + version: 5.0.0(prisma@5.1.0) "@typescript-eslint/eslint-plugin": specifier: ^6.0.0 version: 6.0.0(@typescript-eslint/parser@6.0.0)(eslint@8.45.0)(typescript@5.1.6) itty-router: specifier: ^4.0.14 version: 4.0.14 + lucia: + specifier: ^2.0.0 + version: 2.0.0 prettier: specifier: ^3.0.0 version: 3.0.0 + prisma: + specifier: ^5.1.0 + version: 5.1.0 render2: specifier: ^1.2.1 version: 1.2.1 @@ -487,6 +496,19 @@ packages: integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==, } + /@lucia-auth/adapter-prisma@3.0.0(@prisma/client@5.0.0)(lucia@2.0.0): + resolution: + { + integrity: sha512-qrFA5IID4AulINQbLQLQPIXqE9+M3zjmN558VDhrS3Y7Fdn5dyObPbHijUWw7lGYgOrhxDox9UUG8oyZ3+D1MA==, + } + peerDependencies: + "@prisma/client": ^4.2.0 || ^5.0.0 + lucia: ^2.0.0 + dependencies: + "@prisma/client": 5.0.0(prisma@5.1.0) + lucia: 2.0.0 + dev: false + /@nodelib/fs.scandir@2.1.5: resolution: { @@ -522,7 +544,7 @@ packages: engines: { node: ">=16" } dev: false - /@prisma/client@5.0.0: + /@prisma/client@5.0.0(prisma@5.1.0): resolution: { integrity: sha512-XlO5ELNAQ7rV4cXIDJUNBEgdLwX3pjtt9Q/RHqDpGf43szpNJx2hJnggfFs7TKNx0cOFsl6KJCSfqr5duEU/bQ==, @@ -536,6 +558,7 @@ packages: optional: true dependencies: "@prisma/engines-version": 4.17.0-26.6b0aef69b7cdfc787f822ecd7cdc76d5f1991584 + prisma: 5.1.0 dev: false /@prisma/engines-version@4.17.0-26.6b0aef69b7cdfc787f822ecd7cdc76d5f1991584: @@ -545,6 +568,14 @@ packages: } dev: false + /@prisma/engines@5.1.0: + resolution: + { + integrity: sha512-HqaFsnPmZOdMWkPq6tT2eTVTQyaAXEDdKszcZ4yc7DGMBIYRP6j/zAJTtZUG9SsMV8FaucdL5vRyxY/p5Ni28g==, + } + requiresBuild: true + dev: false + /@types/json-schema@7.0.12: resolution: { @@ -1700,6 +1731,13 @@ packages: dependencies: yallist: 4.0.0 + /lucia@2.0.0: + resolution: + { + integrity: sha512-WRBMoZIgTHH6y2bAEHZWgWcMH6tDsQ+wf45juUgmn3ycjipn/e6OGpWki4XSjEuRm50WXghH+2EF9LCjCHUsUw==, + } + dev: false + /magic-string@0.25.9: resolution: { @@ -2002,6 +2040,18 @@ packages: } dev: true + /prisma@5.1.0: + resolution: + { + integrity: sha512-wkXvh+6wxk03G8qwpZMOed4Y3j+EQ+bMTlvbDZHeal6k1E8QuGKzRO7DRXlE1NV0WNgOAas8kwZqcLETQ2+BiQ==, + } + engines: { node: ">=16.13" } + hasBin: true + requiresBuild: true + dependencies: + "@prisma/engines": 5.1.0 + dev: false + /pump@3.0.0: resolution: { diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 00000000..e6994ad8 --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,189 @@ +datasource db { + provider = "mysql" + url = env("DATABASE_URL") + relationMode = "prisma" +} + +generator client { + provider = "prisma-client-js" + previewFeatures = ["fullTextSearch", "fullTextIndex"] +} + +model User { + id String @id @unique + avatar_url String? + banner_url String? + username String @unique + username_colour String? + email String @unique + email_verified Int @default(0) + pronouns String? + verified Int @default(0) + bio String? @default("") + assets Assets[] + date_joined DateTime + role RoleNames @default(USER) + self_assignable_tags SelfAssignableTag[] + socials_connections SocialsConnection[] + saved_oc_generators SavedOCGenerators[] + auth_session Session[] + auth_key Key[] + + // relations + followers Follower[] @relation("FollowerToUser") + following Following[] @relation("FollowingToUser") +} + +model Session { + id String @id @unique + user_id String + active_expires BigInt + idle_expires BigInt + user User @relation(references: [id], fields: [user_id], onDelete: Cascade) + + @@index([user_id]) +} + +model Key { + id String @id @unique + hashed_password String? + user_id String + user User @relation(references: [id], fields: [user_id], onDelete: Cascade) + + @@index([user_id]) +} + +model EmailVerificationToken { + id String @id @unique + user_id String + expires BigInt + + @@index([user_id]) +} + +model PasswordResetToken { + id String @id @unique + user_id String + expires BigInt + + @@index([user_id]) +} + +model Follower { + id String @id @unique + user_id String + follower User @relation("FollowerToUser", fields: [user_id], references: [id], onDelete: Cascade) + + @@index([user_id]) + @@map("follower") +} + +model Following { + id String @id @unique + user_id String + following User @relation("FollowingToUser", fields: [user_id], references: [id], onDelete: Cascade) + + @@index([user_id]) + @@map("following") +} + +model SelfAssignableTag { + id Int @id @default(autoincrement()) + name String + user_id String + user User @relation(fields: [user_id], references: [id], onDelete: Cascade) + + @@index([user_id]) + @@map("self_assignable_tag") +} + +model SocialsConnection { + id String @id @unique + user_id String + tiktok String? + discord String? + user User @relation(fields: [user_id], references: [id], onDelete: Cascade) + + @@index([user_id]) + @@map("socials_connection") +} + +model Games { + id Int @id @default(autoincrement()) + name String + description String + asset_count Int @default(0) + asset_categories String @default("") // e.g characters,items,splash-art etc.. + + @@index([id]) + @@index([name]) + @@map("games") +} + +model Assets { + id Int @id @default(autoincrement()) + name String + game String + asset_category String + tags AssetTagsName @default(OFFICIAL) + url String + status Status @default(PENDING) + user User @relation(fields: [uploaded_by], references: [id], onDelete: Cascade) + uploaded_by String + uploaded_date String + view_count Int @default(0) + download_count Int @default(0) + file_size Int + + @@index([id]) + @@index([name]) + @@index([game]) + @@index([status]) + @@index([tags]) + @@index([uploaded_by]) + @@map("assets") +} + +model SavedOCGenerators { + id Int @id @default(autoincrement()) + game String + data String + user User @relation(fields: [user_id], references: [id], onDelete: Cascade) + user_id String + saved_date String + + @@index([id]) + @@index([game]) + @@index([user_id]) + @@map("saved_oc_generators") +} + +// role & tag enums +enum RoleNames { + USER + CONTRIBUTOR + TRANSLATOR + STAFF + DEVELOPER + CREATOR +} + +enum SelfAssignTagsNames { + DESIGNER + DEVELOPER + ARTIST + WRITER + CONTENT_CREATOR +} + +enum AssetTagsName { + OFFICIAL + FANMADE +} + +// status enums +enum Status { + PENDING + APPROVED + REJECTED +} diff --git a/src/lib/auth/lucia.ts b/src/lib/auth/lucia.ts new file mode 100644 index 00000000..01521b1b --- /dev/null +++ b/src/lib/auth/lucia.ts @@ -0,0 +1,37 @@ +import { lucia } from "lucia"; +import { web } from "lucia/middleware"; +import { prisma as prismaAdapter } from "@lucia-auth/adapter-prisma"; +import __prisma from "./prisma"; + +export const auth = lucia({ + adapter: prismaAdapter(__prisma), + env: "DEV", + middleware: web(), + sessionExpiresIn: { + idlePeriod: 0, + activePeriod: 30 * 24 * 60 * 60 * 1000, // 30 days + }, + sessionCookie: { + expires: false, + }, + experimental: { + debugMode: true, + }, + getUserAttributes: (dbUser) => { + return { + username: dbUser.username, + usernameColour: dbUser.username_colour, + avatarUrl: dbUser.avatar_url, + bannerUrl: dbUser.banner_url, + email: dbUser.email, + emailVerified: dbUser.email_verified, + pronouns: dbUser.pronouns, + verified: dbUser.verified, + bio: dbUser.bio, + role: dbUser.role, + dateJoined: dbUser.date_joined, + }; + }, +}); + +export type Auth = typeof auth; diff --git a/src/lib/auth/prisma.ts b/src/lib/auth/prisma.ts new file mode 100644 index 00000000..7c0b486c --- /dev/null +++ b/src/lib/auth/prisma.ts @@ -0,0 +1,9 @@ +import { PrismaClient } from "@prisma/client"; + +declare global { + const __prisma: PrismaClient | undefined; +} + +const __prisma = new PrismaClient(); + +export default __prisma; diff --git a/src/lucia.d.ts b/src/lucia.d.ts new file mode 100644 index 00000000..15f81e7e --- /dev/null +++ b/src/lucia.d.ts @@ -0,0 +1,18 @@ +/// +declare namespace Lucia { + type Auth = import("./lib/auth/lucia").Auth; + type DatabaseUserAttributes = { + username: string; + username_colour: string | null; + avatar_url: string | null; + banner_url: string | null; + email: string; + email_verified: number; + pronouns: string | null; + verified: number; + bio: string | null; + role: string; + date_joined: Date; + }; + // type DatabaseSessionAttributes = {} +}