Merge pull request 'implemented new polling system for user account changes' (#95) from 81-user-state-polling into main
All checks were successful
Continuous Integration / Update Development (push) Successful in 2m30s

Reviewed-on: #95
This commit was merged in pull request #95.
This commit is contained in:
2025-12-14 15:45:24 -06:00
3 changed files with 63 additions and 4 deletions

View File

@@ -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");
}

View File

@@ -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') },

View File

@@ -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 }
})