diff --git a/api/src/index.ts b/api/src/index.ts index 8327b4d..7230a30 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -5,7 +5,11 @@ import express = require('express'); import cors = require('cors'); import morgan = require('morgan'); const app = express() -app.use(morgan('dev')) +app.use(morgan('dev', { + skip: (req) => { + return req.path === '/members/me'; + } +})) app.use(cors({ origin: [process.env.CLIENT_URL], // your SPA origins @@ -27,7 +31,7 @@ if (process.env.DISABLE_GLITCHTIP === "true") { let release = process.env.APPLICATION_VERSION; let environment = process.env.APPLICATION_ENVIRONMENT; console.log(release, environment) - sentry.init({ dsn: dsn, release: release, environment: environment, integrations: [sentry.captureConsoleIntegration({levels: ['error']})] }); + sentry.init({ dsn: dsn, release: release, environment: environment, integrations: [sentry.captureConsoleIntegration({ levels: ['error'] })] }); console.log("Glitchtip initialized"); } diff --git a/ui/src/router/index.js b/ui/src/router/index.js index 34c15d0..6003535 100644 --- a/ui/src/router/index.js +++ b/ui/src/router/index.js @@ -32,7 +32,7 @@ const router = createRouter({ // ADMIN / STAFF ROUTES { path: '/administration', - meta: { requiresAuth: true, memberOnly: true, roles: ['staff', 'admin'] }, + 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') }, diff --git a/ui/src/stores/user.ts b/ui/src/stores/user.ts index f3ff0f1..a5e04c9 100644 --- a/ui/src/stores/user.ts +++ b/ui/src/stores/user.ts @@ -1,5 +1,8 @@ -import { ref, computed } from 'vue' +import { ref, computed, watch } from 'vue' import { defineStore } from 'pinia' +import { useRoute, useRouter } from 'vue-router' + +const POLL_INTERVAL = 10_000 export const useUserStore = defineStore('user', () => { const user = ref(null) @@ -33,5 +36,57 @@ export const useUserStore = defineStore('user', () => { return requiredRoles.some(r => roles.value.has(r)) } + const route = useRoute(); + const router = useRouter(); + watch(user, (newUser) => { + if (!newUser) return + console.log(newUser); + + const currentRoute = route.meta + + // Member-only route + if (currentRoute.memberOnly && state.value !== 'member') { + router.replace('/unauthorized') + return + } + + // Role-based route + if (currentRoute.roles && !hasRole('Dev') && !hasAnyRole(currentRoute.roles as string[])) { + return '/unauthorized' + } + }, + { deep: true } // deep watch ensures nested changes trigger + ) + + //polling system + let pollTimeout: number | null = null + let polling = false; + let lastVersion: string | null = null + + async function poll() { + // Only poll if tab is visible + if (document.hidden) { + polling = false; + return + } + + await loadUser(); + + scheduleNext() + } + + function scheduleNext() { + polling = true; + pollTimeout = window.setTimeout(poll, POLL_INTERVAL) + } + + poll() //start polling + + document.addEventListener('visibilitychange', () => { + if (!document.hidden && polling === false) { + poll() + } + }) + return { user, isLoggedIn, roles, loadUser, loaded, hasAnyRole, hasRole, state } })