feat: production deployment - full update with providers, admin, glossaries, pricing, tests
Major changes across backend, frontend, infrastructure: - Provider system with model selection (Google, DeepL, OpenAI, Ollama, Google Cloud) - Admin panel: user management, pricing, settings - Glossary system with CSV import/export - Subscription and tier quota management - Security hardening (rate limiting, API key auth, path traversal fixes) - Docker compose for dev, prod, and IONOS deployment - Alembic migrations for new tables - Frontend: dashboard, pricing page, landing page, i18n (en/fr) - Test suite and verification scripts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,18 @@ export default function AdminLayout({
|
||||
const { settings, setAdminToken } = useTranslationStore();
|
||||
const [isChecking, setIsChecking] = useState(true);
|
||||
const [isValid, setIsValid] = useState(false);
|
||||
/** Sans ça, au premier rendu après un chargement complet le token n’est pas encore lu depuis localStorage → fausse absence de token → redirection /admin/login (bug sur F5 ou URL directe). */
|
||||
const [persistHydrated, setPersistHydrated] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const unsub = useTranslationStore.persist.onFinishHydration(() => {
|
||||
setPersistHydrated(true);
|
||||
});
|
||||
if (useTranslationStore.persist.hasHydrated()) {
|
||||
setPersistHydrated(true);
|
||||
}
|
||||
return unsub;
|
||||
}, []);
|
||||
|
||||
const verifyToken = useCallback(async (token: string): Promise<boolean> => {
|
||||
try {
|
||||
@@ -39,6 +51,10 @@ export default function AdminLayout({
|
||||
return;
|
||||
}
|
||||
|
||||
if (!persistHydrated) {
|
||||
return;
|
||||
}
|
||||
|
||||
const adminToken = settings.adminToken;
|
||||
if (!adminToken) {
|
||||
router.push(`/admin/login?redirect=${encodeURIComponent(pathname)}`);
|
||||
@@ -54,7 +70,7 @@ export default function AdminLayout({
|
||||
setIsValid(true);
|
||||
setIsChecking(false);
|
||||
});
|
||||
}, [settings.adminToken, pathname, router, verifyToken, setAdminToken]);
|
||||
}, [settings.adminToken, pathname, router, verifyToken, setAdminToken, persistHydrated]);
|
||||
|
||||
if (isChecking && pathname !== "/admin/login") {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user