diff options
| author | Mohamed Bassem <me@mbassem.com> | 2025-11-30 00:27:07 +0000 |
|---|---|---|
| committer | Mohamed Bassem <me@mbassem.com> | 2025-11-30 00:27:20 +0000 |
| commit | e4f434e730f4bb683523326f8e6fbeaffa0ab439 (patch) | |
| tree | 5f92398faf33576d3f8f63993f5d54fd0a07eb38 | |
| parent | d6d319d3a89466d0f0766d8ef81ba962b64143d6 (diff) | |
| download | karakeep-e4f434e730f4bb683523326f8e6fbeaffa0ab439.tar.zst | |
fix: fix bypass email verification in apiKey.exchange
| -rw-r--r-- | packages/trpc/routers/apiKeys.test.ts | 46 | ||||
| -rw-r--r-- | packages/trpc/routers/apiKeys.ts | 10 |
2 files changed, 56 insertions, 0 deletions
diff --git a/packages/trpc/routers/apiKeys.test.ts b/packages/trpc/routers/apiKeys.test.ts index 1fd2159a..d68eaaf1 100644 --- a/packages/trpc/routers/apiKeys.test.ts +++ b/packages/trpc/routers/apiKeys.test.ts @@ -417,6 +417,52 @@ describe("API Keys Routes", () => { }), ).rejects.toThrow(/UNAUTHORIZED/); }); + + test<CustomTestContext>("rejects unverified user when email verification is enabled", async ({ + db, + }) => { + // Import User model to create an unverified user directly + const { User } = await import("../models/users"); + + // Create user with password but without email verification + await User.createRaw(db, { + name: "Unverified User", + email: "unverified@test.com", + password: await ( + await import("../auth") + ).hashPassword("password123", "test-salt"), + salt: "test-salt", + emailVerified: null, // User is not verified + }); + + // Mock serverConfig to enable email verification requirement + const originalConfig = (await import("@karakeep/shared/config")).default; + vi.spyOn( + originalConfig.auth, + "emailVerificationRequired", + "get", + ).mockReturnValue(true); + + const { createCallerFactory } = await import("../index"); + const { appRouter } = await import("./_app"); + const createCaller = createCallerFactory(appRouter); + const caller = createCaller({ + user: null, + db, + req: { ip: null }, + }); + + // Attempting to exchange should fail with verification error + await expect(() => + caller.apiKeys.exchange({ + keyName: "Extension Key", + email: "unverified@test.com", + password: "password123", + }), + ).rejects.toThrow(/verify your email/i); + + vi.restoreAllMocks(); + }); }); describe("integration scenarios", () => { diff --git a/packages/trpc/routers/apiKeys.ts b/packages/trpc/routers/apiKeys.ts index 93b7d9ec..763bc23a 100644 --- a/packages/trpc/routers/apiKeys.ts +++ b/packages/trpc/routers/apiKeys.ts @@ -131,6 +131,16 @@ export const apiKeysAppRouter = router({ } catch { throw new TRPCError({ code: "UNAUTHORIZED" }); } + + // Check if email verification is required and if the user has verified their email + if (serverConfig.auth.emailVerificationRequired && !user.emailVerified) { + throw new TRPCError({ + message: + "Please verify your email address before generating an API key", + code: "FORBIDDEN", + }); + } + return await generateApiKey(input.keyName, user.id, ctx.db); }), validate: publicProcedure |
