From ab3f188c042efe585333e21eb6e3ed782bc942e3 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 28 May 2026 18:18:31 +0800 Subject: [PATCH] fix: logout only clears instances, not devices - Remove device deletion on logout - Only delete DeviceSession records - Support clearing specific instance or all instances Co-Authored-By: Claude Opus 4.7 --- backend/internal/router/app/user.go | 69 ++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/backend/internal/router/app/user.go b/backend/internal/router/app/user.go index 509973e..e93e3fa 100644 --- a/backend/internal/router/app/user.go +++ b/backend/internal/router/app/user.go @@ -51,23 +51,72 @@ func handleAppLogout(c *gin.Context) { return } + // 获取用户在该应用下的所有设备 + var devices []model.UserDevice + if err := database.DB.Where("user_id = ? AND application_id = ?", userID, app.ID).Find(&devices).Error; err != nil { + response.Error(c, 500, "获取设备失败") + return + } + + if len(devices) == 0 { + response.Success(c, gin.H{"message": "登出成功"}) + return + } + + deviceIDs := make([]uint, len(devices)) + deviceMap := make(map[uint]string) + for i, d := range devices { + deviceIDs[i] = d.ID + deviceMap[d.ID] = d.DeviceID + } + + var deletedCount int64 + if req.DeviceID != "" { - var device model.UserDevice - if err := database.DB.Where("user_id = ? AND application_id = ? AND device_id = ?", userID, app.ID, req.DeviceID).First(&device).Error; err == nil { - if req.InstanceID != "" { - database.DB.Where("device_id = ? AND instance_id = ?", device.ID, req.InstanceID).Delete(&model.DeviceSession{}) - log.Printf("[INFO] Logout: deleted session for device %s, instance %s", req.DeviceID, req.InstanceID) - } else { - database.DB.Where("device_id = ?", device.ID).Delete(&model.DeviceSession{}) - log.Printf("[INFO] Logout: deleted all sessions for device %s", 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 + } + + if req.InstanceID != "" { + // 清除指定实例 + 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 { + // 清除该设备所有实例 + result := database.DB.Where("device_id = ?", targetDeviceID).Delete(&model.DeviceSession{}) + deletedCount = result.RowsAffected + log.Printf("[INFO] Logout: deleted all sessions for device %s, count %d", req.DeviceID, 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) + } } - service.LogVerification(c, &app.ID, uintPtr(userID.(uint)), "logout", "用户登出", req.DeviceID, nil) + service.LogVerification(c, &app.ID, uintPtr(userID.(uint)), "logout", fmt.Sprintf("用户登出,清除 %d 个实例", deletedCount), req.DeviceID, nil) response.Success(c, gin.H{ - "message": "登出成功", + "message": "登出成功", + "deleted_count": deletedCount, }) }