v5.migration.test.js 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321
  1. /* eslint-disable max-len */
  2. const mongoose = require('mongoose');
  3. const { getInstance } = require('../setup-crowi');
  4. describe('V5 page migration', () => {
  5. let crowi;
  6. let Page;
  7. let User;
  8. let UserGroup;
  9. let UserGroupRelation;
  10. let testUser1;
  11. let rootUser;
  12. let rootPage;
  13. const rootUserGroupId = new mongoose.Types.ObjectId();
  14. const testUser1GroupId = new mongoose.Types.ObjectId();
  15. const groupIdIsolate = new mongoose.Types.ObjectId();
  16. const groupIdA = new mongoose.Types.ObjectId();
  17. const groupIdB = new mongoose.Types.ObjectId();
  18. const groupIdC = new mongoose.Types.ObjectId();
  19. const pageId1 = new mongoose.Types.ObjectId();
  20. const pageId2 = new mongoose.Types.ObjectId();
  21. const pageId3 = new mongoose.Types.ObjectId();
  22. const pageId4 = new mongoose.Types.ObjectId();
  23. const pageId5 = new mongoose.Types.ObjectId();
  24. const pageId6 = new mongoose.Types.ObjectId();
  25. const pageId7 = new mongoose.Types.ObjectId();
  26. const pageId8 = new mongoose.Types.ObjectId();
  27. const pageId9 = new mongoose.Types.ObjectId();
  28. const pageId10 = new mongoose.Types.ObjectId();
  29. const pageId11 = new mongoose.Types.ObjectId();
  30. const onlyPublic = filter => ({ grant: Page.GRANT_PUBLIC, ...filter });
  31. const ownedByTestUser1 = filter => ({ grant: Page.GRANT_OWNER, grantedUsers: [testUser1._id], ...filter });
  32. const root = filter => ({ grantedUsers: [rootUser._id], ...filter });
  33. const rootUserGroup = filter => ({
  34. grantedGroups: {
  35. $elemMatch: {
  36. item: rootUserGroupId,
  37. },
  38. },
  39. ...filter,
  40. });
  41. const testUser1Group = filter => ({
  42. grantedGroups: {
  43. $elemMatch: {
  44. item: testUser1GroupId,
  45. },
  46. },
  47. ...filter,
  48. });
  49. const normalized = { parent: { $ne: null } };
  50. const notNormalized = { parent: null };
  51. const empty = { isEmpty: true };
  52. beforeAll(async() => {
  53. jest.restoreAllMocks();
  54. crowi = await getInstance();
  55. Page = mongoose.model('Page');
  56. User = mongoose.model('User');
  57. UserGroup = mongoose.model('UserGroup');
  58. UserGroupRelation = mongoose.model('UserGroupRelation');
  59. await crowi.configManager.updateConfig('app:isV5Compatible', true);
  60. await User.insertMany([
  61. { name: 'rootUser', username: 'rootUser', email: 'rootUser@example.com' },
  62. { name: 'testUser1', username: 'testUser1', email: 'testUser1@example.com' },
  63. ]);
  64. rootUser = await User.findOne({ username: 'rootUser' });
  65. testUser1 = await User.findOne({ username: 'testUser1' });
  66. rootPage = await Page.findOne({ path: '/' });
  67. await UserGroup.insertMany([
  68. {
  69. _id: rootUserGroupId,
  70. name: 'rootUserGroup',
  71. },
  72. {
  73. _id: testUser1GroupId,
  74. name: 'testUser1Group',
  75. },
  76. {
  77. _id: groupIdIsolate,
  78. name: 'groupIsolate',
  79. },
  80. {
  81. _id: groupIdA,
  82. name: 'groupA',
  83. },
  84. {
  85. _id: groupIdB,
  86. name: 'groupB',
  87. parent: groupIdA,
  88. },
  89. {
  90. _id: groupIdC,
  91. name: 'groupC',
  92. parent: groupIdB,
  93. },
  94. ]);
  95. await UserGroupRelation.insertMany([
  96. {
  97. relatedGroup: rootUserGroupId,
  98. relatedUser: rootUser._id,
  99. },
  100. {
  101. relatedGroup: testUser1GroupId,
  102. relatedUser: testUser1._id,
  103. },
  104. {
  105. relatedGroup: groupIdIsolate,
  106. relatedUser: testUser1._id,
  107. },
  108. {
  109. relatedGroup: groupIdA,
  110. relatedUser: testUser1._id,
  111. },
  112. {
  113. relatedGroup: groupIdB,
  114. relatedUser: testUser1._id,
  115. },
  116. {
  117. relatedGroup: groupIdC,
  118. relatedUser: testUser1._id,
  119. },
  120. ]);
  121. await Page.insertMany([
  122. {
  123. path: '/private1',
  124. grant: Page.GRANT_OWNER,
  125. creator: testUser1,
  126. lastUpdateUser: testUser1,
  127. grantedUsers: [testUser1._id],
  128. },
  129. {
  130. path: '/dummyParent/private1',
  131. grant: Page.GRANT_OWNER,
  132. creator: testUser1,
  133. lastUpdateUser: testUser1,
  134. grantedUsers: [testUser1._id],
  135. },
  136. {
  137. path: '/dummyParent/private1/private2',
  138. grant: Page.GRANT_OWNER,
  139. creator: testUser1,
  140. lastUpdateUser: testUser1,
  141. grantedUsers: [testUser1._id],
  142. },
  143. {
  144. path: '/dummyParent/private1/private3',
  145. grant: Page.GRANT_OWNER,
  146. creator: testUser1,
  147. lastUpdateUser: testUser1,
  148. grantedUsers: [testUser1._id],
  149. },
  150. {
  151. _id: pageId1,
  152. path: '/normalize_1',
  153. parent: rootPage._id,
  154. grant: Page.GRANT_PUBLIC,
  155. isEmpty: true,
  156. },
  157. {
  158. _id: pageId2,
  159. path: '/normalize_1/normalize_2',
  160. parent: pageId1,
  161. grant: Page.GRANT_USER_GROUP,
  162. grantedGroups: [{ item: groupIdB, type: 'UserGroup' }],
  163. grantedUsers: [testUser1._id],
  164. },
  165. {
  166. _id: pageId3,
  167. path: '/normalize_1',
  168. grant: Page.GRANT_USER_GROUP,
  169. grantedGroups: [{ item: groupIdA, type: 'UserGroup' }],
  170. grantedUsers: [testUser1._id],
  171. },
  172. {
  173. _id: pageId4,
  174. path: '/normalize_4',
  175. parent: rootPage._id,
  176. grant: Page.GRANT_PUBLIC,
  177. isEmpty: true,
  178. },
  179. {
  180. _id: pageId5,
  181. path: '/normalize_4/normalize_5',
  182. parent: pageId4,
  183. grant: Page.GRANT_USER_GROUP,
  184. grantedGroups: [{ item: groupIdA, type: 'UserGroup' }],
  185. grantedUsers: [testUser1._id],
  186. },
  187. {
  188. _id: pageId6,
  189. path: '/normalize_4',
  190. grant: Page.GRANT_USER_GROUP,
  191. grantedGroups: [{ item: groupIdIsolate, type: 'UserGroup' }],
  192. grantedUsers: [testUser1._id],
  193. },
  194. {
  195. path: '/normalize_7/normalize_8_gA',
  196. grant: Page.GRANT_USER_GROUP,
  197. creator: testUser1,
  198. grantedGroups: [{ item: groupIdA, type: 'UserGroup' }],
  199. grantedUsers: [testUser1._id],
  200. },
  201. {
  202. path: '/normalize_7/normalize_8_gA/normalize_9_gB',
  203. grant: Page.GRANT_USER_GROUP,
  204. creator: testUser1,
  205. grantedGroups: [{ item: groupIdB, type: 'UserGroup' }],
  206. grantedUsers: [testUser1._id],
  207. },
  208. {
  209. path: '/normalize_7/normalize_8_gC',
  210. grant: Page.GRANT_USER_GROUP,
  211. grantedGroups: [{ item: groupIdC, type: 'UserGroup' }],
  212. grantedUsers: [testUser1._id],
  213. },
  214. {
  215. _id: pageId7,
  216. path: '/normalize_10',
  217. grant: Page.GRANT_PUBLIC,
  218. isEmpty: true,
  219. parent: rootPage._id,
  220. descendantCount: 3,
  221. },
  222. {
  223. _id: pageId8,
  224. path: '/normalize_10/normalize_11_gA',
  225. isEmpty: true,
  226. parent: pageId7,
  227. descendantCount: 1,
  228. },
  229. {
  230. _id: pageId9, // not v5
  231. path: '/normalize_10/normalize_11_gA',
  232. grant: Page.GRANT_USER_GROUP,
  233. grantedGroups: [{ item: groupIdA, type: 'UserGroup' }],
  234. },
  235. {
  236. _id: pageId10,
  237. path: '/normalize_10/normalize_11_gA/normalize_11_gB',
  238. grant: Page.GRANT_USER_GROUP,
  239. grantedGroups: [{ item: groupIdB, type: 'UserGroup' }],
  240. parent: pageId8,
  241. descendantCount: 0,
  242. },
  243. {
  244. _id: pageId11,
  245. path: '/normalize_10/normalize_12_gC',
  246. grant: Page.GRANT_USER_GROUP,
  247. grantedGroups: [{ item: groupIdC, type: 'UserGroup' }],
  248. grantedUsers: [testUser1._id],
  249. parent: pageId7,
  250. descendantCount: 0,
  251. },
  252. ]);
  253. });
  254. const normalizeParentRecursivelyByPages = async(pages, user) => {
  255. return crowi.pageService.normalizeParentRecursivelyByPages(pages, user);
  256. };
  257. const normalizeParentByPage = async(page, user) => {
  258. return crowi.pageService.normalizeParentByPage(page, user);
  259. };
  260. describe('normalizeParentRecursivelyByPages()', () => {
  261. test('should migrate all pages specified by pageIds', async() => {
  262. jest.restoreAllMocks();
  263. const pagesToRun = await Page.find({ path: { $in: ['/private1', '/dummyParent/private1'] } });
  264. // migrate
  265. await normalizeParentRecursivelyByPages(pagesToRun, testUser1);
  266. const migratedPages = await Page.find({
  267. path: {
  268. $in: ['/private1', '/dummyParent', '/dummyParent/private1', '/dummyParent/private1/private2', '/dummyParent/private1/private3'],
  269. },
  270. });
  271. const migratedPagePaths = migratedPages.filter(doc => doc.parent != null).map(doc => doc.path);
  272. const expected = ['/private1', '/dummyParent', '/dummyParent/private1', '/dummyParent/private1/private2', '/dummyParent/private1/private3'];
  273. expect(migratedPagePaths.sort()).toStrictEqual(expected.sort());
  274. });
  275. test('should change all v4 pages with usergroup to v5 compatible and create new parent page', async() => {
  276. const page8 = await Page.findOne({ path: '/normalize_7/normalize_8_gA' });
  277. const page9 = await Page.findOne({ path: '/normalize_7/normalize_8_gA/normalize_9_gB' });
  278. const page10 = await Page.findOne({ path: '/normalize_7/normalize_8_gC' });
  279. const page11 = await Page.findOne({ path: '/normalize_7' });
  280. expect(page8).toBeTruthy();
  281. expect(page9).toBeTruthy();
  282. expect(page10).toBeTruthy();
  283. expect(page11).toBeNull();
  284. await normalizeParentRecursivelyByPages([page8, page9, page10], testUser1);
  285. // AM => After Migration
  286. const page7 = await Page.findOne({ path: '/normalize_7' });
  287. const page8AM = await Page.findOne({ path: '/normalize_7/normalize_8_gA' });
  288. const page9AM = await Page.findOne({ path: '/normalize_7/normalize_8_gA/normalize_9_gB' });
  289. const page10AM = await Page.findOne({ path: '/normalize_7/normalize_8_gC' });
  290. expect(page7).toBeTruthy();
  291. expect(page8AM).toBeTruthy();
  292. expect(page9AM).toBeTruthy();
  293. expect(page10AM).toBeTruthy();
  294. expect(page7.isEmpty).toBe(true);
  295. expect(page7.parent).toStrictEqual(rootPage._id);
  296. expect(page8AM.parent).toStrictEqual(page7._id);
  297. expect(page9AM.parent).toStrictEqual(page8AM._id);
  298. expect(page10AM.parent).toStrictEqual(page7._id);
  299. });
  300. test('should replace empty page with same path with new non-empty page and update all related children\'s parent', async() => {
  301. const page1 = await Page.findOne({ path: '/normalize_10', isEmpty: true, parent: { $ne: null } });
  302. const page2 = await Page.findOne({
  303. path: '/normalize_10/normalize_11_gA', _id: pageId8, isEmpty: true, parent: { $ne: null },
  304. });
  305. const page3 = await Page.findOne({ path: '/normalize_10/normalize_11_gA', _id: pageId9, parent: null }); // not v5
  306. const page4 = await Page.findOne({ path: '/normalize_10/normalize_11_gA/normalize_11_gB', parent: { $ne: null } });
  307. const page5 = await Page.findOne({ path: '/normalize_10/normalize_12_gC', parent: { $ne: null } });
  308. expect(page1).toBeTruthy();
  309. expect(page2).toBeTruthy();
  310. expect(page3).toBeTruthy();
  311. expect(page4).toBeTruthy();
  312. expect(page5).toBeTruthy();
  313. await normalizeParentRecursivelyByPages([page3], testUser1);
  314. // AM => After Migration
  315. const page1AM = await Page.findOne({ path: '/normalize_10' });
  316. const page2AM = await Page.findOne({ path: '/normalize_10/normalize_11_gA', _id: pageId8 });
  317. const page3AM = await Page.findOne({ path: '/normalize_10/normalize_11_gA', _id: pageId9 });
  318. const page4AM = await Page.findOne({ path: '/normalize_10/normalize_11_gA/normalize_11_gB' });
  319. const page5AM = await Page.findOne({ path: '/normalize_10/normalize_12_gC' });
  320. expect(page1AM).toBeTruthy();
  321. expect(page3AM).toBeTruthy();
  322. expect(page4AM).toBeTruthy();
  323. expect(page5AM).toBeTruthy();
  324. expect(page2AM).toBeNull();
  325. expect(page1AM.isEmpty).toBeTruthy();
  326. expect(page3AM.parent).toStrictEqual(page1AM._id);
  327. expect(page4AM.parent).toStrictEqual(page3AM._id);
  328. expect(page5AM.parent).toStrictEqual(page1AM._id);
  329. expect(page3AM.isEmpty).toBe(false);
  330. });
  331. });
  332. describe('should normalize only selected pages recursively (while observing the page permission rule)', () => {
  333. /*
  334. * # Test flow 1
  335. * - Existing pages
  336. * - v5 compatible pages
  337. * - /normalize_a (empty)
  338. * - /normalize_a/normalize_b (public)
  339. * - v4 pages
  340. * - /normalize_a (user group)
  341. * - /normalize_c (user group)
  342. *
  343. * - Normalize /normalize_a (user group)
  344. * - Expect
  345. * - Error should be thrown
  346. *
  347. *
  348. * # Test flow 2
  349. * - Existing pages
  350. * - v5 compatible pages
  351. * - /normalize_d (empty)
  352. * - /normalize_d/normalize_e (user group)
  353. * - v4 pages
  354. * - /normalize_d (user group)
  355. * - /normalize_f (user group)
  356. *
  357. * - Normalize /normalize_d (user group)
  358. * - Expect
  359. * - Normalization succeeds
  360. * - /normalize_f (user group) remains in v4 schema
  361. *
  362. *
  363. * # Test flow 3 (should replace all unnecessary empty pages)
  364. * - Existing pages
  365. * - v5 compatible pages
  366. * - / (root)
  367. * - /normalize_g (public)
  368. * - v4 pages
  369. * - /normalize_g/normalize_h (only me)
  370. * - /normalize_g/normalize_i (only me)
  371. * - /normalize_g/normalize_h/normalize_j (only me)
  372. * - /normalize_g/normalize_i/normalize_k (only me)
  373. *
  374. * - Normalize /normalize_g/normalize_h/normalize_j (only me) & /normalize_g/normalize_i/normalize_k (only me)
  375. * - Expect
  376. * - /normalize_g/normalize_h (empty)
  377. * - parent is /normalize_g (public)
  378. * - /normalize_g/normalize_i (empty)
  379. * - parent is /normalize_g (public)
  380. * - /normalize_g/normalize_h/normalize_j (only me) is normalized
  381. * - /normalize_g/normalize_i/normalize_k (only me) is normalized
  382. */
  383. beforeAll(async() => {
  384. // Prepare data
  385. const id1 = new mongoose.Types.ObjectId();
  386. const id2 = new mongoose.Types.ObjectId();
  387. const id3 = new mongoose.Types.ObjectId();
  388. const id4 = new mongoose.Types.ObjectId();
  389. await Page.insertMany([
  390. // 1
  391. {
  392. _id: id3,
  393. path: '/deep_path',
  394. grant: Page.GRANT_PUBLIC,
  395. parent: rootPage._id,
  396. },
  397. {
  398. _id: id1,
  399. path: '/deep_path/normalize_a',
  400. isEmpty: true,
  401. parent: id3,
  402. },
  403. {
  404. path: '/deep_path/normalize_a/normalize_b',
  405. grant: Page.GRANT_PUBLIC,
  406. parent: id1,
  407. },
  408. {
  409. path: '/deep_path/normalize_a',
  410. grant: Page.GRANT_USER_GROUP,
  411. grantedGroups: [{ item: testUser1GroupId, type: 'UserGroup' }],
  412. parent: null,
  413. },
  414. {
  415. path: '/deep_path/normalize_c',
  416. grant: Page.GRANT_USER_GROUP,
  417. grantedGroups: [{ item: testUser1GroupId, type: 'UserGroup' }],
  418. parent: null,
  419. },
  420. // 2
  421. {
  422. _id: id2,
  423. path: '/normalize_d',
  424. isEmpty: true,
  425. parent: rootPage._id,
  426. },
  427. {
  428. path: '/normalize_d',
  429. grant: Page.GRANT_USER_GROUP,
  430. grantedGroups: [{ item: testUser1GroupId, type: 'UserGroup' }],
  431. parent: null,
  432. },
  433. {
  434. path: '/normalize_d/normalize_e',
  435. grant: Page.GRANT_USER_GROUP,
  436. grantedGroups: [{ item: testUser1GroupId, type: 'UserGroup' }],
  437. parent: id2,
  438. },
  439. {
  440. path: '/normalize_f',
  441. grant: Page.GRANT_USER_GROUP,
  442. grantedGroups: [{ item: testUser1GroupId, type: 'UserGroup' }],
  443. parent: null,
  444. },
  445. // 3
  446. {
  447. _id: id4,
  448. path: '/normalize_g',
  449. parent: rootPage._id,
  450. },
  451. {
  452. path: '/normalize_g/normalize_h',
  453. grant: Page.GRANT_OWNER,
  454. grantedUsers: [testUser1._id],
  455. parent: null,
  456. },
  457. {
  458. path: '/normalize_g/normalize_i',
  459. grant: Page.GRANT_OWNER,
  460. grantedUsers: [testUser1._id],
  461. parent: null,
  462. },
  463. {
  464. path: '/normalize_g/normalize_h/normalize_j',
  465. grant: Page.GRANT_OWNER,
  466. grantedUsers: [testUser1._id],
  467. parent: null,
  468. },
  469. {
  470. path: '/normalize_g/normalize_i/normalize_k',
  471. grant: Page.GRANT_OWNER,
  472. grantedUsers: [testUser1._id],
  473. parent: null,
  474. },
  475. ]);
  476. });
  477. test('should not run normalization when the target page is GRANT_USER_GROUP surrounded by public pages', async() => {
  478. const mockMainOperation = jest.spyOn(crowi.pageService, 'normalizeParentRecursivelyMainOperation').mockImplementation(v => v);
  479. const _page1 = await Page.findOne(onlyPublic({ path: '/deep_path/normalize_a', ...empty }));
  480. const _page2 = await Page.findOne(onlyPublic({ path: '/deep_path/normalize_a/normalize_b', ...normalized }));
  481. const _page3 = await Page.findOne(testUser1Group({ path: '/deep_path/normalize_a', ...notNormalized }));
  482. const _page4 = await Page.findOne(testUser1Group({ path: '/deep_path/normalize_c', ...notNormalized }));
  483. expect(_page1).not.toBeNull();
  484. expect(_page2).not.toBeNull();
  485. expect(_page3).not.toBeNull();
  486. expect(_page4).not.toBeNull();
  487. // Normalize
  488. await normalizeParentRecursivelyByPages([_page3], testUser1);
  489. expect(mockMainOperation).not.toHaveBeenCalled();
  490. mockMainOperation.mockRestore();
  491. });
  492. test('should not include siblings', async() => {
  493. const _page1 = await Page.findOne(onlyPublic({ path: '/normalize_d', ...empty }));
  494. const _page2 = await Page.findOne(testUser1Group({ path: '/normalize_d/normalize_e', ...normalized }));
  495. const _page3 = await Page.findOne(testUser1Group({ path: '/normalize_d', ...notNormalized }));
  496. const _page4 = await Page.findOne(testUser1Group({ path: '/normalize_f', ...notNormalized }));
  497. expect(_page1).not.toBeNull();
  498. expect(_page2).not.toBeNull();
  499. expect(_page3).not.toBeNull();
  500. expect(_page4).not.toBeNull();
  501. // Normalize
  502. await normalizeParentRecursivelyByPages([_page3], testUser1);
  503. const page1 = await Page.findOne(testUser1Group({ path: '/normalize_d/normalize_e' }));
  504. const page2 = await Page.findOne(testUser1Group({ path: '/normalize_d' }));
  505. const page3 = await Page.findOne(testUser1Group({ path: '/normalize_f' }));
  506. const empty4 = await Page.findOne(onlyPublic({ path: '/normalize_d', ...empty }));
  507. expect(page1).not.toBeNull();
  508. expect(page2).not.toBeNull();
  509. expect(page3).not.toBeNull();
  510. expect(empty4).toBeNull(); // empty page should be removed
  511. // Check parent
  512. expect(page1.parent).toStrictEqual(page2._id);
  513. expect(page2.parent).toStrictEqual(rootPage._id);
  514. expect(page3.parent).toBeNull(); // should not be normalized
  515. // Check descendantCount
  516. expect(page1.descendantCount).toBe(0);
  517. expect(page2.descendantCount).toBe(1);
  518. expect(page3.descendantCount).toBe(0); // should not be normalized
  519. });
  520. test('should replace all unnecessary empty pages and normalization succeeds', async() => {
  521. const _pageG = await Page.findOne(onlyPublic({ path: '/normalize_g', ...normalized }));
  522. const _pageGH = await Page.findOne(ownedByTestUser1({ path: '/normalize_g/normalize_h', ...notNormalized }));
  523. const _pageGI = await Page.findOne(ownedByTestUser1({ path: '/normalize_g/normalize_i', ...notNormalized }));
  524. const _pageGHJ = await Page.findOne(ownedByTestUser1({ path: '/normalize_g/normalize_h/normalize_j', ...notNormalized }));
  525. const _pageGIK = await Page.findOne(ownedByTestUser1({ path: '/normalize_g/normalize_i/normalize_k', ...notNormalized }));
  526. expect(_pageG).not.toBeNull();
  527. expect(_pageGH).not.toBeNull();
  528. expect(_pageGI).not.toBeNull();
  529. expect(_pageGHJ).not.toBeNull();
  530. expect(_pageGIK).not.toBeNull();
  531. // Normalize
  532. await normalizeParentRecursivelyByPages([_pageGHJ, _pageGIK], testUser1);
  533. const countG = await Page.count({ path: '/normalize_g' });
  534. const countGH = await Page.count({ path: '/normalize_g/normalize_h' });
  535. const countGI = await Page.count({ path: '/normalize_g/normalize_i' });
  536. const countGHJ = await Page.count({ path: '/normalize_g/normalize_h/normalize_j' });
  537. const countGIK = await Page.count({ path: '/normalize_g/normalize_i/normalize_k' });
  538. expect(countG).toBe(1);
  539. expect(countGH).toBe(2);
  540. expect(countGI).toBe(2);
  541. expect(countGHJ).toBe(1);
  542. expect(countGIK).toBe(1);
  543. // -- normalized pages
  544. const pageG = await Page.findOne(onlyPublic({ path: '/normalize_g' }));
  545. const emptyGH = await Page.findOne({ path: '/normalize_g/normalize_h', ...empty });
  546. const emptyGI = await Page.findOne({ path: '/normalize_g/normalize_i', ...empty });
  547. const pageGHJ = await Page.findOne({ path: '/normalize_g/normalize_h/normalize_j' });
  548. const pageGIK = await Page.findOne({ path: '/normalize_g/normalize_i/normalize_k' });
  549. // Check existence
  550. expect(pageG).not.toBeNull();
  551. expect(pageGHJ).not.toBeNull();
  552. expect(pageGIK).not.toBeNull();
  553. expect(emptyGH).not.toBeNull();
  554. expect(emptyGI).not.toBeNull();
  555. // Check parent
  556. expect(pageG.parent).toStrictEqual(rootPage._id);
  557. expect(emptyGH.parent).toStrictEqual(pageG._id);
  558. expect(emptyGI.parent).toStrictEqual(pageG._id);
  559. expect(pageGHJ.parent).toStrictEqual(emptyGH._id);
  560. expect(pageGIK.parent).toStrictEqual(emptyGI._id);
  561. // Check descendantCount
  562. expect(pageG.descendantCount).toStrictEqual(2);
  563. expect(emptyGH.descendantCount).toStrictEqual(1);
  564. expect(emptyGI.descendantCount).toStrictEqual(1);
  565. expect(pageGHJ.descendantCount).toStrictEqual(0);
  566. expect(pageGIK.descendantCount).toStrictEqual(0);
  567. // -- not normalized pages
  568. const pageGH = await Page.findOne(ownedByTestUser1({ path: '/normalize_g/normalize_h' }));
  569. const pageGI = await Page.findOne(ownedByTestUser1({ path: '/normalize_g/normalize_i' }));
  570. // Check existence
  571. expect(pageGH).not.toBeNull();
  572. expect(pageGI).not.toBeNull();
  573. // Check parent
  574. expect(pageGH.parent).toBeNull(); // should not be normalized
  575. expect(pageGI.parent).toBeNull(); // should not be normalized
  576. // Check descendantCount
  577. expect(pageGH.descendantCount).toStrictEqual(0); // should not be normalized
  578. expect(pageGI.descendantCount).toStrictEqual(0); // should not be normalized
  579. });
  580. });
  581. describe('should normalize only selected pages recursively (especially should NOT normalize non-selected ancestors)', () => {
  582. /*
  583. * # Test flow
  584. * - Existing pages
  585. * - All pages are NOT normalized
  586. * - A, B, C, and D are owned by "testUser1"
  587. * A. /normalize_A_owned
  588. * B. /normalize_A_owned/normalize_B_owned
  589. * C. /normalize_A_owned/normalize_B_owned/normalize_C_owned
  590. * D. /normalize_A_owned/normalize_B_owned/normalize_C_owned/normalize_D_owned
  591. * E. /normalize_A_owned/normalize_B_owned/normalize_C_owned/normalize_D_root
  592. * - Owned by "rootUser"
  593. * F. /normalize_A_owned/normalize_B_owned/normalize_C_owned/normalize_D_group
  594. * - Owned by the userGroup "groupIdIsolate"
  595. *
  596. * 1. Normalize A and B one by one.
  597. * - Expect
  598. * - A and B are normalized
  599. * - C and D are NOT normalized
  600. * - E and F are NOT normalized
  601. * 2. Recursively normalize D.
  602. * - Expect
  603. * - A, B, and D are normalized
  604. * - C is NOT normalized
  605. * - C is substituted by an empty page whose path is "/normalize_A_owned/normalize_B_owned/normalize_C_owned"
  606. * - E and F are NOT normalized
  607. * 3. Recursively normalize C.
  608. * - Expect
  609. * - A, B, C, and D are normalized
  610. * - An empty page at "/normalize_A_owned/normalize_B_owned/normalize_C_owned" does NOT exist (removed)
  611. * - E and F are NOT normalized
  612. */
  613. beforeAll(async() => {
  614. // Prepare data
  615. const id17 = new mongoose.Types.ObjectId();
  616. const id21 = new mongoose.Types.ObjectId();
  617. const id22 = new mongoose.Types.ObjectId();
  618. const id23 = new mongoose.Types.ObjectId();
  619. await Page.insertMany([
  620. // 1
  621. {
  622. path: '/normalize_13_owned',
  623. grant: Page.GRANT_OWNER,
  624. grantedUsers: [testUser1._id],
  625. },
  626. {
  627. path: '/normalize_13_owned/normalize_14_owned',
  628. grant: Page.GRANT_OWNER,
  629. grantedUsers: [testUser1._id],
  630. },
  631. {
  632. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned',
  633. grant: Page.GRANT_OWNER,
  634. grantedUsers: [testUser1._id],
  635. },
  636. {
  637. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_owned',
  638. grant: Page.GRANT_OWNER,
  639. grantedUsers: [testUser1._id],
  640. },
  641. {
  642. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_root',
  643. grant: Page.GRANT_OWNER,
  644. grantedUsers: [rootUser._id],
  645. },
  646. {
  647. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_group',
  648. grant: Page.GRANT_USER_GROUP,
  649. grantedGroups: [{ item: testUser1GroupId, type: 'UserGroup' }],
  650. },
  651. // 2
  652. {
  653. _id: id17,
  654. path: '/normalize_17_owned',
  655. grant: Page.GRANT_OWNER,
  656. grantedUsers: [testUser1._id],
  657. parent: rootPage._id,
  658. },
  659. {
  660. path: '/normalize_17_owned/normalize_18_owned',
  661. grant: Page.GRANT_OWNER,
  662. grantedUsers: [testUser1._id],
  663. parent: id17,
  664. },
  665. {
  666. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned',
  667. grant: Page.GRANT_OWNER,
  668. grantedUsers: [testUser1._id],
  669. },
  670. {
  671. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_owned',
  672. grant: Page.GRANT_OWNER,
  673. grantedUsers: [testUser1._id],
  674. },
  675. {
  676. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_root',
  677. grant: Page.GRANT_OWNER,
  678. grantedUsers: [rootUser._id],
  679. },
  680. {
  681. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_group',
  682. grant: Page.GRANT_USER_GROUP,
  683. grantedGroups: [{ item: rootUserGroupId, type: 'UserGroup' }],
  684. },
  685. // 3
  686. {
  687. _id: id21,
  688. path: '/normalize_21_owned',
  689. grant: Page.GRANT_OWNER,
  690. grantedUsers: [testUser1._id],
  691. parent: rootPage._id,
  692. },
  693. {
  694. _id: id22,
  695. path: '/normalize_21_owned/normalize_22_owned',
  696. grant: Page.GRANT_OWNER,
  697. grantedUsers: [testUser1._id],
  698. parent: id21,
  699. },
  700. {
  701. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned',
  702. grant: Page.GRANT_OWNER,
  703. grantedUsers: [testUser1._id],
  704. parent: null,
  705. },
  706. {
  707. _id: id23,
  708. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned',
  709. isEmpty: true,
  710. parent: id22,
  711. },
  712. {
  713. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_owned',
  714. grant: Page.GRANT_OWNER,
  715. grantedUsers: [testUser1._id],
  716. parent: id23,
  717. },
  718. {
  719. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_root',
  720. grant: Page.GRANT_OWNER,
  721. grantedUsers: [rootUser._id],
  722. },
  723. {
  724. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_rootGroup',
  725. grant: Page.GRANT_USER_GROUP,
  726. grantedGroups: [{ item: rootUserGroupId, type: 'UserGroup' }],
  727. },
  728. ]);
  729. });
  730. test('Should normalize a single page without including other pages', async() => {
  731. const _owned13 = await Page.findOne(ownedByTestUser1({ path: '/normalize_13_owned', ...notNormalized }));
  732. const _owned14 = await Page.findOne(ownedByTestUser1({ path: '/normalize_13_owned/normalize_14_owned', ...notNormalized }));
  733. const _owned15 = await Page.findOne(ownedByTestUser1({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned', ...notNormalized }));
  734. const _owned16 = await Page.findOne(ownedByTestUser1({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_owned', ...notNormalized }));
  735. const _root16 = await Page.findOne(root({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_root', ...notNormalized }));
  736. const _group16 = await Page.findOne(testUser1Group({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_group', ...notNormalized }));
  737. expect(_owned13).not.toBeNull();
  738. expect(_owned14).not.toBeNull();
  739. expect(_owned15).not.toBeNull();
  740. expect(_owned16).not.toBeNull();
  741. expect(_root16).not.toBeNull();
  742. expect(_group16).not.toBeNull();
  743. // Normalize
  744. await normalizeParentByPage(_owned14, testUser1);
  745. const owned13 = await Page.findOne({ path: '/normalize_13_owned' });
  746. const empty13 = await Page.findOne({ path: '/normalize_13_owned', ...empty });
  747. const owned14 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned' });
  748. const owned15 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned' });
  749. const owned16 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_owned' });
  750. const root16 = await Page.findOne(root({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_root' }));
  751. const group16 = await Page.findOne(testUser1Group({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_group' }));
  752. expect(owned13).not.toBeNull();
  753. expect(empty13).not.toBeNull();
  754. expect(owned14).not.toBeNull();
  755. expect(owned15).not.toBeNull();
  756. expect(owned16).not.toBeNull();
  757. expect(root16).not.toBeNull();
  758. expect(group16).not.toBeNull();
  759. // Check parent
  760. expect(owned13.parent).toBeNull();
  761. expect(empty13.parent).toStrictEqual(rootPage._id);
  762. expect(owned14.parent).toStrictEqual(empty13._id);
  763. expect(owned15.parent).toBeNull();
  764. expect(owned16.parent).toBeNull();
  765. expect(root16.parent).toBeNull();
  766. expect(group16.parent).toBeNull();
  767. // Check descendantCount
  768. expect(owned13.descendantCount).toBe(0);
  769. expect(empty13.descendantCount).toBe(1);
  770. expect(owned14.descendantCount).toBe(0);
  771. });
  772. test('Should normalize pages recursively excluding the pages not selected', async() => {
  773. const _owned17 = await Page.findOne(ownedByTestUser1({ path: '/normalize_17_owned', ...normalized }));
  774. const _owned18 = await Page.findOne(ownedByTestUser1({ path: '/normalize_17_owned/normalize_18_owned', ...normalized }));
  775. const _owned19 = await Page.findOne(ownedByTestUser1({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned', ...notNormalized }));
  776. const _owned20 = await Page.findOne(ownedByTestUser1({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_owned', ...notNormalized }));
  777. const _root20 = await Page.findOne(root({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_root', ...notNormalized }));
  778. const _group20 = await Page.findOne(rootUserGroup({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_group', ...notNormalized }));
  779. expect(_owned17).not.toBeNull();
  780. expect(_owned18).not.toBeNull();
  781. expect(_owned19).not.toBeNull();
  782. expect(_owned20).not.toBeNull();
  783. expect(_root20).not.toBeNull();
  784. expect(_group20).not.toBeNull();
  785. // Normalize
  786. await normalizeParentRecursivelyByPages([_owned20], testUser1);
  787. const owned17 = await Page.findOne({ path: '/normalize_17_owned' });
  788. const owned18 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned' });
  789. const owned19 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned' });
  790. const empty19 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned', ...empty });
  791. const owned20 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_owned' });
  792. const root20 = await Page.findOne(root({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_root' }));
  793. const group20 = await Page.findOne(rootUserGroup({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_group' }));
  794. expect(owned17).not.toBeNull();
  795. expect(owned18).not.toBeNull();
  796. expect(owned19).not.toBeNull();
  797. expect(empty19).not.toBeNull();
  798. expect(owned20).not.toBeNull();
  799. expect(root20).not.toBeNull();
  800. expect(group20).not.toBeNull();
  801. // Check parent
  802. expect(owned17.parent).toStrictEqual(rootPage._id);
  803. expect(owned18.parent).toStrictEqual(owned17._id);
  804. expect(owned19.parent).toBeNull();
  805. expect(empty19.parent).toStrictEqual(owned18._id);
  806. expect(owned20.parent).toStrictEqual(empty19._id);
  807. expect(root20.parent).toBeNull();
  808. expect(group20.parent).toBeNull();
  809. // Check isEmpty
  810. expect(owned17.isEmpty).toBe(false);
  811. expect(owned18.isEmpty).toBe(false);
  812. });
  813. test('Should normalize pages recursively excluding the pages of not user\'s & Should delete unnecessary empty pages', async() => {
  814. const _owned21 = await Page.findOne(ownedByTestUser1({ path: '/normalize_21_owned', ...normalized }));
  815. const _owned22 = await Page.findOne(ownedByTestUser1({ path: '/normalize_21_owned/normalize_22_owned', ...normalized }));
  816. const _owned23 = await Page.findOne(ownedByTestUser1({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...notNormalized }));
  817. const _empty23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...normalized, ...empty });
  818. const _owned24 = await Page.findOne(ownedByTestUser1({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_owned', ...normalized }));
  819. const _root24 = await Page.findOne(root({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_root', ...notNormalized }));
  820. const _rootGroup24 = await Page.findOne(rootUserGroup({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_rootGroup', ...notNormalized }));
  821. expect(_owned21).not.toBeNull();
  822. expect(_owned22).not.toBeNull();
  823. expect(_owned23).not.toBeNull();
  824. expect(_empty23).not.toBeNull();
  825. expect(_owned24).not.toBeNull();
  826. expect(_root24).not.toBeNull();
  827. expect(_rootGroup24).not.toBeNull();
  828. // Normalize
  829. await normalizeParentRecursivelyByPages([_owned23], testUser1);
  830. const owned21 = await Page.findOne({ path: '/normalize_21_owned' });
  831. const owned22 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned' });
  832. const owned23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned' });
  833. const empty23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...empty });
  834. const owned24 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_owned' });
  835. const root24 = await Page.findOne(root({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_root' }));
  836. const rootGroup24 = await Page.findOne(rootUserGroup({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_rootGroup' }));
  837. expect(owned21).not.toBeNull();
  838. expect(owned22).not.toBeNull();
  839. expect(owned23).not.toBeNull();
  840. expect(empty23).toBeNull(); // removed
  841. expect(owned24).not.toBeNull();
  842. expect(root24).not.toBeNull();
  843. expect(rootGroup24).not.toBeNull();
  844. // Check parent
  845. expect(owned21.parent).toStrictEqual(rootPage._id);
  846. expect(owned22.parent).toStrictEqual(owned21._id);
  847. expect(owned23.parent).toStrictEqual(owned22._id);
  848. expect(owned24.parent).toStrictEqual(owned23._id); // not empty23._id
  849. expect(root24.parent).toBeNull();
  850. expect(rootGroup24.parent).toBeNull(); // excluded from the pages to be normalized
  851. // Check isEmpty
  852. expect(owned21.isEmpty).toBe(false);
  853. expect(owned22.isEmpty).toBe(false);
  854. expect(owned23.isEmpty).toBe(false);
  855. });
  856. });
  857. describe('normalizeAllPublicPages()', () => {
  858. jest.setTimeout(60000);
  859. let createPagePaths;
  860. let allPossiblePagePaths;
  861. beforeAll(async() => {
  862. createPagePaths = [
  863. '/publicA', '/publicA/privateB', '/publicA/privateB/publicC', '/parenthesis/(a)[b]{c}d', '/parenthesis/(a)[b]{c}d/public', '/migratedD',
  864. ];
  865. allPossiblePagePaths = [...createPagePaths, '/parenthesis', '/'];
  866. // initialize pages for test
  867. await Page.insertMany([
  868. {
  869. path: '/publicA',
  870. grant: Page.GRANT_PUBLIC,
  871. creator: testUser1,
  872. lastUpdateUser: testUser1,
  873. },
  874. {
  875. path: '/publicA/privateB',
  876. grant: Page.GRANT_OWNER,
  877. creator: testUser1,
  878. lastUpdateUser: testUser1,
  879. grantedUsers: [testUser1._id],
  880. },
  881. {
  882. path: '/publicA/privateB/publicC',
  883. grant: Page.GRANT_PUBLIC,
  884. creator: testUser1,
  885. lastUpdateUser: testUser1,
  886. },
  887. {
  888. path: '/parenthesis/(a)[b]{c}d',
  889. grant: Page.GRANT_PUBLIC,
  890. creator: testUser1,
  891. lastUpdateUser: testUser1,
  892. },
  893. {
  894. path: '/parenthesis/(a)[b]{c}d/public',
  895. grant: Page.GRANT_PUBLIC,
  896. creator: testUser1,
  897. lastUpdateUser: testUser1,
  898. },
  899. ]);
  900. const parent = await Page.find({ path: '/' });
  901. await Page.insertMany([
  902. {
  903. path: '/migratedD',
  904. grant: Page.GRANT_PUBLIC,
  905. creator: testUser1,
  906. lastUpdateUser: testUser1,
  907. parent: parent._id,
  908. },
  909. ]);
  910. // migrate
  911. await crowi.pageService.normalizeAllPublicPages(Page.GRANT_PUBLIC);
  912. jest.setTimeout(30000);
  913. });
  914. test('should migrate all public pages', async() => {
  915. const migratedPages = await Page.find({
  916. path: {
  917. $in: allPossiblePagePaths,
  918. },
  919. parent: { $ne: null },
  920. });
  921. const migratedEmptyPages = await Page.find({
  922. path: {
  923. $in: allPossiblePagePaths,
  924. },
  925. isEmpty: true,
  926. parent: { $ne: null },
  927. });
  928. const nonMigratedPages = await Page.find({
  929. path: {
  930. $in: allPossiblePagePaths,
  931. },
  932. parent: null,
  933. });
  934. const migratedPaths = migratedPages.map(page => page.path).sort();
  935. const migratedEmptyPaths = migratedEmptyPages.map(page => page.path).sort();
  936. const nonMigratedPaths = nonMigratedPages.map(page => page.path).sort();
  937. const expectedMigratedPaths = allPossiblePagePaths.filter(path => path !== '/').sort();
  938. const expectedMigratedEmptyPaths = ['/publicA/privateB', '/parenthesis'].sort();
  939. const expectedNonMigratedPaths = ['/publicA/privateB', '/'].sort();
  940. expect(migratedPaths).toStrictEqual(expectedMigratedPaths);
  941. expect(migratedEmptyPaths).toStrictEqual(expectedMigratedEmptyPaths);
  942. expect(nonMigratedPaths).toStrictEqual(expectedNonMigratedPaths);
  943. });
  944. });
  945. describe('normalizeParentByPage()', () => {
  946. test('it should normalize not v5 page with usergroup that has parent group', async() => {
  947. const page1 = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  948. const page2 = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2', parent: page1._id });
  949. const page3 = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // NOT v5
  950. expect(page1).toBeTruthy();
  951. expect(page2).toBeTruthy();
  952. expect(page3).toBeTruthy();
  953. await normalizeParentByPage(page3, testUser1);
  954. // AM => After Migration
  955. const page1AM = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  956. const page2AM = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2' });
  957. const page3AM = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // v5 compatible
  958. expect(page2AM).toBeTruthy();
  959. expect(page3AM).toBeTruthy();
  960. expect(page1AM).toBeNull();
  961. expect(page2AM.parent).toStrictEqual(page3AM._id);
  962. expect(page3AM.parent).toStrictEqual(rootPage._id);
  963. });
  964. test('should throw error if a page with isolated group becomes the parent of other page with different group after normalizing', async() => {
  965. const page4 = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  966. const page5 = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  967. const page6 = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  968. expect(page4).toBeTruthy();
  969. expect(page5).toBeTruthy();
  970. expect(page6).toBeTruthy();
  971. let isThrown;
  972. try {
  973. await normalizeParentByPage(page6, testUser1);
  974. }
  975. catch (err) {
  976. isThrown = true;
  977. }
  978. // AM => After Migration
  979. const page4AM = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  980. const page5AM = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  981. const page6AM = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  982. expect(isThrown).toBe(true);
  983. expect(page4AM).toBeTruthy();
  984. expect(page5AM).toBeTruthy();
  985. expect(page6AM).toBeTruthy();
  986. expect(page4AM).toStrictEqual(page4);
  987. expect(page5AM).toStrictEqual(page5);
  988. expect(page6AM).toStrictEqual(page6);
  989. });
  990. });
  991. test('replace private parents with empty pages', async() => {
  992. const replacedPathPages = await Page.find({ path: '/publicA/privateB' }); // ex-private page
  993. const _newEmptyPage = replacedPathPages.filter(page => page.parent != null)[0];
  994. const newEmptyPage = {
  995. path: _newEmptyPage.path,
  996. grant: _newEmptyPage.grant,
  997. isEmpty: _newEmptyPage.isEmpty,
  998. };
  999. const expectedNewEmptyPage = {
  1000. path: '/publicA/privateB',
  1001. grant: Page.GRANT_PUBLIC,
  1002. isEmpty: true,
  1003. };
  1004. const _privatePage = replacedPathPages.filter(page => page.parent == null)[0];
  1005. const privatePage = {
  1006. path: _privatePage.path,
  1007. grant: _privatePage.grant,
  1008. isEmpty: _privatePage.isEmpty,
  1009. };
  1010. const expectedPrivatePage = {
  1011. path: '/publicA/privateB',
  1012. grant: Page.GRANT_OWNER,
  1013. isEmpty: false,
  1014. };
  1015. expect(replacedPathPages.length).toBe(2);
  1016. expect(newEmptyPage).toStrictEqual(expectedNewEmptyPage);
  1017. expect(privatePage).toStrictEqual(expectedPrivatePage);
  1018. });
  1019. describe('normalizeParentByPath', () => {
  1020. const normalizeParentByPath = async(path, user) => {
  1021. const mock = jest.spyOn(crowi.pageService, 'normalizeParentRecursivelyMainOperation').mockReturnValue(null);
  1022. const result = await crowi.pageService.normalizeParentByPath(path, user);
  1023. const args = mock.mock.calls[0];
  1024. mock.mockRestore();
  1025. await crowi.pageService.normalizeParentRecursivelyMainOperation(...args);
  1026. return result;
  1027. };
  1028. beforeAll(async() => {
  1029. const pageIdD = new mongoose.Types.ObjectId();
  1030. const pageIdG = new mongoose.Types.ObjectId();
  1031. await Page.insertMany([
  1032. {
  1033. path: '/norm_parent_by_path_A',
  1034. grant: Page.GRANT_OWNER,
  1035. grantedUsers: [testUser1._id],
  1036. creator: testUser1._id,
  1037. lastUpdateUser: testUser1._id,
  1038. parent: rootPage._id,
  1039. },
  1040. {
  1041. path: '/norm_parent_by_path_B/norm_parent_by_path_C',
  1042. grant: Page.GRANT_OWNER,
  1043. grantedUsers: [rootUser._id],
  1044. creator: rootUser._id,
  1045. lastUpdateUser: rootUser._id,
  1046. },
  1047. {
  1048. _id: pageIdD,
  1049. path: '/norm_parent_by_path_D',
  1050. isEmpty: true,
  1051. parent: rootPage._id,
  1052. descendantCount: 1,
  1053. },
  1054. {
  1055. path: '/norm_parent_by_path_D/norm_parent_by_path_E',
  1056. grant: Page.GRANT_PUBLIC,
  1057. creator: rootUser._id,
  1058. lastUpdateUser: rootUser._id,
  1059. parent: pageIdD,
  1060. },
  1061. {
  1062. path: '/norm_parent_by_path_D/norm_parent_by_path_F',
  1063. grant: Page.GRANT_OWNER,
  1064. grantedUsers: [rootUser._id],
  1065. creator: rootUser._id,
  1066. lastUpdateUser: rootUser._id,
  1067. },
  1068. {
  1069. _id: pageIdG,
  1070. path: '/norm_parent_by_path_G',
  1071. grant: Page.GRANT_PUBLIC,
  1072. creator: rootUser._id,
  1073. lastUpdateUser: rootUser._id,
  1074. parent: rootPage._id,
  1075. descendantCount: 1,
  1076. },
  1077. {
  1078. path: '/norm_parent_by_path_G/norm_parent_by_path_H',
  1079. grant: Page.GRANT_PUBLIC,
  1080. creator: rootUser._id,
  1081. lastUpdateUser: rootUser._id,
  1082. parent: pageIdG,
  1083. },
  1084. {
  1085. path: '/norm_parent_by_path_G/norm_parent_by_path_I',
  1086. grant: Page.GRANT_OWNER,
  1087. grantedUsers: [rootUser._id],
  1088. creator: rootUser._id,
  1089. lastUpdateUser: rootUser._id,
  1090. },
  1091. ]);
  1092. });
  1093. test('should fail when the user is not allowed to edit the target page found by path', async() => {
  1094. const pageTestUser1 = await Page.findOne(ownedByTestUser1({ path: '/norm_parent_by_path_A' }));
  1095. expect(pageTestUser1).not.toBeNull();
  1096. await expect(normalizeParentByPath('/norm_parent_by_path_A', rootUser)).rejects.toThrowError();
  1097. });
  1098. test('should normalize all granted pages under the path when no page exists at the path', async() => {
  1099. const _pageB = await Page.findOne({ path: '/norm_parent_by_path_B' });
  1100. const _pageBC = await Page.findOne(root({ path: '/norm_parent_by_path_B/norm_parent_by_path_C' }));
  1101. expect(_pageB).toBeNull();
  1102. expect(_pageBC).not.toBeNull();
  1103. await normalizeParentByPath('/norm_parent_by_path_B', rootUser);
  1104. const pagesB = await Page.find({ path: '/norm_parent_by_path_B' }); // did not exist before running normalizeParentByPath
  1105. const pageBC = await Page.findById(_pageBC._id);
  1106. // -- check count
  1107. expect(pagesB.length).toBe(1);
  1108. const pageB = pagesB[0];
  1109. // -- check existance
  1110. expect(pageB.path).toBe('/norm_parent_by_path_B');
  1111. expect(pageBC.path).toBe('/norm_parent_by_path_B/norm_parent_by_path_C');
  1112. // -- check parent
  1113. expect(pageB.parent).toStrictEqual(rootPage._id);
  1114. expect(pageBC.parent).toStrictEqual(pageB._id);
  1115. // -- check descendantCount
  1116. expect(pageB.descendantCount).toBe(1);
  1117. expect(pageBC.descendantCount).toBe(0);
  1118. });
  1119. test('should normalize all granted pages under the path when an empty page exists at the path', async() => {
  1120. const _emptyD = await Page.findOne({ path: '/norm_parent_by_path_D', ...empty, ...normalized });
  1121. const _pageDE = await Page.findOne(onlyPublic({ path: '/norm_parent_by_path_D/norm_parent_by_path_E', ...normalized }));
  1122. const _pageDF = await Page.findOne(root({ path: '/norm_parent_by_path_D/norm_parent_by_path_F', ...notNormalized }));
  1123. expect(_emptyD).not.toBeNull();
  1124. expect(_pageDE).not.toBeNull();
  1125. expect(_pageDF).not.toBeNull();
  1126. await normalizeParentByPath('/norm_parent_by_path_D', rootUser);
  1127. const countD = await Page.count({ path: '/norm_parent_by_path_D' });
  1128. // -- check count
  1129. expect(countD).toBe(1);
  1130. const pageD = await Page.findById(_emptyD._id);
  1131. const pageDE = await Page.findById(_pageDE._id);
  1132. const pageDF = await Page.findById(_pageDF._id);
  1133. // -- check existance
  1134. expect(pageD.path).toBe('/norm_parent_by_path_D');
  1135. expect(pageDE.path).toBe('/norm_parent_by_path_D/norm_parent_by_path_E');
  1136. expect(pageDF.path).toBe('/norm_parent_by_path_D/norm_parent_by_path_F');
  1137. // -- check isEmpty of pageD
  1138. // pageD should not be empty because growi system will create a non-empty page while running normalizeParentByPath
  1139. expect(pageD.isEmpty).toBe(false);
  1140. // -- check parent
  1141. expect(pageD.parent).toStrictEqual(rootPage._id);
  1142. expect(pageDE.parent).toStrictEqual(pageD._id);
  1143. expect(pageDF.parent).toStrictEqual(pageD._id);
  1144. // -- check descendantCount
  1145. expect(pageD.descendantCount).toBe(2);
  1146. expect(pageDE.descendantCount).toBe(0);
  1147. expect(pageDF.descendantCount).toBe(0);
  1148. });
  1149. test('should normalize all granted pages under the path when a non-empty page exists at the path', async() => {
  1150. const _pageG = await Page.findOne(onlyPublic({ path: '/norm_parent_by_path_G', ...normalized }));
  1151. const _pageGH = await Page.findOne(onlyPublic({ path: '/norm_parent_by_path_G/norm_parent_by_path_H', ...normalized }));
  1152. const _pageGI = await Page.findOne(root({ path: '/norm_parent_by_path_G/norm_parent_by_path_I', ...notNormalized }));
  1153. expect(_pageG).not.toBeNull();
  1154. expect(_pageGH).not.toBeNull();
  1155. expect(_pageGI).not.toBeNull();
  1156. await normalizeParentByPath('/norm_parent_by_path_G', rootUser);
  1157. const countG = await Page.count({ path: '/norm_parent_by_path_G' });
  1158. // -- check count
  1159. expect(countG).toBe(1);
  1160. const pageG = await Page.findById(_pageG._id);
  1161. const pageGH = await Page.findById(_pageGH._id);
  1162. const pageGI = await Page.findById(_pageGI._id);
  1163. // -- check existance
  1164. expect(pageG.path).toBe('/norm_parent_by_path_G');
  1165. expect(pageGH.path).toBe('/norm_parent_by_path_G/norm_parent_by_path_H');
  1166. expect(pageGI.path).toBe('/norm_parent_by_path_G/norm_parent_by_path_I');
  1167. // -- check parent
  1168. expect(pageG.parent).toStrictEqual(rootPage._id);
  1169. expect(pageGH.parent).toStrictEqual(pageG._id);
  1170. expect(pageGI.parent).toStrictEqual(pageG._id);
  1171. // -- check descendantCount
  1172. expect(pageG.descendantCount).toBe(2);
  1173. expect(pageGH.descendantCount).toBe(0);
  1174. expect(pageGI.descendantCount).toBe(0);
  1175. });
  1176. });
  1177. });