#4074 useAcls #584

Merged
jorgep merged 30 commits from 4074-useAcls into dev 2024-09-10 11:50:45 +00:00
7 changed files with 52 additions and 56 deletions
Showing only changes of commit c766110bd9 - Show all commits

View File

@ -1,6 +1,7 @@
<script setup> <script setup>
import { ref, computed } from 'vue'; import { ref, computed } from 'vue';
import { useRole } from 'src/composables/useRole'; import { useRole } from 'src/composables/useRole';
import { useAcl } from 'src/composables/useAcl';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue']);
@ -11,6 +12,10 @@ const $props = defineProps({
type: Array, type: Array,
default: () => ['developer'], default: () => ['developer'],
}, },
acls: {
type: Array,
default: () => [],
},
actionIcon: { actionIcon: {
type: String, type: String,
default: 'add', default: 'add',
@ -22,9 +27,11 @@ const $props = defineProps({
}); });
const role = useRole(); const role = useRole();
const acl = useAcl()
const showForm = ref(false); const showForm = ref(false);
const isAllowedToCreate = computed(() => { const isAllowedToCreate = computed(() => {
if ($props.acls.length) console.log(acl.hasAny($props.acls));
return role.hasAny($props.rolesAllowedToCreate); return role.hasAny($props.rolesAllowedToCreate);
Review

Mantenemos retrocompatibilidad.

Mantenemos retrocompatibilidad.
}); });

View File

@ -9,6 +9,7 @@ import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue'; import VnUserLink from 'src/components/ui/VnUserLink.vue';
Review

Porque se modifica este componente reemplazando por VnTitle??

Porque se modifica este componente reemplazando <component /> por VnTitle??
Review

Porque es un summary, los summary gastan VnTitle. Si te fijas, gasta un router-link o un span con la clase link...

Porque es un summary, los summary gastan VnTitle. Si te fijas, gasta un router-link o un span con la clase link...
import { useRole } from 'src/composables/useRole'; import { useRole } from 'src/composables/useRole';
jorgep marked this conversation as resolved
Review

Porque no se hace con el archivo siguiente, crear una funcion llamada getUrl??

Porque no se hace con el archivo siguiente, crear una funcion llamada getUrl??
Review

No veo la necesidad, pero te lo cambio.

