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'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
routes: [
|
routes: [
|
||||||
// PUBLIC
|
// PUBLIC
|
||||||
{ path: '/join', component: () => import('@/pages/Join.vue') },
|
{ path: '/join', component: () => import('@/pages/Join.vue') },
|
||||||
{ path: '/applications', component: () => import('@/pages/MyApplications.vue'), meta: { requiresAuth: true } },
|
{ path: '/applications', component: () => import('@/pages/MyApplications.vue'), meta: { requiresAuth: true } },
|
||||||
{ path: '/applications/:id', component: () => import('@/pages/MyApplications.vue'), meta: { requiresAuth: true } },
|
{ path: '/applications/:id', component: () => import('@/pages/MyApplications.vue'), meta: { requiresAuth: true } },
|
||||||
|
|
||||||
// AUTH REQUIRED
|
// AUTH REQUIRED
|
||||||
{ path: '/', component: () => import('@/pages/Homepage.vue') },
|
{ path: '/', component: () => import('@/pages/Homepage.vue') },
|
||||||
|
|
||||||
// MEMBER ROUTES
|
// MEMBER ROUTES
|
||||||
{ path: '/members', component: () => import('@/pages/memberList.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
{ 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: '/loa', component: () => import('@/pages/SubmitLOA.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||||
{ path: '/transfer', component: () => import('@/pages/Transfer.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: '/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: '/calendar', component: () => import('@/pages/Calendar.vue') },
|
||||||
{ path: '/trainingReport/new', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
{ path: '/calendar/event/:id', component: () => import('@/pages/Calendar.vue') },
|
||||||
{ path: '/trainingReport/:id', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
|
||||||
|
|
||||||
// ADMIN / STAFF ROUTES
|
// disabled in favor of linking
|
||||||
{
|
// { path: '/documents', component: () => import('@/pages/Documentation.vue'), meta: { requiresAuth: true, memberOnly: true }, },
|
||||||
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: '/trainingReport', component: () => import('@/pages/TrainingReport.vue'), meta: { requiresAuth: true, memberOnly: true } },
|
||||||
{ path: '/unauthorized', component: () => import('@/pages/Unauthorized.vue') }
|
{ 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;
|
const addr = import.meta.env.VITE_APIHOST;
|
||||||
|
|
||||||
|
|
||||||
router.beforeEach(async (to) => {
|
router.beforeEach(async (to) => {
|
||||||
const user = useUserStore()
|
const user = useUserStore()
|
||||||
|
|
||||||
// Make sure user state is loaded before checking
|
// Make sure user state is loaded before checking
|
||||||
if (!user.loaded) {
|
if (!user.loaded) {
|
||||||
await user.loadUser();
|
await user.loadUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not logged in
|
// Not logged in
|
||||||
if (to.meta.requiresAuth && !user.isLoggedIn) {
|
if (to.meta.requiresAuth && !user.isLoggedIn) {
|
||||||
// Redirect back to original page after login
|
// Redirect back to original page after login
|
||||||
const redirectUrl = encodeURIComponent(window.location.origin + to.fullPath)
|
const redirectUrl = encodeURIComponent(window.location.origin + to.fullPath)
|
||||||
window.location.href = `${addr}/login?redirect=${redirectUrl}`
|
window.location.href = `${addr}/login?redirect=${redirectUrl}`
|
||||||
return false // Prevent Vue Router from continuing
|
return false // Prevent Vue Router from continuing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// banned state
|
||||||
|
if (user.state === 'banned' && to.path !== '/restricted') {
|
||||||
|
return '/restricted';
|
||||||
|
}
|
||||||
|
|
||||||
// Must be a member
|
// Must be a member
|
||||||
if (to.meta.memberOnly && user.state !== 'member') {
|
if (to.meta.memberOnly && user.state !== 'member') {
|
||||||
return '/unauthorized'
|
return '/unauthorized'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must have specific role
|
// Must have specific role
|
||||||
if (to.meta.roles && !user.hasRole('Dev') && !user.hasAnyRole(to.meta.roles)) {
|
if (to.meta.roles && !user.hasRole('Dev') && !user.hasAnyRole(to.meta.roles)) {
|
||||||
return '/unauthorized'
|
return '/unauthorized'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
Reference in New Issue
Block a user