码桶
发现社区成员的开源项目
password.js2.5 KB
// Self-service password change (authenticated users only, not admin)
import { hashPassword, verifyPassword, isLegacyHash } from '../_crypto.js';
export async function onRequestPost(context) {
const { env } = context;
const kv = env.CF_DNS_KV;
if (!kv) {
return new Response(JSON.stringify({ error: 'KV storage not configured.' }), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
const user = context.data.user;
if (!user || !user.username) {
return new Response(JSON.stringify({ error: 'Authentication required.' }), {
status: 401,
headers: { 'Content-Type': 'application/json' }
});
}
const body = await context.request.json();
const { currentPassword, newPassword } = body;
if (!currentPassword || !newPassword) {
return new Response(JSON.stringify({ error: 'Current and new passwords are required.' }), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}
const username = user.username;
if (username === 'admin') {
// Admin password is APP_PASSWORD env var — cannot be changed at runtime
return new Response(JSON.stringify({ error: 'Admin password is managed via environment variables.' }), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}
const dataJson = await kv.get(`USER:${username}`);
if (!dataJson) {
return new Response(JSON.stringify({ error: 'User not found.' }), {
status: 404,
headers: { 'Content-Type': 'application/json' }
});
}
const userData = JSON.parse(dataJson);
// Verify current password (handle both legacy SHA-256 and PBKDF2 formats)
let verified = false;
if (isLegacyHash(userData.passwordHash)) {
verified = currentPassword === userData.passwordHash;
} else {
verified = await verifyPassword(currentPassword, userData.passwordHash);
}
if (!verified) {
return new Response(JSON.stringify({ error: 'Current password is incorrect.' }), {
status: 403,
headers: { 'Content-Type': 'application/json' }
});
}
// Store new password with PBKDF2
userData.passwordHash = await hashPassword(newPassword);
await kv.put(`USER:${username}`, JSON.stringify(userData));
return new Response(JSON.stringify({ success: true, message: 'Password updated.' }), {
headers: { 'Content-Type': 'application/json' }
});
}