v5.migration.test.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  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 normalizeParentByPageId = async(page, user) => {
  246. return crowi.pageService.normalizeParentByPageId(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.only('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. * Fst. Recursively normalize A and B.
  324. * - Expect
  325. * - A and B are normalized
  326. * - C and D are NOT normalized
  327. * - E and F are NOT normalized
  328. * Snd. 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. * Trd. 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: testUser1GroupId,
  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. path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_testGroup',
  464. grant: Page.GRANT_USER_GROUP,
  465. grantedGroup: testUser1GroupId,
  466. },
  467. ]);
  468. });
  469. test('1', async() => {
  470. /*
  471. * 1
  472. */
  473. const _owned13 = await Page.findOne(owned({ path: '/normalize_13_owned', ...notNormalized }));
  474. const _owned14 = await Page.findOne(owned({ path: '/normalize_13_owned/normalize_14_owned', ...notNormalized }));
  475. const _owned15 = await Page.findOne(owned({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned', ...notNormalized }));
  476. const _owned16 = await Page.findOne(owned({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_owned', ...notNormalized }));
  477. const _root16 = await Page.findOne(root({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_root', ...notNormalized }));
  478. const _group16 = await Page.findOne(testUser1Group({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_group', ...notNormalized }));
  479. expect(_owned13).not.toBeNull();
  480. expect(_owned14).not.toBeNull();
  481. expect(_owned15).not.toBeNull();
  482. expect(_owned16).not.toBeNull();
  483. expect(_root16).not.toBeNull();
  484. expect(_group16).not.toBeNull();
  485. // Normalize
  486. await normalizeParentByPageId(_owned13, testUser1);
  487. await normalizeParentByPageId(_owned14, testUser1);
  488. const owned13 = await Page.findOne({ path: '/normalize_13_owned' });
  489. const owned14 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned' });
  490. const owned15 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned' });
  491. const owned16 = await Page.findOne({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_owned' });
  492. const root16 = await Page.findOne(root({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_root' }));
  493. const group16 = await Page.findOne(rootUserGroup({ path: '/normalize_13_owned/normalize_14_owned/normalize_15_owned/normalize_16_group' }));
  494. expect(owned13).not.toBeNull();
  495. expect(owned14).not.toBeNull();
  496. expect(owned15).not.toBeNull();
  497. expect(owned16).not.toBeNull();
  498. expect(root16).not.toBeNull();
  499. expect(group16).not.toBeNull();
  500. // Check parent
  501. expect(owned13.parent).toStrictEqual(rootPage._id);
  502. expect(owned14.parent).toStrictEqual(owned13._id);
  503. expect(owned15.parent).toBeNull();
  504. expect(owned16.parent).toBeNull();
  505. expect(root16.parent).toBeNull();
  506. expect(group16.parent).toBeNull();
  507. // Check isEmpty
  508. expect(owned13.isEmpty).toBe(false);
  509. expect(owned14.isEmpty).toBe(false);
  510. });
  511. test('2', async() => {
  512. /*
  513. * 2
  514. */
  515. const _owned17 = await Page.findOne(owned({ path: '/normalize_17_owned', ...normalized }));
  516. const _owned18 = await Page.findOne(owned({ path: '/normalize_17_owned/normalize_18_owned', ...normalized }));
  517. const _owned19 = await Page.findOne(owned({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned', ...notNormalized }));
  518. const _owned20 = await Page.findOne(owned({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_owned', ...notNormalized }));
  519. const _root20 = await Page.findOne(root({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_root', ...notNormalized }));
  520. const _group20 = await Page.findOne(testUser1Group({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_group', ...notNormalized }));
  521. expect(_owned17).not.toBeNull();
  522. expect(_owned18).not.toBeNull();
  523. expect(_owned19).not.toBeNull();
  524. expect(_owned20).not.toBeNull();
  525. expect(_root20).not.toBeNull();
  526. expect(_group20).not.toBeNull();
  527. // Normalize
  528. await normalizeParentRecursivelyByPages([_owned20], testUser1);
  529. const owned17 = await Page.findOne({ path: '/normalize_17_owned' });
  530. const owned18 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned' });
  531. const owned19 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned' });
  532. const empty19 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned', ...empty });
  533. const owned20 = await Page.findOne({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_owned' });
  534. const root20 = await Page.findOne(root({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_root' }));
  535. const group20 = await Page.findOne(rootUserGroup({ path: '/normalize_17_owned/normalize_18_owned/normalize_19_owned/normalize_20_group' }));
  536. expect(owned17).not.toBeNull();
  537. expect(owned18).not.toBeNull();
  538. expect(owned19).not.toBeNull();
  539. expect(empty19).not.toBeNull();
  540. expect(owned20).not.toBeNull();
  541. expect(root20).not.toBeNull();
  542. expect(group20).not.toBeNull();
  543. // Check parent
  544. expect(owned17.parent).toStrictEqual(rootPage._id);
  545. expect(owned18.parent).toStrictEqual(owned17._id);
  546. expect(owned19.parent).toBeNull();
  547. expect(empty19.parent).toStrictEqual(owned18._id);
  548. expect(owned20.parent).toStrictEqual(empty19._id);
  549. expect(root20.parent).toBeNull();
  550. expect(group20.parent).toBeNull();
  551. // Check isEmpty
  552. expect(owned17.isEmpty).toBe(false);
  553. expect(owned18.isEmpty).toBe(false);
  554. });
  555. test('3', async() => {
  556. /*
  557. * 3
  558. */
  559. const _owned21 = await Page.findOne(owned({ path: '/normalize_21_owned', ...normalized }));
  560. const _owned22 = await Page.findOne(owned({ path: '/normalize_21_owned/normalize_22_owned', ...normalized }));
  561. const _owned23 = await Page.findOne(owned({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...notNormalized }));
  562. const _empty23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...normalized, ...empty });
  563. const _owned24 = await Page.findOne(owned({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_owned', ...normalized }));
  564. const _root24 = await Page.findOne(root({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_root', ...notNormalized }));
  565. const _rootGroup24 = await Page.findOne(rootUserGroup({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_rootGroup', ...notNormalized }));
  566. const _testGroup24 = await Page.findOne(testUser1Group({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_testGroup', ...notNormalized }));
  567. expect(_owned21).not.toBeNull();
  568. expect(_owned22).not.toBeNull();
  569. expect(_owned23).not.toBeNull();
  570. expect(_empty23).not.toBeNull();
  571. expect(_owned24).not.toBeNull();
  572. expect(_root24).not.toBeNull();
  573. expect(_rootGroup24).not.toBeNull();
  574. expect(_testGroup24).not.toBeNull();
  575. // Normalize
  576. await normalizeParentRecursivelyByPages([_owned23], testUser1);
  577. const owned21 = await Page.findOne({ path: '/normalize_21_owned' });
  578. const owned22 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned' });
  579. const owned23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned' });
  580. const empty23 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned', ...empty });
  581. const owned24 = await Page.findOne({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_owned' });
  582. const root24 = await Page.findOne(root({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_root' }));
  583. const rootGroup24 = await Page.findOne(rootUserGroup({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_rootGroup' }));
  584. const testGroup24 = await Page.findOne(testUser1Group({ path: '/normalize_21_owned/normalize_22_owned/normalize_23_owned/normalize_24_testGroup' }));
  585. expect(owned21).not.toBeNull();
  586. expect(owned22).not.toBeNull();
  587. expect(owned23).not.toBeNull();
  588. expect(empty23).toBeNull(); // removed
  589. expect(owned24).not.toBeNull();
  590. expect(root24).not.toBeNull();
  591. expect(rootGroup24).not.toBeNull();
  592. expect(testGroup24).not.toBeNull();
  593. // Check parent
  594. expect(owned21.parent).toStrictEqual(rootPage._id);
  595. expect(owned22.parent).toStrictEqual(owned21._id);
  596. expect(owned23.parent).toStrictEqual(owned22._id);
  597. expect(owned24.parent).toStrictEqual(owned23._id); // not empty23._id
  598. expect(root24.parent).toBeNull();
  599. expect(rootGroup24.parent).toBeNull(); // excluded from the pages to be normalized
  600. expect(testGroup24.parent).toStrictEqual(owned23._id); // included in the pages to be normalized
  601. // Check isEmpty
  602. expect(owned21.isEmpty).toBe(false);
  603. expect(owned22.isEmpty).toBe(false);
  604. expect(owned23.isEmpty).toBe(false);
  605. });
  606. });
  607. describe('normalizeAllPublicPages()', () => {
  608. jest.setTimeout(60000);
  609. let createPagePaths;
  610. let allPossiblePagePaths;
  611. beforeAll(async() => {
  612. createPagePaths = [
  613. '/publicA', '/publicA/privateB', '/publicA/privateB/publicC', '/parenthesis/(a)[b]{c}d', '/parenthesis/(a)[b]{c}d/public', '/migratedD',
  614. ];
  615. allPossiblePagePaths = [...createPagePaths, '/parenthesis', '/'];
  616. // initialize pages for test
  617. await Page.insertMany([
  618. {
  619. path: '/publicA',
  620. grant: Page.GRANT_PUBLIC,
  621. creator: testUser1,
  622. lastUpdateUser: testUser1,
  623. },
  624. {
  625. path: '/publicA/privateB',
  626. grant: Page.GRANT_OWNER,
  627. creator: testUser1,
  628. lastUpdateUser: testUser1,
  629. grantedUsers: [testUser1._id],
  630. },
  631. {
  632. path: '/publicA/privateB/publicC',
  633. grant: Page.GRANT_PUBLIC,
  634. creator: testUser1,
  635. lastUpdateUser: testUser1,
  636. },
  637. {
  638. path: '/parenthesis/(a)[b]{c}d',
  639. grant: Page.GRANT_PUBLIC,
  640. creator: testUser1,
  641. lastUpdateUser: testUser1,
  642. },
  643. {
  644. path: '/parenthesis/(a)[b]{c}d/public',
  645. grant: Page.GRANT_PUBLIC,
  646. creator: testUser1,
  647. lastUpdateUser: testUser1,
  648. },
  649. ]);
  650. const parent = await Page.find({ path: '/' });
  651. await Page.insertMany([
  652. {
  653. path: '/migratedD',
  654. grant: Page.GRANT_PUBLIC,
  655. creator: testUser1,
  656. lastUpdateUser: testUser1,
  657. parent: parent._id,
  658. },
  659. ]);
  660. // migrate
  661. await crowi.pageService.normalizeAllPublicPages(Page.GRANT_PUBLIC);
  662. jest.setTimeout(30000);
  663. });
  664. test('should migrate all public pages', async() => {
  665. const migratedPages = await Page.find({
  666. path: {
  667. $in: allPossiblePagePaths,
  668. },
  669. parent: { $ne: null },
  670. });
  671. const migratedEmptyPages = await Page.find({
  672. path: {
  673. $in: allPossiblePagePaths,
  674. },
  675. isEmpty: true,
  676. parent: { $ne: null },
  677. });
  678. const nonMigratedPages = await Page.find({
  679. path: {
  680. $in: allPossiblePagePaths,
  681. },
  682. parent: null,
  683. });
  684. const migratedPaths = migratedPages.map(page => page.path).sort();
  685. const migratedEmptyPaths = migratedEmptyPages.map(page => page.path).sort();
  686. const nonMigratedPaths = nonMigratedPages.map(page => page.path).sort();
  687. const expectedMigratedPaths = allPossiblePagePaths.filter(path => path !== '/').sort();
  688. const expectedMigratedEmptyPaths = ['/publicA/privateB', '/parenthesis'].sort();
  689. const expectedNonMigratedPaths = ['/publicA/privateB', '/'].sort();
  690. expect(migratedPaths).toStrictEqual(expectedMigratedPaths);
  691. expect(migratedEmptyPaths).toStrictEqual(expectedMigratedEmptyPaths);
  692. expect(nonMigratedPaths).toStrictEqual(expectedNonMigratedPaths);
  693. });
  694. });
  695. describe('normalizeParentByPageId()', () => {
  696. test('it should normalize not v5 page with usergroup that has parent group', async() => {
  697. const page1 = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  698. const page2 = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2', parent: page1._id });
  699. const page3 = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // NOT v5
  700. expectAllToBeTruthy([page1, page2, page3]);
  701. await normalizeParentByPageId(page3, testUser1);
  702. // AM => After Migration
  703. const page1AM = await Page.findOne({ _id: pageId1, path: '/normalize_1', isEmpty: true });
  704. const page2AM = await Page.findOne({ _id: pageId2, path: '/normalize_1/normalize_2' });
  705. const page3AM = await Page.findOne({ _id: pageId3, path: '/normalize_1' }); // v5 compatible
  706. expectAllToBeTruthy([page2AM, page3AM]);
  707. expect(page1AM).toBeNull();
  708. expect(page2AM.parent).toStrictEqual(page3AM._id);
  709. expect(page3AM.parent).toStrictEqual(rootPage._id);
  710. });
  711. test('should throw error if a page with isolated group becomes the parent of other page with different gourp after normalizing', async() => {
  712. const page4 = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  713. const page5 = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  714. const page6 = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  715. expectAllToBeTruthy([page4, page5, page6]);
  716. let isThrown;
  717. try {
  718. await normalizeParentByPageId(page6, testUser1);
  719. }
  720. catch (err) {
  721. isThrown = true;
  722. }
  723. // AM => After Migration
  724. const page4AM = await Page.findOne({ _id: pageId4, path: '/normalize_4', isEmpty: true });
  725. const page5AM = await Page.findOne({ _id: pageId5, path: '/normalize_4/normalize_5', parent: page4._id });
  726. const page6AM = await Page.findOne({ _id: pageId6, path: '/normalize_4' }); // NOT v5
  727. expectAllToBeTruthy([page4AM, page5AM, page6AM]);
  728. expect(isThrown).toBe(true);
  729. expect(page4AM).toStrictEqual(page4);
  730. expect(page5AM).toStrictEqual(page5);
  731. expect(page6AM).toStrictEqual(page6);
  732. });
  733. });
  734. test('replace private parents with empty pages', async() => {
  735. const replacedPathPages = await Page.find({ path: '/publicA/privateB' }); // ex-private page
  736. const _newEmptyPage = replacedPathPages.filter(page => page.parent != null)[0];
  737. const newEmptyPage = {
  738. path: _newEmptyPage.path,
  739. grant: _newEmptyPage.grant,
  740. isEmpty: _newEmptyPage.isEmpty,
  741. };
  742. const expectedNewEmptyPage = {
  743. path: '/publicA/privateB',
  744. grant: Page.GRANT_PUBLIC,
  745. isEmpty: true,
  746. };
  747. const _privatePage = replacedPathPages.filter(page => page.parent == null)[0];
  748. const privatePage = {
  749. path: _privatePage.path,
  750. grant: _privatePage.grant,
  751. isEmpty: _privatePage.isEmpty,
  752. };
  753. const expectedPrivatePage = {
  754. path: '/publicA/privateB',
  755. grant: Page.GRANT_OWNER,
  756. isEmpty: false,
  757. };
  758. expect(replacedPathPages.length).toBe(2);
  759. expect(newEmptyPage).toStrictEqual(expectedNewEmptyPage);
  760. expect(privatePage).toStrictEqual(expectedPrivatePage);
  761. });
  762. });