|
1 | | -import { genAuthCode } from '@codebuff/common/util/credentials' |
2 | | -import db from '@codebuff/internal/db' |
3 | | -import * as schema from '@codebuff/internal/db/schema' |
4 | 1 | import { env } from '@codebuff/internal/env' |
5 | | -import { and, eq, gt, or, isNull } from 'drizzle-orm' |
6 | | -import { NextResponse } from 'next/server' |
7 | | -import { z } from 'zod/v4' |
8 | 2 |
|
| 3 | +import { createLoginStatusDb } from './_db' |
| 4 | +import { getLoginStatus } from './_get' |
9 | 5 | import { logger } from '@/util/logger' |
10 | 6 |
|
11 | 7 | export async function GET(req: Request) { |
12 | | - const { searchParams } = new URL(req.url) |
13 | | - const reqSchema = z.object({ |
14 | | - fingerprintId: z.string(), |
15 | | - fingerprintHash: z.string(), |
16 | | - expiresAt: z.string().transform(Number), |
| 8 | + return getLoginStatus({ |
| 9 | + req, |
| 10 | + db: createLoginStatusDb(), |
| 11 | + logger, |
| 12 | + secret: env.NEXTAUTH_SECRET, |
17 | 13 | }) |
18 | | - const result = reqSchema.safeParse({ |
19 | | - fingerprintId: searchParams.get('fingerprintId'), |
20 | | - fingerprintHash: searchParams.get('fingerprintHash'), |
21 | | - expiresAt: searchParams.get('expiresAt'), |
22 | | - }) |
23 | | - if (!result.success) { |
24 | | - return NextResponse.json( |
25 | | - { error: 'Invalid query parameters' }, |
26 | | - { status: 400 }, |
27 | | - ) |
28 | | - } |
29 | | - |
30 | | - const { fingerprintId, fingerprintHash, expiresAt } = result.data |
31 | | - |
32 | | - if (Date.now() > expiresAt) { |
33 | | - logger.info( |
34 | | - { fingerprintId, fingerprintHash, expiresAt }, |
35 | | - 'Auth code expired', |
36 | | - ) |
37 | | - return NextResponse.json( |
38 | | - { error: 'Authentication failed' }, |
39 | | - { status: 401 }, |
40 | | - ) |
41 | | - } |
42 | | - |
43 | | - const expectedHash = genAuthCode( |
44 | | - fingerprintId, |
45 | | - expiresAt.toString(), |
46 | | - env.NEXTAUTH_SECRET, |
47 | | - ) |
48 | | - if (fingerprintHash !== expectedHash) { |
49 | | - logger.info( |
50 | | - { fingerprintId, fingerprintHash, expectedHash }, |
51 | | - 'Invalid auth code', |
52 | | - ) |
53 | | - return NextResponse.json( |
54 | | - { error: 'Authentication failed' }, |
55 | | - { status: 401 }, |
56 | | - ) |
57 | | - } |
58 | | - |
59 | | - try { |
60 | | - const users = await db |
61 | | - .select({ |
62 | | - id: schema.user.id, |
63 | | - email: schema.user.email, |
64 | | - name: schema.user.name, |
65 | | - authToken: schema.session.sessionToken, |
66 | | - }) |
67 | | - .from(schema.user) |
68 | | - .leftJoin(schema.session, eq(schema.user.id, schema.session.userId)) |
69 | | - .leftJoin( |
70 | | - schema.fingerprint, |
71 | | - eq(schema.session.fingerprint_id, schema.fingerprint.id), |
72 | | - ) |
73 | | - .where( |
74 | | - and( |
75 | | - eq(schema.session.fingerprint_id, fingerprintId), |
76 | | - or( |
77 | | - eq(schema.fingerprint.sig_hash, fingerprintHash), |
78 | | - isNull(schema.fingerprint.sig_hash), |
79 | | - ), |
80 | | - gt(schema.session.expires, new Date()), |
81 | | - ), |
82 | | - ) |
83 | | - |
84 | | - if (users.length === 0) { |
85 | | - logger.info( |
86 | | - { fingerprintId, fingerprintHash }, |
87 | | - 'No active session found or fingerprint claimed by another user', |
88 | | - ) |
89 | | - return NextResponse.json( |
90 | | - { error: 'Authentication failed' }, |
91 | | - { status: 401 }, |
92 | | - ) |
93 | | - } |
94 | | - |
95 | | - const user = users[0] |
96 | | - return NextResponse.json({ |
97 | | - user: { |
98 | | - id: user.id, |
99 | | - name: user.name, |
100 | | - email: user.email, |
101 | | - authToken: user.authToken, |
102 | | - fingerprintId, |
103 | | - fingerprintHash, |
104 | | - }, |
105 | | - message: 'Authentication successful!', |
106 | | - }) |
107 | | - } catch (error) { |
108 | | - logger.error({ error }, 'Error checking login status') |
109 | | - return NextResponse.json( |
110 | | - { error: 'Internal server error' }, |
111 | | - { status: 500 }, |
112 | | - ) |
113 | | - } |
114 | 14 | } |
0 commit comments