import { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react' import { useAuth } from './AuthContext' const PermissionsContext = createContext(null) // Intervall für automatisches Neuladen der Permissions (30 Sekunden) const PERMISSIONS_REFRESH_INTERVAL = 30000 export const PermissionsProvider = ({ children }) => { const { authFetch, isAuthenticated } = useAuth() const [permissions, setPermissions] = useState({ isAdmin: false, hasFullAccess: false, accessibleSpaces: [], canCreateSpace: false, canDeleteSpace: false, canCreateFqdn: {}, canDeleteFqdn: {}, canUploadCSR: {}, canSignCSR: {}, }) const [loading, setLoading] = useState(true) const intervalRef = useRef(null) const isMountedRef = useRef(true) const fetchPermissions = useCallback(async (isInitial = false) => { if (!isAuthenticated) { setLoading(false) return } try { if (isInitial) { setLoading(true) } const response = await authFetch('/api/user/permissions') if (response.ok && isMountedRef.current) { const data = await response.json() setPermissions({ isAdmin: data.isAdmin || false, hasFullAccess: data.hasFullAccess || false, accessibleSpaces: data.accessibleSpaces || [], canCreateSpace: data.permissions?.canCreateSpace || false, canDeleteSpace: data.permissions?.canDeleteSpace || false, canCreateFqdn: data.permissions?.canCreateFqdn || {}, canDeleteFqdn: data.permissions?.canDeleteFqdn || {}, canUploadCSR: data.permissions?.canUploadCSR || {}, canSignCSR: data.permissions?.canSignCSR || {}, }) } } catch (err) { console.error('Error fetching permissions:', err) } finally { if (isInitial && isMountedRef.current) { setLoading(false) } } }, [isAuthenticated, authFetch]) // Initiales Laden der Permissions useEffect(() => { if (isAuthenticated) { fetchPermissions(true) } else { setPermissions({ isAdmin: false, hasFullAccess: false, accessibleSpaces: [], canCreateSpace: false, canDeleteSpace: false, canCreateFqdn: {}, canDeleteFqdn: {}, canUploadCSR: {}, canSignCSR: {}, }) setLoading(false) } }, [isAuthenticated, fetchPermissions]) // Automatisches Neuladen der Permissions im Hintergrund useEffect(() => { if (!isAuthenticated) { return } // Starte Polling-Intervall const startPolling = () => { if (intervalRef.current) { clearInterval(intervalRef.current) } intervalRef.current = setInterval(() => { if (isMountedRef.current && document.visibilityState === 'visible') { fetchPermissions(false) } }, PERMISSIONS_REFRESH_INTERVAL) } // Handle visibility change - pausiere Polling wenn Tab versteckt ist const handleVisibilityChange = () => { if (document.hidden) { // Tab ist versteckt, stoppe Intervall if (intervalRef.current) { clearInterval(intervalRef.current) intervalRef.current = null } } else { // Tab ist sichtbar, lade Permissions sofort und starte Polling if (isMountedRef.current) { fetchPermissions(false) startPolling() } } } // Starte initiales Polling startPolling() // Event Listener für visibility change document.addEventListener('visibilitychange', handleVisibilityChange) // Cleanup return () => { document.removeEventListener('visibilitychange', handleVisibilityChange) if (intervalRef.current) { clearInterval(intervalRef.current) intervalRef.current = null } } }, [isAuthenticated, fetchPermissions]) // Cleanup beim Unmount useEffect(() => { isMountedRef.current = true return () => { isMountedRef.current = false if (intervalRef.current) { clearInterval(intervalRef.current) intervalRef.current = null } } }, []) const canCreateSpace = () => permissions.canCreateSpace const canDeleteSpace = (spaceId) => permissions.canDeleteSpace const canCreateFqdn = (spaceId) => permissions.canCreateFqdn[spaceId] === true const canDeleteFqdn = (spaceId) => permissions.canDeleteFqdn[spaceId] === true const canUploadCSR = (spaceId) => permissions.canUploadCSR[spaceId] === true const canSignCSR = (spaceId) => permissions.canSignCSR[spaceId] === true const hasAccessToSpace = (spaceId) => permissions.accessibleSpaces.includes(spaceId) // refreshPermissions Funktion, die auch loading state setzt const refreshPermissions = useCallback(async () => { await fetchPermissions(true) }, [fetchPermissions]) const value = { permissions, loading, refreshPermissions, isAdmin: permissions.isAdmin, hasFullAccess: permissions.hasFullAccess, accessibleSpaces: permissions.accessibleSpaces, canCreateSpace, canDeleteSpace, canCreateFqdn, canDeleteFqdn, canUploadCSR, canSignCSR, hasAccessToSpace, } return {children} } export const usePermissions = () => { const context = useContext(PermissionsContext) if (!context) { throw new Error('usePermissions muss innerhalb eines PermissionsProvider verwendet werden') } return context }