v5.page.test.js 64 KB

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