fix(cors,n8n): fix CORS for production, add unattended n8n init with seed #47

Merged
Ichitux merged 1 commits from fix/cors-n8n-init-seed into main 2026-07-17 10:59:56 +00:00
4 changed files with 54 additions and 128 deletions
Showing only changes of commit f6fc356c76 - Show all commits
+11 -4
View File
@@ -10,6 +10,11 @@ services:
POSTGRES_DB: farmafinder POSTGRES_DB: farmafinder
POSTGRES_USER: farmafinder POSTGRES_USER: farmafinder
POSTGRES_PASSWORD: ${PG_PASSWORD:-change-me-in-production} POSTGRES_PASSWORD: ${PG_PASSWORD:-change-me-in-production}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U farmafinder"]
interval: 5s
timeout: 3s
retries: 5
volumes: volumes:
- postgres_data:/var/lib/postgresql/data - postgres_data:/var/lib/postgresql/data
@@ -156,9 +161,12 @@ services:
- n8n_data:/home/node/.n8n - n8n_data:/home/node/.n8n
- ./n8n/workflows:/home/node/workflows - ./n8n/workflows:/home/node/workflows
depends_on: depends_on:
- postgres postgres:
condition: service_healthy
n8n-init:
condition: service_completed_successfully
# --- N8N Init: import workflows, activate, and seed DB --- # --- N8N Init: import + activate workflows BEFORE n8n starts, then seed DB ---
n8n-init: n8n-init:
image: n8nio/n8n:latest image: n8nio/n8n:latest
entrypoint: ["/bin/sh", "/home/node/init-import.sh"] entrypoint: ["/bin/sh", "/home/node/init-import.sh"]
@@ -174,10 +182,9 @@ services:
- n8n_data:/home/node/.n8n - n8n_data:/home/node/.n8n
- ./n8n/workflows:/home/node/workflows - ./n8n/workflows:/home/node/workflows
- ./n8n/init-import.sh:/home/node/init-import.sh:ro - ./n8n/init-import.sh:/home/node/init-import.sh:ro
- ./n8n/activate-workflows.js:/home/node/activate-workflows.js:ro
- ./n8n/seed.json:/home/node/seed.json:ro - ./n8n/seed.json:/home/node/seed.json:ro
depends_on: depends_on:
n8n: postgres:
condition: service_healthy condition: service_healthy
parapharmacy-api: parapharmacy-api:
condition: service_healthy condition: service_healthy
-82
View File
@@ -1,82 +0,0 @@
// Activate all inactive n8n workflows via API.
// Usage: node activate-workflows.js <email> <password>
import http from 'node:http';
const [, , email, password] = process.argv;
if (!email || !password) {
console.error('Usage: node activate-workflows.js <email> <password>');
process.exit(1);
}
const HOST = 'n8n';
const PORT = 5678;
function request(method, path, body, cookie) {
return new Promise((resolve, reject) => {
const opts = {
hostname: HOST, port: PORT, path, method,
headers: { 'Content-Type': 'application/json' },
};
if (cookie) opts.headers['Cookie'] = cookie;
const req = http.request(opts, (res) => {
const chunks = [];
res.on('data', (c) => chunks.push(c));
res.on('end', () => {
const raw = Buffer.concat(chunks).toString();
const setCookie = res.headers['set-cookie'];
let cookieVal = cookie;
if (setCookie) {
const match = setCookie.find((c) => c.startsWith('n8n-auth='));
if (match) cookieVal = match.split(';')[0];
}
let data;
try { data = JSON.parse(raw); } catch { data = raw; }
resolve({ status: res.statusCode, data, cookie: cookieVal });
});
});
req.on('error', reject);
if (body) req.write(JSON.stringify(body));
req.end();
});
}
async function main() {
// 1. Login
console.log('[activate] Logging in...');
const login = await request('POST', '/api/v1/login', { email, password });
if (!login.cookie) {
console.error('[activate] Login failed — no session cookie.');
process.exit(1);
}
console.log('[activate] Login OK.');
// 2. List workflows
const list = await request('GET', '/api/v1/workflows', null, login.cookie);
const workflows = list.data?.data || list.data || [];
if (!Array.isArray(workflows)) {
console.error('[activate] Unexpected response:', JSON.stringify(list.data).slice(0, 200));
process.exit(1);
}
// 3. Activate inactive ones
let activated = 0;
for (const wf of workflows) {
if (!wf.active) {
const res = await request('PATCH', `/api/v1/workflows/${wf.id}`, { active: true }, login.cookie);
if (res.status < 300) {
console.log(`[activate] Activated: ${wf.name || wf.id}`);
activated++;
} else {
console.error(`[activate] Failed to activate ${wf.id}: HTTP ${res.status}`);
}
}
}
console.log(`[activate] Done. ${activated} workflow(s) activated.`);
}
main().catch((err) => {
console.error('[activate] Error:', err.message);
process.exit(1);
});
+21 -20
View File
@@ -1,5 +1,6 @@
#!/bin/sh #!/bin/sh
# One-shot init: import workflows, activate them, and seed the DB. # One-shot init: import + activate workflows (before n8n starts), then seed DB.
# Runs BEFORE n8n so it reads the activated state from DB on startup.
# Skips if already done (flag file in shared n8n_data volume). # Skips if already done (flag file in shared n8n_data volume).
set -e set -e
@@ -10,29 +11,29 @@ if [ -f "$FLAG" ]; then
exit 0 exit 0
fi fi
# ── 1. Wait for n8n ────────────────────────────────────────────────── # ── 1. Import workflows via CLI (writes to DB) ───────────────────────
echo "[n8n-init] Waiting for n8n to be ready..."
until wget -qO /dev/null http://n8n:5678/healthz 2>/dev/null; do
sleep 2
done
echo "[n8n-init] n8n is up."
# ── 2. Import workflows ──────────────────────────────────────────────
echo "[n8n-init] Importing workflows..." echo "[n8n-init] Importing workflows..."
n8n import:workflow --separate --input=/home/node/workflows/ n8n import:workflow --separate --input=/home/node/workflows/ 2>/dev/null
echo "[n8n-init] Workflows imported."
# ── 3. Activate workflows via n8n API (Node.js) ───────────────────── # ── 3. Activate all workflows via CLI ────────────────────────────────
if [ -f /home/node/activate-workflows.js ]; then echo "[n8n-init] Activating workflows..."
echo "[n8n-init] Activating workflows via n8n API..." TMPFILE=$(mktemp)
node /home/node/activate-workflows.js "${N8N_OWNER_EMAIL}" "${N8N_OWNER_PASSWORD}" || \ n8n export:workflow --all --output="$TMPFILE" 2>/dev/null
echo "[n8n-init] WARNING: Workflow activation failed. Activate manually via n8n UI."
else node -e "
echo "[n8n-init] WARNING: activate-workflows.js not found, skipping activation." const fs = require('fs');
fi const wfs = JSON.parse(fs.readFileSync('$TMPFILE', 'utf8'));
wfs.forEach(w => console.log(w.id));
" | while read -r WF_ID; do
n8n publish:workflow --id="$WF_ID" 2>/dev/null
echo "[n8n-init] Activated $WF_ID"
done
rm -f "$TMPFILE"
echo "[n8n-init] Workflows activated."
# ── 4. Seed parapharmacy DB ────────────────────────────────────────── # ── 4. Seed parapharmacy DB ──────────────────────────────────────────
echo "[n8n-init] Waiting for parapharmacy-api to be ready..." echo "[n8n-init] Waiting for parapharmacy-api..."
until wget -qO /dev/null http://parapharmacy-api:3002/api/health 2>/dev/null; do until wget -qO /dev/null http://parapharmacy-api:3002/api/health 2>/dev/null; do
sleep 2 sleep 2
done done
+22 -22
View File
@@ -1,22 +1,22 @@
[ {"products": [
{"name":"Bioderma Atoderm Crema Hidratante 500ml","brand":"Bioderma","category":"Dermocosmética","price":18.95,"source":"seed","source_product_id":"seed_bioderma_atoderm","currency":"EUR","available":true}, {"name":"Bioderma Atoderm Crema Hidratante 500ml","brand":"Bioderma","category":"Dermocosmética","price":18.95,"source":"seed","source_product_id":"seed_bioderma_atoderm","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"La Roche-Posay Anthelios Airlicium FPS50+","brand":"La Roche-Posay","category":"Solar","price":19.95,"source":"seed","source_product_id":"seed_lrp_anthelios","currency":"EUR","available":true}, {"name":"La Roche-Posay Anthelios Airlicium FPS50+","brand":"La Roche-Posay","category":"Solar","price":19.95,"source":"seed","source_product_id":"seed_lrp_anthelios","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Mustela Gel de Ducha 500ml","brand":"Mustela","category":"Bebé","price":12.50,"source":"seed","source_product_id":"seed_mustela_gel","currency":"EUR","available":true}, {"name":"Mustela Gel de Ducha 500ml","brand":"Mustela","category":"Bebé","price":12.50,"source":"seed","source_product_id":"seed_mustela_gel","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Centrum Multivitaminicos 30 comprimidos","brand":"Centrum","category":"Vitaminas","price":15.80,"source":"seed","source_product_id":"seed_centrum_multi","currency":"EUR","available":true}, {"name":"Centrum Multivitaminicos 30 comprimidos","brand":"Centrum","category":"Vitaminas","price":15.80,"source":"seed","source_product_id":"seed_centrum_multi","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Dolocordalpan 1g Paracetamol 20 sobres","brand":"Dolocordalpan","category":"Analgésicos","price":4.95,"source":"seed","source_product_id":"seed_dolocordalpan","currency":"EUR","available":true}, {"name":"Dolocordalpan 1g Paracetamol 20 sobres","brand":"Dolocordalpan","category":"Analgésicos","price":4.95,"source":"seed","source_product_id":"seed_dolocordalpan","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Nurofen Flash 400mg 20 cápsulas","brand":"Nurofen","category":"Antiinflamatorios","price":6.75,"source":"seed","source_product_id":"seed_nurofen_flash","currency":"EUR","available":true}, {"name":"Nurofen Flash 400mg 20 cápsulas","brand":"Nurofen","category":"Antiinflamatorios","price":6.75,"source":"seed","source_product_id":"seed_nurofen_flash","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Omeprazol Cinfa 20mg 28 cápsulas","brand":"Cinfa","category":"Gastrointestinal","price":8.50,"source":"seed","source_product_id":"seed_omeprazol_cinfa","currency":"EUR","available":true}, {"name":"Omeprazol Cinfa 20mg 28 cápsulas","brand":"Cinfa","category":"Gastrointestinal","price":8.50,"source":"seed","source_product_id":"seed_omeprazol_cinfa","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Vichy Mineral 89 Sérum Hidratante 30ml","brand":"Vichy","category":"Dermocosmética","price":25.90,"source":"seed","source_product_id":"seed_vichy_mineral89","currency":"EUR","available":true}, {"name":"Vichy Mineral 89 Sérum Hidratante 30ml","brand":"Vichy","category":"Dermocosmética","price":25.90,"source":"seed","source_product_id":"seed_vichy_mineral89","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Avène Agua Termal 300ml","brand":"Avène","category":"Dermocosmética","price":9.95,"source":"seed","source_product_id":"seed_avene_agua","currency":"EUR","available":true}, {"name":"Avène Agua Termal 300ml","brand":"Avène","category":"Dermocosmética","price":9.95,"source":"seed","source_product_id":"seed_avene_agua","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"CeraVe Crema Hidratante 340g","brand":"CeraVe","category":"Dermocosmética","price":14.95,"source":"seed","source_product_id":"seed_cerave_crema","currency":"EUR","available":true}, {"name":"CeraVe Crema Hidratante 340g","brand":"CeraVe","category":"Dermocosmética","price":14.95,"source":"seed","source_product_id":"seed_cerave_crema","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Ibuprofeno Alter 600mg 20 comprimidos","brand":"Alter","category":"Antiinflamatorios","price":5.20,"source":"seed","source_product_id":"seed_ibuprofeno_alter","currency":"EUR","available":true}, {"name":"Ibuprofeno Alter 600mg 20 comprimidos","brand":"Alter","category":"Antiinflamatorios","price":5.20,"source":"seed","source_product_id":"seed_ibuprofeno_alter","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Salonpas Parches Analgésicos 5 unidades","brand":"Salonpas","category":"Analgésicos","price":7.80,"source":"seed","source_product_id":"seed_salonpas","currency":"EUR","available":true}, {"name":"Salonpas Parches Analgésicos 5 unidades","brand":"Salonpas","category":"Analgésicos","price":7.80,"source":"seed","source_product_id":"seed_salonpas","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Fisiomer Spray Nasal 135ml","brand":"Fisiomer","category":"Respiratorio","price":11.50,"source":"seed","source_product_id":"seed_fisiomer","currency":"EUR","available":true}, {"name":"Fisiomer Spray Nasal 135ml","brand":"Fisiomer","category":"Respiratorio","price":11.50,"source":"seed","source_product_id":"seed_fisiomer","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Thealoz Duo Colirio 10ml","brand":"Thea","category":"Oftalmología","price":12.95,"source":"seed","source_product_id":"seed_thealoz","currency":"EUR","available":true}, {"name":"Thealoz Duo Colirio 10ml","brand":"Thea","category":"Oftalmología","price":12.95,"source":"seed","source_product_id":"seed_thealoz","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Neutrogena Crema Manos Noruega 50ml","brand":"Neutrogena","category":"Dermocosmética","price":4.50,"source":"seed","source_product_id":"seed_neutrogena_manos","currency":"EUR","available":true}, {"name":"Neutrogena Crema Manos Noruega 50ml","brand":"Neutrogena","category":"Dermocosmética","price":4.50,"source":"seed","source_product_id":"seed_neutrogena_manos","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Capricare 1 Leche en polvo 400g","brand":"Capricare","category":"Fórmulas lácteas","price":14.95,"source":"seed","source_product_id":"seed_capricare1","currency":"EUR","available":true}, {"name":"Capricare 1 Leche en polvo 400g","brand":"Capricare","category":"Fórmulas lácteas","price":14.95,"source":"seed","source_product_id":"seed_capricare1","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Nutribén 2 Leche 800g","brand":"Nutribén","category":"Fórmulas lácteas","price":16.50,"source":"seed","source_product_id":"seed_nutriben2","currency":"EUR","available":true}, {"name":"Nutribén 2 Leche 800g","brand":"Nutribén","category":"Fórmulas lácteas","price":16.50,"source":"seed","source_product_id":"seed_nutriben2","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Bebelin Vitamina C 1g 20 comprimidos","brand":"Bebelín","category":"Vitaminas","price":6.95,"source":"seed","source_product_id":"seed_bebelin_vitc","currency":"EUR","available":true}, {"name":"Bebelin Vitamina C 1g 20 comprimidos","brand":"Bebelín","category":"Vitaminas","price":6.95,"source":"seed","source_product_id":"seed_bebelin_vitc","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Lacer Pasta Dientes Sensibilidad 75ml","brand":"Lacer","category":"Oral","price":5.80,"source":"seed","source_product_id":"seed_lacer_pasta","currency":"EUR","available":true}, {"name":"Lacer Pasta Dientes Sensibilidad 75ml","brand":"Lacer","category":"Oral","price":5.80,"source":"seed","source_product_id":"seed_lacer_pasta","source_url":"https://www.promofarma.com","currency":"EUR","available":true},
{"name":"Fotosan Crema Solar FPS50 200ml","brand":"Fotosan","category":"Solar","price":22.50,"source":"seed","source_product_id":"seed_fotosan_solar","currency":"EUR","available":true} {"name":"Fotosan Crema Solar FPS50 200ml","brand":"Fotosan","category":"Solar","price":22.50,"source":"seed","source_product_id":"seed_fotosan_solar","source_url":"https://www.promofarma.com","currency":"EUR","available":true}
] ]}