feat: Añadir configuración de Nginx para el API de LMS y ajustar las rutas en el frontend de OpenCCB

This commit is contained in:
2026-03-31 12:32:55 -03:00
parent d331381efd
commit 2d2ea216e0
8 changed files with 79 additions and 8 deletions
+1
View File
@@ -20,6 +20,7 @@ services:
- html:/usr/share/nginx/html
- ./nginx/proxy.conf:/etc/nginx/conf.d/proxy.conf:ro
- ./nginx/studio.conf:/etc/nginx/vhost.d/studio.norteamericano.com:ro
- ./nginx/learning.conf:/etc/nginx/vhost.d/learning.norteamericano.com:ro
restart: always
networks:
- openccb-network
+13
View File
@@ -0,0 +1,13 @@
# Custom nginx configuration for OpenCCB Learning
# Keep the learning frontend on port 3003 and expose LMS API via same-origin /lms-api.
location /lms-api/ {
rewrite ^/lms-api/(.*)$ /$1 break;
proxy_pass http://openccb-experience:3002;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Connection "";
proxy_http_version 1.1;
}
+41 -2
View File
@@ -15,6 +15,17 @@ location /cms-api/ {
proxy_http_version 1.1;
}
location /lms-api/ {
rewrite ^/lms-api/(.*)$ /$1 break;
proxy_pass http://openccb-experience:3002;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Connection "";
proxy_http_version 1.1;
}
# Auth pages like GET /auth/login and GET /auth/register must be served by Next.js (3000),
# while the auth API endpoints (POST /auth/login, POST /auth/register, /auth/me, /auth/sso/*)
# must continue to go to the CMS backend (3001).
@@ -222,8 +233,28 @@ location /grading/ {
proxy_http_version 1.1;
}
location = /question-bank {
proxy_pass http://openccb-studio:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Connection "";
proxy_http_version 1.1;
}
location = /question-bank/ {
proxy_pass http://openccb-studio:3000/question-bank;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_set_header Connection "";
proxy_http_version 1.1;
}
location /question-bank/ {
proxy_pass http://openccb-studio:3001;
proxy_pass http://openccb-studio:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@@ -252,8 +283,16 @@ location = /admin/ {
proxy_http_version 1.1;
}
location = /admin/organizations {
return 302 /admin;
}
location = /admin/organizations/ {
return 302 /admin;
}
location /admin/ {
proxy_pass http://openccb-studio:3001;
proxy_pass http://openccb-studio:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+6 -1
View File
@@ -10,7 +10,12 @@ const getApiBaseUrl = (defaultPort: string, envVar?: string) => {
return `http://localhost:${defaultPort}`;
};
export const getLmsApiUrl = () => getApiBaseUrl("3002", process.env.NEXT_PUBLIC_LMS_API_URL);
export const getLmsApiUrl = () => {
if (typeof window !== 'undefined' && window.location.hostname === 'learning.norteamericano.com') {
return `${window.location.protocol}//learning.norteamericano.com/lms-api`;
}
return getApiBaseUrl("3002", process.env.NEXT_PUBLIC_LMS_API_URL);
};
export const getCmsApiUrl = () => getApiBaseUrl("3001", process.env.NEXT_PUBLIC_CMS_API_URL);
export const getImageUrl = (path?: string) => {
+8 -2
View File
@@ -25,7 +25,12 @@ const nextConfig = {
],
},
async rewrites() {
return [
// Using `fallback` ensures Next.js pages (including dynamic routes like
// /courses/[id]) are matched BEFORE these proxy rewrites. Without this,
// `afterFiles` rewrites (the default for arrays) would intercept RSC
// prefetch requests to dynamic pages and proxy them to Rust instead.
return {
fallback: [
{
source: '/assets/:path*',
destination: 'http://localhost:3001/assets/:path*',
@@ -143,7 +148,8 @@ const nextConfig = {
source: '/health',
destination: 'http://localhost:3001/health',
},
];
],
};
},
};
+1 -1
View File
@@ -20,7 +20,7 @@ export default function AdminLayout({ children }: { children: React.ReactNode })
const menuItems = [
{ icon: LayoutDashboard, label: "Dashboard", href: "/admin" },
{ icon: Building2, label: "Organizations", href: "/admin/organizations" },
{ icon: Building2, label: "Organizations", href: "/admin" },
{ icon: Users, label: "Users", href: "/admin/users" },
{ icon: Mic, label: "Audio Evaluations", href: "/admin/audio-evaluations" },
{ icon: ClipboardList, label: "Audit Logs", href: "/admin/audit" },
+1 -1
View File
@@ -10,7 +10,7 @@ export default function AuthHeader() {
<div className="flex items-center gap-4">
{user?.role === 'admin' && (
<>
<Link href="/admin/organizations" className="text-xs font-bold uppercase tracking-widest text-gray-400 hover:text-white transition-colors flex items-center gap-2" title="Organizations">
<Link href="/admin" className="text-xs font-bold uppercase tracking-widest text-gray-400 hover:text-white transition-colors flex items-center gap-2" title="Organizations">
<Building2 size={16} /> <span className="hidden md:inline">Org</span>
</Link>
<Link href="/admin/audit" className="text-xs font-bold uppercase tracking-widest text-gray-400 hover:text-white transition-colors flex items-center gap-2" title="Audit Logs">
+8 -1
View File
@@ -26,7 +26,14 @@ const getApiBaseUrl = (defaultPort: string, envVar?: string) => {
};
export const API_BASE_URL = getApiBaseUrl("3001", process.env.NEXT_PUBLIC_CMS_API_URL);
export const LMS_API_BASE_URL = getApiBaseUrl("3002", process.env.NEXT_PUBLIC_LMS_API_URL);
const getLmsBaseUrl = (envVar?: string) => {
if (typeof window !== 'undefined' && window.location.hostname === 'studio.norteamericano.com') {
return `${window.location.protocol}//studio.norteamericano.com/lms-api`;
}
return getApiBaseUrl("3002", envVar);
};
export const LMS_API_BASE_URL = getLmsBaseUrl(process.env.NEXT_PUBLIC_LMS_API_URL);
// Polyfill for crypto.randomUUID() for non-HTTPS contexts
export function generateUUID(): string {