v5.migration.test.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  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. beforeAll(async() => {
  31. jest.restoreAllMocks();
  32. crowi = await getInstance();
  33. Page = mongoose.model('Page');
  34. User = mongoose.model('User');
  35. UserGroup = mongoose.model('UserGroup');
  36. UserGroupRelation = mongoose.model('UserGroupRelation');
  37. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', { 'app:isV5Compatible': true });
  38. await User.insertMany([
  39. { name: 'rootUser', username: 'rootUser', email: 'rootUser@example.com' },
  40. { name: 'testUser1', username: 'testUser1', email: 'testUser1@example.com' },
  41. ]);
  42. rootUser = await User.findOne({ username: 'rootUser' });
  43. testUser1 = await User.findOne({ username: 'testUser1' });
  44. rootPage = await Page.findOne({ path: '/' });
  45. await UserGroup.insertMany([
  46. {
  47. _id: rootUserGroupId,
  48. name: 'rootUserGroup',
  49. },
  50. {
  51. _id: testUser1GroupId,
  52. name: 'testUser1Group',
  53. },
  54. {
  55. _id: groupIdIsolate,
  56. name: 'groupIsolate',
  57. },
  58. {
  59. _id: groupIdA,
  60. name: 'groupA',
  61. },
  62. {
  63. _id: groupIdB,
  64. name: 'groupB',
  65. parent: groupIdA,
  66. },
  67. {
  68. _id: groupIdC,
  69. name: 'groupC',
  70. parent: groupIdB,
  71. },
  72. ]);
  73. await UserGroupRelation.insertMany([
  74. {
  75. relatedGroup: rootUserGroupId,
  76. relatedUser: rootUser._id,
  77. },
  78. {
  79. relatedGroup: testUser1GroupId,
  80. relatedUser: testUser1._id,
  81. },
  82. {
  83. relatedGroup: groupIdIsolate,
  84. relatedUser: testUser1._id,
  85. },
  86. {
  87. relatedGroup: groupIdA,
  88. relatedUser: testUser1._id,
  89. },
  90. {
  91. relatedGroup: groupIdB,
  92. relatedUser: testUser1._id,
  93. },
  94. {
  95. relatedGroup: groupIdC,
  96. relatedUser: testUser1._id,
  97. },
  98. ]);
  99. await Page.insertMany([
  100. {
  101. path: '/private1',
  102. grant: Page.GRANT_OWNER,
  103. creator: testUser1,
  104. lastUpdateUser: testUser1,
  105. grantedUsers: [testUser1._id],
  106. },
  107. {
  108. path: '/dummyParent/private1',
  109. grant: Page.GRANT_OWNER,
  110. creator: testUser1,
  111. lastUpdateUser: testUser1,
  112. grantedUsers: [testUser1._id],
  113. },
  114. {
  115. path: '/dummyParent/private1/private2',
  116. grant: Page.GRANT_OWNER,
  117. creator: testUser1,
  118. lastUpdateUser: testUser1,
  119. grantedUsers: [testUser1._id],
  120. },
  121. {
  122. path: '/dummyParent/private1/private3',
  123. grant: Page.GRANT_OWNER,
  124. creator: testUser1,
  125. lastUpdateUser: testUser1,
  126. grantedUsers: [testUser1._id],
  127. },
  128. {
  129. _id: pageId1,
  130. path: '/normalize_1',
  131. parent: rootPage._id,
  132. grant: Page.GRANT_PUBLIC,
  133. isEmpty: true,
  134. },
  135. {
  136. _id: pageId2,
  137. path: '/normalize_1/normalize_2',
  138. parent: pageId1,
  139. grant: Page.GRANT_USER_GROUP,
  140. grantedGroup: groupIdB,
  141. grantedUsers: [testUser1._id],
  142. },
  143. {
  144. _id: pageId3,
  145. path: '/normalize_1',
  146. grant: Page.GRANT_USER_GROUP,
  147. grantedGroup: groupIdA,
  148. grantedUsers: [testUser1._id],
  149. },
  150. {
  151. _id: pageId4,
  152. path: '/normalize_4',
  153. parent: rootPage._id,
  154. grant: Page.GRANT_PUBLIC,
  155. isEmpty: true,
  156. },
  157. {
  158. _id: pageId5,
  159. path: '/normalize_4/normalize_5',
  160. parent: pageId4,
  161. grant: Page.GRANT_USER_GROUP,
  162. grantedGroup: groupIdA,
  163. grantedUsers: [testUser1._id],
  164. },
  165. {
  166. _id: pageId6,
  167. path: '/normalize_4',
  168. grant: Page.GRANT_USER_GROUP,
  169. grantedGroup: groupIdIsolate,
  170. grantedUsers: [testUser1._id],
  171. },
  172. {
  173. path: '/normalize_7/normalize_8_gA',
  174. grant: Page.GRANT_USER_GROUP,
  175. creator: testUser1,
  176. grantedGroup: groupIdA,
  177. grantedUsers: [testUser1._id],
  178. },
  179. {
  180. path: '/normalize_7/normalize_8_gA/normalize_9_gB',
  181. grant: Page.GRANT_USER_GROUP,
  182. creator: testUser1,
  183. grantedGroup: groupIdB,
  184. grantedUsers: [testUser1._id],
  185. },
  186. {
  187. path: '/normalize_7/normalize_8_gC',
  188. grant: Page.GRANT_USER_GROUP,
  189. grantedGroup: groupIdC,
  190. grantedUsers: [testUser1._id],
  191. },
  192. {
  193. _id: pageId7,
  194. path: '/normalize_10',
  195. grant: Page.GRANT_PUBLIC,
  196. isEmpty: true,
  197. parent: rootPage._id,
  198. descendantCount: 3,
  199. },
  200. {
  201. _id: pageId8,
  202. path: '/normalize_10/normalize_11_gA',
  203. isEmpty: true,
  204. parent: pageId7,
  205. descendantCount: 1,
  206. },
  207. {
  208. _id: pageId9, // not v5
  209. path: '/normalize_10/normalize_11_gA',
  210. grant: Page.GRANT_USER_GROUP,
  211. grantedGroup: groupIdA,
  212. grantedUsers: [testUser1._id],
  213. },
  214. {
  215. _id: pageId10,
  216. path: '/normalize_10/normalize_11_gA/normalize_11_gB',
  217. grant: Page.GRANT_USER_GROUP,
  218. grantedGroup: groupIdB,
  219. grantedUsers: [testUser1._id],
  220. parent: pageId8,
  221. descendantCount: 0,
  222. },
  223. {
  224. _id: pageId11,
  225. path: '/normalize_10/normalize_12_gC',
  226. grant: Page.GRANT_USER_GROUP,
  227. grantedGroup: groupIdC,
  228. grantedUsers: [testUser1._id],
  229. parent: pageId7,
  230. descendantCount: 0,
  231. },
  232. ]);
  233. });
  234. // https://github.com/jest-community/eslint-plugin-jest/blob/v24.3.5/docs/rules/expect-expect.md#assertfunctionnames
  235. // pass unless the data is one of [false, 0, '', null, undefined, NaN]
  236. const expectAllToBeTruthy = (dataList) => {
  237. dataList.forEach((data, i) => {
  238. if (data == null) { console.log(`index: ${i}`) }
  239. expect(data).toBeTruthy();
  240. });
  241. };
  242. const normalizeParentRecursivelyByPages = async(pages, user) => {
  243. return crowi.pageService.normalizeParentRecursivelyByPages(pages, user);
  244. };
  245. const normalizeParentByPage = async(page, user) => {
  246. return crowi.pageService.normalizeParentByPage(page, user);
  247. };
  248. describe('normalizeParentRecursivelyByPages()', () => {
  249. test('should migrate all pages specified by pageIds', async() => {
  250. jest.restoreAllMocks();
  251. const pagesToRun = await Page.find({ path: { $in: ['/private1', '/dummyParent/private1'] } });
  252. // migrate
  253. await normalizeParentRecursivelyByPages(pagesToRun, testUser1);
  254. const migratedPages = await Page.find({
  255. path: {
  256. $in: ['/private1', '/dummyParent', '/dummyParent/private1', '/dummyParent/private1/private2', '/dummyParent/private1/private3'],
  257. },
  258. });
  259. const migratedPagePaths = migratedPages.filter(doc => doc.parent != null).map(doc => doc.path);
  260. const expected = ['/private1', '/dummyParent', '/dummyParent/private1', '/dummyParent/private1/private2', '/dummyParent/private1/private3'];
  261. expect(migratedPagePaths.sort()).toStrictEqual(expected.sort());
  262. });
  263. test('should change all v4 pages with usergroup to v5 compatible and create new parent page', async() => {
  264. const page8 = await Page.findOne({ path: '/normalize_7/normalize_8_gA' });
  265. const page9 = await Page.findOne({ path: '/normalize_7/normalize_8_gA/normalize_9_gB' });
  266. const page10 = await Page.findOne({ path: '/normalize_7/normalize_8_gC' });
  267. const page11 = await Page.findOne({ path: '/normalize_7' });
  268. expectAllToBeTruthy([page8, page9, page10]);
  269. expect(page11).toBeNull();
  270. await normalizeParentRecursivelyByPages([page8, page9, page10], testUser1);
  271. // AM => After Migration
  272. const page7 = await Page.findOne({ path: '/normalize_7' });
  273. const page8AM = await Page.findOne({ path: '/normalize_7/normalize_8_gA' });
  274. const page9AM = await Page.findOne({ path: '/normalize_7/normalize_8_gA/normalize_9_gB' });
  275. const page10AM = await Page.findOne({ path: '/normalize_7/normalize_8_gC' });
  276. expectAllToBeTruthy([page7, page8AM, page9AM, page10AM]);
  277. expect(page7.isEmpty).toBe(true);
  278. expect(page7.parent).toStrictEqual(rootPage._id);
  279. expect(page8AM.parent).toStrictEqual(page7._id);
  280. expect(page9AM.parent).toStrictEqual(page8AM._id);
  281. expect(page10AM.parent).toStrictEqual(page7._id);
  282. });
  283. test('should replace empty page with same path with new non-empty page and update all related children\'s parent', async() => {
  284. const page1 = await Page.findOne({ path: '/normalize_10', isEmpty: true, parent: { $ne: null } });
  285. const page2 = await Page.findOne({
  286. path: '/normalize_10/normalize_11_gA', _id: pageId8, isEmpty: true, parent: { $ne: null },
  287. });
  288. const page3 = await Page.findOne({ path: '/normalize_10/normalize_11_gA', _id: pageId9, parent: null }); // not v5
  289. const page4 = await Page.findOne({ path: '/normalize_10/normalize_11_gA/normalize_11_gB', parent: { $ne: null } });
  290. const page5 = await Page.findOne({ path: '/normalize_10/normalize_12_gC', parent: { $ne: null } });
  291. expectAllToBeTruthy([page1, page2, page3, page4, page5]);
  292. await normalizeParentRecursivelyByPages([page3], testUser1);
  293. // AM => After Migration
  294. const page1AM = await Page.findOne({ path: '/normalize_10' });
  295. const page2AM = await Page.findOne({ path: '/normalize_10/normalize_11_gA', _id: pageId8 });
  296. const page3AM = await Page.findOne({ path: '/normalize_10/normalize_11_gA', _id: pageId9 });
  297. const page4AM = await Page.findOne({ path: '/normalize_10/normalize_11_gA/normalize_11_gB' });
  298. const page5AM = await Page.findOne({ path: '/normalize_10/normalize_12_gC' });
  299. expectAllToBeTruthy([page1AM, page3AM, page4AM, page5AM]);
  300. expect(page2AM).toBeNull();
  301. expect(page1AM.isEmpty).toBeTruthy();
  302. expect(page3AM.parent).toStrictEqual(page1AM._id);
  303. expect(page4AM.parent).toStrictEqual(page3AM._id);
  304. expect(page5AM.parent).toStrictEqual(page1AM._id);
  305. expect(page3AM.isEmpty).toBe(false);
  306. });
  307. });
  308. describe('should normalize only selected pages recursively (especially should NOT normalize non-selected ancestors)', () => {
  309. /*
  310. * # Test flow
  311. * - Existing pages
  312. * - All pages are NOT normalized
  313. * - A, B, C, and D are owned by "testUser1"
  314. * A. /normalize_A_owned
  315. * B. /normalize_A_owned/normalize_B_owned
  316. * C. /normalize_A_owned/normalize_B_owned/normalize_C_owned
  317. * D. /normalize_A_owned/normalize_B_owned/normalize_C_owned/normalize_D_owned
  318. * E. /normalize_A_owned/normalize_B_owned/normalize_C_owned/normalize_D_root
  319. * - Owned by "rootUser"
  320. * F. /normalize_A_owned/normalize_B_owned/normalize_C_owned/normalize_D_group
  321. * - Owned by the userGroup "groupIdIsolate"
  322. *
  323. * 1. Normalize A and B one by one.
  324. * - Expect
  325. * - A and B are normalized
  326. * - C and D are NOT normalized
  327. * - E and F are NOT normalized
  328. * 2. Recursively normalize D.
  329. * - Expect
  330. * - A, B, and D are normalized
  331. * - C is NOT normalized
  332. * - C is substituted by an empty page whose path is "/normalize_A_owned/normalize_B_owned/normalize_C_owned"
  333. * - E and F are NOT normalized
  334. * 3. Recursively normalize C.
  335. * - Expect
  336. * - A, B, C, and D are normalized
  337. * - An empty page at "/normalize_A_owned/normalize_B_owned/normalize_C_owned" does NOT exist (removed)
  338. * - E and F are NOT normalized
  339. */
  340. const owned = filter => ({ grantedUsers: [testUser1._id], ...filter });
  341. const root = filter => ({ grantedUsers: [rootUser._id], ...filter });
  342. const rootUserGroup = filter => ({ grantedGroup: rootUserGroupId, ...filter });
  343. const testUser1Group = filter => ({ grantedGroup: testUser1GroupId, ...filter });
  344. const normalized = { parent: { $ne: null } };
  345. const notNormalized = { parent: null };
  346. const empty = { isEmpty: true };
  347. beforeAll(async() => {
  348. // Prepare data
  349. const id17 = new mongoose.Types.ObjectId();
  350. const id21 = new mongoose.Types.ObjectId();
  351. const id22 = new mongoose.Types.ObjectId();
  352. const id23 = new mongoose.Types.ObjectId();
  353. await Page.insertMany([
  354. // 1
  355. {
  356. path: '/normalize_13_owned',
  357. grant: Page.GRANT_OWNER,
  358. grantedUsers: [testUser1._id],
  359. },
  360. {
  361. path: '/normalize_13_owned/normalize_14_owned',
  362. grant: Page.GRANT_OWNER,
  363. grantedUsers: [testUser1._id],
  364. },
  365. {
  366. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned',
  367. grant: Page.GRANT_OWNER,
  368. grantedUsers: [testUser1._id],
  369. },
  370. {
  371. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_owned',
  372. grant: Page.GRANT_OWNER,
  373. grantedUsers: [testUser1._id],
  374. },
  375. {
  376. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_root',
  377. grant: Page.GRANT_OWNER,
  378. grantedUsers: [rootUser._id],
  379. },
  380. {
  381. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_group',
  382. grant: Page.GRANT_USER_GROUP,
  383. grantedGroup: testUser1GroupId,
  384. },
  385. // 2
  386. {
  387. _id: id17,
  388. path: '/normalize_17_owned',
  389. grant: Page.GRANT_OWNER,
  390. grantedUsers: [testUser1._id],
  391. parent: rootPage._id,
  392. },
  393. {
  394. path: '/normalize_17_owned/normalize_18_owned',
  395. grant: Page.GRANT_OWNER,
  396. grantedUsers: [testUser1._id],
  397. parent: id17,
  398. },
  399. {
  400. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned',
  401. grant: Page.GRANT_OWNER,
  402. grantedUsers: [testUser1._id],
  403. },
  404. {
  405. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_owned',
  406. grant: Page.GRANT_OWNER,
  407. grantedUsers: [testUser1._id],
  408. },
  409. {
  410. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_root',
  411. grant: Page.GRANT_OWNER,
  412. grantedUsers: [rootUser._id],
  413. },
  414. {
  415. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_group',
  416. grant: Page.GRANT_USER_GROUP,
  417. grantedGroup: rootUserGroupId,
  418. },
  419. // 3
  420. {
  421. _id: id21,
  422. path: '/normalize_21_owned',
  423. grant: Page.GRANT_OWNER,
  424. grantedUsers: [testUser1._id],
  425. parent: rootPage._id,
  426. },
  427. {
  428. _id: id22,
  429. path: '/normalize_21_owned/normalize_22_owned',
  430. grant: Page.GRANT_OWNER,
  431. grantedUsers: [testUser1._id],
  432. parent: id21,
  433. },
  434. {
  435. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned',
  436. grant: Page.GRANT_OWNER,
  437. grantedUsers: [testUser1._id],
  438. parent: null,
  439. },
  440. {
  441. _id: id23,
  442. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned',
  443. isEmpty: true,
  444. parent: id22,
  445. },
  446. {
  447. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_owned',
  448. grant: Page.GRANT_OWNER,
  449. grantedUsers: [testUser1._id],
  450. parent: id23,
  451. },
  452. {
  453. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_root',
  454. grant: Page.GRANT_OWNER,
  455. grantedUsers: [rootUser._id],
  456. },
  457. {
  458. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_rootGroup',
  459. grant: Page.GRANT_USER_GROUP,
  460. grantedGroup: rootUserGroupId,
  461. },
  462. ]);
  463. });
  464. test('Should normalize pages one by one without including other pages', async() => {
  465. const _owned13 = await Page.findOne(owned({ path: '/normalize_13_owned', ...notNormalized }));
  466. const _owned14 = await Page.findOne(owned({ path: '/normalize_13_owned/normalize_14_owned', ...notNormalized }));
  467. const _owned15 = await Page.findOne(owned({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned', ...notNormalized }));
  468. const _owned16 = await Page.findOne(owned({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_owned', ...notNormalized }));
  469. const _root16 = await Page.findOne(root({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_root', ...notNormalized }));
  470. const _group16 = await Page.findOne(testUser1Group({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_group', ...notNormalized }));
  471. expect(_owned13).not.toBeNull();
  472. expect(_owned14).not.toBeNull();
  473. expect(_owned15).not.toBeNull();
  474. expect(_owned16).not.toBeNull();
  475. expect(_root16).not.toBeNull();
  476. expect(_group16).not.toBeNull();
  477. // Normalize
  478. await normalizeParentByPage(_owned14, testUser1);
  479. const owned13 = await Page.findOne({ path: '/normalize_13_owned' });
  480. const empty13 = await Page.findOne({ path: '/normalize_13_owned', ...empty });
  481. const owned14 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned' });
  482. const owned15 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned' });
  483. const owned16 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_owned' });
  484. const root16 = await Page.findOne(root({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_root' }));
  485. const group16 = await Page.findOne(testUser1Group({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_group' }));
  486. expect(owned13).not.toBeNull();
  487. expect(empty13).not.toBeNull();
  488. expect(owned14).not.toBeNull();
  489. expect(owned15).not.toBeNull();
  490. expect(owned16).not.toBeNull();
  491. expect(root16).not.toBeNull();
  492. expect(group16).not.toBeNull();
  493. // Check parent
  494. expect(owned13.parent).toBeNull();
  495. expect(empty13.parent).toStrictEqual(rootPage._id);
  496. expect(owned14.parent).toStrictEqual(empty13._id);
  497. expect(owned15.parent).toBeNull();
  498. expect(owned16.parent).toBeNull();
  499. expect(root16.parent).toBeNull();
  500. expect(group16.parent).toBeNull();
  501. // Check descendantCount
  502. expect(owned13.descendantCount).toBe(0);
  503. expect(empty13.descendantCount).toBe(1);
  504. expect(owned14.descendantCount).toBe(0);
  505. });
  506. test('Should normalize pages recursively excluding the pages not selected', async() => {
  507. const _owned17 = await Page.findOne(owned({ path: '/normalize_17_owned', ...normalized }));
  508. const _owned18 = await Page.findOne(owned({ path: '/normalize_17_owned/normalize_18_owned', ...normalized }));
  509. const _owned19 = await Page.findOne(owned({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned', ...notNormalized }));
  510. const _owned20 = await Page.findOne(owned({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_owned', ...notNormalized }));
  511. const _root20 = await Page.findOne(root({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_root', ...notNormalized }));
  512. const _group20 = await Page.findOne(rootUserGroup({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_group', ...notNormalized }));
  513. expect(_owned17).not.toBeNull();
  514. expect(_owned18).not.toBeNull();
  515. expect(_owned19).not.toBeNull();
  516. expect(_owned20).not.toBeNull();
  517. expect(_root20).not.toBeNull();
  518. expect(_group20).not.toBeNull();
  519. // Normalize
  520. await normalizeParentRecursivelyByPages([_owned20], testUser1);
  521. const owned17 = await Page.findOne({ path: '/normalize_17_owned' });
  522. const owned18 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned' });
  523. const owned19 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned' });
  524. const empty19 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned', ...empty });
  525. const owned20 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_owned' });
  526. const root20 = await Page.findOne(root({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_root' }));
  527. const group20 = await Page.findOne(rootUserGroup({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_group' }));
  528. expect(owned17).not.toBeNull();
  529. expect(owned18).not.toBeNull();
  530. expect(owned19).not.toBeNull();
  531. expect(empty19).not.toBeNull();
  532. expect(owned20).not.toBeNull();
  533. expect(root20).not.toBeNull();
  534. expect(group20).not.toBeNull();
  535. // Check parent
  536. expect(owned17.parent).toStrictEqual(rootPage._id);
  537. expect(owned18.parent).toStrictEqual(owned17._id);
  538. expect(owned19.parent).toBeNull();
  539. expect(empty19.parent).toStrictEqual(owned18._id);
  540. expect(owned20.parent).toStrictEqual(empty19._id);
  541. expect(root20.parent).toBeNull();
  542. expect(group20.parent).toBeNull();
  543. // Check isEmpty
  544. expect(owned17.isEmpty).toBe(false);
  545. expect(owned18.isEmpty).toBe(false);
  546. });
  547. test('Should normalize pages recursively excluding the pages of not user\'s & Should delete unnecessary empty pages', async() => {
  548. const _owned21 = await Page.findOne(owned({ path: '/normalize_21_owned', ...normalized }));
  549. const _owned22 = await Page.findOne(owned({ path: '/normalize_21_owned/normalize_22_owned', ...normalized }));
  550. const _owned23 = await Page.findOne(owned({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...notNormalized }));
  551. const _empty23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...normalized, ...empty });
  552. const _owned24 = await Page.findOne(owned({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_owned', ...normalized }));
  553. const _root24 = await Page.findOne(root({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_root', ...notNormalized }));
  554. const _rootGroup24 = await Page.findOne(rootUserGroup({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_rootGroup', ...notNormalized }));
  555. expect(_owned21).not.toBeNull();
  556. expect(_owned22).not.toBeNull();
  557. expect(_owned23).not.toBeNull();
  558. expect(_empty23).not.toBeNull();
  559. expect(_owned24).not.toBeNull();
  560. expect(_root24).not.toBeNull();
  561. expect(_rootGroup24).not.toBeNull();
  562. // Normalize
  563. await normalizeParentRecursivelyByPages([_owned23], testUser1);
  564. const owned21 = await Page.findOne({ path: '/normalize_21_owned' });
  565. const owned22 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned' });
  566. const owned23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned' });
  567. const empty23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...empty });
  568. const owned24 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_owned' });
  569. const root24 = await Page.findOne(root({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_root' }));
  570. const rootGroup24 = await Page.findOne(rootUserGroup({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_rootGroup' }));
  571. expect(owned21).not.toBeNull();
  572. expect(owned22).not.toBeNull();
  573. expect(owned23).not.toBeNull();
  574. expect(empty23).toBeNull(); // removed
  575. expect(owned24).not.toBeNull();
  576. expect(root24).not.toBeNull();
  577. expect(rootGroup24).not.toBeNull();
  578. // Check parent
  579. expect(owned21.parent).toStrictEqual(rootPage._id);
  580. expect(owned22.parent).toStrictEqual(owned21._id);
  581. expect(owned23.parent).toStrictEqual(owned22._id);
  582. expect(owned24.parent).toStrictEqual(owned23._id); // not empty23._id
  583. expect(root24.parent).toBeNull();
  584. expect(rootGroup24.parent).toBeNull(); // excluded from the pages to be normalized
  585. // Check isEmpty
  586. expect(owned21.isEmpty).toBe(false);
  587. expect(owned22.isEmpty).toBe(false);
  588. expect(owned23.isEmpty).toBe(false);
  589. });
  590. });
  591. describe('normalizeAllPublicPages()', () => {
  592. jest.setTimeout(60000);
  593. let createPagePaths;
  594. let allPossiblePagePaths;
  595. beforeAll(async() => {
  596. createPagePaths = [
  597. '/publicA', '/publicA/privateB', '/publicA/privateB/publicC', '/parenthesis/(a)[b]{c}d', '/parenthesis/(a)[b]{c}d/public', '/migratedD',
  598. ];
  599. allPossiblePagePaths = [...createPagePaths, '/parenthesis', '/'];
  600. // initialize pages for test
  601. await Page.insertMany([
  602. {
  603. path: '/publicA',
  604. grant: Page.GRANT_PUBLIC,
  605. creator: testUser1,
  606. lastUpdateUser: testUser1,
  607. },
  608. {
  609. path: '/publicA/privateB',
  610. grant: Page.GRANT_OWNER,
  611. creator: testUser1,
  612. lastUpdateUser: testUser1,
  613. grantedUsers: [testUser1._id],
  614. },
  615. {
  616. path: '/publicA/privateB/publicC',
  617. grant: Page.GRANT_PUBLIC,
  618. creator: testUser1,
  619. lastUpdateUser: testUser1,
  620. },
  621. {
  622. path: '/parenthesis/(a)[b]{c}d',
  623. grant: Page.GRANT_PUBLIC,
  624. creator: testUser1,
  625. lastUpdateUser: testUser1,
  626. },
  627. {
  628. path: '/parenthesis/(a)[b]{c}d/public',
  629. grant: Page.GRANT_PUBLIC,
  630. creator: testUser1,
  631. lastUpdateUser: testUser1,
  632. },
  633. ]);
  634. const parent = await Page.find({ path: '/' });
  635. await Page.insertMany([
  636. {
  637. path: '/migratedD',
  638. grant: Page.GRANT_PUBLIC,
  639. creator: testUser1,
  640. lastUpdateUser: testUser1,
  641. parent: parent._id,
  642. },
  643. ]);
  644. // migrate
  645. await crowi.pageService.normalizeAllPublicPages(Page.GRANT_PUBLIC);
  646. jest.setTimeout(30000);
  647. });
  648. test('should migrate all public pages', async() => {
  649. const migratedPages = await Page.find({
  650. path: {
  651. $in: allPossiblePagePaths,
  652. },
  653. parent: { $ne: null },
  654. });
  655. const migratedEmptyPages = await Page.find({
  656. path: {
  657. $in: allPossiblePagePaths,
  658. },
  659. isEmpty: true,
  660. parent: { $ne: null },
  661. });
  662. const nonMigratedPages = await Page.find({
  663. path: {
  664. $in: allPossiblePagePaths,
  665. },
  666. parent: null,
  667. });
  668. const migratedPaths = migratedPages.map(page => page.path).sort();
  669. const migratedEmptyPaths = migratedEmptyPages.map(page => page.path).sort();
  670. const nonMigratedPaths = nonMigratedPages.map(page => page.path).sort();
  671. const expectedMigratedPaths = allPossiblePagePaths.filter(path => path !== '/').sort();
  672. const expectedMigratedEmptyPaths = ['/publicA/privateB', '/parenthesis'].sort();
  673. const expectedNonMigratedPaths = ['/publicA/privateB', '/'].sort();
  674. expect(migratedPaths).toStrictEqual(expectedMigratedPaths);
  675. expect(migratedEmptyPaths).toStrictEqual(expectedMigratedEmptyPaths);
  676. expect(nonMigratedPaths).toStrictEqual(expectedNonMigratedPaths);
  677. });
  678. });
  679. describe('normalizeParentByPage()', () => {
  680. test('it should normalize not v5 page with usergroup that has parent group', async() => {
  681. const page1 = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  682. const page2 = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2', parent: page1._id });
  683. const page3 = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // NOT v5
  684. expectAllToBeTruthy([page1, page2, page3]);
  685. await normalizeParentByPage(page3, testUser1);
  686. // AM => After Migration
  687. const page1AM = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  688. const page2AM = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2' });
  689. const page3AM = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // v5 compatible
  690. expectAllToBeTruthy([page2AM, page3AM]);
  691. expect(page1AM).toBeNull();
  692. expect(page2AM.parent).toStrictEqual(page3AM._id);
  693. expect(page3AM.parent).toStrictEqual(rootPage._id);
  694. });
  695. test('should throw error if a page with isolated group becomes the parent of other page with different gourp after normalizing', async() => {
  696. const page4 = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  697. const page5 = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  698. const page6 = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  699. expectAllToBeTruthy([page4, page5, page6]);
  700. let isThrown;
  701. try {
  702. await normalizeParentByPage(page6, testUser1);
  703. }
  704. catch (err) {
  705. isThrown = true;
  706. }
  707. // AM => After Migration
  708. const page4AM = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  709. const page5AM = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  710. const page6AM = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  711. expectAllToBeTruthy([page4AM, page5AM, page6AM]);
  712. expect(isThrown).toBe(true);
  713. expect(page4AM).toStrictEqual(page4);
  714. expect(page5AM).toStrictEqual(page5);
  715. expect(page6AM).toStrictEqual(page6);
  716. });
  717. });
  718. test('replace private parents with empty pages', async() => {
  719. const replacedPathPages = await Page.find({ path: '/publicA/privateB' }); // ex-private page
  720. const _newEmptyPage = replacedPathPages.filter(page => page.parent != null)[0];
  721. const newEmptyPage = {
  722. path: _newEmptyPage.path,
  723. grant: _newEmptyPage.grant,
  724. isEmpty: _newEmptyPage.isEmpty,
  725. };
  726. const expectedNewEmptyPage = {
  727. path: '/publicA/privateB',
  728. grant: Page.GRANT_PUBLIC,
  729. isEmpty: true,
  730. };
  731. const _privatePage = replacedPathPages.filter(page => page.parent == null)[0];
  732. const privatePage = {
  733. path: _privatePage.path,
  734. grant: _privatePage.grant,
  735. isEmpty: _privatePage.isEmpty,
  736. };
  737. const expectedPrivatePage = {
  738. path: '/publicA/privateB',
  739. grant: Page.GRANT_OWNER,
  740. isEmpty: false,
  741. };
  742. expect(replacedPathPages.length).toBe(2);
  743. expect(newEmptyPage).toStrictEqual(expectedNewEmptyPage);
  744. expect(privatePage).toStrictEqual(expectedPrivatePage);
  745. });
  746. });