v5.non-public-page.test.ts 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174
  1. /* eslint-disable no-unused-vars */
  2. import { advanceTo } from 'jest-date-mock';
  3. import mongoose from 'mongoose';
  4. import { getInstance } from '../setup-crowi';
  5. describe('PageService page operations with non-public pages', () => {
  6. let dummyUser1;
  7. let dummyUser2;
  8. let npDummyUser1;
  9. let npDummyUser2;
  10. let npDummyUser3;
  11. let groupIdIsolate;
  12. let groupIdA;
  13. let groupIdB;
  14. let groupIdC;
  15. let crowi;
  16. let Page;
  17. let Revision;
  18. let User;
  19. let UserGroup;
  20. let UserGroupRelation;
  21. let Tag;
  22. let PageTagRelation;
  23. let Bookmark;
  24. let Comment;
  25. let ShareLink;
  26. let PageRedirect;
  27. let xssSpy;
  28. let rootPage;
  29. /**
  30. * Rename
  31. */
  32. const pageIdRename1 = new mongoose.Types.ObjectId();
  33. const pageIdRename2 = new mongoose.Types.ObjectId();
  34. const pageIdRename3 = new mongoose.Types.ObjectId();
  35. const pageIdRename4 = new mongoose.Types.ObjectId();
  36. const pageIdRename5 = new mongoose.Types.ObjectId();
  37. const pageIdRename6 = new mongoose.Types.ObjectId();
  38. const pageIdRename7 = new mongoose.Types.ObjectId();
  39. const pageIdRename8 = new mongoose.Types.ObjectId();
  40. const pageIdRename9 = new mongoose.Types.ObjectId();
  41. /**
  42. * Duplicate
  43. */
  44. // page id
  45. const pageIdDuplicate1 = new mongoose.Types.ObjectId();
  46. const pageIdDuplicate2 = new mongoose.Types.ObjectId();
  47. const pageIdDuplicate3 = new mongoose.Types.ObjectId();
  48. const pageIdDuplicate4 = new mongoose.Types.ObjectId();
  49. const pageIdDuplicate5 = new mongoose.Types.ObjectId();
  50. const pageIdDuplicate6 = new mongoose.Types.ObjectId();
  51. // revision id
  52. const revisionIdDuplicate1 = new mongoose.Types.ObjectId();
  53. const revisionIdDuplicate2 = new mongoose.Types.ObjectId();
  54. const revisionIdDuplicate3 = new mongoose.Types.ObjectId();
  55. const revisionIdDuplicate4 = new mongoose.Types.ObjectId();
  56. const revisionIdDuplicate5 = new mongoose.Types.ObjectId();
  57. const revisionIdDuplicate6 = new mongoose.Types.ObjectId();
  58. /**
  59. * Revert
  60. */
  61. // page id
  62. const pageIdRevert1 = new mongoose.Types.ObjectId();
  63. const pageIdRevert2 = new mongoose.Types.ObjectId();
  64. const pageIdRevert3 = new mongoose.Types.ObjectId();
  65. const pageIdRevert4 = new mongoose.Types.ObjectId();
  66. const pageIdRevert5 = new mongoose.Types.ObjectId();
  67. const pageIdRevert6 = new mongoose.Types.ObjectId();
  68. // revision id
  69. const revisionIdRevert1 = new mongoose.Types.ObjectId();
  70. const revisionIdRevert2 = new mongoose.Types.ObjectId();
  71. const revisionIdRevert3 = new mongoose.Types.ObjectId();
  72. const revisionIdRevert4 = new mongoose.Types.ObjectId();
  73. const revisionIdRevert5 = new mongoose.Types.ObjectId();
  74. const revisionIdRevert6 = new mongoose.Types.ObjectId();
  75. // tag id
  76. const tagIdRevert1 = new mongoose.Types.ObjectId();
  77. const tagIdRevert2 = new mongoose.Types.ObjectId();
  78. beforeAll(async() => {
  79. crowi = await getInstance();
  80. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', { 'app:isV5Compatible': true });
  81. User = mongoose.model('User');
  82. UserGroup = mongoose.model('UserGroup');
  83. UserGroupRelation = mongoose.model('UserGroupRelation');
  84. Page = mongoose.model('Page');
  85. Revision = mongoose.model('Revision');
  86. Tag = mongoose.model('Tag');
  87. PageTagRelation = mongoose.model('PageTagRelation');
  88. Bookmark = mongoose.model('Bookmark');
  89. Comment = mongoose.model('Comment');
  90. ShareLink = mongoose.model('ShareLink');
  91. PageRedirect = mongoose.model('PageRedirect');
  92. UserGroup = mongoose.model('UserGroup');
  93. UserGroupRelation = mongoose.model('UserGroupRelation');
  94. /*
  95. * Common
  96. */
  97. const npUserId1 = new mongoose.Types.ObjectId();
  98. const npUserId2 = new mongoose.Types.ObjectId();
  99. const npUserId3 = new mongoose.Types.ObjectId();
  100. await User.insertMany([
  101. {
  102. _id: npUserId1, name: 'npUser1', username: 'npUser1', email: 'npUser1@example.com',
  103. },
  104. {
  105. _id: npUserId2, name: 'npUser2', username: 'npUser2', email: 'npUser2@example.com',
  106. },
  107. {
  108. _id: npUserId3, name: 'npUser3', username: 'npUser3', email: 'npUser3@example.com',
  109. },
  110. ]);
  111. groupIdIsolate = new mongoose.Types.ObjectId();
  112. groupIdA = new mongoose.Types.ObjectId();
  113. groupIdB = new mongoose.Types.ObjectId();
  114. groupIdC = new mongoose.Types.ObjectId();
  115. await UserGroup.insertMany([
  116. {
  117. _id: groupIdIsolate,
  118. name: 'np_groupIsolate',
  119. },
  120. {
  121. _id: groupIdA,
  122. name: 'np_groupA',
  123. },
  124. {
  125. _id: groupIdB,
  126. name: 'np_groupB',
  127. parent: groupIdA,
  128. },
  129. {
  130. _id: groupIdC,
  131. name: 'np_groupC',
  132. parent: groupIdB,
  133. },
  134. ]);
  135. await UserGroupRelation.insertMany([
  136. {
  137. relatedGroup: groupIdIsolate,
  138. relatedUser: npUserId1,
  139. createdAt: new Date(),
  140. },
  141. {
  142. relatedGroup: groupIdIsolate,
  143. relatedUser: npUserId2,
  144. createdAt: new Date(),
  145. },
  146. {
  147. relatedGroup: groupIdA,
  148. relatedUser: npUserId1,
  149. createdAt: new Date(),
  150. },
  151. {
  152. relatedGroup: groupIdA,
  153. relatedUser: npUserId2,
  154. createdAt: new Date(),
  155. },
  156. {
  157. relatedGroup: groupIdA,
  158. relatedUser: npUserId3,
  159. createdAt: new Date(),
  160. },
  161. {
  162. relatedGroup: groupIdB,
  163. relatedUser: npUserId2,
  164. createdAt: new Date(),
  165. },
  166. {
  167. relatedGroup: groupIdB,
  168. relatedUser: npUserId3,
  169. createdAt: new Date(),
  170. },
  171. {
  172. relatedGroup: groupIdC,
  173. relatedUser: npUserId3,
  174. createdAt: new Date(),
  175. },
  176. ]);
  177. xssSpy = jest.spyOn(crowi.xss, 'process').mockImplementation(path => path);
  178. dummyUser1 = await User.findOne({ username: 'v5DummyUser1' });
  179. dummyUser2 = await User.findOne({ username: 'v5DummyUser2' });
  180. npDummyUser1 = await User.findOne({ username: 'npUser1' });
  181. npDummyUser2 = await User.findOne({ username: 'npUser2' });
  182. npDummyUser3 = await User.findOne({ username: 'npUser3' });
  183. rootPage = await Page.findOne({ path: '/' });
  184. if (rootPage == null) {
  185. const pages = await Page.insertMany([{ path: '/', grant: Page.GRANT_PUBLIC }]);
  186. rootPage = pages[0];
  187. }
  188. /*
  189. * Rename
  190. */
  191. await Page.insertMany([
  192. {
  193. _id: pageIdRename1,
  194. path: '/np_rename1_destination',
  195. grant: Page.GRANT_PUBLIC,
  196. creator: dummyUser1._id,
  197. lastUpdateUser: dummyUser1._id,
  198. parent: rootPage._id,
  199. },
  200. {
  201. _id: pageIdRename2,
  202. path: '/np_rename2',
  203. grant: Page.GRANT_USER_GROUP,
  204. grantedGroup: groupIdB,
  205. creator: npDummyUser2._id,
  206. lastUpdateUser: npDummyUser2._id,
  207. parent: rootPage._id,
  208. },
  209. {
  210. _id: pageIdRename3,
  211. path: '/np_rename2/np_rename3',
  212. grant: Page.GRANT_USER_GROUP,
  213. grantedGroup: groupIdC,
  214. creator: npDummyUser3._id,
  215. lastUpdateUser: npDummyUser3._id,
  216. parent: pageIdRename2._id,
  217. },
  218. {
  219. _id: pageIdRename4,
  220. path: '/np_rename4_destination',
  221. grant: Page.GRANT_USER_GROUP,
  222. grantedGroup: groupIdIsolate,
  223. creator: npDummyUser3._id,
  224. lastUpdateUser: npDummyUser3._id,
  225. parent: rootPage._id,
  226. },
  227. {
  228. _id: pageIdRename5,
  229. path: '/np_rename5',
  230. grant: Page.GRANT_USER_GROUP,
  231. grantedGroup: groupIdB,
  232. creator: npDummyUser2._id,
  233. lastUpdateUser: npDummyUser2._id,
  234. parent: rootPage._id,
  235. },
  236. {
  237. _id: pageIdRename6,
  238. path: '/np_rename5/np_rename6',
  239. grant: Page.GRANT_USER_GROUP,
  240. grantedGroup: groupIdB,
  241. creator: npDummyUser2._id,
  242. lastUpdateUser: npDummyUser2._id,
  243. parent: pageIdRename5,
  244. },
  245. {
  246. _id: pageIdRename7,
  247. path: '/np_rename7_destination',
  248. grant: Page.GRANT_USER_GROUP,
  249. grantedGroup: groupIdIsolate,
  250. creator: npDummyUser2._id,
  251. lastUpdateUser: npDummyUser2._id,
  252. parent: pageIdRename5,
  253. },
  254. {
  255. _id: pageIdRename8,
  256. path: '/np_rename8',
  257. grant: Page.GRANT_RESTRICTED,
  258. creator: dummyUser1._id,
  259. lastUpdateUser: dummyUser1._id,
  260. },
  261. {
  262. _id: pageIdRename9,
  263. path: '/np_rename8/np_rename9',
  264. grant: Page.GRANT_RESTRICTED,
  265. creator: dummyUser2._id,
  266. lastUpdateUser: dummyUser2._id,
  267. },
  268. ]);
  269. /*
  270. * Duplicate
  271. */
  272. await Page.insertMany([
  273. {
  274. _id: pageIdDuplicate1,
  275. path: '/np_duplicate1',
  276. grant: Page.GRANT_RESTRICTED,
  277. creator: dummyUser1._id,
  278. lastUpdateUser: dummyUser1._id,
  279. revision: revisionIdDuplicate1,
  280. },
  281. {
  282. _id: pageIdDuplicate2,
  283. path: '/np_duplicate2',
  284. grant: Page.GRANT_USER_GROUP,
  285. grantedGroup: groupIdA,
  286. creator: npDummyUser1._id,
  287. lastUpdateUser: npDummyUser1._id,
  288. revision: revisionIdDuplicate2,
  289. parent: rootPage._id,
  290. },
  291. {
  292. _id: pageIdDuplicate3,
  293. path: '/np_duplicate2/np_duplicate3',
  294. grant: Page.GRANT_USER_GROUP,
  295. grantedGroup: groupIdB,
  296. creator: npDummyUser2._id,
  297. lastUpdateUser: npDummyUser2._id,
  298. revision: revisionIdDuplicate3,
  299. parent: pageIdDuplicate2,
  300. },
  301. {
  302. _id: pageIdDuplicate4,
  303. path: '/np_duplicate4',
  304. grant: Page.GRANT_PUBLIC,
  305. creator: npDummyUser1._id,
  306. lastUpdateUser: npDummyUser1._id,
  307. revision: revisionIdDuplicate4,
  308. parent: rootPage._id,
  309. },
  310. {
  311. _id: pageIdDuplicate5,
  312. path: '/np_duplicate4/np_duplicate5',
  313. grant: Page.GRANT_RESTRICTED,
  314. creator: npDummyUser1._id,
  315. lastUpdateUser: npDummyUser1._id,
  316. revision: revisionIdDuplicate5,
  317. },
  318. {
  319. _id: pageIdDuplicate6,
  320. path: '/np_duplicate4/np_duplicate6',
  321. grant: Page.GRANT_PUBLIC,
  322. creator: npDummyUser1._id,
  323. lastUpdateUser: npDummyUser1._id,
  324. parent: pageIdDuplicate4,
  325. revision: revisionIdDuplicate6,
  326. },
  327. ]);
  328. await Revision.insertMany([
  329. {
  330. _id: revisionIdDuplicate1,
  331. body: 'np_duplicate1',
  332. format: 'markdown',
  333. pageId: pageIdDuplicate1,
  334. author: npDummyUser1._id,
  335. },
  336. {
  337. _id: revisionIdDuplicate2,
  338. body: 'np_duplicate2',
  339. format: 'markdown',
  340. pageId: pageIdDuplicate2,
  341. author: npDummyUser2._id,
  342. },
  343. {
  344. _id: revisionIdDuplicate3,
  345. body: 'np_duplicate3',
  346. format: 'markdown',
  347. pageId: pageIdDuplicate3,
  348. author: npDummyUser2._id,
  349. },
  350. {
  351. _id: revisionIdDuplicate4,
  352. body: 'np_duplicate4',
  353. format: 'markdown',
  354. pageId: pageIdDuplicate4,
  355. author: npDummyUser2._id,
  356. },
  357. {
  358. _id: revisionIdDuplicate5,
  359. body: 'np_duplicate5',
  360. format: 'markdown',
  361. pageId: pageIdDuplicate5,
  362. author: npDummyUser2._id,
  363. },
  364. {
  365. _id: revisionIdDuplicate6,
  366. body: 'np_duplicate6',
  367. format: 'markdown',
  368. pageId: pageIdDuplicate6,
  369. author: npDummyUser1._id,
  370. },
  371. ]);
  372. /**
  373. * Delete
  374. */
  375. const pageIdDelete1 = new mongoose.Types.ObjectId();
  376. const pageIdDelete2 = new mongoose.Types.ObjectId();
  377. const pageIdDelete3 = new mongoose.Types.ObjectId();
  378. const pageIdDelete4 = new mongoose.Types.ObjectId();
  379. await Page.insertMany([
  380. {
  381. _id: pageIdDelete1,
  382. path: '/npdel1_awl',
  383. grant: Page.GRANT_RESTRICTED,
  384. status: Page.STATUS_PUBLISHED,
  385. isEmpty: false,
  386. },
  387. {
  388. _id: pageIdDelete2,
  389. path: '/npdel2_ug',
  390. grant: Page.GRANT_USER_GROUP,
  391. grantedGroup: groupIdA,
  392. status: Page.STATUS_PUBLISHED,
  393. isEmpty: false,
  394. parent: rootPage._id,
  395. descendantCount: 0,
  396. },
  397. {
  398. _id: pageIdDelete3,
  399. path: '/npdel3_top',
  400. grant: Page.GRANT_USER_GROUP,
  401. grantedGroup: groupIdA,
  402. status: Page.STATUS_PUBLISHED,
  403. isEmpty: false,
  404. parent: rootPage._id,
  405. descendantCount: 2,
  406. },
  407. {
  408. _id: pageIdDelete4,
  409. path: '/npdel3_top/npdel4_ug',
  410. grant: Page.GRANT_USER_GROUP,
  411. grantedGroup: groupIdB,
  412. status: Page.STATUS_PUBLISHED,
  413. isEmpty: false,
  414. parent: pageIdDelete3._id,
  415. descendantCount: 1,
  416. },
  417. {
  418. path: '/npdel3_top/npdel4_ug',
  419. grant: Page.GRANT_RESTRICTED,
  420. status: Page.STATUS_PUBLISHED,
  421. isEmpty: false,
  422. },
  423. {
  424. path: '/npdel3_top/npdel4_ug/npdel5_ug',
  425. grant: Page.GRANT_USER_GROUP,
  426. grantedGroup: groupIdC,
  427. status: Page.STATUS_PUBLISHED,
  428. isEmpty: false,
  429. parent: pageIdDelete4._id,
  430. descendantCount: 0,
  431. },
  432. ]);
  433. /**
  434. * Delete completely
  435. */
  436. const pageIdDeleteComp1 = new mongoose.Types.ObjectId();
  437. const pageIdDeleteComp2 = new mongoose.Types.ObjectId();
  438. await Page.insertMany([
  439. {
  440. path: '/npdc1_awl',
  441. grant: Page.GRANT_RESTRICTED,
  442. status: Page.STATUS_PUBLISHED,
  443. isEmpty: false,
  444. },
  445. {
  446. path: '/npdc2_ug',
  447. grant: Page.GRANT_USER_GROUP,
  448. grantedGroup: groupIdA,
  449. status: Page.STATUS_PUBLISHED,
  450. isEmpty: false,
  451. parent: rootPage._id,
  452. },
  453. {
  454. _id: pageIdDeleteComp1,
  455. path: '/npdc3_ug',
  456. grant: Page.GRANT_USER_GROUP,
  457. grantedGroup: groupIdA,
  458. status: Page.STATUS_PUBLISHED,
  459. isEmpty: false,
  460. parent: rootPage._id,
  461. },
  462. {
  463. _id: pageIdDeleteComp2,
  464. path: '/npdc3_ug/npdc4_ug',
  465. grant: Page.GRANT_USER_GROUP,
  466. grantedGroup: groupIdB,
  467. status: Page.STATUS_PUBLISHED,
  468. isEmpty: false,
  469. parent: pageIdDeleteComp1,
  470. },
  471. {
  472. path: '/npdc3_ug/npdc4_ug/npdc5_ug',
  473. grant: Page.GRANT_USER_GROUP,
  474. grantedGroup: groupIdC,
  475. status: Page.STATUS_PUBLISHED,
  476. isEmpty: false,
  477. parent: pageIdDeleteComp2,
  478. },
  479. {
  480. path: '/npdc3_ug/npdc4_ug',
  481. grant: Page.GRANT_RESTRICTED,
  482. status: Page.STATUS_PUBLISHED,
  483. isEmpty: false,
  484. },
  485. ]);
  486. /**
  487. * Revert
  488. */
  489. await Page.insertMany([
  490. {
  491. _id: pageIdRevert1,
  492. path: '/trash/np_revert1',
  493. grant: Page.GRANT_RESTRICTED,
  494. revision: revisionIdRevert1,
  495. status: Page.STATUS_DELETED,
  496. },
  497. {
  498. _id: pageIdRevert2,
  499. path: '/trash/np_revert2',
  500. grant: Page.GRANT_USER_GROUP,
  501. grantedGroup: groupIdA,
  502. revision: revisionIdRevert2,
  503. status: Page.STATUS_DELETED,
  504. },
  505. {
  506. _id: pageIdRevert3,
  507. path: '/trash/np_revert3',
  508. revision: revisionIdRevert3,
  509. status: Page.STATUS_DELETED,
  510. parent: rootPage._id,
  511. },
  512. {
  513. _id: pageIdRevert4,
  514. path: '/trash/np_revert3/middle/np_revert4',
  515. grant: Page.GRANT_RESTRICTED,
  516. revision: revisionIdRevert4,
  517. status: Page.STATUS_DELETED,
  518. },
  519. {
  520. _id: pageIdRevert5,
  521. path: '/trash/np_revert5',
  522. grant: Page.GRANT_USER_GROUP,
  523. grantedGroup: groupIdA,
  524. revision: revisionIdRevert5,
  525. status: Page.STATUS_DELETED,
  526. },
  527. {
  528. _id: pageIdRevert6,
  529. path: '/trash/np_revert5/middle/np_revert6',
  530. grant: Page.GRANT_USER_GROUP,
  531. grantedGroup: groupIdB,
  532. revision: revisionIdRevert6,
  533. status: Page.STATUS_DELETED,
  534. },
  535. ]);
  536. await Revision.insertMany([
  537. {
  538. _id: revisionIdRevert1,
  539. pageId: pageIdRevert1,
  540. body: 'np_revert1',
  541. format: 'markdown',
  542. author: dummyUser1._id,
  543. },
  544. {
  545. _id: revisionIdRevert2,
  546. pageId: pageIdRevert2,
  547. body: 'np_revert2',
  548. format: 'markdown',
  549. author: npDummyUser1,
  550. },
  551. {
  552. _id: revisionIdRevert3,
  553. pageId: pageIdRevert3,
  554. body: 'np_revert3',
  555. format: 'markdown',
  556. author: npDummyUser1,
  557. },
  558. {
  559. _id: revisionIdRevert4,
  560. pageId: pageIdRevert4,
  561. body: 'np_revert4',
  562. format: 'markdown',
  563. author: npDummyUser1,
  564. },
  565. {
  566. _id: revisionIdRevert5,
  567. pageId: pageIdRevert5,
  568. body: 'np_revert5',
  569. format: 'markdown',
  570. author: npDummyUser1,
  571. },
  572. {
  573. _id: revisionIdRevert6,
  574. pageId: pageIdRevert6,
  575. body: 'np_revert6',
  576. format: 'markdown',
  577. author: npDummyUser1,
  578. },
  579. ]);
  580. await Tag.insertMany([
  581. { _id: tagIdRevert1, name: 'np_revertTag1' },
  582. { _id: tagIdRevert2, name: 'np_revertTag2' },
  583. ]);
  584. await PageTagRelation.insertMany([
  585. {
  586. relatedPage: pageIdRevert1,
  587. relatedTag: tagIdRevert1,
  588. isPageTrashed: true,
  589. },
  590. {
  591. relatedPage: pageIdRevert2,
  592. relatedTag: tagIdRevert2,
  593. isPageTrashed: true,
  594. },
  595. ]);
  596. });
  597. describe('Rename', () => {
  598. const renamePage = async(page, newPagePath, user, options) => {
  599. // mock return value
  600. const mockedRenameSubOperation = jest.spyOn(crowi.pageService, 'renameSubOperation').mockReturnValue(null);
  601. const mockedCreateAndSendNotifications = jest.spyOn(crowi.pageService, 'createAndSendNotifications').mockReturnValue(null);
  602. const renamedPage = await crowi.pageService.renamePage(page, newPagePath, user, options);
  603. // retrieve the arguments passed when calling method renameSubOperation inside renamePage method
  604. const argsForRenameSubOperation = mockedRenameSubOperation.mock.calls[0];
  605. // restores the original implementation
  606. mockedRenameSubOperation.mockRestore();
  607. mockedCreateAndSendNotifications.mockRestore();
  608. // rename descendants
  609. if (page.grant !== Page.GRANT_RESTRICTED) {
  610. await crowi.pageService.renameSubOperation(...argsForRenameSubOperation);
  611. }
  612. return renamedPage;
  613. };
  614. test('Should rename/move with descendants with grant normalized pages', async() => {
  615. const _pathD = '/np_rename1_destination';
  616. const _path2 = '/np_rename2';
  617. const _path3 = '/np_rename2/np_rename3';
  618. const _propertiesD = { grant: Page.GRANT_PUBLIC };
  619. const _properties2 = { grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB };
  620. const _properties3 = { grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdC };
  621. const _pageD = await Page.findOne({ path: _pathD, ..._propertiesD });
  622. const _page2 = await Page.findOne({ path: _path2, ..._properties2 });
  623. const _page3 = await Page.findOne({ path: _path3, ..._properties3, parent: _page2._id });
  624. expect(_pageD).toBeTruthy();
  625. expect(_page2).toBeTruthy();
  626. expect(_page3).toBeTruthy();
  627. const newPathForPage2 = '/np_rename1_destination/np_rename2';
  628. const newPathForPage3 = '/np_rename1_destination/np_rename2/np_rename3';
  629. await renamePage(_page2, newPathForPage2, npDummyUser2, {});
  630. const pageD = await Page.findOne({ path: _pathD, ..._propertiesD });
  631. const page2 = await Page.findOne({ path: _path2, ..._properties2 }); // not exist
  632. const page3 = await Page.findOne({ path: _path3, ..._properties3, parent: _page2._id }); // not exist
  633. const page2Renamed = await Page.findOne({ path: newPathForPage2 }); // renamed
  634. const page3Renamed = await Page.findOne({ path: newPathForPage3 }); // renamed
  635. expect(pageD).toBeTruthy();
  636. expect(page2).toBeNull();
  637. expect(page3).toBeNull();
  638. expect(page2Renamed).toBeTruthy();
  639. expect(page3Renamed).toBeTruthy();
  640. expect(page2Renamed.parent).toStrictEqual(_pageD._id);
  641. expect(page3Renamed.parent).toStrictEqual(page2Renamed._id);
  642. expect(page2Renamed.grantedGroup).toStrictEqual(_page2.grantedGroup);
  643. expect(page3Renamed.grantedGroup).toStrictEqual(_page3.grantedGroup);
  644. expect(xssSpy).toHaveBeenCalled();
  645. });
  646. test('Should throw with NOT grant normalized pages', async() => {
  647. const _pathD = '/np_rename4_destination';
  648. const _path2 = '/np_rename5';
  649. const _path3 = '/np_rename5/np_rename6';
  650. const _propertiesD = { grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdIsolate };
  651. const _properties2 = { grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB };
  652. const _properties3 = { grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB };
  653. const _pageD = await Page.findOne({ path: _pathD, ..._propertiesD });// isolate
  654. const _page2 = await Page.findOne({ path: _path2, ..._properties2 });// groupIdB
  655. const _page3 = await Page.findOne({ path: _path3, ..._properties3, parent: _page2 });// groupIdB
  656. expect(_pageD).toBeTruthy();
  657. expect(_page2).toBeTruthy();
  658. expect(_page3).toBeTruthy();
  659. const newPathForPage2 = '/np_rename4_destination/np_rename5';
  660. const newPathForPage3 = '/np_rename4_destination/np_rename5/np_rename6';
  661. let isThrown = false;
  662. try {
  663. await renamePage(_page2, newPathForPage2, dummyUser1, {});
  664. }
  665. catch (err) {
  666. isThrown = true;
  667. }
  668. expect(isThrown).toBe(true);
  669. const page2 = await Page.findOne({ path: _path2 }); // not renamed thus exist
  670. const page3 = await Page.findOne({ path: _path3 }); // not renamed thus exist
  671. const page2Renamed = await Page.findOne({ path: newPathForPage2 }); // not exist
  672. const page3Renamed = await Page.findOne({ path: newPathForPage3 }); // not exist
  673. expect(page2).toBeTruthy();
  674. expect(page3).toBeTruthy();
  675. expect(page2Renamed).toBeNull();
  676. expect(page3Renamed).toBeNull();
  677. });
  678. test('Should rename/move multiple pages: child page with GRANT_RESTRICTED should NOT be renamed.', async() => {
  679. const _pathD = '/np_rename7_destination';
  680. const _path2 = '/np_rename8';
  681. const _path3 = '/np_rename8/np_rename9';
  682. const _pageD = await Page.findOne({ path: _pathD, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdIsolate });
  683. const _page2 = await Page.findOne({ path: _path2, grant: Page.GRANT_RESTRICTED });
  684. const _page3 = await Page.findOne({ path: _path3, grant: Page.GRANT_RESTRICTED });
  685. expect(_pageD).toBeTruthy();
  686. expect(_page2).toBeTruthy();
  687. expect(_page3).toBeTruthy();
  688. const newPathForPage2 = '/np_rename7_destination/np_rename8';
  689. const newpathForPage3 = '/np_rename7_destination/np_rename8/np_rename9';
  690. await renamePage(_page2, newPathForPage2, npDummyUser1, { isRecursively: true });
  691. const page2 = await Page.findOne({ path: _path2 }); // not exist
  692. const page3 = await Page.findOne({ path: _path3 }); // not renamed thus exist
  693. const page2Renamed = await Page.findOne({ path: newPathForPage2 }); // exist
  694. const page3Renamed = await Page.findOne({ path: newpathForPage3 }); // not exist
  695. expect(page2).toBeNull();
  696. expect(page3).toBeTruthy();
  697. expect(page2Renamed).toBeTruthy();
  698. expect(page3Renamed).toBeNull();
  699. expect(page2Renamed.parent).toBeNull();
  700. expect(xssSpy).toHaveBeenCalled();
  701. });
  702. });
  703. describe('Duplicate', () => {
  704. const duplicate = async(page, newPagePath, user, isRecursively) => {
  705. // mock return value
  706. const mockedDuplicateRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'duplicateRecursivelyMainOperation').mockReturnValue(null);
  707. const mockedCreateAndSendNotifications = jest.spyOn(crowi.pageService, 'createAndSendNotifications').mockReturnValue(null);
  708. const duplicatedPage = await crowi.pageService.duplicate(page, newPagePath, user, isRecursively);
  709. // retrieve the arguments passed when calling method duplicateRecursivelyMainOperation inside duplicate method
  710. const argsForDuplicateRecursivelyMainOperation = mockedDuplicateRecursivelyMainOperation.mock.calls[0];
  711. // restores the original implementation
  712. mockedDuplicateRecursivelyMainOperation.mockRestore();
  713. mockedCreateAndSendNotifications.mockRestore();
  714. // duplicate descendants
  715. if (page.grant !== Page.GRANT_RESTRICTED && isRecursively) {
  716. await crowi.pageService.duplicateRecursivelyMainOperation(...argsForDuplicateRecursivelyMainOperation);
  717. }
  718. return duplicatedPage;
  719. };
  720. test('Duplicate single page with GRANT_RESTRICTED', async() => {
  721. const _page = await Page.findOne({ path: '/np_duplicate1', grant: Page.GRANT_RESTRICTED }).populate({ path: 'revision', model: 'Revision' });
  722. const _revision = _page.revision;
  723. expect(_page).toBeTruthy();
  724. expect(_revision).toBeTruthy();
  725. const newPagePath = '/dup_np_duplicate1';
  726. await duplicate(_page, newPagePath, npDummyUser1, false);
  727. const duplicatedPage = await Page.findOne({ path: newPagePath });
  728. const duplicatedRevision = await Revision.findOne({ pageId: duplicatedPage._id });
  729. expect(xssSpy).toHaveBeenCalled();
  730. expect(duplicatedPage).toBeTruthy();
  731. expect(duplicatedPage._id).not.toStrictEqual(_page._id);
  732. expect(duplicatedPage.grant).toBe(_page.grant);
  733. expect(duplicatedPage.parent).toBeNull();
  734. expect(duplicatedPage.parent).toStrictEqual(_page.parent);
  735. expect(duplicatedPage.revision).toStrictEqual(duplicatedRevision._id);
  736. expect(duplicatedRevision.body).toBe(_revision.body);
  737. });
  738. test('Should duplicate multiple pages with GRANT_USER_GROUP', async() => {
  739. const _path1 = '/np_duplicate2';
  740. const _path2 = '/np_duplicate2/np_duplicate3';
  741. const _page1 = await Page.findOne({ path: _path1, parent: rootPage._id, grantedGroup: groupIdA })
  742. .populate({ path: 'revision', model: 'Revision', grantedPage: groupIdA._id });
  743. const _page2 = await Page.findOne({ path: _path2, parent: _page1._id, grantedGroup: groupIdB })
  744. .populate({ path: 'revision', model: 'Revision', grantedPage: groupIdB._id });
  745. const _revision1 = _page1.revision;
  746. const _revision2 = _page2.revision;
  747. expect(_page1).toBeTruthy();
  748. expect(_page2).toBeTruthy();
  749. expect(_revision1).toBeTruthy();
  750. expect(_revision2).toBeTruthy();
  751. const newPagePath = '/dup_np_duplicate2';
  752. await duplicate(_page1, newPagePath, npDummyUser2, true);
  753. const duplicatedPage1 = await Page.findOne({ path: newPagePath }).populate({ path: 'revision', model: 'Revision' });
  754. const duplicatedPage2 = await Page.findOne({ path: '/dup_np_duplicate2/np_duplicate3' }).populate({ path: 'revision', model: 'Revision' });
  755. const duplicatedRevision1 = duplicatedPage1.revision;
  756. const duplicatedRevision2 = duplicatedPage2.revision;
  757. expect(xssSpy).toHaveBeenCalled();
  758. expect(duplicatedPage1).toBeTruthy();
  759. expect(duplicatedPage2).toBeTruthy();
  760. expect(duplicatedRevision1).toBeTruthy();
  761. expect(duplicatedRevision2).toBeTruthy();
  762. expect(duplicatedPage1.grantedGroup).toStrictEqual(groupIdA._id);
  763. expect(duplicatedPage2.grantedGroup).toStrictEqual(groupIdB._id);
  764. expect(duplicatedPage1.parent).toStrictEqual(_page1.parent);
  765. expect(duplicatedPage2.parent).toStrictEqual(duplicatedPage1._id);
  766. expect(duplicatedRevision1.body).toBe(_revision1.body);
  767. expect(duplicatedRevision2.body).toBe(_revision2.body);
  768. expect(duplicatedRevision1.pageId).toStrictEqual(duplicatedPage1._id);
  769. expect(duplicatedRevision2.pageId).toStrictEqual(duplicatedPage2._id);
  770. });
  771. test('Should duplicate multiple pages. Page with GRANT_RESTRICTED should NOT be duplicated', async() => {
  772. const _path1 = '/np_duplicate4';
  773. const _path2 = '/np_duplicate4/np_duplicate5';
  774. const _path3 = '/np_duplicate4/np_duplicate6';
  775. const _page1 = await Page.findOne({ path: _path1, parent: rootPage._id, grant: Page.GRANT_PUBLIC })
  776. .populate({ path: 'revision', model: 'Revision' });
  777. const _page2 = await Page.findOne({ path: _path2, grant: Page.GRANT_RESTRICTED }).populate({ path: 'revision', model: 'Revision' });
  778. const _page3 = await Page.findOne({ path: _path3, grant: Page.GRANT_PUBLIC }).populate({ path: 'revision', model: 'Revision' });
  779. const baseRevision1 = _page1.revision;
  780. const baseRevision2 = _page2.revision;
  781. const baseRevision3 = _page3.revision;
  782. expect(_page1).toBeTruthy();
  783. expect(_page2).toBeTruthy();
  784. expect(_page3).toBeTruthy();
  785. expect(baseRevision1).toBeTruthy();
  786. expect(baseRevision2).toBeTruthy();
  787. const newPagePath = '/dup_np_duplicate4';
  788. await duplicate(_page1, newPagePath, npDummyUser1, true);
  789. const duplicatedPage1 = await Page.findOne({ path: newPagePath }).populate({ path: 'revision', model: 'Revision' });
  790. const duplicatedPage2 = await Page.findOne({ path: '/dup_np_duplicate4/np_duplicate5' }).populate({ path: 'revision', model: 'Revision' });
  791. const duplicatedPage3 = await Page.findOne({ path: '/dup_np_duplicate4/np_duplicate6' }).populate({ path: 'revision', model: 'Revision' });
  792. const duplicatedRevision1 = duplicatedPage1.revision;
  793. const duplicatedRevision3 = duplicatedPage3.revision;
  794. expect(xssSpy).toHaveBeenCalled();
  795. expect(duplicatedPage1).toBeTruthy();
  796. expect(duplicatedPage2).toBeNull();
  797. expect(duplicatedPage3).toBeTruthy();
  798. expect(duplicatedRevision1).toBeTruthy();
  799. expect(duplicatedRevision3).toBeTruthy();
  800. expect(duplicatedPage1.grant).toStrictEqual(Page.GRANT_PUBLIC);
  801. expect(duplicatedPage3.grant).toStrictEqual(Page.GRANT_PUBLIC);
  802. expect(duplicatedPage1.parent).toStrictEqual(_page1.parent);
  803. expect(duplicatedPage3.parent).toStrictEqual(duplicatedPage1._id);
  804. expect(duplicatedRevision1.body).toBe(baseRevision1.body);
  805. expect(duplicatedRevision3.body).toBe(baseRevision3.body);
  806. expect(duplicatedRevision1.pageId).toStrictEqual(duplicatedPage1._id);
  807. expect(duplicatedRevision3.pageId).toStrictEqual(duplicatedPage3._id);
  808. });
  809. });
  810. describe('Delete', () => {
  811. const deletePage = async(page, user, options, isRecursively) => {
  812. const mockedDeleteRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'deleteRecursivelyMainOperation').mockReturnValue(null);
  813. const mockedCreateAndSendNotifications = jest.spyOn(crowi.pageService, 'createAndSendNotifications').mockReturnValue(null);
  814. const deletedPage = await crowi.pageService.deletePage(page, user, options, isRecursively);
  815. const argsForDeleteRecursivelyMainOperation = mockedDeleteRecursivelyMainOperation.mock.calls[0];
  816. mockedDeleteRecursivelyMainOperation.mockRestore();
  817. mockedCreateAndSendNotifications.mockRestore();
  818. if (isRecursively) {
  819. await crowi.pageService.deleteRecursivelyMainOperation(...argsForDeleteRecursivelyMainOperation);
  820. }
  821. return deletedPage;
  822. };
  823. describe('Delete single page with grant RESTRICTED', () => {
  824. test('should be able to delete', async() => {
  825. const _pathT = '/npdel1_awl';
  826. const _pageT = await Page.findOne({ path: _pathT, grant: Page.GRANT_RESTRICTED });
  827. expect(_pageT).toBeTruthy();
  828. const isRecursively = false;
  829. await deletePage(_pageT, dummyUser1, {}, isRecursively);
  830. const pageT = await Page.findOne({ path: `/trash${_pathT}` });
  831. const pageN = await Page.findOne({ path: _pathT }); // should not exist
  832. expect(pageT).toBeTruthy();
  833. expect(pageN).toBeNull();
  834. expect(pageT.grant).toBe(Page.GRANT_RESTRICTED);
  835. expect(pageT.status).toBe(Page.STATUS_DELETED);
  836. });
  837. });
  838. describe('Delete single page with grant USER_GROUP', () => {
  839. test('should be able to delete', async() => {
  840. const _path = '/npdel2_ug';
  841. const _page1 = await Page.findOne({ path: _path, grantedGroup: groupIdA });
  842. expect(_page1).toBeTruthy();
  843. const isRecursively = false;
  844. await deletePage(_page1, npDummyUser1, {}, isRecursively);
  845. const pageN = await Page.findOne({ path: _path, grantedGroup: groupIdA });
  846. const page1 = await Page.findOne({ path: `/trash${_path}`, grantedGroup: groupIdA });
  847. expect(pageN).toBeNull();
  848. expect(page1).toBeTruthy();
  849. expect(page1.status).toBe(Page.STATUS_DELETED);
  850. expect(page1.descendantCount).toBe(0);
  851. expect(page1.parent).toBeNull();
  852. });
  853. });
  854. describe('Delete multiple pages with grant USER_GROUP', () => {
  855. test('should be able to delete all descendants except page with GRANT_RESTRICTED', async() => {
  856. const _pathT = '/npdel3_top';
  857. const _path1 = '/npdel3_top/npdel4_ug';
  858. const _path2 = '/npdel3_top/npdel4_ug/npdel5_ug';
  859. const _pageT = await Page.findOne({ path: _pathT, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA }); // A
  860. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB }); // B
  861. const _page2 = await Page.findOne({ path: _path2, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdC }); // C
  862. const _pageR = await Page.findOne({ path: _path1, grant: Page.GRANT_RESTRICTED }); // Restricted
  863. expect(_pageT).toBeTruthy();
  864. expect(_page1).toBeTruthy();
  865. expect(_page2).toBeTruthy();
  866. expect(_pageR).toBeTruthy();
  867. const isRecursively = true;
  868. await deletePage(_pageT, npDummyUser1, {}, isRecursively);
  869. const pageTNotExist = await Page.findOne({ path: _pathT, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA }); // A should not exist
  870. const page1NotExist = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB }); // B should not exist
  871. const page2NotExist = await Page.findOne({ path: _path2, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdC }); // C should not exist
  872. const pageT = await Page.findOne({ path: `/trash${_pathT}`, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA }); // A
  873. const page1 = await Page.findOne({ path: `/trash${_path1}`, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB }); // B
  874. const page2 = await Page.findOne({ path: `/trash${_path2}`, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdC }); // C
  875. const pageR = await Page.findOne({ path: _path1, grant: Page.GRANT_RESTRICTED }); // Restricted
  876. expect(page1NotExist).toBeNull();
  877. expect(pageTNotExist).toBeNull();
  878. expect(page2NotExist).toBeNull();
  879. expect(pageT).toBeTruthy();
  880. expect(page1).toBeTruthy();
  881. expect(page2).toBeTruthy();
  882. expect(pageR).toBeTruthy();
  883. expect(pageT.status).toBe(Page.STATUS_DELETED);
  884. expect(pageT.status).toBe(Page.STATUS_DELETED);
  885. expect(page1.status).toBe(Page.STATUS_DELETED);
  886. expect(page1.descendantCount).toBe(0);
  887. expect(page2.descendantCount).toBe(0);
  888. expect(page2.descendantCount).toBe(0);
  889. expect(pageT.parent).toBeNull();
  890. expect(page1.parent).toBeNull();
  891. expect(page2.parent).toBeNull();
  892. });
  893. });
  894. });
  895. describe('Delete completely', () => {
  896. const deleteCompletely = async(page, user, options = {}, isRecursively = false, preventEmitting = false) => {
  897. const mockedDeleteCompletelyRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'deleteCompletelyRecursivelyMainOperation').mockReturnValue(null);
  898. const mockedCreateAndSendNotifications = jest.spyOn(crowi.pageService, 'createAndSendNotifications').mockReturnValue(null);
  899. await crowi.pageService.deleteCompletely(page, user, options, isRecursively, preventEmitting);
  900. const argsForDeleteCompletelyRecursivelyMainOperation = mockedDeleteCompletelyRecursivelyMainOperation.mock.calls[0];
  901. mockedDeleteCompletelyRecursivelyMainOperation.mockRestore();
  902. mockedCreateAndSendNotifications.mockRestore();
  903. if (isRecursively) {
  904. await crowi.pageService.deleteCompletelyRecursivelyMainOperation(...argsForDeleteCompletelyRecursivelyMainOperation);
  905. }
  906. return;
  907. };
  908. describe('Delete single page with grant RESTRICTED', () => {
  909. test('should be able to delete completely', async() => {
  910. const _path = '/npdc1_awl';
  911. const _page = await Page.findOne({ path: _path, grant: Page.GRANT_RESTRICTED });
  912. expect(_page).toBeTruthy();
  913. await deleteCompletely(_page, dummyUser1, {}, false);
  914. const page = await Page.findOne({ path: _path, grant: Page.GRANT_RESTRICTED });
  915. expect(page).toBeNull();
  916. });
  917. });
  918. describe('Delete single page with grant USER_GROUP', () => {
  919. test('should be able to delete completely', async() => {
  920. const _path = '/npdc2_ug';
  921. const _page = await Page.findOne({ path: _path, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
  922. expect(_page).toBeTruthy();
  923. await deleteCompletely(_page, npDummyUser1, {}, false);
  924. const page = await Page.findOne({ path: _path, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
  925. expect(page).toBeNull();
  926. });
  927. });
  928. describe('Delete multiple pages with grant USER_GROUP', () => {
  929. test('should be able to delete all descendants completely except page with GRANT_RESTRICTED', async() => {
  930. const _path1 = '/npdc3_ug';
  931. const _path2 = '/npdc3_ug/npdc4_ug';
  932. const _path3 = '/npdc3_ug/npdc4_ug/npdc5_ug';
  933. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
  934. const _page2 = await Page.findOne({ path: _path2, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB });
  935. const _page3 = await Page.findOne({ path: _path3, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdC });
  936. const _page4 = await Page.findOne({ path: _path2, grant: Page.GRANT_RESTRICTED });
  937. expect(_page1).toBeTruthy();
  938. expect(_page2).toBeTruthy();
  939. expect(_page3).toBeTruthy();
  940. expect(_page4).toBeTruthy();
  941. await deleteCompletely(_page1, npDummyUser1, {}, true);
  942. const page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdA });
  943. const page2 = await Page.findOne({ path: _path2, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdB });
  944. const page3 = await Page.findOne({ path: _path3, grant: Page.GRANT_USER_GROUP, grantedGroup: groupIdC });
  945. const page4 = await Page.findOne({ path: _path2, grant: Page.GRANT_RESTRICTED });
  946. expect(page1).toBeNull();
  947. expect(page2).toBeNull();
  948. expect(page3).toBeNull();
  949. expect(page4).toBeTruthy();
  950. });
  951. });
  952. });
  953. describe('revert', () => {
  954. const revertDeletedPage = async(page, user, options = {}, isRecursively = false) => {
  955. // mock return value
  956. const mockedRevertRecursivelyMainOperation = jest.spyOn(crowi.pageService, 'revertRecursivelyMainOperation').mockReturnValue(null);
  957. const revertedPage = await crowi.pageService.revertDeletedPage(page, user, options, isRecursively);
  958. const argsForRecursivelyMainOperation = mockedRevertRecursivelyMainOperation.mock.calls[0];
  959. // restores the original implementation
  960. mockedRevertRecursivelyMainOperation.mockRestore();
  961. if (isRecursively) {
  962. await crowi.pageService.revertRecursivelyMainOperation(...argsForRecursivelyMainOperation);
  963. }
  964. return revertedPage;
  965. };
  966. test('should revert single deleted page with GRANT_RESTRICTED', async() => {
  967. const trashedPage = await Page.findOne({ path: '/trash/np_revert1', status: Page.STATUS_DELETED, grant: Page.GRANT_RESTRICTED });
  968. const revision = await Revision.findOne({ pageId: trashedPage._id });
  969. const tag = await Tag.findOne({ name: 'np_revertTag1' });
  970. const deletedPageTagRelation = await PageTagRelation.findOne({ relatedPage: trashedPage._id, relatedTag: tag._id, isPageTrashed: true });
  971. expect(trashedPage).toBeTruthy();
  972. expect(revision).toBeTruthy();
  973. expect(tag).toBeTruthy();
  974. expect(deletedPageTagRelation).toBeTruthy();
  975. await revertDeletedPage(trashedPage, dummyUser1, {}, false);
  976. const revertedPage = await Page.findOne({ path: '/np_revert1' });
  977. const deltedPageBeforeRevert = await Page.findOne({ path: '/trash/np_revert1' });
  978. const pageTagRelation = await PageTagRelation.findOne({ relatedPage: revertedPage._id, relatedTag: tag._id });
  979. expect(revertedPage).toBeTruthy();
  980. expect(pageTagRelation).toBeTruthy();
  981. expect(deltedPageBeforeRevert).toBeNull();
  982. // page with GRANT_RESTRICTED does not have parent
  983. expect(revertedPage.parent).toBeNull();
  984. expect(revertedPage.status).toBe(Page.STATUS_PUBLISHED);
  985. expect(revertedPage.grant).toBe(Page.GRANT_RESTRICTED);
  986. expect(pageTagRelation.isPageTrashed).toBe(false);
  987. });
  988. test('should revert single deleted page with GRANT_USER_GROUP', async() => {
  989. const beforeRevertPath = '/trash/np_revert2';
  990. const user1 = await User.findOne({ name: 'npUser1' });
  991. const trashedPage = await Page.findOne({ path: beforeRevertPath, status: Page.STATUS_DELETED, grant: Page.GRANT_USER_GROUP });
  992. const revision = await Revision.findOne({ pageId: trashedPage._id });
  993. const tag = await Tag.findOne({ name: 'np_revertTag2' });
  994. const deletedPageTagRelation = await PageTagRelation.findOne({ relatedPage: trashedPage._id, relatedTag: tag._id, isPageTrashed: true });
  995. expect(trashedPage).toBeTruthy();
  996. expect(revision).toBeTruthy();
  997. expect(tag).toBeTruthy();
  998. expect(deletedPageTagRelation).toBeTruthy();
  999. await revertDeletedPage(trashedPage, user1, {}, false);
  1000. const revertedPage = await Page.findOne({ path: '/np_revert2' });
  1001. const trashedPageBR = await Page.findOne({ path: beforeRevertPath });
  1002. const pageTagRelation = await PageTagRelation.findOne({ relatedPage: revertedPage._id, relatedTag: tag._id });
  1003. expect(revertedPage).toBeTruthy();
  1004. expect(pageTagRelation).toBeTruthy();
  1005. expect(trashedPageBR).toBeNull();
  1006. expect(revertedPage.parent).toStrictEqual(rootPage._id);
  1007. expect(revertedPage.status).toBe(Page.STATUS_PUBLISHED);
  1008. expect(revertedPage.grant).toBe(Page.GRANT_USER_GROUP);
  1009. expect(revertedPage.grantedGroup).toStrictEqual(groupIdA);
  1010. expect(pageTagRelation.isPageTrashed).toBe(false);
  1011. });
  1012. test(`revert multiple pages: only target page should be reverted.
  1013. Non-existant middle page and leaf page with GRANT_RESTRICTED shoud not be reverted`, async() => {
  1014. const beforeRevertPath1 = '/trash/np_revert3';
  1015. const beforeRevertPath2 = '/trash/np_revert3/middle/np_revert4';
  1016. const trashedPage1 = await Page.findOne({ path: beforeRevertPath1, status: Page.STATUS_DELETED, grant: Page.GRANT_PUBLIC });
  1017. const trashedPage2 = await Page.findOne({ path: beforeRevertPath2, status: Page.STATUS_DELETED, grant: Page.GRANT_RESTRICTED });
  1018. const revision1 = await Revision.findOne({ pageId: trashedPage1._id });
  1019. const revision2 = await Revision.findOne({ pageId: trashedPage2._id });
  1020. expect(trashedPage1).toBeTruthy();
  1021. expect(trashedPage2).toBeTruthy();
  1022. expect(revision1).toBeTruthy();
  1023. expect(revision2).toBeTruthy();
  1024. await revertDeletedPage(trashedPage1, npDummyUser2, {}, true);
  1025. const revertedPage = await Page.findOne({ path: '/np_revert3' });
  1026. const middlePage = await Page.findOne({ path: '/np_revert3/middle' });
  1027. const notRestrictedPage = await Page.findOne({ path: '/np_revert3/middle/np_revert4' });
  1028. // AR => After Revert
  1029. const trashedPage1AR = await Page.findOne({ path: beforeRevertPath1 });
  1030. const trashedPage2AR = await Page.findOne({ path: beforeRevertPath2 });
  1031. const revision1AR = await Revision.findOne({ pageId: revertedPage._id });
  1032. const revision2AR = await Revision.findOne({ pageId: trashedPage2AR._id });
  1033. expect(revertedPage).toBeTruthy();
  1034. expect(trashedPage2AR).toBeTruthy();
  1035. expect(revision1AR).toBeTruthy();
  1036. expect(revision2AR).toBeTruthy();
  1037. expect(trashedPage1AR).toBeNull();
  1038. expect(notRestrictedPage).toBeNull();
  1039. expect(middlePage).toBeNull();
  1040. expect(revertedPage.parent).toStrictEqual(rootPage._id);
  1041. expect(revertedPage.status).toBe(Page.STATUS_PUBLISHED);
  1042. expect(revertedPage.grant).toBe(Page.GRANT_PUBLIC);
  1043. });
  1044. test('revert multiple pages: target page, initially non-existant page and leaf page with GRANT_USER_GROUP shoud be reverted', async() => {
  1045. const user = await User.findOne({ _id: npDummyUser3 });
  1046. const beforeRevertPath1 = '/trash/np_revert5';
  1047. const beforeRevertPath2 = '/trash/np_revert5/middle/np_revert6';
  1048. const beforeRevertPath3 = '/trash/np_revert5/middle';
  1049. const trashedPage1 = await Page.findOne({ path: beforeRevertPath1, status: Page.STATUS_DELETED, grantedGroup: groupIdA });
  1050. const trashedPage2 = await Page.findOne({ path: beforeRevertPath2, status: Page.STATUS_DELETED, grantedGroup: groupIdB });
  1051. const nonExistantPage3 = await Page.findOne({ path: beforeRevertPath3 }); // not exist
  1052. const revision1 = await Revision.findOne({ pageId: trashedPage1._id });
  1053. const revision2 = await Revision.findOne({ pageId: trashedPage2._id });
  1054. expect(trashedPage1).toBeTruthy();
  1055. expect(trashedPage2).toBeTruthy();
  1056. expect(revision1).toBeTruthy();
  1057. expect(revision2).toBeTruthy();
  1058. expect(user).toBeTruthy();
  1059. expect(nonExistantPage3).toBeNull();
  1060. await revertDeletedPage(trashedPage1, user, {}, true);
  1061. const revertedPage1 = await Page.findOne({ path: '/np_revert5' });
  1062. const newlyCreatedPage = await Page.findOne({ path: '/np_revert5/middle' });
  1063. const revertedPage2 = await Page.findOne({ path: '/np_revert5/middle/np_revert6' });
  1064. // // AR => After Revert
  1065. const trashedPage1AR = await Page.findOne({ path: beforeRevertPath1 });
  1066. const trashedPage2AR = await Page.findOne({ path: beforeRevertPath2 });
  1067. expect(revertedPage1).toBeTruthy();
  1068. expect(newlyCreatedPage).toBeTruthy();
  1069. expect(revertedPage2).toBeTruthy();
  1070. expect(trashedPage1AR).toBeNull();
  1071. expect(trashedPage2AR).toBeNull();
  1072. expect(newlyCreatedPage.isEmpty).toBe(true);
  1073. expect(revertedPage1.parent).toStrictEqual(rootPage._id);
  1074. expect(revertedPage2.parent).toStrictEqual(newlyCreatedPage._id);
  1075. expect(newlyCreatedPage.parent).toStrictEqual(revertedPage1._id);
  1076. expect(revertedPage1.status).toBe(Page.STATUS_PUBLISHED);
  1077. expect(revertedPage2.status).toBe(Page.STATUS_PUBLISHED);
  1078. expect(newlyCreatedPage.status).toBe(Page.STATUS_PUBLISHED);
  1079. expect(revertedPage1.grantedGroup).toStrictEqual(groupIdA);
  1080. expect(revertedPage2.grantedGroup).toStrictEqual(groupIdB);
  1081. expect(newlyCreatedPage.grant).toBe(Page.GRANT_PUBLIC);
  1082. });
  1083. });
  1084. });