diff --git a/config/backdev.front.env b/config/backdev.front.env index 9db91ea..27cf54e 100644 --- a/config/backdev.front.env +++ b/config/backdev.front.env @@ -2,3 +2,4 @@ VITE_KEYCLOAK_URL=http://localhost:7080 VITE_KEYCLOAK_CLIENT_ID=myinpulse VITE_KEYCLOAK_REALM=test VITE_APP_URL=http://localhost:8080 +VITE_BACKEND_URL=http://localhost:8081/ diff --git a/config/frontdev.front.env b/config/frontdev.front.env index d6b7016..5eba221 100644 --- a/config/frontdev.front.env +++ b/config/frontdev.front.env @@ -1,4 +1,5 @@ VITE_KEYCLOAK_URL=http://localhost:7080 -VITE_KEYCLOAK_CLIENT_ID=myinpulse +VITE_KEYCLOAK_CLIENT_ID=myinpulse-dev VITE_KEYCLOAK_REALM=test VITE_APP_URL=http://localhost:5173 +VITE_BACKEND_URL=http://localhost:8081/ diff --git a/config/prod.front.env b/config/prod.front.env index d5007dc..cb42a37 100644 --- a/config/prod.front.env +++ b/config/prod.front.env @@ -2,3 +2,4 @@ VITE_KEYCLOAK_URL=https://0549cd63f912d5dc9b31278d6f.eirb.fr VITE_KEYCLOAK_CLIENT_ID=myinpulse-eirb VITE_KEYCLOAK_REALM=test VITE_APP_URL=https://0549cd63f912d5dc9b31278d6f.piair.dev +VITE_BACKEND_URL=http://TODO/ diff --git a/front/MyINPulse-front/src/components/HelloWorld.vue b/front/MyINPulse-front/src/components/HelloWorld.vue deleted file mode 100644 index d174cf8..0000000 --- a/front/MyINPulse-front/src/components/HelloWorld.vue +++ /dev/null @@ -1,41 +0,0 @@ - - - - - diff --git a/front/MyINPulse-front/src/components/TheWelcome.vue b/front/MyINPulse-front/src/components/TheWelcome.vue deleted file mode 100644 index 674b490..0000000 --- a/front/MyINPulse-front/src/components/TheWelcome.vue +++ /dev/null @@ -1,94 +0,0 @@ - - - diff --git a/front/MyINPulse-front/src/components/WelcomeItem.vue b/front/MyINPulse-front/src/components/WelcomeItem.vue deleted file mode 100644 index 6d7086a..0000000 --- a/front/MyINPulse-front/src/components/WelcomeItem.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - diff --git a/front/MyINPulse-front/src/components/errorModal.vue b/front/MyINPulse-front/src/components/errorModal.vue new file mode 100644 index 0000000..0d7dd57 --- /dev/null +++ b/front/MyINPulse-front/src/components/errorModal.vue @@ -0,0 +1,94 @@ + + + + + \ No newline at end of file diff --git a/front/MyINPulse-front/src/components/icons/IconCommunity.vue b/front/MyINPulse-front/src/components/icons/IconCommunity.vue deleted file mode 100644 index 2dc8b05..0000000 --- a/front/MyINPulse-front/src/components/icons/IconCommunity.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/front/MyINPulse-front/src/components/icons/IconDocumentation.vue b/front/MyINPulse-front/src/components/icons/IconDocumentation.vue deleted file mode 100644 index 6d4791c..0000000 --- a/front/MyINPulse-front/src/components/icons/IconDocumentation.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/front/MyINPulse-front/src/components/icons/IconEcosystem.vue b/front/MyINPulse-front/src/components/icons/IconEcosystem.vue deleted file mode 100644 index c3a4f07..0000000 --- a/front/MyINPulse-front/src/components/icons/IconEcosystem.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/front/MyINPulse-front/src/components/icons/IconSupport.vue b/front/MyINPulse-front/src/components/icons/IconSupport.vue deleted file mode 100644 index 7452834..0000000 --- a/front/MyINPulse-front/src/components/icons/IconSupport.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/front/MyINPulse-front/src/components/icons/IconTooling.vue b/front/MyINPulse-front/src/components/icons/IconTooling.vue deleted file mode 100644 index 660598d..0000000 --- a/front/MyINPulse-front/src/components/icons/IconTooling.vue +++ /dev/null @@ -1,19 +0,0 @@ - - diff --git a/front/MyINPulse-front/src/main.ts b/front/MyINPulse-front/src/main.ts index e33d5c1..198447d 100644 --- a/front/MyINPulse-front/src/main.ts +++ b/front/MyINPulse-front/src/main.ts @@ -1,69 +1,37 @@ import { createApp } from 'vue' import App from './App.vue' import router from './router' -//import VueKeyCloak from '@dsb-norge/vue-keycloak-js' -//import { useKeycloak } from '@dsb-norge/vue-keycloak-js' -//import axios from 'axios' import {createPinia} from "pinia"; import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'; import AuthStorePlugin from './plugins/authStore'; import keycloakService from './services/keycloak'; +import axios from "axios"; +import {useAuthStore} from "@/stores/authStore.ts"; +let store: any; keycloakService.CallInit(() => { + try { + const app = createApp(App) - const app = createApp(App) + // Setup pinia store, allowing user to keep logged in status after refresh + const pinia = createPinia(); + pinia.use(piniaPluginPersistedstate); + app.use(pinia); + app.use(AuthStorePlugin, { pinia }); + store = useAuthStore(); + app.use(router) - -// Setup pinia store, allowing user to keep logged in status after refresh - const pinia = createPinia(); - pinia.use(piniaPluginPersistedstate); - - app.use(pinia); - app.use(AuthStorePlugin, { pinia }); - app.use(router) - app.mount('#app'); + app.mount('#app'); + } catch (e) { + console.error("Error while initiating Keycloak.") + console.error(e) + createApp(App).mount('#app'); + } }) -createApp(App).mount('#app'); - -// TODO: fix the comment -/* -function tokenInterceptor () { - axios.interceptors.request.use(config => { - const keycloak = useKeycloak() - if (keycloak.authenticated) { - // Note that this is a simple example. - // you should be careful not to leak tokens to third parties. - // in this example the token is added to all usage of axios. - config.headers.Authorization = `Bearer ${keycloak.token}` - } - return config - }, error => { - console.error("tokenInterceptor: Rejected") - return Promise.reject(error) - }) -} -*/ - -/* -app.use(VueKeyCloak,{ - onReady: (keycloak) => { - console.log("Ready !") - tokenInterceptor() - }, - init: { - onLoad: 'login-required', - checkLoginIframe: false, - - }, - - config: { - realm: 'test', - url: 'http://localhost:7080', - clientId: 'myinpulse' - } -} ); -*/ + + +export {store}; \ No newline at end of file diff --git a/front/MyINPulse-front/src/router/index.ts b/front/MyINPulse-front/src/router/router.ts similarity index 100% rename from front/MyINPulse-front/src/router/index.ts rename to front/MyINPulse-front/src/router/router.ts diff --git a/front/MyINPulse-front/src/services/api.ts b/front/MyINPulse-front/src/services/api.ts index eb75333..d29273a 100644 --- a/front/MyINPulse-front/src/services/api.ts +++ b/front/MyINPulse-front/src/services/api.ts @@ -1,13 +1,55 @@ -// file: src/services/api.js - import axios from "axios"; +import {store} from "@/main.ts"; -// Creating an instance for axios to be used by the token interceptor service -const instance = axios.create({ - baseURL: `${import.meta.env.VITE_BE_API_URL}/api`, +const axiosInstance = axios.create({ + baseURL: import.meta.env.VITE_BACKEND_URL, headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, }); -export default instance; \ No newline at end of file +axiosInstance.interceptors.response.use( + response => response, // Directly return successful responses. + async error => { + const originalRequest = error.config; + if (error.response.status === 401 && !originalRequest._retry && store.authenticated) { + originalRequest._retry = true; // Mark the request as retried to avoid infinite loops. + try { + await store.refreshUserToken(); + // Update the authorization header with the new access token. + axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${store.user.token}`; + return axiosInstance(originalRequest); // Retry the original request with the new access token. + } catch (refreshError) { + // Handle refresh token errors by clearing stored tokens and redirecting to the login page. + console.error('Token refresh failed:', refreshError); + localStorage.removeItem('accessToken'); + localStorage.removeItem('refreshToken'); + window.location.href = '/login'; + return Promise.reject(refreshError); + } + } + return Promise.reject(error); // For all other errors, return the error as is. + } +); + +// TODO: spawn a error modal +function defaultApiErrorHandler(err: String){ + console.log(err) +} + +function defaultApiSuccessHandler(response: () => void){ + console.log(response) +} +function callApi(endpoint: string, onSuccessHandler?: any, onErrorHandler?: any): void { + axiosInstance.get(endpoint).then( + onSuccessHandler == null ? defaultApiSuccessHandler : onSuccessHandler + ).catch( + (err) => { + onErrorHandler == null ? defaultApiErrorHandler(err): onErrorHandler(err); + throw err; + } + ) +} + + +export {callApi} \ No newline at end of file diff --git a/front/MyINPulse-front/src/services/popupDisplayer.ts b/front/MyINPulse-front/src/services/popupDisplayer.ts new file mode 100644 index 0000000..61d02b9 --- /dev/null +++ b/front/MyINPulse-front/src/services/popupDisplayer.ts @@ -0,0 +1,17 @@ +import {ref} from "vue"; +enum errorType {Error, Warning} + +function addNewError(errorMessage: string, timeout?: number, type?: errorType){ + if (timeout == null){ + timeout = 5000; + } + if (type == null){ + type = Error; + } + errorList.value.push({errorMessage: errorMessage, timeout: timeout, type: type}) + setTimeout(() => errorList.value.pop(errorMessage), 5000) +} + +const errorList = ref([]) + +export {addNewError, errorList} \ No newline at end of file diff --git a/front/MyINPulse-front/src/views/errorModal.vue b/front/MyINPulse-front/src/views/errorModal.vue deleted file mode 100644 index 92722f1..0000000 --- a/front/MyINPulse-front/src/views/errorModal.vue +++ /dev/null @@ -1,32 +0,0 @@ - - - - - \ No newline at end of file diff --git a/front/MyINPulse-front/src/views/errorWrapper.vue b/front/MyINPulse-front/src/views/errorWrapper.vue new file mode 100644 index 0000000..96c0baf --- /dev/null +++ b/front/MyINPulse-front/src/views/errorWrapper.vue @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/front/MyINPulse-front/src/views/Home.vue b/front/MyINPulse-front/src/views/test.vue similarity index 58% rename from front/MyINPulse-front/src/views/Home.vue rename to front/MyINPulse-front/src/views/test.vue index 7fbe869..e879aef 100644 --- a/front/MyINPulse-front/src/views/Home.vue +++ b/front/MyINPulse-front/src/views/test.vue @@ -1,7 +1,16 @@ @@ -26,19 +35,26 @@ const store = useAuthStore() {{store.user.refreshToken}} - Unauthenticated API call - + Entrepreneur API call + res - Authenticated API call - + Admin API call + res + + Unauth API call + + res + + +