v5.page.test.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  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: pageIdUpd14,
  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. },
  358. {
  359. _id: pageIdUpd15,
  360. path: '/mup27_pub',
  361. grant: Page.GRANT_PUBLIC,
  362. creator: pModelUserId1,
  363. lastUpdateUser: pModelUserId1,
  364. isEmpty: false,
  365. parent: rootPage,
  366. descendantCount: 1,
  367. },
  368. {
  369. path: '/mup27_pub/mup28_owner',
  370. grant: Page.GRANT_OWNER,
  371. creator: pModelUserId1,
  372. lastUpdateUser: pModelUserId1,
  373. isEmpty: false,
  374. parent: pageIdUpd15,
  375. grantedUsers: [pModelUserId1],
  376. descendantCount: 0,
  377. },
  378. {
  379. _id: pageIdUpd16,
  380. path: '/mup29_A',
  381. grant: Page.GRANT_USER_GROUP,
  382. grantedGroup: groupIdA,
  383. creator: pModelUserId1,
  384. lastUpdateUser: pModelUserId1,
  385. isEmpty: false,
  386. parent: rootPage,
  387. descendantCount: 1,
  388. },
  389. {
  390. path: '/mup29_A/mup30_owner',
  391. grant: Page.GRANT_OWNER,
  392. grantedUsers: [pModelUserId1],
  393. creator: pModelUserId1,
  394. lastUpdateUser: pModelUserId1,
  395. isEmpty: false,
  396. parent: pageIdUpd16,
  397. descendantCount: 0,
  398. },
  399. {
  400. _id: pageIdUpd17,
  401. path: '/mup31_A',
  402. grant: Page.GRANT_USER_GROUP,
  403. grantedGroup: groupIdA,
  404. creator: pModelUserId1,
  405. lastUpdateUser: pModelUserId1,
  406. isEmpty: false,
  407. parent: rootPage,
  408. descendantCount: 1,
  409. },
  410. {
  411. path: '/mup31_A/mup32_owner',
  412. grant: Page.GRANT_OWNER,
  413. grantedUsers: [pModelUserId1],
  414. creator: pModelUserId1,
  415. lastUpdateUser: pModelUserId1,
  416. isEmpty: false,
  417. parent: pageIdUpd17,
  418. descendantCount: 0,
  419. },
  420. {
  421. _id: pageIdUpd18,
  422. path: '/mup33_C',
  423. grant: Page.GRANT_USER_GROUP,
  424. grantedGroup: groupIdC,
  425. creator: pModelUserId3,
  426. lastUpdateUser: pModelUserId3,
  427. isEmpty: false,
  428. parent: rootPage,
  429. descendantCount: 1,
  430. },
  431. {
  432. path: '/mup33_C/mup34_owner',
  433. grant: Page.GRANT_OWNER,
  434. grantedUsers: [pModelUserId3],
  435. creator: pModelUserId3,
  436. lastUpdateUser: pModelUserId3,
  437. isEmpty: false,
  438. parent: pageIdUpd18,
  439. descendantCount: 0,
  440. },
  441. {
  442. _id: pageIdUpd19,
  443. path: '/mup35_owner',
  444. grant: Page.GRANT_OWNER,
  445. grantedUsers: [pModelUserId1],
  446. creator: pModelUserId1,
  447. lastUpdateUser: pModelUserId1,
  448. isEmpty: false,
  449. parent: rootPage,
  450. descendantCount: 1,
  451. },
  452. {
  453. path: '/mup35_owner/mup36_owner',
  454. grant: Page.GRANT_OWNER,
  455. grantedUsers: [pModelUserId1],
  456. creator: pModelUserId1,
  457. lastUpdateUser: pModelUserId1,
  458. isEmpty: false,
  459. parent: pageIdUpd19,
  460. descendantCount: 0,
  461. },
  462. {
  463. path: '/mup40', // used this number to resolve conflict
  464. grant: Page.GRANT_OWNER,
  465. grantedUsers: [dummyUser1._id],
  466. creator: dummyUser1,
  467. lastUpdateUser: dummyUser1._id,
  468. isEmpty: false,
  469. parent: rootPage._id,
  470. descendantCount: 0,
  471. },
  472. ]);
  473. });
  474. describe('update', () => {
  475. const updatePage = async(page, newRevisionBody, oldRevisionBody, user, options = {}) => {
  476. const mockedRenameSubOperation = jest.spyOn(Page, 'emitPageEventUpdate').mockReturnValue(null);
  477. const savedPage = await Page.updatePage(page, newRevisionBody, oldRevisionBody, user, options);
  478. mockedRenameSubOperation.mockRestore();
  479. return savedPage;
  480. };
  481. describe('Changing grant from PUBLIC to RESTRICTED of', () => {
  482. test('an only-child page will delete its empty parent page', async() => {
  483. const pathT = '/mup13_top';
  484. const path1 = '/mup13_top/mup1_emp';
  485. const path2 = '/mup13_top/mup1_emp/mup2_pub';
  486. const pageT = await Page.findOne({ path: pathT, descendantCount: 2 });
  487. const page1 = await Page.findOne({ path: path1, isEmpty: true });
  488. const page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC });
  489. expect(pageT).toBeTruthy();
  490. expect(page1).toBeTruthy();
  491. expect(page2).toBeTruthy();
  492. const options = { grant: Page.GRANT_RESTRICTED, grantUserGroupId: null };
  493. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, options);
  494. const _pageT = await Page.findOne({ path: pathT });
  495. const _page1 = await Page.findOne({ path: path1 });
  496. const _page2 = await Page.findOne({ path: path2, grant: Page.GRANT_RESTRICTED });
  497. expect(_pageT).toBeTruthy();
  498. expect(_page1).toBeNull();
  499. expect(_page2).toBeTruthy();
  500. expect(_pageT.descendantCount).toBe(1);
  501. });
  502. test('a page that has children will create an empty page with the same path and it becomes a new parent', async() => {
  503. const pathT = '/mup14_top';
  504. const path1 = '/mup14_top/mup6_pub';
  505. const path2 = '/mup14_top/mup6_pub/mup7_pub';
  506. const top = await Page.findOne({ path: pathT, descendantCount: 2 });
  507. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  508. const page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC });
  509. expect(top).toBeTruthy();
  510. expect(page1).toBeTruthy();
  511. expect(page2).toBeTruthy();
  512. await Page.updatePage(page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  513. const _top = await Page.findOne({ path: pathT });
  514. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  515. const _page2 = await Page.findOne({ path: path2 });
  516. const _pageN = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  517. expect(_page1).toBeTruthy();
  518. expect(_page2).toBeTruthy();
  519. expect(_pageN).toBeTruthy();
  520. expect(_page1.parent).toBeNull();
  521. expect(_page2.parent).toStrictEqual(_pageN._id);
  522. expect(_pageN.parent).toStrictEqual(top._id);
  523. expect(_pageN.isEmpty).toBe(true);
  524. expect(_pageN.descendantCount).toBe(1);
  525. expect(_top.descendantCount).toBe(1);
  526. });
  527. test('of a leaf page will NOT have an empty page with the same path', async() => {
  528. const pathT = '/mup15_top';
  529. const path1 = '/mup15_top/mup8_pub';
  530. const pageT = await Page.findOne({ path: pathT, descendantCount: 1 });
  531. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  532. const count = await Page.count({ path: path1 });
  533. expect(pageT).toBeTruthy();
  534. expect(page1).toBeTruthy();
  535. expect(count).toBe(1);
  536. await Page.updatePage(page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  537. const _pageT = await Page.findOne({ path: pathT });
  538. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  539. const _pageNotExist = await Page.findOne({ path: path1, isEmpty: true });
  540. expect(_pageT).toBeTruthy();
  541. expect(_page1).toBeTruthy();
  542. expect(_pageNotExist).toBeNull();
  543. expect(_pageT.descendantCount).toBe(0);
  544. });
  545. });
  546. describe('Changing grant to GRANT_RESTRICTED', () => {
  547. test('successfully change to GRANT_RESTRICTED from GRANT_OWNER', async() => {
  548. const path = '/mup40';
  549. const _page = await Page.findOne({ path, grant: Page.GRANT_OWNER, grantedUsers: [dummyUser1._id] });
  550. expect(_page).toBeTruthy();
  551. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  552. const page = await Page.findOne({ path });
  553. expect(page).toBeTruthy();
  554. expect(page.grant).toBe(Page.GRANT_RESTRICTED);
  555. expect(page.grantedUsers).toStrictEqual([]);
  556. });
  557. });
  558. describe('Changing grant from RESTRICTED to PUBLIC of', () => {
  559. test('a page will create ancestors if they do not exist', async() => {
  560. const pathT = '/mup16_top';
  561. const path1 = '/mup16_top/mup9_pub';
  562. const path2 = '/mup16_top/mup9_pub/mup10_pub';
  563. const path3 = '/mup16_top/mup9_pub/mup10_pub/mup11_awl';
  564. const top = await Page.findOne({ path: pathT });
  565. const page1 = await Page.findOne({ path: path1 });
  566. const page2 = await Page.findOne({ path: path2 });
  567. const page3 = await Page.findOne({ path: path3, grant: Page.GRANT_RESTRICTED });
  568. expect(top).toBeTruthy();
  569. expect(page3).toBeTruthy();
  570. expect(page1).toBeNull();
  571. expect(page2).toBeNull();
  572. await Page.updatePage(page3, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_PUBLIC });
  573. const _pageT = await Page.findOne({ path: pathT });
  574. const _page1 = await Page.findOne({ path: path1, isEmpty: true });
  575. const _page2 = await Page.findOne({ path: path2, isEmpty: true });
  576. const _page3 = await Page.findOne({ path: path3, grant: Page.GRANT_PUBLIC });
  577. expect(_page1).toBeTruthy();
  578. expect(_page2).toBeTruthy();
  579. expect(_page3).toBeTruthy();
  580. expect(_page1.parent).toStrictEqual(top._id);
  581. expect(_page2.parent).toStrictEqual(_page1._id);
  582. expect(_page3.parent).toStrictEqual(_page2._id);
  583. expect(_pageT.descendantCount).toBe(1);
  584. });
  585. test('a page will replace an empty page with the same path if any', async() => {
  586. const pathT = '/mup17_top';
  587. const path1 = '/mup17_top/mup12_emp';
  588. const path2 = '/mup17_top/mup12_emp/mup18_pub';
  589. const pageT = await Page.findOne({ path: pathT, descendantCount: 1 });
  590. const page1 = await Page.findOne({ path: path1, isEmpty: true });
  591. const page2 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED, isEmpty: false });
  592. const page3 = await Page.findOne({ path: path2 });
  593. expect(pageT).toBeTruthy();
  594. expect(page1).toBeTruthy();
  595. expect(page2).toBeTruthy();
  596. expect(page3).toBeTruthy();
  597. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_PUBLIC });
  598. const _pageT = await Page.findOne({ path: pathT });
  599. const _page1 = await Page.findOne({ path: path1, isEmpty: true }); // should be replaced
  600. const _page2 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  601. const _page3 = await Page.findOne({ path: path2 });
  602. expect(_pageT).toBeTruthy();
  603. expect(_page1).toBeNull();
  604. expect(_page2).toBeTruthy();
  605. expect(_page3).toBeTruthy();
  606. expect(_page2.grant).toBe(Page.GRANT_PUBLIC);
  607. expect(_page2.parent).toStrictEqual(_pageT._id);
  608. expect(_page3.parent).toStrictEqual(_page2._id);
  609. expect(_pageT.descendantCount).toBe(2);
  610. });
  611. });
  612. describe('Changing grant to GRANT_OWNER(onlyme)', () => {
  613. test('successfully change to GRANT_OWNER from GRANT_PUBLIC', async() => {
  614. const path = '/mup19';
  615. const _page = await Page.findOne({ path, grant: Page.GRANT_PUBLIC });
  616. expect(_page).toBeTruthy();
  617. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER });
  618. const page = await Page.findOne({ path });
  619. expect(page.grant).toBe(Page.GRANT_OWNER);
  620. expect(page.grantedUsers).toStrictEqual([dummyUser1._id]);
  621. });
  622. test('successfully change to GRANT_OWNER from GRANT_USER_GROUP', async() => {
  623. const path = '/mup20';
  624. const _page = await Page.findOne({ path, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
  625. expect(_page).toBeTruthy();
  626. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', pModelUser1, { grant: Page.GRANT_OWNER });
  627. const page = await Page.findOne({ path });
  628. expect(page.grant).toBe(Page.GRANT_OWNER);
  629. expect(page.grantedUsers).toStrictEqual([pModelUser1._id]);
  630. expect(page.grantedGroup).toBeNull();
  631. });
  632. test('successfully change to GRANT_OWNER from GRANT_RESTRICTED', async() => {
  633. const path = '/mup21';
  634. const _page = await Page.findOne({ path, grant: Page.GRANT_RESTRICTED });
  635. expect(_page).toBeTruthy();
  636. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER });
  637. const page = await Page.findOne({ path });
  638. expect(page.grant).toBe(Page.GRANT_OWNER);
  639. expect(page.grantedUsers).toStrictEqual([dummyUser1._id]);
  640. });
  641. test('Failed to change to GRANT_OWNER if one of the ancestors is GRANT_USER_GROUP page', async() => {
  642. const path1 = '/mup22';
  643. const path2 = '/mup22/mup23';
  644. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  645. const _page2 = await Page.findOne({ path: path2, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
  646. expect(_page1).toBeTruthy();
  647. expect(_page2).toBeTruthy();
  648. await expect(updatePage(_page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER }))
  649. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  650. const page1 = await Page.findOne({ path1 });
  651. expect(page1).toBeTruthy();
  652. expect(page1.grant).toBe(Page.GRANT_PUBLIC);
  653. expect(page1.grantedUsers).not.toStrictEqual([dummyUser1._id]);
  654. });
  655. });
  656. describe('Changing grant to GRANT_USER_GROUP', () => {
  657. describe('update grant of a page under a page with GRANT_PUBLIC', () => {
  658. test('successfully change to GRANT_USER_GROUP from GRANT_PUBLIC if parent page is GRANT_PUBLIC', async() => {
  659. // path
  660. const path1 = '/mup24_pub';
  661. const path2 = '/mup24_pub/mup25_pub';
  662. // page
  663. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC }); // out of update scope
  664. const _page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC, parent: _page1._id }); // update target
  665. expect(_page1).toBeTruthy();
  666. expect(_page2).toBeTruthy();
  667. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: groupIdA };
  668. const updatedPage = await updatePage(_page2, 'new', 'old', pModelUser1, options); // from GRANT_PUBLIC to GRANT_USER_GROUP(groupIdA)
  669. const page1 = await Page.findById(_page1._id);
  670. const page2 = await Page.findById(_page2._id);
  671. expect(page1).toBeTruthy();
  672. expect(page2).toBeTruthy();
  673. expect(updatedPage).toBeTruthy();
  674. expect(updatedPage._id).toStrictEqual(page2._id);
  675. // check page2 grant and group
  676. expect(page2.grant).toBe(Page.GRANT_USER_GROUP);
  677. expect(page2.grantedGroup._id).toStrictEqual(groupIdA);
  678. });
  679. test('successfully change to GRANT_USER_GROUP from GRANT_RESTRICTED if parent page is GRANT_PUBLIC', async() => {
  680. // path
  681. const _path1 = '/mup26_awl';
  682. // page
  683. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_RESTRICTED });
  684. expect(_page1).toBeTruthy();
  685. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: groupIdA };
  686. const updatedPage = await updatePage(_page1, 'new', 'old', pModelUser1, options); // from GRANT_RESTRICTED to GRANT_USER_GROUP(groupIdA)
  687. const page1 = await Page.findById(_page1._id);
  688. expect(page1).toBeTruthy();
  689. expect(updatedPage).toBeTruthy();
  690. expect(updatedPage._id).toStrictEqual(page1._id);
  691. // updated page
  692. expect(page1.grant).toBe(Page.GRANT_USER_GROUP);
  693. expect(page1.grantedGroup._id).toStrictEqual(groupIdA);
  694. // parent's grant check
  695. const parent = await Page.findById(page1.parent);
  696. expect(parent.grant).toBe(Page.GRANT_PUBLIC);
  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({
  705. path: path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1], parent: _page1._id,
  706. }); // update target
  707. expect(_page1).toBeTruthy();
  708. expect(_page2).toBeTruthy();
  709. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: groupIdA };
  710. const updatedPage = await updatePage(_page2, 'new', 'old', pModelUser1, options); // from GRANT_OWNER to GRANT_USER_GROUP(groupIdA)
  711. const page1 = await Page.findById(_page1._id);
  712. const page2 = await Page.findById(_page2._id);
  713. expect(page1).toBeTruthy();
  714. expect(page2).toBeTruthy();
  715. expect(updatedPage).toBeTruthy();
  716. expect(updatedPage._id).toStrictEqual(page2._id);
  717. // grant check
  718. expect(page2.grant).toBe(Page.GRANT_USER_GROUP);
  719. expect(page2.grantedGroup._id).toStrictEqual(groupIdA);
  720. expect(page2.grantedUsers.length).toBe(0);
  721. });
  722. });
  723. describe('update grant of a page under a page with GRANT_USER_GROUP', () => {
  724. test('successfully change to GRANT_USER_GROUP if the group to set is the child or descendant of the parent page group', async() => {
  725. // path
  726. const _path1 = '/mup29_A';
  727. const _path2 = '/mup29_A/mup30_owner';
  728. // page
  729. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA }); // out of update scope
  730. const _page2 = await Page.findOne({ // update target
  731. path: _path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1], parent: _page1._id,
  732. });
  733. expect(_page1).toBeTruthy();
  734. expect(_page2).toBeTruthy();
  735. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: groupIdB };
  736. // First round
  737. // Group relation(parent -> child): groupIdA -> groupIdB -> groupIdC
  738. const updatedPage = await updatePage(_page2, 'new', 'old', pModelUser3, options); // from GRANT_OWNER to GRANT_USER_GROUP(groupIdB)
  739. const page1 = await Page.findById(_page1._id);
  740. const page2 = await Page.findById(_page2._id);
  741. expect(page1).toBeTruthy();
  742. expect(page2).toBeTruthy();
  743. expect(updatedPage).toBeTruthy();
  744. expect(updatedPage._id).toStrictEqual(page2._id);
  745. expect(page2.grant).toBe(Page.GRANT_USER_GROUP);
  746. expect(page2.grantedGroup._id).toStrictEqual(groupIdB);
  747. expect(page2.grantedUsers.length).toBe(0);
  748. // Second round
  749. // Update group to groupC which is a grandchild from pageA's point of view
  750. const secondRoundOptions = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: groupIdC }; // from GRANT_USER_GROUP(groupIdB) to GRANT_USER_GROUP(groupIdC)
  751. const secondRoundUpdatedPage = await updatePage(_page2, 'new', 'new', pModelUser3, secondRoundOptions);
  752. expect(secondRoundUpdatedPage).toBeTruthy();
  753. expect(secondRoundUpdatedPage.grant).toBe(Page.GRANT_USER_GROUP);
  754. expect(secondRoundUpdatedPage.grantedGroup._id).toStrictEqual(groupIdC);
  755. });
  756. 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() => {
  757. // path
  758. const _path1 = '/mup31_A';
  759. const _path2 = '/mup31_A/mup32_owner';
  760. // page
  761. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
  762. const _page2 = await Page.findOne({ // update target
  763. path: _path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1._id], parent: _page1._id,
  764. });
  765. expect(_page1).toBeTruthy();
  766. expect(_page2).toBeTruthy();
  767. // group
  768. const _groupIsolated = await UserGroup.findById(groupIdIsolate);
  769. expect(_groupIsolated).toBeTruthy();
  770. // group parent check
  771. expect(_groupIsolated.parent).toBeUndefined(); // should have no parent
  772. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: groupIdIsolate };
  773. await expect(updatePage(_page2, 'new', 'old', pModelUser1, options)) // from GRANT_OWNER to GRANT_USER_GROUP(groupIdIsolate)
  774. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  775. const page1 = await Page.findById(_page1._id);
  776. const page2 = await Page.findById(_page2._id);
  777. expect(page1).toBeTruthy();
  778. expect(page1).toBeTruthy();
  779. expect(page2.grant).toBe(Page.GRANT_OWNER); // should be the same before the update
  780. expect(page2.grantedUsers).toStrictEqual([pModelUser1._id]); // should be the same before the update
  781. expect(page2.grantedGroup).toBeUndefined(); // no group should be set
  782. });
  783. test('Fail to change to GRANT_USER_GROUP if the group to set is an ancestor of the parent page group', async() => {
  784. // path
  785. const _path1 = '/mup33_C';
  786. const _path2 = '/mup33_C/mup34_owner';
  787. // page
  788. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdC }); // groupC
  789. const _page2 = await Page.findOne({ // update target
  790. path: _path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser3], parent: _page1._id,
  791. });
  792. expect(_page1).toBeTruthy();
  793. expect(_page2).toBeTruthy();
  794. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: groupIdA };
  795. // Group relation(parent -> child): groupIdA -> groupIdB -> groupIdC
  796. // this should fail because the groupC is a descendant of groupA
  797. await expect(updatePage(_page2, 'new', 'old', pModelUser3, options)) // from GRANT_OWNER to GRANT_USER_GROUP(groupIdA)
  798. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  799. const page1 = await Page.findById(_page1._id);
  800. const page2 = await Page.findById(_page2._id);
  801. expect(page1).toBeTruthy();
  802. expect(page2).toBeTruthy();
  803. expect(page2.grant).toBe(Page.GRANT_OWNER); // should be the same before the update
  804. expect(page2.grantedUsers).toStrictEqual([pModelUser3._id]); // should be the same before the update
  805. expect(page2.grantedGroup).toBeUndefined(); // no group should be set
  806. });
  807. });
  808. describe('update grant of a page under a page with GRANT_OWNER', () => {
  809. test('Fail to change from GRNAT_OWNER', async() => {
  810. // path
  811. const path1 = '/mup35_owner';
  812. const path2 = '/mup35_owner/mup36_owner';
  813. // page
  814. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1] });
  815. const _page2 = await Page.findOne({ // update target
  816. path: path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1], parent: _page1._id,
  817. });
  818. expect(_page1).toBeTruthy();
  819. expect(_page2).toBeTruthy();
  820. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: groupIdA };
  821. await expect(updatePage(_page2, 'new', 'old', pModelUser1, options)) // from GRANT_OWNER to GRANT_USER_GROUP(groupIdA)
  822. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  823. const page1 = await Page.findById(_page1.id);
  824. const page2 = await Page.findById(_page2.id);
  825. expect(page1).toBeTruthy();
  826. expect(page2).toBeTruthy();
  827. expect(page2.grant).toBe(Page.GRANT_OWNER); // should be the same before the update
  828. expect(page2.grantedUsers).toStrictEqual([pModelUser1._id]); // should be the same before the update
  829. expect(page2.grantedGroup).toBeUndefined(); // no group should be set
  830. });
  831. });
  832. });
  833. });
  834. });