Initial commit — DRB server stack

Includes c2-core (FastAPI/MQTT/Firestore), discord-bot (slash commands),
frontend (Next.js admin UI), and mosquitto config.
This commit is contained in:
Logan
2026-04-05 19:01:39 -04:00
commit 2f0597c81b
77 changed files with 4126 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
"use client";
import { createContext, useContext, useEffect, useState } from "react";
import { onAuthStateChanged, signOut as firebaseSignOut, User } from "firebase/auth";
import { auth } from "@/lib/firebase";
interface AuthContextType {
user: User | null;
loading: boolean;
isAdmin: boolean;
signOut: () => Promise<void>;
}
const AuthContext = createContext<AuthContextType>({
user: null,
loading: true,
isAdmin: false,
signOut: async () => {},
});
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const [isAdmin, setIsAdmin] = useState(false);
useEffect(() => {
return onAuthStateChanged(auth, async (u) => {
setUser(u);
setLoading(false);
if (u) {
document.cookie = "drb_session=1; path=/; SameSite=Strict";
// Read custom claims to determine admin status
const result = await u.getIdTokenResult(true);
setIsAdmin(!!result.claims.admin);
} else {
document.cookie = "drb_session=; path=/; max-age=0";
setIsAdmin(false);
}
});
}, []);
async function signOut() {
await firebaseSignOut(auth);
document.cookie = "drb_session=; path=/; max-age=0";
}
return (
<AuthContext.Provider value={{ user, loading, isAdmin, signOut }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
return useContext(AuthContext);
}