syncPermsLogic_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. package pub
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "testing"
  7. "time"
  8. permModel "perms-system-server/internal/model/perm"
  9. productModel "perms-system-server/internal/model/product"
  10. "perms-system-server/internal/response"
  11. "perms-system-server/internal/testutil"
  12. "perms-system-server/internal/types"
  13. "github.com/stretchr/testify/assert"
  14. "github.com/stretchr/testify/require"
  15. "golang.org/x/crypto/bcrypt"
  16. )
  17. func insertSyncTestProduct(t *testing.T, ctx context.Context, code, appKey, appSecret string, status int64) (int64, func()) {
  18. t.Helper()
  19. svcCtx := newTestSvcCtx()
  20. conn := testutil.GetTestSqlConn()
  21. now := time.Now().Unix()
  22. hashedSecret, err := bcrypt.GenerateFromPassword([]byte(appSecret), bcrypt.MinCost)
  23. require.NoError(t, err)
  24. res, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{
  25. Code: code,
  26. Name: code,
  27. AppKey: appKey,
  28. AppSecret: string(hashedSecret),
  29. Status: status,
  30. CreateTime: now,
  31. UpdateTime: now,
  32. })
  33. require.NoError(t, err)
  34. id, _ := res.LastInsertId()
  35. cleanup := func() {
  36. testutil.CleanTable(ctx, conn, "`sys_product`", id)
  37. }
  38. return id, cleanup
  39. }
  40. // TC-0036: 全部新增
  41. func TestSyncPerms_AllNew(t *testing.T) {
  42. ctx := context.Background()
  43. svcCtx := newTestSvcCtx()
  44. conn := testutil.GetTestSqlConn()
  45. pc := testutil.UniqueId()
  46. appKey := testutil.UniqueId()
  47. appSecret := testutil.UniqueId()
  48. _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1)
  49. t.Cleanup(cleanProduct)
  50. t.Cleanup(func() { testutil.CleanTableByField(ctx, conn, "`sys_perm`", "productCode", pc) })
  51. logic := NewSyncPermsLogic(ctx, svcCtx)
  52. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  53. AppKey: appKey,
  54. AppSecret: appSecret,
  55. Perms: []types.SyncPermItem{
  56. {Code: "perm_a", Name: "Perm A", Remark: "remark a"},
  57. {Code: "perm_b", Name: "Perm B"},
  58. {Code: "perm_c", Name: "Perm C"},
  59. },
  60. })
  61. require.NoError(t, err)
  62. require.NotNil(t, resp)
  63. assert.Equal(t, int64(3), resp.Added)
  64. assert.Equal(t, int64(0), resp.Updated)
  65. assert.Equal(t, int64(0), resp.Disabled)
  66. }
  67. // TC-0037: 更新已有(名称变更)
  68. func TestSyncPerms_UpdateExisting(t *testing.T) {
  69. ctx := context.Background()
  70. svcCtx := newTestSvcCtx()
  71. conn := testutil.GetTestSqlConn()
  72. pc := testutil.UniqueId()
  73. appKey := testutil.UniqueId()
  74. appSecret := testutil.UniqueId()
  75. now := time.Now().Unix()
  76. _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1)
  77. t.Cleanup(cleanProduct)
  78. permRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  79. ProductCode: pc, Name: "Old Name", Code: "upd_code", Remark: "old remark", Status: 1, CreateTime: now, UpdateTime: now,
  80. })
  81. require.NoError(t, err)
  82. permId, _ := permRes.LastInsertId()
  83. t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", permId) })
  84. logic := NewSyncPermsLogic(ctx, svcCtx)
  85. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  86. AppKey: appKey,
  87. AppSecret: appSecret,
  88. Perms: []types.SyncPermItem{
  89. {Code: "upd_code", Name: "New Name", Remark: "new remark"},
  90. },
  91. })
  92. require.NoError(t, err)
  93. require.NotNil(t, resp)
  94. assert.Equal(t, int64(0), resp.Added)
  95. assert.Equal(t, int64(1), resp.Updated)
  96. assert.Equal(t, int64(0), resp.Disabled)
  97. updated, err := svcCtx.SysPermModel.FindOne(ctx, permId)
  98. require.NoError(t, err)
  99. assert.Equal(t, "New Name", updated.Name)
  100. assert.Equal(t, "new remark", updated.Remark)
  101. assert.Equal(t, int64(1), updated.Status)
  102. }
  103. // TC-0038: 无变化
  104. func TestSyncPerms_NoChanges(t *testing.T) {
  105. ctx := context.Background()
  106. svcCtx := newTestSvcCtx()
  107. conn := testutil.GetTestSqlConn()
  108. pc := testutil.UniqueId()
  109. appKey := testutil.UniqueId()
  110. appSecret := testutil.UniqueId()
  111. now := time.Now().Unix()
  112. _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1)
  113. t.Cleanup(cleanProduct)
  114. permRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  115. ProductCode: pc, Name: "Same Name", Code: "same_code", Remark: "same remark", Status: 1, CreateTime: now, UpdateTime: now,
  116. })
  117. require.NoError(t, err)
  118. permId, _ := permRes.LastInsertId()
  119. t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", permId) })
  120. logic := NewSyncPermsLogic(ctx, svcCtx)
  121. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  122. AppKey: appKey,
  123. AppSecret: appSecret,
  124. Perms: []types.SyncPermItem{
  125. {Code: "same_code", Name: "Same Name", Remark: "same remark"},
  126. },
  127. })
  128. require.NoError(t, err)
  129. require.NotNil(t, resp)
  130. assert.Equal(t, int64(0), resp.Added)
  131. assert.Equal(t, int64(0), resp.Updated)
  132. assert.Equal(t, int64(0), resp.Disabled)
  133. }
  134. // TC-0039: 禁用权限重启
  135. func TestSyncPerms_ReEnableDisabled(t *testing.T) {
  136. ctx := context.Background()
  137. svcCtx := newTestSvcCtx()
  138. conn := testutil.GetTestSqlConn()
  139. pc := testutil.UniqueId()
  140. appKey := testutil.UniqueId()
  141. appSecret := testutil.UniqueId()
  142. now := time.Now().Unix()
  143. _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1)
  144. t.Cleanup(cleanProduct)
  145. permRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  146. ProductCode: pc, Name: "Disabled Perm", Code: "dis_code", Remark: "", Status: 2, CreateTime: now, UpdateTime: now,
  147. })
  148. require.NoError(t, err)
  149. permId, _ := permRes.LastInsertId()
  150. t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", permId) })
  151. logic := NewSyncPermsLogic(ctx, svcCtx)
  152. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  153. AppKey: appKey,
  154. AppSecret: appSecret,
  155. Perms: []types.SyncPermItem{
  156. {Code: "dis_code", Name: "Disabled Perm"},
  157. },
  158. })
  159. require.NoError(t, err)
  160. require.NotNil(t, resp)
  161. assert.Equal(t, int64(0), resp.Added)
  162. assert.Equal(t, int64(1), resp.Updated)
  163. reEnabled, err := svcCtx.SysPermModel.FindOne(ctx, permId)
  164. require.NoError(t, err)
  165. assert.Equal(t, int64(1), reEnabled.Status)
  166. }
  167. // TC-0040: 移除不在列表的权限
  168. func TestSyncPerms_DisableNotInList(t *testing.T) {
  169. ctx := context.Background()
  170. svcCtx := newTestSvcCtx()
  171. conn := testutil.GetTestSqlConn()
  172. pc := testutil.UniqueId()
  173. appKey := testutil.UniqueId()
  174. appSecret := testutil.UniqueId()
  175. now := time.Now().Unix()
  176. _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1)
  177. t.Cleanup(cleanProduct)
  178. keepCode := testutil.UniqueId()
  179. removeCode := testutil.UniqueId()
  180. keepRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  181. ProductCode: pc, Name: "Keep", Code: keepCode, Status: 1, CreateTime: now, UpdateTime: now,
  182. })
  183. require.NoError(t, err)
  184. keepId, _ := keepRes.LastInsertId()
  185. removeRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  186. ProductCode: pc, Name: "Remove", Code: removeCode, Status: 1, CreateTime: now, UpdateTime: now,
  187. })
  188. require.NoError(t, err)
  189. removeId, _ := removeRes.LastInsertId()
  190. t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", keepId, removeId) })
  191. logic := NewSyncPermsLogic(ctx, svcCtx)
  192. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  193. AppKey: appKey,
  194. AppSecret: appSecret,
  195. Perms: []types.SyncPermItem{
  196. {Code: keepCode, Name: "Keep"},
  197. },
  198. })
  199. require.NoError(t, err)
  200. require.NotNil(t, resp)
  201. assert.Equal(t, int64(0), resp.Added)
  202. assert.Equal(t, int64(1), resp.Disabled)
  203. disabled, err := svcCtx.SysPermModel.FindOne(ctx, removeId)
  204. require.NoError(t, err)
  205. assert.Equal(t, int64(2), disabled.Status)
  206. kept, err := svcCtx.SysPermModel.FindOne(ctx, keepId)
  207. require.NoError(t, err)
  208. assert.Equal(t, int64(1), kept.Status)
  209. }
  210. // TC-0041: 空perms数组应被拒绝
  211. func TestSyncPerms_EmptyPermsRejected(t *testing.T) {
  212. ctx := context.Background()
  213. svcCtx := newTestSvcCtx()
  214. pc := testutil.UniqueId()
  215. appKey := testutil.UniqueId()
  216. appSecret := testutil.UniqueId()
  217. _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1)
  218. t.Cleanup(cleanProduct)
  219. logic := NewSyncPermsLogic(ctx, svcCtx)
  220. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  221. AppKey: appKey,
  222. AppSecret: appSecret,
  223. Perms: []types.SyncPermItem{},
  224. })
  225. require.Nil(t, resp)
  226. require.Error(t, err)
  227. var codeErr *response.CodeError
  228. require.True(t, errors.As(err, &codeErr))
  229. assert.Equal(t, 400, codeErr.Code())
  230. assert.Contains(t, codeErr.Error(), "权限列表不能为空")
  231. }
  232. // TC-0043: appKey无效
  233. func TestSyncPerms_InvalidAppKey(t *testing.T) {
  234. ctx := context.Background()
  235. svcCtx := newTestSvcCtx()
  236. logic := NewSyncPermsLogic(ctx, svcCtx)
  237. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  238. AppKey: "nonexistent_key_" + testutil.UniqueId(),
  239. AppSecret: "whatever",
  240. Perms: []types.SyncPermItem{{Code: "x", Name: "x"}},
  241. })
  242. require.Nil(t, resp)
  243. require.Error(t, err)
  244. var codeErr *response.CodeError
  245. require.True(t, errors.As(err, &codeErr))
  246. assert.Equal(t, 401, codeErr.Code())
  247. assert.Equal(t, "无效的appKey", codeErr.Error())
  248. }
  249. // TC-0044: appSecret错误
  250. func TestSyncPerms_WrongAppSecret(t *testing.T) {
  251. ctx := context.Background()
  252. svcCtx := newTestSvcCtx()
  253. pc := testutil.UniqueId()
  254. appKey := testutil.UniqueId()
  255. appSecret := testutil.UniqueId()
  256. _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1)
  257. t.Cleanup(cleanProduct)
  258. logic := NewSyncPermsLogic(ctx, svcCtx)
  259. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  260. AppKey: appKey,
  261. AppSecret: "wrong_secret",
  262. Perms: []types.SyncPermItem{{Code: "x", Name: "x"}},
  263. })
  264. require.Nil(t, resp)
  265. require.Error(t, err)
  266. var codeErr *response.CodeError
  267. require.True(t, errors.As(err, &codeErr))
  268. assert.Equal(t, 401, codeErr.Code())
  269. assert.Equal(t, "appSecret验证失败", codeErr.Error())
  270. }
  271. // TC-0045: 产品已禁用
  272. func TestSyncPerms_ProductDisabled(t *testing.T) {
  273. ctx := context.Background()
  274. svcCtx := newTestSvcCtx()
  275. pc := testutil.UniqueId()
  276. appKey := testutil.UniqueId()
  277. appSecret := testutil.UniqueId()
  278. _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 2)
  279. t.Cleanup(cleanProduct)
  280. logic := NewSyncPermsLogic(ctx, svcCtx)
  281. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  282. AppKey: appKey,
  283. AppSecret: appSecret,
  284. Perms: []types.SyncPermItem{{Code: "x", Name: "x"}},
  285. })
  286. require.Nil(t, resp)
  287. require.Error(t, err)
  288. var codeErr *response.CodeError
  289. require.True(t, errors.As(err, &codeErr))
  290. assert.Equal(t, 403, codeErr.Code())
  291. assert.Equal(t, "产品已被禁用", codeErr.Error())
  292. }
  293. // TC-0046: 大批量(1000条)
  294. func TestSyncPerms_LargeBatch1000(t *testing.T) {
  295. ctx := context.Background()
  296. svcCtx := newTestSvcCtx()
  297. conn := testutil.GetTestSqlConn()
  298. pc := testutil.UniqueId()
  299. appKey := testutil.UniqueId()
  300. appSecret := testutil.UniqueId()
  301. _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1)
  302. t.Cleanup(cleanProduct)
  303. t.Cleanup(func() { testutil.CleanTableByField(ctx, conn, "`sys_perm`", "productCode", pc) })
  304. perms := make([]types.SyncPermItem, 1000)
  305. for i := 0; i < 1000; i++ {
  306. perms[i] = types.SyncPermItem{
  307. Code: fmt.Sprintf("batch_%s_%d", pc, i),
  308. Name: fmt.Sprintf("Perm_%d", i),
  309. }
  310. }
  311. logic := NewSyncPermsLogic(ctx, svcCtx)
  312. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  313. AppKey: appKey,
  314. AppSecret: appSecret,
  315. Perms: perms,
  316. })
  317. require.NoError(t, err)
  318. require.NotNil(t, resp)
  319. assert.Equal(t, int64(1000), resp.Added)
  320. assert.Equal(t, int64(0), resp.Updated)
  321. assert.Equal(t, int64(0), resp.Disabled)
  322. }
  323. // TC-0047: 重复code去重
  324. func TestSyncPerms_DeduplicateCodes(t *testing.T) {
  325. ctx := context.Background()
  326. svcCtx := newTestSvcCtx()
  327. conn := testutil.GetTestSqlConn()
  328. pc := testutil.UniqueId()
  329. appKey := testutil.UniqueId()
  330. appSecret := testutil.UniqueId()
  331. _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1)
  332. t.Cleanup(cleanProduct)
  333. t.Cleanup(func() { testutil.CleanTableByField(ctx, conn, "`sys_perm`", "productCode", pc) })
  334. logic := NewSyncPermsLogic(ctx, svcCtx)
  335. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  336. AppKey: appKey,
  337. AppSecret: appSecret,
  338. Perms: []types.SyncPermItem{
  339. {Code: "dup_code", Name: "Perm First"},
  340. {Code: "dup_code", Name: "Perm Duplicate"},
  341. {Code: "unique_code", Name: "Unique"},
  342. },
  343. })
  344. require.NoError(t, err)
  345. require.NotNil(t, resp)
  346. assert.Equal(t, int64(2), resp.Added, "重复code应被去重,只添加2条")
  347. }
  348. // TC-0042: 验证disabled返回值
  349. func TestSyncPerms_VerifyDisabledCount(t *testing.T) {
  350. ctx := context.Background()
  351. svcCtx := newTestSvcCtx()
  352. conn := testutil.GetTestSqlConn()
  353. pc := testutil.UniqueId()
  354. appKey := testutil.UniqueId()
  355. appSecret := testutil.UniqueId()
  356. now := time.Now().Unix()
  357. _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1)
  358. t.Cleanup(cleanProduct)
  359. var permIds []int64
  360. for i := 0; i < 5; i++ {
  361. res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{
  362. ProductCode: pc, Name: fmt.Sprintf("p%d", i), Code: fmt.Sprintf("code_%s_%d", pc, i),
  363. Status: 1, CreateTime: now, UpdateTime: now,
  364. })
  365. require.NoError(t, err)
  366. id, _ := res.LastInsertId()
  367. permIds = append(permIds, id)
  368. }
  369. t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", permIds...) })
  370. logic := NewSyncPermsLogic(ctx, svcCtx)
  371. resp, err := logic.SyncPerms(&types.SyncPermsReq{
  372. AppKey: appKey,
  373. AppSecret: appSecret,
  374. Perms: []types.SyncPermItem{
  375. {Code: fmt.Sprintf("code_%s_0", pc), Name: "p0"},
  376. {Code: fmt.Sprintf("code_%s_1", pc), Name: "p1"},
  377. },
  378. })
  379. require.NoError(t, err)
  380. require.NotNil(t, resp)
  381. assert.Equal(t, int64(0), resp.Added)
  382. assert.Equal(t, int64(3), resp.Disabled)
  383. }