| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703 |
- import { describe, test, expect } from 'vitest'
- import {MongoAbility} from "@casl/ability/dist/types/Ability";
- import {AbilitiesType, AccessProfile, organizationState} from "~/types/interfaces";
- import AbilityBuilder from "~/services/rights/abilityBuilder";
- import {ABILITIES} from "~/types/enum/enums";
- let ability: MongoAbility
- let accessProfile: AccessProfile
- let organizationProfile: organizationState
- let abilityBuilder: AbilityBuilder
- // Mock the content of the config yaml files
- // > This must be done in the global scope: https://vitest.dev/api/vi.html#vi-mock
- const doc = {
- abilities: {
- 'subject1': {
- action: ABILITIES.READ,
- conditions: [
- {
- 'function': 'fct1',
- 'parameters': ['param1'],
- 'expectedResult': true
- }
- ]
- },
- 'subject2': {
- action: ABILITIES.READ,
- conditions: {
- 'function': 'fct2',
- 'parameters': ['param2'],
- 'expectedResult': false
- }
- }
- }
- }
- vi.mock('yaml-import', async () => {
- return {
- default: { read: vi.fn((data: string) => doc) }
- }
- })
- beforeEach(() => {
- ability = vi.fn() as any as MongoAbility
- accessProfile = vi.fn() as any as AccessProfile
- organizationProfile = vi.fn() as any as organizationState
- abilityBuilder = new AbilityBuilder(ability, accessProfile, organizationProfile)
- })
- describe('buildAbilities', () => {
- test('base call', () => {
- const roleAbilities: Array<AbilitiesType> = [
- {action: ABILITIES.READ, subject: 'subject1'},
- {action: ABILITIES.READ, subject: 'subject2'}
- ]
- const configAbilities: Array<AbilitiesType> = [
- {action: ABILITIES.READ, subject: 'subject3'},
- {action: ABILITIES.READ, subject: 'subject4'}
- ]
- const allAbilities: Array<AbilitiesType> = roleAbilities.concat(configAbilities)
- abilityBuilder.buildAbilitiesFromRoles = vi.fn(() => roleAbilities)
- abilityBuilder.buildAbilitiesFromConfig = vi.fn(() => configAbilities)
- ability.update = vi.fn()
- const result = abilityBuilder.buildAbilities()
- expect(ability.update).toHaveBeenCalledTimes(2)
- expect(ability.update).toHaveBeenCalledWith(roleAbilities)
- expect(ability.update).toHaveBeenCalledWith(allAbilities)
- expect(abilityBuilder.buildAbilitiesFromRoles).toHaveBeenCalledOnce()
- expect(abilityBuilder.buildAbilitiesFromConfig).toHaveBeenCalledOnce()
- expect(result).toEqual(allAbilities)
- })
- })
- describe('buildAbilitiesFromRoles', () => {
- test('calls roleUtils', () => {
- accessProfile.roles = ['ROLE_EVENTS_VIEW', 'ROLE_COURSES', 'ROLE_TEACHER_CORE', 'ROLE_OTHER']
- const expected = [
- { subject: 'events', action: 'read' },
- { subject: 'courses', action: 'manage' },
- { subject: 'other', action: 'manage' },
- ]
- expect(abilityBuilder.buildAbilitiesFromRoles()).toEqual(expected)
- })
- })
- describe('buildAbilitiesFromConfig', () => {
- test('calls roleUtils', () => {
- abilityBuilder.hasConfigAbility = vi.fn(() => true)
- expect(abilityBuilder.buildAbilitiesFromConfig()).toEqual([
- { action: 'read', subject: 'subject1' },
- { action: 'read', subject: 'subject2' },
- ])
- })
- })
- describe('hasConfigAbility', () => {
- beforeEach(() => {
- accessProfile.isGuardian = true
- // @ts-ignore
- organizationProfile.isSchool = true
- // @ts-ignore
- organizationProfile.isCmf = false
- })
- test('fulfill all conditions', () => {
- const conditions = [
- {'function': 'accessHasAnyProfile', parameters: ['guardian', 'payer']},
- {'function': 'organizationIsSchool'},
- ]
- expect(abilityBuilder.hasConfigAbility(conditions)).toBeTruthy()
- })
- test('fulfill at least one condition', () => {
- const conditions = [
- {'function': 'accessHasAnyProfile', parameters: ['guardian', 'payer']},
- {'function': 'organizationIsCmf'},
- ]
- expect(abilityBuilder.hasConfigAbility(conditions)).toBeFalsy()
- })
- test('fulfill none of the conditions', () => {
- const conditions = [
- {'function': 'organizationIsCmf'},
- ]
- expect(abilityBuilder.hasConfigAbility(conditions)).toBeFalsy()
- })
- })
- describe('execAndValidateCondition', () => {
- test('accessHasAllRoleAbilities', () => {
- ability.can = vi.fn((action: string, subject: string) => {
- return action === 'read' && (subject === 'subject1' || subject === 'subject2')
- })
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {
- 'function': 'accessHasAllRoleAbilities',
- parameters: [
- {action: ABILITIES.READ, subject: 'subject1'},
- {action: ABILITIES.READ, subject: 'subject2'},
- ]
- })
- ).toBeTruthy()
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {
- 'function': 'accessHasAllRoleAbilities',
- parameters: [
- {action: ABILITIES.READ, subject: 'subject1'},
- {action: ABILITIES.READ, subject: 'subject3'}
- ]
- })
- ).toBeFalsy()
- })
- test('accessHasAnyRoleAbility', () => {
- ability.can = vi.fn((action: string, subject: string) => {
- return action === 'read' && subject === 'subject1'
- })
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {
- 'function': 'accessHasAnyRoleAbility',
- parameters: [
- {action: ABILITIES.READ, subject: 'subject1'},
- {action: ABILITIES.READ, subject: 'subject2'},
- ]
- })
- ).toBeTruthy()
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {'function': 'accessHasAnyRoleAbility', parameters: [{action: ABILITIES.READ, subject: 'subject2'}]})
- ).toBeFalsy()
- })
- test('accessHasAnyProfile', () => {
- accessProfile.isMember = true
- accessProfile.isGuardian = true
- accessProfile.isPayer = true
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {'function': 'accessHasAnyProfile', parameters: ['guardian', 'payer']}
- )
- ).toBeTruthy()
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {'function': 'accessHasAnyProfile', parameters: ['guardian', 'caMember']}
- )
- ).toBeTruthy()
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {'function': 'accessHasAnyProfile', parameters: ['caMember']}
- )
- ).toBeFalsy()
- })
- test('organizationHasAllModules', () => {
- // @ts-ignore
- organizationProfile.hasModule = vi.fn(
- (module: string) => module === 'module1' || module === 'module2'
- )
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {'function': 'organizationHasAllModules', parameters: ['module1', 'module2']}
- )
- ).toBeTruthy()
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {'function': 'organizationHasAllModules', parameters: ['module1', 'module3']}
- )
- ).toBeFalsy()
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {'function': 'organizationHasAllModules', parameters: ['module3']}
- )
- ).toBeFalsy()
- })
- test('organizationHasAnyModule', () => {
- // @ts-ignore
- organizationProfile.hasModule = vi.fn(
- (module: string) => module === 'module1' || module === 'module2'
- )
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {'function': 'organizationHasAnyModule', parameters: ['module1', 'module2']}
- )
- ).toBeTruthy()
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {'function': 'organizationHasAnyModule', parameters: ['module1', 'module3']}
- )
- ).toBeTruthy()
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition(
- {'function': 'organizationHasAnyModule', parameters: ['module3']}
- )
- ).toBeFalsy()
- })
- test('organizationHasAnyModule', () => {
- // @ts-ignore
- accessProfile.isAdminAccount = true
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'accessIsAdminAccount'})).toBeTruthy()
- // @ts-ignore
- accessProfile.isAdminAccount = false
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'accessIsAdminAccount'})).toBeFalsy()
- })
- test('organizationIsSchool', () => {
- // @ts-ignore
- organizationProfile.isSchool = true
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsSchool'})).toBeTruthy()
- // @ts-ignore
- organizationProfile.isSchool = false
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsSchool'})).toBeFalsy()
- })
- test('organizationIsArtist', () => {
- // @ts-ignore
- organizationProfile.isArtist = true
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsArtist'})).toBeTruthy()
- // @ts-ignore
- organizationProfile.isArtist = false
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsArtist'})).toBeFalsy()
- })
- test('organizationIsManagerProduct', () => {
- // @ts-ignore
- organizationProfile.isManagerProduct = true
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsManagerProduct'})).toBeTruthy()
- // @ts-ignore
- organizationProfile.isManagerProduct = false
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsManagerProduct'})).toBeFalsy()
- })
- test('organizationHasChildren', () => {
- // @ts-ignore
- organizationProfile.hasChildren = true
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationHasChildren'})).toBeTruthy()
- // @ts-ignore
- organizationProfile.hasChildren = false
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationHasChildren'})).toBeFalsy()
- })
- test('organizationIsAssociation', () => {
- // @ts-ignore
- organizationProfile.isAssociation = true
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsAssociation'})).toBeTruthy()
- // @ts-ignore
- organizationProfile.isAssociation = false
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsAssociation'})).toBeFalsy()
- })
- test('organizationIsShowAdherentList', () => {
- // @ts-ignore
- organizationProfile.isShowAdherentList = true
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsShowAdherentList'})).toBeTruthy()
- // @ts-ignore
- organizationProfile.isShowAdherentList = false
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsShowAdherentList'})).toBeFalsy()
- })
- test('organizationIsCmf', () => {
- // @ts-ignore
- organizationProfile.isCmf = true
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsCmf'})).toBeTruthy()
- // @ts-ignore
- organizationProfile.isCmf = false
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationIsCmf'})).toBeFalsy()
- })
- test('organizationHasWebsite', () => {
- // @ts-ignore
- organizationProfile.getWebsite = true
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationHasWebsite'})).toBeTruthy()
- // @ts-ignore
- organizationProfile.getWebsite = false
- // @ts-ignore
- expect(abilityBuilder.execAndValidateCondition({'function': 'organizationHasWebsite'})).toBeFalsy()
- })
- test('with expected result', () => {
- // @ts-ignore
- organizationProfile.getWebsite = true
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition({'function': 'organizationHasWebsite', expectedResult: true})
- ).toBeTruthy()
- expect(
- // @ts-ignore
- abilityBuilder.execAndValidateCondition({'function': 'organizationHasWebsite', expectedResult: 'abc'})
- ).toBeFalsy()
- })
- test('invalid function', () => {
- expect(
- // @ts-ignore
- () => abilityBuilder.execAndValidateCondition({'function': 'invalid'})
- ).toThrowError('unknown condition function : invalid')
- })
- })
- describe('hasRoleAbility', () => {
- beforeEach(() => {
- ability.can = vi.fn((action: string, subject: string) => {
- return action === 'read' && subject === 'a_subject'
- })
- })
- test('owned ability', () => {
- expect(abilityBuilder.hasRoleAbility({action: ABILITIES.READ, subject: 'a_subject'})).toBeTruthy()
- })
- test('not owned ability', () => {
- expect(abilityBuilder.hasRoleAbility({action: ABILITIES.READ, subject: 'other_subject'})).toBeFalsy()
- })
- })
- describe('hasAllRoleAbilities', () => {
- beforeEach(() => {
- ability.can = vi.fn((action: string, subject: string) => {
- return action === 'read' && (subject === 'subject1' || subject === 'subject2')
- })
- })
- test('own all abilities', () => {
- const result = abilityBuilder.hasAllRoleAbilities(
- [
- {action: ABILITIES.READ, subject: 'subject1'},
- {action: ABILITIES.READ, subject: 'subject2'},
- ]
- )
- expect(result).toBeTruthy()
- })
- test('own at least one ability', () => {
- const result = abilityBuilder.hasAllRoleAbilities(
- [
- {action: ABILITIES.READ, subject: 'subject1'},
- {action: ABILITIES.READ, subject: 'subject3'},
- ]
- )
- expect(result).toBeFalsy()
- })
- test('own none of the abilities', () => {
- const result = abilityBuilder.hasAllRoleAbilities(
- [
- {action: ABILITIES.READ, subject: 'subject3'},
- {action: ABILITIES.READ, subject: 'subject4'},
- ]
- )
- expect(result).toBeFalsy()
- })
- })
- describe('hasAnyRoleAbility', () => {
- beforeEach(() => {
- ability.can = vi.fn((action: string, subject: string) => {
- return action === 'read' && (subject === 'subject1' || subject === 'subject2')
- })
- })
- test('has all abilities', () => {
- const result = abilityBuilder.hasAnyRoleAbility(
- [
- {action: ABILITIES.READ, subject: 'subject1'},
- {action: ABILITIES.READ, subject: 'subject2'},
- ]
- )
- expect(result).toBeTruthy()
- })
- test('has at least one ability', () => {
- const result = abilityBuilder.hasAnyRoleAbility(
- [
- {action: ABILITIES.READ, subject: 'subject1'},
- {action: ABILITIES.READ, subject: 'subject3'},
- ]
- )
- expect(result).toBeTruthy()
- })
- test('any none of the abilites', () => {
- const result = abilityBuilder.hasAnyRoleAbility(
- [
- {action: ABILITIES.READ, subject: 'subject3'},
- {action: ABILITIES.READ, subject: 'subject4'},
- ]
- )
- expect(result).toBeFalsy()
- })
- })
- describe('hasProfile', () => {
- test('owned profiles', () => {
- accessProfile.isAdmin = true
- accessProfile.isAdministratifManager = true
- accessProfile.isPedagogicManager = true
- accessProfile.isFinancialManager = true
- accessProfile.isCaMember = true
- accessProfile.isStudent = true
- accessProfile.isTeacher = true
- accessProfile.isMember = true
- accessProfile.isOther = true
- accessProfile.isGuardian = true
- accessProfile.isPayer = true
- expect(abilityBuilder.hasProfile('admin')).toBeTruthy()
- expect(abilityBuilder.hasProfile('administratifManager')).toBeTruthy()
- expect(abilityBuilder.hasProfile('pedagogicManager')).toBeTruthy()
- expect(abilityBuilder.hasProfile('financialManager')).toBeTruthy()
- expect(abilityBuilder.hasProfile('caMember')).toBeTruthy()
- expect(abilityBuilder.hasProfile('student')).toBeTruthy()
- expect(abilityBuilder.hasProfile('teacher')).toBeTruthy()
- expect(abilityBuilder.hasProfile('member')).toBeTruthy()
- expect(abilityBuilder.hasProfile('other')).toBeTruthy()
- expect(abilityBuilder.hasProfile('guardian')).toBeTruthy()
- expect(abilityBuilder.hasProfile('payor')).toBeTruthy()
- })
- test('not owned profiles', () => {
- accessProfile.isAdmin = false
- accessProfile.isAdministratifManager = false
- accessProfile.isPedagogicManager = false
- accessProfile.isFinancialManager = false
- accessProfile.isCaMember = false
- accessProfile.isStudent = false
- accessProfile.isTeacher = false
- accessProfile.isMember = false
- accessProfile.isOther = false
- accessProfile.isGuardian = false
- accessProfile.isPayer = false
- expect(abilityBuilder.hasProfile('admin')).toBeFalsy()
- expect(abilityBuilder.hasProfile('administratifManager')).toBeFalsy()
- expect(abilityBuilder.hasProfile('pedagogicManager')).toBeFalsy()
- expect(abilityBuilder.hasProfile('financialManager')).toBeFalsy()
- expect(abilityBuilder.hasProfile('caMember')).toBeFalsy()
- expect(abilityBuilder.hasProfile('student')).toBeFalsy()
- expect(abilityBuilder.hasProfile('teacher')).toBeFalsy()
- expect(abilityBuilder.hasProfile('member')).toBeFalsy()
- expect(abilityBuilder.hasProfile('other')).toBeFalsy()
- expect(abilityBuilder.hasProfile('guardian')).toBeFalsy()
- expect(abilityBuilder.hasProfile('payor')).toBeFalsy()
- })
- })
- describe('hasAnyProfile', () => {
- beforeEach(() => {
- accessProfile.isMember = true
- accessProfile.isGuardian = true
- accessProfile.isPayer = true
- })
- test('own all profiles', () => {
- expect(abilityBuilder.hasAnyProfile(['member', 'guardian', 'payor'])).toBeTruthy()
- })
- test('own at least one profile', () => {
- expect(abilityBuilder.hasAnyProfile(['member', 'caMember'])).toBeTruthy()
- })
- test('own none of the profiles', () => {
- expect(abilityBuilder.hasAnyProfile(['caMember', 'isFinancialManager'])).toBeFalsy()
- })
- })
- describe('hasAllProfiles', () => {
- beforeEach(() => {
- accessProfile.isMember = true
- accessProfile.isGuardian = true
- accessProfile.isPayer = true
- })
- test('own all profiles', () => {
- expect(abilityBuilder.hasAllProfiles(['member', 'guardian', 'payor'])).toBeTruthy()
- })
- test('own only one of the profiles', () => {
- expect(abilityBuilder.hasAllProfiles(['member', 'caMember'])).toBeFalsy()
- })
- test('own none of the profiles', () => {
- expect(abilityBuilder.hasAllProfiles(['caMember', 'isFinancialManager'])).toBeFalsy()
- })
- })
- describe('hasRole', () => {
- beforeEach(() => {
- // @ts-ignore
- accessProfile.hasRole = vi.fn((role: string) => role === 'foo')
- })
- test('has role', () => {
- expect(abilityBuilder.hasRole('foo')).toBeTruthy()
- })
- test('has not role', () => {
- expect(abilityBuilder.hasRole('bar')).toBeFalsy()
- })
- })
- describe('hasAnyRole', () => {
- beforeEach(() => {
- // @ts-ignore
- accessProfile.hasRole = vi.fn((role: string) => role === 'role1' || role === 'role2')
- })
- test('own all roles', () => {
- expect(abilityBuilder.hasAnyRole(['role1', 'role2'])).toBeTruthy()
- })
- test('own at least one role', () => {
- expect(abilityBuilder.hasAnyRole(['role1', 'role3'])).toBeTruthy()
- })
- test('own none of the roles', () => {
- expect(abilityBuilder.hasAnyRole(['role3'])).toBeFalsy()
- })
- })
- describe('hasAllRoles', () => {
- beforeEach(() => {
- // @ts-ignore
- accessProfile.hasRole = vi.fn((role: string) => role === 'role1' || role === 'role2')
- })
- test('own all roles', () => {
- expect(abilityBuilder.hasAllRoles(['role1', 'role2'])).toBeTruthy()
- })
- test('own at least one role', () => {
- expect(abilityBuilder.hasAllRoles(['role1', 'role3'])).toBeFalsy()
- })
- test('own none of the roles', () => {
- expect(abilityBuilder.hasAllRoles(['role3'])).toBeFalsy()
- })
- })
- describe('hasModule', () => {
- beforeEach(() => {
- // @ts-ignore
- organizationProfile.hasModule = vi.fn((module: string) => module === 'foo')
- })
- test('has module', () => {
- expect(abilityBuilder.hasModule('foo')).toBeTruthy()
- })
- test('has not module', () => {
- expect(abilityBuilder.hasModule('bar')).toBeFalsy()
- })
- })
- describe('hasAnyModule', () => {
- beforeEach(() => {
- // @ts-ignore
- organizationProfile.hasModule = vi.fn((Module: string) => Module === 'Module1' || Module === 'Module2')
- })
- test('own all modules', () => {
- expect(abilityBuilder.hasAnyModule(['Module1', 'Module2'])).toBeTruthy()
- })
- test('own at least one module', () => {
- expect(abilityBuilder.hasAnyModule(['Module1', 'Module3'])).toBeTruthy()
- })
- test('own none of the modules', () => {
- expect(abilityBuilder.hasAnyModule(['Module3'])).toBeFalsy()
- })
- })
- describe('hasAllModules', () => {
- beforeEach(() => {
- // @ts-ignore
- organizationProfile.hasModule = vi.fn((Module: string) => Module === 'Module1' || Module === 'Module2')
- })
- test('own all modules', () => {
- expect(abilityBuilder.hasAllModules(['Module1', 'Module2'])).toBeTruthy()
- })
- test('own at least one module', () => {
- expect(abilityBuilder.hasAllModules(['Module1', 'Module3'])).toBeFalsy()
- })
- test('own none of the modules', () => {
- expect(abilityBuilder.hasAllModules(['Module3'])).toBeFalsy()
- })
- })
|