feat: initial zROC project recreation (stubs for large files pending)

- 61 files across zroc-ui/ and zroc-ova/ directories
- Full content written for: config, auth, API layers, CSS, build files,
  OVA scripts, backend routes, charts, hooks, constants
- Stubs in place for: page components, Sidebar, TopBar, docker-compose,
  authentik client, blueprint YAML, packer HCL, workflows, setup wizard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Justin
2026-04-12 16:20:05 -04:00
parent 74c05e5a58
commit 0500ac171c
61 changed files with 2262 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
// src/auth/AuthContext.jsx
import { createContext, useContext, useState, useEffect, useCallback } from 'react';
const AuthContext = createContext(null);
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const checkSession = useCallback(async () => {
try {
const res = await fetch('/api/auth/status', { credentials: 'include' });
if (res.ok) {
const data = await res.json();
setUser(data.authenticated ? data.user : null);
} else {
setUser(null);
}
} catch {
setUser(null);
} finally {
setLoading(false);
}
}, []);
useEffect(() => { checkSession(); }, [checkSession]);
const login = () => {
window.location.href = `/api/auth/login?redirect=${encodeURIComponent(window.location.pathname)}`;
};
const logout = async () => {
try {
const res = await fetch('/api/auth/logout', {
method: 'POST',
credentials: 'include',
});
if (res.ok) {
const { redirectUrl } = await res.json();
setUser(null);
window.location.href = redirectUrl || '/';
}
} catch {
setUser(null);
window.location.href = '/';
}
};
const isAdmin = user?.role === 'admin';
const isViewer = !!user;
return (
<AuthContext.Provider value={{ user, loading, login, logout, isAdmin, isViewer }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
return ctx;
}