diff --git a/app/api/client/login/route.ts b/app/api/client/login/route.ts index 29caed9..e6cd2c8 100644 --- a/app/api/client/login/route.ts +++ b/app/api/client/login/route.ts @@ -3,6 +3,7 @@ import { headers } from 'next/headers'; import { query } from '@/lib/db'; import bcrypt from 'bcryptjs'; import * as jose from 'jose'; +import { getJwtSecret } from '@/lib/auth-utils'; import { isRateLimited } from '@/lib/rate-limit'; import { auditLog } from '@/lib/audit-logger'; @@ -31,12 +32,7 @@ export async function POST(req: Request) { return NextResponse.json({ error: 'Invalid credentials' }, { status: 401 }); } - if (!process.env.JWT_SECRET || process.env.JWT_SECRET.length < 64) { - throw new Error("JWT_SECRET missing or too weak (min 64 chars required)"); - } - - // Generate JWT using jose - const secret = new TextEncoder().encode(process.env.JWT_SECRET); + const secret = await getJwtSecret(); const token = await new jose.SignJWT({ id: user.id, username: user.username }) .setProtectedHeader({ alg: 'HS256' }) .setIssuedAt() diff --git a/app/api/sessions/[id]/route.ts b/app/api/sessions/[id]/route.ts index 8fec119..edc43ae 100644 --- a/app/api/sessions/[id]/route.ts +++ b/app/api/sessions/[id]/route.ts @@ -10,7 +10,7 @@ export async function DELETE( const { id } = await params; if (!id) throw new Error('ID required'); - await query('UPDATE sessions SET status = "disconnected", end_time = CURRENT_TIMESTAMP WHERE id = ?', [id]); + await query('UPDATE sessions SET status = ?, end_time = CURRENT_TIMESTAMP WHERE id = ?', ['disconnected', id]); return NextResponse.json({ success: true }); } catch (error) { return handleApiError(error); diff --git a/app/api/users/[id]/route.ts b/app/api/users/[id]/route.ts index ebf8849..1c7f8a1 100644 --- a/app/api/users/[id]/route.ts +++ b/app/api/users/[id]/route.ts @@ -1,5 +1,6 @@ import { NextResponse } from 'next/server'; import { z } from 'zod'; +import bcrypt from 'bcryptjs'; import pool from '@/lib/db'; import { auditLog } from '@/lib/audit-logger'; @@ -92,7 +93,7 @@ export async function PATCH( if (validatedData.data.password) { updates.push('password_hash = ?'); - values.push(validatedData.data.password); + values.push(await bcrypt.hash(validatedData.data.password, 10)); } if (updates.length === 0) { diff --git a/app/api/users/route.ts b/app/api/users/route.ts index 062061a..04fccbd 100644 --- a/app/api/users/route.ts +++ b/app/api/users/route.ts @@ -1,5 +1,6 @@ import { NextResponse } from 'next/server'; import { z } from 'zod'; +import bcrypt from 'bcryptjs'; import pool from '@/lib/db'; import { auditLog } from '@/lib/audit-logger'; @@ -58,7 +59,8 @@ export async function GET(request: Request) { params.push(limit, offset); const [rows] = await pool.execute(sql, params); - const [countResult]: any = await pool.execute(countSql, params.slice(0, 1)); + const countParams = search ? [`%${search}%`] : []; + const [countResult]: any = await pool.execute(countSql, countParams); const total = countResult[0].total; return NextResponse.json({ @@ -104,12 +106,13 @@ export async function POST(request: Request) { // Convert empty string from date input to null const finalExpiresAt = expires_at ? new Date(expires_at) : null; - // In a real app, hash password here + const hashedPassword = password ? await bcrypt.hash(password, 10) : null; + const [result]: any = await pool.execute( `INSERT INTO vpn_users (username, password_hash, role, status, traffic_limit_gb, max_connections, expires_at, cisco_password, l2tp_password, wg_pubkey, xray_uuid, port, main_protocol) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, - [username, password || null, role, status, traffic_limit_gb, max_connections, finalExpiresAt, cisco_password || null, l2tp_password || null, wg_pubkey || null, xray_uuid || null, port || null, main_protocol || null] + [username, hashedPassword, role, status, traffic_limit_gb, max_connections, finalExpiresAt, cisco_password || null, l2tp_password || null, wg_pubkey || null, xray_uuid || null, port || null, main_protocol || null] ); const userId = result.insertId; diff --git a/lib/db.ts b/lib/db.ts index 360d757..4b20a3e 100644 --- a/lib/db.ts +++ b/lib/db.ts @@ -58,7 +58,7 @@ export async function validateConnection() { // Ensure connection is validated on startup if (process.env.NODE_ENV !== 'test') { - validateConnection(); + validateConnection().catch(err => console.error('[db] Failed to initialize database:', err)); } /**