package auth import ( "context" "database/sql" "errors" "testing" "time" "perms-system-server/internal/loaders" "perms-system-server/internal/middleware" userModel "perms-system-server/internal/model/user" "perms-system-server/internal/response" "perms-system-server/internal/svc" "perms-system-server/internal/testutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // TC-0720: Logout 正常:tokenVersion 递增且 loader 缓存被清理 func TestLogout_Normal_IncrementsTokenVersion(t *testing.T) { ctx := context.Background() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() now := time.Now().Unix() username := testutil.UniqueId() res, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{ Username: username, Password: testutil.HashPassword("pw"), Nickname: "lg", Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2, Status: 1, TokenVersion: 0, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) userId, _ := res.LastInsertId() t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_user`", userId) }) ud, err := svcCtx.UserDetailsLoader.Load(ctx, userId, "") require.NoError(t, err, "M-1:正常用户 Load 应当 (*UserDetails, nil)") require.NotNil(t, ud) assert.Equal(t, int64(0), ud.TokenVersion) lctx := middleware.WithUserDetails(context.Background(), &loaders.UserDetails{ UserId: userId, Username: username, Status: 1, IsSuperAdmin: false, }) logic := NewLogoutLogic(lctx, svcCtx) require.NoError(t, logic.Logout()) u, err := svcCtx.SysUserModel.FindOne(ctx, userId) require.NoError(t, err) assert.Equal(t, int64(1), u.TokenVersion, "logout 必须递增 tokenVersion") ud2, err := svcCtx.UserDetailsLoader.Load(ctx, userId, "") require.NoError(t, err) require.NotNil(t, ud2) assert.Equal(t, int64(1), ud2.TokenVersion, "clean 后重新 Load 应拿到最新 TokenVersion") } // TC-0721: Logout 未登录返回 401 func TestLogout_Unauthorized(t *testing.T) { svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) logic := NewLogoutLogic(context.Background(), svcCtx) err := logic.Logout() require.Error(t, err) var ce *response.CodeError require.True(t, errors.As(err, &ce)) assert.Equal(t, 401, ce.Code()) assert.Equal(t, "未登录", ce.Error()) } // TC-0722: Logout 连续两次:tokenVersion 累加 func TestLogout_TwiceAccumulates(t *testing.T) { ctx := context.Background() svcCtx := svc.NewServiceContext(testutil.GetTestConfig()) conn := testutil.GetTestSqlConn() now := time.Now().Unix() username := testutil.UniqueId() res, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{ Username: username, Password: testutil.HashPassword("pw"), Nickname: "lg2", Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2, Status: 1, TokenVersion: 0, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) userId, _ := res.LastInsertId() t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_user`", userId) }) lctx := middleware.WithUserDetails(context.Background(), &loaders.UserDetails{ UserId: userId, Username: username, Status: 1, }) require.NoError(t, NewLogoutLogic(lctx, svcCtx).Logout()) require.NoError(t, NewLogoutLogic(lctx, svcCtx).Logout()) u, err := svcCtx.SysUserModel.FindOne(ctx, userId) require.NoError(t, err) assert.Equal(t, int64(2), u.TokenVersion) }