feat(auth): 重构认证流程并补充前端登录态保护

- 拆分后端认证处理与会话创建逻辑,支持登录、注册、退出、个人资料和改密接口
- 增加二次验证挑战、Turnstile 人机校验与旧版邮箱迁移清理
- 新增前端认证守卫、管理员访问控制、退出 Hook 与验证工具
- 统一抽离接口类型,优化登录页、注册页和个人资料页的认证交互
This commit is contained in:
LanQin_
2026-06-16 10:10:21 +08:00
parent be8cd4be31
commit 45122162d0
20 changed files with 595 additions and 417 deletions
+67 -13
View File
@@ -305,19 +305,73 @@ func (a *App) migrateLegacyBootstrapMailbox(ctx context.Context) error {
if adminEmail == "" || !strings.Contains(adminEmail, "@") {
return nil
}
now := time.Now().UTC().Format(time.RFC3339Nano)
_, err := a.db.ExecContext(ctx, `
UPDATE mailboxes
SET status='disabled', updated_at=?
WHERE address=?
AND display_name='LanQin Admin'
AND EXISTS (
SELECT 1 FROM users
WHERE users.id=mailboxes.user_id
AND users.email=?
AND users.role='admin'
)`, now, adminEmail, adminEmail)
return err
rows, err := a.db.QueryContext(ctx, `
SELECT mb.id, mb.domain_id
FROM mailboxes mb
JOIN users u ON u.id=mb.user_id
WHERE mb.address=?
AND mb.display_name='LanQin Admin'
AND u.email=?
AND u.role='admin'`, adminEmail, adminEmail)
if err != nil {
return err
}
type legacyMailbox struct {
id string
domainID string
}
items := []legacyMailbox{}
for rows.Next() {
var item legacyMailbox
if err := rows.Scan(&item.id, &item.domainID); err != nil {
rows.Close()
return err
}
items = append(items, item)
}
if err := rows.Err(); err != nil {
rows.Close()
return err
}
if err := rows.Close(); err != nil {
return err
}
for _, item := range items {
messageRows, err := a.db.QueryContext(ctx, `SELECT id FROM messages WHERE mailbox_id=?`, item.id)
if err != nil {
return err
}
messageIDs := []string{}
for messageRows.Next() {
var messageID string
if err := messageRows.Scan(&messageID); err != nil {
messageRows.Close()
return err
}
messageIDs = append(messageIDs, messageID)
}
if err := messageRows.Err(); err != nil {
messageRows.Close()
return err
}
if err := messageRows.Close(); err != nil {
return err
}
for _, messageID := range messageIDs {
a.deleteMessageFiles(ctx, messageID)
}
if _, err := a.db.ExecContext(ctx, `DELETE FROM mailboxes WHERE id=?`, item.id); err != nil {
return err
}
if _, err := a.db.ExecContext(ctx, `
DELETE FROM domains
WHERE id=?
AND NOT EXISTS (SELECT 1 FROM mailboxes WHERE domain_id=domains.id)
AND NOT EXISTS (SELECT 1 FROM aliases WHERE domain_id=domains.id)`, item.domainID); err != nil {
return err
}
}
return nil
}
func (a *App) migrateMailRulesBuilder(ctx context.Context) error {