production: docker + nginx config for rf-flux.com
Deploy to VPS / deploy (push) Has been cancelled

This commit is contained in:
2026-03-20 13:46:05 -05:00
parent b275b19f08
commit fc24313f15
187 changed files with 20977 additions and 767 deletions
+69
View File
@@ -0,0 +1,69 @@
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { jwtVerify } from 'jose';
// 🌍 1. Importamos el motor de idiomas
import createIntlMiddleware from 'next-intl/middleware';
import { routing } from './i18n/routing';
// Configuramos el proxy de next-intl
const handleI18nRouting = createIntlMiddleware(routing);
// 🔒 2. Llave de seguridad del CMS
const secretKey = process.env.SESSION_SECRET || "FLUX_SUPER_SECRET_KEY_2026_ARCHITECTURE";
const encodedKey = new TextEncoder().encode(secretKey);
// 🔥 AHORA SE LLAMA "proxy" EN LUGAR DE "middleware" 🔥
export async function proxy(request: NextRequest) {
const path = request.nextUrl.pathname;
// --------------------------------------------------------
// ZONA ROJA: CENTRO DE MANDO (Seguridad estricta, sin idiomas)
// --------------------------------------------------------
if (path.startsWith('/hq-command')) {
const isPublicHQRoute = path === '/hq-command/login' || path === '/hq-command/setup';
const cookie = request.cookies.get('flux_session')?.value;
// Si intenta entrar al dashboard sin pase
if (!isPublicHQRoute && !cookie) {
return NextResponse.redirect(new URL('/hq-command/login', request.url));
}
// Verificamos el pase
if (cookie) {
try {
await jwtVerify(cookie, encodedKey);
// Si tiene pase y está en el login, lo mandamos al dashboard
if (isPublicHQRoute) {
return NextResponse.redirect(new URL('/hq-command/dashboard', request.url));
}
return NextResponse.next(); // Pasa al CMS tranquilamente
} catch (error) {
// Pase falso o expirado
if (!isPublicHQRoute) {
return NextResponse.redirect(new URL('/hq-command/login', request.url));
}
}
}
return NextResponse.next(); // Pasa a login/setup si no hay cookie
}
// --------------------------------------------------------
// ZONA VERDE: WEB PÚBLICA (Motor de Traducciones i18n)
// --------------------------------------------------------
// Si el usuario no va al CMS, le pasamos el control a next-intl
// para que gestione los prefijos /en/, /it/, /vec/, etc.
return handleI18nRouting(request);
}
// --------------------------------------------------------
// OPTIMIZACIÓN EXTREMA DEL MATCHER
// --------------------------------------------------------
export const config = {
// Coincide con TODAS las rutas de la aplicación EXCEPTO:
// - /api (nuestras rutas backend)
// - /_next/static y /_next/image (archivos internos de React/Next)
// - Archivos estáticos como .jpg, .png, .mp4, .glb, .svg (.*\\..*)
// IMPORTANTE: Al ignorar los estáticos, las fotos y videos del CMS cargarán rapidísimo.
matcher: ['/((?!api|_next/static|_next/image|.*\\..*).*)'],
};