more work with Dockerfile and dbmate
This commit is contained in:
@@ -14,5 +14,5 @@ COPY . .
|
|||||||
# Puerto de la aplicación
|
# Puerto de la aplicación
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
# Comando de inicio
|
# Ejecutar migraciones, seed y luego iniciar la app
|
||||||
CMD ["npm", "start"]
|
CMD ["sh", "-c", "npm run migrate:up && npm run seed && npm start"]
|
||||||
|
|||||||
13
db/migrations/20260204180834_seed_tenant_piaf.sql
Normal file
13
db/migrations/20260204180834_seed_tenant_piaf.sql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
-- migrate:up
|
||||||
|
-- Crear tenant Piaf (sin credenciales sensibles - esas van por variable de entorno)
|
||||||
|
|
||||||
|
INSERT INTO tenants (id, key, name)
|
||||||
|
VALUES (
|
||||||
|
'eb71b9a7-9ccf-430e-9b25-951a0c589c0f'::uuid,
|
||||||
|
'piaf',
|
||||||
|
'Piaf'
|
||||||
|
)
|
||||||
|
ON CONFLICT (id) DO NOTHING;
|
||||||
|
|
||||||
|
-- migrate:down
|
||||||
|
DELETE FROM tenants WHERE id = 'eb71b9a7-9ccf-430e-9b25-951a0c589c0f'::uuid;
|
||||||
@@ -9,6 +9,11 @@ services:
|
|||||||
- PORT=3000
|
- PORT=3000
|
||||||
- DATABASE_URL=postgres://${POSTGRES_USER:-botino}:${POSTGRES_PASSWORD:-botino}@db:5432/${POSTGRES_DB:-botino}
|
- DATABASE_URL=postgres://${POSTGRES_USER:-botino}:${POSTGRES_PASSWORD:-botino}@db:5432/${POSTGRES_DB:-botino}
|
||||||
- REDIS_URL=redis://redis:6379
|
- REDIS_URL=redis://redis:6379
|
||||||
|
# Variables para seed (configurar en Coolify)
|
||||||
|
- APP_ENCRYPTION_KEY=${APP_ENCRYPTION_KEY:-}
|
||||||
|
- WOO_CONSUMER_KEY=${WOO_CONSUMER_KEY:-}
|
||||||
|
- WOO_CONSUMER_SECRET=${WOO_CONSUMER_SECRET:-}
|
||||||
|
- WOO_BASE_URL=${WOO_BASE_URL:-}
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ OPENAI_MODEL=gpt-4o-mini
|
|||||||
TURN_ENGINE=v1
|
TURN_ENGINE=v1
|
||||||
|
|
||||||
# ===================
|
# ===================
|
||||||
# WooCommerce (fallback si falta config por tenant)
|
# WooCommerce (usado por seed y fallback)
|
||||||
|
# Estas variables son leídas por scripts/seed-tenant.mjs para crear
|
||||||
|
# la configuración inicial del tenant en la base de datos.
|
||||||
# ===================
|
# ===================
|
||||||
WOO_BASE_URL=https://tu-tienda.com
|
WOO_BASE_URL=https://tu-tienda.com
|
||||||
WOO_CONSUMER_KEY=ck_xxx
|
WOO_CONSUMER_KEY=ck_xxx
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
"migrate:up": "dbmate up",
|
"migrate:up": "dbmate up",
|
||||||
"migrate:down": "dbmate down",
|
"migrate:down": "dbmate down",
|
||||||
"migrate:redo": "dbmate rollback && dbmate up",
|
"migrate:redo": "dbmate rollback && dbmate up",
|
||||||
"migrate:status": "dbmate status"
|
"migrate:status": "dbmate status",
|
||||||
|
"seed": "node scripts/seed-tenant.mjs"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "Lucas Tettamanti",
|
"author": "Lucas Tettamanti",
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
"ajv": "^8.17.1",
|
"ajv": "^8.17.1",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"csv-parse": "^6.1.0",
|
"csv-parse": "^6.1.0",
|
||||||
|
"dbmate": "^2.0.0",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"mysql2": "^3.16.2",
|
"mysql2": "^3.16.2",
|
||||||
@@ -32,7 +34,6 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitest/coverage-v8": "^4.0.18",
|
"@vitest/coverage-v8": "^4.0.18",
|
||||||
"dbmate": "^2.0.0",
|
|
||||||
"nodemon": "^3.0.3",
|
"nodemon": "^3.0.3",
|
||||||
"vitest": "^4.0.18"
|
"vitest": "^4.0.18"
|
||||||
}
|
}
|
||||||
|
|||||||
93
scripts/seed-tenant.mjs
Normal file
93
scripts/seed-tenant.mjs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* Seed script para configurar tenant con credenciales de WooCommerce.
|
||||||
|
* Lee las credenciales de variables de entorno (no hardcodeadas).
|
||||||
|
*
|
||||||
|
* Variables requeridas:
|
||||||
|
* - DATABASE_URL: conexión a PostgreSQL
|
||||||
|
* - APP_ENCRYPTION_KEY: clave para encriptar credenciales
|
||||||
|
* - WOO_CONSUMER_KEY: consumer key de WooCommerce
|
||||||
|
* - WOO_CONSUMER_SECRET: consumer secret de WooCommerce
|
||||||
|
* - WOO_BASE_URL: URL base de WooCommerce (opcional, default: https://piaf.floda.dev/wp-json/wc/v3)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import pg from "pg";
|
||||||
|
|
||||||
|
const TENANT_ID = "eb71b9a7-9ccf-430e-9b25-951a0c589c0f";
|
||||||
|
|
||||||
|
async function seed() {
|
||||||
|
const {
|
||||||
|
DATABASE_URL,
|
||||||
|
APP_ENCRYPTION_KEY,
|
||||||
|
WOO_CONSUMER_KEY,
|
||||||
|
WOO_CONSUMER_SECRET,
|
||||||
|
WOO_BASE_URL = "https://piaf.floda.dev/wp-json/wc/v3",
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
// Validar variables requeridas
|
||||||
|
if (!DATABASE_URL) {
|
||||||
|
console.log("[seed] DATABASE_URL no configurada, saltando seed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!APP_ENCRYPTION_KEY || !WOO_CONSUMER_KEY || !WOO_CONSUMER_SECRET) {
|
||||||
|
console.log("[seed] Variables de WooCommerce no configuradas, saltando seed de ecommerce config");
|
||||||
|
console.log("[seed] Para configurar, definir: APP_ENCRYPTION_KEY, WOO_CONSUMER_KEY, WOO_CONSUMER_SECRET");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pool = new pg.Pool({ connectionString: DATABASE_URL });
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Verificar si ya existe la config
|
||||||
|
const check = await pool.query(
|
||||||
|
"SELECT 1 FROM tenant_ecommerce_config WHERE tenant_id = $1",
|
||||||
|
[TENANT_ID]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (check.rows.length > 0) {
|
||||||
|
console.log("[seed] tenant_ecommerce_config ya existe, saltando");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configurar encryption key para la sesión
|
||||||
|
await pool.query("SELECT set_config('app.encryption_key', $1, false)", [
|
||||||
|
APP_ENCRYPTION_KEY,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Insertar config de WooCommerce
|
||||||
|
await pool.query(
|
||||||
|
`INSERT INTO tenant_ecommerce_config (
|
||||||
|
tenant_id,
|
||||||
|
provider,
|
||||||
|
base_url,
|
||||||
|
credential_ref,
|
||||||
|
api_version,
|
||||||
|
timeout_ms,
|
||||||
|
enabled,
|
||||||
|
enc_consumer_key,
|
||||||
|
enc_consumer_secret
|
||||||
|
) VALUES (
|
||||||
|
$1::uuid,
|
||||||
|
'woo',
|
||||||
|
$2,
|
||||||
|
'secret://woo/piaf',
|
||||||
|
'wc/v3',
|
||||||
|
8000,
|
||||||
|
true,
|
||||||
|
pgp_sym_encrypt($3, current_setting('app.encryption_key')),
|
||||||
|
pgp_sym_encrypt($4, current_setting('app.encryption_key'))
|
||||||
|
)`,
|
||||||
|
[TENANT_ID, WOO_BASE_URL, WOO_CONSUMER_KEY, WOO_CONSUMER_SECRET]
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("[seed] tenant_ecommerce_config creada exitosamente");
|
||||||
|
} catch (err) {
|
||||||
|
console.error("[seed] Error:", err.message);
|
||||||
|
// No fallar el startup si el seed falla (puede ser que las tablas no existan aún)
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
seed();
|
||||||
Reference in New Issue
Block a user