feat: implement address password authentication feature (#731)

* feat: implement address password authentication feature

- Add password field to address table for storing hashed passwords
- Implement address authentication APIs (login, change password)
- Add automatic password generation for new addresses
- Support password login alongside credential login in frontend
- Add password management in account settings and admin panel
- Add ENABLE_ADDRESS_PASSWORD environment variable for feature control
- Update documentation and i18n support
- Enhance security with SHA-256 password hashing

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* feat: upgrade dependencies

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Dream Hunter
2025-09-26 14:52:05 +08:00
committed by GitHub
parent 6ae90be3bf
commit a905ba5f06
35 changed files with 1552 additions and 1105 deletions

View File

@@ -2,7 +2,7 @@ import { Hono } from 'hono'
import { Jwt } from 'hono/utils/jwt'
import i18n from '../i18n'
import { sendAdminInternalMail, getJsonSetting, saveSetting, getUserRoles } from '../utils'
import { sendAdminInternalMail, getJsonSetting, saveSetting, getUserRoles, getBooleanValue, hashPassword } from '../utils'
import { newAddress, handleListQuery } from '../common'
import { CONSTANTS } from '../constants'
import cleanup_api from './cleanup_api'
@@ -56,6 +56,7 @@ api.post('/admin/new_address', async (c) => {
checkAllowDomains: false,
enableCheckNameRegex: false,
});
return c.json(res);
} catch (e) {
return c.text(`${msgs.FailedCreateAddressMsg}: ${(e as Error).message}`, 400)
@@ -131,6 +132,30 @@ api.get('/admin/show_password/:id', async (c) => {
})
})
api.post('/admin/address/:id/reset_password', async (c) => {
const { id } = c.req.param();
const { password } = await c.req.json();
// 检查功能是否启用
if (!getBooleanValue(c.env.ENABLE_ADDRESS_PASSWORD)) {
return c.text("Password management is disabled", 403);
}
if (!password) {
return c.text("Password is required", 400);
}
const hashedPassword = await hashPassword(password);
const { success } = await c.env.DB.prepare(
`UPDATE address SET password = ?, updated_at = datetime('now') WHERE id = ?`
).bind(hashedPassword, id).run();
if (!success) {
return c.text("Failed to reset password", 500);
}
return c.json({ success: true });
})
// mail api
api.get('/admin/mails', admin_mail_api.getMails);
api.get('/admin/mails_unknow', admin_mail_api.getUnknowMails);