183 lines
5.4 KiB
JavaScript
183 lines
5.4 KiB
JavaScript
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 <PermissionsContext.Provider value={value}>{children}</PermissionsContext.Provider>
|
|
}
|
|
|
|
export const usePermissions = () => {
|
|
const context = useContext(PermissionsContext)
|
|
if (!context) {
|
|
throw new Error('usePermissions muss innerhalb eines PermissionsProvider verwendet werden')
|
|
}
|
|
return context
|
|
}
|
|
|