Todos los Microservicios saludables.
Nuevo microservicio Plugins + cambios a microservicios anteriores, creación de módulos para conexiones a bases de datos y ajustes en las variables de entorno.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
# ===== Runtime =====
|
||||
NODE_ENV=development
|
||||
PORT=5050
|
||||
|
||||
|
||||
# ===== Session (usa el Redis del stack) =====
|
||||
# Para DEV podemos reutilizar el Redis de Authentik. En prod conviene uno separado.
|
||||
SESSION_SECRET=Neon*Mammal*Boaster*Ludicrous*Fender8*Crablike
|
||||
SESSION_COOKIE_NAME=sc.sid
|
||||
|
||||
# ===== DB principal (metadatos de SuiteCoffee) =====
|
||||
# Usa el alias de red del servicio 'db' (compose: aliases [dev-db])
|
||||
DB_HOST=dev-db
|
||||
DB_NAME=dev_suitecoffee_core
|
||||
DB_PORT=5432
|
||||
DB_USER=dev-user-suitecoffee
|
||||
DB_PASS=dev-pass-suitecoffee
|
||||
|
||||
CORE_DB_HOST=dev-db
|
||||
CORE_DB_NAME=dev_suitecoffee_core
|
||||
CORE_DB_PORT=5432
|
||||
CORE_DB_USER=dev-user-suitecoffee
|
||||
CORE_DB_PASS=dev-pass-suitecoffee
|
||||
|
||||
# ===== DB tenants (Tenants de SuiteCoffee) =====
|
||||
TENANTS_HOST=dev-tenants
|
||||
TENANTS_DB=dev_suitecoffee_tenants
|
||||
TENANTS_PORT=5432
|
||||
TENANTS_USER=suitecoffee
|
||||
TENANTS_PASS=suitecoffee
|
||||
|
||||
TENANTS_DB_HOST=dev-tenants
|
||||
TENANTS_DB_NAME=dev_suitecoffee_tenants
|
||||
TENANTS_DB_PORT=5432
|
||||
TENANTS_DB_USER=suitecoffee
|
||||
TENANTS_DB_PASS=suitecoffee
|
||||
|
||||
|
||||
# ===== Authentik — Admin API (server-to-server dentro de la red) =====
|
||||
# Usa el alias de red del servicio 'authentik' y su puerto interno 9000
|
||||
AK_TOKEN=h2apVHbd3ApMcnnSwfQPXbvximkvP8HnUE25ot3zXWuEEtJFaNCcOzDHB6Xw
|
||||
AK_REDIS_URL=redis://ak-redis:6379
|
||||
|
||||
# ===== OIDC (DEBE coincidir con el Provider) =====
|
||||
# DEV (todo dentro de la red de Docker):
|
||||
# - El auth service redirige al navegador a este issuer. Si NO tenés reverse proxy hacia Authentik,
|
||||
# esta URL interna NO será accesible desde el navegador del host. En ese caso, ver nota más abajo.
|
||||
|
||||
APP_BASE_URL=https://suitecoffee.uy
|
||||
|
||||
OIDC_LOGIN_URL=https://sso.suitecoffee.uy
|
||||
OIDC_REDIRECT_URI = https://suitecoffee.uy/auth/callback
|
||||
|
||||
OIDC_CLIEN_ID=1orMM8vOvf3WkN2FejXYvUFpPtONG0Lx1eMlwIpW
|
||||
OIDC_CONFIG_URL=https://sso.suitecoffee.uy/application/o/suitecoffee/.well-known/openid-configuration
|
||||
OIDC_ISSUER=https://sso.suitecoffee.uy/application/o/suitecoffee/
|
||||
OIDC_ISSUER_DISCOVERY=https://sso.suitecoffee.uy/application/o/suitecoffee/.well-known/openid-configuration
|
||||
OIDC_AUTHORIZE_URL=https://sso.suitecoffee.uy/application/o/authorize/
|
||||
OIDC_TOKEN_URL=https://sso.suitecoffee.uy/application/o/token/
|
||||
OIDC_USERINFO_URL=https://sso.suitecoffee.uy/application/o/userinfo/
|
||||
OIDC_LOGOUT_URL=https://sso.suitecoffee.uy/application/o/suitecoffee/end-session/
|
||||
OIDC_JWKS_URL=https://sso.suitecoffee.uy/application/o/suitecoffee/jwks/
|
||||
Generated
+2381
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "plugins",
|
||||
"version": "1.0.0",
|
||||
"main": "src/index.mjs",
|
||||
"scripts": {
|
||||
"start": "NODE_ENV=production node ./src/index.js",
|
||||
"dev": "NODE_ENV=development npx nodemon ./src/index.js",
|
||||
"test": "NODE_ENV=stage node ./src/index.js"
|
||||
},
|
||||
"author": "Mateo Saldain",
|
||||
"license": "ISC",
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"cross-env": "^10.0.0",
|
||||
"nodemon": "^3.1.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"bcrypt": "^6.0.0",
|
||||
"chalk": "^5.6.0",
|
||||
"connect-redis": "^9.0.0",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^17.2.1",
|
||||
"ejs": "^3.1.10",
|
||||
"express": "^5.1.0",
|
||||
"express-ejs-layouts": "^2.5.1",
|
||||
"express-session": "^1.18.2",
|
||||
"ioredis": "^5.7.0",
|
||||
"jose": "^6.1.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"jwks-rsa": "^3.2.0",
|
||||
"morgan": "^1.10.1",
|
||||
"node-appwrite": "^20.2.1",
|
||||
"node-fetch": "^3.3.2",
|
||||
"pg": "^8.16.3",
|
||||
"pg-format": "^1.0.4",
|
||||
"redis": "^5.8.2",
|
||||
"serve-favicon": "^2.5.1"
|
||||
},
|
||||
"imports": {
|
||||
"#v1Router": "./src/api/v1/routes/routes.js",
|
||||
"#pages": "./src/pages/pages.js",
|
||||
"#db": "./src/db/poolSingleton.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"description": ""
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// Coneción Singleton a base de datos.
|
||||
|
||||
import { Pool } from 'pg';
|
||||
|
||||
class DatabaseCore {
|
||||
constructor() {
|
||||
|
||||
if (DatabaseCore.instance) {
|
||||
return Database.instance;
|
||||
}
|
||||
|
||||
const config = {
|
||||
host: process.env.DB_HOST,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASS,
|
||||
database: process.env.DB_NAME,
|
||||
port: process.env.DB_LOCAL_PORT ? Number(process.env.DB_LOCAL_PORT) : undefined,
|
||||
ssl: process.env.PGSSL === 'true' ? { rejectUnauthorized: false } : undefined,
|
||||
};
|
||||
|
||||
this.connection = new Pool(config);
|
||||
|
||||
DatabaseCore.instance = this;
|
||||
}
|
||||
async query(sql, params) {
|
||||
return this.connection.query(sql,params);
|
||||
}
|
||||
|
||||
async connect() { /* Definida solo para evitar errores */
|
||||
return this.connection.connect();
|
||||
}
|
||||
async getClient() {
|
||||
return this.connection.connect();
|
||||
}
|
||||
|
||||
async release() {
|
||||
await this.connection.end();
|
||||
}
|
||||
}
|
||||
class DatabaseTenants {
|
||||
constructor() {
|
||||
|
||||
if (DatabaseTenants.instance) {
|
||||
return Database.instance;
|
||||
}
|
||||
|
||||
const config = {
|
||||
host: process.env.DB_HOST,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASS,
|
||||
database: process.env.DB_NAME,
|
||||
port: process.env.DB_LOCAL_PORT ? Number(process.env.DB_LOCAL_PORT) : undefined,
|
||||
ssl: process.env.PGSSL === 'true' ? { rejectUnauthorized: false } : undefined,
|
||||
};
|
||||
|
||||
this.connection = new Pool(config);
|
||||
|
||||
DatabaseTenants.instance = this;
|
||||
}
|
||||
async query(sql, params) {
|
||||
return this.connection.query(sql,params);
|
||||
}
|
||||
|
||||
async connect() { /* Definida solo para evitar errores */
|
||||
return this.connection.connect();
|
||||
}
|
||||
async getClient() {
|
||||
return this.connection.connect();
|
||||
}
|
||||
|
||||
async release() {
|
||||
await this.connection.end();
|
||||
}
|
||||
}
|
||||
|
||||
// const db = new Database();
|
||||
// db.query('SELECT * FROM users');
|
||||
|
||||
const poolCore = new DatabaseCore();
|
||||
const poolTenants = new DatabaseTenants();
|
||||
export default {poolCore, poolTenants};
|
||||
export { poolCore, poolTenants };
|
||||
@@ -0,0 +1,140 @@
|
||||
// services/plugins/asistencias/index.mjs
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
|
||||
import 'dotenv/config'; // Variables de Entorno
|
||||
import express from 'express';
|
||||
import expressLayouts from 'express-ejs-layouts';
|
||||
|
||||
import { poolCore, poolTenants } from '#db'; // dbCore y dbTenants
|
||||
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import cookieParser from 'cookie-parser';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Validación de entorno mínimo (ajusta nombres si difieren)
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Función para verificar que ciertas variables de entorno estén definida
|
||||
function checkRequiredEnvVars(...requiredKeys) {
|
||||
const missingKeys = requiredKeys.filter((key) => !process.env[key]); // Filtramos las que NO existen en process.env
|
||||
if (missingKeys.length > 0) { // Si falta alguna, mostramos una advertencia
|
||||
console.warn(
|
||||
`[PLUGIN] No se encontraron las siguientes variables de entorno: \n\n-> ${missingKeys.join('\n-> ')}`+
|
||||
`\n`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
checkRequiredEnvVars(
|
||||
'PORT',
|
||||
'CORE_DB_HOST', 'CORE_DB_PORT', 'CORE_DB_NAME',
|
||||
'TENANTS_DB_HOST', 'TENANTS_DB_PORT', 'TENANTS_DB_NAME'
|
||||
);
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Variables del sistema
|
||||
// ----------------------------------------------------------
|
||||
const PORT = process.env.PORT;
|
||||
|
||||
const CORE_DB_HOST = process.env.CORE_DB_HOST;
|
||||
const CORE_DB_PORT = process.env.CORE_DB_PORT;
|
||||
const CORE_DB_NAME = process.env.CORE_DB_NAME;
|
||||
|
||||
const TENANTS_DB_HOST = process.env.TENANTS_DB_HOST;
|
||||
const TENANTS_DB_PORT = process.env.TENANTS_DB_PORT;
|
||||
const TENANTS_DB_NAME = process.env.TENANTS_DB_NAME;
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// App + Motor de vistas EJS
|
||||
// ----------------------------------------------------------
|
||||
const app = express();
|
||||
app.set('trust proxy', true);
|
||||
app.set("views", path.join(__dirname, "views"));
|
||||
app.set("view engine", "ejs");
|
||||
app.set("layout", "layouts/main");
|
||||
|
||||
app.use(express.json());
|
||||
app.use(express.json({ limit: '1mb' }));
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(express.static(path.join(__dirname, 'public'))); // Carga de archivos estaticos
|
||||
|
||||
|
||||
app.use(expressLayouts); // Carga los layouts que usara el renderizado
|
||||
app.use(cookieParser(process.env.SESSION_SECRET));
|
||||
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Verificación de conexión
|
||||
// ----------------------------------------------------------
|
||||
|
||||
async function verificarConexionCore() {
|
||||
try {
|
||||
console.log(`[PLUGINS] Comprobando accesibilidad a la db ${CORE_DB_NAME} del host ${CORE_DB_HOST} ...`);
|
||||
const client = await poolCore.connect();
|
||||
const { rows } = await client.query('SELECT NOW() AS ahora');
|
||||
console.log(`\n[PLUGINS] Conexión con ${CORE_DB_NAME} OK. Hora DB:`, rows[0].ahora);
|
||||
client.release();
|
||||
} catch (error) {
|
||||
console.error('[PLUGINS] Error al conectar con la base de datos al iniciar:', error.message);
|
||||
console.error('[PLUGINS] Revisar credenciales, accesos de red y firewall.');
|
||||
}
|
||||
}
|
||||
async function verificarConexionTenants() {
|
||||
try {
|
||||
console.log(`[PLUGINS] Comprobando accesibilidad a la db ${TENANTS_DB_NAME} del host ${TENANTS_DB_HOST} ...`);
|
||||
const client = await poolTenants.connect();
|
||||
const { rows } = await client.query('SELECT NOW() AS ahora');
|
||||
console.log(`\n[PLUGINS] Conexión con ${TENANTS_DB_NAME} OK. Hora DB:`, rows[0].ahora);
|
||||
client.release();
|
||||
} catch (error) {
|
||||
console.error('[PLUGINS] Error al conectar con la base de datos al iniciar:', error.message);
|
||||
console.error('[PLUGINS] Revisar credenciales, accesos de red y firewall.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Middleware para datos globales
|
||||
// ----------------------------------------------------------
|
||||
app.use((req, res, next) => {
|
||||
res.locals.currentPath = req.path;
|
||||
res.locals.pageTitle = "SuiteCoffee";
|
||||
res.locals.pageId = "";
|
||||
next();
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Inicio del servidor
|
||||
// ----------------------------------------------------------
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`[PLUGINS] http://localhost:${PORT}`);
|
||||
verificarConexionCore();
|
||||
verificarConexionTenants();
|
||||
});
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Healthcheck
|
||||
// -----------------------------------------------------------------------------
|
||||
app.get('/health', (_req, res) => {
|
||||
res.status(200).json({ status: 'ok'}),
|
||||
console.log(`[PLUGINS] Saludable`)
|
||||
});
|
||||
Reference in New Issue
Block a user