v5.page.test.js 67 KB

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