Browse Source

Merge branch 'feature/BTTF-56' into develop

# Conflicts:
#	lang/layout/fr-FR.js
#	services/profile/accessProfile.ts
#	services/profile/organizationProfile.ts
#	services/rights/abilitiesUtils.ts
#	store/profile/access.ts
#	store/profile/organization.ts
#	use/layout/Menus/accountMenu.ts
Vincent GUFFON 4 years ago
parent
commit
bad9dc13de

+ 100 - 0
config/abilities/pages/myAccount.yaml

@@ -0,0 +1,100 @@
+  my_schedule_page:
+    action: 'display'
+    services:
+      access:
+        - { function: isAdminAccount, result: false }
+
+  attendance_bookings_page:
+    action: 'display'
+    services:
+      access:
+        - {function: hasAbility, parameters: [{action: 'write', subject: 'attendances'}]}
+      organization:
+        - {function: hasModule, parameters: ['Attendances']}
+
+  my_attendance_page:
+    action: 'display'
+    services:
+      access:
+        - { function: isAdminAccount, result: false }
+
+  my_invitation_page:
+    action: 'display'
+    services:
+      access:
+        - { function: isAdminAccount, result: false }
+
+  my_students_page:
+    action: 'display'
+    services:
+      access:
+        - { function: hasProfile, parameters: [ 'teacher'] }
+
+  my_students_education_students_page:
+    action: 'display'
+    services:
+      access:
+        - { function: hasProfile, parameters: [ 'teacher'] }
+
+  criteria_notations_page_from_account_menu:
+    action: 'display'
+    services:
+      access:
+        - {function: hasAbility, parameters: [{action: 'read', subject: 'criterianotation'}]}
+      organization:
+        - {function: hasModule, parameters: ['PedagogicsAdministation']}
+
+  my_education_students_page:
+    action: 'display'
+    services:
+      access:
+        - { function: hasProfile, parameters: [ 'student'] }
+
+  send_an_email_page:
+    action: 'display'
+    services:
+      access:
+        - { function: hasProfile, parameters: [ 'admin', 'teacher' ] }
+
+  my_documents_page:
+    action: 'display'
+    services:
+      access:
+        - { function: isAdminAccount, result: false }
+
+  my_profile_page:
+    action: 'display'
+    services:
+      access:
+        - { function: isAdminAccount, result: false }
+
+  adherent_list_page:
+    action: 'display'
+    services:
+      access:
+        - { function: hasProfile, parameters: [ 'member'] }
+      organization:
+        - {function: isShowAdherentList}
+        - {function: hasModule, parameters: ['Users']}
+
+  subscription_page:
+    action: 'display'
+    services:
+      access:
+        - { function: hasProfile, parameters: ['admin', 'administratifManager', 'pedagogicManager', 'financialManager']}
+      organization:
+        - {function: hasModule, parameters: ['GeneralConfig']}
+
+  my_bills_page:
+    action: 'display'
+    services:
+      access:
+        - { function: hasProfile, parameters: ['guardian', 'payor']}
+
+  cmf_licence_page:
+    action: 'display'
+    services:
+      access:
+        - { function: isAdminAccount, result: false }
+      organization:
+        - {function: isCmf}

+ 17 - 2
lang/layout/fr-FR.js

@@ -105,11 +105,26 @@ export default (context, locale) => {
     my_list: 'Mes listes',
     searchList: 'Rechercher parmi mes listes personnalisées',
     template_systems: 'Mails système',
-    my_subscription: 'Mon abonnement',
     informations: 'Informations',
     more_features: 'Plus de fonctionnalités',
     client_id: 'Numéro de client',
     version: 'Version',
-    paying_structure: 'Établissement payeur'
+    paying_structure: 'Établissement payeur',
+    my_account: 'Mon compte',
+    my_schedule_page: "Mon planning",
+    attendance_bookings_menu: "Gestion des absences & fiches de présence",
+    my_attendance: "Mes absences",
+    my_invitation: "Mes invitations",
+    my_students: "Mes élèves",
+    my_students_education_students: "Suivi pédagogique",
+    my_education_students: "Mes évaluations",
+    send_an_email: "Envoyer un email",
+    my_documents: "Mes documents",
+    my_profile: "Mon profil",
+    adherent_list: "Liste des adhérents avec leurs coordonnées",
+    my_subscription: "Mon abonnement",
+    my_bills: "Mes factures",
+    print_my_licence: "Imprimer ma licence CMF",
+    logout: "Se déconnecter",
   })
 }

+ 70 - 15
services/profile/accessProfile.ts

