(req: http.IncomingMessage, res: http.ServerResponse)
| 487 | } |
| 488 | |
| 489 | private handlePasswordReset(req: http.IncomingMessage, res: http.ServerResponse): void { |
| 490 | this.readBody(req, (body) => { |
| 491 | try { |
| 492 | const { token, newPassword } = JSON.parse(body); |
| 493 | if (token !== this.resetToken) { |
| 494 | res.writeHead(403, { "Content-Type": "application/json" }); |
| 495 | res.end(JSON.stringify({ error: "Invalid reset token" })); |
| 496 | return; |
| 497 | } |
| 498 | if (!newPassword || newPassword.length < 4) { |
| 499 | res.writeHead(400, { "Content-Type": "application/json" }); |
| 500 | res.end(JSON.stringify({ error: "Password must be at least 4 characters" })); |
| 501 | return; |
| 502 | } |
| 503 | this.auth.passwordHash = this.hashPassword(newPassword); |
| 504 | this.auth.sessions.clear(); |
| 505 | this.saveAuth(); |
| 506 | this.resetToken = crypto.randomBytes(16).toString("hex"); |
| 507 | this.log.info(`memos-local: password has been reset. New reset token: ${this.resetToken}`); |
| 508 | const sessionToken = this.createSession(); |
| 509 | res.writeHead(200, { |
| 510 | "Content-Type": "application/json", |
| 511 | "Set-Cookie": `${this.cookieName}=${sessionToken}; Path=/; HttpOnly; SameSite=Strict; Max-Age=86400`, |
| 512 | }); |
| 513 | res.end(JSON.stringify({ ok: true, message: "Password reset successfully" })); |
| 514 | } catch (err) { |
| 515 | res.writeHead(400, { "Content-Type": "application/json" }); |
| 516 | res.end(JSON.stringify({ error: String(err) })); |
| 517 | } |
| 518 | }); |
| 519 | } |
| 520 | |
| 521 | // ─── Pages ─── |
| 522 |
no test coverage detected