aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2025-06-21 10:44:53 +0000
committerMohamed Bassem <me@mbassem.com>2025-06-21 10:45:36 +0000
commitf1f665f89cba21d4d448d27471d01a4d78a184ff (patch)
tree61a730db28e71bdfad5d27af976f5585fe637daa
parent6c0bcca1d5f4c72d128e8ae0298e2e896d2b2e30 (diff)
downloadkarakeep-f1f665f89cba21d4d448d27471d01a4d78a184ff.tar.zst
fix: Fix oauth creation failure due to missing UserSettings table. Fixes #1583
-rw-r--r--apps/web/package.json4
-rw-r--r--apps/web/server/auth.ts31
-rw-r--r--packages/trpc/routers/users.ts46
-rw-r--r--pnpm-lock.yaml45
4 files changed, 81 insertions, 45 deletions
diff --git a/apps/web/package.json b/apps/web/package.json
index 4d4e6dfd..ff6410f6 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -17,7 +17,7 @@
"lint:fix": "next lint --fix"
},
"dependencies": {
- "@auth/drizzle-adapter": "^1.4.2",
+ "@auth/drizzle-adapter": "~1.5.0",
"@emoji-mart/data": "^1.1.2",
"@emoji-mart/react": "^1.1.1",
"@hookform/resolvers": "^3.3.4",
@@ -67,7 +67,7 @@
"lexical": "^0.20.2",
"lucide-react": "^0.501.0",
"next": "14.2.25",
- "next-auth": "^4.24.5",
+ "next-auth": "^4.24.11",
"next-i18next": "^15.3.1",
"next-pwa": "^5.6.0",
"next-themes": "^0.3.0",
diff --git a/apps/web/server/auth.ts b/apps/web/server/auth.ts
index 67621a17..3d32f702 100644
--- a/apps/web/server/auth.ts
+++ b/apps/web/server/auth.ts
@@ -1,4 +1,4 @@
-import type { Adapter } from "next-auth/adapters";
+import { Adapter, AdapterUser } from "@auth/core/adapters";
import { DrizzleAdapter } from "@auth/drizzle-adapter";
import { and, count, eq } from "drizzle-orm";
import NextAuth, {
@@ -6,6 +6,7 @@ import NextAuth, {
getServerSession,
NextAuthOptions,
} from "next-auth";
+import { Adapter as NextAuthAdapater } from "next-auth/adapters";
import CredentialsProvider from "next-auth/providers/credentials";
import { Provider } from "next-auth/providers/index";
import requestIp from "request-ip";
@@ -19,6 +20,7 @@ import {
} from "@karakeep/db/schema";
import serverConfig from "@karakeep/shared/config";
import { logAuthenticationError, validatePassword } from "@karakeep/trpc/auth";
+import { createUserRaw } from "@karakeep/trpc/routers/users";
type UserRole = "admin" | "user";
@@ -70,6 +72,26 @@ async function isAdmin(email: string): Promise<boolean> {
return res?.role == "admin";
}
+const CustomProvider = (): Adapter => {
+ const adapter = DrizzleAdapter(db, {
+ usersTable: users,
+ accountsTable: accounts,
+ sessionsTable: sessions,
+ verificationTokensTable: verificationTokens,
+ });
+
+ return {
+ ...adapter,
+ createUser: async (user: Omit<AdapterUser, "id">) => {
+ return await createUserRaw(db, {
+ name: user.name ?? "",
+ email: user.email,
+ emailVerified: user.emailVerified,
+ });
+ },
+ };
+};
+
const providers: Provider[] = [
CredentialsProvider({
// The name to display on the sign in form (e.g. "Sign in with...")
@@ -135,12 +157,7 @@ if (oauth.wellKnownUrl) {
export const authOptions: NextAuthOptions = {
// https://github.com/nextauthjs/next-auth/issues/9493
- adapter: DrizzleAdapter(db, {
- usersTable: users,
- accountsTable: accounts,
- sessionsTable: sessions,
- verificationTokensTable: verificationTokens,
- }) as Adapter,
+ adapter: CustomProvider() as NextAuthAdapater,
providers: providers,
session: {
strategy: "jwt",
diff --git a/packages/trpc/routers/users.ts b/packages/trpc/routers/users.ts
index 3813387f..87923f94 100644
--- a/packages/trpc/routers/users.ts
+++ b/packages/trpc/routers/users.ts
@@ -31,13 +31,19 @@ import {
router,
} from "../index";
-export async function createUser(
- input: z.infer<typeof zSignUpSchema>,
- ctx: Context,
- role?: "user" | "admin",
+export async function createUserRaw(
+ db: Context["db"],
+ input: {
+ name: string;
+ email: string;
+ password?: string;
+ salt?: string;
+ role?: "user" | "admin";
+ emailVerified?: Date | null;
+ },
) {
- return ctx.db.transaction(async (trx) => {
- let userRole = role;
+ return await db.transaction(async (trx) => {
+ let userRole = input.role;
if (!userRole) {
const [{ count: userCount }] = await trx
.select({ count: count() })
@@ -45,30 +51,31 @@ export async function createUser(
userRole = userCount == 0 ? "admin" : "user";
}
- const salt = generatePasswordSalt();
try {
- const result = await trx
+ const [result] = await trx
.insert(users)
.values({
name: input.name,
email: input.email,
- password: await hashPassword(input.password, salt),
- salt,
+ password: input.password,
+ salt: input.salt,
role: userRole,
+ emailVerified: input.emailVerified,
})
.returning({
id: users.id,
name: users.name,
email: users.email,
role: users.role,
+ emailVerified: users.emailVerified,
});
// Insert user settings for the new user
await trx.insert(userSettings).values({
- userId: result[0].id,
+ userId: result.id,
});
- return result[0];
+ return result;
} catch (e) {
if (e instanceof SqliteError) {
if (e.code == "SQLITE_CONSTRAINT_UNIQUE") {
@@ -86,6 +93,21 @@ export async function createUser(
});
}
+export async function createUser(
+ input: z.infer<typeof zSignUpSchema>,
+ ctx: Context,
+ role?: "user" | "admin",
+) {
+ const salt = generatePasswordSalt();
+ return await createUserRaw(ctx.db, {
+ name: input.name,
+ email: input.email,
+ password: await hashPassword(input.password, salt),
+ salt,
+ role,
+ });
+}
+
export const usersAppRouter = router({
create: publicProcedure
.input(zSignUpSchema)
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ce81f281..5d141ed8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -507,8 +507,8 @@ importers:
apps/web:
dependencies:
'@auth/drizzle-adapter':
- specifier: ^1.4.2
- version: 1.4.2
+ specifier: ~1.5.0
+ version: 1.5.3
'@emoji-mart/data':
specifier: ^1.1.2
version: 1.1.2
@@ -657,8 +657,8 @@ importers:
specifier: 14.2.25
version: 14.2.25(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.1)
next-auth:
- specifier: ^4.24.5
- version: 4.24.6(next@14.2.25(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ specifier: ^4.24.11
+ version: 4.24.11(next@14.2.25(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
next-i18next:
specifier: ^15.3.1
version: 15.3.1(i18next@23.16.5)(next@14.2.25(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.1))(react-i18next@15.1.1(i18next@23.16.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
@@ -1512,8 +1512,8 @@ packages:
nodemailer:
optional: true
- '@auth/core@0.34.2':
- resolution: {integrity: sha512-KywHKRgLiF3l7PLyL73fjLSIBe1YNcA6sMeew4yMP6cfCWGXZrkkXd32AjRi1hlJ9nvovUBGZHvbn+LijO6ZeQ==}
+ '@auth/core@0.35.3':
+ resolution: {integrity: sha512-g6qfiqU4OtyvIEZ8J7UoIwAxEnNnLJV0/f/DW41U+4G5nhBlaCrnKhawJIJpU0D3uavXLeDT3B0BkjtiimvMDA==}
peerDependencies:
'@simplewebauthn/browser': ^9.0.1
'@simplewebauthn/server': ^9.0.2
@@ -1526,8 +1526,8 @@ packages:
nodemailer:
optional: true
- '@auth/drizzle-adapter@1.4.2':
- resolution: {integrity: sha512-rqukaT9CeWB8VOt6g2bQ6uYMHVOQIYCBkzddZXWshi8aqwLABatpRWAc+pehpcMDn0RSW/uvKMs7tkON+Bho9Q==}
+ '@auth/drizzle-adapter@1.5.3':
+ resolution: {integrity: sha512-VNyYb1hiGtorJhCjShtncjN3TKXxtwxOwphYecq8lZSVuFDLIWHhp4ZbdZDjnmkvEk8G66IpFrYW84qpt+WUIg==}
'@babel/code-frame@7.10.4':
resolution: {integrity: sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==}
@@ -6507,10 +6507,6 @@ packages:
resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
engines: {node: '>=6.6.0'}
- cookie@0.5.0:
- resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
- engines: {node: '>= 0.6'}
-
cookie@0.6.0:
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
engines: {node: '>= 0.6'}
@@ -10554,14 +10550,17 @@ packages:
resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==}
engines: {node: '>= 0.4.0'}
- next-auth@4.24.6:
- resolution: {integrity: sha512-djQt3ZEaWEIxcsuh3HTW2uuzLfXMRjHH+ugAsichlQSbH4iA5MRcgMA2HvTNvsDTDLh44tyU72+/gWsxgTbAKg==}
+ next-auth@4.24.11:
+ resolution: {integrity: sha512-pCFXzIDQX7xmHFs4KVH4luCjaCbuPRtZ9oBUjUhOk84mZ9WVPf94n87TxYI4rSRf9HmfHEF8Yep3JrYDVOo3Cw==}
peerDependencies:
- next: ^12.2.5 || ^13 || ^14
+ '@auth/core': 0.34.2
+ next: ^12.2.5 || ^13 || ^14 || ^15
nodemailer: ^6.6.5
- react: ^17.0.2 || ^18
- react-dom: ^17.0.2 || ^18
+ react: ^17.0.2 || ^18 || ^19
+ react-dom: ^17.0.2 || ^18 || ^19
peerDependenciesMeta:
+ '@auth/core':
+ optional: true
nodemailer:
optional: true
@@ -14775,7 +14774,7 @@ snapshots:
preact: 10.11.3
preact-render-to-string: 5.2.3(preact@10.11.3)
- '@auth/core@0.34.2':
+ '@auth/core@0.35.3':
dependencies:
'@panva/hkdf': 1.2.1
'@types/cookie': 0.6.0
@@ -14785,9 +14784,9 @@ snapshots:
preact: 10.11.3
preact-render-to-string: 5.2.3(preact@10.11.3)
- '@auth/drizzle-adapter@1.4.2':
+ '@auth/drizzle-adapter@1.5.3':
dependencies:
- '@auth/core': 0.34.2
+ '@auth/core': 0.35.3
transitivePeerDependencies:
- '@simplewebauthn/browser'
- '@simplewebauthn/server'
@@ -22080,8 +22079,6 @@ snapshots:
cookie-signature@1.2.2: {}
- cookie@0.5.0: {}
-
cookie@0.6.0: {}
cookie@0.7.1: {}
@@ -27300,11 +27297,11 @@ snapshots:
netmask@2.0.2: {}
- next-auth@4.24.6(next@14.2.25(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ next-auth@4.24.11(next@14.2.25(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@babel/runtime': 7.27.6
'@panva/hkdf': 1.2.1
- cookie: 0.5.0
+ cookie: 0.7.2
jose: 4.15.9
next: 14.2.25(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.1)
oauth: 0.9.15