v5.migration.test.js 49 KB

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