Skip to content

Commit 04a7290

Browse files
committed
fix(setup-guide): 修复设置密码后无效的问题
feat(setup-guide): 完成设置向导页面的国际化支持
1 parent c5c6a33 commit 04a7290

3 files changed

Lines changed: 194 additions & 121 deletions

File tree

internal/api/auth.go

Lines changed: 99 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -238,127 +238,165 @@ type SecurityUpdateRequest struct {
238238

239239
// HandleChangePassword 修改密码
240240
func (h *AuthHandler) HandleChangePassword(c *gin.Context) {
241-
// 获取 session cookie
242-
sessionID, err := c.Cookie("session")
243-
if err != nil {
244-
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "message": "未登录"})
241+
// 从 context 中获取用户名(由 AuthMiddleware 注入)
242+
username, exists := c.Get("username")
243+
if !exists {
244+
c.JSON(http.StatusUnauthorized, gin.H{
245+
"success": false,
246+
"message": "未登录",
247+
})
245248
return
246249
}
247250

248-
if !h.authService.ValidateSession(sessionID) {
249-
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "message": "会话无效"})
250-
return
251-
}
252-
253-
sess, ok := h.authService.GetSession(sessionID)
254-
if !ok {
255-
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "message": "会话无效"})
256-
return
257-
}
251+
currentUsername := username.(string)
258252

259253
var req PasswordChangeRequest
260254
if err := c.ShouldBindJSON(&req); err != nil {
261-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "无效请求体"})
255+
c.JSON(http.StatusBadRequest, gin.H{
256+
"success": false,
257+
"message": "无效请求体",
258+
})
262259
return
263260
}
264261

265262
if req.CurrentPassword == "" || req.NewPassword == "" {
266-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "缺少字段"})
263+
c.JSON(http.StatusBadRequest, gin.H{
264+
"success": false,
265+
"message": "缺少字段",
266+
})
267267
return
268268
}
269269

270-
ok2, msg := h.authService.ChangePassword(sess.Username, req.CurrentPassword, req.NewPassword)
270+
ok2, msg := h.authService.ChangePassword(currentUsername, req.CurrentPassword, req.NewPassword)
271271
if !ok2 {
272-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": msg})
272+
c.JSON(http.StatusBadRequest, gin.H{
273+
"success": false,
274+
"message": msg,
275+
})
273276
return
274277
}
275278

276-
c.JSON(http.StatusOK, gin.H{"success": true, "message": msg})
279+
c.JSON(http.StatusOK, gin.H{
280+
"success": true,
281+
"message": msg,
282+
})
277283
}
278284

279285
// HandleChangeUsername 修改用户名
280286
func (h *AuthHandler) HandleChangeUsername(c *gin.Context) {
281-
sessionID, err := c.Cookie("session")
282-
if err != nil {
283-
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "message": "未登录"})
284-
return
285-
}
286-
287-
if !h.authService.ValidateSession(sessionID) {
288-
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "message": "会话无效"})
287+
// 从 context 中获取用户名(由 AuthMiddleware 注入)
288+
username, exists := c.Get("username")
289+
if !exists {
290+
c.JSON(http.StatusUnauthorized, gin.H{
291+
"success": false,
292+
"message": "未登录",
293+
})
289294
return
290295
}
291296

292-
sess, ok := h.authService.GetSession(sessionID)
293-
if !ok {
294-
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "message": "会话无效"})
295-
return
296-
}
297+
currentUsername := username.(string)
297298

298299
var req UsernameChangeRequest
299300
if err := c.ShouldBindJSON(&req); err != nil {
300-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "无效请求体"})
301+
c.JSON(http.StatusBadRequest, gin.H{
302+
"success": false,
303+
"message": "无效请求体",
304+
})
301305
return
302306
}
303307

304308
if req.NewUsername == "" {
305-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "新用户名不能为空"})
309+
c.JSON(http.StatusBadRequest, gin.H{
310+
"success": false,
311+
"message": "新用户名不能为空",
312+
})
306313
return
307314
}
308315

309-
ok2, msg := h.authService.ChangeUsername(sess.Username, req.NewUsername)
316+
ok2, msg := h.authService.ChangeUsername(currentUsername, req.NewUsername)
310317
if !ok2 {
311-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": msg})
318+
c.JSON(http.StatusBadRequest, gin.H{
319+
"success": false,
320+
"message": msg,
321+
})
312322
return
313323
}
314324

315-
c.JSON(http.StatusOK, gin.H{"success": true, "message": msg})
325+
c.JSON(http.StatusOK, gin.H{
326+
"success": true,
327+
"message": msg,
328+
})
316329
}
317330

318331
// HandleUpdateSecurity 同时修改用户名和密码
319332
func (h *AuthHandler) HandleUpdateSecurity(c *gin.Context) {
320-
// 获取 session cookie
321-
sessionID, err := c.Cookie("session")
322-
if err != nil {
323-
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "message": "未登录"})
324-
return
325-
}
326-
327-
if !h.authService.ValidateSession(sessionID) {
328-
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "message": "会话无效"})
333+
// 从 context 中获取用户名(由 AuthMiddleware 注入)
334+
username, exists := c.Get("username")
335+
if !exists {
336+
c.JSON(http.StatusUnauthorized, gin.H{
337+
"success": false,
338+
"message": "未登录",
339+
})
329340
return
330341
}
331342

332-
sess, ok := h.authService.GetSession(sessionID)
333-
if !ok {
334-
c.JSON(http.StatusUnauthorized, gin.H{"success": false, "message": "会话无效"})
335-
return
336-
}
343+
currentUsername := username.(string)
337344

