mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-08-05 06:50:10 +00:00
fix: address security issue
This commit is contained in:
@@ -353,9 +353,15 @@ export async function handleRegister(request: Request, env: Env): Promise<Respon
|
||||
return errorResponse('Invite code is required', 403);
|
||||
}
|
||||
|
||||
const inviteMarked = await storage.markInviteUsed(inviteCode, user.id);
|
||||
if (!inviteMarked) {
|
||||
return errorResponse('Invite code is invalid or expired', 403);
|
||||
}
|
||||
|
||||
try {
|
||||
await storage.createUser(user);
|
||||
} catch (error) {
|
||||
await storage.revertInviteUsed(inviteCode, user.id);
|
||||
const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
|
||||
if (msg.includes('unique') || msg.includes('constraint')) {
|
||||
return errorResponse('Email already registered', 409);
|
||||
@@ -363,12 +369,6 @@ export async function handleRegister(request: Request, env: Env): Promise<Respon
|
||||
throw error;
|
||||
}
|
||||
|
||||
const inviteMarked = await storage.markInviteUsed(inviteCode, user.id);
|
||||
if (!inviteMarked) {
|
||||
await storage.deleteUserById(user.id);
|
||||
return errorResponse('Invite code is invalid or expired', 403);
|
||||
}
|
||||
|
||||
await writeAuditEvent(storage, {
|
||||
actorUserId: user.id,
|
||||
action: 'user.register.invite',
|
||||
@@ -891,7 +891,7 @@ export async function handleDisableTwoFactorProvider(request: Request, env: Env,
|
||||
}
|
||||
|
||||
// PUT /api/accounts/totp
|
||||
// enable: { enabled: true, secret: "...", token: "123456" }
|
||||
// enable: { enabled: true, secret: "...", token: "123456", masterPasswordHash?: "...", userVerificationToken?: "..." }
|
||||
// disable: { enabled: false, masterPasswordHash: "..." }
|
||||
export async function handleSetTotpStatus(request: Request, env: Env, userId: string): Promise<Response> {
|
||||
const storage = new StorageService(env.DB);
|
||||
@@ -899,7 +899,13 @@ export async function handleSetTotpStatus(request: Request, env: Env, userId: st
|
||||
const user = await storage.getUserById(userId);
|
||||
if (!user) return errorResponse('User not found', 404);
|
||||
|
||||
let body: { enabled?: boolean; secret?: string; token?: string; masterPasswordHash?: string };
|
||||
let body: {
|
||||
enabled?: boolean;
|
||||
secret?: string;
|
||||
token?: string;
|
||||
masterPasswordHash?: string;
|
||||
userVerificationToken?: string;
|
||||
};
|
||||
try {
|
||||
body = await request.json();
|
||||
} catch {
|
||||
@@ -908,12 +914,24 @@ export async function handleSetTotpStatus(request: Request, env: Env, userId: st
|
||||
|
||||
if (body.enabled === true) {
|
||||
const normalizedSecret = normalizeTotpSecret(body.secret || '');
|
||||
const masterPasswordHash = readBodyString(body, ['masterPasswordHash', 'MasterPasswordHash']);
|
||||
const userVerificationToken = readBodyString(body, ['userVerificationToken', 'UserVerificationToken']);
|
||||
if (!isTotpEnabled(normalizedSecret)) {
|
||||
return errorResponse('Invalid TOTP secret', 400);
|
||||
}
|
||||
if (!body.token) {
|
||||
return errorResponse('TOTP token is required', 400);
|
||||
}
|
||||
let verifiedUser = false;
|
||||
if (userVerificationToken) {
|
||||
verifiedUser = await verifyTotpUserVerificationToken(env, user, normalizedSecret, userVerificationToken);
|
||||
}
|
||||
if (!verifiedUser && masterPasswordHash) {
|
||||
verifiedUser = await auth.verifyPassword(masterPasswordHash, user.masterPasswordHash, user.email);
|
||||
}
|
||||
if (!verifiedUser) {
|
||||
return errorResponse('User verification failed.', 400);
|
||||
}
|
||||
const verified = await verifyTotpToken(normalizedSecret, body.token);
|
||||
if (!verified) {
|
||||
return errorResponse('Invalid TOTP token', 400);
|
||||
|
||||
Reference in New Issue
Block a user