v5.page.test.js 30 KB

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