v5.page.test.js 35 KB

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