v5.page.test.js 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668
  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: null,
  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: null,
  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: null,
  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: null,
  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: null,
  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: null,
  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: null,
  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: null,
  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: null,
  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: null,
  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. await createDocumentsToTestUpdatePageOverwritingDescendants();
  968. });
  969. describe('update', () => {
  970. describe('Changing grant from PUBLIC to RESTRICTED of', () => {
  971. test('an only-child page will delete its empty parent page', async() => {
  972. const pathT = '/mup13_top';
  973. const path1 = '/mup13_top/mup1_emp';
  974. const path2 = '/mup13_top/mup1_emp/mup2_pub';
  975. const pageT = await Page.findOne({ path: pathT, descendantCount: 2 });
  976. const page1 = await Page.findOne({ path: path1, isEmpty: true });
  977. const page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC });
  978. expect(pageT).toBeTruthy();
  979. expect(page1).toBeTruthy();
  980. expect(page2).toBeTruthy();
  981. const options = { grant: Page.GRANT_RESTRICTED, grantUserGroupIds: null };
  982. await updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, options);
  983. const _pageT = await Page.findOne({ path: pathT });
  984. const _page1 = await Page.findOne({ path: path1 });
  985. const _page2 = await Page.findOne({ path: path2, grant: Page.GRANT_RESTRICTED });
  986. expect(_pageT).toBeTruthy();
  987. expect(_page1).toBeNull();
  988. expect(_page2).toBeTruthy();
  989. expect(_pageT.descendantCount).toBe(1);
  990. });
  991. test('a page that has children will create an empty page with the same path and it becomes a new parent', async() => {
  992. const pathT = '/mup14_top';
  993. const path1 = '/mup14_top/mup6_pub';
  994. const path2 = '/mup14_top/mup6_pub/mup7_pub';
  995. const top = await Page.findOne({ path: pathT, descendantCount: 2 });
  996. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  997. const page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC });
  998. expect(top).toBeTruthy();
  999. expect(page1).toBeTruthy();
  1000. expect(page2).toBeTruthy();
  1001. await updatePage(page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  1002. const _top = await Page.findOne({ path: pathT });
  1003. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  1004. const _page2 = await Page.findOne({ path: path2 });
  1005. const _pageN = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  1006. expect(_page1).toBeTruthy();
  1007. expect(_page2).toBeTruthy();
  1008. expect(_pageN).toBeTruthy();
  1009. expect(_page1.parent).toBeNull();
  1010. expect(_page2.parent).toStrictEqual(_pageN._id);
  1011. expect(_pageN.parent).toStrictEqual(top._id);
  1012. expect(_pageN.isEmpty).toBe(true);
  1013. expect(_pageN.descendantCount).toBe(1);
  1014. expect(_top.descendantCount).toBe(1);
  1015. });
  1016. test('of a leaf page will NOT have an empty page with the same path', async() => {
  1017. const pathT = '/mup15_top';
  1018. const path1 = '/mup15_top/mup8_pub';
  1019. const pageT = await Page.findOne({ path: pathT, descendantCount: 1 });
  1020. const page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  1021. const count = await Page.count({ path: path1 });
  1022. expect(pageT).toBeTruthy();
  1023. expect(page1).toBeTruthy();
  1024. expect(count).toBe(1);
  1025. await updatePage(page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  1026. const _pageT = await Page.findOne({ path: pathT });
  1027. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED });
  1028. const _pageNotExist = await Page.findOne({ path: path1, isEmpty: true });
  1029. expect(_pageT).toBeTruthy();
  1030. expect(_page1).toBeTruthy();
  1031. expect(_pageNotExist).toBeNull();
  1032. expect(_pageT.descendantCount).toBe(0);
  1033. });
  1034. });
  1035. describe('Changing grant to GRANT_RESTRICTED', () => {
  1036. test('successfully change to GRANT_RESTRICTED from GRANT_OWNER', async() => {
  1037. const path = '/mup40';
  1038. const _page = await Page.findOne({ path, grant: Page.GRANT_OWNER, grantedUsers: [dummyUser1._id] });
  1039. expect(_page).toBeTruthy();
  1040. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_RESTRICTED });
  1041. const page = await Page.findOne({ path });
  1042. expect(page).toBeTruthy();
  1043. expect(page.grant).toBe(Page.GRANT_RESTRICTED);
  1044. expect(page.grantedUsers).toStrictEqual([]);
  1045. });
  1046. });
  1047. describe('Changing grant from RESTRICTED to PUBLIC of', () => {
  1048. test('a page will create ancestors if they do not exist', async() => {
  1049. const pathT = '/mup16_top';
  1050. const path1 = '/mup16_top/mup9_pub';
  1051. const path2 = '/mup16_top/mup9_pub/mup10_pub';
  1052. const path3 = '/mup16_top/mup9_pub/mup10_pub/mup11_awl';
  1053. const top = await Page.findOne({ path: pathT });
  1054. const page1 = await Page.findOne({ path: path1 });
  1055. const page2 = await Page.findOne({ path: path2 });
  1056. const page3 = await Page.findOne({ path: path3, grant: Page.GRANT_RESTRICTED });
  1057. expect(top).toBeTruthy();
  1058. expect(page3).toBeTruthy();
  1059. expect(page1).toBeNull();
  1060. expect(page2).toBeNull();
  1061. await updatePage(page3, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_PUBLIC });
  1062. const _pageT = await Page.findOne({ path: pathT });
  1063. const _page1 = await Page.findOne({ path: path1, isEmpty: true });
  1064. const _page2 = await Page.findOne({ path: path2, isEmpty: true });
  1065. const _page3 = await Page.findOne({ path: path3, grant: Page.GRANT_PUBLIC });
  1066. expect(_page1).toBeTruthy();
  1067. expect(_page2).toBeTruthy();
  1068. expect(_page3).toBeTruthy();
  1069. expect(_page1.parent).toStrictEqual(top._id);
  1070. expect(_page2.parent).toStrictEqual(_page1._id);
  1071. expect(_page3.parent).toStrictEqual(_page2._id);
  1072. expect(_pageT.descendantCount).toBe(1);
  1073. });
  1074. test('a page will replace an empty page with the same path if any', async() => {
  1075. const pathT = '/mup17_top';
  1076. const path1 = '/mup17_top/mup12_emp';
  1077. const path2 = '/mup17_top/mup12_emp/mup18_pub';
  1078. const pageT = await Page.findOne({ path: pathT, descendantCount: 1 });
  1079. const page1 = await Page.findOne({ path: path1, isEmpty: true });
  1080. const page2 = await Page.findOne({ path: path1, grant: Page.GRANT_RESTRICTED, isEmpty: false });
  1081. const page3 = await Page.findOne({ path: path2 });
  1082. expect(pageT).toBeTruthy();
  1083. expect(page1).toBeTruthy();
  1084. expect(page2).toBeTruthy();
  1085. expect(page3).toBeTruthy();
  1086. await updatePage(page2, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_PUBLIC });
  1087. const _pageT = await Page.findOne({ path: pathT });
  1088. const _page1 = await Page.findOne({ path: path1, isEmpty: true }); // should be replaced
  1089. const _page2 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  1090. const _page3 = await Page.findOne({ path: path2 });
  1091. expect(_pageT).toBeTruthy();
  1092. expect(_page1).toBeNull();
  1093. expect(_page2).toBeTruthy();
  1094. expect(_page3).toBeTruthy();
  1095. expect(_page2.grant).toBe(Page.GRANT_PUBLIC);
  1096. expect(_page2.parent).toStrictEqual(_pageT._id);
  1097. expect(_page3.parent).toStrictEqual(_page2._id);
  1098. expect(_pageT.descendantCount).toBe(2);
  1099. });
  1100. });
  1101. describe('Changing grant to GRANT_OWNER(onlyme)', () => {
  1102. test('successfully change to GRANT_OWNER from GRANT_PUBLIC', async() => {
  1103. const path = '/mup19';
  1104. const _page = await Page.findOne({ path, grant: Page.GRANT_PUBLIC });
  1105. expect(_page).toBeTruthy();
  1106. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER });
  1107. const page = await Page.findOne({ path });
  1108. expect(page.grant).toBe(Page.GRANT_OWNER);
  1109. expect(page.grantedUsers).toStrictEqual([dummyUser1._id]);
  1110. });
  1111. test('successfully change to GRANT_OWNER from GRANT_USER_GROUP', async() => {
  1112. const path = '/mup20';
  1113. const _page = await Page.findOne({ path, grant: Page.GRANT_USER_GROUP, grantedGroups: { $elemMatch: { item: userGroupIdPModelA } } });
  1114. expect(_page).toBeTruthy();
  1115. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', pModelUser1, { grant: Page.GRANT_OWNER });
  1116. const page = await Page.findOne({ path });
  1117. expect(page.grant).toBe(Page.GRANT_OWNER);
  1118. expect(page.grantedUsers).toStrictEqual([pModelUser1._id]);
  1119. expect(page.grantedGroups.length).toBe(0);
  1120. });
  1121. test('successfully change to GRANT_OWNER from GRANT_RESTRICTED', async() => {
  1122. const path = '/mup21';
  1123. const _page = await Page.findOne({ path, grant: Page.GRANT_RESTRICTED });
  1124. expect(_page).toBeTruthy();
  1125. await updatePage(_page, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER });
  1126. const page = await Page.findOne({ path });
  1127. expect(page.grant).toBe(Page.GRANT_OWNER);
  1128. expect(page.grantedUsers).toStrictEqual([dummyUser1._id]);
  1129. });
  1130. test('Failed to change to GRANT_OWNER if one of the ancestors is GRANT_USER_GROUP page', async() => {
  1131. const path1 = '/mup22';
  1132. const path2 = '/mup22/mup23';
  1133. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC });
  1134. const _page2 = await Page.findOne({ path: path2, grant: Page.GRANT_USER_GROUP, grantedGroups: { $elemMatch: { item: userGroupIdPModelA } } });
  1135. expect(_page1).toBeTruthy();
  1136. expect(_page2).toBeTruthy();
  1137. await expect(updatePage(_page1, 'newRevisionBody', 'oldRevisionBody', dummyUser1, { grant: Page.GRANT_OWNER }))
  1138. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  1139. const page1 = await Page.findOne({ path1 });
  1140. expect(page1).toBeTruthy();
  1141. expect(page1.grant).toBe(Page.GRANT_PUBLIC);
  1142. expect(page1.grantedUsers).not.toStrictEqual([dummyUser1._id]);
  1143. });
  1144. });
  1145. describe('Changing grant to GRANT_USER_GROUP', () => {
  1146. describe('update grant of a page under a page with GRANT_PUBLIC', () => {
  1147. test('successfully change to GRANT_USER_GROUP from GRANT_PUBLIC if parent page is GRANT_PUBLIC', async() => {
  1148. // path
  1149. const path1 = '/mup24_pub';
  1150. const path2 = '/mup24_pub/mup25_pub';
  1151. // page
  1152. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC }); // out of update scope
  1153. const _page2 = await Page.findOne({ path: path2, grant: Page.GRANT_PUBLIC, parent: _page1._id }); // update target
  1154. expect(_page1).toBeTruthy();
  1155. expect(_page2).toBeTruthy();
  1156. const newGrantedGroups = [
  1157. { item: userGroupIdPModelA, type: GroupType.userGroup },
  1158. { item: externalUserGroupIdPModelA, type: GroupType.externalUserGroup },
  1159. ];
  1160. const options = {
  1161. grant: Page.GRANT_USER_GROUP,
  1162. grantUserGroupIds: newGrantedGroups,
  1163. };
  1164. const updatedPage = await updatePage(_page2, 'new', 'old', pModelUser1, options); // from GRANT_PUBLIC to GRANT_USER_GROUP(userGroupIdPModelA)
  1165. const page1 = await Page.findById(_page1._id);
  1166. const page2 = await Page.findById(_page2._id);
  1167. expect(page1).toBeTruthy();
  1168. expect(page2).toBeTruthy();
  1169. expect(updatedPage).toBeTruthy();
  1170. expect(updatedPage._id).toStrictEqual(page2._id);
  1171. // check page2 grant and group
  1172. expect(page2.grant).toBe(Page.GRANT_USER_GROUP);
  1173. expect(normalizeGrantedGroups(page2.grantedGroups)).toStrictEqual(newGrantedGroups);
  1174. });
  1175. test('successfully change to GRANT_USER_GROUP from GRANT_RESTRICTED if parent page is GRANT_PUBLIC', async() => {
  1176. // path
  1177. const _path1 = '/mup26_awl';
  1178. // page
  1179. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_RESTRICTED });
  1180. expect(_page1).toBeTruthy();
  1181. const newGrantedGroups = [
  1182. { item: userGroupIdPModelA, type: GroupType.userGroup },
  1183. { item: externalUserGroupIdPModelA, type: GroupType.externalUserGroup },
  1184. ];
  1185. const options = {
  1186. grant: Page.GRANT_USER_GROUP,
  1187. grantUserGroupIds: newGrantedGroups,
  1188. };
  1189. const updatedPage = await updatePage(_page1, 'new', 'old', pModelUser1, options); // from GRANT_RESTRICTED to GRANT_USER_GROUP(userGroupIdPModelA)
  1190. const page1 = await Page.findById(_page1._id);
  1191. expect(page1).toBeTruthy();
  1192. expect(updatedPage).toBeTruthy();
  1193. expect(updatedPage._id).toStrictEqual(page1._id);
  1194. // updated page
  1195. expect(page1.grant).toBe(Page.GRANT_USER_GROUP);
  1196. expect(normalizeGrantedGroups(page1.grantedGroups)).toStrictEqual(newGrantedGroups);
  1197. // parent's grant check
  1198. const parent = await Page.findById(page1.parent);
  1199. expect(parent.grant).toBe(Page.GRANT_PUBLIC);
  1200. });
  1201. test('successfully change to GRANT_USER_GROUP from GRANT_OWNER if parent page is GRANT_PUBLIC', async() => {
  1202. // path
  1203. const path1 = '/mup27_pub';
  1204. const path2 = '/mup27_pub/mup28_owner';
  1205. // page
  1206. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_PUBLIC }); // out of update scope
  1207. const _page2 = await Page.findOne({
  1208. path: path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1], parent: _page1._id,
  1209. }); // update target
  1210. expect(_page1).toBeTruthy();
  1211. expect(_page2).toBeTruthy();
  1212. const newGrantedGroups = [
  1213. { item: userGroupIdPModelA, type: GroupType.userGroup },
  1214. { item: externalUserGroupIdPModelA, type: GroupType.externalUserGroup },
  1215. ];
  1216. const options = {
  1217. grant: Page.GRANT_USER_GROUP,
  1218. grantUserGroupIds: newGrantedGroups,
  1219. };
  1220. const updatedPage = await updatePage(_page2, 'new', 'old', pModelUser1, options); // from GRANT_OWNER to GRANT_USER_GROUP(userGroupIdPModelA)
  1221. const page1 = await Page.findById(_page1._id);
  1222. const page2 = await Page.findById(_page2._id);
  1223. expect(page1).toBeTruthy();
  1224. expect(page2).toBeTruthy();
  1225. expect(updatedPage).toBeTruthy();
  1226. expect(updatedPage._id).toStrictEqual(page2._id);
  1227. // grant check
  1228. expect(page2.grant).toBe(Page.GRANT_USER_GROUP);
  1229. expect(normalizeGrantedGroups(page2.grantedGroups)).toStrictEqual(newGrantedGroups);
  1230. expect(page2.grantedUsers.length).toBe(0);
  1231. });
  1232. });
  1233. describe('update grant of a page under a page with GRANT_USER_GROUP', () => {
  1234. test('successfully change to GRANT_USER_GROUP if the group to set is the child or descendant of the parent page group', async() => {
  1235. // path
  1236. const _path1 = '/mup29_A';
  1237. const _path2 = '/mup29_A/mup30_owner';
  1238. // page
  1239. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroups: { $elemMatch: { item: userGroupIdPModelA } } }); // out of update scope
  1240. const _page2 = await Page.findOne({ // update target
  1241. path: _path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1], parent: _page1._id,
  1242. });
  1243. expect(_page1).toBeTruthy();
  1244. expect(_page2).toBeTruthy();
  1245. // First round
  1246. // Group relation(parent -> child): userGroupIdPModelA -> userGroupIdPModelB -> userGroupIdPModelC
  1247. const newGrantedGroups = [
  1248. { item: userGroupIdPModelB, type: GroupType.userGroup },
  1249. { item: externalUserGroupIdPModelB, type: GroupType.externalUserGroup },
  1250. ];
  1251. const options = {
  1252. grant: Page.GRANT_USER_GROUP,
  1253. grantUserGroupIds: newGrantedGroups,
  1254. };
  1255. const updatedPage = await updatePage(_page2, 'new', 'old', pModelUser3, options); // from GRANT_OWNER to GRANT_USER_GROUP(userGroupIdPModelB)
  1256. const page1 = await Page.findById(_page1._id);
  1257. const page2 = await Page.findById(_page2._id);
  1258. expect(page1).toBeTruthy();
  1259. expect(page2).toBeTruthy();
  1260. expect(updatedPage).toBeTruthy();
  1261. expect(updatedPage._id).toStrictEqual(page2._id);
  1262. expect(page2.grant).toBe(Page.GRANT_USER_GROUP);
  1263. expect(normalizeGrantedGroups(page2.grantedGroups)).toStrictEqual(newGrantedGroups);
  1264. expect(page2.grantedUsers.length).toBe(0);
  1265. // Second round
  1266. // Update group to groupC which is a grandchild from pageA's point of view
  1267. const secondRoundNewGrantedGroups = [
  1268. { item: userGroupIdPModelC, type: GroupType.userGroup },
  1269. { item: externalUserGroupIdPModelC, type: GroupType.externalUserGroup },
  1270. ];
  1271. const secondRoundOptions = { grant: Page.GRANT_USER_GROUP, grantUserGroupIds: secondRoundNewGrantedGroups }; // from GRANT_USER_GROUP(userGroupIdPModelB) to GRANT_USER_GROUP(userGroupIdPModelC)
  1272. // undo grantedGroups populate to prevent Page.hydrate error
  1273. _page2.grantedGroups.forEach((group) => {
  1274. group.item = group.item._id;
  1275. });
  1276. const secondRoundUpdatedPage = await updatePage(_page2, 'new', 'new', pModelUser3, secondRoundOptions);
  1277. expect(secondRoundUpdatedPage).toBeTruthy();
  1278. expect(secondRoundUpdatedPage.grant).toBe(Page.GRANT_USER_GROUP);
  1279. expect(normalizeGrantedGroups(secondRoundUpdatedPage.grantedGroups)).toStrictEqual(secondRoundNewGrantedGroups);
  1280. });
  1281. 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() => {
  1282. // path
  1283. const _path1 = '/mup31_A';
  1284. const _path2 = '/mup31_A/mup32_owner';
  1285. // page
  1286. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroups: { $elemMatch: { item: userGroupIdPModelA } } });
  1287. const _page2 = await Page.findOne({ // update target
  1288. path: _path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1._id], parent: _page1._id,
  1289. });
  1290. expect(_page1).toBeTruthy();
  1291. expect(_page2).toBeTruthy();
  1292. // group
  1293. const _groupIsolated = await UserGroup.findById(userGroupIdPModelIsolate);
  1294. expect(_groupIsolated).toBeTruthy();
  1295. // group parent check
  1296. expect(_groupIsolated.parent).toBeUndefined(); // should have no parent
  1297. const options = {
  1298. grant: Page.GRANT_USER_GROUP,
  1299. grantUserGroupIds: [
  1300. { item: userGroupIdPModelIsolate, type: GroupType.userGroup },
  1301. { item: externalUserGroupIdPModelIsolate, type: GroupType.externalUserGroup },
  1302. ],
  1303. };
  1304. await expect(updatePage(_page2, 'new', 'old', pModelUser1, options)) // from GRANT_OWNER to GRANT_USER_GROUP(userGroupIdPModelIsolate)
  1305. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  1306. const page1 = await Page.findById(_page1._id);
  1307. const page2 = await Page.findById(_page2._id);
  1308. expect(page1).toBeTruthy();
  1309. expect(page1).toBeTruthy();
  1310. expect(page2.grant).toBe(Page.GRANT_OWNER); // should be the same before the update
  1311. expect(page2.grantedUsers).toStrictEqual([pModelUser1._id]); // should be the same before the update
  1312. expect(page2.grantedGroups.length).toBe(0); // no group should be set
  1313. });
  1314. test('Fail to change to GRANT_USER_GROUP if the group to set is an ancestor of the parent page group', async() => {
  1315. // path
  1316. const _path1 = '/mup33_C';
  1317. const _path2 = '/mup33_C/mup34_owner';
  1318. // page
  1319. const _page1 = await Page.findOne({ path: _path1, grant: Page.GRANT_USER_GROUP, grantedGroups: { $elemMatch: { item: userGroupIdPModelC } } }); // groupC
  1320. const _page2 = await Page.findOne({ // update target
  1321. path: _path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser3], parent: _page1._id,
  1322. });
  1323. expect(_page1).toBeTruthy();
  1324. expect(_page2).toBeTruthy();
  1325. const options = {
  1326. grant: Page.GRANT_USER_GROUP,
  1327. grantUserGroupIds: [
  1328. { item: userGroupIdPModelA, type: GroupType.userGroup },
  1329. { item: externalUserGroupIdPModelA, type: GroupType.externalUserGroup },
  1330. ],
  1331. };
  1332. // Group relation(parent -> child): userGroupIdPModelA -> userGroupIdPModelB -> userGroupIdPModelC
  1333. // this should fail because the groupC is a descendant of groupA
  1334. await expect(updatePage(_page2, 'new', 'old', pModelUser3, options)) // from GRANT_OWNER to GRANT_USER_GROUP(userGroupIdPModelA)
  1335. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  1336. const page1 = await Page.findById(_page1._id);
  1337. const page2 = await Page.findById(_page2._id);
  1338. expect(page1).toBeTruthy();
  1339. expect(page2).toBeTruthy();
  1340. expect(page2.grant).toBe(Page.GRANT_OWNER); // should be the same before the update
  1341. expect(page2.grantedUsers).toStrictEqual([pModelUser3._id]); // should be the same before the update
  1342. expect(page2.grantedGroups.length).toBe(0); // no group should be set
  1343. });
  1344. });
  1345. describe('update grant of a page under a page with GRANT_OWNER', () => {
  1346. test('Fail to change from GRNAT_OWNER', async() => {
  1347. // path
  1348. const path1 = '/mup35_owner';
  1349. const path2 = '/mup35_owner/mup36_owner';
  1350. // page
  1351. const _page1 = await Page.findOne({ path: path1, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1] });
  1352. const _page2 = await Page.findOne({ // update target
  1353. path: path2, grant: Page.GRANT_OWNER, grantedUsers: [pModelUser1], parent: _page1._id,
  1354. });
  1355. expect(_page1).toBeTruthy();
  1356. expect(_page2).toBeTruthy();
  1357. const options = { grant: Page.GRANT_USER_GROUP, grantUserGroupIds: [{ item: userGroupIdPModelA, type: GroupType.userGroup }] };
  1358. await expect(updatePage(_page2, 'new', 'old', pModelUser1, options)) // from GRANT_OWNER to GRANT_USER_GROUP(userGroupIdPModelA)
  1359. .rejects.toThrow(new Error('The selected grant or grantedGroup is not assignable to this page.'));
  1360. const page1 = await Page.findById(_page1.id);
  1361. const page2 = await Page.findById(_page2.id);
  1362. expect(page1).toBeTruthy();
  1363. expect(page2).toBeTruthy();
  1364. expect(page2.grant).toBe(Page.GRANT_OWNER); // should be the same before the update
  1365. expect(page2.grantedUsers).toStrictEqual([pModelUser1._id]); // should be the same before the update
  1366. expect(page2.grantedGroups.length).toBe(0); // no group should be set
  1367. });
  1368. });
  1369. });
  1370. });
  1371. // see: https://dev.growi.org/635a314eac6bcd85cbf359fc about the specification
  1372. describe('updatePage with overwriteScopesOfDescendants true', () => {
  1373. test('(case 1) it should update all granted descendant pages when update grant is GRANT_PUBLIC', async() => {
  1374. const upodPagegAB = await Page.findOne({ path: '/gAB_upod_1' });
  1375. const upodPagegB = await Page.findOne({ path: '/gAB_upod_1/gB_upod_1' });
  1376. const upodPageonlyB = await Page.findOne({ path: '/gAB_upod_1/onlyB_upod_1' });
  1377. expect(upodPagegAB).not.toBeNull();
  1378. expect(upodPagegB).not.toBeNull();
  1379. expect(upodPageonlyB).not.toBeNull();
  1380. expect(upodPagegAB.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1381. expect(upodPagegB.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1382. expect(upodPageonlyB.grant).toBe(PageGrant.GRANT_OWNER);
  1383. // Update
  1384. const options = {
  1385. grant: PageGrant.GRANT_PUBLIC,
  1386. overwriteScopesOfDescendants: true,
  1387. };
  1388. const updatedPage = await updatePage(upodPagegAB, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1389. const upodPagegBUpdated = await Page.findOne({ path: '/gAB_upod_1/gB_upod_1' });
  1390. const upodPageonlyBUpdated = await Page.findOne({ path: '/gAB_upod_1/onlyB_upod_1' });
  1391. // Changed
  1392. const newGrant = PageGrant.GRANT_PUBLIC;
  1393. expect(updatedPage.grant).toBe(newGrant);
  1394. // Not changed
  1395. expect(upodPagegBUpdated.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1396. expect(upodPagegBUpdated.grantedGroups).toStrictEqual(upodPagegB.grantedGroups);
  1397. expect(upodPageonlyBUpdated.grant).toBe(PageGrant.GRANT_OWNER);
  1398. expect(upodPageonlyBUpdated.grantedUsers).toStrictEqual(upodPageonlyB.grantedUsers);
  1399. });
  1400. test('(case 2) it should update all granted descendant pages when all descendant pages are granted by the operator', async() => {
  1401. const upodPagePublic = await Page.findOne({ path: '/public_upod_2' });
  1402. const upodPagegA = await Page.findOne({ path: '/public_upod_2/gA_upod_2' });
  1403. const upodPagegAIsolated = await Page.findOne({ path: '/public_upod_2/gAIsolated_upod_2' });
  1404. const upodPageonlyA = await Page.findOne({ path: '/public_upod_2/onlyA_upod_2' });
  1405. expect(upodPagePublic).not.toBeNull();
  1406. expect(upodPagegA).not.toBeNull();
  1407. expect(upodPagegAIsolated).not.toBeNull();
  1408. expect(upodPageonlyA).not.toBeNull();
  1409. expect(upodPagePublic.grant).toBe(PageGrant.GRANT_PUBLIC);
  1410. expect(upodPagegA.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1411. expect(upodPagegAIsolated.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1412. expect(upodPageonlyA.grant).toBe(PageGrant.GRANT_OWNER);
  1413. // Update
  1414. const options = {
  1415. grant: PageGrant.GRANT_OWNER,
  1416. overwriteScopesOfDescendants: true,
  1417. };
  1418. const updatedPage = await updatePage(upodPagePublic, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1419. const upodPagegAUpdated = await Page.findOne({ path: '/public_upod_2/gA_upod_2' });
  1420. const upodPagegAIsolatedUpdated = await Page.findOne({ path: '/public_upod_2/gAIsolated_upod_2' });
  1421. const upodPageonlyAUpdated = await Page.findOne({ path: '/public_upod_2/onlyA_upod_2' });
  1422. // Changed
  1423. const newGrant = PageGrant.GRANT_OWNER;
  1424. const newGrantedUsers = [upodUserA._id];
  1425. expect(updatedPage.grant).toBe(newGrant);
  1426. expect(updatedPage.grantedUsers).toStrictEqual(newGrantedUsers);
  1427. expect(upodPagegAUpdated.grant).toBe(newGrant);
  1428. expect(upodPagegAUpdated.grantedUsers).toStrictEqual(newGrantedUsers);
  1429. expect(upodPagegAIsolatedUpdated.grant).toBe(newGrant);
  1430. expect(upodPagegAIsolatedUpdated.grantedUsers).toStrictEqual(newGrantedUsers);
  1431. expect(upodPageonlyAUpdated.grant).toBe(newGrant);
  1432. expect(upodPageonlyAUpdated.grantedUsers).toStrictEqual(newGrantedUsers);
  1433. });
  1434. test(`(case 3) it should update all granted descendant pages when update grant is GRANT_USER_GROUP
  1435. , all user groups of descendants are the children or itself of the update user group
  1436. , and all users of descendants belong to the update user group`, async() => {
  1437. const upodPagePublic = await Page.findOne({ path: '/public_upod_3' });
  1438. const upodPagegAB = await Page.findOne({ path: '/public_upod_3/gAB_upod_3' });
  1439. const upodPagegB = await Page.findOne({ path: '/public_upod_3/gB_upod_3' });
  1440. const upodPageonlyB = await Page.findOne({ path: '/public_upod_3/onlyB_upod_3' });
  1441. expect(upodPagePublic).not.toBeNull();
  1442. expect(upodPagegAB).not.toBeNull();
  1443. expect(upodPagegB).not.toBeNull();
  1444. expect(upodPageonlyB).not.toBeNull();
  1445. expect(upodPagePublic.grant).toBe(PageGrant.GRANT_PUBLIC);
  1446. expect(upodPagegAB.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1447. expect(upodPagegB.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1448. expect(upodPageonlyB.grant).toBe(PageGrant.GRANT_OWNER);
  1449. // Update
  1450. const options = {
  1451. grant: PageGrant.GRANT_USER_GROUP,
  1452. grantUserGroupIds: [
  1453. { item: upodUserGroupIdAB, type: GroupType.userGroup },
  1454. { item: upodExternalUserGroupIdAB, type: GroupType.externalUserGroup },
  1455. ],
  1456. overwriteScopesOfDescendants: true,
  1457. };
  1458. const updatedPage = await updatePage(upodPagePublic, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1459. const upodPagegABUpdated = await Page.findOne({ path: '/public_upod_3/gAB_upod_3' });
  1460. const upodPagegBUpdated = await Page.findOne({ path: '/public_upod_3/gB_upod_3' });
  1461. const upodPageonlyBUpdated = await Page.findOne({ path: '/public_upod_3/onlyB_upod_3' });
  1462. // Changed
  1463. const newGrant = PageGrant.GRANT_USER_GROUP;
  1464. const newGrantedGroups = [
  1465. { item: upodUserGroupIdAB, type: GroupType.userGroup },
  1466. { item: upodExternalUserGroupIdAB, type: GroupType.externalUserGroup },
  1467. ];
  1468. expect(updatedPage.grant).toBe(newGrant);
  1469. expect(normalizeGrantedGroups(updatedPage.grantedGroups)).toStrictEqual(newGrantedGroups);
  1470. expect(upodPagegABUpdated.grant).toBe(newGrant);
  1471. expect(normalizeGrantedGroups(upodPagegABUpdated.grantedGroups)).toStrictEqual(newGrantedGroups);
  1472. // Not changed
  1473. expect(upodPagegBUpdated.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1474. expect(upodPagegBUpdated.grantedGroups).toStrictEqual(upodPagegB.grantedGroups);
  1475. expect(upodPageonlyBUpdated.grant).toBe(PageGrant.GRANT_OWNER);
  1476. expect(upodPageonlyBUpdated.grantedUsers).toStrictEqual(upodPageonlyB.grantedUsers);
  1477. });
  1478. test(`(case 4) it should throw when some of descendants is not granted
  1479. , update grant is GRANT_USER_GROUP
  1480. , and some of user groups of descendants are not children or itself of the update user group`, async() => {
  1481. const upodPagePublic = await Page.findOne({ path: '/public_upod_4' });
  1482. const upodPagegA = await Page.findOne({ path: '/public_upod_4/gA_upod_4' });
  1483. const upodPagegC = await Page.findOne({ path: '/public_upod_4/gC_upod_4' });
  1484. expect(upodPagePublic).not.toBeNull();
  1485. expect(upodPagegA).not.toBeNull();
  1486. expect(upodPagegC).not.toBeNull();
  1487. expect(upodPagePublic.grant).toBe(PageGrant.GRANT_PUBLIC);
  1488. expect(upodPagegA.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1489. expect(upodPagegC.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1490. // Update
  1491. const options = {
  1492. grant: PageGrant.GRANT_USER_GROUP,
  1493. grantUserGroupIds: [
  1494. { item: upodUserGroupIdAB, type: GroupType.userGroup },
  1495. { item: upodExternalUserGroupIdAB, type: GroupType.externalUserGroup },
  1496. ],
  1497. overwriteScopesOfDescendants: true,
  1498. };
  1499. const updatedPagePromise = updatePage(upodPagePublic, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1500. await expect(updatedPagePromise).rejects.toThrowError();
  1501. });
  1502. test(`(case 5) it should throw when some of descendants is not granted
  1503. , update grant is GRANT_USER_GROUP
  1504. , and some of users of descendants does NOT belong to the update user group`, async() => {
  1505. const upodPagePublic = await Page.findOne({ path: '/public_upod_5' });
  1506. const upodPagegA = await Page.findOne({ path: '/public_upod_5/gA_upod_5' });
  1507. const upodPageonlyC = await Page.findOne({ path: '/public_upod_5/onlyC_upod_5' });
  1508. expect(upodPagePublic).not.toBeNull();
  1509. expect(upodPagegA).not.toBeNull();
  1510. expect(upodPageonlyC).not.toBeNull();
  1511. expect(upodPagePublic.grant).toBe(PageGrant.GRANT_PUBLIC);
  1512. expect(upodPagegA.grant).toBe(PageGrant.GRANT_USER_GROUP);
  1513. expect(upodPageonlyC.grant).toBe(PageGrant.GRANT_OWNER);
  1514. // Update
  1515. const options = {
  1516. grant: PageGrant.GRANT_USER_GROUP,
  1517. grantUserGroupIds: [
  1518. { item: upodUserGroupIdAB, type: GroupType.userGroup },
  1519. { item: upodExternalUserGroupIdAB, type: GroupType.externalUserGroup },
  1520. ],
  1521. overwriteScopesOfDescendants: true,
  1522. };
  1523. const updatedPagePromise = updatePage(upodPagePublic, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1524. await expect(updatedPagePromise).rejects.toThrowError();
  1525. });
  1526. test('(case 6) it should throw when some of descendants is not granted and update grant is GRANT_OWNER', async() => {
  1527. const upodPagePublic = await Page.findOne({ path: '/public_upod_6' });
  1528. const upodPageonlyC = await Page.findOne({ path: '/public_upod_6/onlyC_upod_6' });
  1529. expect(upodPagePublic).not.toBeNull();
  1530. expect(upodPageonlyC).not.toBeNull();
  1531. expect(upodPagePublic.grant).toBe(PageGrant.GRANT_PUBLIC);
  1532. expect(upodPageonlyC.grant).toBe(PageGrant.GRANT_OWNER);
  1533. // Update
  1534. const options = {
  1535. grant: PageGrant.GRANT_USER_GROUP,
  1536. grantUserGroupIds: [
  1537. { item: upodUserGroupIdAB, type: GroupType.userGroup },
  1538. { item: upodExternalUserGroupIdAB, type: GroupType.externalUserGroup },
  1539. ],
  1540. overwriteScopesOfDescendants: true,
  1541. };
  1542. const updatedPagePromise = updatePage(upodPagePublic, 'newRevisionBody', 'oldRevisionBody', upodUserA, options);
  1543. await expect(updatedPagePromise).rejects.toThrowError();
  1544. });
  1545. });
  1546. });