153 lines
5.1 KiB
TypeScript
153 lines
5.1 KiB
TypeScript
// 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<string[] | undefined> {
|
|
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;
|