Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions app/api/client/login/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion app/api/sessions/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion app/api/users/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -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) {
Expand Down
9 changes: 6 additions & 3 deletions app/api/users/route.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion lib/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

/**
Expand Down
Loading