Actualizaciones de archivo.

Modificaciones pequeñas
This commit is contained in:
Mateo Saldain 2025-08-16 03:25:24 +00:00
parent f9bf5f4824
commit 97db600b1f
9 changed files with 124 additions and 134 deletions

View File

@ -17,12 +17,15 @@ services:
- "81:81" # UI de administración NPM
- "443:443" # HTTPS público
volumes:
- npm_data:/data # config + DB (SQLite)
- npm_letsencrypt:/etc/letsencrypt
- dev-npm_data:/data # config + DB (SQLite)
- dev-npm_letsencrypt:/etc/letsencrypt
networks:
- suitecoffee-net
suitecoffee-app:
image: node:20-bookworm
container_name: suitecoffee-app
depends_on:
suitecoffee-db:
@ -31,9 +34,11 @@ services:
condition: service_healthy
ports:
- 3000:3000
working_dir: /app
user: "${UID:-1000}:${GID:-1000}"
volumes:
- ./services/app:/app
- /app/node_modules
- ./services/app:/app:rw
- ./node_modules:/app/node_modules
env_file:
- ./services/app/.env.development
environment:
@ -50,16 +55,22 @@ services:
networks:
- suitecoffee-net
suitecoffee-auth:
image: node:20-bookworm
container_name: suitecoffee-auth
depends_on:
suitecoffee-db:
condition: service_healthy
ports:
- 4000:4000
working_dir: /app
user: "${UID:-1000}:${GID:-1000}"
volumes:
- ./services/auth:/app
- /app/node_modules
- ./services/app:/app:rw
- ./node_modules:/app/node_modules
env_file:
- ./services/auth/.env.development
environment:
@ -83,9 +94,9 @@ services:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASS}
ports:
- 54321:5432
- ${DB_LOCAL_PORT}:${DB_DOCKER_PORT}
volumes:
- suitecoffee-data:/var/lib/postgresql/data
- dev-suitecoffee-data:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
@ -104,9 +115,9 @@ services:
POSTGRES_USER: ${TENANTS_DB_USER}
POSTGRES_PASSWORD: ${TENANTS_DB_PASS}
volumes:
- tenants-data:/var/lib/postgresql/data
- dev-tenants-data:/var/lib/postgresql/data
ports:
- 54322:5432
- ${TENANTS_DB_LOCAL_PORT}:${TENANTS_DB_DOCKER_PORT}
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${TENANTS_DB_USER} -d ${TENANTS_DB_NAME}"]
@ -129,8 +140,8 @@ services:
ports:
- 8978:8978
volumes:
- dbeaver_logs:/opt/cloudbeaver/logs
- dbeaver_workspace:/opt/cloudbeaver/workspace
- dev-dbeaver_logs:/opt/cloudbeaver/logs
- dev-dbeaver_workspace:/opt/cloudbeaver/workspace
networks:
- suitecoffee-net
@ -149,12 +160,12 @@ services:
# - suitecoffee-net
volumes:
tenants-data:
suitecoffee-data:
npm_data:
npm_letsencrypt:
dbeaver_logs:
dbeaver_workspace:
dev-tenants-data:
dev-suitecoffee-data:
dev-npm_data:
dev-npm_letsencrypt:
dev-dbeaver_logs:
dev-dbeaver_workspace:
networks:
suitecoffee-net:

View File

@ -1,5 +1,6 @@
{
"dependencies": {
"app": "file:services/app"
"app": "file:services/app",
"auth": "file:services/auth"
}
}

View File

@ -1,13 +0,0 @@
{
"watch": ["src"],
"ext": "js,json",
"ignore": [
"node_modules/**/node_modules",
"node_modules/",
".git"
],
"env": {
"NODE_ENV": "development"
},
"exec": "node ./src/index.js"
}

View File

@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"chalk": "^5.3.0",
"chalk": "^5.5.0",
"cors": "^2.8.5",
"dotenv": "^17.2.1",
"express": "^5.1.0",

View File

