// Ported from legacy henza_admin/src/router.js import { createRouter, createWebHistory } from 'vue-router'; import { adminRoute, fullPageAdminRoute } from './admin'; import { branchRoute, fullPageBranchRoute } from './branch'; import { iamAppUrl, isBranch, tokenName, userName } from '../utils'; import { useUsersStore } from '../stores/users'; import api from '../api/client'; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), // legacy router.js:17-19 scrollBehavior() { return { left: 0, top: 0 }; }, routes: [ // ── MAIN LAYOUT ROUTES ────────────────────────────────────────── { path: '', component: () => import('../layouts/main/Main.vue'), children: isBranch() ? branchRoute : adminRoute, }, // ── FULL PAGE LAYOUTS ─────────────────────────────────────────── { path: '', component: () => import('../layouts/full-page/FullPage.vue'), children: [ ...(isBranch() ? fullPageBranchRoute : fullPageAdminRoute), { path: '/auth/iam/callback', name: 'iam-callback', component: () => import('../views/auth/IamCallback.vue'), meta: { rule: 'editor' }, }, { path: '/pages/error-404', name: 'page-error-404', component: () => import('../views/pages/Error404.vue'), meta: { rule: 'editor' }, }, { path: '/pages/error-500', name: 'page-error-500', component: () => import('../views/pages/Error500.vue'), meta: { rule: 'editor' }, }, { path: '/pages/not-authorized', name: 'page-not-authorized', component: () => import('../views/pages/NotAuthorized.vue'), meta: { rule: 'editor' }, }, { path: '/pages/maintenance', name: 'page-maintenance', component: () => import('../views/pages/Maintenance.vue'), meta: { rule: 'editor' }, }, ], }, // Redirect to 404 page, if no match found { path: '/:pathMatch(.*)*', redirect: '/pages/error-404', }, ], }); // legacy router.js:147-153 router.afterEach(() => { const appLoading = document.getElementById('loading-bg'); if (appLoading) { appLoading.style.display = 'none'; } }); // legacy router.js:156-161 const noneAuthUrl = ['/auth/login', '/auth/forgot-password', '/auth/register', '/reg', '/auth/iam/callback']; /** * Port of legacy getPermission() (router.js:163-182). * * Legacy cached the result in a MODULE-SCOPED `let roles`, which was never reset * on logout — so the next user to sign in on the same tab inherited the previous * user's permissions (bug #2 in docs/ADMIN-PORT-PLAN.md). Here the cache is the * Pinia users store, which auth.logout() clears; `roles === undefined` still * means "not fetched", exactly as legacy's check did. */ async function getPermission(): Promise { const users = useUsersStore(); if (users.roles) return users.roles; try { const { data } = await api.get('users/show'); users.getRoles(data.permission); // Legacy stripped these before caching the user blob. delete data.permission; delete data.ut; if (data.api_token) { localStorage.setItem(tokenName, data.api_token); } localStorage.setItem(userName, JSON.stringify(data)); } catch (e) { console.log(e); } return users.roles; } /** * Port of legacy router.beforeEach (router.js:184-199). * * One deliberate change: legacy's final line was a bare * router.push({path: '/auth/login'}) * with no next() call, which in Vue Router 4 leaves the navigation permanently * pending and hangs the app (bug #1). Returning the redirect is the Vue Router 4 * equivalent and produces the same user-visible result. */ router.beforeEach(async (to) => { if (!localStorage.getItem(tokenName) && to.path !== '/auth/iam/callback' && sessionStorage.getItem('gb_admin_iam_sso_checked') !== '1') { sessionStorage.setItem('gb_admin_iam_sso_checked', '1'); try { const { data } = await api.get('admin/auth/sso/start', { params: { redirect_uri: iamAppUrl('auth/iam/callback') }, }); if (data?.enabled && data.authorize_url) { window.location.assign(data.authorize_url); return false; } } catch { // سامانه هویت برای این پنل تنظیم نشده } } if (noneAuthUrl.indexOf(to.path) > -1) { return true; } const token = localStorage.getItem(tokenName); if (token) { const roles = await getPermission(); if (roles && to.meta && to.meta.role && !roles.includes(to.meta.role as string)) { if (to.name === 'dashboard-ecommerce' || to.name === 'dashboard-analytics') { return { name: 'my-data' }; } return { name: 'page-not-authorized' }; } return true; } return { path: '/auth/login' }; }); export default router;