@@ -1,5 +1,6 @@
-import { Ability } from '@casl/ability'
-import { AbilitiesType, accessState, AccessStore, AnyJson } from '~/types/interfaces'
+import {AbilitiesType, accessState, AccessStore, AnyJson} from "~/types/interfaces";
+import {Ability} from "@casl/ability";
+import {Store} from "vuex";
 
 /**
  * L'AccessProfile permet de manipuler l'AccessState l'Access qui peuvent
@@ -8,7 +9,9 @@ import { AbilitiesType, accessState, AccessStore, AnyJson } from '~/types/interf
  */
 class AccessProfile {
   private accessProfile: accessState
-  private $ability: Ability = {} as Ability
+
+  private $ability:Ability = {} as Ability
+  private store:Store<any>
 
   /**
    * @constructor
@@ -19,6 +22,7 @@ class AccessProfile {
   constructor (store: AccessStore, ability: Ability) {
     this.accessProfile = store.state.profile.access
     this.$ability = ability
+    this.store = store
   }
 
   /**
@@ -42,21 +46,70 @@ class AccessProfile {
   }
 
   /**
-   * Est-ce que l'utilisateur possède l'habilité?
-   *
-   * @param {Array<AbilitiesType>} ability habilité à tester
+   * Est-ce que l'utilisateur possède l'abilité
+   * @param {Array<AbilitiesType>} abilities abilités à tester
    * @return {boolean}
    */
-  hasAbility (ability: Array<AbilitiesType>): boolean {
-    if (ability === null) {
-      return true
+  hasAbility(abilities:Array<AbilitiesType>): boolean{
+    if(abilities === null)
+      return true;
+
+    let hasAbility= false;
+    abilities.map((ability) => {
+      if (this.$ability.can(ability.action, ability.subject))
+        hasAbility = true;
+    });
+    return hasAbility;
+  }
+
+  /**
+   * Retourne vrai si l'utilisateur connecté possède l'un des profiles passés en paramètre
+   * @param {Array<string>} profiles : profiles à tester
+   * @return {boolean}
+   */
+  hasProfile(profiles: Array<string>): boolean{
+    if (null === profiles)
+      return true;
+
+    let hasProfile = false;
+    profiles.map(async (profile) => {
+      if (this.testProfile(profile))
+        hasProfile = true;
+    });
+    return hasProfile;
+  }
+
+  /**
+   * Factory pour tester le profil d'un utilisateur
+   * @param {string} profile : profile à tester
+   * @return {boolean}
+   */
+  testProfile(profile:string): boolean{
+    const factory: {[key: string]: boolean} = {
+      'admin': this.accessProfile.isAdmin,
+      'administratifManager': this.accessProfile.isAdministratifManager,
+      'pedagogicManager': this.accessProfile.isPedagogicManager,
+      'financialManager': this.accessProfile.isFinancialManager,
+      'caMember': this.accessProfile.isCaMember,
+      'student': this.accessProfile.isStudent,
+      'teacher': this.accessProfile.isTeacher,
+      'member': this.accessProfile.isMember,
+      'other': this.accessProfile.isOther,
+      'guardian': this.accessProfile.isGuardian,
+      'payor': this.accessProfile.isPayor,
     }
 
-    let hasAbility = false
-    ability.map((ability) => {
-      if (this.$ability.can(ability.action, ability.subject)) { hasAbility = true }
-    })
-    return hasAbility
+    if(profile in factory)
+      return factory[profile]
+    else return false
+  }
+
+  /**
+   * Est-ce que l'utilisateur possède un compte administrateur
+   * @return {boolean}
+   */
+  isAdminAccount(): boolean{
+    return this.accessProfile.isAdminAccess
   }
 
   /**
@@ -67,7 +120,9 @@ class AccessProfile {
   handler (): AnyJson {
     return {
       hasRole: this.hasRole.bind(this),
-      hasAbility: this.hasAbility.bind(this)
+      hasAbility: this.hasAbility.bind(this),
+      hasProfile: this.hasProfile.bind(this),
+      isAdminAccount: this.isAdminAccount.bind(this)
     }
   }
 }

+ 10 - 1
services/profile/organizationProfile.ts

@@ -121,13 +121,21 @@ class OrganizationProfile {
   }
 
   /**
-   * L'organization possède-t-elle des enfants
+   * L'organization possède t-elle des enfants
    * @return {boolean|null}
    */
   hasChildren (): any {
     return this.organizationProfile.hasChildren
   }
 
+  /**
+   * L'organization peut elle afficher la lister des adhérents avec leurs coordonnées
+   * @return {boolean|null}
+   */
+  isShowAdherentList():any{
+    return this.organizationProfile.showAdherentList;
+  }
+
   /**
    * Factory
    *
@@ -140,6 +148,7 @@ class OrganizationProfile {
       isArtist: this.isArtist.bind(this),
       isManagerProduct: this.isManagerProduct.bind(this),
       isOrganizationWithChildren: this.hasChildren.bind(this),
+      isShowAdherentList: this.isShowAdherentList.bind(this),
       isCmf: this.isCmf.bind(this)
     }
   }

+ 18 - 13
services/rights/abilitiesUtils.ts

@@ -58,7 +58,10 @@ class AbilitiesUtils {
 
         switch (action.type) {
           case 'profile/organization/setProfile':
-            // On les store puis on update le service ability pour le mettre à jour.
+            //On récupère les abilités
+            const abilities: Array<AbilitiesType> = this.getAbilities();
+
+            //On les store puis on update le service ability pour le mettre à jour.
             this.$store.commit('profile/access/setAbilities', abilities)
             this.$ability.update(abilities)
             // Unsubscribe pour éviter les memory leaks
@@ -74,10 +77,10 @@ class AbilitiesUtils {
    *
    * @return {Array<AbilitiesType>}
    */
-  getAbilities (): Array<AbilitiesType> {
-    const abilitiesByRoles = this.getAbilitiesByRoles(this.$store.state.profile.access.roles)
-    this.$ability.update(abilitiesByRoles)
-    this.initFactory()
+  getAbilities():Array<AbilitiesType> {
+    const abilitiesByRoles: Array<AbilitiesType> = this.getAbilitiesByRoles(this.$store.state.profile.access.roles)
+    this.$ability.update(abilitiesByRoles);
+    this.initFactory();
     return abilitiesByRoles.concat(this.getAbilitiesByConfig('./config/abilities/config.yaml'))
   }
 
@@ -149,16 +152,18 @@ class AbilitiesUtils {
    * @param {AnyJson} functionByServices
    * @return {boolean}
    */
-  canHaveTheAbility (functionByServices: AnyJson) {
-    let hasAbility = true
-    _.each(functionByServices, (functions, service) => {
+  canHaveTheAbility(functionByservices: AnyJson) {
+    let hasAbility: boolean = true;
+    _.each(functionByservices, (functions, service) => {
       if (hasAbility) {
-        const nbFunctions = functions.length
-        let cmpt = 0
+        const nbFunctions: number = functions.length
+        let cmpt: number = 0
+
         while (hasAbility && nbFunctions > cmpt) {
-          const f = functions[cmpt].function
-          const parameters = functions[cmpt].parameters ?? null
-          const result = functions[cmpt].result ?? null
+          const f: string = functions[cmpt]['function'];
+          const parameters: any = functions[cmpt]['parameters'] ?? null;
+          const result: boolean = functions[cmpt]['result'] ?? true;
+
           hasAbility = result !== null ? this.factory[service].handler()[f](parameters) == result : this.factory[service].handler()[f](parameters)
           cmpt++
         }

+ 22 - 11
store/profile/access.ts

@@ -17,6 +17,7 @@ export const state = () => ({
   historical: [],
   roles: [],
   abilities: [],
+  isAdminAccess: false,
   isAdmin: false,
   isAdministratifManager: false,
   isPedagogicManager: false,
@@ -26,6 +27,8 @@ export const state = () => ({
   isTeacher: false,
   isMember: false,
   isOther: false,
+  isGuardian: false,
+  isPayor: false,
   hasLateralMenu: false,
   hasConfigurationMenu: false,
   hasAccessesMenu: false,
@@ -99,7 +102,13 @@ export const mutations = {
   setIsOther (state: accessState, isRole: boolean) {
     state.isOther = isRole
   },
-  setHasLateralMenu (state: accessState, hasLateralMenu: boolean) {
+  setIsGuardian(state:accessState, isGuardian:boolean){
+    state.isGuardian = isGuardian
+  },
+  setIsPayor(state:accessState, isPayor:boolean){
+    state.isPayor = isPayor
+  },
+  setHasLateralMenu(state:accessState, hasLateralMenu:boolean){
     state.hasLateralMenu = hasLateralMenu
   },
   setHasConfigurationMenu (state: accessState, hasConfigurationMenu: boolean) {
@@ -133,16 +142,18 @@ export const actions = {
     context.commit('setActivityYear', profile.activityYear)
     context.commit('setHistorical', profile.historical)
     context.commit('setIsAdminAccess', profile.isAdminAccess)
-    context.commit('setIsAdmin', $roleUtils.isA('ADMIN', rolesArray))
-    context.commit('setIsAdministratifManager', $roleUtils.isA('ADMINISTRATIF_MANAGER', rolesArray))
-    context.commit('setIsPedagogicManager', $roleUtils.isA('PEDAGOGICS_MANAGER', rolesArray))
-    context.commit('setIsFinancialManager', $roleUtils.isA('FINANCIAL_MANAGER', rolesArray))
-    context.commit('setIsCaMember', $roleUtils.isA('CA', rolesArray))
-    context.commit('setIsStudent', $roleUtils.isA('STUDENT', rolesArray))
-    context.commit('setIsTeacher', $roleUtils.isA('TEACHER', rolesArray))
-    context.commit('setIsMember', $roleUtils.isA('MEMBER', rolesArray))
-    context.commit('setIsOther', $roleUtils.isA('OTHER', rolesArray))
-    context.commit('setRoles', $roleUtils.filterFunctionRoles(rolesArray))
+    context.commit('setIsAdmin', $roleUtils.isA('ADMIN', roles_to_array))
+    context.commit('setIsAdministratifManager', $roleUtils.isA('ADMINISTRATIF_MANAGER', roles_to_array))
+    context.commit('setIsPedagogicManager', $roleUtils.isA('PEDAGOGICS_MANAGER', roles_to_array))
+    context.commit('setIsFinancialManager', $roleUtils.isA('FINANCIAL_MANAGER', roles_to_array))
+    context.commit('setIsCaMember', $roleUtils.isA('CA', roles_to_array))
+    context.commit('setIsStudent', $roleUtils.isA('STUDENT', roles_to_array))
+    context.commit('setIsTeacher', $roleUtils.isA('TEACHER', roles_to_array))
+    context.commit('setIsMember', $roleUtils.isA('MEMBER', roles_to_array))
+    context.commit('setIsOther', $roleUtils.isA('OTHER', roles_to_array))
+    context.commit('setIsGuardian', profile.isGuardian)
+    context.commit('setIsPayor', profile.isPayor)
+    context.commit('setRoles', $roleUtils.filterFunctionRoles(roles_to_array))
     context.commit('setIsAdminAccess', profile.isAdminAccess)
 
     // Time to set Multi Accesses

+ 6 - 1
store/profile/organization.ts

@@ -7,6 +7,7 @@ export const state = () => ({
   product: '',
   modules: [],
   hasChildren: false,
+  showAdherentList: false,
   networks: [],
   website: '',
   subDomain: '',
@@ -29,7 +30,10 @@ export const mutations = {
   setHasChildren (state: organizationState, hasChildren: boolean) {
     state.hasChildren = hasChildren
   },
-  setNetworks (state: organizationState, networks: Array<string>) {
+  setShowAdherentList(state:organizationState, showAdherentList:boolean) {
+    state.showAdherentList = showAdherentList
+  },
+  setNetworks(state:organizationState, networks:Array<string>) {
     state.networks = networks
   },
   setParents (state: organizationState, parents: Array<organizationState>) {
@@ -55,6 +59,7 @@ export const actions = {
     context.commit('setSubDomain', profile.subDomain)
     context.commit('setModules', profile.modules)
     context.commit('setHasChildren', profile.hasChildren)
+    context.commit('setShowAdherentList', profile.showAdherentList)
     context.commit('setNetworks', profile.networks)
 
     _.each(profile.parents, (parent) => {

+ 24 - 0
tests/unit/services/profile/accessProfile.spec.ts

@@ -55,3 +55,27 @@ describe('hasAbility()', () => {
     expect(accessProfile.hasAbility(ability_to_have)).toBeTruthy()
   })
 })
+
+describe('hasProfile()', () => {
+  it('should return true if there is no profile', () => {
+    expect(accessProfile.hasProfile(null)).toBeTruthy()
+  })
+
+  it('should return false if user do not have the profile', () =>{
+    const profile_to_have = ['admin']
+    expect(accessProfile.hasProfile(profile_to_have)).toBeFalsy()
+  })
+
+  it('should return true if user have the profile', () =>{
+    const profile_to_have = ['admin']
+    store.commit('access/setIsAdmin', true)
+    expect(accessProfile.hasProfile(profile_to_have)).toBeTruthy()
+  })
+})
+
+describe('testProfile()', () => {
+  it('should return false if profile do not exist', () => {
+    const profile_to_test = ['none']
+    expect(accessProfile.testProfile(profile_to_test)).toBeFalsy()
+  })
+})

+ 3 - 0
types/interfaces.d.ts

@@ -95,6 +95,8 @@ interface accessState extends baseAccessState {
   isTeacher: boolean,
   isMember: boolean,
   isOther: boolean,
+  isGuardian: boolean,
+  isPayor: boolean,
   hasLateralMenu: boolean,
   hasConfigurationMenu: boolean,
   hasAccessesMenu: boolean,
@@ -119,6 +121,7 @@ interface organizationState extends baseOrganizationState {
   product?: string,
   modules?: Array<string>,
   hasChildren?: boolean,
+  showAdherentList?: boolean,
   networks: Array<string>,
   parents: Array<organizationState>,
 }

+ 60 - 4
use/layout/Menus/accountMenu.ts

@@ -29,13 +29,69 @@ class AccountMenu extends BaseMenu implements Menu {
   getHeaderMenu (): ItemMenu | null {
     const children: ItemsMenu = []
 
-    if (this.$ability.can('display', 'organization_page')) {
-      children.push(this.constructMenu('organization_page', undefined, '/organization/edit'))
+    if (this.$ability.can('display', 'my_schedule_page')) {
+      children.push(this.constructMenu('my_schedule_page', undefined, '/my_calendar', true))
     }
 
-    children.push(this.constructMenu('my_subscription', undefined, '/organization/subscription'))
+    if (this.$ability.can('display', 'attendance_bookings_page')) {
+      children.push(this.constructMenu('attendance_bookings_menu', undefined, '/attendance_bookings', true))
+    }
+
+    if (this.$ability.can('display', 'my_attendance_page')) {
+      children.push(this.constructMenu('my_attendance', undefined, '/my_attendances/list', true))
+    }
+
+    if (this.$ability.can('display', 'my_invitation_page')) {
+      children.push(this.constructMenu('my_invitation', undefined, '/my_invitations/list', true))
+    }
+
+    if (this.$ability.can('display', 'my_students_page')) {
+      children.push(this.constructMenu('my_students', undefined, '/my_students/list', true))
+    }
+
+    if (this.$ability.can('display', 'my_students_education_students_page')) {
+      children.push(this.constructMenu('my_students_education_students', undefined, '/my_students_education_students/list', true))
+    }
+
+    if (this.$ability.can('display', 'criteria_notations_page') || this.$ability.can('display', 'criteria_notations_page_from_account_menu')) {
+      children.push(this.constructMenu('criteria_notations', undefined, '/criteria_notations/list', true))
+    }
+
+    if (this.$ability.can('display', 'my_education_students_page')) {
+      children.push(this.constructMenu('my_education_students', undefined, `/main/my_profile/${this.$store.state.profile.access.id}/dashboard/my_education_students/list`, true))
+    }
+
+    if (this.$ability.can('display', 'send_an_email_page')) {
+      children.push(this.constructMenu('send_an_email', undefined, `/list/create/emails`, true))
+    }
+
+    if (this.$ability.can('display', 'my_documents_page')) {
+      children.push(this.constructMenu('my_documents', undefined, `/main/my_profile/${this.$store.state.profile.access.id}/dashboard/show/my_access_file`, true))
+    }
+
+    if (this.$ability.can('display', 'my_profile_page')) {
+      children.push(this.constructMenu('my_profile', undefined, `/main/my_profile/${this.$store.state.profile.access.id}/dashboard`, true))
+    }
+
+    if (this.$ability.can('display', 'adherent_list_page')) {
+      children.push(this.constructMenu('adherent_list', undefined, `/adherent_contacts/list/`, true))
+    }
+
+    if (this.$ability.can('display', 'subscription_page')) {
+      children.push(this.constructMenu('my_subscription', undefined, `/subscription`, true))
+    }
+
+    if (this.$ability.can('display', 'my_bills_page')) {
+      children.push(this.constructMenu('my_bills', undefined, `/main/my_profile/${this.$store.state.profile.access.id}/dashboard/show/my_bills`, true))
+    }
+
+    if (this.$ability.can('display', 'cmf_licence_page')) {
+      children.push(this.constructMenu('print_my_licence', undefined, `/licence-cmf`, true))
+    }
+
+    children.push(this.constructMenu('logout', undefined, `/logout`, true))
 
-    return children.length > 0 ? this.constructMenu('configuration', 'fa-user', undefined, undefined, children) : null
+    return children.length > 0 ? this.constructMenu('my_account', 'fa-user', undefined, undefined, children) : null;
   }
 }