Added systems to handle banned users
This commit is contained in:
26
ui/src/pages/Banned.vue
Normal file
26
ui/src/pages/Banned.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div class="w-full max-w-2xl flex flex-col gap-8 justify-center mx-auto">
|
||||
<h1 class="text-3xl sm:text-4xl font-bold text-left">
|
||||
Access Restricted
|
||||
</h1>
|
||||
<div class="space-y-4 text-muted-foreground text-left leading-relaxed">
|
||||
<p>
|
||||
Your access to the <strong>17th Ranger Battalion</strong> has been
|
||||
<strong>revoked</strong> due to a violation of our community standards
|
||||
or policies.
|
||||
</p>
|
||||
<p>
|
||||
If you believe this action was taken in error or would like to better
|
||||
understand the reason for this decision, you may
|
||||
<strong>reach out to our administrative staff on Discord</strong>
|
||||
to request clarification or discuss a potential appeal.
|
||||
</p>
|
||||
<p>
|
||||
Regards,<br />
|
||||
<span class="text-foreground font-medium">
|
||||
The 17th Ranger Battalion Administration Team
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -2,82 +2,91 @@ import { useUserStore } from '@/stores/user'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
// PUBLIC
|
||||
{ path: '/join', component: () => import('@/pages/Join.vue') },
|
||||
{ path: '/applications', component: () => import('@/pages/MyApplications.vue'), meta: { requiresAuth: true } },
|
||||
{ path: '/applications/:id', component: () => import('@/pages/MyApplications.vue'), meta: { requiresAuth: true } },
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
// PUBLIC
|
||||
{ path: '/join', component: () => import('@/pages/Join.vue') },
|
||||
{ path: '/applications', component: () => import('@/pages/MyApplications.vue'), meta: { requiresAuth: true } },
|
||||
{ path: '/applications/:id', component: () => import('@/pages/MyApplications.vue'), meta: { requiresAuth: true } },
|
||||
|
||||
// AUTH REQUIRED
|
||||
{ path: '/', component: () => import('@/pages/Homepage.vue') },
|
||||
// AUTH REQUIRED
|
||||
{ path: '/', component: () => import('@/pages/Homepage.vue') },
|
||||
|
||||
// MEMBER ROUTES
|
||||
{ path: '/members', component: () => import('@/pages/memberList.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
{ path: '/loa', component: () => import('@/pages/SubmitLOA.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
{ path: '/transfer', component: () => import('@/pages/Transfer.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
{ path: '/profile', component: () => import('@/pages/MyProfile.vue'), meta: { requiresAuth: true } },
|
||||
// MEMBER ROUTES
|
||||
{ path: '/members', component: () => import('@/pages/memberList.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
{ path: '/loa', component: () => import('@/pages/SubmitLOA.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
{ path: '/transfer', component: () => import('@/pages/Transfer.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
{ path: '/profile', component: () => import('@/pages/MyProfile.vue'), meta: { requiresAuth: true } },
|
||||
|
||||
|
||||
{ path: '/calendar', component: () => import('@/pages/Calendar.vue') },
|
||||
{ path: '/calendar/event/:id', component: () => import('@/pages/Calendar.vue') },
|
||||
|
||||
// disabled in favor of linking
|
||||
// { path: '/documents', component: () => import('@/pages/Documentation.vue'), meta: { requiresAuth: true, memberOnly: true }, },
|
||||
|
||||
{ path: '/trainingReport', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
{ path: '/trainingReport/new', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
{ path: '/trainingReport/:id', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
{ path: '/calendar', component: () => import('@/pages/Calendar.vue') },
|
||||
{ path: '/calendar/event/:id', component: () => import('@/pages/Calendar.vue') },
|
||||
|
||||
// ADMIN / STAFF ROUTES
|
||||
{
|
||||
path: '/administration',
|
||||
meta: { requiresAuth: true, memberOnly: true, roles: ['17th Administrator', '17th HQ', '17th Command'] },
|
||||
children: [
|
||||
{ path: 'applications', component: () => import('@/pages/ManageApplications.vue') },
|
||||
{ path: 'applications/:id', component: () => import('@/pages/ManageApplications.vue') },
|
||||
{ path: 'rankChange', component: () => import('@/pages/RankChange.vue') },
|
||||
{ path: 'applications/:id', component: () => import('@/pages/Application.vue') },
|
||||
{ path: 'transfer', component: () => import('@/pages/ManageTransfers.vue') },
|
||||
{ path: 'loa', component: () => import('@/pages/ManageLOA.vue') },
|
||||
{ path: 'roles', component: () => import('@/pages/ManageRoles.vue') }
|
||||
]
|
||||
},
|
||||
// disabled in favor of linking
|
||||
// { path: '/documents', component: () => import('@/pages/Documentation.vue'), meta: { requiresAuth: true, memberOnly: true }, },
|
||||
|
||||
// UNAUTHORIZED PAGE
|
||||
{ path: '/unauthorized', component: () => import('@/pages/Unauthorized.vue') }
|
||||
]
|
||||
{ path: '/trainingReport', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
{ path: '/trainingReport/new', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
{ path: '/trainingReport/:id', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||
|
||||
// ADMIN / STAFF ROUTES
|
||||
{
|
||||
path: '/administration',
|
||||
meta: { requiresAuth: true, memberOnly: true, roles: ['17th Administrator', '17th HQ', '17th Command'] },
|
||||
children: [
|
||||
{ path: 'applications', component: () => import('@/pages/ManageApplications.vue') },
|
||||
{ path: 'applications/:id', component: () => import('@/pages/ManageApplications.vue') },
|
||||
{ path: 'rankChange', component: () => import('@/pages/RankChange.vue') },
|
||||
{ path: 'applications/:id', component: () => import('@/pages/Application.vue') },
|
||||
{ path: 'transfer', component: () => import('@/pages/ManageTransfers.vue') },
|
||||
{ path: 'loa', component: () => import('@/pages/ManageLOA.vue') },
|
||||
{ path: 'roles', component: () => import('@/pages/ManageRoles.vue') }
|
||||
]
|
||||
},
|
||||
|
||||
// UNAUTHORIZED PAGE
|
||||
{ path: '/unauthorized', component: () => import('@/pages/Unauthorized.vue') },
|
||||
|
||||
{ path: '/restricted', component: () => import('@/pages/Banned.vue'), meta: { requiresAuth: true } },
|
||||
|
||||
]
|
||||
})
|
||||
|
||||
const addr = import.meta.env.VITE_APIHOST;
|
||||
|
||||
|
||||
router.beforeEach(async (to) => {
|
||||
const user = useUserStore()
|
||||
const user = useUserStore()
|
||||
|
||||
// Make sure user state is loaded before checking
|
||||
if (!user.loaded) {
|
||||
await user.loadUser();
|
||||
}
|
||||
// Make sure user state is loaded before checking
|
||||
if (!user.loaded) {
|
||||
await user.loadUser();
|
||||
}
|
||||
|
||||
// Not logged in
|
||||
if (to.meta.requiresAuth && !user.isLoggedIn) {
|
||||
// Redirect back to original page after login
|
||||
const redirectUrl = encodeURIComponent(window.location.origin + to.fullPath)
|
||||
window.location.href = `${addr}/login?redirect=${redirectUrl}`
|
||||
return false // Prevent Vue Router from continuing
|
||||
}
|
||||
// Not logged in
|
||||
if (to.meta.requiresAuth && !user.isLoggedIn) {
|
||||
// Redirect back to original page after login
|
||||
const redirectUrl = encodeURIComponent(window.location.origin + to.fullPath)
|
||||
window.location.href = `${addr}/login?redirect=${redirectUrl}`
|
||||
return false // Prevent Vue Router from continuing
|
||||
}
|
||||
|
||||
// banned state
|
||||
if (user.state === 'banned' && to.path !== '/restricted') {
|
||||
return '/restricted';
|
||||
}
|
||||
|
||||
// Must be a member
|
||||
if (to.meta.memberOnly && user.state !== 'member') {
|
||||
return '/unauthorized'
|
||||
}
|
||||
// Must be a member
|
||||
if (to.meta.memberOnly && user.state !== 'member') {
|
||||
return '/unauthorized'
|
||||
}
|
||||
|
||||
// Must have specific role
|
||||
if (to.meta.roles && !user.hasRole('Dev') && !user.hasAnyRole(to.meta.roles)) {
|
||||
return '/unauthorized'
|
||||
}
|
||||
// Must have specific role
|
||||
if (to.meta.roles && !user.hasRole('Dev') && !user.hasAnyRole(to.meta.roles)) {
|
||||
return '/unauthorized'
|
||||
}
|
||||
})
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user