feat: add role negation and negate some routes to admins

This commit is contained in:
2026-06-17 22:27:03 +02:00 Unverified
parent 3315a9ce6e
commit ed0e12b1b6
4 changed files with 45 additions and 9 deletions
+4 -4
View File
@@ -26,15 +26,15 @@ onUnmounted(() => {
} }
}) })
const { isAuthenticated, user, logout } = useAuth()
const panelLabel = computed(() => isAdmin(user.value?.role) ? 'Pannello' : 'Dashboard')
const navLinks = [ const navLinks = [
{ name: 'Home', path: '/' }, { name: 'Home', path: '/' },
{ name: 'Fai una segnalazione', path: '/reports/new' }, ...(isCitizen(user.value?.role) ? [{ name: 'Fai una segnalazione', path: '/reports/new' }] : []),
{ name: 'Esplora i dati', path: '/open-data' }, { name: 'Esplora i dati', path: '/open-data' },
{ name: 'Come funziona', path: '/info' } { name: 'Come funziona', path: '/info' }
] ]
const { isAuthenticated, user, logout } = useAuth()
const panelLabel = computed(() => isAdmin(user.value?.role) ? 'Pannello' : 'Dashboard')
</script> </script>
<template> <template>
+5 -3
View File
@@ -1,3 +1,5 @@
import { checkRoleAccess, type MetaRoleRequirement } from '~/utils/roles'
export default defineNuxtRouteMiddleware(async (to) => { export default defineNuxtRouteMiddleware(async (to) => {
const auth = useAuth() const auth = useAuth()
@@ -14,13 +16,13 @@ export default defineNuxtRouteMiddleware(async (to) => {
return navigateTo('/auth/login') return navigateTo('/auth/login')
} }
const requiredRole = to.meta.auth?.role const requiredRole = to.meta.auth?.role as MetaRoleRequirement | undefined
if (requiredRole && auth.user.value) { if (requiredRole && auth.user.value) {
const userRole = auth.user.value.role const userRole = auth.user.value.role
if (!hasMinimumRole(userRole, requiredRole)) { if (!checkRoleAccess(userRole, requiredRole)) {
console.warn(`[Auth] User role ${userRole} insufficient for required ${requiredRole}`) console.warn(`[Auth] User role '${userRole}' rejected for route requirement:`, requiredRole)
return navigateTo('/') return navigateTo('/')
} }
} }
+3
View File
@@ -3,6 +3,9 @@ import type { CreateReportRequest } from '~/types/api'
definePageMeta({ definePageMeta({
middleware: 'auth', middleware: 'auth',
auth: {
role: ['!ADMIN', '!OPERATOR']
}
}) })
useHead({ title: 'Nuova segnalazione - Visione' }) useHead({ title: 'Nuova segnalazione - Visione' })
+33 -2
View File
@@ -5,6 +5,8 @@ export const ROLES = {
} as const } as const
export type Role = keyof typeof ROLES export type Role = keyof typeof ROLES
export type NegatedRole = `!${Role}`
export type MetaRoleRequirement = Role | NegatedRole | Array<Role | NegatedRole>
export const ROLE_LEVELS: Record<string, number> = { export const ROLE_LEVELS: Record<string, number> = {
[ROLES.CITIZEN]: 1, [ROLES.CITIZEN]: 1,
@@ -17,12 +19,12 @@ export function normalizeRole(role?: string | null): string {
} }
export function isRole(userRole: string | undefined | null, targetRole: string): boolean { export function isRole(userRole: string | undefined | null, targetRole: string): boolean {
return normalizeRole(userRole) === targetRole.toUpperCase() return normalizeRole(userRole) === normalizeRole(targetRole)
} }
export function hasMinimumRole(userRole: string | undefined | null, requiredRole: string): boolean { export function hasMinimumRole(userRole: string | undefined | null, requiredRole: string): boolean {
const userLvl = ROLE_LEVELS[normalizeRole(userRole)] || 0 const userLvl = ROLE_LEVELS[normalizeRole(userRole)] || 0
const reqLvl = ROLE_LEVELS[requiredRole.toUpperCase()] || 0 const reqLvl = ROLE_LEVELS[normalizeRole(requiredRole)] || 0
return userLvl >= reqLvl return userLvl >= reqLvl
} }
@@ -41,3 +43,32 @@ export function isCitizen(userRole?: string | null): boolean {
export function canAccess(userRole: string | undefined | null, requiredRole: string): boolean { export function canAccess(userRole: string | undefined | null, requiredRole: string): boolean {
return hasMinimumRole(userRole, requiredRole) return hasMinimumRole(userRole, requiredRole)
} }
export function checkRoleAccess(userRole: string | undefined | null, requirement: MetaRoleRequirement | undefined): boolean {
if (!requirement) return true
const normalizedUserRole = normalizeRole(userRole)
if (!normalizedUserRole) return false
const requirements = Array.isArray(requirement) ? requirement : [requirement]
for (const req of requirements) {
const isNegated = req.startsWith('!')
const rawTarget = isNegated ? req.substring(1) : req
const targetRole = normalizeRole(rawTarget)
if (isNegated) {
console.log("negated", normalizedUserRole, targetRole)
if (normalizedUserRole === targetRole) {
return false
}
} else {
if (!hasMinimumRole(normalizedUserRole, targetRole)) {
return false
}
}
}
return true
}