@@ -7,6 +7,7 @@
|
|||||||
"php": ">=8.4",
|
"php": ">=8.4",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-iconv": "*",
|
"ext-iconv": "*",
|
||||||
|
"ext-soap": "*",
|
||||||
"api-platform/doctrine-orm": "^4.2",
|
"api-platform/doctrine-orm": "^4.2",
|
||||||
"api-platform/symfony": "^4.2",
|
"api-platform/symfony": "^4.2",
|
||||||
"doctrine/doctrine-bundle": "^3.2",
|
"doctrine/doctrine-bundle": "^3.2",
|
||||||
|
|||||||
Generated
+3
-2
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "9c04091eea0e10c19713a1d882b04f91",
|
"content-hash": "9a85291a52081179f427fa0c2b60d061",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "api-platform/doctrine-common",
|
"name": "api-platform/doctrine-common",
|
||||||
@@ -11664,7 +11664,8 @@
|
|||||||
"platform": {
|
"platform": {
|
||||||
"php": ">=8.4",
|
"php": ">=8.4",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-iconv": "*"
|
"ext-iconv": "*",
|
||||||
|
"ext-soap": "*"
|
||||||
},
|
},
|
||||||
"platform-dev": {},
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.9.0"
|
"plugin-api-version": "2.9.0"
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
<div
|
<div
|
||||||
v-for="item in items"
|
v-for="item in items"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
class="grid gap-4 px-4 py-3 text-sm hover:bg-slate-50 cursor-pointer border-t border-slate-200"
|
class="grid gap-4 px-4 py-3 text-sm border-t border-slate-200"
|
||||||
|
:class="canOpenItems ? 'hover:bg-slate-50 cursor-pointer' : ''"
|
||||||
:style="{ gridTemplateColumns: gridCols }"
|
:style="{ gridTemplateColumns: gridCols }"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@@ -50,8 +51,10 @@ const props = withDefaults(defineProps<{
|
|||||||
items: any[]
|
items: any[]
|
||||||
routePrefix: string
|
routePrefix: string
|
||||||
showActions?: boolean
|
showActions?: boolean
|
||||||
|
canOpenItems?: boolean
|
||||||
}>(), {
|
}>(), {
|
||||||
showActions: false
|
showActions: false,
|
||||||
|
canOpenItems: true
|
||||||
})
|
})
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -62,6 +65,9 @@ const gridCols = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const goToItem = (id: number) => {
|
const goToItem = (id: number) => {
|
||||||
|
if (!props.canOpenItems) {
|
||||||
|
return
|
||||||
|
}
|
||||||
router.push(`${props.routePrefix}/${id}`)
|
router.push(`${props.routePrefix}/${id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,13 @@ import { useAuthStore } from '~/stores/auth'
|
|||||||
|
|
||||||
export default defineNuxtRouteMiddleware(async (to) => {
|
export default defineNuxtRouteMiddleware(async (to) => {
|
||||||
const auth = useAuthStore()
|
const auth = useAuthStore()
|
||||||
|
const guestAllowedPaths = [
|
||||||
|
'/',
|
||||||
|
'/reception/waiting-reception',
|
||||||
|
'/reception/finish-reception',
|
||||||
|
'/shipment/waiting-shipment',
|
||||||
|
'/shipment/finish-shipment'
|
||||||
|
]
|
||||||
|
|
||||||
if (to.path === '/login') {
|
if (to.path === '/login') {
|
||||||
return
|
return
|
||||||
@@ -14,4 +21,8 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
|||||||
if (!auth.isAuthenticated) {
|
if (!auth.isAuthenticated) {
|
||||||
return navigateTo('/login')
|
return navigateTo('/login')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auth.isGuest && !guestAllowedPaths.includes(to.path)) {
|
||||||
|
return navigateTo('/')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -96,8 +96,7 @@ const hydrateFromUser = (user: UserData | null) => {
|
|||||||
isHydrating.value = true
|
isHydrating.value = true
|
||||||
form.username = user.username ?? ''
|
form.username = user.username ?? ''
|
||||||
const roles = user.roles ?? []
|
const roles = user.roles ?? []
|
||||||
const hasAdmin = roles.includes('ROLE_ADMIN')
|
form.role = ROLE.find((role) => roles.includes(role.value))?.value ?? 'ROLE_USER'
|
||||||
form.role = hasAdmin ? 'ROLE_ADMIN' : 'ROLE_USER'
|
|
||||||
form.password = ''
|
form.password = ''
|
||||||
isHydrating.value = false
|
isHydrating.value = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useAuthStore } from '~/stores/auth'
|
||||||
|
|
||||||
|
const auth = useAuthStore()
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-wrap justify-center pb-16 gap-12">
|
<div class="flex flex-wrap justify-center pb-16 gap-12">
|
||||||
<card-link label="NOUVELLE RÉCEPTION" link="/reception" iconName="mdi:truck-outline" />
|
<card-link v-if="auth.canUseWorkflow" label="NOUVELLE RÉCEPTION" link="/reception" iconName="mdi:truck-outline" />
|
||||||
<card-link label="NOUVELLE EXPÉDITION" link="/shipment" iconName="mdi:truck-fast-outline" />
|
<card-link v-if="auth.canUseWorkflow" label="NOUVELLE EXPÉDITION" link="/shipment" iconName="mdi:truck-fast-outline" />
|
||||||
<card-link label="PLAN DE SITE" link="/infrastructure/building" iconName="material-symbols:warehouse-outline-rounded" />
|
<card-link v-if="auth.canUseWorkflow" label="PLAN DE SITE" link="/infrastructure/building" iconName="material-symbols:warehouse-outline-rounded" />
|
||||||
<card-link link="/reception/waiting-reception" iconName="mdi:truck-remove-outline">
|
<card-link link="/reception/waiting-reception" iconName="mdi:truck-remove-outline">
|
||||||
<template #label>
|
<template #label>
|
||||||
Réceptions<br>EN ATTENTE
|
Réceptions<br>EN ATTENTE
|
||||||
@@ -15,10 +18,10 @@
|
|||||||
EXPÉDITIONS<br>EN ATTENTE
|
EXPÉDITIONS<br>EN ATTENTE
|
||||||
</template>
|
</template>
|
||||||
</card-link>
|
</card-link>
|
||||||
<card-link label="CASES" link="/infrastructure/case" iconName="material-symbols:bottom-sheets-outline" />
|
<card-link v-if="auth.canUseWorkflow" label="CASES" link="/infrastructure/case" iconName="material-symbols:bottom-sheets-outline" />
|
||||||
<card-link label="RÉCEPTIONS FINIES" link="/reception/finish-reception" iconName="mdi:truck-check-outline" />
|
<card-link label="RÉCEPTIONS FINIES" link="/reception/finish-reception" iconName="mdi:truck-check-outline" />
|
||||||
<card-link label="EXPÉDITIONS FINIES" link="/shipment/finish-shipment" iconName="mdi:truck-delivery-outline" />
|
<card-link label="EXPÉDITIONS FINIES" link="/shipment/finish-shipment" iconName="mdi:truck-delivery-outline" />
|
||||||
<card-link link="/" iconName="mdi:cow">
|
<card-link v-if="auth.canUseWorkflow" link="/" iconName="mdi:cow">
|
||||||
<template #label>
|
<template #label>
|
||||||
PASSEPORT<br>DU BOVIN
|
PASSEPORT<br>DU BOVIN
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -17,7 +17,8 @@
|
|||||||
<div
|
<div
|
||||||
v-for="reception in receptionList"
|
v-for="reception in receptionList"
|
||||||
:key="reception.id"
|
:key="reception.id"
|
||||||
class="grid grid-cols-6 gap-4 px-4 py-3 text-sm hover:bg-slate-50 cursor-pointer border-t border-slate-200"
|
class="grid grid-cols-6 gap-4 px-4 py-3 text-sm border-t border-slate-200"
|
||||||
|
:class="auth.canUseWorkflow ? 'hover:bg-slate-50 cursor-pointer' : ''"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@click="goToReception(reception.id)"
|
@click="goToReception(reception.id)"
|
||||||
@@ -36,10 +37,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type {ReceptionData} from "~/services/dto/reception-data";
|
import type {ReceptionData} from "~/services/dto/reception-data";
|
||||||
import {getReceptionList} from "~/services/reception";
|
import {getReceptionList} from "~/services/reception";
|
||||||
import type {ShipmentData} from "~/services/dto/shipment-data";
|
import { useAuthStore } from '~/stores/auth'
|
||||||
|
|
||||||
const receptionList = ref<ReceptionData[]>()
|
const receptionList = ref<ReceptionData[]>()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const auth = useAuthStore()
|
||||||
|
|
||||||
const formatDate = (date: string | null) => {
|
const formatDate = (date: string | null) => {
|
||||||
if (!date) return '—'
|
if (!date) return '—'
|
||||||
@@ -66,6 +68,7 @@ const formatWeighing = (reception: ReceptionData) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const goToReception = (id: number) => {
|
const goToReception = (id: number) => {
|
||||||
|
if (!auth.canUseWorkflow) return
|
||||||
router.push(`/reception/update/${id}`)
|
router.push(`/reception/update/${id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
:columns="columns"
|
:columns="columns"
|
||||||
:items="receptionList ?? []"
|
:items="receptionList ?? []"
|
||||||
route-prefix="/reception"
|
route-prefix="/reception"
|
||||||
show-actions
|
:show-actions="auth.canUseWorkflow"
|
||||||
|
:can-open-items="auth.canUseWorkflow"
|
||||||
>
|
>
|
||||||
<template #cell-receptionDate="{ item }">
|
<template #cell-receptionDate="{ item }">
|
||||||
{{ formatDate(item.receptionDate) }}
|
{{ formatDate(item.receptionDate) }}
|
||||||
@@ -23,6 +24,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ReceptionData } from '~/services/dto/reception-data'
|
import type { ReceptionData } from '~/services/dto/reception-data'
|
||||||
import { getReceptionList, deleteReception } from '~/services/reception'
|
import { getReceptionList, deleteReception } from '~/services/reception'
|
||||||
|
import { useAuthStore } from '~/stores/auth'
|
||||||
|
|
||||||
|
const auth = useAuthStore()
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ key: 'receptionDate', label: 'Date et heure' },
|
{ key: 'receptionDate', label: 'Date et heure' },
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
v-for="shipment in shipmentList"
|
v-for="shipment in shipmentList"
|
||||||
:key="shipment
|
:key="shipment
|
||||||
.id"
|
.id"
|
||||||
class="grid grid-cols-6 gap-4 px-4 py-3 text-sm hover:bg-slate-50 cursor-pointer border-t border-slate-200"
|
class="grid grid-cols-6 gap-4 px-4 py-3 text-sm border-t border-slate-200"
|
||||||
|
:class="auth.canUseWorkflow ? 'hover:bg-slate-50 cursor-pointer' : ''"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@click="goShipment(shipment.id)"
|
@click="goShipment(shipment.id)"
|
||||||
@@ -47,9 +48,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type {ShipmentData} from "~/services/dto/shipment-data";
|
import type {ShipmentData} from "~/services/dto/shipment-data";
|
||||||
import {getShipmentList} from "~/services/shipment";
|
import {getShipmentList} from "~/services/shipment";
|
||||||
|
import { useAuthStore } from '~/stores/auth'
|
||||||
|
|
||||||
const shipmentList = ref<ShipmentData[]>()
|
const shipmentList = ref<ShipmentData[]>()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const auth = useAuthStore()
|
||||||
|
|
||||||
const formatWeighing = (shipment: ShipmentData) => {
|
const formatWeighing = (shipment: ShipmentData) => {
|
||||||
const gross = shipment.weights?.find((weight) => weight.type === 'gross')?.weight
|
const gross = shipment.weights?.find((weight) => weight.type === 'gross')?.weight
|
||||||
@@ -76,6 +79,7 @@ const formatShipmentLines = (shipment: ShipmentData) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const goShipment = (id: number) => {
|
const goShipment = (id: number) => {
|
||||||
|
if (!auth.canUseWorkflow) return
|
||||||
router.push(`/shipment/update/${id}`)
|
router.push(`/shipment/update/${id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
:columns="columns"
|
:columns="columns"
|
||||||
:items="shipmentList ?? []"
|
:items="shipmentList ?? []"
|
||||||
route-prefix="/shipment"
|
route-prefix="/shipment"
|
||||||
show-actions
|
:show-actions="auth.canUseWorkflow"
|
||||||
|
:can-open-items="auth.canUseWorkflow"
|
||||||
>
|
>
|
||||||
<template #cell-shipmentDate="{ item }">
|
<template #cell-shipmentDate="{ item }">
|
||||||
{{ formatDate(item.shipmentDate) }}
|
{{ formatDate(item.shipmentDate) }}
|
||||||
@@ -35,6 +36,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ShipmentData } from '~/services/dto/shipment-data'
|
import type { ShipmentData } from '~/services/dto/shipment-data'
|
||||||
import { getShipmentList, deleteShipment } from '~/services/shipment'
|
import { getShipmentList, deleteShipment } from '~/services/shipment'
|
||||||
|
import { useAuthStore } from '~/stores/auth'
|
||||||
|
|
||||||
|
const auth = useAuthStore()
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ key: 'shipmentDate', label: 'Date et heure' },
|
{ key: 'shipmentDate', label: 'Date et heure' },
|
||||||
|
|||||||
@@ -12,7 +12,12 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
isAuthenticated: (state) => Boolean(state.user),
|
isAuthenticated: (state) => Boolean(state.user),
|
||||||
isAdmin: (state) => Boolean(state.user?.roles?.includes(ROLE[0].value))
|
isAdmin: (state) => Boolean(state.user?.roles?.includes(ROLE[0].value)),
|
||||||
|
isGuest: (state) => Boolean(state.user?.roles?.includes('ROLE_GUEST')),
|
||||||
|
canUseWorkflow: (state) => Boolean(
|
||||||
|
state.user?.roles?.includes(ROLE[0].value) ||
|
||||||
|
state.user?.roles?.includes('ROLE_USER')
|
||||||
|
)
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
clearSession() {
|
clearSession() {
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ export const MERCHANDISE_TYPE_CODES = {
|
|||||||
|
|
||||||
export const ROLE = [
|
export const ROLE = [
|
||||||
{ label: 'Administrateur', value: 'ROLE_ADMIN' },
|
{ label: 'Administrateur', value: 'ROLE_ADMIN' },
|
||||||
{ label: 'Utilisateur', value: 'ROLE_USER' }
|
{ label: 'Utilisateur', value: 'ROLE_USER' },
|
||||||
|
{ label: 'Visiteur', value: 'ROLE_GUEST' }
|
||||||
]
|
]
|
||||||
export const SUPPLIER_CODE = {
|
export const SUPPLIER_CODE = {
|
||||||
LIOT: 'LIOT'
|
LIOT: 'LIOT'
|
||||||
|
|||||||
@@ -35,9 +35,11 @@ use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
|||||||
new Get(
|
new Get(
|
||||||
requirements: ['id' => '\d+'],
|
requirements: ['id' => '\d+'],
|
||||||
normalizationContext: ['groups' => ['reception:read']],
|
normalizationContext: ['groups' => ['reception:read']],
|
||||||
|
security: "is_granted('ROLE_USER') or is_granted('ROLE_GUEST')",
|
||||||
),
|
),
|
||||||
new GetCollection(
|
new GetCollection(
|
||||||
normalizationContext: ['groups' => ['reception:read']],
|
normalizationContext: ['groups' => ['reception:read']],
|
||||||
|
security: "is_granted('ROLE_USER') or is_granted('ROLE_GUEST')",
|
||||||
),
|
),
|
||||||
new Post(
|
new Post(
|
||||||
normalizationContext: ['groups' => ['reception:read']],
|
normalizationContext: ['groups' => ['reception:read']],
|
||||||
@@ -70,6 +72,7 @@ use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
|||||||
),
|
),
|
||||||
output: false,
|
output: false,
|
||||||
provider: ReceptionReceiptProvider::class,
|
provider: ReceptionReceiptProvider::class,
|
||||||
|
security: "is_granted('ROLE_USER') or is_granted('ROLE_GUEST')",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
security: "is_granted('ROLE_USER')",
|
security: "is_granted('ROLE_USER')",
|
||||||
|
|||||||
@@ -35,9 +35,11 @@ use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
|||||||
new Get(
|
new Get(
|
||||||
requirements: ['id' => '\d+'],
|
requirements: ['id' => '\d+'],
|
||||||
normalizationContext: ['groups' => ['shipment:read']],
|
normalizationContext: ['groups' => ['shipment:read']],
|
||||||
|
security: "is_granted('ROLE_USER') or is_granted('ROLE_GUEST')",
|
||||||
),
|
),
|
||||||
new GetCollection(
|
new GetCollection(
|
||||||
normalizationContext: ['groups' => ['shipment:read']],
|
normalizationContext: ['groups' => ['shipment:read']],
|
||||||
|
security: "is_granted('ROLE_USER') or is_granted('ROLE_GUEST')",
|
||||||
),
|
),
|
||||||
new Post(
|
new Post(
|
||||||
normalizationContext: ['groups' => ['shipment:read']],
|
normalizationContext: ['groups' => ['shipment:read']],
|
||||||
@@ -70,6 +72,7 @@ use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
|||||||
),
|
),
|
||||||
output: false,
|
output: false,
|
||||||
provider: ShipmentReceiptProvider::class,
|
provider: ShipmentReceiptProvider::class,
|
||||||
|
security: "is_granted('ROLE_USER') or is_granted('ROLE_GUEST')",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
security: "is_granted('ROLE_USER')",
|
security: "is_granted('ROLE_USER')",
|
||||||
|
|||||||
+4
-1
@@ -23,7 +23,7 @@ use Symfony\Component\Serializer\Attribute\Groups;
|
|||||||
new Get(
|
new Get(
|
||||||
uriTemplate: '/me',
|
uriTemplate: '/me',
|
||||||
normalizationContext: ['groups' => ['user:read']],
|
normalizationContext: ['groups' => ['user:read']],
|
||||||
security: "is_granted('ROLE_USER')",
|
security: "is_granted('ROLE_USER') or is_granted('ROLE_GUEST')",
|
||||||
provider: MeProvider::class
|
provider: MeProvider::class
|
||||||
),
|
),
|
||||||
new Get(
|
new Get(
|
||||||
@@ -101,7 +101,10 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|||||||
public function getRoles(): array
|
public function getRoles(): array
|
||||||
{
|
{
|
||||||
$roles = $this->roles;
|
$roles = $this->roles;
|
||||||
|
|
||||||
|
if (!in_array('ROLE_GUEST', $roles, true)) {
|
||||||
$roles[] = 'ROLE_USER';
|
$roles[] = 'ROLE_USER';
|
||||||
|
}
|
||||||
|
|
||||||
return array_unique($roles);
|
return array_unique($roles);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user