From c03a56f69fb774c3399f8147bf8e5521da9769ea Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Fri, 28 Mar 2025 09:28:24 +0100
Subject: [PATCH 1/3] feat: refs #7995 added hasAcl to check only one acl

---
 src/composables/useAcl.js                             | 11 +++++++++++
 src/pages/Account/Card/AccountDescriptorMenu.vue      | 10 +++-------
 src/pages/Customer/Card/CustomerBalance.vue           |  6 ++----
 .../Ticket/Card/BasicData/TicketBasicDataForm.vue     |  4 +---
 src/pages/Ticket/Card/TicketSaleMoreActions.vue       |  4 +---
 src/pages/Travel/Card/TravelDescriptorMenuItems.vue   |  2 +-
 src/pages/Worker/Card/WorkerCalendar.vue              |  4 +---
 src/pages/Worker/Card/WorkerLocker.vue                |  8 ++------
 src/pages/Worker/Card/WorkerTimeControl.vue           |  8 ++------
 9 files changed, 24 insertions(+), 33 deletions(-)

diff --git a/src/composables/useAcl.js b/src/composables/useAcl.js
index ede359186..581e553aa 100644
--- a/src/composables/useAcl.js
+++ b/src/composables/useAcl.js
@@ -30,9 +30,20 @@ export function useAcl() {
         return false;
     }
 
+    function hasAcl(model, props, accessType) {
+        const modelAcl = state.getAcls().value[model];
+        const access = modelAcl[props];
+        if (!modelAcl || !access) return false;
+        if (access[accessType] || access['*']) {
+            return true;
+        }
+        return false;
+    }
+
     return {
         fetch,
         hasAny,
         state,
+        hasAcl,
     };
 }
diff --git a/src/pages/Account/Card/AccountDescriptorMenu.vue b/src/pages/Account/Card/AccountDescriptorMenu.vue
index eafd62df6..f3eabb531 100644
--- a/src/pages/Account/Card/AccountDescriptorMenu.vue
+++ b/src/pages/Account/Card/AccountDescriptorMenu.vue
@@ -100,12 +100,8 @@ const onChangePass = (oldPass) => {
 };
 
 onMounted(() => {
-    hasitManagementAccess.value = useAcl().hasAny([
-        { model: 'VnUser', props: 'higherPrivileges', accessType: 'WRITE' },
-    ]);
-    hasSysadminAccess.value = useAcl().hasAny([
-        { model: 'VnUser', props: 'adminUser', accessType: 'WRITE' },
-    ]);
+    hasitManagementAccess.value = useAcl().hasAcl('VnUser', 'higherPrivileges', 'WRITE');
+    hasSysadminAccess.value = useAcl().hasAcl('VnUser', 'adminUser', 'WRITE');
 });
 </script>
 <template>
