v5.migration.test.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  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. const normalizeParentRecursivelyByPages = async(pages, user) => {
  235. return crowi.pageService.normalizeParentRecursivelyByPages(pages, user);
  236. };
  237. const normalizeParentByPage = async(page, user) => {
  238. return crowi.pageService.normalizeParentByPage(page, user);
  239. };
  240. describe('normalizeParentRecursivelyByPages()', () => {
  241. test('should migrate all pages specified by pageIds', async() => {
  242. jest.restoreAllMocks();
  243. const pagesToRun = await Page.find({ path: { $in: ['/private1', '/dummyParent/private1'] } });
  244. // migrate
  245. await normalizeParentRecursivelyByPages(pagesToRun, testUser1);
  246. const migratedPages = await Page.find({
  247. path: {
  248. $in: ['/private1', '/dummyParent', '/dummyParent/private1', '/dummyParent/private1/private2', '/dummyParent/private1/private3'],
  249. },
  250. });
  251. const migratedPagePaths = migratedPages.filter(doc => doc.parent != null).map(doc => doc.path);
  252. const expected = ['/private1', '/dummyParent', '/dummyParent/private1', '/dummyParent/private1/private2', '/dummyParent/private1/private3'];
  253. expect(migratedPagePaths.sort()).toStrictEqual(expected.sort());
  254. });
  255. test('should change all v4 pages with usergroup to v5 compatible and create new parent page', async() => {
  256. const page8 = await Page.findOne({ path: '/normalize_7/normalize_8_gA' });
  257. const page9 = await Page.findOne({ path: '/normalize_7/normalize_8_gA/normalize_9_gB' });
  258. const page10 = await Page.findOne({ path: '/normalize_7/normalize_8_gC' });
  259. const page11 = await Page.findOne({ path: '/normalize_7' });
  260. expect(page8).toBeTruthy();
  261. expect(page9).toBeTruthy();
  262. expect(page10).toBeTruthy();
  263. expect(page11).toBeNull();
  264. await normalizeParentRecursivelyByPages([page8, page9, page10], testUser1);
  265. // AM => After Migration
  266. const page7 = await Page.findOne({ path: '/normalize_7' });
  267. const page8AM = await Page.findOne({ path: '/normalize_7/normalize_8_gA' });
  268. const page9AM = await Page.findOne({ path: '/normalize_7/normalize_8_gA/normalize_9_gB' });
  269. const page10AM = await Page.findOne({ path: '/normalize_7/normalize_8_gC' });
  270. expect(page7).toBeTruthy();
  271. expect(page8AM).toBeTruthy();
  272. expect(page9AM).toBeTruthy();
  273. expect(page10AM).toBeTruthy();
  274. expect(page7.isEmpty).toBe(true);
  275. expect(page7.parent).toStrictEqual(rootPage._id);
  276. expect(page8AM.parent).toStrictEqual(page7._id);
  277. expect(page9AM.parent).toStrictEqual(page8AM._id);
  278. expect(page10AM.parent).toStrictEqual(page7._id);
  279. });
  280. test('should replace empty page with same path with new non-empty page and update all related children\'s parent', async() => {
  281. const page1 = await Page.findOne({ path: '/normalize_10', isEmpty: true, parent: { $ne: null } });
  282. const page2 = await Page.findOne({
  283. path: '/normalize_10/normalize_11_gA', _id: pageId8, isEmpty: true, parent: { $ne: null },
  284. });
  285. const page3 = await Page.findOne({ path: '/normalize_10/normalize_11_gA', _id: pageId9, parent: null }); // not v5
  286. const page4 = await Page.findOne({ path: '/normalize_10/normalize_11_gA/normalize_11_gB', parent: { $ne: null } });
  287. const page5 = await Page.findOne({ path: '/normalize_10/normalize_12_gC', parent: { $ne: null } });
  288. expect(page1).toBeTruthy();
  289. expect(page2).toBeTruthy();
  290. expect(page3).toBeTruthy();
  291. expect(page4).toBeTruthy();
  292. expect(page5).toBeTruthy();
  293. await normalizeParentRecursivelyByPages([page3], testUser1);
  294. // AM => After Migration
  295. const page1AM = await Page.findOne({ path: '/normalize_10' });
  296. const page2AM = await Page.findOne({ path: '/normalize_10/normalize_11_gA', _id: pageId8 });
  297. const page3AM = await Page.findOne({ path: '/normalize_10/normalize_11_gA', _id: pageId9 });
  298. const page4AM = await Page.findOne({ path: '/normalize_10/normalize_11_gA/normalize_11_gB' });
  299. const page5AM = await Page.findOne({ path: '/normalize_10/normalize_12_gC' });
  300. expect(page1AM).toBeTruthy();
  301. expect(page3AM).toBeTruthy();
  302. expect(page4AM).toBeTruthy();
  303. expect(page5AM).toBeTruthy();
  304. expect(page2AM).toBeNull();
  305. expect(page1AM.isEmpty).toBeTruthy();
  306. expect(page3AM.parent).toStrictEqual(page1AM._id);
  307. expect(page4AM.parent).toStrictEqual(page3AM._id);
  308. expect(page5AM.parent).toStrictEqual(page1AM._id);
  309. expect(page3AM.isEmpty).toBe(false);
  310. });
  311. });
  312. describe('should normalize only selected pages recursively (especially should NOT normalize non-selected ancestors)', () => {
  313. /*
  314. * # Test flow
  315. * - Existing pages
  316. * - All pages are NOT normalized
  317. * - A, B, C, and D are owned by "testUser1"
  318. * A. /normalize_A_owned
  319. * B. /normalize_A_owned/normalize_B_owned
  320. * C. /normalize_A_owned/normalize_B_owned/normalize_C_owned
  321. * D. /normalize_A_owned/normalize_B_owned/normalize_C_owned/normalize_D_owned
  322. * E. /normalize_A_owned/normalize_B_owned/normalize_C_owned/normalize_D_root
  323. * - Owned by "rootUser"
  324. * F. /normalize_A_owned/normalize_B_owned/normalize_C_owned/normalize_D_group
  325. * - Owned by the userGroup "groupIdIsolate"
  326. *
  327. * 1. Normalize A and B one by one.
  328. * - Expect
  329. * - A and B are normalized
  330. * - C and D are NOT normalized
  331. * - E and F are NOT normalized
  332. * 2. Recursively normalize D.
  333. * - Expect
  334. * - A, B, and D are normalized
  335. * - C is NOT normalized
  336. * - C is substituted by an empty page whose path is "/normalize_A_owned/normalize_B_owned/normalize_C_owned"
  337. * - E and F are NOT normalized
  338. * 3. Recursively normalize C.
  339. * - Expect
  340. * - A, B, C, and D are normalized
  341. * - An empty page at "/normalize_A_owned/normalize_B_owned/normalize_C_owned" does NOT exist (removed)
  342. * - E and F are NOT normalized
  343. */
  344. const owned = filter => ({ grantedUsers: [testUser1._id], ...filter });
  345. const root = filter => ({ grantedUsers: [rootUser._id], ...filter });
  346. const rootUserGroup = filter => ({ grantedGroup: rootUserGroupId, ...filter });
  347. const testUser1Group = filter => ({ grantedGroup: testUser1GroupId, ...filter });
  348. const normalized = { parent: { $ne: null } };
  349. const notNormalized = { parent: null };
  350. const empty = { isEmpty: true };
  351. beforeAll(async() => {
  352. // Prepare data
  353. const id17 = new mongoose.Types.ObjectId();
  354. const id21 = new mongoose.Types.ObjectId();
  355. const id22 = new mongoose.Types.ObjectId();
  356. const id23 = new mongoose.Types.ObjectId();
  357. await Page.insertMany([
  358. // 1
  359. {
  360. path: '/normalize_13_owned',
  361. grant: Page.GRANT_OWNER,
  362. grantedUsers: [testUser1._id],
  363. },
  364. {
  365. path: '/normalize_13_owned/normalize_14_owned',
  366. grant: Page.GRANT_OWNER,
  367. grantedUsers: [testUser1._id],
  368. },
  369. {
  370. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned',
  371. grant: Page.GRANT_OWNER,
  372. grantedUsers: [testUser1._id],
  373. },
  374. {
  375. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_owned',
  376. grant: Page.GRANT_OWNER,
  377. grantedUsers: [testUser1._id],
  378. },
  379. {
  380. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_root',
  381. grant: Page.GRANT_OWNER,
  382. grantedUsers: [rootUser._id],
  383. },
  384. {
  385. path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_group',
  386. grant: Page.GRANT_USER_GROUP,
  387. grantedGroup: testUser1GroupId,
  388. },
  389. // 2
  390. {
  391. _id: id17,
  392. path: '/normalize_17_owned',
  393. grant: Page.GRANT_OWNER,
  394. grantedUsers: [testUser1._id],
  395. parent: rootPage._id,
  396. },
  397. {
  398. path: '/normalize_17_owned/normalize_18_owned',
  399. grant: Page.GRANT_OWNER,
  400. grantedUsers: [testUser1._id],
  401. parent: id17,
  402. },
  403. {
  404. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned',
  405. grant: Page.GRANT_OWNER,
  406. grantedUsers: [testUser1._id],
  407. },
  408. {
  409. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_owned',
  410. grant: Page.GRANT_OWNER,
  411. grantedUsers: [testUser1._id],
  412. },
  413. {
  414. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_root',
  415. grant: Page.GRANT_OWNER,
  416. grantedUsers: [rootUser._id],
  417. },
  418. {
  419. path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_group',
  420. grant: Page.GRANT_USER_GROUP,
  421. grantedGroup: rootUserGroupId,
  422. },
  423. // 3
  424. {
  425. _id: id21,
  426. path: '/normalize_21_owned',
  427. grant: Page.GRANT_OWNER,
  428. grantedUsers: [testUser1._id],
  429. parent: rootPage._id,
  430. },
  431. {
  432. _id: id22,
  433. path: '/normalize_21_owned/normalize_22_owned',
  434. grant: Page.GRANT_OWNER,
  435. grantedUsers: [testUser1._id],
  436. parent: id21,
  437. },
  438. {
  439. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned',
  440. grant: Page.GRANT_OWNER,
  441. grantedUsers: [testUser1._id],
  442. parent: null,
  443. },
  444. {
  445. _id: id23,
  446. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned',
  447. isEmpty: true,
  448. parent: id22,
  449. },
  450. {
  451. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_owned',
  452. grant: Page.GRANT_OWNER,
  453. grantedUsers: [testUser1._id],
  454. parent: id23,
  455. },
  456. {
  457. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_root',
  458. grant: Page.GRANT_OWNER,
  459. grantedUsers: [rootUser._id],
  460. },
  461. {
  462. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_rootGroup',
  463. grant: Page.GRANT_USER_GROUP,
  464. grantedGroup: rootUserGroupId,
  465. },
  466. ]);
  467. });
  468. test('Should normalize pages one by one without including other pages', async() => {
  469. const _owned13 = await Page.findOne(owned({ path: '/normalize_13_owned', ...notNormalized }));
  470. const _owned14 = await Page.findOne(owned({ path: '/normalize_13_owned/normalize_14_owned', ...notNormalized }));
  471. const _owned15 = await Page.findOne(owned({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned', ...notNormalized }));
  472. const _owned16 = await Page.findOne(owned({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_owned', ...notNormalized }));
  473. const _root16 = await Page.findOne(root({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_root', ...notNormalized }));
  474. const _group16 = await Page.findOne(testUser1Group({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_group', ...notNormalized }));
  475. expect(_owned13).not.toBeNull();
  476. expect(_owned14).not.toBeNull();
  477. expect(_owned15).not.toBeNull();
  478. expect(_owned16).not.toBeNull();
  479. expect(_root16).not.toBeNull();
  480. expect(_group16).not.toBeNull();
  481. // Normalize
  482. await normalizeParentByPage(_owned14, testUser1);
  483. const owned13 = await Page.findOne({ path: '/normalize_13_owned' });
  484. const empty13 = await Page.findOne({ path: '/normalize_13_owned', ...empty });
  485. const owned14 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned' });
  486. const owned15 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned' });
  487. const owned16 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_owned' });
  488. const root16 = await Page.findOne(root({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_root' }));
  489. const group16 = await Page.findOne(testUser1Group({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_group' }));
  490. expect(owned13).not.toBeNull();
  491. expect(empty13).not.toBeNull();
  492. expect(owned14).not.toBeNull();
  493. expect(owned15).not.toBeNull();
  494. expect(owned16).not.toBeNull();
  495. expect(root16).not.toBeNull();
  496. expect(group16).not.toBeNull();
  497. // Check parent
  498. expect(owned13.parent).toBeNull();
  499. expect(empty13.parent).toStrictEqual(rootPage._id);
  500. expect(owned14.parent).toStrictEqual(empty13._id);
  501. expect(owned15.parent).toBeNull();
  502. expect(owned16.parent).toBeNull();
  503. expect(root16.parent).toBeNull();
  504. expect(group16.parent).toBeNull();
  505. // Check descendantCount
  506. expect(owned13.descendantCount).toBe(0);
  507. expect(empty13.descendantCount).toBe(1);
  508. expect(owned14.descendantCount).toBe(0);
  509. });
  510. test('Should normalize pages recursively excluding the pages not selected', async() => {
  511. const _owned17 = await Page.findOne(owned({ path: '/normalize_17_owned', ...normalized }));
  512. const _owned18 = await Page.findOne(owned({ path: '/normalize_17_owned/normalize_18_owned', ...normalized }));
  513. const _owned19 = await Page.findOne(owned({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned', ...notNormalized }));
  514. const _owned20 = await Page.findOne(owned({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_owned', ...notNormalized }));
  515. const _root20 = await Page.findOne(root({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_root', ...notNormalized }));
  516. const _group20 = await Page.findOne(rootUserGroup({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_group', ...notNormalized }));
  517. expect(_owned17).not.toBeNull();
  518. expect(_owned18).not.toBeNull();
  519. expect(_owned19).not.toBeNull();
  520. expect(_owned20).not.toBeNull();
  521. expect(_root20).not.toBeNull();
  522. expect(_group20).not.toBeNull();
  523. // Normalize
  524. await normalizeParentRecursivelyByPages([_owned20], testUser1);
  525. const owned17 = await Page.findOne({ path: '/normalize_17_owned' });
  526. const owned18 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned' });
  527. const owned19 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned' });
  528. const empty19 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned', ...empty });
  529. const owned20 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_owned' });
  530. const root20 = await Page.findOne(root({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_root' }));
  531. const group20 = await Page.findOne(rootUserGroup({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_group' }));
  532. expect(owned17).not.toBeNull();
  533. expect(owned18).not.toBeNull();
  534. expect(owned19).not.toBeNull();
  535. expect(empty19).not.toBeNull();
  536. expect(owned20).not.toBeNull();
  537. expect(root20).not.toBeNull();
  538. expect(group20).not.toBeNull();
  539. // Check parent
  540. expect(owned17.parent).toStrictEqual(rootPage._id);
  541. expect(owned18.parent).toStrictEqual(owned17._id);
  542. expect(owned19.parent).toBeNull();
  543. expect(empty19.parent).toStrictEqual(owned18._id);
  544. expect(owned20.parent).toStrictEqual(empty19._id);
  545. expect(root20.parent).toBeNull();
  546. expect(group20.parent).toBeNull();
  547. // Check isEmpty
  548. expect(owned17.isEmpty).toBe(false);
  549. expect(owned18.isEmpty).toBe(false);
  550. });
  551. test('Should normalize pages recursively excluding the pages of not user\'s & Should delete unnecessary empty pages', async() => {
  552. const _owned21 = await Page.findOne(owned({ path: '/normalize_21_owned', ...normalized }));
  553. const _owned22 = await Page.findOne(owned({ path: '/normalize_21_owned/normalize_22_owned', ...normalized }));
  554. const _owned23 = await Page.findOne(owned({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...notNormalized }));
  555. const _empty23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...normalized, ...empty });
  556. const _owned24 = await Page.findOne(owned({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_owned', ...normalized }));
  557. const _root24 = await Page.findOne(root({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_root', ...notNormalized }));
  558. const _rootGroup24 = await Page.findOne(rootUserGroup({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_rootGroup', ...notNormalized }));
  559. expect(_owned21).not.toBeNull();
  560. expect(_owned22).not.toBeNull();
  561. expect(_owned23).not.toBeNull();
  562. expect(_empty23).not.toBeNull();
  563. expect(_owned24).not.toBeNull();
  564. expect(_root24).not.toBeNull();
  565. expect(_rootGroup24).not.toBeNull();
  566. // Normalize
  567. await normalizeParentRecursivelyByPages([_owned23], testUser1);
  568. const owned21 = await Page.findOne({ path: '/normalize_21_owned' });
  569. const owned22 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned' });
  570. const owned23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned' });
  571. const empty23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...empty });
  572. const owned24 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_owned' });
  573. const root24 = await Page.findOne(root({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_root' }));
  574. const rootGroup24 = await Page.findOne(rootUserGroup({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_rootGroup' }));
  575. expect(owned21).not.toBeNull();
  576. expect(owned22).not.toBeNull();
  577. expect(owned23).not.toBeNull();
  578. expect(empty23).toBeNull(); // removed
  579. expect(owned24).not.toBeNull();
  580. expect(root24).not.toBeNull();
  581. expect(rootGroup24).not.toBeNull();
  582. // Check parent
  583. expect(owned21.parent).toStrictEqual(rootPage._id);
  584. expect(owned22.parent).toStrictEqual(owned21._id);
  585. expect(owned23.parent).toStrictEqual(owned22._id);
  586. expect(owned24.parent).toStrictEqual(owned23._id); // not empty23._id
  587. expect(root24.parent).toBeNull();
  588. expect(rootGroup24.parent).toBeNull(); // excluded from the pages to be normalized
  589. // Check isEmpty
  590. expect(owned21.isEmpty).toBe(false);
  591. expect(owned22.isEmpty).toBe(false);
  592. expect(owned23.isEmpty).toBe(false);
  593. });
  594. });
  595. describe('normalizeAllPublicPages()', () => {
  596. jest.setTimeout(60000);
  597. let createPagePaths;
  598. let allPossiblePagePaths;
  599. beforeAll(async() => {
  600. createPagePaths = [
  601. '/publicA', '/publicA/privateB', '/publicA/privateB/publicC', '/parenthesis/(a)[b]{c}d', '/parenthesis/(a)[b]{c}d/public', '/migratedD',
  602. ];
  603. allPossiblePagePaths = [...createPagePaths, '/parenthesis', '/'];
  604. // initialize pages for test
  605. await Page.insertMany([
  606. {
  607. path: '/publicA',
  608. grant: Page.GRANT_PUBLIC,
  609. creator: testUser1,
  610. lastUpdateUser: testUser1,
  611. },
  612. {
  613. path: '/publicA/privateB',
  614. grant: Page.GRANT_OWNER,
  615. creator: testUser1,
  616. lastUpdateUser: testUser1,
  617. grantedUsers: [testUser1._id],
  618. },
  619. {
  620. path: '/publicA/privateB/publicC',
  621. grant: Page.GRANT_PUBLIC,
  622. creator: testUser1,
  623. lastUpdateUser: testUser1,
  624. },
  625. {
  626. path: '/parenthesis/(a)[b]{c}d',
  627. grant: Page.GRANT_PUBLIC,
  628. creator: testUser1,
  629. lastUpdateUser: testUser1,
  630. },
  631. {
  632. path: '/parenthesis/(a)[b]{c}d/public',
  633. grant: Page.GRANT_PUBLIC,
  634. creator: testUser1,
  635. lastUpdateUser: testUser1,
  636. },
  637. ]);
  638. const parent = await Page.find({ path: '/' });
  639. await Page.insertMany([
  640. {
  641. path: '/migratedD',
  642. grant: Page.GRANT_PUBLIC,
  643. creator: testUser1,
  644. lastUpdateUser: testUser1,
  645. parent: parent._id,
  646. },
  647. ]);
  648. // migrate
  649. await crowi.pageService.normalizeAllPublicPages(Page.GRANT_PUBLIC);
  650. jest.setTimeout(30000);
  651. });
  652. test('should migrate all public pages', async() => {
  653. const migratedPages = await Page.find({
  654. path: {
  655. $in: allPossiblePagePaths,
  656. },
  657. parent: { $ne: null },
  658. });
  659. const migratedEmptyPages = await Page.find({
  660. path: {
  661. $in: allPossiblePagePaths,
  662. },
  663. isEmpty: true,
  664. parent: { $ne: null },
  665. });
  666. const nonMigratedPages = await Page.find({
  667. path: {
  668. $in: allPossiblePagePaths,
  669. },
  670. parent: null,
  671. });
  672. const migratedPaths = migratedPages.map(page => page.path).sort();
  673. const migratedEmptyPaths = migratedEmptyPages.map(page => page.path).sort();
  674. const nonMigratedPaths = nonMigratedPages.map(page => page.path).sort();
  675. const expectedMigratedPaths = allPossiblePagePaths.filter(path => path !== '/').sort();
  676. const expectedMigratedEmptyPaths = ['/publicA/privateB', '/parenthesis'].sort();
  677. const expectedNonMigratedPaths = ['/publicA/privateB', '/'].sort();
  678. expect(migratedPaths).toStrictEqual(expectedMigratedPaths);
  679. expect(migratedEmptyPaths).toStrictEqual(expectedMigratedEmptyPaths);
  680. expect(nonMigratedPaths).toStrictEqual(expectedNonMigratedPaths);
  681. });
  682. });
  683. describe('normalizeParentByPage()', () => {
  684. test('it should normalize not v5 page with usergroup that has parent group', async() => {
  685. const page1 = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  686. const page2 = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2', parent: page1._id });
  687. const page3 = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // NOT v5
  688. expect(page1).toBeTruthy();
  689. expect(page2).toBeTruthy();
  690. expect(page3).toBeTruthy();
  691. await normalizeParentByPage(page3, testUser1);
  692. // AM => After Migration
  693. const page1AM = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  694. const page2AM = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2' });
  695. const page3AM = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // v5 compatible
  696. expect(page2AM).toBeTruthy();
  697. expect(page3AM).toBeTruthy();
  698. expect(page1AM).toBeNull();
  699. expect(page2AM.parent).toStrictEqual(page3AM._id);
  700. expect(page3AM.parent).toStrictEqual(rootPage._id);
  701. });
  702. test('should throw error if a page with isolated group becomes the parent of other page with different gourp after normalizing', async() => {
  703. const page4 = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  704. const page5 = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  705. const page6 = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  706. expect(page4).toBeTruthy();
  707. expect(page5).toBeTruthy();
  708. expect(page6).toBeTruthy();
  709. let isThrown;
  710. try {
  711. await normalizeParentByPage(page6, testUser1);
  712. }
  713. catch (err) {
  714. isThrown = true;
  715. }
  716. // AM => After Migration
  717. const page4AM = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  718. const page5AM = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  719. const page6AM = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  720. expect(isThrown).toBe(true);
  721. expect(page4AM).toBeTruthy();
  722. expect(page5AM).toBeTruthy();
  723. expect(page6AM).toBeTruthy();
  724. expect(page4AM).toStrictEqual(page4);
  725. expect(page5AM).toStrictEqual(page5);
  726. expect(page6AM).toStrictEqual(page6);
  727. });
  728. });
  729. test('replace private parents with empty pages', async() => {
  730. const replacedPathPages = await Page.find({ path: '/publicA/privateB' }); // ex-private page
  731. const _newEmptyPage = replacedPathPages.filter(page => page.parent != null)[0];
  732. const newEmptyPage = {
  733. path: _newEmptyPage.path,
  734. grant: _newEmptyPage.grant,
  735. isEmpty: _newEmptyPage.isEmpty,
  736. };
  737. const expectedNewEmptyPage = {
  738. path: '/publicA/privateB',
  739. grant: Page.GRANT_PUBLIC,
  740. isEmpty: true,
  741. };
  742. const _privatePage = replacedPathPages.filter(page => page.parent == null)[0];
  743. const privatePage = {
  744. path: _privatePage.path,
  745. grant: _privatePage.grant,
  746. isEmpty: _privatePage.isEmpty,
  747. };
  748. const expectedPrivatePage = {
  749. path: '/publicA/privateB',
  750. grant: Page.GRANT_OWNER,
  751. isEmpty: false,
  752. };
  753. expect(replacedPathPages.length).toBe(2);
  754. expect(newEmptyPage).toStrictEqual(expectedNewEmptyPage);
  755. expect(privatePage).toStrictEqual(expectedPrivatePage);
  756. });
  757. });