v5.page.test.js 52 KB

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