From 4af2ef49a07befb22748fae0b934a501b6611ebf Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Mon, 26 Feb 2024 07:11:33 +0100 Subject: [PATCH 1/6] refs #6930: replace tokenUSer with tokenMultimedia --- src/components/NavBar.vue | 4 ++-- src/components/UserPanel.vue | 2 +- src/components/ui/VnAvatar.vue | 4 ++-- src/composables/downloadFile.js | 4 ++-- src/composables/useSession.js | 16 ++++++++++++++-- src/pages/Claim/Card/ClaimBasicData.vue | 4 ++-- src/pages/Claim/Card/ClaimPhoto.vue | 4 ++-- src/pages/Claim/Card/ClaimSummary.vue | 4 ++-- src/pages/Customer/Card/CustomerBasicData.vue | 4 ++-- src/pages/Entry/EntryLatestBuys.vue | 4 ++-- src/pages/Item/Card/ItemDescriptor.vue | 4 ++-- src/pages/Order/Card/OrderCatalogItem.vue | 4 ++-- src/pages/Order/OrderLines.vue | 4 ++-- src/pages/Route/Cmr/CmrList.vue | 4 ++-- src/pages/Route/RouteList.vue | 16 ++++++++-------- src/pages/Wagon/WagonCounter.vue | 4 ++-- src/pages/Worker/Card/WorkerDescriptor.vue | 4 ++-- 17 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 12366e174..17b8c2b7e 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -10,12 +10,12 @@ import UserPanel from 'components/UserPanel.vue'; import VnBreadcrumbs from './common/VnBreadcrumbs.vue'; const { t } = useI18n(); -const session = useSession(); const stateStore = useStateStore(); const quasar = useQuasar(); const state = useState(); const user = state.getUser(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const appName = 'Lilium'; onMounted(() => stateStore.setMounted()); diff --git a/src/components/UserPanel.vue b/src/components/UserPanel.vue index e0b6b86ed..a18dad79a 100644 --- a/src/components/UserPanel.vue +++ b/src/components/UserPanel.vue @@ -44,7 +44,7 @@ const darkMode = computed({ }); const user = state.getUser(); -const token = session.getToken(); +const token = session.getTokenMultimedia(); onMounted(async () => { updatePreferences(); diff --git a/src/components/ui/VnAvatar.vue b/src/components/ui/VnAvatar.vue index 5a5483084..287f741e0 100644 --- a/src/components/ui/VnAvatar.vue +++ b/src/components/ui/VnAvatar.vue @@ -10,8 +10,8 @@ const $props = defineProps({ size: { type: String, default: null }, title: { type: String, default: null }, }); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const { t } = useI18n(); const title = computed(() => $props.title ?? t('globals.system')); diff --git a/src/composables/downloadFile.js b/src/composables/downloadFile.js index 877d2a254..b26dec731 100644 --- a/src/composables/downloadFile.js +++ b/src/composables/downloadFile.js @@ -1,8 +1,8 @@ import { useSession } from 'src/composables/useSession'; import { getUrl } from './getUrl'; -const session = useSession(); -const token = session.getToken(); +const {getTokenMultimedia} = useSession(); +const token = getTokenMultimedia(); export async function downloadFile(dmsId) { let appUrl = await getUrl('', 'lilium'); diff --git a/src/composables/useSession.js b/src/composables/useSession.js index 008337b02..4d182a934 100644 --- a/src/composables/useSession.js +++ b/src/composables/useSession.js @@ -10,12 +10,20 @@ export function useSession() { return localToken || sessionToken || ''; } + function getTokenMultimedia() { + const localTokenMultimedia = localStorage.getItem('tokenMultimedia'); + const sessionTokenMultimedia = sessionStorage.getItem('tokenMultimedia'); + + return localTokenMultimedia || sessionTokenMultimedia || ''; + } function setToken(data) { if (data.keepLogin) { localStorage.setItem('token', data.token); + localStorage.setItem('tokenMultimedia', data.tokenMultimedia); } else { sessionStorage.setItem('token', data.token); + sessionStorage.setItem('tokenMultimedia', data.tokenMultimedia); } } @@ -23,6 +31,9 @@ export function useSession() { if (localStorage.getItem('token')) localStorage.removeItem('token') + if (localStorage.getItem('tokenMultimedia')) + localStorage.removeItem('tokenMultimedia') + if (sessionStorage.getItem('token')) sessionStorage.removeItem('token'); @@ -37,8 +48,8 @@ export function useSession() { }); } - async function login(token, keepLogin) { - setToken({ token, keepLogin }); + async function login(token, tokenMultimedia, keepLogin) { + setToken({ token, tokenMultimedia, keepLogin }); await useRole().fetch(); await useUserConfig().fetch(); @@ -53,6 +64,7 @@ export function useSession() { return { getToken, + getTokenMultimedia, setToken, destroy, login, diff --git a/src/pages/Claim/Card/ClaimBasicData.vue b/src/pages/Claim/Card/ClaimBasicData.vue index 35f93c736..1c4f998d8 100644 --- a/src/pages/Claim/Card/ClaimBasicData.vue +++ b/src/pages/Claim/Card/ClaimBasicData.vue @@ -13,8 +13,8 @@ import { useSession } from 'src/composables/useSession'; const route = useRoute(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const claimFilter = { fields: [ diff --git a/src/pages/Claim/Card/ClaimPhoto.vue b/src/pages/Claim/Card/ClaimPhoto.vue index 6ac116ce0..dd97b60df 100644 --- a/src/pages/Claim/Card/ClaimPhoto.vue +++ b/src/pages/Claim/Card/ClaimPhoto.vue @@ -11,8 +11,8 @@ import FetchData from 'components/FetchData.vue'; const router = useRouter(); const quasar = useQuasar(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const claimId = computed(() => router.currentRoute.value.params.id); diff --git a/src/pages/Claim/Card/ClaimSummary.vue b/src/pages/Claim/Card/ClaimSummary.vue index cdc1f15be..9281cc08a 100644 --- a/src/pages/Claim/Card/ClaimSummary.vue +++ b/src/pages/Claim/Card/ClaimSummary.vue @@ -14,8 +14,8 @@ import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; const route = useRoute(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const $props = defineProps({ id: { diff --git a/src/pages/Customer/Card/CustomerBasicData.vue b/src/pages/Customer/Card/CustomerBasicData.vue index 458d50082..d23b08f17 100644 --- a/src/pages/Customer/Card/CustomerBasicData.vue +++ b/src/pages/Customer/Card/CustomerBasicData.vue @@ -11,8 +11,8 @@ import VnInput from 'src/components/common/VnInput.vue'; const route = useRoute(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const workers = ref([]); const workersCopy = ref([]); diff --git a/src/pages/Entry/EntryLatestBuys.vue b/src/pages/Entry/EntryLatestBuys.vue index f4a423f3b..db66b8f0b 100644 --- a/src/pages/Entry/EntryLatestBuys.vue +++ b/src/pages/Entry/EntryLatestBuys.vue @@ -15,8 +15,8 @@ import { useSession } from 'composables/useSession'; import { dashIfEmpty } from 'src/filters'; const router = useRouter(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const stateStore = useStateStore(); const { t } = useI18n(); diff --git a/src/pages/Item/Card/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue index 362fcfc67..af6de04e8 100644 --- a/src/pages/Item/Card/ItemDescriptor.vue +++ b/src/pages/Item/Card/ItemDescriptor.vue @@ -36,7 +36,7 @@ const quasar = useQuasar(); const route = useRoute(); const router = useRouter(); const { t } = useI18n(); -const { getToken } = useSession(); +const { getTokenMultimedia } = useSession(); const state = useState(); const user = state.getUser(); @@ -72,7 +72,7 @@ onMounted(async () => { }); const getItemAvatar = async () => { - const token = getToken(); + const token = getTokenMultimedia(); const timeStamp = `timestamp=${Date.now()}`; image.value = `/api/Images/catalog/200x200/${entityId.value}/download?access_token=${token}&${timeStamp}`; }; diff --git a/src/pages/Order/Card/OrderCatalogItem.vue b/src/pages/Order/Card/OrderCatalogItem.vue index ee73bcffb..a197ceafc 100644 --- a/src/pages/Order/Card/OrderCatalogItem.vue +++ b/src/pages/Order/Card/OrderCatalogItem.vue @@ -11,8 +11,8 @@ import toCurrency from '../../../filters/toCurrency'; const DEFAULT_PRICE_KG = 0; -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const { t } = useI18n(); defineProps({ diff --git a/src/pages/Order/OrderLines.vue b/src/pages/Order/OrderLines.vue index a2ee42481..4b6c21c75 100644 --- a/src/pages/Order/OrderLines.vue +++ b/src/pages/Order/OrderLines.vue @@ -17,9 +17,9 @@ import axios from 'axios'; const route = useRoute(); const { t } = useI18n(); -const session = useSession(); +const { getTokenMultimedia } = useSession(); const quasar = useQuasar(); -const token = session.getToken(); +const token = getTokenMultimedia(); const orderSummary = ref({ total: null, vat: null, diff --git a/src/pages/Route/Cmr/CmrList.vue b/src/pages/Route/Cmr/CmrList.vue index dc5602c1c..c0a6d263d 100644 --- a/src/pages/Route/Cmr/CmrList.vue +++ b/src/pages/Route/Cmr/CmrList.vue @@ -12,8 +12,8 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy const stateStore = useStateStore(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const selected = ref([]); const columns = computed(() => [ diff --git a/src/pages/Route/RouteList.vue b/src/pages/Route/RouteList.vue index 0b4aa6795..be8a29ceb 100644 --- a/src/pages/Route/RouteList.vue +++ b/src/pages/Route/RouteList.vue @@ -16,7 +16,7 @@ import RouteSearchbar from 'pages/Route/Card/RouteSearchbar.vue'; import RouteFilter from 'pages/Route/Card/RouteFilter.vue'; import RouteSummary from 'pages/Route/Card/RouteSummary.vue'; import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; -import {useSession} from "composables/useSession"; +import { useSession } from 'composables/useSession'; import { useSummaryDialog } from 'src/composables/useSummaryDialog'; const stateStore = useStateStore(); @@ -144,21 +144,21 @@ const cloneRoutes = () => { }; const showRouteReport = () => { - const ids = selectedRows.value.map(row => row?.id) - const idString = ids.join(',') + const ids = selectedRows.value.map((row) => row?.id); + const idString = ids.join(','); let url; if (selectedRows.value.length <= 1) { - url = `api/Routes/${idString}/driver-route-pdf?access_token=${session.getToken()}`; + url = `api/Routes/${idString}/driver-route-pdf?access_token=${session.getTokenMultimedia()}`; } else { const params = new URLSearchParams({ - access_token: session.getToken(), - id: idString - }) + access_token: session.getTokenMultimedia(), + id: idString, + }); url = `api/Routes/downloadZip?${params.toString()}`; } window.open(url, '_blank'); -} +}; const markAsServed = () => { selectedRows.value.forEach((row) => { diff --git a/src/pages/Wagon/WagonCounter.vue b/src/pages/Wagon/WagonCounter.vue index bd5d2ca67..15a1ab7ba 100644 --- a/src/pages/Wagon/WagonCounter.vue +++ b/src/pages/Wagon/WagonCounter.vue @@ -7,8 +7,8 @@ import VnConfirm from 'components/ui/VnConfirm.vue'; const quasar = useQuasar(); const { t } = useI18n(); -const session = useSession(); -const token = session.getToken(); +const { getTokenMultimedia } = useSession(); +const token = getTokenMultimedia(); const counters = ref({ alquilerBandeja: { count: 0, id: 96001, title: 'CC Bandeja', isTray: true }, diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue index bec56bee7..5144b3bfa 100644 --- a/src/pages/Worker/Card/WorkerDescriptor.vue +++ b/src/pages/Worker/Card/WorkerDescriptor.vue @@ -22,7 +22,7 @@ const $props = defineProps({ const route = useRoute(); const { t } = useI18n(); -const { getToken } = useSession(); +const { getTokenMultimedia } = useSession(); const entityId = computed(() => { return $props.id || route.params.id; @@ -56,7 +56,7 @@ const filter = { const sip = computed(() => worker.value?.sip && worker.value.sip.extension); function getWorkerAvatar() { - const token = getToken(); + const token = getTokenMultimedia(); return `/api/Images/user/160x160/${entityId.value}/download?access_token=${token}`; } const data = ref(useCardDescription()); From d86675446827f092d816ff701d516aea1940bb26 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Mon, 26 Feb 2024 07:47:22 +0100 Subject: [PATCH 2/6] refs #6930: handle tokenMultimedia --- src/pages/Login/LoginMain.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Login/LoginMain.vue b/src/pages/Login/LoginMain.vue index e2ccdac16..7a141e878 100644 --- a/src/pages/Login/LoginMain.vue +++ b/src/pages/Login/LoginMain.vue @@ -31,7 +31,7 @@ async function onSubmit() { if (!data) return; - await session.login(data.token, keepLogin.value); + await session.login(data.token, data.multimediaToken.id, keepLogin.value); quasar.notify({ message: t('login.loginSuccess'), From bddfe8f9d7ff94ca253b2e34acf57434712976c2 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Wed, 28 Feb 2024 08:33:26 +0100 Subject: [PATCH 3/6] refs #6930 feat: call shareToken endpoint --- src/pages/Login/LoginMain.vue | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/pages/Login/LoginMain.vue b/src/pages/Login/LoginMain.vue index 7a141e878..0bdc02142 100644 --- a/src/pages/Login/LoginMain.vue +++ b/src/pages/Login/LoginMain.vue @@ -30,8 +30,15 @@ async function onSubmit() { const { data } = await axios.post('Accounts/login', params); if (!data) return; + const { + data: { multimediaToken }, + } = await axios.get('VnUsers/ShareToken', { + headers: { Authorization: data.token }, + }); - await session.login(data.token, data.multimediaToken.id, keepLogin.value); + if (!multimediaToken) return; + + await session.login(data.token, multimediaToken.id, keepLogin.value); quasar.notify({ message: t('login.loginSuccess'), From 0d80fd37a4127c7f395916f505cf6873bef53ba3 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Wed, 28 Feb 2024 11:28:57 +0100 Subject: [PATCH 4/6] refs #6930 feat: call loutMultimedia endpoint --- src/boot/axios.js | 2 +- src/composables/useSession.js | 37 ++++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/boot/axios.js b/src/boot/axios.js index c58cc2d08..e3e7289af 100644 --- a/src/boot/axios.js +++ b/src/boot/axios.js @@ -11,7 +11,7 @@ axios.defaults.baseURL = '/api/'; const onRequest = (config) => { const token = session.getToken(); - if (token.length && config.headers) { + if (token.length && !config.headers.Authorization) { config.headers.Authorization = token; } diff --git a/src/composables/useSession.js b/src/composables/useSession.js index 4d182a934..580efbdf8 100644 --- a/src/composables/useSession.js +++ b/src/composables/useSession.js @@ -1,6 +1,7 @@ import { useState } from './useState'; import { useRole } from './useRole'; import { useUserConfig } from './useUserConfig'; +import axios from 'axios'; export function useSession() { @@ -27,15 +28,37 @@ export function useSession() { } } - function destroy() { - if (localStorage.getItem('token')) - localStorage.removeItem('token') - - if (localStorage.getItem('tokenMultimedia')) + async function destroy() { + if (localStorage.getItem('tokenMultimedia')){ + await axios.post('VnUsers/logoutMultimedia', null, { + headers: {Authorization: localStorage.getItem('tokenMultimedia') } + }); localStorage.removeItem('tokenMultimedia') - if (sessionStorage.getItem('token')) - sessionStorage.removeItem('token'); + } + if (localStorage.getItem('token')){ + await axios.post('VnUsers/logout', null, { + headers: {Authorization: localStorage.getItem('token') } + }); + localStorage.removeItem('token') + } + + + if (sessionStorage.getItem('tokenMultimedia')){ + await axios.post('VnUsers/logoutMultimedia', null, { + headers: {Authorization: sessionStorage.getItem('tokenMultimedia') } + }); + sessionStorage.removeItem('tokenMultimedia') + + } + if (sessionStorage.getItem('token')){ + await axios.post('VnUsers/logout', null, { + headers: {Authorization: sessionStorage.getItem('token') } + }); + sessionStorage.removeItem('token') + } + + const { setUser } = useState(); From 39381f29d739b2ccc865a91adf1dd5c55a460981 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Wed, 28 Feb 2024 13:15:59 +0100 Subject: [PATCH 5/6] refs #6980 test: fix failed tests --- .../vitest/__tests__/composables/useSession.spec.js | 13 ++++++++----- test/vitest/__tests__/pages/Login/Login.spec.js | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/test/vitest/__tests__/composables/useSession.spec.js b/test/vitest/__tests__/composables/useSession.spec.js index 4f900aca6..f9f3dcb80 100644 --- a/test/vitest/__tests__/composables/useSession.spec.js +++ b/test/vitest/__tests__/composables/useSession.spec.js @@ -54,7 +54,8 @@ describe('session', () => { expect(localStorage.getItem('token')).toEqual('tokenToBeGone'); expect(user.value).toEqual(previousUser); - session.destroy(); + vi.spyOn(axios, 'post').mockResolvedValue({ data: true }); + await session.destroy(); user = state.getUser(); expect(localStorage.getItem('token')).toBeNull(); @@ -92,9 +93,10 @@ describe('session', () => { }); const expectedToken = 'mySessionToken'; + const expectedTokenMultimedia = 'mySessionTokenMultimedia'; const keepLogin = false; - await session.login(expectedToken, keepLogin); + await session.login(expectedToken,expectedTokenMultimedia, keepLogin); const roles = state.getRoles(); const localToken = localStorage.getItem('token'); @@ -104,7 +106,7 @@ describe('session', () => { expect(localToken).toBeNull(); expect(sessionToken).toEqual(expectedToken); - session.destroy(); // this clears token and user for any other test + await session.destroy(); // this clears token and user for any other test }); it('should fetch the user roles and then set token in the localStorage', async () => { @@ -114,9 +116,10 @@ describe('session', () => { }); const expectedToken = 'myLocalToken'; + const expectedTokenMultimedia = 'myLocalTokenMultimedia'; const keepLogin = true; - await session.login(expectedToken, keepLogin); + await session.login(expectedToken, expectedTokenMultimedia, keepLogin); const roles = state.getRoles(); const localToken = localStorage.getItem('token'); @@ -126,7 +129,7 @@ describe('session', () => { expect(localToken).toEqual(expectedToken); expect(sessionToken).toBeNull(); - session.destroy(); // this clears token and user for any other test + await session.destroy(); // this clears token and user for any other test }); }); }); diff --git a/test/vitest/__tests__/pages/Login/Login.spec.js b/test/vitest/__tests__/pages/Login/Login.spec.js index fadfc898f..6e2de9870 100644 --- a/test/vitest/__tests__/pages/Login/Login.spec.js +++ b/test/vitest/__tests__/pages/Login/Login.spec.js @@ -22,9 +22,9 @@ describe('Login', () => { darkMode: false, }, }; - vi.spyOn(axios, 'post').mockResolvedValue({ data: { token: 'token' } }); + vi.spyOn(axios, 'post').mockResolvedValueOnce({ data: { token: 'token' } }); vi.spyOn(axios, 'get').mockResolvedValue({ - data: { roles: [], user: expectedUser }, + data: { roles: [], user: expectedUser , multimediaToken: {id:'multimediaToken' }}, }); vi.spyOn(vm.quasar, 'notify'); @@ -36,7 +36,7 @@ describe('Login', () => { expect(vm.quasar.notify).toHaveBeenCalledWith( expect.objectContaining({ type: 'positive' }) ); - vm.session.destroy(); + await vm.session.destroy(); }); it('should not set the token into session if any error occurred', async () => { From 0fe0a6385bc26465a104b6264bda80759563aaf6 Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 15 Mar 2024 10:43:25 +0100 Subject: [PATCH 6/6] hotFix(Readme): change bun to pnpm --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 86fe11ca7..e87a84d60 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,13 @@ Lilium frontend ## Install the dependencies ```bash -bun install +pnpm install ``` ### Install quasar cli ```bash -sudo bun install -g @quasar/cli +sudo npm install -g @quasar/cli ``` ### Start the app in development mode (hot-code reloading, error reporting, etc.) @@ -23,13 +23,13 @@ quasar dev ### Run unit tests ```bash -bun run test:unit +pnpm run test:unit ``` ### Run e2e tests ```bash -npm run test:e2e +pnpm run test:e2e ``` ### Build the app for production