page-grant.test.ts 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
  1. import { GroupType, type IPage, PageGrant } from '@growi/core';
  2. import mongoose from 'mongoose';
  3. import { ExternalGroupProviderType } from '../../../src/features/external-user-group/interfaces/external-user-group';
  4. import ExternalUserGroup, {
  5. type ExternalUserGroupDocument,
  6. } from '../../../src/features/external-user-group/server/models/external-user-group';
  7. import ExternalUserGroupRelation from '../../../src/features/external-user-group/server/models/external-user-group-relation';
  8. import { UserGroupPageGrantStatus } from '../../../src/interfaces/page';
  9. import type Crowi from '../../../src/server/crowi';
  10. import type { PageDocument, PageModel } from '../../../src/server/models/page';
  11. import UserGroup, {
  12. type UserGroupDocument,
  13. } from '../../../src/server/models/user-group';
  14. import UserGroupRelation from '../../../src/server/models/user-group-relation';
  15. import type { IPageGrantService } from '../../../src/server/service/page-grant';
  16. import { getInstance } from '../setup-crowi';
  17. /*
  18. * There are 3 grant types to test.
  19. * GRANT_PUBLIC, GRANT_OWNER, GRANT_USER_GROUP
  20. */
  21. describe('PageGrantService', () => {
  22. /*
  23. * models
  24. */
  25. // biome-ignore lint/suspicious/noImplicitAnyLet: ignore
  26. let User;
  27. let Page: PageModel;
  28. /*
  29. * global instances
  30. */
  31. let crowi: Crowi;
  32. let pageGrantService: IPageGrantService;
  33. // biome-ignore lint/suspicious/noImplicitAnyLet: ignore
  34. let user1;
  35. // biome-ignore lint/suspicious/noImplicitAnyLet: ignore
  36. let user2;
  37. let groupParent: UserGroupDocument;
  38. let groupChild: UserGroupDocument;
  39. let differentTreeGroup: UserGroupDocument;
  40. let externalGroupParent: ExternalUserGroupDocument;
  41. let externalGroupChild: ExternalUserGroupDocument;
  42. const userGroupIdParent = new mongoose.Types.ObjectId();
  43. const externalUserGroupIdParent = new mongoose.Types.ObjectId();
  44. let rootPage: PageDocument;
  45. let rootPublicPage: PageDocument;
  46. let rootOnlyMePage: PageDocument;
  47. let rootOnlyInsideTheGroup: PageDocument;
  48. let emptyPage1: PageDocument;
  49. let emptyPage2: PageDocument;
  50. let emptyPage3: PageDocument;
  51. const emptyPagePath1 = '/E1';
  52. const emptyPagePath2 = '/E2';
  53. const emptyPagePath3 = '/E3';
  54. let multipleGroupTreesAndUsersPage: PageDocument;
  55. const pageRootPublicPath = '/Public';
  56. const pageRootGroupParentPath = '/GroupParent';
  57. const pageMultipleGroupTreesAndUsersPath = '/MultipleGroupTreesAndUsers';
  58. const v4PageRootOnlyMePagePath = '/v4OnlyMe';
  59. const v4PageRootAnyoneWithTheLinkPagePath = '/v4AnyoneWithTheLink';
  60. const v4PageRootOnlyInsideTheGroupPagePath = '/v4OnlyInsideTheGroup';
  61. const pagePublicOnlyMePath = `${pageRootPublicPath}/OnlyMe`;
  62. const pagePublicAnyoneWithTheLinkPath = `${pageRootPublicPath}/AnyoneWithTheLink`;
  63. const pagePublicOnlyInsideTheGroupPath = `${pageRootPublicPath}/OnlyInsideTheGroup`;
  64. const pageOnlyMePublicPath = `${v4PageRootOnlyMePagePath}/Public`;
  65. const pageOnlyMeAnyoneWithTheLinkPath = `${v4PageRootOnlyMePagePath}/AnyoneWithTheLink`;
  66. const pageOnlyMeOnlyInsideTheGroupPath = `${v4PageRootOnlyMePagePath}/OnlyInsideTheGroup`;
  67. const pageOnlyInsideTheGroupPublicPath = `${v4PageRootOnlyInsideTheGroupPagePath}/Public`;
  68. const pageOnlyInsideTheGroupOnlyMePath = `${v4PageRootOnlyInsideTheGroupPagePath}/OnlyMe`;
  69. const pageOnlyInsideTheGroupAnyoneWithTheLinkPath = `${v4PageRootOnlyInsideTheGroupPagePath}/AnyoneWithTheLink`;
  70. const pageE1PublicPath = '/E1/Public';
  71. const pageE2User1Path = '/E2/User1';
  72. const pageE3GroupParentPath = '/E3/GroupParent';
  73. const pageE3GroupChildPath = '/E3/GroupChild';
  74. const pageE3User1Path = '/E3/User1';
  75. // getPageGroupGrantData test data
  76. // biome-ignore lint/suspicious/noImplicitAnyLet: ignore
  77. let user3;
  78. let groupGrantDataTestChildPagePath: string;
  79. let groupGrantDataTestParentUserGroupId: mongoose.Types.ObjectId;
  80. let groupGrantDataTestChildUserGroupId: mongoose.Types.ObjectId;
  81. let groupGrantDataTestExternalUserGroupId: mongoose.Types.ObjectId;
  82. let groupGrantDataTestExternalUserGroupId2: mongoose.Types.ObjectId;
  83. const createDocumentsToTestIsGrantNormalized = async () => {
  84. // Users
  85. await User.insertMany([
  86. { name: 'User1', username: 'User1', email: 'user1@example.com' },
  87. { name: 'User2', username: 'User2', email: 'user2@example.com' },
  88. ]);
  89. user1 = await User.findOne({ username: 'User1' });
  90. user2 = await User.findOne({ username: 'User2' });
  91. await UserGroup.insertMany([
  92. {
  93. _id: userGroupIdParent,
  94. name: 'GroupParent',
  95. parent: null,
  96. },
  97. {
  98. name: 'GroupChild',
  99. parent: userGroupIdParent,
  100. },
  101. {
  102. name: 'DifferentTreeGroup',
  103. parent: null,
  104. },
  105. ]);
  106. groupParent = (await UserGroup.findOne({ name: 'GroupParent' }))!;
  107. groupChild = (await UserGroup.findOne({ name: 'GroupChild' }))!;
  108. differentTreeGroup = (await UserGroup.findOne({
  109. name: 'DifferentTreeGroup',
  110. }))!;
  111. // UserGroupRelations
  112. await UserGroupRelation.insertMany([
  113. {
  114. relatedGroup: groupParent._id,
  115. relatedUser: user1._id,
  116. },
  117. {
  118. relatedGroup: groupParent._id,
  119. relatedUser: user2._id,
  120. },
  121. {
  122. relatedGroup: groupChild._id,
  123. relatedUser: user1._id,
  124. },
  125. {
  126. relatedGroup: differentTreeGroup._id,
  127. relatedUser: user1._id,
  128. },
  129. ]);
  130. await ExternalUserGroup.insertMany([
  131. {
  132. _id: externalUserGroupIdParent,
  133. name: 'ExternalGroupParent',
  134. externalId: 'ExternalGroupParent',
  135. provider: ExternalGroupProviderType.ldap,
  136. parent: null,
  137. },
  138. {
  139. name: 'ExternalGroupChild',
  140. externalId: 'ExternalGroupChild',
  141. provider: ExternalGroupProviderType.ldap,
  142. parent: externalUserGroupIdParent,
  143. },
  144. ]);
  145. externalGroupParent = await ExternalUserGroup.findOne({
  146. name: 'ExternalGroupParent',
  147. });
  148. externalGroupChild = await ExternalUserGroup.findOne({
  149. name: 'ExternalGroupChild',
  150. });
  151. await ExternalUserGroupRelation.insertMany([
  152. {
  153. relatedGroup: externalGroupParent._id,
  154. relatedUser: user1._id,
  155. },
  156. {
  157. relatedGroup: externalGroupParent._id,
  158. relatedUser: user2._id,
  159. },
  160. {
  161. relatedGroup: externalGroupChild._id,
  162. relatedUser: user1._id,
  163. },
  164. ]);
  165. // Root page (Depth: 0)
  166. rootPage = (await Page.findOne({ path: '/' }))!;
  167. // Empty pages (Depth: 1)
  168. await Page.insertMany([
  169. {
  170. path: emptyPagePath1,
  171. grant: Page.GRANT_PUBLIC,
  172. isEmpty: true,
  173. parent: rootPage._id,
  174. },
  175. {
  176. path: emptyPagePath2,
  177. grant: Page.GRANT_PUBLIC,
  178. isEmpty: true,
  179. parent: rootPage._id,
  180. },
  181. {
  182. path: emptyPagePath3,
  183. grant: Page.GRANT_PUBLIC,
  184. isEmpty: true,
  185. parent: rootPage._id,
  186. },
  187. {
  188. path: pageRootPublicPath,
  189. grant: Page.GRANT_PUBLIC,
  190. creator: user1,
  191. lastUpdateUser: user1,
  192. grantedUsers: null,
  193. grantedGroups: [],
  194. parent: rootPage._id,
  195. },
  196. {
  197. path: pageRootGroupParentPath,
  198. grant: Page.GRANT_USER_GROUP,
  199. creator: user1,
  200. lastUpdateUser: user1,
  201. grantedUsers: null,
  202. grantedGroups: [
  203. { item: groupParent._id, type: GroupType.userGroup },
  204. { item: externalGroupParent._id, type: GroupType.externalUserGroup },
  205. ],
  206. parent: rootPage._id,
  207. },
  208. {
  209. path: pageMultipleGroupTreesAndUsersPath,
  210. grant: Page.GRANT_USER_GROUP,
  211. creator: user1,
  212. lastUpdateUser: user1,
  213. grantedUsers: null,
  214. grantedGroups: [
  215. { item: groupParent._id, type: GroupType.userGroup },
  216. { item: differentTreeGroup._id, type: GroupType.userGroup },
  217. ],
  218. parent: null,
  219. },
  220. ]);
  221. multipleGroupTreesAndUsersPage = (await Page.findOne({
  222. path: pageMultipleGroupTreesAndUsersPath,
  223. }))!;
  224. await Page.insertMany([
  225. // Root Page
  226. {
  227. path: rootPage,
  228. grant: Page.GRANT_PUBLIC,
  229. parent: null,
  230. },
  231. // OnlyMe v4
  232. {
  233. path: v4PageRootOnlyMePagePath,
  234. grant: Page.GRANT_OWNER,
  235. grantedUsers: [user1._id],
  236. parent: null,
  237. },
  238. // AnyoneWithTheLink v4
  239. {
  240. path: v4PageRootAnyoneWithTheLinkPagePath,
  241. grant: Page.GRANT_RESTRICTED,
  242. parent: null,
  243. },
  244. // OnlyInsideTheGroup v4
  245. {
  246. path: v4PageRootOnlyInsideTheGroupPagePath,
  247. grant: Page.GRANT_USER_GROUP,
  248. parent: null,
  249. grantedGroups: [
  250. { item: groupParent._id, type: GroupType.userGroup },
  251. { item: externalGroupParent._id, type: GroupType.externalUserGroup },
  252. ],
  253. },
  254. ]);
  255. rootPublicPage = (await Page.findOne({ path: pageRootPublicPath }))!;
  256. rootOnlyMePage = (await Page.findOne({ path: v4PageRootOnlyMePagePath }))!;
  257. rootOnlyInsideTheGroup = (await Page.findOne({
  258. path: v4PageRootOnlyInsideTheGroupPagePath,
  259. }))!;
  260. // Leaf pages (Depth: 2)
  261. await Page.insertMany([
  262. /*
  263. * Parent is public
  264. */
  265. {
  266. path: pagePublicOnlyMePath,
  267. grant: Page.GRANT_OWNER,
  268. parent: rootPublicPage._id,
  269. },
  270. {
  271. path: pagePublicAnyoneWithTheLinkPath,
  272. grant: Page.GRANT_RESTRICTED,
  273. parent: rootPublicPage._id,
  274. },
  275. {
  276. path: pagePublicOnlyInsideTheGroupPath,
  277. grant: Page.GRANT_USER_GROUP,
  278. parent: rootPublicPage._id,
  279. },
  280. /*
  281. * Parent is onlyMe
  282. */
  283. {
  284. path: pageOnlyMePublicPath,
  285. grant: Page.GRANT_PUBLIC,
  286. parent: rootOnlyMePage._id,
  287. },
  288. {
  289. path: pageOnlyMeAnyoneWithTheLinkPath,
  290. grant: Page.GRANT_RESTRICTED,
  291. parent: rootOnlyMePage._id,
  292. },
  293. {
  294. path: pageOnlyMeOnlyInsideTheGroupPath,
  295. grant: Page.GRANT_USER_GROUP,
  296. parent: rootOnlyMePage._id,
  297. },
  298. /*
  299. * Parent is OnlyInsideTheGroup
  300. */
  301. {
  302. path: pageOnlyInsideTheGroupPublicPath,
  303. grant: Page.GRANT_PUBLIC,
  304. parent: rootOnlyInsideTheGroup._id,
  305. },
  306. {
  307. path: pageOnlyInsideTheGroupOnlyMePath,
  308. grant: Page.GRANT_PUBLIC,
  309. parent: rootOnlyInsideTheGroup._id,
  310. },
  311. {
  312. path: pageOnlyInsideTheGroupAnyoneWithTheLinkPath,
  313. grant: Page.GRANT_PUBLIC,
  314. parent: rootOnlyInsideTheGroup._id,
  315. },
  316. ]);
  317. emptyPage1 = (await Page.findOne({ path: emptyPagePath1 }))!;
  318. emptyPage2 = (await Page.findOne({ path: emptyPagePath2 }))!;
  319. emptyPage3 = (await Page.findOne({ path: emptyPagePath3 }))!;
  320. // Leaf pages (Depth: 2)
  321. await Page.insertMany([
  322. {
  323. path: pageE1PublicPath,
  324. grant: Page.GRANT_PUBLIC,
  325. creator: user1,
  326. lastUpdateUser: user1,
  327. grantedUsers: null,
  328. grantedGroups: [],
  329. parent: emptyPage1._id,
  330. },
  331. {
  332. path: pageE2User1Path,
  333. grant: Page.GRANT_OWNER,
  334. creator: user1,
  335. lastUpdateUser: user1,
  336. grantedUsers: [user1._id],
  337. grantedGroups: [],
  338. parent: emptyPage2._id,
  339. },
  340. {
  341. path: pageE3GroupParentPath,
  342. grant: Page.GRANT_USER_GROUP,
  343. creator: user1,
  344. lastUpdateUser: user1,
  345. grantedUsers: null,
  346. grantedGroups: [
  347. { item: groupParent._id, type: GroupType.userGroup },
  348. { item: externalGroupParent._id, type: GroupType.externalUserGroup },
  349. ],
  350. parent: emptyPage3._id,
  351. },
  352. {
  353. path: pageE3GroupChildPath,
  354. grant: Page.GRANT_USER_GROUP,
  355. creator: user1,
  356. lastUpdateUser: user1,
  357. grantedUsers: null,
  358. grantedGroups: [
  359. { item: groupChild._id, type: GroupType.userGroup },
  360. { item: externalGroupChild._id, type: GroupType.externalUserGroup },
  361. ],
  362. parent: emptyPage3._id,
  363. },
  364. {
  365. path: pageE3User1Path,
  366. grant: Page.GRANT_OWNER,
  367. creator: user1,
  368. lastUpdateUser: user1,
  369. grantedUsers: [user1._id],
  370. grantedGroups: [],
  371. parent: emptyPage3._id,
  372. },
  373. ]);
  374. };
  375. const createDocumentsToTestGetPageGroupGrantData = async () => {
  376. await User.insertMany([
  377. { name: 'User3', username: 'User3', email: 'user3@example.com' },
  378. ]);
  379. user3 = await User.findOne({ username: 'User3' });
  380. groupGrantDataTestParentUserGroupId = new mongoose.Types.ObjectId();
  381. groupGrantDataTestChildUserGroupId = new mongoose.Types.ObjectId();
  382. await UserGroup.insertMany([
  383. {
  384. _id: groupGrantDataTestParentUserGroupId, // cannotGrant
  385. name: 'groupGrantDataTestParentGroup',
  386. parent: null,
  387. },
  388. {
  389. _id: groupGrantDataTestChildUserGroupId, // isGranted
  390. name: 'groupGrantDataTestChildGroup',
  391. parent: groupGrantDataTestParentUserGroupId,
  392. },
  393. ]);
  394. await UserGroupRelation.insertMany([
  395. {
  396. relatedGroup: groupGrantDataTestParentUserGroupId._id,
  397. relatedUser: user3._id,
  398. },
  399. {
  400. relatedGroup: groupGrantDataTestChildUserGroupId._id,
  401. relatedUser: user3._id,
  402. },
  403. ]);
  404. groupGrantDataTestExternalUserGroupId = new mongoose.Types.ObjectId();
  405. groupGrantDataTestExternalUserGroupId2 = new mongoose.Types.ObjectId();
  406. await ExternalUserGroup.insertMany([
  407. {
  408. _id: groupGrantDataTestExternalUserGroupId,
  409. name: 'groupGrantDataTestExternalGroup',
  410. externalId: 'groupGrantDataTestExternalGroup',
  411. provider: ExternalGroupProviderType.ldap,
  412. parent: null,
  413. },
  414. {
  415. _id: groupGrantDataTestExternalUserGroupId2,
  416. name: 'groupGrantDataTestExternalGroup2',
  417. externalId: 'groupGrantDataTestExternalGroup2',
  418. provider: ExternalGroupProviderType.ldap,
  419. parent: null,
  420. },
  421. ]);
  422. await ExternalUserGroupRelation.insertMany([
  423. {
  424. relatedGroup: groupGrantDataTestExternalUserGroupId._id,
  425. relatedUser: user3._id,
  426. },
  427. ]);
  428. const groupGrantDataTestParentPagePath = '/groupGrantDataTestParentPage';
  429. const groupGrantDataTestParentPageId = new mongoose.Types.ObjectId();
  430. groupGrantDataTestChildPagePath =
  431. '/groupGrantDataTestParentPage/groupGrantDataTestChildPagePath';
  432. await Page.insertMany([
  433. {
  434. _id: groupGrantDataTestParentPageId,
  435. path: groupGrantDataTestParentPagePath,
  436. grant: Page.GRANT_USER_GROUP,
  437. creator: user3._id,
  438. lastUpdateUser: user3._id,
  439. grantedUsers: null,
  440. grantedGroups: [
  441. {
  442. item: groupGrantDataTestChildUserGroupId._id,
  443. type: GroupType.userGroup,
  444. },
  445. {
  446. item: groupGrantDataTestExternalUserGroupId._id,
  447. type: GroupType.externalUserGroup,
  448. },
  449. {
  450. item: groupGrantDataTestExternalUserGroupId2._id,
  451. type: GroupType.externalUserGroup,
  452. },
  453. ],
  454. parent: rootPage._id,
  455. },
  456. {
  457. path: groupGrantDataTestChildPagePath,
  458. grant: Page.GRANT_USER_GROUP,
  459. creator: user3._id,
  460. lastUpdateUser: user3._id,
  461. grantedUsers: null,
  462. grantedGroups: [
  463. {
  464. item: groupGrantDataTestChildUserGroupId._id,
  465. type: GroupType.userGroup,
  466. },
  467. {
  468. item: groupGrantDataTestExternalUserGroupId2._id,
  469. type: GroupType.externalUserGroup,
  470. },
  471. ],
  472. parent: groupGrantDataTestParentPageId,
  473. },
  474. ]);
  475. };
  476. /*
  477. * prepare before all tests
  478. */
  479. beforeAll(async () => {
  480. crowi = await getInstance();
  481. pageGrantService = crowi.pageGrantService;
  482. User = mongoose.model('User');
  483. Page = mongoose.model<IPage, PageModel>('Page');
  484. rootPage = (await Page.findOne({ path: '/' }))!;
  485. await createDocumentsToTestIsGrantNormalized();
  486. await createDocumentsToTestGetPageGroupGrantData();
  487. });
  488. describe('Test isGrantNormalized method with shouldCheckDescendants false', () => {
  489. test('Should return true when Ancestor: root, Target: public', async () => {
  490. const targetPath = '/NEW';
  491. const grant = Page.GRANT_PUBLIC;
  492. const grantedUserIds = undefined;
  493. const grantedGroupIds = [];
  494. const shouldCheckDescendants = false;
  495. const result = await pageGrantService.isGrantNormalized(
  496. user1,
  497. targetPath,
  498. grant,
  499. grantedUserIds,
  500. grantedGroupIds,
  501. shouldCheckDescendants,
  502. );
  503. expect(result).toBe(true);
  504. });
  505. test('Should return true when Ancestor: root, Target: GroupParent', async () => {
  506. const targetPath = '/NEW_GroupParent';
  507. const grant = Page.GRANT_USER_GROUP;
  508. const grantedUserIds = undefined;
  509. const grantedGroupIds = [
  510. { item: groupParent._id, type: GroupType.userGroup },
  511. { item: externalGroupParent._id, type: GroupType.externalUserGroup },
  512. ];
  513. const shouldCheckDescendants = false;
  514. const result = await pageGrantService.isGrantNormalized(
  515. user1,
  516. targetPath,
  517. grant,
  518. grantedUserIds,
  519. grantedGroupIds,
  520. shouldCheckDescendants,
  521. );
  522. expect(result).toBe(true);
  523. });
  524. test('Should return true when Ancestor: under-root public, Target: public', async () => {
  525. const targetPath = `${pageRootPublicPath}/NEW`;
  526. const grant = Page.GRANT_PUBLIC;
  527. const grantedUserIds = undefined;
  528. const grantedGroupIds = [];
  529. const shouldCheckDescendants = false;
  530. const result = await pageGrantService.isGrantNormalized(
  531. user1,
  532. targetPath,
  533. grant,
  534. grantedUserIds,
  535. grantedGroupIds,
  536. shouldCheckDescendants,
  537. );
  538. expect(result).toBe(true);
  539. });
  540. test('Should return true when Ancestor: under-root GroupParent, Target: GroupParent', async () => {
  541. const targetPath = `${pageRootGroupParentPath}/NEW`;
  542. const grant = Page.GRANT_USER_GROUP;
  543. const grantedUserIds = undefined;
  544. const grantedGroupIds = [
  545. { item: groupParent._id, type: GroupType.userGroup },
  546. { item: externalGroupParent._id, type: GroupType.externalUserGroup },
  547. ];
  548. const shouldCheckDescendants = false;
  549. const result = await pageGrantService.isGrantNormalized(
  550. user1,
  551. targetPath,
  552. grant,
  553. grantedUserIds,
  554. grantedGroupIds,
  555. shouldCheckDescendants,
  556. );
  557. expect(result).toBe(true);
  558. });
  559. test('Should return true when Ancestor: public, Target: public', async () => {
  560. const targetPath = `${pageE1PublicPath}/NEW`;
  561. const grant = Page.GRANT_PUBLIC;
  562. const grantedUserIds = undefined;
  563. const grantedGroupIds = [];
  564. const shouldCheckDescendants = false;
  565. const result = await pageGrantService.isGrantNormalized(
  566. user1,
  567. targetPath,
  568. grant,
  569. grantedUserIds,
  570. grantedGroupIds,
  571. shouldCheckDescendants,
  572. );
  573. expect(result).toBe(true);
  574. });
  575. test('Should return true when Ancestor: owned by User1, Target: owned by User1', async () => {
  576. const targetPath = `${pageE2User1Path}/NEW`;
  577. const grant = Page.GRANT_OWNER;
  578. const grantedUserIds = [user1._id];
  579. const grantedGroupIds = [];
  580. const shouldCheckDescendants = false;
  581. const result = await pageGrantService.isGrantNormalized(
  582. user1,
  583. targetPath,
  584. grant,
  585. grantedUserIds,
  586. grantedGroupIds,
  587. shouldCheckDescendants,
  588. );
  589. expect(result).toBe(true);
  590. });
  591. test('Should return false when Ancestor: owned by GroupParent, Target: public', async () => {
  592. const targetPath = `${pageE3GroupParentPath}/NEW`;
  593. const grant = Page.GRANT_PUBLIC;
  594. const grantedUserIds = undefined;
  595. const grantedGroupIds = [];
  596. const shouldCheckDescendants = false;
  597. const result = await pageGrantService.isGrantNormalized(
  598. user1,
  599. targetPath,
  600. grant,
  601. grantedUserIds,
  602. grantedGroupIds,
  603. shouldCheckDescendants,
  604. );
  605. expect(result).toBe(false);
  606. });
  607. test('Should return false when Ancestor: owned by GroupChild, Target: GroupParent', async () => {
  608. const targetPath = `${pageE3GroupChildPath}/NEW`;
  609. const grant = Page.GRANT_USER_GROUP;
  610. const grantedUserIds = undefined;
  611. const grantedGroupIds = [
  612. { item: groupParent._id, type: GroupType.userGroup },
  613. { item: externalGroupParent._id, type: GroupType.externalUserGroup },
  614. ];
  615. const shouldCheckDescendants = false;
  616. const result = await pageGrantService.isGrantNormalized(
  617. user1,
  618. targetPath,
  619. grant,
  620. grantedUserIds,
  621. grantedGroupIds,
  622. shouldCheckDescendants,
  623. );
  624. expect(result).toBe(false);
  625. });
  626. });
  627. describe('Test isGrantNormalized method with shouldCheckDescendants true', () => {
  628. test('Should return true when Target: public, Descendant: public', async () => {
  629. const targetPath = emptyPagePath1;
  630. const grant = Page.GRANT_PUBLIC;
  631. const grantedUserIds = undefined;
  632. const grantedGroupIds = [];
  633. const shouldCheckDescendants = true;
  634. const result = await pageGrantService.isGrantNormalized(
  635. user1,
  636. targetPath,
  637. grant,
  638. grantedUserIds,
  639. grantedGroupIds,
  640. shouldCheckDescendants,
  641. );
  642. expect(result).toBe(true);
  643. });
  644. test('Should return true when Target: owned by User1, Descendant: User1 only', async () => {
  645. const targetPath = emptyPagePath2;
  646. const grant = Page.GRANT_OWNER;
  647. const grantedUserIds = [user1._id];
  648. const grantedGroupIds = [];
  649. const shouldCheckDescendants = true;
  650. const result = await pageGrantService.isGrantNormalized(
  651. user1,
  652. targetPath,
  653. grant,
  654. grantedUserIds,
  655. grantedGroupIds,
  656. shouldCheckDescendants,
  657. );
  658. expect(result).toBe(true);
  659. });
  660. test('Should return true when Target: owned by GroupParent, Descendant: GroupParent, GroupChild and User1', async () => {
  661. const targetPath = emptyPagePath3;
  662. const grant = Page.GRANT_USER_GROUP;
  663. const grantedUserIds = undefined;
  664. const grantedGroupIds = [
  665. { item: groupParent._id, type: GroupType.userGroup },
  666. { item: externalGroupParent._id, type: GroupType.externalUserGroup },
  667. ];
  668. const shouldCheckDescendants = true;
  669. const result = await pageGrantService.isGrantNormalized(
  670. user1,
  671. targetPath,
  672. grant,
  673. grantedUserIds,
  674. grantedGroupIds,
  675. shouldCheckDescendants,
  676. );
  677. expect(result).toBe(true);
  678. });
  679. test('Should return false when Target: owned by User1, Descendant: public', async () => {
  680. const targetPath = emptyPagePath1;
  681. const grant = Page.GRANT_OWNER;
  682. const grantedUserIds = [user1._id];
  683. const grantedGroupIds = [];
  684. const shouldCheckDescendants = true;
  685. const result = await pageGrantService.isGrantNormalized(
  686. user1,
  687. targetPath,
  688. grant,
  689. grantedUserIds,
  690. grantedGroupIds,
  691. shouldCheckDescendants,
  692. );
  693. expect(result).toBe(false);
  694. });
  695. });
  696. describe('Test validateGrantChange method', () => {
  697. test('Should return true when Target: completely owned by User1 (belongs to all groups)', async () => {
  698. const grant = Page.GRANT_PUBLIC;
  699. const grantedGroupIds = [];
  700. const result = await pageGrantService.validateGrantChange(
  701. user1,
  702. multipleGroupTreesAndUsersPage.grantedGroups,
  703. grant,
  704. grantedGroupIds,
  705. );
  706. expect(result).toBe(true);
  707. });
  708. test('Should return false when Target: partially owned by User2 (belongs to one of the groups), and change to public grant', async () => {
  709. const grant = Page.GRANT_PUBLIC;
  710. const grantedGroupIds = [];
  711. const result = await pageGrantService.validateGrantChange(
  712. user2,
  713. multipleGroupTreesAndUsersPage.grantedGroups,
  714. grant,
  715. grantedGroupIds,
  716. );
  717. expect(result).toBe(false);
  718. });
  719. test('Should return false when Target: partially owned by User2 (belongs to one of the groups), and change to owner grant', async () => {
  720. const grant = Page.GRANT_OWNER;
  721. const grantedGroupIds = [];
  722. const result = await pageGrantService.validateGrantChange(
  723. user2,
  724. multipleGroupTreesAndUsersPage.grantedGroups,
  725. grant,
  726. grantedGroupIds,
  727. );
  728. expect(result).toBe(false);
  729. });
  730. test('Should return false when Target: partially owned by User2 (belongs to one of the groups), and change to restricted grant', async () => {
  731. const grant = Page.GRANT_RESTRICTED;
  732. const grantedGroupIds = [];
  733. const result = await pageGrantService.validateGrantChange(
  734. user2,
  735. multipleGroupTreesAndUsersPage.grantedGroups,
  736. grant,
  737. grantedGroupIds,
  738. );
  739. expect(result).toBe(false);
  740. });
  741. test('Should return false when Target: partially owned by User2, and change to group grant without any groups of user2', async () => {
  742. const grant = Page.GRANT_USER_GROUP;
  743. const grantedGroupIds = [
  744. { item: differentTreeGroup._id, type: GroupType.userGroup },
  745. ];
  746. const result = await pageGrantService.validateGrantChange(
  747. user2,
  748. multipleGroupTreesAndUsersPage.grantedGroups,
  749. grant,
  750. grantedGroupIds,
  751. );
  752. expect(result).toBe(false);
  753. });
  754. });
  755. describe('Test for calcApplicableGrantData', () => {
  756. test('Only Public is Applicable in case of top page', async () => {
  757. const result = await pageGrantService.calcApplicableGrantData(
  758. rootPage,
  759. user1,
  760. );
  761. expect(result).toStrictEqual({
  762. [PageGrant.GRANT_PUBLIC]: null,
  763. });
  764. });
  765. // parent property of all private pages is null
  766. test('Any grant is allowed if parent is null', async () => {
  767. const userRelatedUserGroups =
  768. await UserGroupRelation.findAllGroupsForUser(user1);
  769. const userRelatedExternalUserGroups =
  770. await ExternalUserGroupRelation.findAllGroupsForUser(user1);
  771. const userRelatedGroups = [
  772. ...userRelatedUserGroups.map((group) => {
  773. return { type: GroupType.userGroup, item: group };
  774. }),
  775. ...userRelatedExternalUserGroups.map((group) => {
  776. return { type: GroupType.externalUserGroup, item: group };
  777. }),
  778. ];
  779. // OnlyMe
  780. const rootOnlyMePage = await Page.findOne({
  781. path: v4PageRootOnlyMePagePath,
  782. });
  783. const rootOnlyMePageRes = await pageGrantService.calcApplicableGrantData(
  784. rootOnlyMePage,
  785. user1,
  786. );
  787. expect(rootOnlyMePageRes).toStrictEqual({
  788. [PageGrant.GRANT_PUBLIC]: null,
  789. [PageGrant.GRANT_RESTRICTED]: null,
  790. [PageGrant.GRANT_OWNER]: null,
  791. [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userRelatedGroups },
  792. });
  793. // AnyoneWithTheLink
  794. const rootAnyoneWithTheLinkPage = await Page.findOne({
  795. path: v4PageRootAnyoneWithTheLinkPagePath,
  796. });
  797. const anyoneWithTheLinkRes =
  798. await pageGrantService.calcApplicableGrantData(
  799. rootAnyoneWithTheLinkPage,
  800. user1,
  801. );
  802. expect(anyoneWithTheLinkRes).toStrictEqual({
  803. [PageGrant.GRANT_PUBLIC]: null,
  804. [PageGrant.GRANT_RESTRICTED]: null,
  805. [PageGrant.GRANT_OWNER]: null,
  806. [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userRelatedGroups },
  807. });
  808. // OnlyInsideTheGroup
  809. const rootOnlyInsideTheGroupPage = await Page.findOne({
  810. path: v4PageRootOnlyInsideTheGroupPagePath,
  811. });
  812. const onlyInsideTheGroupRes =
  813. await pageGrantService.calcApplicableGrantData(
  814. rootOnlyInsideTheGroupPage,
  815. user1,
  816. );
  817. expect(onlyInsideTheGroupRes).toStrictEqual({
  818. [PageGrant.GRANT_PUBLIC]: null,
  819. [PageGrant.GRANT_RESTRICTED]: null,
  820. [PageGrant.GRANT_OWNER]: null,
  821. [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userRelatedGroups },
  822. });
  823. });
  824. test('Any grant is allowed if parent is public', async () => {
  825. const userRelatedUserGroups =
  826. await UserGroupRelation.findAllGroupsForUser(user1);
  827. const userRelatedExternalUserGroups =
  828. await ExternalUserGroupRelation.findAllGroupsForUser(user1);
  829. const userRelatedGroups = [
  830. ...userRelatedUserGroups.map((group) => {
  831. return { type: GroupType.userGroup, item: group };
  832. }),
  833. ...userRelatedExternalUserGroups.map((group) => {
  834. return { type: GroupType.externalUserGroup, item: group };
  835. }),
  836. ];
  837. // OnlyMe
  838. const publicOnlyMePage = await Page.findOne({
  839. path: pagePublicOnlyMePath,
  840. });
  841. const publicOnlyMeRes = await pageGrantService.calcApplicableGrantData(
  842. publicOnlyMePage,
  843. user1,
  844. );
  845. expect(publicOnlyMeRes).toStrictEqual({
  846. [PageGrant.GRANT_PUBLIC]: null,
  847. [PageGrant.GRANT_RESTRICTED]: null,
  848. [PageGrant.GRANT_OWNER]: null,
  849. [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userRelatedGroups },
  850. });
  851. // AnyoneWithTheLink
  852. const publicAnyoneWithTheLinkPage = await Page.findOne({
  853. path: pagePublicAnyoneWithTheLinkPath,
  854. });
  855. const publicAnyoneWithTheLinkRes =
  856. await pageGrantService.calcApplicableGrantData(
  857. publicAnyoneWithTheLinkPage,
  858. user1,
  859. );
  860. expect(publicAnyoneWithTheLinkRes).toStrictEqual({
  861. [PageGrant.GRANT_PUBLIC]: null,
  862. [PageGrant.GRANT_RESTRICTED]: null,
  863. [PageGrant.GRANT_OWNER]: null,
  864. [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userRelatedGroups },
  865. });
  866. // OnlyInsideTheGroup
  867. const publicOnlyInsideTheGroupPage = await Page.findOne({
  868. path: pagePublicOnlyInsideTheGroupPath,
  869. });
  870. const publicOnlyInsideTheGroupRes =
  871. await pageGrantService.calcApplicableGrantData(
  872. publicOnlyInsideTheGroupPage,
  873. user1,
  874. );
  875. expect(publicOnlyInsideTheGroupRes).toStrictEqual({
  876. [PageGrant.GRANT_PUBLIC]: null,
  877. [PageGrant.GRANT_RESTRICTED]: null,
  878. [PageGrant.GRANT_OWNER]: null,
  879. [PageGrant.GRANT_USER_GROUP]: { applicableGroups: userRelatedGroups },
  880. });
  881. });
  882. test('Only "GRANT_OWNER" is allowed if the user is the parent page\'s grantUser', async () => {
  883. // Public
  884. const onlyMePublicPage = await Page.findOne({
  885. path: pageOnlyMePublicPath,
  886. });
  887. const onlyMePublicRes = await pageGrantService.calcApplicableGrantData(
  888. onlyMePublicPage,
  889. user1,
  890. );
  891. expect(onlyMePublicRes).toStrictEqual({
  892. [PageGrant.GRANT_RESTRICTED]: null,
  893. [PageGrant.GRANT_OWNER]: null,
  894. });
  895. // AnyoneWithTheLink
  896. const onlyMeAnyoneWithTheLinkPage = await Page.findOne({
  897. path: pageOnlyMeAnyoneWithTheLinkPath,
  898. });
  899. const onlyMeAnyoneWithTheLinkRes =
  900. await pageGrantService.calcApplicableGrantData(
  901. onlyMeAnyoneWithTheLinkPage,
  902. user1,
  903. );
  904. expect(onlyMeAnyoneWithTheLinkRes).toStrictEqual({
  905. [PageGrant.GRANT_RESTRICTED]: null,
  906. [PageGrant.GRANT_OWNER]: null,
  907. });
  908. // OnlyInsideTheGroup
  909. const publicOnlyInsideTheGroupPage = await Page.findOne({
  910. path: pageOnlyMeOnlyInsideTheGroupPath,
  911. });
  912. const publicOnlyInsideTheGroupRes =
  913. await pageGrantService.calcApplicableGrantData(
  914. publicOnlyInsideTheGroupPage,
  915. user1,
  916. );
  917. expect(publicOnlyInsideTheGroupRes).toStrictEqual({
  918. [PageGrant.GRANT_RESTRICTED]: null,
  919. [PageGrant.GRANT_OWNER]: null,
  920. });
  921. });
  922. test('"GRANT_OWNER" is not allowed if the user is not the parent page\'s grantUser', async () => {
  923. // Public
  924. const onlyMePublicPage = await Page.findOne({
  925. path: pageOnlyMePublicPath,
  926. });
  927. const onlyMePublicRes = await pageGrantService.calcApplicableGrantData(
  928. onlyMePublicPage,
  929. user2,
  930. );
  931. expect(onlyMePublicRes).toStrictEqual({
  932. [PageGrant.GRANT_RESTRICTED]: null,
  933. });
  934. // AnyoneWithTheLink
  935. const onlyMeAnyoneWithTheLinkPage = await Page.findOne({
  936. path: pageOnlyMeAnyoneWithTheLinkPath,
  937. });
  938. const onlyMeAnyoneWithTheLinkRes =
  939. await pageGrantService.calcApplicableGrantData(
  940. onlyMeAnyoneWithTheLinkPage,
  941. user2,
  942. );
  943. expect(onlyMeAnyoneWithTheLinkRes).toStrictEqual({
  944. [PageGrant.GRANT_RESTRICTED]: null,
  945. });
  946. // OnlyInsideTheGroup
  947. const publicOnlyInsideTheGroupPage = await Page.findOne({
  948. path: pageOnlyMeOnlyInsideTheGroupPath,
  949. });
  950. const publicOnlyInsideTheGroupRes =
  951. await pageGrantService.calcApplicableGrantData(
  952. publicOnlyInsideTheGroupPage,
  953. user2,
  954. );
  955. expect(publicOnlyInsideTheGroupRes).toStrictEqual({
  956. [PageGrant.GRANT_RESTRICTED]: null,
  957. });
  958. });
  959. test('"GRANT_USER_GROUP" is allowed if the parent\'s grant is GRANT_USER_GROUP and the user is included in the group', async () => {
  960. const userGroups =
  961. await UserGroupRelation.findGroupsWithDescendantsByGroupAndUser(
  962. groupParent,
  963. user1,
  964. );
  965. const externalUserGroups =
  966. await ExternalUserGroupRelation.findGroupsWithDescendantsByGroupAndUser(
  967. externalGroupParent,
  968. user1,
  969. );
  970. const applicableGroups = [
  971. ...userGroups.map((group) => {
  972. return { type: GroupType.userGroup, item: group };
  973. }),
  974. ...externalUserGroups.map((group) => {
  975. return { type: GroupType.externalUserGroup, item: group };
  976. }),
  977. ];
  978. // Public
  979. const onlyInsideGroupPublicPage = await Page.findOne({
  980. path: pageOnlyInsideTheGroupPublicPath,
  981. });
  982. const onlyInsideGroupPublicRes =
  983. await pageGrantService.calcApplicableGrantData(
  984. onlyInsideGroupPublicPage,
  985. user1,
  986. );
  987. expect(onlyInsideGroupPublicRes).toStrictEqual({
  988. [PageGrant.GRANT_RESTRICTED]: null,
  989. [PageGrant.GRANT_OWNER]: null,
  990. [PageGrant.GRANT_USER_GROUP]: { applicableGroups },
  991. });
  992. // OnlyMe
  993. const onlyInsideTheGroupOnlyMePage = await Page.findOne({
  994. path: pageOnlyInsideTheGroupOnlyMePath,
  995. });
  996. const onlyInsideTheGroupOnlyMeRes =
  997. await pageGrantService.calcApplicableGrantData(
  998. onlyInsideTheGroupOnlyMePage,
  999. user1,
  1000. );
  1001. expect(onlyInsideTheGroupOnlyMeRes).toStrictEqual({
  1002. [PageGrant.GRANT_RESTRICTED]: null,
  1003. [PageGrant.GRANT_OWNER]: null,
  1004. [PageGrant.GRANT_USER_GROUP]: { applicableGroups },
  1005. });
  1006. // AnyoneWithTheLink
  1007. const onlyInsideTheGroupAnyoneWithTheLinkPage = await Page.findOne({
  1008. path: pageOnlyInsideTheGroupAnyoneWithTheLinkPath,
  1009. });
  1010. const onlyInsideTheGroupAnyoneWithTheLinkRes =
  1011. await pageGrantService.calcApplicableGrantData(
  1012. onlyInsideTheGroupAnyoneWithTheLinkPage,
  1013. user1,
  1014. );
  1015. expect(onlyInsideTheGroupAnyoneWithTheLinkRes).toStrictEqual({
  1016. [PageGrant.GRANT_RESTRICTED]: null,
  1017. [PageGrant.GRANT_OWNER]: null,
  1018. [PageGrant.GRANT_USER_GROUP]: { applicableGroups },
  1019. });
  1020. });
  1021. });
  1022. describe('Test for getPageGroupGrantData', () => {
  1023. test('return expected group grant data', async () => {
  1024. const groupGrantDataTestChildPage = await Page.findOne({
  1025. path: groupGrantDataTestChildPagePath,
  1026. });
  1027. const result = await pageGrantService.getPageGroupGrantData(
  1028. groupGrantDataTestChildPage,
  1029. user3,
  1030. );
  1031. expect(result).toStrictEqual({
  1032. userRelatedGroups: [
  1033. {
  1034. id: groupGrantDataTestExternalUserGroupId.toString(),
  1035. name: 'groupGrantDataTestExternalGroup',
  1036. type: GroupType.externalUserGroup,
  1037. provider: ExternalGroupProviderType.ldap,
  1038. status: UserGroupPageGrantStatus.notGranted,
  1039. },
  1040. {
  1041. id: groupGrantDataTestChildUserGroupId.toString(),
  1042. name: 'groupGrantDataTestChildGroup',
  1043. type: GroupType.userGroup,
  1044. provider: undefined,
  1045. status: UserGroupPageGrantStatus.isGranted,
  1046. },
  1047. {
  1048. id: groupGrantDataTestParentUserGroupId.toString(),
  1049. name: 'groupGrantDataTestParentGroup',
  1050. type: GroupType.userGroup,
  1051. provider: undefined,
  1052. status: UserGroupPageGrantStatus.cannotGrant,
  1053. },
  1054. ],
  1055. nonUserRelatedGrantedGroups: [
  1056. {
  1057. id: groupGrantDataTestExternalUserGroupId2.toString(),
  1058. name: 'groupGrantDataTestExternalGroup2',
  1059. type: GroupType.externalUserGroup,
  1060. provider: ExternalGroupProviderType.ldap,
  1061. },
  1062. ],
  1063. });
  1064. });
  1065. test('return empty arrays when page is root', async () => {
  1066. const result = await pageGrantService.getPageGroupGrantData(
  1067. rootPage,
  1068. user1,
  1069. );
  1070. expect(result).toStrictEqual({
  1071. userRelatedGroups: [],
  1072. nonUserRelatedGrantedGroups: [],
  1073. });
  1074. });
  1075. });
  1076. });