@@ -227,7 +223,7 @@ onMounted(() => {
         <QItemSection>{{ t('account.card.actions.deactivateUser.name') }}</QItemSection>
     </QItem>
     <QItem
-        v-if="useAcl().hasAny([{ model: 'VnRole', props: '*', accessType: 'WRITE' }])"
+        v-if="useAcl().hasAcl('VnRole', '*', 'WRITE')"
         v-ripple
         clickable
         @click="showSyncDialog = true"
diff --git a/src/pages/Customer/Card/CustomerBalance.vue b/src/pages/Customer/Card/CustomerBalance.vue
index 11db92eab..eea532de6 100644
--- a/src/pages/Customer/Card/CustomerBalance.vue
+++ b/src/pages/Customer/Card/CustomerBalance.vue
@@ -24,7 +24,7 @@ import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescr
 const { openConfirmationModal } = useVnConfirm();
 const { sendEmail, openReport } = usePrintService();
 const { t } = useI18n();
-const { hasAny } = useAcl();
+const { hasAcl } = useAcl();
 
 const quasar = useQuasar();
 const route = useRoute();
@@ -276,9 +276,7 @@ const showBalancePdf = ({ id }) => {
             >
                 <VnInput
                     v-model="scope.value"
-                    :disable="
-                        !hasAny([{ model: 'Receipt', props: '*', accessType: 'WRITE' }])
-                    "
+                    :disable="!hasAcl('Receipt', '*', 'WRITE')"
                     @keypress.enter="scope.set"
                     autofocus
                 />
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
index 9d70fea38..61932468c 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
@@ -25,9 +25,7 @@ const { validate } = useValidator();
 const { notify } = useNotify();
 const router = useRouter();
 const { t } = useI18n();
-const canEditZone = useAcl().hasAny([
-    { model: 'Ticket', props: 'editZone', accessType: 'WRITE' },
-]);
+const canEditZone = useAcl().hasAcl('Ticket', 'editZone', 'WRITE');
 
 const agencyFetchRef = ref();
 const warehousesOptions = ref([]);
diff --git a/src/pages/Ticket/Card/TicketSaleMoreActions.vue b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
index 773b0807f..864bfd03f 100644
--- a/src/pages/Ticket/Card/TicketSaleMoreActions.vue
+++ b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
@@ -55,9 +55,7 @@ const isClaimable = computed(() => {
     if (ticket.value) {
         const landedPlusWeek = new Date(ticket.value.landed);
         landedPlusWeek.setDate(landedPlusWeek.getDate() + 7);
-        const createAfterDeadline = acl.hasAny([
-            { model: 'Claim', props: 'createAfterDeadline', accessType: 'WRITE' },
-        ]);
+        const createAfterDeadline = acl.hasAcl('Claim', 'createAfterDeadline', 'WRITE');
         return landedPlusWeek >= Date.vnNew() || createAfterDeadline;
     }
     return false;
diff --git a/src/pages/Travel/Card/TravelDescriptorMenuItems.vue b/src/pages/Travel/Card/TravelDescriptorMenuItems.vue
index 14d824b86..f8828bffe 100644
--- a/src/pages/Travel/Card/TravelDescriptorMenuItems.vue
+++ b/src/pages/Travel/Card/TravelDescriptorMenuItems.vue
@@ -37,7 +37,7 @@ const cloneTravelWithEntries = async () => {
     router.push({ name: 'TravelBasicData', params: { id: data.id } });
 };
 
-const canDelete = computed(() => useAcl().hasAny('Travel', '*', 'WRITE'));
+const canDelete = computed(() => useAcl().hasAcl('Travel', '*', 'WRITE'));
 
 const openDeleteEntryDialog = (id) => {
     quasar
diff --git a/src/pages/Worker/Card/WorkerCalendar.vue b/src/pages/Worker/Card/WorkerCalendar.vue
index df4616011..05ebb4687 100644
--- a/src/pages/Worker/Card/WorkerCalendar.vue
+++ b/src/pages/Worker/Card/WorkerCalendar.vue
@@ -18,9 +18,7 @@ const router = useRouter();
 const route = useRoute();
 const { t } = useI18n();
 const acl = useAcl();
-const canSeeNotes = computed(() =>
-    acl.hasAny([{ model: 'Worker', props: '__get__business', accessType: 'READ' }]),
-);
+const canSeeNotes = computed(() => acl.hasAcl('Worker', '__get__business', 'READ'));
 const workerIsFreelance = ref();
 const WorkerFreelanceRef = ref();
 const workerCalendarFilterRef = ref(null);
diff --git a/src/pages/Worker/Card/WorkerLocker.vue b/src/pages/Worker/Card/WorkerLocker.vue
index 015bced35..62891070d 100644
--- a/src/pages/Worker/Card/WorkerLocker.vue
+++ b/src/pages/Worker/Card/WorkerLocker.vue
@@ -9,7 +9,7 @@ import VnSelect from 'src/components/common/VnSelect.vue';
 import { useArrayData } from 'src/composables/useArrayData';
 import FetchData from 'components/FetchData.vue';
 
-const { hasAny } = useAcl();
+const { hasAcl } = useAcl();
 const { t } = useI18n();
 const fetchData = ref();
 const originaLockerId = ref();
@@ -58,11 +58,7 @@ const init = async (data) => {
                 option-label="code"
                 option-value="id"
                 hide-selected
-                :readonly="
-                    !hasAny([
-                        { model: 'Worker', props: '__get__locker', accessType: 'READ' },
-                    ])
-                "
+                :readonly="!hasAcl('Worker', '__get__locker', 'READ')"
             />
         </template>
     </FormModel>
diff --git a/src/pages/Worker/Card/WorkerTimeControl.vue b/src/pages/Worker/Card/WorkerTimeControl.vue
index 9c0fa6758..b64166c7d 100644
--- a/src/pages/Worker/Card/WorkerTimeControl.vue
+++ b/src/pages/Worker/Card/WorkerTimeControl.vue
@@ -68,13 +68,9 @@ const arrayData = useArrayData('Worker');
 const acl = useAcl();
 const selectedDateYear = computed(() => moment(selectedDate.value).isoWeekYear());
 const worker = computed(() => arrayData.store?.data);
-const canSend = computed(() =>
-    acl.hasAny([{ model: 'WorkerTimeControl', props: 'sendMail', accessType: 'WRITE' }]),
-);
+const canSend = computed(() => acl.hasAcl('WorkerTimeControl', 'sendMail', 'WRITE'));
 const canUpdate = computed(() =>
-    acl.hasAny([
-        { model: 'WorkerTimeControl', props: 'updateMailState', accessType: 'WRITE' },
-    ]),
+    acl.hasAcl('WorkerTimeControl', 'updateMailState', 'WRITE'),
 );
 const isHimself = computed(() => user.value.id === Number(route.params.id));
 

From f8cc7b95abe28463859b7e02e7daf705330f38e5 Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Mon, 31 Mar 2025 09:51:40 +0200
Subject: [PATCH 2/3] refactor: refs #7995 modified hasAcl function

---
 src/composables/useAcl.js | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/composables/useAcl.js b/src/composables/useAcl.js
index 581e553aa..4033ee9a6 100644
--- a/src/composables/useAcl.js
+++ b/src/composables/useAcl.js
@@ -32,12 +32,13 @@ export function useAcl() {
 
     function hasAcl(model, props, accessType) {
         const modelAcl = state.getAcls().value[model];
-        const access = modelAcl[props];
-        if (!modelAcl || !access) return false;
-        if (access[accessType] || access['*']) {
-            return true;
-        }
-        return false;
+        const propAcl = modelAcl[props] || {};
+        return !!(
+            propAcl[accessType] ||
+            modelAcl['*']?.[accessType] ||
+            propAcl['*'] ||
+            modelAcl['*']?.['*']
+        );
     }
 
     return {

From b00d89a4bee022b8810ff7b308332e8691cce30f Mon Sep 17 00:00:00 2001
From: Jon <jon@verdnatura.es>
Date: Tue, 1 Apr 2025 09:34:38 +0200
Subject: [PATCH 3/3] perf: refs #7995 has acl function

---
 src/composables/useAcl.js | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/src/composables/useAcl.js b/src/composables/useAcl.js
index 4033ee9a6..52704fee9 100644
--- a/src/composables/useAcl.js
+++ b/src/composables/useAcl.js
@@ -30,15 +30,10 @@ export function useAcl() {
         return false;
     }
 
-    function hasAcl(model, props, accessType) {
+    function hasAcl(model, prop, accessType) {
         const modelAcl = state.getAcls().value[model];
-        const propAcl = modelAcl[props] || {};
-        return !!(
-            propAcl[accessType] ||
-            modelAcl['*']?.[accessType] ||
-            propAcl['*'] ||
-            modelAcl['*']?.['*']
-        );
+        const propAcl = modelAcl?.[prop] || modelAcl?.['*'];
+        return !!(propAcl?.[accessType] || propAcl?.['*']);
     }
 
     return {