Vincent GUFFON 4 年之前
父节点
当前提交
5f45e1499b

+ 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}

+ 16 - 0
lang/layout/fr-FR.js

@@ -105,5 +105,21 @@ export default (context, locale) => {
     my_list: 'Mes listes',
     searchList: 'Rechercher parmis mes listes personnalisées',
     template_systems: "Mails système",
+    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",
   })
 }

+ 59 - 4
services/profile/accessProfile.ts

@@ -1,5 +1,6 @@
 import {AbilitiesType, accessState, AccessStore, AnyJson} from "~/types/interfaces";
 import {Ability} from "@casl/ability";
+import {Store} from "vuex";
 
 /**
  * @category Services/profiles
@@ -10,6 +11,7 @@ class AccessProfile{
   private accessProfile: accessState
 
   private $ability:Ability = {} as Ability
+  private store:Store<any>
 
   /**
    * @constructor
@@ -19,6 +21,7 @@ class AccessProfile{
   constructor(store:AccessStore, ability:Ability) {
     this.accessProfile = store.state.profile.access
     this.$ability = ability
+    this.store = store
   }
 
   /**
@@ -40,21 +43,71 @@ class AccessProfile{
 
   /**
    * Est-ce que l'utilisateur possède l'abilité
-   * @param {Array<AbilitiesType>} ability abilité à tester
+   * @param {Array<AbilitiesType>} abilities abilités à tester
    * @return {boolean}
    */
-  hasAbility(ability:Array<AbilitiesType>): boolean{
-    if(ability === null)
+  hasAbility(abilities:Array<AbilitiesType>): boolean{
+    if(abilities === null)
       return true;
 
     let hasAbility= false;
-    ability.map((ability) => {
+    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,
+    }
+
+    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
+  }
+
   /**
    * Factory
    * @return {AnyJson} retourne les fonction rendues publiques
@@ -63,6 +116,8 @@ class AccessProfile{
     return {
       hasRole: this.hasRole.bind(this),
       hasAbility: this.hasAbility.bind(this),
+      hasProfile: this.hasProfile.bind(this),
+      isAdminAccount: this.isAdminAccount.bind(this)
     }
   }
 }

+ 10 - 1
services/profile/organizationProfile.ts

@@ -117,13 +117,21 @@ class OrganizationProfile{
   }
 
   /**
-   * L'organization possède t'elledes enfants
+   * L'organization possède t'elle des enfants
    * @return {boolean|null}
    */
   isOrganizationWithChildren():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
    * @return {AnyJson} retourne les fonction rendues publiques
@@ -135,6 +143,7 @@ class OrganizationProfile{
       isArtist: this.isArtist.bind(this),
       isManagerProduct: this.isManagerProduct.bind(this),
       isOrganizationWithChildren: this.isOrganizationWithChildren.bind(this),
+      isShowAdherentList: this.isShowAdherentList.bind(this),
       isCmf: this.isCmf.bind(this)
     }
   }

+ 10 - 8
services/rights/abilitiesUtils.ts

@@ -59,7 +59,7 @@ class AbilitiesUtils {
         switch (action.type) {
           case 'profile/organization/setProfile':
             //On récupère les abilités
-            const abilities = this.getAbilities();
+            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)
@@ -77,7 +77,7 @@ class AbilitiesUtils {
    * @return {Array<AbilitiesType>}
    */
   getAbilities():Array<AbilitiesType> {
-    const abilitiesByRoles = this.getAbilitiesByRoles(this.$store.state.profile.access.roles)
+    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,15 +149,17 @@ class AbilitiesUtils {
    * @return {boolean}
    */
   canHaveTheAbility(functionByservices: AnyJson) {
-    let hasAbility = true;
+    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++
         }

+ 11 - 0
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,6 +102,12 @@ export const mutations = {
   setIsOther(state:accessState, isRole:boolean){
     state.isOther = isRole
   },
+  setIsGuardian(state:accessState, isGuardian:boolean){
+    state.isGuardian = isGuardian
+  },
+  setIsPayor(state:accessState, isPayor:boolean){
+    state.isPayor = isPayor
+  },
   setHasLateralMenu(state:accessState, hasLateralMenu:boolean){
     state.hasLateralMenu = hasLateralMenu
   },
@@ -142,6 +151,8 @@ export const actions = {
     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)
 

+ 5 - 0
store/profile/organization.ts

@@ -7,6 +7,7 @@ export const state = () => ({
   product: '',
   modules: [],
   hasChildren: false,
+  showAdherentList: false,
   networks: [],
   website: '',
   subDomain: '',
@@ -29,6 +30,9 @@ export const mutations = {
   setHasChildren(state:organizationState, hasChildren:boolean) {
     state.hasChildren = hasChildren
   },
+  setShowAdherentList(state:organizationState, showAdherentList:boolean) {
+    state.showAdherentList = showAdherentList
+  },
   setNetworks(state:organizationState, networks:Array<string>) {
     state.networks = networks
   },
@@ -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>,
 }

+ 61 - 3
use/layout/Menus/accountMenu.ts

@@ -29,11 +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))
     }
 
-    return children.length > 0 ? this.constructMenu('configuration', 'fa-user', undefined, undefined, children) : null;
+    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('my_account', 'fa-user', undefined, undefined, children) : null;
   }
 }