338345
// 验证系统是否仍使用默认凭据,只有使用默认凭据时才允许此操作
339346
if !h.authService.IsDefaultCredentials() {
340-
c.JSON(http.StatusForbidden, gin.H{"success": false, "message": "此操作仅在首次设置时可用"})
347+
c.JSON(http.StatusForbidden, gin.H{
348+
"success": false,
349+
"message": "此操作仅在首次设置时可用",
350+
})
341351
return
342352
}
343353

344354
var req SecurityUpdateRequest
345355
if err := c.ShouldBindJSON(&req); err != nil {
346-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "无效请求体"})
356+
c.JSON(http.StatusBadRequest, gin.H{
357+
"success": false,
358+
"message": "无效请求体",
359+
})
347360
return
348361
}
349362

350363
if req.CurrentPassword == "" || req.NewUsername == "" || req.NewPassword == "" {
351-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "缺少必填字段"})
364+
c.JSON(http.StatusBadRequest, gin.H{
365+
"success": false,
366+
"message": "缺少必填字段",
367+
})
352368
return
353369
}
354370

355-
ok2, msg := h.authService.UpdateSecurity(sess.Username, req.CurrentPassword, req.NewUsername, req.NewPassword)
371+
ok2, msg := h.authService.UpdateSecurity(currentUsername, req.CurrentPassword, req.NewUsername, req.NewPassword)
356372
if !ok2 {
357-
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": msg})
373+
c.JSON(http.StatusBadRequest, gin.H{
374+
"success": false,
375+
"message": msg,
376+
})
377+
return
378+
}
379+
380+
// 修改成功后,生成新的 JWT token(基于新用户名)
381+
token, expiresAt, jti, err := h.authService.GenerateToken(req.NewUsername)
382+
if err != nil {
383+
c.JSON(http.StatusInternalServerError, gin.H{
384+
"success": false,
385+
"message": "生成新 token 失败",
386+
})
358387
return
359388
}
360389

361-
c.JSON(http.StatusOK, gin.H{"success": true, "message": msg})
390+
// 保存新的 JTI 到内存(使旧 token 失效)
391+
h.authService.SetCurrentJTI(jti)
392+
393+
c.JSON(http.StatusOK, gin.H{
394+
"success": true,
395+
"message": msg,
396+
"token": token,
397+
"expiresAt": expiresAt.Format(time.RFC3339),
398+
"username": req.NewUsername,
399+
})
362400
}
363401

364402
// HandleCheckDefaultCredentials 检查系统是否仍使用默认凭据
@@ -787,12 +825,11 @@ type OAuth2ConfigRequest struct {
787825
func (h *AuthHandler) HandleOAuth2Config(c *gin.Context) {
788826
switch c.Request.Method {
789827
case http.MethodGet:
790-
// 若请求携带有效 session,则返回完整配置;否则只返回 provider
828+
// 检查是否通过 JWT 认证(由 authMiddleware 注入)
791829
includeCfg := false
792-
if sessionID, err := c.Cookie("session"); err == nil {
793-
if h.authService.ValidateSession(sessionID) {
794-
includeCfg = true
795-
}
830+
if _, exists := c.Get("username"); exists {
831+
// 已通过 JWT 认证,返回完整配置
832+
includeCfg = true
796833
}
797834

798835
curProvider, _ := h.authService.GetSystemConfig("oauth2_provider")

web/src/lib/i18n.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import debugZh from "@/locales/zh-CN/debug.json";
1414
import examplesZh from "@/locales/zh-CN/examples.json";
1515
import modalsZh from "@/locales/zh-CN/modals.json";
1616
import oauthZh from "@/locales/zh-CN/oauth.json";
17+
import setupGuideZh from "@/locales/zh-CN/setup-guide.json";
1718
import commonEn from "@/locales/en-US/common.json";
1819
import authEn from "@/locales/en-US/auth.json";
1920
import dashboardEn from "@/locales/en-US/dashboard.json";
@@ -25,6 +26,7 @@ import debugEn from "@/locales/en-US/debug.json";
2526
import examplesEn from "@/locales/en-US/examples.json";
2627
import modalsEn from "@/locales/en-US/modals.json";
2728
import oauthEn from "@/locales/en-US/oauth.json";
29+
import setupGuideEn from "@/locales/en-US/setup-guide.json";
2830

2931
// 定义支持的语言
3032
export const supportedLanguages = ["zh-CN", "en-US"] as const;
@@ -66,6 +68,7 @@ export const resources = {
6668
examples: examplesZh,
6769
modals: modalsZh,
6870
oauth: oauthZh,
71+
"setup-guide": setupGuideZh,
6972
},
7073
"en-US": {
7174
common: commonEn,
@@ -79,6 +82,7 @@ export const resources = {
7982
examples: examplesEn,
8083
modals: modalsEn,
8184
oauth: oauthEn,
85+
"setup-guide": setupGuideEn,
8286
},
8387
} as const;
8488

@@ -90,7 +94,7 @@ i18n
9094
resources,
9195
fallbackLng: "zh-CN", // 默认语言为中文
9296
defaultNS: "common", // 默认命名空间
93-
ns: ["common", "auth", "dashboard", "services", "settings", "tunnels", "endpoints", "debug", "examples", "modals", "oauth"], // 可用的命名空间
97+
ns: ["common", "auth", "dashboard", "services", "settings", "tunnels", "endpoints", "debug", "examples", "modals", "oauth", "setup-guide"], // 可用的命名空间
9498

9599
// 语言检测配置
96100
detection: {

0 commit comments

Comments
 (0)