| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- package auth
- import (
- "testing"
- "perms-system-server/internal/loaders"
- "perms-system-server/internal/middleware"
- "perms-system-server/internal/testutil/mocks"
- "github.com/stretchr/testify/require"
- "go.uber.org/mock/gomock"
- )
- // ---------------------------------------------------------------------------
- // 覆盖目标:审计 M-R11-2 —— Logout Logic 必须把 middleware.UserDetails 里的 Username
- // 直接透传给 SysUserModel.IncrementTokenVersion,而不是让 Model 内部再 FindOne 取一次。
- //
- // 本文件以 mock 的方式对 Logic→Model 的契约做最严格的钉子:
- // IncrementTokenVersion 的第 3 个参数必须**字面等于** ud.Username;
- // 若 DEV 未来回归成"传 '' 让 Model 内部 FindOne",gomock 会拦截报错。
- // ---------------------------------------------------------------------------
- // TC-1047: M-R11-2 —— Logout 透传 ud.Username 给 IncrementTokenVersion
- func TestLogout_ForwardsUsername_NoInternalFindOne(t *testing.T) {
- ctrl := gomock.NewController(t)
- t.Cleanup(ctrl.Finish)
- const userId = int64(7777)
- const username = "m_r11_2_subject"
- mockUser := mocks.NewMockSysUserModel(ctrl)
- // 契约:username 参数必须与 ud.Username 字面一致。
- mockUser.EXPECT().
- IncrementTokenVersion(gomock.Any(), userId, username).
- Return(int64(1), nil)
- // 不允许再出现任何 FindOne / FindOneByUsername 的调用(gomock 默认就会对未声明的调用 fail)。
- svcCtx := mocks.NewMockServiceContext(mocks.MockModels{User: mockUser})
- ctx := middleware.WithUserDetails(t.Context(), &loaders.UserDetails{
- UserId: userId, Username: username, Status: 1,
- })
- require.NoError(t, NewLogoutLogic(ctx, svcCtx).Logout(),
- "Logout 正常路径应通过,且必须按签名字面透传 username")
- }
- // TC-1048: M-R11-2 —— Logout 在 Username 为 "" 的极端场景下仍然透传空串(不隐式 FindOne 修补)
- // 该契约保证 Model 层对 "调用方未提供 username" 的场景**不做缓存键兜底**;
- // 若 DEV 回退成 Model 内部 FindOne,行为会变:Logic 传 "" 进来时 Model 会真的去 DB 查一次。
- func TestLogout_EmptyUsernameStillForwarded(t *testing.T) {
- ctrl := gomock.NewController(t)
- t.Cleanup(ctrl.Finish)
- const userId = int64(8888)
- mockUser := mocks.NewMockSysUserModel(ctrl)
- mockUser.EXPECT().
- IncrementTokenVersion(gomock.Any(), userId, ""). // 严格 "" 不是 gomock.Any()
- Return(int64(3), nil)
- svcCtx := mocks.NewMockServiceContext(mocks.MockModels{User: mockUser})
- ctx := middleware.WithUserDetails(t.Context(), &loaders.UserDetails{
- UserId: userId, Username: "", Status: 1,
- })
- require.NoError(t, NewLogoutLogic(ctx, svcCtx).Logout())
- }
|