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

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