v5.page.test.js 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397
  1. import mongoose from 'mongoose';
  2. import { PageGrant } from '~/interfaces/page';
  3. import { getInstance } from '../setup-crowi';
  4. describe('Page', () => {
  5. let crowi;
  6. let pageGrantService;
  7. let Page;
  8. let Revision;
  9. let User;
  10. let PageTagRelation;
  11. let Bookmark;
  12. let Comment;
  13. let ShareLink;
  14. let PageRedirect;
  15. let UserGroup;
  16. let UserGroupRelation;
  17. let xssSpy;
  18. let rootPage;
  19. let dummyUser1;
  20. let pModelUser1;
  21. let pModelUser2;
  22. let pModelUser3;
  23. let userGroupIdPModelIsolate;
  24. let userGroupIdPModelA;
  25. let userGroupIdPModelB;
  26. let userGroupIdPModelC;
  27. // To test updatePage overwriting descendants (prefix `upod`)
  28. let upodUserA;
  29. let upodUserB;
  30. let upodUserC;
  31. let upodGroupAB;
  32. let upodGroupA;
  33. let upodGroupAIsolated;
  34. let upodGroupB;
  35. let upodGroupC;
  36. const upodUserGroupIdA = new mongoose.Types.ObjectId();
  37. const upodUserGroupIdAIsolated = new mongoose.Types.ObjectId();
  38. const upodUserGroupIdB = new mongoose.Types.ObjectId();
  39. const upodUserGroupIdC = new mongoose.Types.ObjectId();
  40. const upodUserGroupIdAB = new mongoose.Types.ObjectId();
  41. const upodPageIdgAB1 = new mongoose.Types.ObjectId();
  42. const upodPageIdPublic2 = new mongoose.Types.ObjectId();
  43. const upodPageIdPublic3 = new mongoose.Types.ObjectId();
  44. const upodPageIdPublic4 = new mongoose.Types.ObjectId();
  45. const upodPageIdPublic5 = new mongoose.Types.ObjectId();
  46. const upodPageIdPublic6 = new mongoose.Types.ObjectId();
  47. const createDocumentsToTestUpdatePageOverwritingDescendants = async() => {
  48. // Users
  49. await User.insertMany([
  50. { name: 'upodUserA', username: 'upodUserA', email: 'upoduserA@example.com' },
  51. { name: 'upodUserB', username: 'upodUserB', email: 'upoduserB@example.com' },
  52. { name: 'upodUserC', username: 'upodUserC', email: 'upodUserC@example.com' },
  53. ]);
  54. upodUserA = await User.findOne({ username: 'upodUserA' });
  55. upodUserB = await User.findOne({ username: 'upodUserB' });
  56. upodUserC = await User.findOne({ username: 'upodUserC' });
  57. await UserGroup.insertMany([
  58. {
  59. _id: upodUserGroupIdAB,
  60. name: 'upodGroupAB',
  61. parent: null,
  62. },
  63. {
  64. _id: upodUserGroupIdA,
  65. name: 'upodGroupA',
  66. parent: upodUserGroupIdAB,
  67. },
  68. {
  69. _id: upodUserGroupIdAIsolated,
  70. name: 'upodGroupAIsolated',
  71. parent: null,
  72. },
  73. {
  74. _id: upodUserGroupIdB,
  75. name: 'upodGroupB',
  76. parent: upodUserGroupIdAB,
  77. },
  78. {
  79. _id: upodUserGroupIdC,
  80. name: 'upodGroupC',
  81. parent: null,
  82. },
  83. ]);
  84. upodGroupAB = await UserGroup.findOne({ name: 'upodGroupAB' });
  85. upodGroupA = await UserGroup.findOne({ name: 'upodGroupA' });
  86. upodGroupAIsolated = await UserGroup.findOne({ name: 'upodGroupAIsolated' });
  87. upodGroupB = await UserGroup.findOne({ name: 'upodGroupB' });
  88. upodGroupC = await UserGroup.findOne({ name: 'upodGroupC' });
  89. // UserGroupRelations
  90. await UserGroupRelation.insertMany([
  91. {
  92. relatedGroup: upodUserGroupIdAB,
  93. relatedUser: upodUserA._id,
  94. },
  95. {
  96. relatedGroup: upodUserGroupIdAB,
  97. relatedUser: upodUserB._id,
  98. },
  99. {
  100. relatedGroup: upodUserGroupIdA,
  101. relatedUser: upodUserA._id,
  102. },
  103. {
  104. relatedGroup: upodUserGroupIdAIsolated,
  105. relatedUser: upodUserA._id,
  106. },
  107. {
  108. relatedGroup: upodUserGroupIdB,
  109. relatedUser: upodUserB._id,
  110. },
  111. {
  112. relatedGroup: upodUserGroupIdC,
  113. relatedUser: upodUserC._id,
  114. },
  115. ]);
  116. // Pages
  117. await Page.insertMany([
  118. // case 1
  119. {
  120. _id: upodPageIdgAB1,
  121. path: '/gAB_upod_1', // to GRANT_PUBLIC
  122. grant: PageGrant.GRANT_USER_GROUP,
  123. creator: upodUserA,
  124. lastUpdateUser: upodUserA,
  125. grantedUsers: null,
  126. grantedGroup: upodUserGroupIdAB,
  127. parent: rootPage._id,
  128. },
  129. {
  130. path: '/gAB_upod_1/gB_upod_1',
  131. grant: PageGrant.GRANT_USER_GROUP,
  132. creator: upodUserB,
  133. lastUpdateUser: upodUserB,
  134. grantedUsers: null,
  135. grantedGroup: upodUserGroupIdB,
  136. parent: upodPageIdgAB1,
  137. },
  138. {
  139. path: '/gAB_upod_1/onlyB_upod_1',
  140. grant: PageGrant.GRANT_OWNER,
  141. creator: upodUserB,
  142. lastUpdateUser: upodUserB,
  143. grantedUsers: [upodUserB._id],
  144. grantedGroup: null,
  145. parent: upodPageIdgAB1,
  146. },
  147. // case 2
  148. {
  149. _id: upodPageIdPublic2,
  150. path: '/public_upod_2', // to Anything
  151. grant: PageGrant.GRANT_PUBLIC,
  152. creator: upodUserA,
  153. lastUpdateUser: upodUserA,
  154. grantedUsers: null,
  155. grantedGroup: null,
  156. parent: rootPage._id,
  157. },
  158. {
  159. path: '/public_upod_2/gA_upod_2',
  160. grant: PageGrant.GRANT_USER_GROUP,
  161. creator: upodUserA,
  162. lastUpdateUser: upodUserA,
  163. grantedUsers: null,
  164. grantedGroup: upodUserGroupIdA,
  165. parent: upodPageIdPublic2,
  166. },
  167. {
  168. path: '/public_upod_2/gAIsolated_upod_2',
  169. grant: PageGrant.GRANT_USER_GROUP,
  170. creator: upodUserA,
  171. lastUpdateUser: upodUserA,
  172. grantedUsers: null,
  173. grantedGroup: upodUserGroupIdAIsolated,
  174. parent: upodPageIdPublic2,
  175. },
  176. {
  177. path: '/public_upod_2/onlyA_upod_2',
  178. grant: PageGrant.GRANT_OWNER,
  179. creator: upodUserA,
  180. lastUpdateUser: upodUserA,
  181. grantedUsers: [upodUserA._id],
  182. grantedGroup: null,
  183. parent: upodPageIdPublic2,
  184. },
  185. // case 3
  186. {
  187. _id: upodPageIdPublic3,
  188. path: '/public_upod_3', // to GRANT_USER_GROUP with upodGroupAB
  189. grant: PageGrant.GRANT_PUBLIC,
  190. creator: upodUserA,
  191. lastUpdateUser: upodUserA,
  192. grantedUsers: null,
  193. grantedGroup: null,
  194. parent: rootPage._id,
  195. },
  196. {
  197. path: '/public_upod_3/gAB_upod_3',
  198. grant: PageGrant.GRANT_USER_GROUP,
  199. creator: upodUserA,
  200. lastUpdateUser: upodUserA,
  201. grantedUsers: null,
  202. grantedGroup: upodUserGroupIdAB,
  203. parent: upodPageIdPublic3,
  204. },
  205. {
  206. path: '/public_upod_3/gB_upod_3',
  207. grant: PageGrant.GRANT_USER_GROUP,
  208. creator: upodUserB,
  209. lastUpdateUser: upodUserB,
  210. grantedUsers: null,
  211. grantedGroup: upodUserGroupIdB,
  212. parent: upodPageIdPublic3,
  213. },
  214. {
  215. path: '/public_upod_3/onlyB_upod_3',
  216. grant: PageGrant.GRANT_OWNER,
  217. creator: upodUserB,
  218. lastUpdateUser: upodUserB,
  219. grantedUsers: [upodUserB._id],
  220. grantedGroup: null,
  221. parent: upodPageIdPublic3,
  222. },
  223. // case 4
  224. {
  225. _id: upodPageIdPublic4,
  226. path: '/public_upod_4', // to GRANT_USER_GROUP with upodGroupAB
  227. grant: PageGrant.GRANT_PUBLIC,
  228. creator: upodUserA,
  229. lastUpdateUser: upodUserA,
  230. grantedUsers: null,
  231. grantedGroup: null,
  232. parent: rootPage._id,
  233. },
  234. {
  235. path: '/public_upod_4/gA_upod_4',
  236. grant: PageGrant.GRANT_USER_GROUP,
  237. creator: upodUserA,
  238. lastUpdateUser: upodUserA,
  239. grantedUsers: null,
  240. grantedGroup: upodUserGroupIdA,
  241. parent: upodPageIdPublic4,
  242. },
  243. {
  244. path: '/public_upod_4/gC_upod_4',
  245. grant: PageGrant.GRANT_USER_GROUP,
  246. creator: upodUserC,
  247. lastUpdateUser: upodUserC,
  248. grantedUsers: null,
  249. grantedGroup: upodUserGroupIdC,
  250. parent: upodPageIdPublic4,
  251. },
  252. // case 5
  253. {
  254. _id: upodPageIdPublic5,
  255. path: '/public_upod_5', // to GRANT_USER_GROUP with upodGroupAB
  256. grant: PageGrant.GRANT_PUBLIC,
  257. creator: upodUserA,
  258. lastUpdateUser: upodUserA,
  259. grantedUsers: null,
  260. grantedGroup: null,
  261. parent: rootPage._id,
  262. },
  263. {
  264. path: '/public_upod_5/gA_upod_5',
  265. grant: PageGrant.GRANT_USER_GROUP,
  266. creator: upodUserA,
  267. lastUpdateUser: upodUserA,
  268. grantedUsers: null,
  269. grantedGroup: upodUserGroupIdA,
  270. parent: upodPageIdPublic5,
  271. },
  272. {
  273. path: '/public_upod_5/onlyC_upod_5',
  274. grant: PageGrant.GRANT_OWNER,
  275. creator: upodUserC,
  276. lastUpdateUser: upodUserC,
  277. grantedUsers: [upodUserC._id],
  278. grantedGroup: null,
  279. parent: upodPageIdPublic5,
  280. },
  281. // case 6
  282. {
  283. _id: upodPageIdPublic6,
  284. path: '/public_upod_6', // to GRANT_USER_GROUP with upodGroupAB
  285. grant: PageGrant.GRANT_PUBLIC,
  286. creator: upodUserA,
  287. lastUpdateUser: upodUserA,
  288. grantedUsers: null,
  289. grantedGroup: null,
  290. parent: rootPage._id,
  291. },
  292. {
  293. path: '/public_upod_6/onlyC_upod_6',
  294. grant: PageGrant.GRANT_OWNER,
  295. creator: upodUserC,
  296. lastUpdateUser: upodUserC,
  297. grantedUsers: [upodUserC._id],
  298. grantedGroup: null,
  299. parent: upodPageIdPublic6,
  300. },
  301. ]);
  302. };
  303. beforeAll(async() => {
  304. crowi = await getInstance();
  305. pageGrantService = crowi.pageGrantService;
  306. await crowi.configManager.updateConfigsInTheSameNamespace('crowi', { 'app:isV5Compatible': true });
  307. jest.restoreAllMocks();
  308. User = mongoose.model('User');
  309. Page = mongoose.model('Page');
  310. Revision = mongoose.model('Revision');
  311. PageTagRelation = mongoose.model('PageTagRelation');
  312. Bookmark = mongoose.model('Bookmark');
  313. Comment = mongoose.model('Comment');
  314. ShareLink = mongoose.model('ShareLink');
  315. PageRedirect = mongoose.model('PageRedirect');
  316. UserGroup = mongoose.model('UserGroup');
  317. UserGroupRelation = mongoose.model('UserGroupRelation');
  318. dummyUser1 = await User.findOne({ username: 'v5DummyUser1' });
  319. rootPage = await Page.findOne({ path: '/' });
  320. const pModelUserId1 = new mongoose.Types.ObjectId();
  321. const pModelUserId2 = new mongoose.Types.ObjectId();
  322. const pModelUserId3 = new mongoose.Types.ObjectId();
  323. await User.insertMany([
  324. {
  325. _id: pModelUserId1,
  326. name: 'pmodelUser1',
  327. username: 'pmodelUser1',
  328. email: 'pmodelUser1@example.com',
  329. },
  330. {
  331. _id: pModelUserId2,
  332. name: 'pmodelUser2',
  333. username: 'pmodelUser2',
  334. email: 'pmodelUser2@example.com',
  335. },
  336. {
  337. _id: pModelUserId3,
  338. name: 'pModelUser3',
  339. username: 'pModelUser3',
  340. email: 'pModelUser3@example.com',
  341. },
  342. ]);
  343. pModelUser1 = await User.findOne({ _id: pModelUserId1 });
  344. pModelUser2 = await User.findOne({ _id: pModelUserId2 });
  345. pModelUser3 = await User.findOne({ _id: pModelUserId3 });
  346. userGroupIdPModelIsolate = new mongoose.Types.ObjectId();
  347. userGroupIdPModelA = new mongoose.Types.ObjectId();
  348. userGroupIdPModelB = new mongoose.Types.ObjectId();
  349. userGroupIdPModelC = new mongoose.Types.ObjectId();
  350. await UserGroup.insertMany([
  351. {
  352. _id: userGroupIdPModelIsolate,
  353. name: 'pModel_groupIsolate',
  354. },
  355. {
  356. _id: userGroupIdPModelA,
  357. name: 'pModel_groupA',
  358. },
  359. {
  360. _id: userGroupIdPModelB,
  361. name: 'pModel_groupB',
  362. parent: userGroupIdPModelA,
  363. },
  364. {
  365. _id: userGroupIdPModelC,
  366. name: 'pModel_groupC',
  367. parent: userGroupIdPModelB,
  368. },
  369. ]);
  370. await UserGroupRelation.insertMany([
  371. {
  372. relatedGroup: userGroupIdPModelIsolate,
  373. relatedUser: pModelUserId1,
  374. createdAt: new Date(),
  375. },
  376. {
  377. relatedGroup: userGroupIdPModelIsolate,
  378. relatedUser: pModelUserId2,
  379. createdAt: new Date(),
  380. },
  381. {
  382. relatedGroup: userGroupIdPModelA,
  383. relatedUser: pModelUserId1,
  384. createdAt: new Date(),
  385. },
  386. {
  387. relatedGroup: userGroupIdPModelA,
  388. relatedUser: pModelUserId2,
  389. createdAt: new Date(),
  390. },
  391. {
  392. relatedGroup: userGroupIdPModelA,
  393. relatedUser: pModelUserId3,
  394. createdAt: new Date(),
  395. },
  396. {
  397. relatedGroup: userGroupIdPModelB,
  398. relatedUser: pModelUserId2,
  399. createdAt: new Date(),
  400. },
  401. {
  402. relatedGroup: userGroupIdPModelB,
  403. relatedUser: pModelUserId3,
  404. createdAt: new Date(),
  405. },
  406. {
  407. relatedGroup: userGroupIdPModelC,
  408. relatedUser: pModelUserId3,
  409. createdAt: new Date(),
  410. },
  411. ]);
  412. /**
  413. * update
  414. * mup_ => model update
  415. * emp => empty => page with isEmpty: true
  416. * pub => public => GRANT_PUBLIC
  417. * awl => Anyone with the link => GRANT_RESTRICTED
  418. */
  419. const pageIdUpd1 = new mongoose.Types.ObjectId();
  420. const pageIdUpd2 = new mongoose.Types.ObjectId();
  421. const pageIdUpd3 = new mongoose.Types.ObjectId();
  422. const pageIdUpd4 = new mongoose.Types.ObjectId();
  423. const pageIdUpd5 = new mongoose.Types.ObjectId();
  424. const pageIdUpd6 = new mongoose.Types.ObjectId();
  425. const pageIdUpd7 = new mongoose.Types.ObjectId();
  426. const pageIdUpd8 = new mongoose.Types.ObjectId();
  427. const pageIdUpd9 = new mongoose.Types.ObjectId();
  428. const pageIdUpd10 = new mongoose.Types.ObjectId();
  429. const pageIdUpd11 = new mongoose.Types.ObjectId();
  430. const pageIdUpd12 = new mongoose.Types.ObjectId();
  431. const pageIdUpd13 = new mongoose.Types.ObjectId();
  432. const pageIdUpd14 = new mongoose.Types.ObjectId();
  433. const pageIdUpd15 = new mongoose.Types.ObjectId();
  434. const pageIdUpd16 = new mongoose.Types.ObjectId();
  435. const pageIdUpd17 = new mongoose.Types.ObjectId();
  436. const pageIdUpd18 = new mongoose.Types.ObjectId();
  437. const pageIdUpd19 = new mongoose.Types.ObjectId();
  438. await Page.insertMany([
  439. {
  440. _id: pageIdUpd1,
  441. path: '/mup13_top/mup1_emp',
  442. grant: Page.GRANT_PUBLIC,
  443. parent: pageIdUpd8._id,
  444. isEmpty: true,
  445. },
  446. {
  447. _id: pageIdUpd2,
  448. path: '/mup13_top/mup1_emp/mup2_pub',
  449. grant: Page.GRANT_PUBLIC,
  450. parent: pageIdUpd1._id,
  451. creator: dummyUser1,
  452. lastUpdateUser: dummyUser1._id,
  453. isEmpty: false,
  454. },
  455. {
  456. _id: pageIdUpd3,
  457. path: '/mup14_top/mup6_pub',
  458. grant: Page.GRANT_PUBLIC,
  459. creator: dummyUser1,
  460. lastUpdateUser: dummyUser1._id,
  461. parent: pageIdUpd9,
  462. isEmpty: false,
  463. descendantCount: 1,
  464. },
  465. {
  466. path: '/mup14_top/mup6_pub/mup7_pub',
  467. grant: Page.GRANT_PUBLIC,
  468. creator: dummyUser1,
  469. lastUpdateUser: dummyUser1._id,
  470. parent: pageIdUpd3,
  471. isEmpty: false,
  472. descendantCount: 0,
  473. },
  474. {
  475. _id: pageIdUpd4,
  476. path: '/mup15_top/mup8_pub',
  477. grant: Page.GRANT_PUBLIC,
  478. creator: dummyUser1,
  479. lastUpdateUser: dummyUser1._id,
  480. parent: pageIdUpd10._id,
  481. isEmpty: false,
  482. },
  483. {
  484. _id: pageIdUpd5,
  485. path: '/mup16_top/mup9_pub/mup10_pub/mup11_awl',
  486. grant: Page.GRANT_RESTRICTED,
  487. creator: dummyUser1,
  488. lastUpdateUser: dummyUser1._id,
  489. isEmpty: false,
  490. },
  491. {
  492. _id: pageIdUpd6,
  493. path: '/mup17_top/mup12_emp',
  494. isEmpty: true,
  495. parent: pageIdUpd12._id,
  496. descendantCount: 1,
  497. },
  498. {
  499. _id: pageIdUpd7,
  500. path: '/mup17_top/mup12_emp',
  501. grant: Page.GRANT_RESTRICTED,
  502. creator: dummyUser1,
  503. lastUpdateUser: dummyUser1._id,
  504. isEmpty: false,
  505. },
  506. {
  507. path: '/mup17_top/mup12_emp/mup18_pub',
  508. isEmpty: false,
  509. creator: dummyUser1,
  510. lastUpdateUser: dummyUser1._id,
  511. parent: pageIdUpd6._id,
  512. },
  513. {
  514. _id: pageIdUpd8,
  515. path: '/mup13_top',
  516. grant: Page.GRANT_PUBLIC,
  517. creator: dummyUser1,
  518. lastUpdateUser: dummyUser1._id,
  519. isEmpty: false,
  520. parent: rootPage._id,
  521. descendantCount: 2,
  522. },
  523. {
  524. _id: pageIdUpd9,
  525. path: '/mup14_top',
  526. grant: Page.GRANT_PUBLIC,
  527. creator: dummyUser1,
  528. lastUpdateUser: dummyUser1._id,
  529. isEmpty: false,
  530. parent: rootPage._id,
  531. descendantCount: 2,
  532. },
  533. {
  534. _id: pageIdUpd10,
  535. path: '/mup15_top',
  536. grant: Page.GRANT_PUBLIC,
  537. creator: dummyUser1,
  538. lastUpdateUser: dummyUser1._id,
  539. isEmpty: false,
  540. parent: rootPage._id,
  541. descendantCount: 1,
  542. },
  543. {
  544. _id: pageIdUpd11,
  545. path: '/mup16_top',
  546. grant: Page.GRANT_PUBLIC,
  547. creator: dummyUser1,
  548. lastUpdateUser: dummyUser1._id,
  549. isEmpty: false,
  550. parent: rootPage._id,
  551. descendantCount: 0,
  552. },
  553. {
  554. _id: pageIdUpd12,
  555. path: '/mup17_top',
  556. grant: Page.GRANT_PUBLIC,
  557. creator: dummyUser1,
  558. lastUpdateUser: dummyUser1._id,
  559. isEmpty: false,
  560. parent: rootPage._id,
  561. descendantCount: 1,
  562. },
  563. {
  564. path: '/mup19',
  565. grant: Page.GRANT_PUBLIC,
  566. creator: dummyUser1,
  567. lastUpdateUser: dummyUser1._id,
  568. isEmpty: false,
  569. parent: rootPage._id,
  570. descendantCount: 0,
  571. },
  572. {
  573. path: '/mup20',
  574. grant: Page.GRANT_USER_GROUP,
  575. grantedGroup: userGroupIdPModelA,
  576. creator: pModelUserId1,
  577. lastUpdateUser: pModelUserId1,
  578. isEmpty: false,
  579. parent: rootPage._id,
  580. descendantCount: 0,
  581. },
  582. {
  583. path: '/mup21',
  584. grant: Page.GRANT_RESTRICTED,
  585. creator: dummyUser1,
  586. lastUpdateUser: dummyUser1._id,
  587. isEmpty: false,
  588. descendantCount: 0,
  589. },
  590. {
  591. _id: pageIdUpd13,
  592. path: '/mup22',
  593. grant: Page.GRANT_PUBLIC,
  594. creator: pModelUser1,
  595. lastUpdateUser: pModelUser1._id,
  596. isEmpty: false,
  597. parent: rootPage._id,
  598. descendantCount: 1,
  599. },
  600. {
  601. path: '/mup22/mup23',
  602. grant: Page.GRANT_USER_GROUP,
  603. grantedGroup: userGroupIdPModelA,
  604. creator: pModelUserId1,
  605. lastUpdateUser: pModelUserId1,
  606. isEmpty: false,
  607. parent: pageIdUpd13,
  608. descendantCount: 0,
  609. },
  610. {
  611. _id: pageIdUpd14,
  612. path: '/mup24_pub',
  613. grant: Page.GRANT_PUBLIC,
  614. creator: pModelUserId1,
  615. lastUpdateUser: pModelUserId1,
  616. isEmpty: false,
  617. parent: rootPage,
  618. descendantCount: 1,
  619. },
  620. {
  621. path: '/mup24_pub/mup25_pub',
  622. grant: Page.GRANT_PUBLIC,
  623. creator: pModelUserId1,
  624. lastUpdateUser: pModelUserId1,
  625. isEmpty: false,
  626. parent: pageIdUpd14,
  627. descendantCount: 0,
  628. },
  629. {
  630. path: '/mup26_awl',
  631. grant: Page.GRANT_RESTRICTED,
  632. creator: pModelUserId1,
  633. lastUpdateUser: pModelUserId1,
  634. isEmpty: false,
  635. descendantCount: 0,
  636. },
  637. {
  638. _id: pageIdUpd15,
  639. path: '/mup27_pub',
  640. grant: Page.GRANT_PUBLIC,
  641. creator: pModelUserId1,
  642. lastUpdateUser: pModelUserId1,
  643. isEmpty: false,
  644. parent: rootPage,
  645. descendantCount: 1,
  646. },
  647. {
  648. path: '/mup27_pub/mup28_owner',
  649. grant: Page.GRANT_OWNER,
  650. creator: pModelUserId1,
  651. lastUpdateUser: pModelUserId1,
  652. isEmpty: false,
  653. parent: pageIdUpd15,
  654. grantedUsers: [pModelUserId1],
  655. descendantCount: 0,
  656. },
  657. {
  658. _id: pageIdUpd16,
  659. path: '/mup29_A',
  660. grant: Page.GRANT_USER_GROUP,
  661. grantedGroup: userGroupIdPModelA,
  662. creator: pModelUserId1,
  663. lastUpdateUser: pModelUserId1,
  664. isEmpty: false,
  665. parent: rootPage,
  666. descendantCount: 1,
  667. },
  668. {
  669. path: '/mup29_A/mup30_owner',
  670. grant: Page.GRANT_OWNER,
  671. grantedUsers: [pModelUserId1],
  672. creator: pModelUserId1,
  673. lastUpdateUser: pModelUserId1,
  674. isEmpty: false,
  675. parent: pageIdUpd16,
  676. descendantCount: 0,
  677. },
  678. {
  679. _id: pageIdUpd17,
  680. path: '/mup31_A',
  681. grant: Page.GRANT_USER_GROUP,
  682. grantedGroup: userGroupIdPModelA,
  683. creator: pModelUserId1,
  684. lastUpdateUser: pModelUserId1,
  685. isEmpty: false,
  686. parent: rootPage,
  687. descendantCount: 1,
  688. },
  689. {
  690. path: '/mup31_A/mup32_owner',
  691. grant: Page.GRANT_OWNER,
  692. grantedUsers: [pModelUserId1],
  693. creator: pModelUserId1,
  694. lastUpdateUser: pModelUserId1,
  695. isEmpty: false,
  696. parent: pageIdUpd17,
  697. descendantCount: 0,
  698. },
  699. {
  700. _id: pageIdUpd18,
  701. path: '/mup33_C',
  702. grant: Page.GRANT_USER_GROUP,
  703. grantedGroup: userGroupIdPModelC,
  704. creator: pModelUserId3,
  705. lastUpdateUser: pModelUserId3,
  706. isEmpty: false,
  707. parent: rootPage,
  708. descendantCount: 1,
  709. },
  710. {
  711. path: '/mup33_C/mup34_owner',
  712. grant: Page.GRANT_OWNER,
  713. grantedUsers: [pModelUserId3],
  714. creator: pModelUserId3,
  715. lastUpdateUser: pModelUserId3,
  716. isEmpty: false,
  717. parent: pageIdUpd18,
  718. descendantCount: 0,
  719. },
  720. {
  721. _id: pageIdUpd19,
  722. path: '/mup35_owner',
  723. grant: Page.GRANT_OWNER,
  724. grantedUsers: [pModelUserId1],
  725. creator: pModelUserId1,
  726. lastUpdateUser: pModelUserId1,
  727. isEmpty: false,
  728. parent: rootPage,
  729. descendantCount: 1,
  730. },
  731. {
  732. path: '/mup35_owner/mup36_owner',
  733. grant: Page.GRANT_OWNER,
  734. grantedUsers: [pModelUserId1],
  735. creator: pModelUserId1,
  736. lastUpdateUser: pModelUserId1,
  737. isEmpty: false,
  738. parent: pageIdUpd19,
  739. descendantCount: 0,
  740. },
  741. {
  742. path: '/mup40', // used this number to resolve conflict
  743. grant: Page.GRANT_OWNER,
  744. grantedUsers: [dummyUser1._id],
  745. creator: dummyUser1,
  746. lastUpdateUser: dummyUser1._id,
  747. isEmpty: false,
  748. parent: rootPage._id,
  749. descendantCount: 0,
  750. },
  751. ]);
  752. await createDocumentsToTestUpdatePageOverwritingDescendants();
  753. });
  754. describe('update', () => {
  755. // TODO*
  756. const updatePage = async(page, newRevisionBody, oldRevisionBody, user, options = {}) => {
  757. const mockedEmitPageEventUpdate = jest.spyOn(Page, 'emitPageEventUpdate').mockReturnValue(null);
  758. const mockedApplyScopesToDescendantsAsyncronously = jest.spyOn(Page, 'applyScopesToDescendantsAsyncronously').mockReturnValue(null);
  759. const savedPage = await Page.updatePage(page, newRevisionBody, oldRevisionBody, user, options);
  760. const argsForApplyScopesToDescendantsAsyncronously = mockedApplyScopesToDescendantsAsyncronously.mock.calls[0];
  761. mockedEmitPageEventUpdate.mockRestore();
  762. mockedApplyScopesToDescendantsAsyncronously.mockRestore();
  763. if (options.overwriteScopesOfDescendants) {
  764. await Page.applyScopesToDescendantsAsyncronously(...argsForApplyScopesToDescendantsAsyncronously);
  765. }
  766. return savedPage;
  767. };
  768. describe('Changing grant from PUBLIC to RESTRICTED of', () => {
  769. test('an only-child page will delete its empty parent page', async() => {
  770. const pathT = '/mup13_top';
  771. const path1 = '/mup13_top/mup1_emp';
  772. const path2 = '/mup13_top/mup1_emp/mup2_pub';
  773. const pageT = await Page.findOne({ path: pathT, descendantCount: 2 });
  774. const page1 = await Page.findOne({ path: path1, isEmpty: true });
  775. const page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC });
  776. expect(pageT).toBeTruthy();
  777. expect(page1).toBeTruthy();
  778. expect(page2).toBeTruthy();
  779. const options = { grant: Page.GRANT_RESTRICTED, grantUserGroupId: null };
  780. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, options);
  781. const _pageT = await Page.findOne({ path: pathT });
  782. const _page1 = await Page.findOne({ path: path1 });
  783. const _page2 = await Page.findOne({ path: path2, grant: Page.GRANT_RESTRICTED });
  784. expect(_pageT).toBeTruthy();
  785. expect(_page1).toBeNull();
  786. expect(_page2).toBeTruthy();
  787. expect(_pageT.descendantCount).toBe(1);
  788. });
  789. test('a page that has children will create an empty page with the same path and it becomes a new parent', async() => {
  790. const pathT = '/mup14_top';
  791. const path1 = '/mup14_top/mup6_pub';
  792. const path2 = '/mup14_top/mup6_pub/mup7_pub';
  793. const top = await Page.findOne({ path: pathT, descendantCount: 2 });
  794. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  795. const page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC });
  796. expect(top).toBeTruthy();
  797. expect(page1).toBeTruthy();
  798. expect(page2).toBeTruthy();
  799. await Page.updatePage(page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  800. const _top = await Page.findOne({ path: pathT });
  801. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  802. const _page2 = await Page.findOne({ path: path2 });
  803. const _pageN = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  804. expect(_page1).toBeTruthy();
  805. expect(_page2).toBeTruthy();
  806. expect(_pageN).toBeTruthy();
  807. expect(_page1.parent).toBeNull();
  808. expect(_page2.parent).toStrictEqual(_pageN._id);
  809. expect(_pageN.parent).toStrictEqual(top._id);
  810. expect(_pageN.isEmpty).toBe(true);
  811. expect(_pageN.descendantCount).toBe(1);
  812. expect(_top.descendantCount).toBe(1);
  813. });
  814. test('of a leaf page will NOT have an empty page with the same path', async() => {
  815. const pathT = '/mup15_top';
  816. const path1 = '/mup15_top/mup8_pub';
  817. const pageT = await Page.findOne({ path: pathT, descendantCount: 1 });
  818. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  819. const count = await Page.count({ path: path1 });
  820. expect(pageT).toBeTruthy();
  821. expect(page1).toBeTruthy();
  822. expect(count).toBe(1);
  823. await Page.updatePage(page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  824. const _pageT = await Page.findOne({ path: pathT });
  825. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  826. const _pageNotExist = await Page.findOne({ path: path1, isEmpty: true });
  827. expect(_pageT).toBeTruthy();
  828. expect(_page1).toBeTruthy();
  829. expect(_pageNotExist).toBeNull();
  830. expect(_pageT.descendantCount).toBe(0);
  831. });
  832. });
  833. describe('Changing grant to GRANT_RESTRICTED', () => {
  834. test('successfully change to GRANT_RESTRICTED from GRANT_OWNER', async() => {
  835. const path = '/mup40';
  836. const _page = await Page.findOne({ path, grant: Page.GRANT_OWNER, grantedUsers: [dummyUser1._id] });
  837. expect(_page).toBeTruthy();
  838. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  839. const page = await Page.findOne({ path });
  840. expect(page).toBeTruthy();
  841. expect(page.grant).toBe(Page.GRANT_RESTRICTED);
  842. expect(page.grantedUsers).toStrictEqual([]);
  843. });
  844. });
  845. describe('Changing grant from RESTRICTED to PUBLIC of', () => {
  846. test('a page will create ancestors if they do not exist', async() => {
  847. const pathT = '/mup16_top';
  848. const path1 = '/mup16_top/mup9_pub';
  849. const path2 = '/mup16_top/mup9_pub/mup10_pub';
  850. const path3 = '/mup16_top/mup9_pub/mup10_pub/mup11_awl';
  851. const top = await Page.findOne({ path: pathT });
  852. const page1 = await Page.findOne({ path: path1 });
  853. const page2 = await Page.findOne({ path: path2 });
  854. const page3 = await Page.findOne({ path: path3, grant: Page.GRANT_RESTRICTED });
  855. expect(top).toBeTruthy();
  856. expect(page3).toBeTruthy();
  857. expect(page1).toBeNull();
  858. expect(page2).toBeNull();
  859. await Page.updatePage(page3, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_PUBLIC });
  860. const _pageT = await Page.findOne({ path: pathT });
  861. const _page1 = await Page.findOne({ path: path1, isEmpty: true });
  862. const _page2 = await Page.findOne({ path: path2, isEmpty: true });
  863. const _page3 = await Page.findOne({ path: path3, grant: Page.GRANT_PUBLIC });
  864. expect(_page1).toBeTruthy();
  865. expect(_page2).toBeTruthy();
  866. expect(_page3).toBeTruthy();
  867. expect(_page1.parent).toStrictEqual(top._id);
  868. expect(_page2.parent).toStrictEqual(_page1._id);
  869. expect(_page3.parent).toStrictEqual(_page2._id);
  870. expect(_pageT.descendantCount).toBe(1);
  871. });
  872. test('a page will replace an empty page with the same path if any', async() => {
  873. const pathT = '/mup17_top';
  874. const path1 = '/mup17_top/mup12_emp';
  875. const path2 = '/mup17_top/mup12_emp/mup18_pub';
  876. const pageT = await Page.findOne({ path: pathT, descendantCount: 1 });
  877. const page1 = await Page.findOne({ path: path1, isEmpty: true });
  878. const page2 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED, isEmpty: false });
  879. const page3 = await Page.findOne({ path: path2 });
  880. expect(pageT).toBeTruthy();
  881. expect(page1).toBeTruthy();
  882. expect(page2).toBeTruthy();
  883. expect(page3).toBeTruthy();
  884. await Page.updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_PUBLIC });
  885. const _pageT = await Page.findOne({ path: pathT });
  886. const _page1 = await Page.findOne({ path: path1, isEmpty: true }); // should be replaced
  887. const _page2 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  888. const _page3 = await Page.findOne({ path: path2 });
  889. expect(_pageT).toBeTruthy();
  890. expect(_page1).toBeNull();
  891. expect(_page2).toBeTruthy();
  892. expect(_page3).toBeTruthy();
  893. expect(_page2.grant).toBe(Page.GRANT_PUBLIC);
  894. expect(_page2.parent).toStrictEqual(_pageT._id);
  895. expect(_page3.parent).toStrictEqual(_page2._id);
  896. expect(_pageT.descendantCount).toBe(2);
  897. });
  898. });
  899. describe('Changing grant to GRANT_OWNER(onlyme)', () => {
  900. test('successfully change to GRANT_OWNER from GRANT_PUBLIC', async() => {
  901. const path = '/mup19';
  902. const _page = await Page.findOne({ path, grant: Page.GRANT_PUBLIC });
  903. expect(_page).toBeTruthy();
  904. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER });
  905. const page = await Page.findOne({ path });
  906. expect(page.grant).toBe(Page.GRANT_OWNER);
  907. expect(page.grantedUsers).toStrictEqual([dummyUser1._id]);
  908. });
  909. test('successfully change to GRANT_OWNER from GRANT_USER_GROUP', async() => {
  910. const path = '/mup20';
  911. const _page = await Page.findOne({ path, grant: Page.GRANT_USER_GROUP, grantedGroup: userGroupIdPModelA });
  912. expect(_page).toBeTruthy();
  913. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', pModelUser1, { grant: Page.GRANT_OWNER });
  914. const page = await Page.findOne({ path });
  915. expect(page.grant).toBe(Page.GRANT_OWNER);
  916. expect(page.grantedUsers).toStrictEqual([pModelUser1._id]);
  917. expect(page.grantedGroup).toBeNull();
  918. });
  919. test('successfully change to GRANT_OWNER from GRANT_RESTRICTED', async() => {
  920. const path = '/mup21';
  921. const _page = await Page.findOne({ path, grant: Page.GRANT_RESTRICTED });
  922. expect(_page).toBeTruthy();
  923. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER });
  924. const page = await Page.findOne({ path });
  925. expect(page.grant).toBe(Page.GRANT_OWNER);
  926. expect(page.grantedUsers).toStrictEqual([dummyUser1._id]);
  927. });
  928. test('Failed to change to GRANT_OWNER if one of the ancestors is GRANT_USER_GROUP page', async() => {
  929. const path1 = '/mup22';
  930. const path2 = '/mup22/mup23';
  931. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  932. const _page2 = await Page.findOne({ path: path2, grant: Page.GRANT_USER_GROUP, grantedGroup: userGroupIdPModelA });
  933. expect(_page1).toBeTruthy();
  934. expect(_page2).toBeTruthy();
  935. await expect(updatePage(_page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER }))
  936. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  937. const page1 = await Page.findOne({ path1 });
  938. expect(page1).toBeTruthy();
  939. expect(page1.grant).toBe(Page.GRANT_PUBLIC);
  940. expect(page1.grantedUsers).not.toStrictEqual([dummyUser1._id]);
  941. });
  942. });
  943. describe('Changing grant to GRANT_USER_GROUP', () => {
  944. describe('update grant of a page under a page with GRANT_PUBLIC', () => {
  945. test('successfully change to GRANT_USER_GROUP from GRANT_PUBLIC if parent page is GRANT_PUBLIC', async() => {
  946. // path
  947. const path1 = '/mup24_pub';
  948. const path2 = '/mup24_pub/mup25_pub';
  949. // page
  950. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC }); // out of update scope
  951. const _page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC, parent: _page1._id }); // update target
  952. expect(_page1).toBeTruthy();
  953. expect(_page2).toBeTruthy();
  954. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: userGroupIdPModelA };
  955. const updatedPage = await updatePage(_page2, 'new', 'old', pModelUser1, options); // from GRANT_PUBLIC to GRANT_USER_GROUP(userGroupIdPModelA)
  956. const page1 = await Page.findById(_page1._id);
  957. const page2 = await Page.findById(_page2._id);
  958. expect(page1).toBeTruthy();
  959. expect(page2).toBeTruthy();
  960. expect(updatedPage).toBeTruthy();
  961. expect(updatedPage._id).toStrictEqual(page2._id);
  962. // check page2 grant and group
  963. expect(page2.grant).toBe(Page.GRANT_USER_GROUP);
  964. expect(page2.grantedGroup._id).toStrictEqual(userGroupIdPModelA);
  965. });
  966. test('successfully change to GRANT_USER_GROUP from GRANT_RESTRICTED if parent page is GRANT_PUBLIC', async() => {
  967. // path
  968. const _path1 = '/mup26_awl';
  969. // page
  970. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_RESTRICTED });
  971. expect(_page1).toBeTruthy();
  972. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: userGroupIdPModelA };
  973. const updatedPage = await updatePage(_page1, 'new', 'old', pModelUser1, options); // from GRANT_RESTRICTED to GRANT_USER_GROUP(userGroupIdPModelA)
  974. const page1 = await Page.findById(_page1._id);
  975. expect(page1).toBeTruthy();
  976. expect(updatedPage).toBeTruthy();
  977. expect(updatedPage._id).toStrictEqual(page1._id);
  978. // updated page
  979. expect(page1.grant).toBe(Page.GRANT_USER_GROUP);
  980. expect(page1.grantedGroup._id).toStrictEqual(userGroupIdPModelA);
  981. // parent's grant check
  982. const parent = await Page.findById(page1.parent);
  983. expect(parent.grant).toBe(Page.GRANT_PUBLIC);
  984. });
  985. test('successfully change to GRANT_USER_GROUP from GRANT_OWNER if parent page is GRANT_PUBLIC', async() => {
  986. // path
  987. const path1 = '/mup27_pub';
  988. const path2 = '/mup27_pub/mup28_owner';
  989. // page
  990. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC }); // out of update scope
  991. const _page2 = await Page.findOne({
  992. path: path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1], parent: _page1._id,
  993. }); // update target
  994. expect(_page1).toBeTruthy();
  995. expect(_page2).toBeTruthy();
  996. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: userGroupIdPModelA };
  997. const updatedPage = await updatePage(_page2, 'new', 'old', pModelUser1, options); // from GRANT_OWNER to GRANT_USER_GROUP(userGroupIdPModelA)
  998. const page1 = await Page.findById(_page1._id);
  999. const page2 = await Page.findById(_page2._id);
  1000. expect(page1).toBeTruthy();
  1001. expect(page2).toBeTruthy();
  1002. expect(updatedPage).toBeTruthy();
  1003. expect(updatedPage._id).toStrictEqual(page2._id);
  1004. // grant check
  1005. expect(page2.grant).toBe(Page.GRANT_USER_GROUP);
  1006. expect(page2.grantedGroup._id).toStrictEqual(userGroupIdPModelA);
  1007. expect(page2.grantedUsers.length).toBe(0);
  1008. });
  1009. });
  1010. describe('update grant of a page under a page with GRANT_USER_GROUP', () => {
  1011. test('successfully change to GRANT_USER_GROUP if the group to set is the child or descendant of the parent page group', async() => {
  1012. // path
  1013. const _path1 = '/mup29_A';
  1014. const _path2 = '/mup29_A/mup30_owner';
  1015. // page
  1016. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: userGroupIdPModelA }); // out of update scope
  1017. const _page2 = await Page.findOne({ // update target
  1018. path: _path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1], parent: _page1._id,
  1019. });
  1020. expect(_page1).toBeTruthy();
  1021. expect(_page2).toBeTruthy();
  1022. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: userGroupIdPModelB };
  1023. // First round
  1024. // Group relation(parent -> child): userGroupIdPModelA -> userGroupIdPModelB -> userGroupIdPModelC
  1025. const updatedPage = await updatePage(_page2, 'new', 'old', pModelUser3, options); // from GRANT_OWNER to GRANT_USER_GROUP(userGroupIdPModelB)
  1026. const page1 = await Page.findById(_page1._id);
  1027. const page2 = await Page.findById(_page2._id);
  1028. expect(page1).toBeTruthy();
  1029. expect(page2).toBeTruthy();
  1030. expect(updatedPage).toBeTruthy();
  1031. expect(updatedPage._id).toStrictEqual(page2._id);
  1032. expect(page2.grant).toBe(Page.GRANT_USER_GROUP);
  1033. expect(page2.grantedGroup._id).toStrictEqual(userGroupIdPModelB);
  1034. expect(page2.grantedUsers.length).toBe(0);
  1035. // Second round
  1036. // Update group to groupC which is a grandchild from pageA's point of view
  1037. const secondRoundOptions = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: userGroupIdPModelC }; // from GRANT_USER_GROUP(userGroupIdPModelB) to GRANT_USER_GROUP(userGroupIdPModelC)
  1038. const secondRoundUpdatedPage = await updatePage(_page2, 'new', 'new', pModelUser3, secondRoundOptions);
  1039. expect(secondRoundUpdatedPage).toBeTruthy();
  1040. expect(secondRoundUpdatedPage.grant).toBe(Page.GRANT_USER_GROUP);
  1041. expect(secondRoundUpdatedPage.grantedGroup._id).toStrictEqual(userGroupIdPModelC);
  1042. });
  1043. test('Fail to change to GRANT_USER_GROUP if the group to set is NOT the child or descendant of the parent page group', async() => {
  1044. // path
  1045. const _path1 = '/mup31_A';
  1046. const _path2 = '/mup31_A/mup32_owner';
  1047. // page
  1048. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: userGroupIdPModelA });
  1049. const _page2 = await Page.findOne({ // update target
  1050. path: _path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1._id], parent: _page1._id,
  1051. });
  1052. expect(_page1).toBeTruthy();
  1053. expect(_page2).toBeTruthy();
  1054. // group
  1055. const _groupIsolated = await UserGroup.findById(userGroupIdPModelIsolate);
  1056. expect(_groupIsolated).toBeTruthy();
  1057. // group parent check
  1058. expect(_groupIsolated.parent).toBeUndefined(); // should have no parent
  1059. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: userGroupIdPModelIsolate };
  1060. await expect(updatePage(_page2, 'new', 'old', pModelUser1, options)) // from GRANT_OWNER to GRANT_USER_GROUP(userGroupIdPModelIsolate)
  1061. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  1062. const page1 = await Page.findById(_page1._id);
  1063. const page2 = await Page.findById(_page2._id);
  1064. expect(page1).toBeTruthy();
  1065. expect(page1).toBeTruthy();
  1066. expect(page2.grant).toBe(Page.GRANT_OWNER); // should be the same before the update
  1067. expect(page2.grantedUsers).toStrictEqual([pModelUser1._id]); // should be the same before the update
  1068. expect(page2.grantedGroup).toBeUndefined(); // no group should be set
  1069. });
  1070. test('Fail to change to GRANT_USER_GROUP if the group to set is an ancestor of the parent page group', async() => {
  1071. // path
  1072. const _path1 = '/mup33_C';
  1073. const _path2 = '/mup33_C/mup34_owner';
  1074. // page
  1075. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroup: userGroupIdPModelC }); // groupC
  1076. const _page2 = await Page.findOne({ // update target
  1077. path: _path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser3], parent: _page1._id,
  1078. });
  1079. expect(_page1).toBeTruthy();
  1080. expect(_page2).toBeTruthy();
  1081. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: userGroupIdPModelA };
  1082. // Group relation(parent -> child): userGroupIdPModelA -> userGroupIdPModelB -> userGroupIdPModelC
  1083. // this should fail because the groupC is a descendant of groupA
  1084. await expect(updatePage(_page2, 'new', 'old', pModelUser3, options)) // from GRANT_OWNER to GRANT_USER_GROUP(userGroupIdPModelA)
  1085. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  1086. const page1 = await Page.findById(_page1._id);
  1087. const page2 = await Page.findById(_page2._id);
  1088. expect(page1).toBeTruthy();
  1089. expect(page2).toBeTruthy();
  1090. expect(page2.grant).toBe(Page.GRANT_OWNER); // should be the same before the update
  1091. expect(page2.grantedUsers).toStrictEqual([pModelUser3._id]); // should be the same before the update
  1092. expect(page2.grantedGroup).toBeUndefined(); // no group should be set
  1093. });
  1094. });
  1095. describe('update grant of a page under a page with GRANT_OWNER', () => {
  1096. test('Fail to change from GRNAT_OWNER', async() => {
  1097. // path
  1098. const path1 = '/mup35_owner';
  1099. const path2 = '/mup35_owner/mup36_owner';
  1100. // page
  1101. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1] });
  1102. const _page2 = await Page.findOne({ // update target
  1103. path: path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1], parent: _page1._id,
  1104. });
  1105. expect(_page1).toBeTruthy();
  1106. expect(_page2).toBeTruthy();
  1107. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupId: userGroupIdPModelA };
  1108. await expect(updatePage(_page2, 'new', 'old', pModelUser1, options)) // from GRANT_OWNER to GRANT_USER_GROUP(userGroupIdPModelA)
  1109. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  1110. const page1 = await Page.findById(_page1.id);
  1111. const page2 = await Page.findById(_page2.id);
  1112. expect(page1).toBeTruthy();
  1113. expect(page2).toBeTruthy();
  1114. expect(page2.grant).toBe(Page.GRANT_OWNER); // should be the same before the update
  1115. expect(page2.grantedUsers).toStrictEqual([pModelUser1._id]); // should be the same before the update
  1116. expect(page2.grantedGroup).toBeUndefined(); // no group should be set
  1117. });
  1118. });
  1119. });
  1120. });
  1121. // see: https://dev.growi.org/635a314eac6bcd85cbf359fc about the specification
  1122. describe('updatePage with overwriteScopesOfDescendants true', () => {
  1123. test('(case 1) it should update all granted descendant pages when update grant is GRANT_PUBLIC', async() => {
  1124. const upodPagegAB = await Page.findOne({ path: '/gAB_upod_1' });
  1125. const upodPagegB = await Page.findOne({ path: '/gAB_upod_1/gB_upod_1' });
  1126. const upodPageonlyB = await Page.findOne({ path: '/gAB_upod_1/onlyB_upod_1' });
  1127. expect(upodPagegAB).not.toBeNull();
  1128. expect(upodPagegB).not.toBeNull();
  1129. expect(upodPageonlyB).not.toBeNull();
  1130. expect(upodPagegAB.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1131. expect(upodPagegB.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1132. expect(upodPageonlyB.grant).toBe(PageGrant.GRANT_OWNER);
  1133. // Update
  1134. const options = {
  1135. grant: PageGrant.GRANT_PUBLIC,
  1136. overwriteScopesOfDescendants: true,
  1137. };
  1138. const updatedPage = await Page.updatePage(upodPagegAB, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1139. const upodPagegBUpdated = await Page.findOne({ path: '/gAB_upod_1/gB_upod_1' });
  1140. const upodPageonlyBUpdated = await Page.findOne({ path: '/gAB_upod_1/onlyB_upod_1' });
  1141. // Changed
  1142. const newGrant = PageGrant.GRANT_PUBLIC;
  1143. expect(updatedPage.grant).toBe(newGrant);
  1144. // Not changed
  1145. expect(upodPagegBUpdated.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1146. expect(upodPagegBUpdated.grantedGroup).toStrictEqual(upodPagegB.grantedGroup);
  1147. expect(upodPageonlyBUpdated.grant).toBe(PageGrant.GRANT_OWNER);
  1148. expect(upodPageonlyBUpdated.grantedUsers).toStrictEqual(upodPageonlyB.grantedUsers);
  1149. });
  1150. test('(case 2) it should update all granted descendant pages when all descendant pages are granted by the operator', async() => {
  1151. const upodPagePublic = await Page.findOne({ path: '/public_upod_2' });
  1152. const upodPagegA = await Page.findOne({ path: '/public_upod_2/gA_upod_2' });
  1153. const upodPagegAIsolated = await Page.findOne({ path: '/public_upod_2/gAIsolated_upod_2' });
  1154. const upodPageonlyA = await Page.findOne({ path: '/public_upod_2/onlyA_upod_2' });
  1155. expect(upodPagePublic).not.toBeNull();
  1156. expect(upodPagegA).not.toBeNull();
  1157. expect(upodPagegAIsolated).not.toBeNull();
  1158. expect(upodPageonlyA).not.toBeNull();
  1159. expect(upodPagePublic.grant).toBe(PageGrant.GRANT_PUBLIC);
  1160. expect(upodPagegA.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1161. expect(upodPagegAIsolated.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1162. expect(upodPageonlyA.grant).toBe(PageGrant.GRANT_OWNER);
  1163. // Update
  1164. const options = {
  1165. grant: PageGrant.GRANT_OWNER,
  1166. overwriteScopesOfDescendants: true,
  1167. };
  1168. const updatedPage = await Page.updatePage(upodPagePublic, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1169. const upodPagegAUpdated = await Page.findOne({ path: '/public_upod_2/gA_upod_2' });
  1170. const upodPagegAIsolatedUpdated = await Page.findOne({ path: '/public_upod_2/gAIsolated_upod_2' });
  1171. const upodPageonlyAUpdated = await Page.findOne({ path: '/public_upod_2/onlyA_upod_2' });
  1172. // Changed
  1173. const newGrant = PageGrant.GRANT_OWNER;
  1174. const newGrantedUsers = [upodUserA._id];
  1175. expect(updatedPage.grant).toBe(newGrant);
  1176. expect(updatedPage.grantedUsers).toStrictEqual(newGrantedUsers);
  1177. expect(upodPagegAUpdated.grant).toBe(newGrant);
  1178. expect(upodPagegAUpdated.grantedUsers).toStrictEqual(newGrantedUsers);
  1179. expect(upodPagegAIsolatedUpdated.grant).toBe(newGrant);
  1180. expect(upodPagegAIsolatedUpdated.grantedUsers).toStrictEqual(newGrantedUsers);
  1181. expect(upodPageonlyAUpdated.grant).toBe(newGrant);
  1182. expect(upodPageonlyAUpdated.grantedUsers).toStrictEqual(newGrantedUsers);
  1183. });
  1184. test(`(case 3) it should update all granted descendant pages when update grant is GRANT_USER_GROUP
  1185. , all user groups of descendants are the children or itself of the update user group
  1186. , and all users of descendants belong to the update user group`, async() => {
  1187. const upodPagePublic = await Page.findOne({ path: '/public_upod_3' });
  1188. const upodPagegAB = await Page.findOne({ path: '/public_upod_3/gAB_upod_3' });
  1189. const upodPagegB = await Page.findOne({ path: '/public_upod_3/gB_upod_3' });
  1190. const upodPageonlyB = await Page.findOne({ path: '/public_upod_3/onlyB_upod_3' });
  1191. expect(upodPagePublic).not.toBeNull();
  1192. expect(upodPagegAB).not.toBeNull();
  1193. expect(upodPagegB).not.toBeNull();
  1194. expect(upodPageonlyB).not.toBeNull();
  1195. expect(upodPagePublic.grant).toBe(PageGrant.GRANT_PUBLIC);
  1196. expect(upodPagegAB.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1197. expect(upodPagegB.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1198. expect(upodPageonlyB.grant).toBe(PageGrant.GRANT_OWNER);
  1199. // Update
  1200. const options = {
  1201. grant: PageGrant.GRANT_USER_GROUP,
  1202. grantUserGroupId: upodUserGroupIdAB,
  1203. overwriteScopesOfDescendants: true,
  1204. };
  1205. const updatedPage = await Page.updatePage(upodPagePublic, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1206. const upodPagegABUpdated = await Page.findOne({ path: '/public_upod_3/gAB_upod_3' });
  1207. const upodPagegBUpdated = await Page.findOne({ path: '/public_upod_3/gB_upod_3' });
  1208. const upodPageonlyBUpdated = await Page.findOne({ path: '/public_upod_3/onlyB_upod_3' });
  1209. // Changed
  1210. const newGrant = PageGrant.GRANT_USER_GROUP;
  1211. const newGrantedGroup = upodUserGroupIdAB;
  1212. expect(updatedPage.grant).toBe(newGrant);
  1213. expect(updatedPage.grantedGroup._id).toStrictEqual(newGrantedGroup);
  1214. expect(upodPagegABUpdated.grant).toBe(newGrant);
  1215. expect(upodPagegABUpdated.grantedGroup._id).toStrictEqual(newGrantedGroup);
  1216. // Not changed
  1217. expect(upodPagegBUpdated.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1218. expect(upodPagegBUpdated.grantedGroup._id).toStrictEqual(upodPagegB.grantedGroup);
  1219. expect(upodPageonlyBUpdated.grant).toBe(PageGrant.GRANT_OWNER);
  1220. expect(upodPageonlyBUpdated.grantedUsers).toStrictEqual(upodPageonlyB.grantedUsers);
  1221. });
  1222. test(`(case 4) it should throw when some of descendants is not granted
  1223. , update grant is GRANT_USER_GROUP
  1224. , and some of user groups of descendants are not children or itself of the update user group`, async() => {
  1225. const upodPagePublic = await Page.findOne({ path: '/public_upod_4' });
  1226. const upodPagegA = await Page.findOne({ path: '/public_upod_4/gA_upod_4' });
  1227. const upodPagegC = await Page.findOne({ path: '/public_upod_4/gC_upod_4' });
  1228. expect(upodPagePublic).not.toBeNull();
  1229. expect(upodPagegA).not.toBeNull();
  1230. expect(upodPagegC).not.toBeNull();
  1231. expect(upodPagePublic.grant).toBe(PageGrant.GRANT_PUBLIC);
  1232. expect(upodPagegA.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1233. expect(upodPagegC.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1234. // Update
  1235. const options = {
  1236. grant: PageGrant.GRANT_USER_GROUP,
  1237. grantUserGroupId: upodUserGroupIdAB,
  1238. overwriteScopesOfDescendants: true,
  1239. };
  1240. const updatedPagePromise = Page.updatePage(upodPagePublic, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1241. await expect(updatedPagePromise).rejects.toThrowError();
  1242. });
  1243. test(`(case 5) it should throw when some of descendants is not granted
  1244. , update grant is GRANT_USER_GROUP
  1245. , and some of users of descendants does NOT belong to the update user group`, async() => {
  1246. const upodPagePublic = await Page.findOne({ path: '/public_upod_5' });
  1247. const upodPagegA = await Page.findOne({ path: '/public_upod_5/gA_upod_5' });
  1248. const upodPageonlyC = await Page.findOne({ path: '/public_upod_5/onlyC_upod_5' });
  1249. expect(upodPagePublic).not.toBeNull();
  1250. expect(upodPagegA).not.toBeNull();
  1251. expect(upodPageonlyC).not.toBeNull();
  1252. expect(upodPagePublic.grant).toBe(PageGrant.GRANT_PUBLIC);
  1253. expect(upodPagegA.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1254. expect(upodPageonlyC.grant).toBe(PageGrant.GRANT_OWNER);
  1255. // Update
  1256. const options = {
  1257. grant: PageGrant.GRANT_USER_GROUP,
  1258. grantUserGroupId: upodUserGroupIdAB,
  1259. overwriteScopesOfDescendants: true,
  1260. };
  1261. const updatedPagePromise = Page.updatePage(upodPagePublic, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1262. await expect(updatedPagePromise).rejects.toThrowError();
  1263. });
  1264. test('(case 6) it should throw when some of descendants is not granted and update grant is GRANT_OWNER', async() => {
  1265. const upodPagePublic = await Page.findOne({ path: '/public_upod_6' });
  1266. const upodPageonlyC = await Page.findOne({ path: '/public_upod_6/onlyC_upod_6' });
  1267. expect(upodPagePublic).not.toBeNull();
  1268. expect(upodPageonlyC).not.toBeNull();
  1269. expect(upodPagePublic.grant).toBe(PageGrant.GRANT_PUBLIC);
  1270. expect(upodPageonlyC.grant).toBe(PageGrant.GRANT_OWNER);
  1271. // Update
  1272. const options = {
  1273. grant: PageGrant.GRANT_USER_GROUP,
  1274. grantUserGroupId: upodUserGroupIdAB,
  1275. overwriteScopesOfDescendants: true,
  1276. };
  1277. const updatedPagePromise = Page.updatePage(upodPagePublic, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1278. await expect(updatedPagePromise).rejects.toThrowError();
  1279. });
  1280. });
  1281. });