From 65a9465af41f0cf67859fd2b7f42fc57d073220a Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 28 May 2026 18:24:23 +0800 Subject: [PATCH] fix: logout requires both device_id and instance_id Only clear specific instance on specific device Remove cross-device and all-instances clearing Co-Authored-By: Claude Opus 4.7 --- backend/internal/router/app/user.go | 60 +++++++++-------------------- 1 file changed, 18 insertions(+), 42 deletions(-) diff --git a/backend/internal/router/app/user.go b/backend/internal/router/app/user.go index 8688117..db90fe0 100644 --- a/backend/internal/router/app/user.go +++ b/backend/internal/router/app/user.go @@ -43,17 +43,11 @@ func handleAppLogout(c *gin.Context) { } var req struct { - DeviceID string `json:"device_id"` - InstanceID string `json:"instance_id"` + DeviceID string `json:"device_id" binding:"required"` + InstanceID string `json:"instance_id" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { - response.Error(c, 400, "参数错误") - return - } - - // 只有 device_id 没有 instance_id 时提示错误 - if req.DeviceID != "" && req.InstanceID == "" { - response.Error(c, 400, "缺少 instance_id 参数") + response.Error(c, 400, "device_id 和 instance_id 为必填参数") return } @@ -69,43 +63,25 @@ func handleAppLogout(c *gin.Context) { return } - deviceIDs := make([]uint, len(devices)) - for i, d := range devices { - deviceIDs[i] = d.ID + // 查找指定设备 + var targetDeviceID uint + for _, d := range devices { + if d.DeviceID == req.DeviceID { + targetDeviceID = d.ID + break + } } - var deletedCount int64 - - if req.InstanceID != "" && req.DeviceID != "" { - // 清除指定设备的指定实例 - var targetDeviceID uint - for _, d := range devices { - if d.DeviceID == req.DeviceID { - targetDeviceID = d.ID - break - } - } - - if targetDeviceID == 0 { - response.Error(c, 404, "设备不存在") - return - } - - result := database.DB.Where("device_id = ? AND instance_id = ?", targetDeviceID, req.InstanceID).Delete(&model.DeviceSession{}) - deletedCount = result.RowsAffected - log.Printf("[INFO] Logout: deleted session for device %s, instance %s, count %d", req.DeviceID, req.InstanceID, deletedCount) - } else if req.InstanceID != "" { - // 清除指定实例(跨设备) - result := database.DB.Where("device_id IN ? AND instance_id = ?", deviceIDs, req.InstanceID).Delete(&model.DeviceSession{}) - deletedCount = result.RowsAffected - log.Printf("[INFO] Logout: deleted instance %s across all devices, count %d", req.InstanceID, deletedCount) - } else { - // 清除该用户所有实例 - result := database.DB.Where("device_id IN ?", deviceIDs).Delete(&model.DeviceSession{}) - deletedCount = result.RowsAffected - log.Printf("[INFO] Logout: deleted all sessions for user %d, count %d", userID, deletedCount) + if targetDeviceID == 0 { + response.Error(c, 404, "设备不存在") + return } + // 清除指定实例 + result := database.DB.Where("device_id = ? AND instance_id = ?", targetDeviceID, req.InstanceID).Delete(&model.DeviceSession{}) + deletedCount := result.RowsAffected + log.Printf("[INFO] Logout: user %d, device %s, instance %s, deleted %d", userID, req.DeviceID, req.InstanceID, deletedCount) + service.LogVerification(c, &app.ID, uintPtr(userID.(uint)), "logout", fmt.Sprintf("用户登出,清除 %d 个实例", deletedCount), req.DeviceID, nil) response.Success(c, gin.H{