diff --git a/src/auth/router.js b/src/auth/router.js index cd561f4..b09e964 100644 --- a/src/auth/router.js +++ b/src/auth/router.js @@ -4,6 +4,7 @@ import { createWebHistory, createRouter } from "vue-router"; import roles from "@/auth/roles"; import { extractRolesFromToken } from "@/utils/keycloak"; +import { hasToken, validateToken, redirectToLogin } from "@/utils/auth"; import Videos from "@/routes/videos"; import NewVideo from "@/routes/videos/new"; @@ -139,37 +140,49 @@ const hasPermission = (requiredPermissions = []) => { ); }; -// router.beforeEach((to, from, next) => { -// if (to.meta.title) { -// document.title = to.meta.title; -// } +router.beforeEach(async (to, from, next) => { + if (to.meta.title) { + document.title = to.meta.title; + } -// console.log(to, from); + const requiresAuth = to.matched.some((record) => record.meta.requiresAuth); + const isGuestRoute = to.matched.some((record) => record.meta.guest); -// // if (to.matched.some((record) => record.meta.requiresAuth)) { -// if (!isAuthenticated()) { -// next({ -// path: "/login", -// }); + if (requiresAuth) { + if (!hasToken()) { + next({ path: "/login" }); + return; + } -// return; -// } + const isValid = await validateToken(); -// // const requiredPermissions = to.meta.permissions || []; + if (!isValid) { + redirectToLogin(); + return; + } -// // if (requiredPermissions.length > 0 && !hasPermission(requiredPermissions)) { -// // next({ path: "/unauthorized" }); + const requiredPermissions = to.meta.permissions || []; -// // return; -// // } -// // } + if (requiredPermissions.length > 0 && !hasPermission(requiredPermissions)) { + next({ path: "/videos" }); + return; + } -// // if (to.matched.some((record) => record.meta.guest) && isAuthenticated()) { -// // next({ path: "/" }); + next(); + return; + } -// // return; -// // } + if (isGuestRoute && hasToken()) { + const isValid = await validateToken(); -// next(); -// return; -// }); + if (isValid) { + next({ path: "/videos" }); + return; + } + + redirectToLogin(); + return; + } + + next(); +}); diff --git a/src/routes/videos/index.vue b/src/routes/videos/index.vue index 95e0222..c003a16 100644 --- a/src/routes/videos/index.vue +++ b/src/routes/videos/index.vue @@ -68,6 +68,8 @@ :options="situations" :loading="situationsLoading" multiple + emit-value + map-options /> @@ -232,6 +234,9 @@ export default { page: pagination.page, ...baseParams, }, + paramsSerializer: { + indexes: null, + }, }); this.rows = data.content; diff --git a/src/utils/auth.js b/src/utils/auth.js new file mode 100644 index 0000000..562efcb --- /dev/null +++ b/src/utils/auth.js @@ -0,0 +1,47 @@ +import Cookies from "js-cookie"; +import { API } from "../config/axios"; + +/** + * Checks if the user has a valid session token + * @returns {boolean} True if token cookie exists + */ +export function hasToken() { + const token = Cookies.get("token"); + return !!token; +} + +/** + * Validates the current token by calling the backend /check-token endpoint + * @returns {Promise} True if token is valid, false otherwise + */ +export async function validateToken() { + if (!hasToken()) { + return false; + } + + try { + const response = await API.get("/auth/check-token"); + return response.data?.valid === true; + } catch (error) { + // If the request fails (401, 403, network error, etc.), token is invalid + return false; + } +} + +/** + * Clears all authentication data from cookies + */ +export function clearAuthData() { + Cookies.remove("token"); + Cookies.remove("refresh_token"); + Cookies.remove("user_roles"); + Cookies.remove("user_profile"); +} + +/** + * Redirects to login page and clears auth data + */ +export function redirectToLogin() { + clearAuthData(); + window.location.href = "/login"; +}