v5.page.test.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. import mongoose from 'mongoose';
  2. import { getInstance } from '../setup-crowi';
  3. describe('Page', () => {
  4. let crowi;
  5. let Page;
  6. let Revision;
  7. let User;
  8. let Tag;
  9. let PageTagRelation;
  10. let Bookmark;
  11. let Comment;
  12. let ShareLink;
  13. let PageRedirect;
  14. let UserGroup;
  15. let UserGroupRelation;
  16. let xssSpy;
  17. let rootPage;
  18. let dummyUser1;
  19. let pModelUser1;
  20. let pModelUser2;
  21. let pModelUser3;
  22. let groupIdIsolate;
  23. let groupIdA;
  24. let groupIdB;
  25. let groupIdC;
  26. beforeAll(async() => {
  27. crowi = await getInstance();
  28. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', { 'app:isV5Compatible': true });
  29. jest.restoreAllMocks();
  30. User = mongoose.model('User');
  31. Page = mongoose.model('Page');
  32. Revision = mongoose.model('Revision');
  33. Tag = mongoose.model('Tag');
  34. PageTagRelation = mongoose.model('PageTagRelation');
  35. Bookmark = mongoose.model('Bookmark');
  36. Comment = mongoose.model('Comment');
  37. ShareLink = mongoose.model('ShareLink');
  38. PageRedirect = mongoose.model('PageRedirect');
  39. UserGroup = mongoose.model('UserGroup');
  40. UserGroupRelation = mongoose.model('UserGroupRelation');
  41. dummyUser1 = await User.findOne({ username: 'v5DummyUser1' });
  42. rootPage = await Page.findOne({ path: '/' });
  43. const pModelUserId1 = new mongoose.Types.ObjectId();
  44. const pModelUserId2 = new mongoose.Types.ObjectId();
  45. const pModelUserId3 = new mongoose.Types.ObjectId();
  46. await User.insertMany([
  47. {
  48. _id: pModelUserId1,
  49. name: 'pmodelUser1',
  50. username: 'pmodelUser1',
  51. email: 'pmodelUser1@example.com',
  52. },
  53. {
  54. _id: pModelUserId2,
  55. name: 'pmodelUser2',
  56. username: 'pmodelUser2',
  57. email: 'pmodelUser2@example.com',
  58. },
  59. {
  60. _id: pModelUserId3,
  61. name: 'pModelUser3',
  62. username: 'pModelUser3',
  63. email: 'pModelUser3@example.com',
  64. },
  65. ]);
  66. pModelUser1 = await User.findOne({ _id: pModelUserId1 });
  67. pModelUser2 = await User.findOne({ _id: pModelUserId2 });
  68. pModelUser3 = await User.findOne({ _id: pModelUserId3 });
  69. groupIdIsolate = new mongoose.Types.ObjectId();
  70. groupIdA = new mongoose.Types.ObjectId();
  71. groupIdB = new mongoose.Types.ObjectId();
  72. groupIdC = new mongoose.Types.ObjectId();
  73. await UserGroup.insertMany([
  74. {
  75. _id: groupIdIsolate,
  76. name: 'pModel_groupIsolate',
  77. },
  78. {
  79. _id: groupIdA,
  80. name: 'pModel_groupA',
  81. },
  82. {
  83. _id: groupIdB,
  84. name: 'pModel_groupB',
  85. parent: groupIdA,
  86. },
  87. {
  88. _id: groupIdC,
  89. name: 'pModel_groupC',
  90. parent: groupIdB,
  91. },
  92. ]);
  93. await UserGroupRelation.insertMany([
  94. {
  95. relatedGroup: groupIdIsolate,
  96. relatedUser: pModelUserId1,
  97. createdAt: new Date(),
  98. },
  99. {
  100. relatedGroup: groupIdIsolate,
  101. relatedUser: pModelUserId2,
  102. createdAt: new Date(),
  103. },
  104. {
  105. relatedGroup: groupIdA,
  106. relatedUser: pModelUserId1,
  107. createdAt: new Date(),
  108. },
  109. {
  110. relatedGroup: groupIdA,
  111. relatedUser: pModelUserId2,
  112. createdAt: new Date(),
  113. },
  114. {
  115. relatedGroup: groupIdA,
  116. relatedUser: pModelUserId3,
  117. createdAt: new Date(),
  118. },
  119. {
  120. relatedGroup: groupIdB,
  121. relatedUser: pModelUserId2,
  122. createdAt: new Date(),
  123. },
  124. {
  125. relatedGroup: groupIdB,
  126. relatedUser: pModelUserId3,
  127. createdAt: new Date(),
  128. },
  129. {
  130. relatedGroup: groupIdC,
  131. relatedUser: pModelUserId3,
  132. createdAt: new Date(),
  133. },
  134. ]);
  135. const pageIdCreate1 = new mongoose.Types.ObjectId();
  136. const pageIdCreate2 = new mongoose.Types.ObjectId();
  137. const pageIdCreate3 = new mongoose.Types.ObjectId();
  138. const pageIdCreate4 = new mongoose.Types.ObjectId();
  139. /**
  140. * create
  141. * mc_ => model create
  142. * emp => empty => page with isEmpty: true
  143. * pub => public => GRANT_PUBLIC
  144. */
  145. await Page.insertMany([
  146. {
  147. _id: pageIdCreate1,
  148. path: '/v5_empty_create_4',
  149. grant: Page.GRANT_PUBLIC,
  150. parent: rootPage._id,
  151. isEmpty: true,
  152. },
  153. {
  154. path: '/v5_empty_create_4/v5_create_5',
  155. grant: Page.GRANT_PUBLIC,
  156. creator: dummyUser1,
  157. lastUpdateUser: dummyUser1._id,
  158. parent: pageIdCreate1,
  159. isEmpty: false,
  160. },
  161. {
  162. _id: pageIdCreate2,
  163. path: '/mc4_top/mc1_emp',
  164. grant: Page.GRANT_PUBLIC,
  165. creator: dummyUser1,
  166. lastUpdateUser: dummyUser1._id,
  167. parent: rootPage._id,
  168. isEmpty: true,
  169. },
  170. {
  171. path: '/mc4_top/mc1_emp/mc2_pub',
  172. grant: Page.GRANT_PUBLIC,
  173. creator: dummyUser1,
  174. lastUpdateUser: dummyUser1._id,
  175. parent: pageIdCreate2,
  176. isEmpty: false,
  177. },
  178. {
  179. path: '/mc5_top/mc3_awl',
  180. grant: Page.GRANT_RESTRICTED,
  181. creator: dummyUser1,
  182. lastUpdateUser: dummyUser1._id,
  183. isEmpty: false,
  184. },
  185. {
  186. _id: pageIdCreate3,
  187. path: '/mc4_top',
  188. grant: Page.GRANT_PUBLIC,
  189. creator: dummyUser1,
  190. lastUpdateUser: dummyUser1._id,
  191. isEmpty: false,
  192. parent: rootPage._id,
  193. descendantCount: 1,
  194. },
  195. {
  196. _id: pageIdCreate4,
  197. path: '/mc5_top',
  198. grant: Page.GRANT_PUBLIC,
  199. creator: dummyUser1,
  200. lastUpdateUser: dummyUser1._id,
  201. isEmpty: false,
  202. parent: rootPage._id,
  203. descendantCount: 0,
  204. },
  205. ]);
  206. /**
  207. * update
  208. * mup_ => model update
  209. * emp => empty => page with isEmpty: true
  210. * pub => public => GRANT_PUBLIC
  211. * awl => Anyone with the link => GRANT_RESTRICTED
  212. */
  213. const pageIdUpd1 = new mongoose.Types.ObjectId();
  214. const pageIdUpd2 = new mongoose.Types.ObjectId();
  215. const pageIdUpd3 = new mongoose.Types.ObjectId();
  216. const pageIdUpd4 = new mongoose.Types.ObjectId();
  217. const pageIdUpd5 = new mongoose.Types.ObjectId();
  218. const pageIdUpd6 = new mongoose.Types.ObjectId();
  219. const pageIdUpd7 = new mongoose.Types.ObjectId();
  220. const pageIdUpd8 = new mongoose.Types.ObjectId();
  221. const pageIdUpd9 = new mongoose.Types.ObjectId();
  222. const pageIdUpd10 = new mongoose.Types.ObjectId();
  223. const pageIdUpd11 = new mongoose.Types.ObjectId();
  224. const pageIdUpd12 = new mongoose.Types.ObjectId();
  225. const pageIdUpd13 = new mongoose.Types.ObjectId();
  226. await Page.insertMany([
  227. {
  228. _id: pageIdUpd1,
  229. path: '/mup13_top/mup1_emp',
  230. grant: Page.GRANT_PUBLIC,
  231. parent: pageIdUpd8._id,
  232. isEmpty: true,
  233. },
  234. {
  235. _id: pageIdUpd2,
  236. path: '/mup13_top/mup1_emp/mup2_pub',
  237. grant: Page.GRANT_PUBLIC,
  238. parent: pageIdUpd1._id,
  239. creator: dummyUser1,
  240. lastUpdateUser: dummyUser1._id,
  241. isEmpty: false,
  242. },
  243. {
  244. _id: pageIdUpd3,
  245. path: '/mup14_top/mup6_pub',
  246. grant: Page.GRANT_PUBLIC,
  247. creator: dummyUser1,
  248. lastUpdateUser: dummyUser1._id,
  249. parent: pageIdUpd9,
  250. isEmpty: false,
  251. descendantCount: 1,
  252. },
  253. {
  254. path: '/mup14_top/mup6_pub/mup7_pub',
  255. grant: Page.GRANT_PUBLIC,
  256. creator: dummyUser1,
  257. lastUpdateUser: dummyUser1._id,
  258. parent: pageIdUpd3,
  259. isEmpty: false,
  260. descendantCount: 0,
  261. },
  262. {
  263. _id: pageIdUpd4,
  264. path: '/mup15_top/mup8_pub',
  265. grant: Page.GRANT_PUBLIC,
  266. creator: dummyUser1,
  267. lastUpdateUser: dummyUser1._id,
  268. parent: pageIdUpd10._id,
  269. isEmpty: false,
  270. },
  271. {
  272. _id: pageIdUpd5,
  273. path: '/mup16_top/mup9_pub/mup10_pub/mup11_awl',
  274. grant: Page.GRANT_RESTRICTED,
  275. creator: dummyUser1,
  276. lastUpdateUser: dummyUser1._id,
  277. isEmpty: false,
  278. },
  279. {
  280. _id: pageIdUpd6,
  281. path: '/mup17_top/mup12_emp',
  282. isEmpty: true,
  283. parent: pageIdUpd12._id,
  284. descendantCount: 1,
  285. },
  286. {
  287. _id: pageIdUpd7,
  288. path: '/mup17_top/mup12_emp',
  289. grant: Page.GRANT_RESTRICTED,
  290. creator: dummyUser1,
  291. lastUpdateUser: dummyUser1._id,
  292. isEmpty: false,
  293. },
  294. {
  295. path: '/mup17_top/mup12_emp/mup18_pub',
  296. isEmpty: false,
  297. creator: dummyUser1,
  298. lastUpdateUser: dummyUser1._id,
  299. parent: pageIdUpd6._id,
  300. },
  301. {
  302. _id: pageIdUpd8,
  303. path: '/mup13_top',
  304. grant: Page.GRANT_PUBLIC,
  305. creator: dummyUser1,
  306. lastUpdateUser: dummyUser1._id,
  307. isEmpty: false,
  308. parent: rootPage._id,
  309. descendantCount: 2,
  310. },
  311. {
  312. _id: pageIdUpd9,
  313. path: '/mup14_top',
  314. grant: Page.GRANT_PUBLIC,
  315. creator: dummyUser1,
  316. lastUpdateUser: dummyUser1._id,
  317. isEmpty: false,
  318. parent: rootPage._id,
  319. descendantCount: 2,
  320. },
  321. {
  322. _id: pageIdUpd10,
  323. path: '/mup15_top',
  324. grant: Page.GRANT_PUBLIC,
  325. creator: dummyUser1,
  326. lastUpdateUser: dummyUser1._id,
  327. isEmpty: false,
  328. parent: rootPage._id,
  329. descendantCount: 1,
  330. },
  331. {
  332. _id: pageIdUpd11,
  333. path: '/mup16_top',
  334. grant: Page.GRANT_PUBLIC,
  335. creator: dummyUser1,
  336. lastUpdateUser: dummyUser1._id,
  337. isEmpty: false,
  338. parent: rootPage._id,
  339. descendantCount: 0,
  340. },
  341. {
  342. _id: pageIdUpd12,
  343. path: '/mup17_top',
  344. grant: Page.GRANT_PUBLIC,
  345. creator: dummyUser1,
  346. lastUpdateUser: dummyUser1._id,
  347. isEmpty: false,
  348. parent: rootPage._id,
  349. descendantCount: 1,
  350. },
  351. {
  352. path: '/mup19',
  353. grant: Page.GRANT_PUBLIC,
  354. creator: dummyUser1,
  355. lastUpdateUser: dummyUser1._id,
  356. isEmpty: false,
  357. parent: rootPage._id,
  358. descendantCount: 0,
  359. },
  360. {
  361. path: '/mup20',
  362. grant: Page.GRANT_USER_GROUP,
  363. grantedGroup: groupIdA,
  364. creator: pModelUserId1,
  365. lastUpdateUser: pModelUserId1,
  366. isEmpty: false,
  367. parent: rootPage._id,
  368. descendantCount: 0,
  369. },
  370. {
  371. path: '/mup21',
  372. grant: Page.GRANT_RESTRICTED,
  373. creator: dummyUser1,
  374. lastUpdateUser: dummyUser1._id,
  375. isEmpty: false,
  376. descendantCount: 0,
  377. },
  378. {
  379. _id: pageIdUpd13,
  380. path: '/mup22',
  381. grant: Page.GRANT_PUBLIC,
  382. creator: pModelUser1,
  383. lastUpdateUser: pModelUser1._id,
  384. isEmpty: false,
  385. parent: rootPage._id,
  386. descendantCount: 1,
  387. },
  388. {
  389. path: '/mup22/mup23',
  390. grant: Page.GRANT_USER_GROUP,
  391. grantedGroup: groupIdA,
  392. creator: pModelUserId1,
  393. lastUpdateUser: pModelUserId1,
  394. isEmpty: false,
  395. parent: pageIdUpd13,
  396. descendantCount: 0,
  397. },
  398. {
  399. path: '/mup24',
  400. grant: Page.GRANT_OWNER,
  401. grantedUsers: [dummyUser1._id],
  402. creator: dummyUser1,
  403. lastUpdateUser: dummyUser1._id,
  404. isEmpty: false,
  405. parent: rootPage._id,
  406. descendantCount: 0,
  407. },
  408. ]);
  409. /**
  410. * getParentAndFillAncestors
  411. */
  412. const pageIdPAF1 = new mongoose.Types.ObjectId();
  413. const pageIdPAF2 = new mongoose.Types.ObjectId();
  414. const pageIdPAF3 = new mongoose.Types.ObjectId();
  415. await Page.insertMany([
  416. {
  417. _id: pageIdPAF1,
  418. path: '/PAF1',
  419. grant: Page.GRANT_PUBLIC,
  420. creator: dummyUser1,
  421. lastUpdateUser: dummyUser1._id,
  422. isEmpty: false,
  423. parent: rootPage._id,
  424. descendantCount: 0,
  425. },
  426. {
  427. _id: pageIdPAF2,
  428. path: '/emp_anc3',
  429. grant: Page.GRANT_PUBLIC,
  430. isEmpty: true,
  431. descendantCount: 1,
  432. parent: rootPage._id,
  433. },
  434. {
  435. path: '/emp_anc3/PAF3',
  436. grant: Page.GRANT_PUBLIC,
  437. creator: dummyUser1,
  438. lastUpdateUser: dummyUser1._id,
  439. isEmpty: false,
  440. descendantCount: 0,
  441. parent: pageIdPAF2,
  442. },
  443. {
  444. _id: pageIdPAF3,
  445. path: '/emp_anc4',
  446. grant: Page.GRANT_PUBLIC,
  447. isEmpty: true,
  448. descendantCount: 1,
  449. parent: rootPage._id,
  450. },
  451. {
  452. path: '/emp_anc4/PAF4',
  453. grant: Page.GRANT_PUBLIC,
  454. creator: dummyUser1,
  455. lastUpdateUser: dummyUser1._id,
  456. isEmpty: false,
  457. descendantCount: 0,
  458. parent: pageIdPAF3,
  459. },
  460. {
  461. path: '/emp_anc4',
  462. grant: Page.GRANT_OWNER,
  463. grantedUsers: [dummyUser1._id],
  464. creator: dummyUser1,
  465. lastUpdateUser: dummyUser1._id,
  466. isEmpty: false,
  467. },
  468. {
  469. path: '/get_parent_A',
  470. creator: dummyUser1,
  471. lastUpdateUser: dummyUser1,
  472. parent: null,
  473. },
  474. {
  475. path: '/get_parent_A/get_parent_B',
  476. creator: dummyUser1,
  477. lastUpdateUser: dummyUser1,
  478. parent: null,
  479. },
  480. {
  481. path: '/get_parent_C',
  482. creator: dummyUser1,
  483. lastUpdateUser: dummyUser1,
  484. parent: rootPage._id,
  485. },
  486. {
  487. path: '/get_parent_C/get_parent_D',
  488. creator: dummyUser1,
  489. lastUpdateUser: dummyUser1,
  490. parent: null,
  491. },
  492. ]);
  493. });
  494. describe('create', () => {
  495. test('Should create single page', async() => {
  496. const page = await Page.create('/v5_create1', 'create1', dummyUser1, {});
  497. expect(page).toBeTruthy();
  498. expect(page.parent).toStrictEqual(rootPage._id);
  499. });
  500. test('Should create empty-child and non-empty grandchild', async() => {
  501. const grandchildPage = await Page.create('/v5_empty_create2/v5_create_3', 'grandchild', dummyUser1, {});
  502. const childPage = await Page.findOne({ path: '/v5_empty_create2' });
  503. expect(childPage.isEmpty).toBe(true);
  504. expect(grandchildPage).toBeTruthy();
  505. expect(childPage).toBeTruthy();
  506. expect(childPage.parent).toStrictEqual(rootPage._id);
  507. expect(grandchildPage.parent).toStrictEqual(childPage._id);
  508. });
  509. test('Should create on empty page', async() => {
  510. const beforeCreatePage = await Page.findOne({ path: '/v5_empty_create_4' });
  511. expect(beforeCreatePage.isEmpty).toBe(true);
  512. const childPage = await Page.create('/v5_empty_create_4', 'body', dummyUser1, {});
  513. const grandchildPage = await Page.findOne({ parent: childPage._id });
  514. expect(childPage).toBeTruthy();
  515. expect(childPage.isEmpty).toBe(false);
  516. expect(childPage.revision.body).toBe('body');
  517. expect(grandchildPage).toBeTruthy();
  518. expect(childPage.parent).toStrictEqual(rootPage._id);
  519. expect(grandchildPage.parent).toStrictEqual(childPage._id);
  520. });
  521. describe('Creating a page using existing path', () => {
  522. test('with grant RESTRICTED should only create the page and change nothing else', async() => {
  523. const pathT = '/mc4_top';
  524. const path1 = '/mc4_top/mc1_emp';
  525. const path2 = '/mc4_top/mc1_emp/mc2_pub';
  526. const pageT = await Page.findOne({ path: pathT, descendantCount: 1 });
  527. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  528. const page2 = await Page.findOne({ path: path2 });
  529. const page3 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  530. expect(pageT).toBeTruthy();
  531. expect(page1).toBeTruthy();
  532. expect(page2).toBeTruthy();
  533. expect(page3).toBeNull();
  534. // use existing path
  535. await Page.create(path1, 'new body', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  536. const _pageT = await Page.findOne({ path: pathT });
  537. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  538. const _page2 = await Page.findOne({ path: path2 });
  539. const _page3 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  540. expect(_pageT).toBeTruthy();
  541. expect(_page1).toBeTruthy();
  542. expect(_page2).toBeTruthy();
  543. expect(_page3).toBeTruthy();
  544. expect(_pageT.descendantCount).toBe(1);
  545. });
  546. });
  547. describe('Creating a page under a page with grant RESTRICTED', () => {
  548. test('will create a new empty page with the same path as the grant RESTRECTED page and become a parent', async() => {
  549. const pathT = '/mc5_top';
  550. const path1 = '/mc5_top/mc3_awl';
  551. const pathN = '/mc5_top/mc3_awl/mc4_pub'; // used to create
  552. const pageT = await Page.findOne({ path: pathT });
  553. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  554. const page2 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  555. expect(pageT).toBeTruthy();
  556. expect(page1).toBeTruthy();
  557. expect(page2).toBeNull();
  558. await Page.create(pathN, 'new body', dummyUser1, { grant: Page.GRANT_PUBLIC });
  559. const _pageT = await Page.findOne({ path: pathT });
  560. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  561. const _page2 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC, isEmpty: true });
  562. const _pageN = await Page.findOne({ path: pathN, grant: Page.GRANT_PUBLIC }); // newly crated
  563. expect(_pageT).toBeTruthy();
  564. expect(_page1).toBeTruthy();
  565. expect(_page2).toBeTruthy();
  566. expect(_pageN).toBeTruthy();
  567. expect(_pageN.parent).toStrictEqual(_page2._id);
  568. expect(_pageT.descendantCount).toStrictEqual(1);
  569. });
  570. });
  571. });
  572. describe('update', () => {
  573. const updatePage = async(page, newRevisionBody, oldRevisionBody, user, options = {}) => {
  574. const mockedRenameSubOperation = jest.spyOn(Page, 'emitPageEventUpdate').mockReturnValue(null);
  575. const savedPage = await Page.updatePage(page, newRevisionBody, oldRevisionBody, user, options);
  576. mockedRenameSubOperation.mockRestore();
  577. return savedPage;
  578. };
  579. describe('Changing grant from PUBLIC to RESTRICTED of', () => {
  580. test('an only-child page will delete its empty parent page', async() => {
  581. const pathT = '/mup13_top';
  582. const path1 = '/mup13_top/mup1_emp';
  583. const path2 = '/mup13_top/mup1_emp/mup2_pub';
  584. const pageT = await Page.findOne({ path: pathT, descendantCount: 2 });
  585. const page1 = await Page.findOne({ path: path1, isEmpty: true });
  586. const page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC });
  587. expect(pageT).toBeTruthy();
  588. expect(page1).toBeTruthy();
  589. expect(page2).toBeTruthy();
  590. const options = { grant: Page.GRANT_RESTRICTED, grantUserGroupId: null };
  591. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, options);
  592. const _pageT = await Page.findOne({ path: pathT });
  593. const _page1 = await Page.findOne({ path: path1 });
  594. const _page2 = await Page.findOne({ path: path2, grant: Page.GRANT_RESTRICTED });
  595. expect(_pageT).toBeTruthy();
  596. expect(_page1).toBeNull();
  597. expect(_page2).toBeTruthy();
  598. expect(_pageT.descendantCount).toBe(1);
  599. });
  600. test('a page that has children will create an empty page with the same path and it becomes a new parent', async() => {
  601. const pathT = '/mup14_top';
  602. const path1 = '/mup14_top/mup6_pub';
  603. const path2 = '/mup14_top/mup6_pub/mup7_pub';
  604. const top = await Page.findOne({ path: pathT, descendantCount: 2 });
  605. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  606. const page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC });
  607. expect(top).toBeTruthy();
  608. expect(page1).toBeTruthy();
  609. expect(page2).toBeTruthy();
  610. await Page.updatePage(page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  611. const _top = await Page.findOne({ path: pathT });
  612. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  613. const _page2 = await Page.findOne({ path: path2 });
  614. const _pageN = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  615. expect(_page1).toBeTruthy();
  616. expect(_page2).toBeTruthy();
  617. expect(_pageN).toBeTruthy();
  618. expect(_page1.parent).toBeNull();
  619. expect(_page2.parent).toStrictEqual(_pageN._id);
  620. expect(_pageN.parent).toStrictEqual(top._id);
  621. expect(_pageN.isEmpty).toBe(true);
  622. expect(_pageN.descendantCount).toBe(1);
  623. expect(_top.descendantCount).toBe(1);
  624. });
  625. test('of a leaf page will NOT have an empty page with the same path', async() => {
  626. const pathT = '/mup15_top';
  627. const path1 = '/mup15_top/mup8_pub';
  628. const pageT = await Page.findOne({ path: pathT, descendantCount: 1 });
  629. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  630. const count = await Page.count({ path: path1 });
  631. expect(pageT).toBeTruthy();
  632. expect(page1).toBeTruthy();
  633. expect(count).toBe(1);
  634. await Page.updatePage(page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  635. const _pageT = await Page.findOne({ path: pathT });
  636. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  637. const _pageNotExist = await Page.findOne({ path: path1, isEmpty: true });
  638. expect(_pageT).toBeTruthy();
  639. expect(_page1).toBeTruthy();
  640. expect(_pageNotExist).toBeNull();
  641. expect(_pageT.descendantCount).toBe(0);
  642. });
  643. });
  644. describe('Changing grant to GRANT_RESTRICTED', () => {
  645. test('successfully change to GRANT_RESTRICTED from GRANT_OWNER', async() => {
  646. const path = '/mup24';
  647. const _page = await Page.findOne({ path, grant: Page.GRANT_OWNER, grantedUsers: [dummyUser1._id] });
  648. expect(_page).toBeTruthy();
  649. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  650. const page = await Page.findOne({ path });
  651. expect(page).toBeTruthy();
  652. expect(page.grant).toBe(Page.GRANT_RESTRICTED);
  653. expect(page.grantedUsers).toStrictEqual([]);
  654. });
  655. });
  656. describe('Changing grant from RESTRICTED to PUBLIC of', () => {
  657. test('a page will create ancestors if they do not exist', async() => {
  658. const pathT = '/mup16_top';
  659. const path1 = '/mup16_top/mup9_pub';
  660. const path2 = '/mup16_top/mup9_pub/mup10_pub';
  661. const path3 = '/mup16_top/mup9_pub/mup10_pub/mup11_awl';
  662. const top = await Page.findOne({ path: pathT });
  663. const page1 = await Page.findOne({ path: path1 });
  664. const page2 = await Page.findOne({ path: path2 });
  665. const page3 = await Page.findOne({ path: path3, grant: Page.GRANT_RESTRICTED });
  666. expect(top).toBeTruthy();
  667. expect(page3).toBeTruthy();
  668. expect(page1).toBeNull();
  669. expect(page2).toBeNull();
  670. await Page.updatePage(page3, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_PUBLIC });
  671. const _pageT = await Page.findOne({ path: pathT });
  672. const _page1 = await Page.findOne({ path: path1, isEmpty: true });
  673. const _page2 = await Page.findOne({ path: path2, isEmpty: true });
  674. const _page3 = await Page.findOne({ path: path3, grant: Page.GRANT_PUBLIC });
  675. expect(_page1).toBeTruthy();
  676. expect(_page2).toBeTruthy();
  677. expect(_page3).toBeTruthy();
  678. expect(_page1.parent).toStrictEqual(top._id);
  679. expect(_page2.parent).toStrictEqual(_page1._id);
  680. expect(_page3.parent).toStrictEqual(_page2._id);
  681. expect(_pageT.descendantCount).toBe(1);
  682. });
  683. test('a page will replace an empty page with the same path if any', async() => {
  684. const pathT = '/mup17_top';
  685. const path1 = '/mup17_top/mup12_emp';
  686. const path2 = '/mup17_top/mup12_emp/mup18_pub';
  687. const pageT = await Page.findOne({ path: pathT, descendantCount: 1 });
  688. const page1 = await Page.findOne({ path: path1, isEmpty: true });
  689. const page2 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED, isEmpty: false });
  690. const page3 = await Page.findOne({ path: path2 });
  691. expect(pageT).toBeTruthy();
  692. expect(page1).toBeTruthy();
  693. expect(page2).toBeTruthy();
  694. expect(page3).toBeTruthy();
  695. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_PUBLIC });
  696. const _pageT = await Page.findOne({ path: pathT });
  697. const _page1 = await Page.findOne({ path: path1, isEmpty: true }); // should be replaced
  698. const _page2 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  699. const _page3 = await Page.findOne({ path: path2 });
  700. expect(_pageT).toBeTruthy();
  701. expect(_page1).toBeNull();
  702. expect(_page2).toBeTruthy();
  703. expect(_page3).toBeTruthy();
  704. expect(_page2.grant).toBe(Page.GRANT_PUBLIC);
  705. expect(_page2.parent).toStrictEqual(_pageT._id);
  706. expect(_page3.parent).toStrictEqual(_page2._id);
  707. expect(_pageT.descendantCount).toBe(2);
  708. });
  709. });
  710. describe('Changing grant to GRANT_OWNER(onlyme)', () => {
  711. test('successfully change to GRANT_OWNER from GRANT_PUBLIC', async() => {
  712. const path = '/mup19';
  713. const _page = await Page.findOne({ path, grant: Page.GRANT_PUBLIC });
  714. expect(_page).toBeTruthy();
  715. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER });
  716. const page = await Page.findOne({ path });
  717. expect(page.grant).toBe(Page.GRANT_OWNER);
  718. expect(page.grantedUsers).toStrictEqual([dummyUser1._id]);
  719. });
  720. test('successfully change to GRANT_OWNER from GRANT_USER_GROUP', async() => {
  721. const path = '/mup20';
  722. const _page = await Page.findOne({ path, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
  723. expect(_page).toBeTruthy();
  724. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', pModelUser1, { grant: Page.GRANT_OWNER });
  725. const page = await Page.findOne({ path });
  726. expect(page.grant).toBe(Page.GRANT_OWNER);
  727. expect(page.grantedUsers).toStrictEqual([pModelUser1._id]);
  728. expect(page.grantedGroup).toBeNull();
  729. });
  730. test('successfully change to GRANT_OWNER from GRANT_RESTRICTED', async() => {
  731. const path = '/mup21';
  732. const _page = await Page.findOne({ path, grant: Page.GRANT_RESTRICTED });
  733. expect(_page).toBeTruthy();
  734. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER });
  735. const page = await Page.findOne({ path });
  736. expect(page.grant).toBe(Page.GRANT_OWNER);
  737. expect(page.grantedUsers).toStrictEqual([dummyUser1._id]);
  738. });
  739. test('Failed to change to GRANT_OWNER if one of the ancestors is GRANT_USER_GROUP page', async() => {
  740. const path1 = '/mup22';
  741. const path2 = '/mup22/mup23';
  742. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  743. const _page2 = await Page.findOne({ path: path2, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
  744. expect(_page1).toBeTruthy();
  745. expect(_page2).toBeTruthy();
  746. await expect(updatePage(_page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER }))
  747. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  748. const page1 = await Page.findOne({ path1 });
  749. expect(page1).toBeTruthy();
  750. expect(page1.grant).toBe(Page.GRANT_PUBLIC);
  751. expect(page1.grantedUsers).not.toStrictEqual([dummyUser1._id]);
  752. });
  753. });
  754. });
  755. describe('getParentAndFillAncestors', () => {
  756. test('return parent if exist', async() => {
  757. const page1 = await Page.findOne({ path: '/PAF1' });
  758. const parent = await Page.getParentAndFillAncestors(page1.path, dummyUser1);
  759. expect(parent).toBeTruthy();
  760. expect(page1.parent).toStrictEqual(parent._id);
  761. });
  762. test('create parent and ancestors when they do not exist, and return the new parent', async() => {
  763. const path1 = '/emp_anc1';
  764. const path2 = '/emp_anc1/emp_anc2';
  765. const path3 = '/emp_anc1/emp_anc2/PAF2';
  766. const _page1 = await Page.findOne({ path: path1 }); // not exist
  767. const _page2 = await Page.findOne({ path: path2 }); // not exist
  768. const _page3 = await Page.findOne({ path: path3 }); // not exist
  769. expect(_page1).toBeNull();
  770. expect(_page2).toBeNull();
  771. expect(_page3).toBeNull();
  772. const parent = await Page.getParentAndFillAncestors(path3, dummyUser1);
  773. const page1 = await Page.findOne({ path: path1 });
  774. const page2 = await Page.findOne({ path: path2 });
  775. const page3 = await Page.findOne({ path: path3 });
  776. expect(parent._id).toStrictEqual(page2._id);
  777. expect(parent.path).toStrictEqual(page2.path);
  778. expect(parent.parent).toStrictEqual(page2.parent);
  779. expect(parent).toBeTruthy();
  780. expect(page1).toBeTruthy();
  781. expect(page2).toBeTruthy();
  782. expect(page3).toBeNull();
  783. expect(page1.parent).toStrictEqual(rootPage._id);
  784. expect(page2.parent).toStrictEqual(page1._id);
  785. });
  786. test('return parent even if the parent page is empty', async() => {
  787. const path1 = '/emp_anc3';
  788. const path2 = '/emp_anc3/PAF3';
  789. const _page1 = await Page.findOne({ path: path1, isEmpty: true });
  790. const _page2 = await Page.findOne({ path: path2, isEmpty: false });
  791. expect(_page1).toBeTruthy();
  792. expect(_page2).toBeTruthy();
  793. const parent = await Page.getParentAndFillAncestors(_page2.path, dummyUser1);
  794. const page1 = await Page.findOne({ path: path1, isEmpty: true }); // parent
  795. const page2 = await Page.findOne({ path: path2, isEmpty: false });
  796. // check for the parent (should be the same as page1)
  797. expect(parent._id).toStrictEqual(page1._id);
  798. expect(parent.path).toStrictEqual(page1.path);
  799. expect(parent.parent).toStrictEqual(page1.parent);
  800. expect(page1.parent).toStrictEqual(rootPage._id);
  801. expect(page2.parent).toStrictEqual(page1._id);
  802. });
  803. test('should find parent while NOT updating private legacy page\'s parent', async() => {
  804. const path1 = '/emp_anc4';
  805. const path2 = '/emp_anc4/PAF4';
  806. const _page1 = await Page.findOne({ path: path1, isEmpty: true, grant: Page.GRANT_PUBLIC });
  807. const _page2 = await Page.findOne({ path: path2, isEmpty: false, grant: Page.GRANT_PUBLIC });
  808. const _page3 = await Page.findOne({ path: path1, isEmpty: false, grant: Page.GRANT_OWNER });
  809. expect(_page1).toBeTruthy();
  810. expect(_page2).toBeTruthy();
  811. expect(_page3).toBeTruthy();
  812. expect(_page3.parent).toBeNull();
  813. const parent = await Page.getParentAndFillAncestors(_page2.path, dummyUser1);
  814. const page1 = await Page.findOne({ path: path1, isEmpty: true, grant: Page.GRANT_PUBLIC });
  815. const page2 = await Page.findOne({ path: path2, isEmpty: false, grant: Page.GRANT_PUBLIC });
  816. const page3 = await Page.findOne({ path: path1, isEmpty: false, grant: Page.GRANT_OWNER });
  817. expect(page1).toBeTruthy();
  818. expect(page2).toBeTruthy();
  819. expect(page3).toBeTruthy();
  820. expect(page3.parent).toBeNull(); // parent property of page in private legacy pages should be null
  821. expect(page1._id).toStrictEqual(parent._id);
  822. expect(page2.parent).toStrictEqual(parent._id);
  823. });
  824. test('should find parent while NOT creating unnecessary empty pages with all v4 public pages', async() => {
  825. // All pages does not have parent (v4 schema)
  826. const _pageA = await Page.findOne({
  827. path: '/get_parent_A',
  828. grant: Page.GRANT_PUBLIC,
  829. isEmpty: false,
  830. parent: null,
  831. });
  832. const _pageAB = await Page.findOne({
  833. path: '/get_parent_A/get_parent_B',
  834. grant: Page.GRANT_PUBLIC,
  835. isEmpty: false,
  836. parent: null,
  837. });
  838. const _emptyA = await Page.findOne({
  839. path: '/get_parent_A',
  840. grant: Page.GRANT_PUBLIC,
  841. isEmpty: true,
  842. });
  843. const _emptyAB = await Page.findOne({
  844. path: '/get_parent_A/get_parent_B',
  845. grant: Page.GRANT_PUBLIC,
  846. isEmpty: true,
  847. });
  848. expect(_pageA).not.toBeNull();
  849. expect(_pageAB).not.toBeNull();
  850. expect(_emptyA).toBeNull();
  851. expect(_emptyAB).toBeNull();
  852. const parent = await Page.getParentAndFillAncestors('/get_parent_A/get_parent_B/get_parent_C', dummyUser1);
  853. const pageA = await Page.findOne({ path: '/get_parent_A', grant: Page.GRANT_PUBLIC, isEmpty: false });
  854. const pageAB = await Page.findOne({ path: '/get_parent_A/get_parent_B', grant: Page.GRANT_PUBLIC, isEmpty: false });
  855. const emptyA = await Page.findOne({ path: '/get_parent_A', grant: Page.GRANT_PUBLIC, isEmpty: true });
  856. const emptyAB = await Page.findOne({ path: '/get_parent_A/get_parent_B', grant: Page.GRANT_PUBLIC, isEmpty: true });
  857. // -- Check existance
  858. expect(parent).not.toBeNull();
  859. expect(pageA).not.toBeNull();
  860. expect(pageAB).not.toBeNull();
  861. expect(emptyA).toBeNull();
  862. expect(emptyAB).toBeNull();
  863. // -- Check parent
  864. expect(pageA.parent).not.toBeNull();
  865. expect(pageAB.parent).not.toBeNull();
  866. });
  867. test('should find parent while NOT creating unnecessary empty pages with some v5 public pages', async() => {
  868. const _pageC = await Page.findOne({
  869. path: '/get_parent_C',
  870. grant: Page.GRANT_PUBLIC,
  871. isEmpty: false,
  872. parent: { $ne: null },
  873. });
  874. const _pageCD = await Page.findOne({
  875. path: '/get_parent_C/get_parent_D',
  876. grant: Page.GRANT_PUBLIC,
  877. isEmpty: false,
  878. });
  879. const _emptyC = await Page.findOne({
  880. path: '/get_parent_C',
  881. grant: Page.GRANT_PUBLIC,
  882. isEmpty: true,
  883. });
  884. const _emptyCD = await Page.findOne({
  885. path: '/get_parent_C/get_parent_D',
  886. grant: Page.GRANT_PUBLIC,
  887. isEmpty: true,
  888. });
  889. expect(_pageC).not.toBeNull();
  890. expect(_pageCD).not.toBeNull();
  891. expect(_emptyC).toBeNull();
  892. expect(_emptyCD).toBeNull();
  893. const parent = await Page.getParentAndFillAncestors('/get_parent_C/get_parent_D/get_parent_E', dummyUser1);
  894. const pageC = await Page.findOne({ path: '/get_parent_C', grant: Page.GRANT_PUBLIC, isEmpty: false });
  895. const pageCD = await Page.findOne({ path: '/get_parent_C/get_parent_D', grant: Page.GRANT_PUBLIC, isEmpty: false });
  896. const emptyC = await Page.findOne({ path: '/get_parent_C', grant: Page.GRANT_PUBLIC, isEmpty: true });
  897. const emptyCD = await Page.findOne({ path: '/get_parent_C/get_parent_D', grant: Page.GRANT_PUBLIC, isEmpty: true });
  898. // -- Check existance
  899. expect(parent).not.toBeNull();
  900. expect(pageC).not.toBeNull();
  901. expect(pageCD).not.toBeNull();
  902. expect(emptyC).toBeNull();
  903. expect(emptyCD).toBeNull();
  904. // -- Check parent attribute
  905. expect(pageC.parent).toStrictEqual(rootPage._id);
  906. expect(pageCD.parent).toStrictEqual(pageC._id);
  907. // -- Check the found parent
  908. expect(parent).toStrictEqual(pageCD);
  909. });
  910. });
  911. });