100 lines
2.6 KiB
TypeScript
100 lines
2.6 KiB
TypeScript
import { createRouter, createWebHistory } from 'vue-router';
|
|
|
|
import Admin from '@/pages/Admin.vue';
|
|
import Login from '@/pages/Login.vue';
|
|
import Settings from '@/pages/Settings.vue';
|
|
import Devices from '@/pages/Devices.vue';
|
|
import DeviceView from './pages/DeviceView.vue';
|
|
import Forbidden from './pages/Forbidden.vue';
|
|
import Create from './pages/Create.vue';
|
|
import { auth } from './lib/auth';
|
|
|
|
|
|
declare module 'vue-router' {
|
|
interface RouteMeta {
|
|
requiresAuth?: boolean
|
|
roles?: string[] // allowed roles
|
|
}
|
|
}
|
|
|
|
const routes = [
|
|
{
|
|
path: '/login',
|
|
name: 'Login',
|
|
component: Login,
|
|
meta: { requiresAuth: false }
|
|
},
|
|
{
|
|
path: '/',
|
|
redirect: '/devices', // Optional: Redirect the root path to /home
|
|
},
|
|
{
|
|
path: '/devices',
|
|
name: 'Devices',
|
|
component: Devices,
|
|
meta: { requiresAuth: true }
|
|
},
|
|
{
|
|
path: '/settings',
|
|
name: 'Settings',
|
|
component: Settings,
|
|
meta: { requiresAuth: true }
|
|
},
|
|
{
|
|
path: '/admin',
|
|
name: 'Admin',
|
|
component: Admin,
|
|
meta: { requiresAuth: true, roles: ['admin'] }
|
|
},
|
|
{
|
|
path: '/device/:guid', // ← new dynamic segment
|
|
name: 'DeviceView',
|
|
component: DeviceView,
|
|
props: true, // so `guid` shows up as a prop
|
|
meta: { requiresAuth: true }
|
|
},
|
|
{
|
|
path: '/forbidden',
|
|
name: 'Forbidden',
|
|
component: Forbidden,
|
|
meta: { requiresAuth: false }
|
|
},
|
|
{
|
|
path: '/create',
|
|
name: 'Create',
|
|
component: Create,
|
|
meta: { requiresAuth: true, roles: ['admin'] }
|
|
}
|
|
]
|
|
|
|
const router = createRouter({
|
|
history: createWebHistory(import.meta.env.BASE_URL),
|
|
routes,
|
|
})
|
|
|
|
// Navigation guard for protected routes.
|
|
// For any route except "Login", we force a full page load so that the server-side session check occurs.
|
|
router.beforeEach((to, _from, next) => {
|
|
const requiresAuth = to.meta.requiresAuth !== false && to.name !== 'Login'
|
|
|
|
// 1) Not authenticated → /login?redirect=<original>
|
|
if (requiresAuth && !auth.isAuthenticated.value) {
|
|
return next({ name: 'Login', query: { redirect: to.fullPath } })
|
|
}
|
|
|
|
// 2) Role check (if any)
|
|
const allowed = to.meta.roles
|
|
if (allowed && allowed.length > 0) {
|
|
const hasRole = allowed.some((r) => auth.roles.value.includes(r))
|
|
if (!hasRole) {
|
|
return next({ name: 'Forbidden' })
|
|
}
|
|
}
|
|
|
|
next()
|
|
})
|
|
|
|
|
|
export default router
|
|
|