@ -1,10 +1,10 @@
{
"name": "app",
"name": "suitecoffee_aplication_service",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "NODE_ENV=production node ./src/index.js",
"dev": "npx nodemon",
"dev": "NODE_ENV=development npx nodemon ./src/index.js",
"test": "NODE_ENV=stage node ./src/index.js"
},
"author": "Mateo Saldain",
@ -15,7 +15,7 @@
"nodemon": "^3.1.10"
},
"dependencies": {
"chalk": "^5.3.0",
"chalk": "^5.5.0",
"cors": "^2.8.5",
"dotenv": "^17.2.1",
"express": "^5.1.0",

View File

@ -1,13 +0,0 @@
{
"watch": ["src"],
"ext": "js,json",
"ignore": [
"node_modules/**/node_modules",
"node_modules/",
".git"
],
"env": {
"NODE_ENV": "development"
},
"exec": "node ./src/index.js"
}

View File

@ -10,7 +10,7 @@
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.1",
"chalk": "^5.3.0",
"chalk": "^5.5.0",
"cors": "^2.8.5",
"dotenv": "^17.2.1",
"express": "^5.1.0",

View File

@ -1,10 +1,10 @@
{
"name": "auth",
"name": "suitecoffee_authentication_service",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "NODE_ENV=production node ./src/index.js",
"dev": "npx nodemon",
"dev": "NODE_ENV=development npx nodemon ./src/index.js",
"test": "NODE_ENV=stage node ./src/index.js"
},
"author": "Mateo Saldain",
@ -16,7 +16,7 @@
},
"dependencies": {
"bcrypt": "^5.1.1",
"chalk": "^5.3.0",
"chalk": "^5.5.0",
"cors": "^2.8.5",
"dotenv": "^17.2.1",
"express": "^5.1.0",

View File

@ -1,10 +1,12 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>SuiteCoffee - Autenticación</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light d-flex justify-content-center align-items-center vh-100">
<div class="card shadow p-4" style="width: 100%; max-width: 400px;">
@ -51,101 +53,103 @@
<div class="text-center mt-3">
<button class="btn btn-link btn-sm" id="toggle-mode">¿No tienes cuenta? Regístrate</button>
</div>
<p>Hola!</p>
</div>
<script>
const form = document.getElementById('formulario');
const mensaje = document.getElementById('mensaje');
const toggleModeBtn = document.getElementById('toggle-mode');
const registroExtra = document.getElementById('registro-extra');
const formTitle = document.getElementById('form-title');
const btnSubmit = document.getElementById('btn-submit');
const form = document.getElementById('formulario');
const mensaje = document.getElementById('mensaje');
const toggleModeBtn = document.getElementById('toggle-mode');
const registroExtra = document.getElementById('registro-extra');
const formTitle = document.getElementById('form-title');
const btnSubmit = document.getElementById('btn-submit');
let modoRegistro = false;
let modoRegistro = false;
toggleModeBtn.addEventListener('click', () => {
modoRegistro = !modoRegistro;
registroExtra.style.display = modoRegistro ? 'block' : 'none';
formTitle.textContent = modoRegistro ? 'Registrar Cuenta' : 'Iniciar Sesión';
btnSubmit.textContent = modoRegistro ? 'Registrarse' : 'Entrar';
toggleModeBtn.textContent = modoRegistro ? '¿Ya tienes cuenta? Inicia sesión' : '¿No tienes cuenta? Regístrate';
toggleModeBtn.addEventListener('click', () => {
modoRegistro = !modoRegistro;
registroExtra.style.display = modoRegistro ? 'block' : 'none';
formTitle.textContent = modoRegistro ? 'Registrar Cuenta' : 'Iniciar Sesión';
btnSubmit.textContent = modoRegistro ? 'Registrarse' : 'Entrar';
toggleModeBtn.textContent = modoRegistro ? '¿Ya tienes cuenta? Inicia sesión' : '¿No tienes cuenta? Regístrate';
if (modoRegistro) {
cargarPlanes(); // ✅ ahora sí se ejecutará correctamente
}
});
if (modoRegistro) {
cargarPlanes(); // ✅ ahora sí se ejecutará correctamente
}
});
form.addEventListener('submit', async (e) => {
e.preventDefault();
mensaje.classList.add('d-none');
form.addEventListener('submit', async (e) => {
e.preventDefault();
mensaje.classList.add('d-none');
const datos = {
correo: document.getElementById('correo').value,
clave_acceso: document.getElementById('clave').value
};
const datos = {
correo: document.getElementById('correo').value,
clave_acceso: document.getElementById('clave').value
};
if (modoRegistro) {
Object.assign(datos, {
nombre_empresa: document.getElementById('nombre_empresa').value,
rut: document.getElementById('rut').value,
telefono: document.getElementById('telefono').value,
direccion: document.getElementById('direccion').value,
logo: document.getElementById('logo').value,
plan_id: document.getElementById('plan_id').value
});
}
try {
const url = modoRegistro ? '/api/registro' : '/api/login';
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(datos)
});
const resultado = await res.json();
if (!res.ok) {
throw new Error(resultado.error || 'Error inesperado');
if (modoRegistro) {
Object.assign(datos, {
nombre_empresa: document.getElementById('nombre_empresa').value,
rut: document.getElementById('rut').value,
telefono: document.getElementById('telefono').value,
direccion: document.getElementById('direccion').value,
logo: document.getElementById('logo').value,
plan_id: document.getElementById('plan_id').value
});
}
mensaje.className = 'alert alert-success';
mensaje.textContent = resultado.message || (modoRegistro ? 'Registro exitoso' : 'Inicio exitoso');
mensaje.classList.remove('d-none');
try {
const url = modoRegistro ? '/api/registro' : '/api/login';
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(datos)
});
if (!modoRegistro) {
// Redirigir a dashboard, por ejemplo
// window.location.href = `/dashboard?tenant=${resultado.uuid}`;
const resultado = await res.json();
if (!res.ok) {
throw new Error(resultado.error || 'Error inesperado');
}
mensaje.className = 'alert alert-success';
mensaje.textContent = resultado.message || (modoRegistro ? 'Registro exitoso' : 'Inicio exitoso');
mensaje.classList.remove('d-none');
if (!modoRegistro) {
// Redirigir a dashboard, por ejemplo
// window.location.href = `/dashboard?tenant=${resultado.uuid}`;
}
} catch (err) {
mensaje.className = 'alert alert-danger';
mensaje.textContent = err.message;
mensaje.classList.remove('d-none');
}
});
// ✅ Ahora la función está declarada correctamente
async function cargarPlanes() {
const select = document.getElementById('plan_id');
select.innerHTML = '<option value="">Cargando planes...</option>';
try {
const res = await fetch('/planes');
const planes = await res.json();
select.innerHTML = '<option value="">Seleccione un plan</option>';
planes.forEach(plan => {
const opt = document.createElement('option');
opt.value = plan.id;
opt.textContent = plan.nombre.charAt(0).toUpperCase() + plan.nombre.slice(1);
select.appendChild(opt);
});
} catch (err) {
select.innerHTML = '<option value="">Error al cargar planes</option>';
console.error('Error cargando planes:', err);
}
} catch (err) {
mensaje.className = 'alert alert-danger';
mensaje.textContent = err.message;
mensaje.classList.remove('d-none');
}
});
// ✅ Ahora la función está declarada correctamente
async function cargarPlanes() {
const select = document.getElementById('plan_id');
select.innerHTML = '<option value="">Cargando planes...</option>';
try {
const res = await fetch('/planes');
const planes = await res.json();
select.innerHTML = '<option value="">Seleccione un plan</option>';
planes.forEach(plan => {
const opt = document.createElement('option');
opt.value = plan.id;
opt.textContent = plan.nombre.charAt(0).toUpperCase() + plan.nombre.slice(1);
select.appendChild(opt);
});
} catch (err) {
select.innerHTML = '<option value="">Error al cargar planes</option>';
console.error('Error cargando planes:', err);
}
}
</script>
</body>
</html>
</html>