No veo la necesidad, pero te lo cambio.
import { useAcl } from 'src/composables/useAcl';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -19,21 +20,13 @@ const $props = defineProps({
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const roleState = useRole();
const entityId = computed(() => $props.id || route.params.id); const entityId = computed(() => $props.id || route.params.id);
const isBuyer = computed(() => { const canEdit = computed(() => useAcl().hasAny('Item', '*', 'WRITE'));
return roleState.hasAny(['buyer']);
});
const isReplenisher = computed(() => { const isReplenisher = computed(() => useRole().hasAny(['replenisher']));
return roleState.hasAny(['replenisher']);
});
const isAdministrative = computed(() => {
return roleState.hasAny(['administrative']);
});
</script> </script>
<template> <template>
@ -66,13 +59,13 @@ const isAdministrative = computed(() => {
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
<component <component
:is="isBuyer ? 'router-link' : 'span'" :is="canEdit ? 'router-link' : 'span'"
:to="{ name: 'ItemBasicData', params: { id: entityId } }" :to="{ name: 'ItemBasicData', params: { id: entityId } }"
class="header" class="header"
:class="{ 'header-link': isBuyer }" :class="{ 'header-link': canEdit }"
> >
{{ t('item.summary.basicData') }} {{ t('item.summary.basicData') }}
<QIcon v-if="isBuyer" name="open_in_new" /> <QIcon v-if="canEdit" name="open_in_new" />
</component> </component>
<VnLv :label="t('item.summary.name')" :value="item.name" /> <VnLv :label="t('item.summary.name')" :value="item.name" />
<VnLv :label="t('item.summary.completeName')" :value="item.longName" /> <VnLv :label="t('item.summary.completeName')" :value="item.longName" />
@ -105,13 +98,13 @@ const isAdministrative = computed(() => {
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
<component <component
:is="isBuyer ? 'router-link' : 'span'" :is="canEdit ? 'router-link' : 'span'"
:to="{ name: 'ItemBasicData', params: { id: entityId } }" :to="{ name: 'ItemBasicData', params: { id: entityId } }"
class="header" class="header"
:class="{ 'header-link': isBuyer }" :class="{ 'header-link': canEdit }"
> >
{{ t('item.summary.otherData') }} {{ t('item.summary.otherData') }}
<QIcon v-if="isBuyer" name="open_in_new" /> <QIcon v-if="canEdit" name="open_in_new" />
</component> </component>
<VnLv <VnLv
:label="t('item.summary.intrastatCode')" :label="t('item.summary.intrastatCode')"
@ -138,13 +131,13 @@ const isAdministrative = computed(() => {
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
<component <component
:is="isBuyer || isReplenisher ? 'router-link' : 'span'" :is="canEdit || isReplenisher ? 'router-link' : 'span'"
:to="{ name: 'ItemTags', params: { id: entityId } }" :to="{ name: 'ItemTags', params: { id: entityId } }"
class="header" class="header"
:class="{ 'header-link': isBuyer || isReplenisher }" :class="{ 'header-link': canEdit || isReplenisher }"
> >
{{ t('item.summary.tags') }} {{ t('item.summary.tags') }}
<QIcon v-if="isBuyer || isReplenisher" name="open_in_new" /> <QIcon v-if="canEdit || isReplenisher" name="open_in_new" />
</component> </component>
<VnLv <VnLv
v-for="(tag, index) in tags" v-for="(tag, index) in tags"
@ -155,13 +148,13 @@ const isAdministrative = computed(() => {
</QCard> </QCard>
<QCard class="vn-one" v-if="item.description"> <QCard class="vn-one" v-if="item.description">
<component <component
:is="isBuyer ? 'router-link' : 'span'" :is="canEdit ? 'router-link' : 'span'"
:to="{ name: 'ItemBasicData', params: { id: entityId } }" :to="{ name: 'ItemBasicData', params: { id: entityId } }"
class="header" class="header"
:class="{ 'header-link': isBuyer }" :class="{ 'header-link': canEdit }"
> >
{{ t('item.summary.description') }} {{ t('item.summary.description') }}
<QIcon v-if="isBuyer" name="open_in_new" /> <QIcon v-if="canEdit" name="open_in_new" />
</component> </component>
<p> <p>
{{ item.description }} {{ item.description }}
@ -169,13 +162,13 @@ const isAdministrative = computed(() => {
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
<component <component
:is="isBuyer || isAdministrative ? 'router-link' : 'span'" :is="canEdit ? 'router-link' : 'span'"
:to="{ name: 'ItemTax', params: { id: entityId } }" :to="{ name: 'ItemTax', params: { id: entityId } }"
class="header" class="header"
:class="{ 'header-link': isBuyer || isAdministrative }" :class="{ 'header-link': canEdit }"
> >
{{ t('item.summary.tax') }} {{ t('item.summary.tax') }}
<QIcon v-if="isBuyer || isAdministrative" name="open_in_new" /> <QIcon v-if="canEdit" name="open_in_new" />
</component> </component>
<VnLv <VnLv
v-for="(tax, index) in item.taxes" v-for="(tax, index) in item.taxes"
@ -186,13 +179,13 @@ const isAdministrative = computed(() => {
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
<component <component
:is="isBuyer ? 'router-link' : 'span'" :is="canEdit ? 'router-link' : 'span'"
:to="{ name: 'ItemBotanical', params: { id: entityId } }" :to="{ name: 'ItemBotanical', params: { id: entityId } }"
class="header" class="header"
:class="{ 'header-link': isBuyer }" :class="{ 'header-link': canEdit }"
> >
{{ t('item.summary.botanical') }} {{ t('item.summary.botanical') }}
<QIcon v-if="isBuyer" name="open_in_new" /> <QIcon v-if="canEdit" name="open_in_new" />
</component> </component>
<VnLv :label="t('item.summary.genus')" :value="botanical?.genus?.name" /> <VnLv :label="t('item.summary.genus')" :value="botanical?.genus?.name" />
<VnLv <VnLv
@ -202,13 +195,13 @@ const isAdministrative = computed(() => {
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
<component <component
:is="isBuyer || isReplenisher ? 'router-link' : 'span'" :is="canEdit || isReplenisher ? 'router-link' : 'span'"
:to="{ name: 'ItemBarcode', params: { id: entityId } }" :to="{ name: 'ItemBarcode', params: { id: entityId } }"
class="header" class="header"
:class="{ 'header-link': isBuyer || isReplenisher }" :class="{ 'header-link': canEdit || isReplenisher }"
> >
{{ t('item.summary.barcode') }} {{ t('item.summary.barcode') }}
<QIcon v-if="isBuyer || isReplenisher" name="open_in_new" /> <QIcon v-if="canEdit || isReplenisher" name="open_in_new" />
</component> </component>
<p v-for="(barcode, index) in item.itemBarcode" :key="index"> <p v-for="(barcode, index) in item.itemBarcode" :key="index">
{{ barcode.code }} {{ barcode.code }}

View File

@ -4,13 +4,12 @@ import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import CardSummary from 'components/ui/CardSummary.vue'; import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue'; import VnLv from 'src/components/ui/VnLv.vue';
import { useRole } from 'src/composables/useRole'; import { useAcl } from 'src/composables/useAcl';
import { dashIfEmpty } from 'src/filters'; import { dashIfEmpty } from 'src/filters';
import VnUserLink from 'src/components/ui/VnUserLink.vue'; import VnUserLink from 'src/components/ui/VnUserLink.vue';
import VnTitle from 'src/components/common/VnTitle.vue'; import VnTitle from 'src/components/common/VnTitle.vue';
const route = useRoute(); const route = useRoute();
const roleState = useRole();
const { t } = useI18n(); const { t } = useI18n();
const $props = defineProps({ const $props = defineProps({
@ -32,13 +31,11 @@ async function setData(data) {
} }
} }
const isAdministrative = computed(() => {
return roleState.hasAny(['administrative']);
});
function getUrl(section) {
return isAdministrative.value && `#/supplier/${entityId.value}/${section}`; const getUrl = (section) =>
} useAcl().hasAny('Supplier','*','WRITE') ? `#/supplier/${entityId.value}/${section}`:'';
</script> </script>
<template> <template>

View File

@ -8,7 +8,7 @@ import VnConfirm from 'components/ui/VnConfirm.vue';
import axios from 'axios'; import axios from 'axios';
import useNotify from 'src/composables/useNotify.js'; import useNotify from 'src/composables/useNotify.js';
import { useRole } from 'src/composables/useRole'; import { useAcl } from 'src/composables/useAcl';
const $props = defineProps({ const $props = defineProps({
travel: { travel: {
@ -21,7 +21,6 @@ const { t } = useI18n();
const router = useRouter(); const router = useRouter();
const quasar = useQuasar(); const quasar = useQuasar();
const { notify } = useNotify(); const { notify } = useNotify();
const role = useRole();
const redirectToCreateView = (queryParams) => { const redirectToCreateView = (queryParams) => {
router.push({ name: 'TravelCreate', query: { travelData: queryParams } }); router.push({ name: 'TravelCreate', query: { travelData: queryParams } });
@ -42,9 +41,7 @@ const cloneTravelWithEntries = async () => {
} }
}; };
const isBuyer = computed(() => { const canDelete = computed(() => useAcl().hasAny('Travel','*','WRITE'));
return role.hasAny(['buyer']);
});
const openDeleteEntryDialog = (id) => { const openDeleteEntryDialog = (id) => {
quasar quasar
@ -81,7 +78,7 @@ const deleteTravel = async (id) => {
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem <QItem
v-if="isBuyer && travel.totalEntries === 0" v-if="canDelete && travel.totalEntries === 0"
v-ripple v-ripple
clickable clickable
@click="openDeleteEntryDialog(travel.id)" @click="openDeleteEntryDialog(travel.id)"

View File

@ -13,6 +13,7 @@ import WorkerTimeControlCalendar from 'pages/Worker/Card/WorkerTimeControlCalend
import useNotify from 'src/composables/useNotify.js'; import useNotify from 'src/composables/useNotify.js';
import axios from 'axios'; import axios from 'axios';
import { useRole } from 'src/composables/useRole'; import { useRole } from 'src/composables/useRole';
import { useAcl } from 'src/composables/useAcl';
import { useWeekdayStore } from 'src/stores/useWeekdayStore'; import { useWeekdayStore } from 'src/stores/useWeekdayStore';
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import { useState } from 'src/composables/useState'; import { useState } from 'src/composables/useState';
@ -26,7 +27,6 @@ import { date } from 'quasar';
const route = useRoute(); const route = useRoute();
const { t, locale } = useI18n(); const { t, locale } = useI18n();
const { notify } = useNotify(); const { notify } = useNotify();
const { hasAny } = useRole();
const _state = useState(); const _state = useState();
const user = _state.getUser(); const user = _state.getUser();
const stateStore = useStateStore(); const stateStore = useStateStore();
@ -62,9 +62,11 @@ const arrayData = useArrayData('workerData');
const worker = computed(() => arrayData.store?.data); const worker = computed(() => arrayData.store?.data);
const isHr = computed(() => hasAny(['hr'])); const isHr = computed(() => useRole().hasAny(['hr']));
const isHimSelf = computed(() => user.value.id === Number(route.params.id)); const canSend = computed(() => useAcl().hasAny('WorkerTimeControl', 'sendMail', 'WRITE'));
const isHimself = computed(() => user.value.id === Number(route.params.id));
Review

duda: en router(index hemos rremplazado userole por useAcl, aqui proque no?

duda: en router(index hemos rremplazado userole por useAcl, aqui proque no?
Review

En este caso en concreto, no lo he tocado porque lo abordaré en otra tarea, ya que tengo que cambiar permisos y añadir otro acl. En el redmite está indicado.

En este caso en concreto, no lo he tocado porque lo abordaré en otra tarea, ya que tengo que cambiar permisos y añadir otro acl. En el redmite está indicado.
const columns = computed(() => { const columns = computed(() => {
return weekdayStore.getLocales?.map((day, index) => { return weekdayStore.getLocales?.map((day, index) => {
@ -443,7 +445,7 @@ onMounted(async () => {
<div> <div>
<QBtnGroup push class="q-gutter-x-sm" flat> <QBtnGroup push class="q-gutter-x-sm" flat>
<QBtn <QBtn
v-if="isHimSelf && state" v-if="isHimself && state"
:label="t('Satisfied')" :label="t('Satisfied')"
color="primary" color="primary"
type="submit" type="submit"
@ -451,7 +453,7 @@ onMounted(async () => {
@click="isSatisfied()" @click="isSatisfied()"
/> />
<QBtn <QBtn
v-if="isHimSelf && state" v-if="isHimself && state"
:label="t('Not satisfied')" :label="t('Not satisfied')"
color="primary" color="primary"
type="submit" type="submit"
@ -462,14 +464,14 @@ onMounted(async () => {
</QBtnGroup> </QBtnGroup>
<QBtnGroup push class="q-gutter-x-sm q-ml-none" flat> <QBtnGroup push class="q-gutter-x-sm q-ml-none" flat>
<QBtn <QBtn
v-if="reason && state && (isHimSelf || isHr)" v-if="reason && state && (isHimself || isHr)"
:label="t('Reason')" :label="t('Reason')"
color="primary" color="primary"
type="submit" type="submit"
@click="showReasonForm()" @click="showReasonForm()"
/> />
<QBtn <QBtn
v-if="isHr && state !== 'CONFIRMED' && canResend" v-if="canSend && state !== 'CONFIRMED' && canResend"
:label="state ? t('Resend') : t('globals.send')" :label="state ? t('Resend') : t('globals.send')"
color="primary" color="primary"
type="submit" type="submit"
@ -596,7 +598,7 @@ onMounted(async () => {
<WorkerTimeReasonForm <WorkerTimeReasonForm
@on-submit="isUnsatisfied($event)" @on-submit="isUnsatisfied($event)"
:reason="reason" :reason="reason"
:is-him-self="isHimSelf" :is-himself="isHimself"
/> />
</QDialog> </QDialog>
</QPage> </QPage>

View File

@ -9,7 +9,7 @@ const $props = defineProps({
type: String, type: String,
default: '', default: '',
}, },
isHimSelf: { isHimself: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
@ -40,7 +40,7 @@ const closeForm = () => {
v-model="reasonFormData" v-model="reasonFormData"
type="textarea" type="textarea"
autogrow autogrow
:disable="!isHimSelf" :disable="!isHimself"
/> />
</template> </template>
</FormPopup> </FormPopup>

View File

@ -269,7 +269,7 @@ function uppercaseStreetModel(data) {
option-label="name" option-label="name"
option-value="id" option-value="id"
hide-selected hide-selected
:roles-allowed-to-create="['salesAssistant', 'hr']" :acls="[]"
:disable="data.isFreelance" :disable="data.isFreelance"
> >
<template #form> <template #form>