abilityBuilder.test.ts 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. import { describe, test, it, expect } from 'vitest'
  2. import {MongoAbility} from "@casl/ability/dist/types/Ability";
  3. import {AccessProfile, organizationState} from "~/types/interfaces";
  4. import AbilityBuilder from "~/services/rights/abilityBuilder";
  5. import {ABILITIES} from "~/types/enum/enums";
  6. let ability: MongoAbility
  7. let accessProfile: AccessProfile
  8. let organizationProfile: organizationState
  9. let abilityBuilder: TestableAbilityBuilder
  10. class TestableAbilityBuilder extends AbilityBuilder {
  11. public execAndValidateCondition(condition: any, subject: string = '') { return super.execAndValidateCondition(condition, subject) }
  12. }
  13. beforeEach(() => {
  14. ability = vi.fn() as any as MongoAbility
  15. accessProfile = vi.fn() as any as AccessProfile
  16. organizationProfile = vi.fn() as any as organizationState
  17. abilityBuilder = new TestableAbilityBuilder(ability, accessProfile, organizationProfile)
  18. })
  19. describe('buildAbilities', () => {
  20. // test('base call', () => {
  21. // abilityBuilder.buildAbilities()
  22. //
  23. // expect(ability.update).toHaveBeenCalledTimes(1)
  24. // // @ts-ignore
  25. // expect(organizationProfile.$onAction).toHaveBeenCalledTimes(1)
  26. // })
  27. })
  28. describe('hasConfigAbility', () => {
  29. beforeEach(() => {
  30. accessProfile.isGuardian = true
  31. // @ts-ignore
  32. organizationProfile.isSchool = true
  33. // @ts-ignore
  34. organizationProfile.isCmf = false
  35. })
  36. test('fulfill all conditions', () => {
  37. const conditions = [
  38. {'function': 'accessHasAnyProfile', parameters: ['guardian', 'payer']},
  39. {'function': 'organizationIsSchool'},
  40. ]
  41. expect(abilityBuilder.hasConfigAbility(conditions)).toBeTruthy()
  42. })
  43. test('fulfill at least one condition', () => {
  44. const conditions = [
  45. {'function': 'accessHasAnyProfile', parameters: ['guardian', 'payer']},
  46. {'function': 'organizationIsCmf'},
  47. ]
  48. expect(abilityBuilder.hasConfigAbility(conditions)).toBeFalsy()
  49. })
  50. test('fulfill none of the conditions', () => {
  51. const conditions = [
  52. {'function': 'organizationIsCmf'},
  53. ]
  54. expect(abilityBuilder.hasConfigAbility(conditions)).toBeFalsy()
  55. })
  56. })
  57. describe('execAndValidateCondition', () => {
  58. test('accessHasAllRoleAbilities', () => {
  59. ability.can = vi.fn((action: string, subject: string) => {
  60. return action === 'read' && (subject === 'subject1' || subject === 'subject2')
  61. })
  62. expect(
  63. abilityBuilder.execAndValidateCondition(
  64. {
  65. 'function': 'accessHasAllRoleAbilities',
  66. parameters: [
  67. {action: ABILITIES.READ, subject: 'subject1'},
  68. {action: ABILITIES.READ, subject: 'subject2'},
  69. ]
  70. })
  71. ).toBeTruthy()
  72. expect(
  73. abilityBuilder.execAndValidateCondition(
  74. {
  75. 'function': 'accessHasAllRoleAbilities',
  76. parameters: [
  77. {action: ABILITIES.READ, subject: 'subject1'},
  78. {action: ABILITIES.READ, subject: 'subject3'}
  79. ]
  80. })
  81. ).toBeFalsy()
  82. })
  83. test('accessHasAnyRoleAbility', () => {
  84. ability.can = vi.fn((action: string, subject: string) => {
  85. return action === 'read' && subject === 'subject1'
  86. })
  87. expect(
  88. abilityBuilder.execAndValidateCondition(
  89. {
  90. 'function': 'accessHasAnyRoleAbility',
  91. parameters: [
  92. {action: ABILITIES.READ, subject: 'subject1'},
  93. {action: ABILITIES.READ, subject: 'subject2'},
  94. ]
  95. })
  96. ).toBeTruthy()
  97. expect(
  98. abilityBuilder.execAndValidateCondition(
  99. {'function': 'accessHasAnyRoleAbility', parameters: [{action: ABILITIES.READ, subject: 'subject2'}]})
  100. ).toBeFalsy()
  101. })
  102. test('accessHasAnyProfile', () => {
  103. accessProfile.isMember = true
  104. accessProfile.isGuardian = true
  105. accessProfile.isPayer = true
  106. expect(
  107. abilityBuilder.execAndValidateCondition(
  108. {'function': 'accessHasAnyProfile', parameters: ['guardian', 'payer']}
  109. )
  110. ).toBeTruthy()
  111. expect(
  112. abilityBuilder.execAndValidateCondition(
  113. {'function': 'accessHasAnyProfile', parameters: ['guardian', 'caMember']}
  114. )
  115. ).toBeTruthy()
  116. expect(
  117. abilityBuilder.execAndValidateCondition(
  118. {'function': 'accessHasAnyProfile', parameters: ['caMember']}
  119. )
  120. ).toBeFalsy()
  121. })
  122. test('organizationHasAllModules', () => {
  123. // @ts-ignore
  124. organizationProfile.hasModule = vi.fn(
  125. (module: string) => module === 'module1' || module === 'module2'
  126. )
  127. expect(
  128. abilityBuilder.execAndValidateCondition(
  129. {'function': 'organizationHasAllModules', parameters: ['module1', 'module2']}
  130. )
  131. ).toBeTruthy()
  132. expect(
  133. abilityBuilder.execAndValidateCondition(
  134. {'function': 'organizationHasAllModules', parameters: ['module1', 'module3']}
  135. )
  136. ).toBeFalsy()
  137. expect(
  138. abilityBuilder.execAndValidateCondition(
  139. {'function': 'organizationHasAllModules', parameters: ['module3']}
  140. )
  141. ).toBeFalsy()
  142. })
  143. test('organizationHasAnyModule', () => {
  144. // @ts-ignore
  145. organizationProfile.hasModule = vi.fn(
  146. (module: string) => module === 'module1' || module === 'module2'
  147. )
  148. expect(
  149. abilityBuilder.execAndValidateCondition(
  150. {'function': 'organizationHasAnyModule', parameters: ['module1', 'module2']}
  151. )
  152. ).toBeTruthy()
  153. expect(
  154. abilityBuilder.execAndValidateCondition(
  155. {'function': 'organizationHasAnyModule', parameters: ['module1', 'module3']}
  156. )
  157. ).toBeTruthy()
  158. expect(
  159. abilityBuilder.execAndValidateCondition(
  160. {'function': 'organizationHasAnyModule', parameters: ['module3']}
  161. )
  162. ).toBeFalsy()
  163. })
  164. test('organizationHasAnyModule', () => {
  165. // @ts-ignore
  166. accessProfile.isAdminAccount = true
  167. expect(abilityBuilder.execAndValidateCondition({'function': 'accessIsAdminAccount'})).toBeTruthy()
  168. // @ts-ignore
  169. accessProfile.isAdminAccount = false
  170. expect(abilityBuilder.execAndValidateCondition({'function': 'accessIsAdminAccount'})).toBeFalsy()
  171. })
  172. test('organizationIsSchool', () => {
  173. // @ts-ignore
  174. organizationProfile.isSchool = true
  175. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsSchool'})).toBeTruthy()
  176. // @ts-ignore
  177. organizationProfile.isSchool = false
  178. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsSchool'})).toBeFalsy()
  179. })
  180. test('organizationIsArtist', () => {
  181. // @ts-ignore
  182. organizationProfile.isArtist = true
  183. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsArtist'})).toBeTruthy()
  184. // @ts-ignore
  185. organizationProfile.isArtist = false
  186. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsArtist'})).toBeFalsy()
  187. })
  188. test('organizationIsManagerProduct', () => {
  189. // @ts-ignore
  190. organizationProfile.isManagerProduct = true
  191. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsManagerProduct'})).toBeTruthy()
  192. // @ts-ignore
  193. organizationProfile.isManagerProduct = false
  194. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsManagerProduct'})).toBeFalsy()
  195. })
  196. test('organizationHasChildren', () => {
  197. // @ts-ignore
  198. organizationProfile.hasChildren = true
  199. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationHasChildren'})).toBeTruthy()
  200. // @ts-ignore
  201. organizationProfile.hasChildren = false
  202. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationHasChildren'})).toBeFalsy()
  203. })
  204. test('organizationIsAssociation', () => {
  205. // @ts-ignore
  206. organizationProfile.isAssociation = true
  207. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsAssociation'})).toBeTruthy()
  208. // @ts-ignore
  209. organizationProfile.isAssociation = false
  210. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsAssociation'})).toBeFalsy()
  211. })
  212. test('organizationIsShowAdherentList', () => {
  213. // @ts-ignore
  214. organizationProfile.isShowAdherentList = true
  215. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsShowAdherentList'})).toBeTruthy()
  216. // @ts-ignore
  217. organizationProfile.isShowAdherentList = false
  218. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsShowAdherentList'})).toBeFalsy()
  219. })
  220. test('organizationIsCmf', () => {
  221. // @ts-ignore
  222. organizationProfile.isCmf = true
  223. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsCmf'})).toBeTruthy()
  224. // @ts-ignore
  225. organizationProfile.isCmf = false
  226. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsCmf'})).toBeFalsy()
  227. })
  228. test('organizationHasWebsite', () => {
  229. // @ts-ignore
  230. organizationProfile.getWebsite = true
  231. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationHasWebsite'})).toBeTruthy()
  232. // @ts-ignore
  233. organizationProfile.getWebsite = false
  234. expect(abilityBuilder.execAndValidateCondition({'function': 'organizationHasWebsite'})).toBeFalsy()
  235. })
  236. test('with expected result', () => {
  237. // @ts-ignore
  238. organizationProfile.getWebsite = true
  239. expect(
  240. abilityBuilder.execAndValidateCondition({'function': 'organizationHasWebsite', expectedResult: true})
  241. ).toBeTruthy()
  242. expect(
  243. abilityBuilder.execAndValidateCondition({'function': 'organizationHasWebsite', expectedResult: 'abc'})
  244. ).toBeFalsy()
  245. })
  246. test('invalid function', () => {
  247. expect(
  248. () => abilityBuilder.execAndValidateCondition({'function': 'invalid'})
  249. ).toThrowError('unknown condition function : invalid')
  250. })
  251. })
  252. describe('hasRoleAbility', () => {
  253. beforeEach(() => {
  254. ability.can = vi.fn((action: string, subject: string) => {
  255. return action === 'read' && subject === 'a_subject'
  256. })
  257. })
  258. test('owned ability', () => {
  259. expect(abilityBuilder.hasRoleAbility({action: ABILITIES.READ, subject: 'a_subject'})).toBeTruthy()
  260. })
  261. test('not owned ability', () => {
  262. expect(abilityBuilder.hasRoleAbility({action: ABILITIES.READ, subject: 'other_subject'})).toBeFalsy()
  263. })
  264. })
  265. describe('hasAllRoleAbilities', () => {
  266. beforeEach(() => {
  267. ability.can = vi.fn((action: string, subject: string) => {
  268. return action === 'read' && (subject === 'subject1' || subject === 'subject2')
  269. })
  270. })
  271. test('own all abilities', () => {
  272. const result = abilityBuilder.hasAllRoleAbilities(
  273. [
  274. {action: ABILITIES.READ, subject: 'subject1'},
  275. {action: ABILITIES.READ, subject: 'subject2'},
  276. ]
  277. )
  278. expect(result).toBeTruthy()
  279. })
  280. test('own at least one ability', () => {
  281. const result = abilityBuilder.hasAllRoleAbilities(
  282. [
  283. {action: ABILITIES.READ, subject: 'subject1'},
  284. {action: ABILITIES.READ, subject: 'subject3'},
  285. ]
  286. )
  287. expect(result).toBeFalsy()
  288. })
  289. test('own none of the abilities', () => {
  290. const result = abilityBuilder.hasAllRoleAbilities(
  291. [
  292. {action: ABILITIES.READ, subject: 'subject3'},
  293. {action: ABILITIES.READ, subject: 'subject4'},
  294. ]
  295. )
  296. expect(result).toBeFalsy()
  297. })
  298. })
  299. describe('hasAnyRoleAbility', () => {
  300. beforeEach(() => {
  301. ability.can = vi.fn((action: string, subject: string) => {
  302. return action === 'read' && (subject === 'subject1' || subject === 'subject2')
  303. })
  304. })
  305. test('has all abilities', () => {
  306. const result = abilityBuilder.hasAnyRoleAbility(
  307. [
  308. {action: ABILITIES.READ, subject: 'subject1'},
  309. {action: ABILITIES.READ, subject: 'subject2'},
  310. ]
  311. )
  312. expect(result).toBeTruthy()
  313. })
  314. test('has at least one ability', () => {
  315. const result = abilityBuilder.hasAnyRoleAbility(
  316. [
  317. {action: ABILITIES.READ, subject: 'subject1'},
  318. {action: ABILITIES.READ, subject: 'subject3'},
  319. ]
  320. )
  321. expect(result).toBeTruthy()
  322. })
  323. test('any none of the abilites', () => {
  324. const result = abilityBuilder.hasAnyRoleAbility(
  325. [
  326. {action: ABILITIES.READ, subject: 'subject3'},
  327. {action: ABILITIES.READ, subject: 'subject4'},
  328. ]
  329. )
  330. expect(result).toBeFalsy()
  331. })
  332. })
  333. describe('hasProfile', () => {
  334. test('owned profiles', () => {
  335. accessProfile.isAdmin = true
  336. accessProfile.isAdministratifManager = true
  337. accessProfile.isPedagogicManager = true
  338. accessProfile.isFinancialManager = true
  339. accessProfile.isCaMember = true
  340. accessProfile.isStudent = true
  341. accessProfile.isTeacher = true
  342. accessProfile.isMember = true
  343. accessProfile.isOther = true
  344. accessProfile.isGuardian = true
  345. accessProfile.isPayer = true
  346. expect(abilityBuilder.hasProfile('admin')).toBeTruthy()
  347. expect(abilityBuilder.hasProfile('administratifManager')).toBeTruthy()
  348. expect(abilityBuilder.hasProfile('pedagogicManager')).toBeTruthy()
  349. expect(abilityBuilder.hasProfile('financialManager')).toBeTruthy()
  350. expect(abilityBuilder.hasProfile('caMember')).toBeTruthy()
  351. expect(abilityBuilder.hasProfile('student')).toBeTruthy()
  352. expect(abilityBuilder.hasProfile('teacher')).toBeTruthy()
  353. expect(abilityBuilder.hasProfile('member')).toBeTruthy()
  354. expect(abilityBuilder.hasProfile('other')).toBeTruthy()
  355. expect(abilityBuilder.hasProfile('guardian')).toBeTruthy()
  356. expect(abilityBuilder.hasProfile('payor')).toBeTruthy()
  357. })
  358. test('not owned profiles', () => {
  359. accessProfile.isAdmin = false
  360. accessProfile.isAdministratifManager = false
  361. accessProfile.isPedagogicManager = false
  362. accessProfile.isFinancialManager = false
  363. accessProfile.isCaMember = false
  364. accessProfile.isStudent = false
  365. accessProfile.isTeacher = false
  366. accessProfile.isMember = false
  367. accessProfile.isOther = false
  368. accessProfile.isGuardian = false
  369. accessProfile.isPayer = false
  370. expect(abilityBuilder.hasProfile('admin')).toBeFalsy()
  371. expect(abilityBuilder.hasProfile('administratifManager')).toBeFalsy()
  372. expect(abilityBuilder.hasProfile('pedagogicManager')).toBeFalsy()
  373. expect(abilityBuilder.hasProfile('financialManager')).toBeFalsy()
  374. expect(abilityBuilder.hasProfile('caMember')).toBeFalsy()
  375. expect(abilityBuilder.hasProfile('student')).toBeFalsy()
  376. expect(abilityBuilder.hasProfile('teacher')).toBeFalsy()
  377. expect(abilityBuilder.hasProfile('member')).toBeFalsy()
  378. expect(abilityBuilder.hasProfile('other')).toBeFalsy()
  379. expect(abilityBuilder.hasProfile('guardian')).toBeFalsy()
  380. expect(abilityBuilder.hasProfile('payor')).toBeFalsy()
  381. })
  382. })
  383. describe('hasAnyProfile', () => {
  384. beforeEach(() => {
  385. accessProfile.isMember = true
  386. accessProfile.isGuardian = true
  387. accessProfile.isPayer = true
  388. })
  389. test('own all profiles', () => {
  390. expect(abilityBuilder.hasAnyProfile(['member', 'guardian', 'payor'])).toBeTruthy()
  391. })
  392. test('own at least one profile', () => {
  393. expect(abilityBuilder.hasAnyProfile(['member', 'caMember'])).toBeTruthy()
  394. })
  395. test('own none of the profiles', () => {
  396. expect(abilityBuilder.hasAnyProfile(['caMember', 'isFinancialManager'])).toBeFalsy()
  397. })
  398. })
  399. describe('hasAllProfiles', () => {
  400. beforeEach(() => {
  401. accessProfile.isMember = true
  402. accessProfile.isGuardian = true
  403. accessProfile.isPayer = true
  404. })
  405. test('own all profiles', () => {
  406. expect(abilityBuilder.hasAllProfiles(['member', 'guardian', 'payor'])).toBeTruthy()
  407. })
  408. test('own only one of the profiles', () => {
  409. expect(abilityBuilder.hasAllProfiles(['member', 'caMember'])).toBeFalsy()
  410. })
  411. test('own none of the profiles', () => {
  412. expect(abilityBuilder.hasAllProfiles(['caMember', 'isFinancialManager'])).toBeFalsy()
  413. })
  414. })
  415. describe('hasRole', () => {
  416. beforeEach(() => {
  417. // @ts-ignore
  418. accessProfile.hasRole = vi.fn((role: string) => role === 'foo')
  419. })
  420. test('has role', () => {
  421. expect(abilityBuilder.hasRole('foo')).toBeTruthy()
  422. })
  423. test('has not role', () => {
  424. expect(abilityBuilder.hasRole('bar')).toBeFalsy()
  425. })
  426. })
  427. describe('hasAnyRole', () => {
  428. beforeEach(() => {
  429. // @ts-ignore
  430. accessProfile.hasRole = vi.fn((role: string) => role === 'role1' || role === 'role2')
  431. })
  432. test('own all roles', () => {
  433. expect(abilityBuilder.hasAnyRole(['role1', 'role2'])).toBeTruthy()
  434. })
  435. test('own at least one role', () => {
  436. expect(abilityBuilder.hasAnyRole(['role1', 'role3'])).toBeTruthy()
  437. })
  438. test('own none of the roles', () => {
  439. expect(abilityBuilder.hasAnyRole(['role3'])).toBeFalsy()
  440. })
  441. })
  442. describe('hasAllRoles', () => {
  443. beforeEach(() => {
  444. // @ts-ignore
  445. accessProfile.hasRole = vi.fn((role: string) => role === 'role1' || role === 'role2')
  446. })
  447. test('own all roles', () => {
  448. expect(abilityBuilder.hasAllRoles(['role1', 'role2'])).toBeTruthy()
  449. })
  450. test('own at least one role', () => {
  451. expect(abilityBuilder.hasAllRoles(['role1', 'role3'])).toBeFalsy()
  452. })
  453. test('own none of the roles', () => {
  454. expect(abilityBuilder.hasAllRoles(['role3'])).toBeFalsy()
  455. })
  456. })
  457. describe('hasModule', () => {
  458. beforeEach(() => {
  459. // @ts-ignore
  460. organizationProfile.hasModule = vi.fn((module: string) => module === 'foo')
  461. })
  462. test('has module', () => {
  463. expect(abilityBuilder.hasModule('foo')).toBeTruthy()
  464. })
  465. test('has not module', () => {
  466. expect(abilityBuilder.hasModule('bar')).toBeFalsy()
  467. })
  468. })
  469. describe('hasAnyModule', () => {
  470. beforeEach(() => {
  471. // @ts-ignore
  472. organizationProfile.hasModule = vi.fn((Module: string) => Module === 'Module1' || Module === 'Module2')
  473. })
  474. test('own all modules', () => {
  475. expect(abilityBuilder.hasAnyModule(['Module1', 'Module2'])).toBeTruthy()
  476. })
  477. test('own at least one module', () => {
  478. expect(abilityBuilder.hasAnyModule(['Module1', 'Module3'])).toBeTruthy()
  479. })
  480. test('own none of the modules', () => {
  481. expect(abilityBuilder.hasAnyModule(['Module3'])).toBeFalsy()
  482. })
  483. })
  484. describe('hasAllModules', () => {
  485. beforeEach(() => {
  486. // @ts-ignore
  487. organizationProfile.hasModule = vi.fn((Module: string) => Module === 'Module1' || Module === 'Module2')
  488. })
  489. test('own all modules', () => {
  490. expect(abilityBuilder.hasAllModules(['Module1', 'Module2'])).toBeTruthy()
  491. })
  492. test('own at least one module', () => {
  493. expect(abilityBuilder.hasAllModules(['Module1', 'Module3'])).toBeFalsy()
  494. })
  495. test('own none of the modules', () => {
  496. expect(abilityBuilder.hasAllModules(['Module3'])).toBeFalsy()
  497. })
  498. })