v5.page.test.js 33 KB

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