permserver_test.go 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438
  1. package server
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "testing"
  7. "time"
  8. authHelper "perms-system-server/internal/logic/auth"
  9. deptModel "perms-system-server/internal/model/dept"
  10. permModel "perms-system-server/internal/model/perm"
  11. productModel "perms-system-server/internal/model/product"
  12. memberModel "perms-system-server/internal/model/productmember"
  13. roleModel "perms-system-server/internal/model/role"
  14. rolePermModel "perms-system-server/internal/model/roleperm"
  15. userModel "perms-system-server/internal/model/user"
  16. userPermModel "perms-system-server/internal/model/userperm"
  17. userRoleModel "perms-system-server/internal/model/userrole"
  18. "perms-system-server/internal/svc"
  19. "perms-system-server/internal/testutil"
  20. "perms-system-server/pb"
  21. "github.com/golang-jwt/jwt/v4"
  22. "github.com/stretchr/testify/assert"
  23. "github.com/stretchr/testify/require"
  24. "golang.org/x/crypto/bcrypt"
  25. "google.golang.org/grpc/codes"
  26. "google.golang.org/grpc/status"
  27. )
  28. func bcryptHash(t *testing.T, plaintext string) string {
  29. t.Helper()
  30. h, err := bcrypt.GenerateFromPassword([]byte(plaintext), bcrypt.MinCost)
  31. require.NoError(t, err)
  32. return string(h)
  33. }
  34. // ---------- SyncPermissions ----------
  35. // TC-0230: 正常同步
  36. func TestSyncPermissions_Normal(t *testing.T) {
  37. ctx := context.Background()
  38. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  39. conn := testutil.GetTestSqlConn()
  40. now := time.Now().Unix()
  41. uid := testutil.UniqueId()
  42. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  43. Code: uid, Name: "test_prod", AppKey: uid, AppSecret: bcryptHash(t, "secret1"),
  44. Status: 1, CreateTime: now, UpdateTime: now,
  45. })
  46. require.NoError(t, err)
  47. pId, _ := pRes.LastInsertId()
  48. t.Cleanup(func() {
  49. testutil.CleanTableByField(ctx, conn, "`sys_perm`", "productCode", uid)
  50. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  51. })
  52. srv := NewPermServer(svcCtx)
  53. resp, err := srv.SyncPermissions(ctx, &pb.SyncPermissionsReq{
  54. AppKey: uid,
  55. AppSecret: "secret1",
  56. Perms: []*pb.PermItem{
  57. {Code: "perm_a", Name: "Perm A", Remark: "remark_a"},
  58. {Code: "perm_b", Name: "Perm B", Remark: "remark_b"},
  59. },
  60. })
  61. require.NoError(t, err)
  62. assert.Equal(t, int64(2), resp.Added)
  63. assert.Equal(t, int64(0), resp.Updated)
  64. assert.Equal(t, int64(0), resp.Disabled)
  65. resp2, err := srv.SyncPermissions(ctx, &pb.SyncPermissionsReq{
  66. AppKey: uid,
  67. AppSecret: "secret1",
  68. Perms: []*pb.PermItem{
  69. {Code: "perm_a", Name: "Perm A Updated", Remark: "remark_a"},
  70. },
  71. })
  72. require.NoError(t, err)
  73. assert.Equal(t, int64(0), resp2.Added)
  74. assert.Equal(t, int64(1), resp2.Updated)
  75. assert.Equal(t, int64(1), resp2.Disabled)
  76. }
  77. // TC-0231: appKey无效
  78. func TestSyncPermissions_InvalidAppKey(t *testing.T) {
  79. ctx := context.Background()
  80. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  81. srv := NewPermServer(svcCtx)
  82. _, err := srv.SyncPermissions(ctx, &pb.SyncPermissionsReq{
  83. AppKey: "nonexistent_key",
  84. AppSecret: "any",
  85. Perms: []*pb.PermItem{{Code: "c", Name: "n"}},
  86. })
  87. require.Error(t, err)
  88. assert.Equal(t, codes.Unauthenticated, status.Code(err))
  89. assert.Equal(t, "无效的appKey", status.Convert(err).Message())
  90. }
  91. // TC-0232: appSecret错误
  92. func TestSyncPermissions_WrongAppSecret(t *testing.T) {
  93. ctx := context.Background()
  94. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  95. conn := testutil.GetTestSqlConn()
  96. now := time.Now().Unix()
  97. uid := testutil.UniqueId()
  98. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  99. Code: uid, Name: "test_prod", AppKey: uid, AppSecret: bcryptHash(t, "real_secret"),
  100. Status: 1, CreateTime: now, UpdateTime: now,
  101. })
  102. require.NoError(t, err)
  103. pId, _ := pRes.LastInsertId()
  104. t.Cleanup(func() {
  105. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  106. })
  107. srv := NewPermServer(svcCtx)
  108. _, err = srv.SyncPermissions(ctx, &pb.SyncPermissionsReq{
  109. AppKey: uid,
  110. AppSecret: "wrong_secret",
  111. Perms: []*pb.PermItem{{Code: "c", Name: "n"}},
  112. })
  113. require.Error(t, err)
  114. assert.Equal(t, codes.Unauthenticated, status.Code(err))
  115. assert.Equal(t, "appSecret验证失败", status.Convert(err).Message())
  116. }
  117. // TC-0233: 产品已禁用
  118. func TestSyncPermissions_ProductDisabled(t *testing.T) {
  119. ctx := context.Background()
  120. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  121. conn := testutil.GetTestSqlConn()
  122. now := time.Now().Unix()
  123. uid := testutil.UniqueId()
  124. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  125. Code: uid, Name: "test_prod", AppKey: uid, AppSecret: bcryptHash(t, "secret1"),
  126. Status: 2, CreateTime: now, UpdateTime: now,
  127. })
  128. require.NoError(t, err)
  129. pId, _ := pRes.LastInsertId()
  130. t.Cleanup(func() {
  131. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  132. })
  133. srv := NewPermServer(svcCtx)
  134. _, err = srv.SyncPermissions(ctx, &pb.SyncPermissionsReq{
  135. AppKey: uid,
  136. AppSecret: "secret1",
  137. Perms: []*pb.PermItem{{Code: "c", Name: "n"}},
  138. })
  139. require.Error(t, err)
  140. assert.Equal(t, codes.PermissionDenied, status.Code(err))
  141. assert.Equal(t, "产品已被禁用", status.Convert(err).Message())
  142. }
  143. // ---------- Login ----------
  144. // TC-0235: 正常登录(普通用户+productCode)
  145. func TestLogin_Normal(t *testing.T) {
  146. ctx := context.Background()
  147. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  148. conn := testutil.GetTestSqlConn()
  149. now := time.Now().Unix()
  150. uid := testutil.UniqueId()
  151. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  152. Username: uid, Password: testutil.HashPassword("pass123"), Nickname: "nick",
  153. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  154. Status: 1, CreateTime: now, UpdateTime: now,
  155. })
  156. require.NoError(t, err)
  157. uId, _ := uRes.LastInsertId()
  158. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  159. Code: uid, Name: "test_prod", AppKey: uid + "_k", AppSecret: "s1",
  160. Status: 1, CreateTime: now, UpdateTime: now,
  161. })
  162. require.NoError(t, err)
  163. pId, _ := pRes.LastInsertId()
  164. pmRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  165. ProductCode: uid, UserId: uId, MemberType: "MEMBER", Status: 1,
  166. CreateTime: now, UpdateTime: now,
  167. })
  168. require.NoError(t, err)
  169. pmId, _ := pmRes.LastInsertId()
  170. t.Cleanup(func() {
  171. testutil.CleanTable(ctx, conn, "`sys_product_member`", pmId)
  172. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  173. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  174. })
  175. srv := NewPermServer(svcCtx)
  176. resp, err := srv.Login(ctx, &pb.LoginReq{
  177. Username: uid,
  178. Password: "pass123",
  179. ProductCode: uid,
  180. })
  181. require.NoError(t, err)
  182. assert.NotEmpty(t, resp.AccessToken)
  183. assert.NotEmpty(t, resp.RefreshToken)
  184. assert.True(t, resp.Expires > time.Now().Unix(), "expires应为未来的unix时间戳")
  185. assert.Equal(t, uId, resp.UserId)
  186. assert.Equal(t, uid, resp.Username)
  187. // BUG-01: proto定义了nickname字段,实现应返回用户昵称
  188. assert.Equal(t, "nick", resp.Nickname, "BUG-01: LoginResp.Nickname 应返回用户昵称而非空字符串")
  189. }
  190. // TC-0236: 用户不存在
  191. func TestLogin_UserNotFound(t *testing.T) {
  192. ctx := context.Background()
  193. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  194. srv := NewPermServer(svcCtx)
  195. _, err := srv.Login(ctx, &pb.LoginReq{
  196. Username: "nonexistent_user_xyz",
  197. Password: "any",
  198. ProductCode: "any_product",
  199. })
  200. require.Error(t, err)
  201. assert.Equal(t, codes.Unauthenticated, status.Code(err))
  202. assert.Equal(t, "用户名或密码错误", status.Convert(err).Message())
  203. }
  204. // TC-0237: 密码错误
  205. func TestLogin_WrongPassword(t *testing.T) {
  206. ctx := context.Background()
  207. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  208. conn := testutil.GetTestSqlConn()
  209. now := time.Now().Unix()
  210. uid := testutil.UniqueId()
  211. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  212. Username: uid, Password: testutil.HashPassword("correct_pass"), Nickname: "nick",
  213. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  214. Status: 1, CreateTime: now, UpdateTime: now,
  215. })
  216. require.NoError(t, err)
  217. uId, _ := uRes.LastInsertId()
  218. t.Cleanup(func() {
  219. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  220. })
  221. srv := NewPermServer(svcCtx)
  222. _, err = srv.Login(ctx, &pb.LoginReq{
  223. Username: uid,
  224. Password: "wrong_pass",
  225. ProductCode: "any_product",
  226. })
  227. require.Error(t, err)
  228. assert.Equal(t, codes.Unauthenticated, status.Code(err))
  229. assert.Equal(t, "用户名或密码错误", status.Convert(err).Message())
  230. }
  231. // TC-0238: 账号冻结
  232. func TestLogin_AccountFrozen(t *testing.T) {
  233. ctx := context.Background()
  234. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  235. conn := testutil.GetTestSqlConn()
  236. now := time.Now().Unix()
  237. uid := testutil.UniqueId()
  238. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  239. Username: uid, Password: testutil.HashPassword("pass123"), Nickname: "nick",
  240. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  241. Status: 2, CreateTime: now, UpdateTime: now,
  242. })
  243. require.NoError(t, err)
  244. uId, _ := uRes.LastInsertId()
  245. t.Cleanup(func() {
  246. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  247. })
  248. srv := NewPermServer(svcCtx)
  249. _, err = srv.Login(ctx, &pb.LoginReq{
  250. Username: uid,
  251. Password: "pass123",
  252. ProductCode: "any_product",
  253. })
  254. require.Error(t, err)
  255. assert.Equal(t, codes.PermissionDenied, status.Code(err))
  256. assert.Equal(t, "账号已被冻结", status.Convert(err).Message())
  257. }
  258. // TC-0239: 超管被拒绝
  259. func TestLogin_SuperAdminRejected(t *testing.T) {
  260. ctx := context.Background()
  261. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  262. conn := testutil.GetTestSqlConn()
  263. now := time.Now().Unix()
  264. uid := testutil.UniqueId()
  265. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  266. Username: uid, Password: testutil.HashPassword("pass123"), Nickname: "sa",
  267. Avatar: sql.NullString{}, IsSuperAdmin: 1, MustChangePassword: 2,
  268. Status: 1, CreateTime: now, UpdateTime: now,
  269. })
  270. require.NoError(t, err)
  271. uId, _ := uRes.LastInsertId()
  272. t.Cleanup(func() {
  273. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  274. })
  275. srv := NewPermServer(svcCtx)
  276. _, err = srv.Login(ctx, &pb.LoginReq{
  277. Username: uid,
  278. Password: "pass123",
  279. ProductCode: "any_product",
  280. })
  281. require.Error(t, err)
  282. assert.Equal(t, codes.PermissionDenied, status.Code(err))
  283. assert.Equal(t, "超级管理员不允许通过产品端登录,请使用管理后台", status.Convert(err).Message())
  284. }
  285. // TC-0240: 普通用户+productCode
  286. func TestLogin_NormalUserWithProductCode(t *testing.T) {
  287. ctx := context.Background()
  288. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  289. conn := testutil.GetTestSqlConn()
  290. now := time.Now().Unix()
  291. uid := testutil.UniqueId()
  292. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  293. Username: uid, Password: testutil.HashPassword("pass123"), Nickname: "nick",
  294. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  295. Status: 1, CreateTime: now, UpdateTime: now,
  296. })
  297. require.NoError(t, err)
  298. uId, _ := uRes.LastInsertId()
  299. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  300. Code: uid, Name: "test_prod", AppKey: uid + "_k", AppSecret: "s1",
  301. Status: 1, CreateTime: now, UpdateTime: now,
  302. })
  303. require.NoError(t, err)
  304. pId, _ := pRes.LastInsertId()
  305. mbrRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  306. ProductCode: uid, UserId: uId, MemberType: "MEMBER",
  307. Status: 1, CreateTime: now, UpdateTime: now,
  308. })
  309. require.NoError(t, err)
  310. mbrId, _ := mbrRes.LastInsertId()
  311. roleRes, err := svcCtx.SysRoleModel.Insert(ctx, &roleModel.SysRole{
  312. ProductCode: uid, Name: uid + "_role", Status: 1, PermsLevel: 1,
  313. CreateTime: now, UpdateTime: now,
  314. })
  315. require.NoError(t, err)
  316. roleId, _ := roleRes.LastInsertId()
  317. pm1Res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  318. ProductCode: uid, Name: "p1", Code: uid + "_c1",
  319. Status: 1, CreateTime: now, UpdateTime: now,
  320. })
  321. require.NoError(t, err)
  322. pm1Id, _ := pm1Res.LastInsertId()
  323. urRes, err := svcCtx.SysUserRoleModel.Insert(ctx, &userRoleModel.SysUserRole{
  324. UserId: uId, RoleId: roleId, CreateTime: now, UpdateTime: now,
  325. })
  326. require.NoError(t, err)
  327. urId, _ := urRes.LastInsertId()
  328. rpRes, err := svcCtx.SysRolePermModel.Insert(ctx, &rolePermModel.SysRolePerm{
  329. RoleId: roleId, PermId: pm1Id, CreateTime: now, UpdateTime: now,
  330. })
  331. require.NoError(t, err)
  332. rpId, _ := rpRes.LastInsertId()
  333. t.Cleanup(func() {
  334. testutil.CleanTable(ctx, conn, "`sys_role_perm`", rpId)
  335. testutil.CleanTable(ctx, conn, "`sys_user_role`", urId)
  336. testutil.CleanTable(ctx, conn, "`sys_perm`", pm1Id)
  337. testutil.CleanTable(ctx, conn, "`sys_role`", roleId)
  338. testutil.CleanTable(ctx, conn, "`sys_product_member`", mbrId)
  339. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  340. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  341. })
  342. srv := NewPermServer(svcCtx)
  343. resp, err := srv.Login(ctx, &pb.LoginReq{
  344. Username: uid,
  345. Password: "pass123",
  346. ProductCode: uid,
  347. })
  348. require.NoError(t, err)
  349. assert.Equal(t, "MEMBER", resp.MemberType)
  350. assert.Contains(t, resp.Perms, uid+"_c1")
  351. assert.NotEmpty(t, resp.AccessToken)
  352. assert.NotEmpty(t, resp.RefreshToken)
  353. }
  354. // TC-0242: productCode为空
  355. func TestLogin_EmptyProductCode(t *testing.T) {
  356. ctx := context.Background()
  357. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  358. srv := NewPermServer(svcCtx)
  359. _, err := srv.Login(ctx, &pb.LoginReq{
  360. Username: "anyuser",
  361. Password: "anypass",
  362. ProductCode: "",
  363. })
  364. require.Error(t, err)
  365. assert.Equal(t, codes.InvalidArgument, status.Code(err))
  366. assert.Equal(t, "productCode不能为空", status.Convert(err).Message())
  367. }
  368. // ---------- RefreshToken ----------
  369. // TC-0243: 正常刷新(refreshToken原样返回,不重新生成)
  370. func TestRefreshToken_Normal(t *testing.T) {
  371. ctx := context.Background()
  372. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  373. conn := testutil.GetTestSqlConn()
  374. now := time.Now().Unix()
  375. uid := testutil.UniqueId()
  376. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  377. Username: uid, Password: testutil.HashPassword("pass123"), Nickname: "nick",
  378. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  379. Status: 1, CreateTime: now, UpdateTime: now,
  380. })
  381. require.NoError(t, err)
  382. uId, _ := uRes.LastInsertId()
  383. t.Cleanup(func() {
  384. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  385. })
  386. cfg := testutil.GetTestConfig()
  387. refreshToken, err := authHelper.GenerateRefreshToken(cfg.Auth.RefreshSecret, cfg.Auth.RefreshExpire, uId, "", 0)
  388. require.NoError(t, err)
  389. srv := NewPermServer(svcCtx)
  390. resp, err := srv.RefreshToken(ctx, &pb.RefreshTokenReq{
  391. RefreshToken: refreshToken,
  392. })
  393. require.NoError(t, err)
  394. assert.NotEmpty(t, resp.AccessToken)
  395. assert.NotEqual(t, refreshToken, resp.RefreshToken, "M-2修复:refreshToken必须发生轮转")
  396. newClaims, perr := authHelper.ParseRefreshToken(resp.RefreshToken, cfg.Auth.RefreshSecret)
  397. require.NoError(t, perr)
  398. assert.Equal(t, int64(1), newClaims.TokenVersion, "新 refreshToken 必须携带递增后的 tokenVersion")
  399. assert.True(t, resp.Expires > time.Now().Unix(), "expires应为未来的unix时间戳")
  400. }
  401. // TC-0244: token无效
  402. func TestRefreshToken_InvalidToken(t *testing.T) {
  403. ctx := context.Background()
  404. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  405. srv := NewPermServer(svcCtx)
  406. _, err := srv.RefreshToken(ctx, &pb.RefreshTokenReq{
  407. RefreshToken: "invalid.token.string",
  408. })
  409. require.Error(t, err)
  410. assert.Equal(t, codes.Unauthenticated, status.Code(err))
  411. assert.Equal(t, "refreshToken无效或已过期", status.Convert(err).Message())
  412. }
  413. // TC-0245: 账号冻结
  414. func TestRefreshToken_AccountFrozen(t *testing.T) {
  415. ctx := context.Background()
  416. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  417. conn := testutil.GetTestSqlConn()
  418. now := time.Now().Unix()
  419. uid := testutil.UniqueId()
  420. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  421. Username: uid, Password: testutil.HashPassword("pass123"), Nickname: "nick",
  422. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  423. Status: 2, CreateTime: now, UpdateTime: now,
  424. })
  425. require.NoError(t, err)
  426. uId, _ := uRes.LastInsertId()
  427. t.Cleanup(func() {
  428. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  429. })
  430. cfg := testutil.GetTestConfig()
  431. refreshToken, err := authHelper.GenerateRefreshToken(cfg.Auth.RefreshSecret, cfg.Auth.RefreshExpire, uId, "", 0)
  432. require.NoError(t, err)
  433. srv := NewPermServer(svcCtx)
  434. _, err = srv.RefreshToken(ctx, &pb.RefreshTokenReq{
  435. RefreshToken: refreshToken,
  436. })
  437. require.Error(t, err)
  438. assert.Equal(t, codes.PermissionDenied, status.Code(err))
  439. assert.Equal(t, "账号已被冻结", status.Convert(err).Message())
  440. }
  441. // TC-0246: productCode回退到claims
  442. func TestRefreshToken_FallbackToClaimsProductCode(t *testing.T) {
  443. ctx := context.Background()
  444. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  445. conn := testutil.GetTestSqlConn()
  446. now := time.Now().Unix()
  447. uid := testutil.UniqueId()
  448. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  449. Username: uid, Password: testutil.HashPassword("pass123"), Nickname: "nick",
  450. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  451. Status: 1, CreateTime: now, UpdateTime: now,
  452. })
  453. require.NoError(t, err)
  454. uId, _ := uRes.LastInsertId()
  455. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  456. Code: uid, Name: "test_prod", AppKey: uid + "_k", AppSecret: "s1",
  457. Status: 1, CreateTime: now, UpdateTime: now,
  458. })
  459. require.NoError(t, err)
  460. pId, _ := pRes.LastInsertId()
  461. mbrRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  462. ProductCode: uid, UserId: uId, MemberType: "MEMBER",
  463. Status: 1, CreateTime: now, UpdateTime: now,
  464. })
  465. require.NoError(t, err)
  466. mbrId, _ := mbrRes.LastInsertId()
  467. t.Cleanup(func() {
  468. testutil.CleanTable(ctx, conn, "`sys_product_member`", mbrId)
  469. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  470. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  471. })
  472. cfg := testutil.GetTestConfig()
  473. refreshToken, err := authHelper.GenerateRefreshToken(cfg.Auth.RefreshSecret, cfg.Auth.RefreshExpire, uId, uid, 0)
  474. require.NoError(t, err)
  475. srv := NewPermServer(svcCtx)
  476. resp, err := srv.RefreshToken(ctx, &pb.RefreshTokenReq{
  477. RefreshToken: refreshToken,
  478. ProductCode: "",
  479. })
  480. require.NoError(t, err)
  481. assert.NotEmpty(t, resp.AccessToken)
  482. assert.NotEqual(t, refreshToken, resp.RefreshToken, "M-2修复:refreshToken必须发生轮转")
  483. newClaims, perr := authHelper.ParseRefreshToken(resp.RefreshToken, cfg.Auth.RefreshSecret)
  484. require.NoError(t, perr)
  485. assert.Equal(t, int64(1), newClaims.TokenVersion, "新 refreshToken 必须携带递增后的 tokenVersion")
  486. assert.Equal(t, uid, newClaims.ProductCode, "fallback 分支:应使用 claims.ProductCode")
  487. }
  488. // TC-0247: 超管+productCode
  489. func TestRefreshToken_SuperAdminWithProductCode(t *testing.T) {
  490. ctx := context.Background()
  491. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  492. conn := testutil.GetTestSqlConn()
  493. now := time.Now().Unix()
  494. uid := testutil.UniqueId()
  495. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  496. Username: uid, Password: testutil.HashPassword("pass123"), Nickname: "sa",
  497. Avatar: sql.NullString{}, IsSuperAdmin: 1, MustChangePassword: 2,
  498. Status: 1, CreateTime: now, UpdateTime: now,
  499. })
  500. require.NoError(t, err)
  501. uId, _ := uRes.LastInsertId()
  502. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  503. Code: uid, Name: "test_prod", AppKey: uid + "_k", AppSecret: "s1",
  504. Status: 1, CreateTime: now, UpdateTime: now,
  505. })
  506. require.NoError(t, err)
  507. pId, _ := pRes.LastInsertId()
  508. pm1Res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  509. ProductCode: uid, Name: "p1", Code: uid + "_c1",
  510. Status: 1, CreateTime: now, UpdateTime: now,
  511. })
  512. require.NoError(t, err)
  513. pm1Id, _ := pm1Res.LastInsertId()
  514. t.Cleanup(func() {
  515. testutil.CleanTable(ctx, conn, "`sys_perm`", pm1Id)
  516. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  517. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  518. })
  519. cfg := testutil.GetTestConfig()
  520. refreshToken, err := authHelper.GenerateRefreshToken(cfg.Auth.RefreshSecret, cfg.Auth.RefreshExpire, uId, uid, 0)
  521. require.NoError(t, err)
  522. srv := NewPermServer(svcCtx)
  523. resp, err := srv.RefreshToken(ctx, &pb.RefreshTokenReq{
  524. RefreshToken: refreshToken,
  525. ProductCode: uid,
  526. })
  527. require.NoError(t, err)
  528. assert.NotEmpty(t, resp.AccessToken)
  529. assert.NotEqual(t, refreshToken, resp.RefreshToken, "M-2修复:refreshToken必须发生轮转")
  530. newClaims, perr := authHelper.ParseRefreshToken(resp.RefreshToken, cfg.Auth.RefreshSecret)
  531. require.NoError(t, perr)
  532. assert.Equal(t, int64(1), newClaims.TokenVersion, "新 refreshToken 必须携带递增后的 tokenVersion")
  533. }
  534. // TC-0248: 普通用户+productCode
  535. func TestRefreshToken_NormalUserWithProductCode(t *testing.T) {
  536. ctx := context.Background()
  537. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  538. conn := testutil.GetTestSqlConn()
  539. now := time.Now().Unix()
  540. uid := testutil.UniqueId()
  541. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  542. Username: uid, Password: testutil.HashPassword("pass123"), Nickname: "nick",
  543. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  544. Status: 1, CreateTime: now, UpdateTime: now,
  545. })
  546. require.NoError(t, err)
  547. uId, _ := uRes.LastInsertId()
  548. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  549. Code: uid, Name: "test_prod", AppKey: uid + "_k", AppSecret: "s1",
  550. Status: 1, CreateTime: now, UpdateTime: now,
  551. })
  552. require.NoError(t, err)
  553. pId, _ := pRes.LastInsertId()
  554. mbrRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  555. ProductCode: uid, UserId: uId, MemberType: "MEMBER",
  556. Status: 1, CreateTime: now, UpdateTime: now,
  557. })
  558. require.NoError(t, err)
  559. mbrId, _ := mbrRes.LastInsertId()
  560. pm1Res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  561. ProductCode: uid, Name: "p1", Code: uid + "_c1",
  562. Status: 1, CreateTime: now, UpdateTime: now,
  563. })
  564. require.NoError(t, err)
  565. pm1Id, _ := pm1Res.LastInsertId()
  566. roleRes, err := svcCtx.SysRoleModel.Insert(ctx, &roleModel.SysRole{
  567. ProductCode: uid, Name: uid + "_role", Status: 1, PermsLevel: 1,
  568. CreateTime: now, UpdateTime: now,
  569. })
  570. require.NoError(t, err)
  571. roleId, _ := roleRes.LastInsertId()
  572. urRes, err := svcCtx.SysUserRoleModel.Insert(ctx, &userRoleModel.SysUserRole{
  573. UserId: uId, RoleId: roleId, CreateTime: now, UpdateTime: now,
  574. })
  575. require.NoError(t, err)
  576. urId, _ := urRes.LastInsertId()
  577. rpRes, err := svcCtx.SysRolePermModel.Insert(ctx, &rolePermModel.SysRolePerm{
  578. RoleId: roleId, PermId: pm1Id, CreateTime: now, UpdateTime: now,
  579. })
  580. require.NoError(t, err)
  581. rpId, _ := rpRes.LastInsertId()
  582. t.Cleanup(func() {
  583. testutil.CleanTable(ctx, conn, "`sys_role_perm`", rpId)
  584. testutil.CleanTable(ctx, conn, "`sys_user_role`", urId)
  585. testutil.CleanTable(ctx, conn, "`sys_perm`", pm1Id)
  586. testutil.CleanTable(ctx, conn, "`sys_role`", roleId)
  587. testutil.CleanTable(ctx, conn, "`sys_product_member`", mbrId)
  588. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  589. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  590. })
  591. cfg := testutil.GetTestConfig()
  592. refreshToken, err := authHelper.GenerateRefreshToken(cfg.Auth.RefreshSecret, cfg.Auth.RefreshExpire, uId, uid, 0)
  593. require.NoError(t, err)
  594. srv := NewPermServer(svcCtx)
  595. resp, err := srv.RefreshToken(ctx, &pb.RefreshTokenReq{
  596. RefreshToken: refreshToken,
  597. ProductCode: uid,
  598. })
  599. require.NoError(t, err)
  600. assert.NotEmpty(t, resp.AccessToken)
  601. assert.NotEqual(t, refreshToken, resp.RefreshToken, "M-2修复:refreshToken必须发生轮转")
  602. newClaims, perr := authHelper.ParseRefreshToken(resp.RefreshToken, cfg.Auth.RefreshSecret)
  603. require.NoError(t, perr)
  604. assert.Equal(t, int64(1), newClaims.TokenVersion, "新 refreshToken 必须携带递增后的 tokenVersion")
  605. }
  606. // ---------- VerifyToken ----------
  607. // TC-0249: 有效token(VerifyToken 现在实时查询DB,需要真实数据)
  608. func TestVerifyToken_Valid(t *testing.T) {
  609. ctx := context.Background()
  610. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  611. cfg := testutil.GetTestConfig()
  612. conn := testutil.GetTestSqlConn()
  613. ts := time.Now().Unix()
  614. uid := testutil.UniqueId()
  615. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  616. Username: uid, Password: testutil.HashPassword("pass123"), Nickname: "nick_verify",
  617. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  618. Status: 1, CreateTime: ts, UpdateTime: ts,
  619. })
  620. require.NoError(t, err)
  621. uId, _ := uRes.LastInsertId()
  622. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  623. Code: uid, Name: "prod_verify", AppKey: uid + "_k", AppSecret: "s1",
  624. Status: 1, CreateTime: ts, UpdateTime: ts,
  625. })
  626. require.NoError(t, err)
  627. pId, _ := pRes.LastInsertId()
  628. pmRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  629. ProductCode: uid, UserId: uId, MemberType: "ADMIN", Status: 1,
  630. CreateTime: ts, UpdateTime: ts,
  631. })
  632. require.NoError(t, err)
  633. pmId, _ := pmRes.LastInsertId()
  634. pm1Res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  635. ProductCode: uid, Name: "perm_a", Code: "perm_a",
  636. Status: 1, CreateTime: ts, UpdateTime: ts,
  637. })
  638. require.NoError(t, err)
  639. pm1Id, _ := pm1Res.LastInsertId()
  640. pm2Res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  641. ProductCode: uid, Name: "perm_b", Code: "perm_b",
  642. Status: 1, CreateTime: ts, UpdateTime: ts,
  643. })
  644. require.NoError(t, err)
  645. pm2Id, _ := pm2Res.LastInsertId()
  646. t.Cleanup(func() {
  647. svcCtx.UserDetailsLoader.Del(ctx, uId, uid)
  648. testutil.CleanTable(ctx, conn, "`sys_perm`", pm1Id, pm2Id)
  649. testutil.CleanTable(ctx, conn, "`sys_product_member`", pmId)
  650. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  651. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  652. })
  653. svcCtx.UserDetailsLoader.Del(ctx, uId, uid)
  654. accessToken, err := authHelper.GenerateAccessToken(
  655. cfg.Auth.AccessSecret, cfg.Auth.AccessExpire,
  656. uId, uid, uid, "ADMIN", 0,
  657. )
  658. require.NoError(t, err)
  659. srv := NewPermServer(svcCtx)
  660. resp, err := srv.VerifyToken(ctx, &pb.VerifyTokenReq{AccessToken: accessToken})
  661. require.NoError(t, err)
  662. assert.True(t, resp.Valid)
  663. assert.Equal(t, uId, resp.UserId)
  664. assert.Equal(t, uid, resp.Username)
  665. assert.Equal(t, "ADMIN", resp.MemberType)
  666. assert.ElementsMatch(t, []string{"perm_a", "perm_b"}, resp.Perms)
  667. // BUG-02: proto定义了productCode字段,实现应返回产品编码
  668. assert.Equal(t, uid, resp.ProductCode, "BUG-02: VerifyTokenResp.ProductCode 应返回产品编码而非空字符串")
  669. }
  670. // TC-0250: 无效token
  671. func TestVerifyToken_Invalid(t *testing.T) {
  672. ctx := context.Background()
  673. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  674. srv := NewPermServer(svcCtx)
  675. resp, err := srv.VerifyToken(ctx, &pb.VerifyTokenReq{AccessToken: "invalid.token.here"})
  676. require.NoError(t, err)
  677. assert.False(t, resp.Valid)
  678. }
  679. // TC-0251: 缺少userId
  680. func TestVerifyToken_MissingUserId(t *testing.T) {
  681. ctx := context.Background()
  682. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  683. cfg := testutil.GetTestConfig()
  684. // Generate a token without userId by using raw JWT
  685. token := createTokenWithoutUserId(cfg.Auth.AccessSecret)
  686. srv := NewPermServer(svcCtx)
  687. resp, err := srv.VerifyToken(ctx, &pb.VerifyTokenReq{AccessToken: token})
  688. require.NoError(t, err)
  689. assert.False(t, resp.Valid)
  690. }
  691. // ---------- GetUserPerms ----------
  692. // TC-0255: 用户不存在
  693. func TestGetUserPerms_UserNotFound(t *testing.T) {
  694. ctx := context.Background()
  695. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  696. conn := testutil.GetTestSqlConn()
  697. now := time.Now().Unix()
  698. uid := testutil.UniqueId()
  699. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  700. Code: uid, Name: "test_prod", AppKey: uid, AppSecret: bcryptHash(t, "secret1"),
  701. Status: 1, CreateTime: now, UpdateTime: now,
  702. })
  703. require.NoError(t, err)
  704. pId, _ := pRes.LastInsertId()
  705. t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_product`", pId) })
  706. srv := NewPermServer(svcCtx)
  707. _, err = srv.GetUserPerms(ctx, &pb.GetUserPermsReq{
  708. UserId: 999999999,
  709. ProductCode: uid,
  710. AppKey: uid,
  711. AppSecret: "secret1",
  712. })
  713. require.Error(t, err)
  714. assert.Equal(t, codes.NotFound, status.Code(err))
  715. assert.Equal(t, "用户不存在", status.Convert(err).Message())
  716. }
  717. // TC-0256: 超管
  718. func TestGetUserPerms_SuperAdmin(t *testing.T) {
  719. ctx := context.Background()
  720. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  721. conn := testutil.GetTestSqlConn()
  722. now := time.Now().Unix()
  723. uid := testutil.UniqueId()
  724. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  725. Username: uid, Password: testutil.HashPassword("pass"), Nickname: "sa",
  726. Avatar: sql.NullString{}, IsSuperAdmin: 1, MustChangePassword: 2,
  727. Status: 1, CreateTime: now, UpdateTime: now,
  728. })
  729. require.NoError(t, err)
  730. uId, _ := uRes.LastInsertId()
  731. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  732. Code: uid, Name: "test_prod", AppKey: uid, AppSecret: bcryptHash(t, "secret1"),
  733. Status: 1, CreateTime: now, UpdateTime: now,
  734. })
  735. require.NoError(t, err)
  736. pId, _ := pRes.LastInsertId()
  737. pm1Res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  738. ProductCode: uid, Name: "p1", Code: uid + "_c1",
  739. Status: 1, CreateTime: now, UpdateTime: now,
  740. })
  741. require.NoError(t, err)
  742. pm1Id, _ := pm1Res.LastInsertId()
  743. mRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  744. ProductCode: uid, UserId: uId, MemberType: "ADMIN",
  745. Status: 1, CreateTime: now, UpdateTime: now,
  746. })
  747. require.NoError(t, err)
  748. mId, _ := mRes.LastInsertId()
  749. t.Cleanup(func() {
  750. testutil.CleanTable(ctx, conn, "`sys_product_member`", mId)
  751. testutil.CleanTable(ctx, conn, "`sys_perm`", pm1Id)
  752. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  753. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  754. })
  755. srv := NewPermServer(svcCtx)
  756. resp, err := srv.GetUserPerms(ctx, &pb.GetUserPermsReq{
  757. UserId: uId,
  758. ProductCode: uid,
  759. AppKey: uid,
  760. AppSecret: "secret1",
  761. })
  762. require.NoError(t, err)
  763. assert.Equal(t, "SUPER_ADMIN", resp.MemberType)
  764. assert.Contains(t, resp.Perms, uid+"_c1")
  765. }
  766. // TC-0234: 验证disabled计数
  767. func TestSyncPermissions_VerifyDisabledCount(t *testing.T) {
  768. ctx := context.Background()
  769. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  770. conn := testutil.GetTestSqlConn()
  771. now := time.Now().Unix()
  772. uid := testutil.UniqueId()
  773. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  774. Code: uid, Name: "test_prod", AppKey: uid, AppSecret: bcryptHash(t, "secret1"),
  775. Status: 1, CreateTime: now, UpdateTime: now,
  776. })
  777. require.NoError(t, err)
  778. pId, _ := pRes.LastInsertId()
  779. var permIds []int64
  780. for i := 0; i < 5; i++ {
  781. pmRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  782. ProductCode: uid, Name: "p", Code: fmt.Sprintf("%s_c%d", uid, i),
  783. Status: 1, CreateTime: now, UpdateTime: now,
  784. })
  785. require.NoError(t, err)
  786. pmId, _ := pmRes.LastInsertId()
  787. permIds = append(permIds, pmId)
  788. }
  789. t.Cleanup(func() {
  790. testutil.CleanTable(ctx, conn, "`sys_perm`", permIds...)
  791. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  792. })
  793. srv := NewPermServer(svcCtx)
  794. resp, err := srv.SyncPermissions(ctx, &pb.SyncPermissionsReq{
  795. AppKey: uid,
  796. AppSecret: "secret1",
  797. Perms: []*pb.PermItem{
  798. {Code: fmt.Sprintf("%s_c0", uid), Name: "p"},
  799. {Code: fmt.Sprintf("%s_c1", uid), Name: "p"},
  800. },
  801. })
  802. require.NoError(t, err)
  803. assert.Equal(t, int64(3), resp.Disabled)
  804. }
  805. // TC-0257: MEMBER-DENY覆盖
  806. func TestGetUserPerms_MemberDENYOverride(t *testing.T) {
  807. ctx := context.Background()
  808. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  809. conn := testutil.GetTestSqlConn()
  810. now := time.Now().Unix()
  811. uid := testutil.UniqueId()
  812. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  813. Username: uid, Password: testutil.HashPassword("pass"), Nickname: "nick",
  814. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  815. Status: 1, CreateTime: now, UpdateTime: now,
  816. })
  817. require.NoError(t, err)
  818. uId, _ := uRes.LastInsertId()
  819. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  820. Code: uid, Name: "test_prod", AppKey: uid + "_k", AppSecret: bcryptHash(t, "secret1"),
  821. Status: 1, CreateTime: now, UpdateTime: now,
  822. })
  823. require.NoError(t, err)
  824. pId, _ := pRes.LastInsertId()
  825. mbrRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  826. ProductCode: uid, UserId: uId, MemberType: "MEMBER",
  827. Status: 1, CreateTime: now, UpdateTime: now,
  828. })
  829. require.NoError(t, err)
  830. mbrId, _ := mbrRes.LastInsertId()
  831. roleRes, err := svcCtx.SysRoleModel.Insert(ctx, &roleModel.SysRole{
  832. ProductCode: uid, Name: uid + "_role", Status: 1, PermsLevel: 1,
  833. CreateTime: now, UpdateTime: now,
  834. })
  835. require.NoError(t, err)
  836. roleId, _ := roleRes.LastInsertId()
  837. permARes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  838. ProductCode: uid, Name: "permA", Code: uid + "_pA",
  839. Status: 1, CreateTime: now, UpdateTime: now,
  840. })
  841. require.NoError(t, err)
  842. permAId, _ := permARes.LastInsertId()
  843. permBRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  844. ProductCode: uid, Name: "permB", Code: uid + "_pB",
  845. Status: 1, CreateTime: now, UpdateTime: now,
  846. })
  847. require.NoError(t, err)
  848. permBId, _ := permBRes.LastInsertId()
  849. urRes, err := svcCtx.SysUserRoleModel.Insert(ctx, &userRoleModel.SysUserRole{
  850. UserId: uId, RoleId: roleId, CreateTime: now, UpdateTime: now,
  851. })
  852. require.NoError(t, err)
  853. urId, _ := urRes.LastInsertId()
  854. rpARes, err := svcCtx.SysRolePermModel.Insert(ctx, &rolePermModel.SysRolePerm{
  855. RoleId: roleId, PermId: permAId, CreateTime: now, UpdateTime: now,
  856. })
  857. require.NoError(t, err)
  858. rpAId, _ := rpARes.LastInsertId()
  859. rpBRes, err := svcCtx.SysRolePermModel.Insert(ctx, &rolePermModel.SysRolePerm{
  860. RoleId: roleId, PermId: permBId, CreateTime: now, UpdateTime: now,
  861. })
  862. require.NoError(t, err)
  863. rpBId, _ := rpBRes.LastInsertId()
  864. upRes, err := svcCtx.SysUserPermModel.Insert(ctx, &userPermModel.SysUserPerm{
  865. UserId: uId, PermId: permAId, Effect: "DENY",
  866. CreateTime: now, UpdateTime: now,
  867. })
  868. require.NoError(t, err)
  869. upId, _ := upRes.LastInsertId()
  870. t.Cleanup(func() {
  871. testutil.CleanTable(ctx, conn, "`sys_user_perm`", upId)
  872. testutil.CleanTable(ctx, conn, "`sys_role_perm`", rpAId, rpBId)
  873. testutil.CleanTable(ctx, conn, "`sys_user_role`", urId)
  874. testutil.CleanTable(ctx, conn, "`sys_perm`", permAId, permBId)
  875. testutil.CleanTable(ctx, conn, "`sys_role`", roleId)
  876. testutil.CleanTable(ctx, conn, "`sys_product_member`", mbrId)
  877. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  878. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  879. })
  880. srv := NewPermServer(svcCtx)
  881. resp, err := srv.GetUserPerms(ctx, &pb.GetUserPermsReq{
  882. UserId: uId,
  883. ProductCode: uid,
  884. AppKey: uid + "_k",
  885. AppSecret: "secret1",
  886. })
  887. require.NoError(t, err)
  888. assert.Equal(t, "MEMBER", resp.MemberType)
  889. assert.Contains(t, resp.Perms, uid+"_pB")
  890. assert.NotContains(t, resp.Perms, uid+"_pA")
  891. }
  892. // TC-0252: gRPC VerifyToken 用户已冻结返回valid=false(H-4修复验证)
  893. func TestVerifyToken_FrozenUserReturnsInvalid(t *testing.T) {
  894. ctx := context.Background()
  895. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  896. conn := testutil.GetTestSqlConn()
  897. now := time.Now().Unix()
  898. uid := testutil.UniqueId()
  899. cfg := testutil.GetTestConfig()
  900. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  901. Username: uid, Password: testutil.HashPassword("pass"), Nickname: "frozen",
  902. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  903. Status: 2, CreateTime: now, UpdateTime: now,
  904. })
  905. require.NoError(t, err)
  906. uId, _ := uRes.LastInsertId()
  907. t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_user`", uId) })
  908. accessToken, err := authHelper.GenerateAccessToken(
  909. cfg.Auth.AccessSecret, cfg.Auth.AccessExpire,
  910. uId, uid, "", "MEMBER", 0,
  911. )
  912. require.NoError(t, err)
  913. srv := NewPermServer(svcCtx)
  914. resp, err := srv.VerifyToken(ctx, &pb.VerifyTokenReq{AccessToken: accessToken})
  915. require.NoError(t, err)
  916. assert.False(t, resp.Valid, "frozen user token should be invalid")
  917. }
  918. // TC-0253: gRPC VerifyToken 非产品成员返回valid=false(H-4修复验证)
  919. func TestVerifyToken_NonMemberReturnsInvalid(t *testing.T) {
  920. ctx := context.Background()
  921. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  922. conn := testutil.GetTestSqlConn()
  923. now := time.Now().Unix()
  924. uid := testutil.UniqueId()
  925. pc := testutil.UniqueId()
  926. cfg := testutil.GetTestConfig()
  927. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  928. Username: uid, Password: testutil.HashPassword("pass"), Nickname: "user",
  929. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  930. Status: 1, CreateTime: now, UpdateTime: now,
  931. })
  932. require.NoError(t, err)
  933. uId, _ := uRes.LastInsertId()
  934. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  935. Code: pc, Name: "prod", AppKey: testutil.UniqueId(), AppSecret: "s",
  936. Status: 1, CreateTime: now, UpdateTime: now,
  937. })
  938. require.NoError(t, err)
  939. pId, _ := pRes.LastInsertId()
  940. t.Cleanup(func() {
  941. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  942. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  943. })
  944. accessToken, err := authHelper.GenerateAccessToken(
  945. cfg.Auth.AccessSecret, cfg.Auth.AccessExpire,
  946. uId, uid, pc, "MEMBER", 0,
  947. )
  948. require.NoError(t, err)
  949. srv := NewPermServer(svcCtx)
  950. resp, err := srv.VerifyToken(ctx, &pb.VerifyTokenReq{AccessToken: accessToken})
  951. require.NoError(t, err)
  952. assert.False(t, resp.Valid, "non-member user with productCode should be invalid")
  953. }
  954. // TC-0254: gRPC VerifyToken 返回实时权限和成员类型(H-4修复验证)
  955. func TestVerifyToken_ReturnsRealtimeData(t *testing.T) {
  956. ctx := context.Background()
  957. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  958. conn := testutil.GetTestSqlConn()
  959. now := time.Now().Unix()
  960. uid := testutil.UniqueId()
  961. cfg := testutil.GetTestConfig()
  962. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  963. Username: uid, Password: testutil.HashPassword("pass"), Nickname: "user",
  964. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  965. Status: 1, CreateTime: now, UpdateTime: now,
  966. })
  967. require.NoError(t, err)
  968. uId, _ := uRes.LastInsertId()
  969. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  970. Code: uid, Name: "prod", AppKey: uid + "_k", AppSecret: "s",
  971. Status: 1, CreateTime: now, UpdateTime: now,
  972. })
  973. require.NoError(t, err)
  974. pId, _ := pRes.LastInsertId()
  975. mbrRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  976. ProductCode: uid, UserId: uId, MemberType: "ADMIN",
  977. Status: 1, CreateTime: now, UpdateTime: now,
  978. })
  979. require.NoError(t, err)
  980. mbrId, _ := mbrRes.LastInsertId()
  981. permRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  982. ProductCode: uid, Name: "realtime_perm", Code: uid + "_rt",
  983. Status: 1, CreateTime: now, UpdateTime: now,
  984. })
  985. require.NoError(t, err)
  986. permId, _ := permRes.LastInsertId()
  987. t.Cleanup(func() {
  988. testutil.CleanTable(ctx, conn, "`sys_perm`", permId)
  989. testutil.CleanTable(ctx, conn, "`sys_product_member`", mbrId)
  990. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  991. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  992. })
  993. accessToken, err := authHelper.GenerateAccessToken(
  994. cfg.Auth.AccessSecret, cfg.Auth.AccessExpire,
  995. uId, uid, uid, "MEMBER", 0,
  996. )
  997. require.NoError(t, err)
  998. svcCtx.UserDetailsLoader.Clean(ctx, uId)
  999. srv := NewPermServer(svcCtx)
  1000. resp, err := srv.VerifyToken(ctx, &pb.VerifyTokenReq{AccessToken: accessToken})
  1001. require.NoError(t, err)
  1002. assert.True(t, resp.Valid)
  1003. assert.Equal(t, "ADMIN", resp.MemberType, "should return realtime memberType, not token's")
  1004. assert.Contains(t, resp.Perms, uid+"_rt", "should return realtime perms")
  1005. }
  1006. // TC-0241: gRPC Login 产品成员被禁用时拒绝(H-3修复验证)
  1007. func TestLogin_DisabledMemberRejected(t *testing.T) {
  1008. ctx := context.Background()
  1009. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  1010. conn := testutil.GetTestSqlConn()
  1011. now := time.Now().Unix()
  1012. uid := testutil.UniqueId()
  1013. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  1014. Username: uid, Password: testutil.HashPassword("pass123"), Nickname: "nick",
  1015. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  1016. Status: 1, CreateTime: now, UpdateTime: now,
  1017. })
  1018. require.NoError(t, err)
  1019. uId, _ := uRes.LastInsertId()
  1020. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  1021. Code: uid, Name: "prod", AppKey: uid + "_k", AppSecret: "s1",
  1022. Status: 1, CreateTime: now, UpdateTime: now,
  1023. })
  1024. require.NoError(t, err)
  1025. pId, _ := pRes.LastInsertId()
  1026. pmRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  1027. ProductCode: uid, UserId: uId, MemberType: "MEMBER", Status: 2,
  1028. CreateTime: now, UpdateTime: now,
  1029. })
  1030. require.NoError(t, err)
  1031. pmId, _ := pmRes.LastInsertId()
  1032. t.Cleanup(func() {
  1033. testutil.CleanTable(ctx, conn, "`sys_product_member`", pmId)
  1034. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  1035. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  1036. })
  1037. srv := NewPermServer(svcCtx)
  1038. _, err = srv.Login(ctx, &pb.LoginReq{
  1039. Username: uid,
  1040. Password: "pass123",
  1041. ProductCode: uid,
  1042. })
  1043. require.Error(t, err)
  1044. assert.Equal(t, codes.PermissionDenied, status.Code(err))
  1045. assert.Equal(t, "您在该产品下的成员资格已被禁用", status.Convert(err).Message())
  1046. }
  1047. // helper: create a JWT with no userId claim
  1048. func createTokenWithoutUserId(secret string) string {
  1049. claims := jwt.MapClaims{
  1050. "username": "test",
  1051. "exp": time.Now().Add(time.Hour).Unix(),
  1052. }
  1053. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  1054. s, _ := token.SignedString([]byte(secret))
  1055. return s
  1056. }
  1057. // =============================================================================
  1058. // audit H-2 修复回归测试:gRPC GetUserPerms 必须对齐 VerifyToken 的状态校验
  1059. // 修复前:GetUserPerms 仅校验"用户存在";冻结用户/被踢出产品的用户仍会被返回全量权限。
  1060. // 修复后:增加 StatusEnabled 判定 + (非超管下)MemberType 非空判定。
  1061. // =============================================================================
  1062. // TC-0700: GetUserPerms 对冻结用户 (Status=Disabled) 必须返回 PermissionDenied
  1063. func TestGetUserPerms_FrozenUser_PermissionDenied(t *testing.T) {
  1064. ctx := context.Background()
  1065. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  1066. conn := testutil.GetTestSqlConn()
  1067. now := time.Now().Unix()
  1068. uid := testutil.UniqueId()
  1069. // 用户 Status=2 (Disabled)
  1070. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  1071. Username: uid, Password: testutil.HashPassword("pass"), Nickname: "frozen",
  1072. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  1073. Status: 2, CreateTime: now, UpdateTime: now,
  1074. })
  1075. require.NoError(t, err)
  1076. uId, _ := uRes.LastInsertId()
  1077. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  1078. Code: uid, Name: "prod", AppKey: uid + "_k", AppSecret: bcryptHash(t, "s"),
  1079. Status: 1, CreateTime: now, UpdateTime: now,
  1080. })
  1081. require.NoError(t, err)
  1082. pId, _ := pRes.LastInsertId()
  1083. // 插入该产品下启用成员,保证 MemberType != "",排除冻结用户与非成员两个判定路径的干扰
  1084. mRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  1085. ProductCode: uid, UserId: uId, MemberType: "MEMBER", Status: 1,
  1086. CreateTime: now, UpdateTime: now,
  1087. })
  1088. require.NoError(t, err)
  1089. mId, _ := mRes.LastInsertId()
  1090. t.Cleanup(func() {
  1091. testutil.CleanTable(ctx, conn, "`sys_product_member`", mId)
  1092. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  1093. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  1094. })
  1095. // 清理缓存确保 loader 从 DB 取最新的 Status=2
  1096. svcCtx.UserDetailsLoader.Clean(ctx, uId)
  1097. srv := NewPermServer(svcCtx)
  1098. _, err = srv.GetUserPerms(ctx, &pb.GetUserPermsReq{
  1099. UserId: uId, ProductCode: uid, AppKey: uid + "_k", AppSecret: "s",
  1100. })
  1101. require.Error(t, err, "冻结用户的 GetUserPerms 必须返回错误,不能再返回全量权限")
  1102. assert.Equal(t, codes.PermissionDenied, status.Code(err),
  1103. "audit H-2: 冻结用户应返回 PermissionDenied 以阻断跨系统一致性漏洞")
  1104. assert.Contains(t, status.Convert(err).Message(), "冻结")
  1105. }
  1106. // TC-0701: GetUserPerms 对已被移出产品的启用用户(非超管 + MemberType 空)必须返回 PermissionDenied
  1107. func TestGetUserPerms_NonMember_PermissionDenied(t *testing.T) {
  1108. ctx := context.Background()
  1109. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  1110. conn := testutil.GetTestSqlConn()
  1111. now := time.Now().Unix()
  1112. uid := testutil.UniqueId()
  1113. // 用户启用但不是目标产品的成员
  1114. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  1115. Username: uid, Password: testutil.HashPassword("pass"), Nickname: "non_member",
  1116. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  1117. Status: 1, CreateTime: now, UpdateTime: now,
  1118. })
  1119. require.NoError(t, err)
  1120. uId, _ := uRes.LastInsertId()
  1121. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  1122. Code: uid, Name: "prod", AppKey: uid + "_k", AppSecret: bcryptHash(t, "s"),
  1123. Status: 1, CreateTime: now, UpdateTime: now,
  1124. })
  1125. require.NoError(t, err)
  1126. pId, _ := pRes.LastInsertId()
  1127. t.Cleanup(func() {
  1128. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  1129. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  1130. })
  1131. svcCtx.UserDetailsLoader.Clean(ctx, uId)
  1132. srv := NewPermServer(svcCtx)
  1133. _, err = srv.GetUserPerms(ctx, &pb.GetUserPermsReq{
  1134. UserId: uId, ProductCode: uid, AppKey: uid + "_k", AppSecret: "s",
  1135. })
  1136. require.Error(t, err)
  1137. assert.Equal(t, codes.PermissionDenied, status.Code(err),
  1138. "audit H-2: 用户不是产品成员时应返回 PermissionDenied")
  1139. assert.Contains(t, status.Convert(err).Message(), "成员")
  1140. }
  1141. // TC-0702: GetUserPerms 对"产品成员被禁用的 DEV 部门用户"必须返回 PermissionDenied
  1142. // 组合 H-2 + H-3 的交叉场景:禁用成员 → MemberType 清空 → 即便 DeptType=DEV 也不应获得权限
  1143. func TestGetUserPerms_DisabledMemberInDevDept_PermissionDenied(t *testing.T) {
  1144. ctx := context.Background()
  1145. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  1146. conn := testutil.GetTestSqlConn()
  1147. now := time.Now().Unix()
  1148. uid := testutil.UniqueId()
  1149. // 插入 DEV 部门
  1150. deptRes, err := svcCtx.SysDeptModel.Insert(ctx, &deptModel.SysDept{
  1151. Name: "dev_" + uid, ParentId: 0, Path: "/",
  1152. DeptType: "DEV", Status: 1, CreateTime: now, UpdateTime: now,
  1153. })
  1154. require.NoError(t, err)
  1155. deptId, _ := deptRes.LastInsertId()
  1156. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  1157. Username: uid, Password: testutil.HashPassword("pass"), Nickname: "dev_user",
  1158. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2, DeptId: deptId,
  1159. Status: 1, CreateTime: now, UpdateTime: now,
  1160. })
  1161. require.NoError(t, err)
  1162. uId, _ := uRes.LastInsertId()
  1163. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  1164. Code: uid, Name: "prod", AppKey: uid + "_k", AppSecret: bcryptHash(t, "s"),
  1165. Status: 1, CreateTime: now, UpdateTime: now,
  1166. })
  1167. require.NoError(t, err)
  1168. pId, _ := pRes.LastInsertId()
  1169. // 被管理员禁用的产品成员 (Status=2)
  1170. mRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  1171. ProductCode: uid, UserId: uId, MemberType: "MEMBER", Status: 2,
  1172. CreateTime: now, UpdateTime: now,
  1173. })
  1174. require.NoError(t, err)
  1175. mId, _ := mRes.LastInsertId()
  1176. // 放几条启用权限,验证"本来能拿到"
  1177. permRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  1178. ProductCode: uid, Name: "all", Code: uid + "_all",
  1179. Status: 1, CreateTime: now, UpdateTime: now,
  1180. })
  1181. require.NoError(t, err)
  1182. permId, _ := permRes.LastInsertId()
  1183. t.Cleanup(func() {
  1184. testutil.CleanTable(ctx, conn, "`sys_perm`", permId)
  1185. testutil.CleanTable(ctx, conn, "`sys_product_member`", mId)
  1186. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  1187. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  1188. testutil.CleanTable(ctx, conn, "`sys_dept`", deptId)
  1189. })
  1190. svcCtx.UserDetailsLoader.Clean(ctx, uId)
  1191. srv := NewPermServer(svcCtx)
  1192. _, err = srv.GetUserPerms(ctx, &pb.GetUserPermsReq{
  1193. UserId: uId, ProductCode: uid, AppKey: uid + "_k", AppSecret: "s",
  1194. })
  1195. require.Error(t, err,
  1196. "audit H-3: 产品成员被禁用的 DEV 部门用户不应再被 loadPerms 授予全量权限,"+
  1197. "GetUserPerms 也不应返回 PermissionDenied 以外的结果")
  1198. assert.Equal(t, codes.PermissionDenied, status.Code(err))
  1199. }
  1200. // TC-0703: GetUserPerms 对"启用的产品成员"返回成功(H-2 回归基准)
  1201. // 验证修复后的正常路径未被误伤
  1202. func TestGetUserPerms_EnabledMember_Succeeds(t *testing.T) {
  1203. ctx := context.Background()
  1204. svcCtx := svc.NewServiceContext(testutil.GetTestConfig())
  1205. conn := testutil.GetTestSqlConn()
  1206. now := time.Now().Unix()
  1207. uid := testutil.UniqueId()
  1208. uRes, err := svcCtx.SysUserModel.Insert(ctx, &userModel.SysUser{
  1209. Username: uid, Password: testutil.HashPassword("pass"), Nickname: "ok",
  1210. Avatar: sql.NullString{}, IsSuperAdmin: 2, MustChangePassword: 2,
  1211. Status: 1, CreateTime: now, UpdateTime: now,
  1212. })
  1213. require.NoError(t, err)
  1214. uId, _ := uRes.LastInsertId()
  1215. pRes, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  1216. Code: uid, Name: "prod", AppKey: uid + "_k", AppSecret: bcryptHash(t, "s"),
  1217. Status: 1, CreateTime: now, UpdateTime: now,
  1218. })
  1219. require.NoError(t, err)
  1220. pId, _ := pRes.LastInsertId()
  1221. mRes, err := svcCtx.SysProductMemberModel.Insert(ctx, &memberModel.SysProductMember{
  1222. ProductCode: uid, UserId: uId, MemberType: "ADMIN", Status: 1,
  1223. CreateTime: now, UpdateTime: now,
  1224. })
  1225. require.NoError(t, err)
  1226. mId, _ := mRes.LastInsertId()
  1227. permRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  1228. ProductCode: uid, Name: "p", Code: uid + "_c",
  1229. Status: 1, CreateTime: now, UpdateTime: now,
  1230. })
  1231. require.NoError(t, err)
  1232. permId, _ := permRes.LastInsertId()
  1233. t.Cleanup(func() {
  1234. testutil.CleanTable(ctx, conn, "`sys_perm`", permId)
  1235. testutil.CleanTable(ctx, conn, "`sys_product_member`", mId)
  1236. testutil.CleanTable(ctx, conn, "`sys_product`", pId)
  1237. testutil.CleanTable(ctx, conn, "`sys_user`", uId)
  1238. })
  1239. srv := NewPermServer(svcCtx)
  1240. resp, err := srv.GetUserPerms(ctx, &pb.GetUserPermsReq{
  1241. UserId: uId, ProductCode: uid, AppKey: uid + "_k", AppSecret: "s",
  1242. })
  1243. require.NoError(t, err)
  1244. assert.Equal(t, "ADMIN", resp.MemberType)
  1245. assert.Contains(t, resp.Perms, uid+"_c")
  1246. }