test5 / Dockerfile
simikkk's picture
Upload 69 files
303f049 verified
Raw
History Blame Contribute Delete
3.28 kB
import { NextRequest, NextResponse } from 'next/server';
import { db } from '@/lib/db';
import { changePasswordSchema, getClientIp } from '@/lib/validation';
import { getSessionUser, verifyPassword, hashPassword, getCookieToken } from '@/lib/auth';
import { rateLimit } from '@/lib/rate-limit';
import { logActivity } from '@/lib/activity';
export async function POST(request: NextRequest) {
try {
// ── Rate Limit ────────────────────────────────────────────────────
const ip = getClientIp(request);
const { allowed, retryAfterMs } = await rateLimit(`password:${ip}`, 3, 60_000);
if (!allowed) {
return NextResponse.json(
{ error: 'Too many password change attempts. Please try again later.' },
{
status: 429,
headers: { 'Retry-After': String(Math.ceil(retryAfterMs / 1000)) },
}
);
}
// ── Authenticate User ─────────────────────────────────────────────
const token = getCookieToken(request);
const user = await getSessionUser(token || '');
if (!user) {
return NextResponse.json(
{ error: 'Authentication required' },
{ status: 401 }
);
}
// ── Parse & Validate Body ─────────────────────────────────────────
const body = await request.json();
const parsed = changePasswordSchema.safeParse(body);
if (!parsed.success) {
return NextResponse.json(
{ error: parsed.error.issues[0].message },
{ status: 400 }
);
}
const { currentPassword, newPassword } = parsed.data;
// ── Verify Current Password ───────────────────────────────────────
const valid = await verifyPassword(currentPassword, user.password);
if (!valid) {
return NextResponse.json(
{ error: 'Invalid credentials' },
{ status: 401 }
);
}
// ── Hash New Password ─────────────────────────────────────────────
const hashedPassword = await hashPassword(newPassword);
// ── Update User Password ──────────────────────────────────────────
await db.user.update({
where: { id: user.id },
data: { password: hashedPassword },
});
// ── Invalidate All Sessions (force re-login) ──────────────────────
await db.session.deleteMany({
where: { userId: user.id },
});
logActivity(user.id, 'password_change', 'Password changed', 'Account password was updated');
return NextResponse.json({
success: true,
message: 'Password updated successfully',
});
} catch (error) {
console.error('[PASSWORD_CHANGE_ERROR]', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}