A few connected fixes around the invite UI shipped in 81d61aa:
1. **Bug in 81d61aa**: `auth.js` referenced `erpFetch` without importing
it, so every invite returned `erpnext.ok=false` with the silent
"erpFetch is not defined" error in the catch. Imported it from
./helpers alongside the other helpers we already used.
2. **Authentik recovery flow not configured** (caught while smoke-testing):
the brand `auth.targo.ca` has `flow_recovery=None` and no SMTP, so
`POST /core/users/{pk}/recovery_email/` returned 400 "No recovery
flow set." Rather than build out a full Authentik recovery flow
via API (multiple stages, brand patch, SMTP env var changes), the
hub now generates a strong-but-readable temp password
(`X7K2-9NQB-4GHM-3RTW` style — no look-alike chars), POSTs it via
`/core/users/{pk}/set_password/`, and emails it via the existing
Mailjet SMTP (already wired into lib/email.js for invoice sends).
Returns `{temp_password, password_set, email_sent}` so the admin
has a fallback if Mailjet drops the message.
3. **Settings dialog** now shows a credentials panel after submit:
• Green banner "✓ Courriel envoyé" when email_sent=true
• Yellow "⚠ transmettez manuellement" when email_sent=false
• The temp password as a copyable field either way
• ERPNext User creation status
4. **Dev onboarding**: added `apps/ops/.env.example`,
`services/targo-hub/.env.example`, and a top-level `docs/SETUP.md`
that explains the local-dev flow (clone → cp .env.example .env →
npm install → npx quasar dev). The example envs are commented
per-section so a new dev knows which keys correspond to which
external integration. None of the real secrets are checked in —
the .gitignore already covers .env files.
103 lines
5.8 KiB
Plaintext
103 lines
5.8 KiB
Plaintext
# ─────────────────────────────────────────────────────────────────────────
|
|
# services/targo-hub — Node/Express middleware
|
|
# Copy to `services/targo-hub/.env`, fill in the values, then
|
|
# `node server.js` or `docker compose up -d` from /opt/targo-hub.
|
|
#
|
|
# Most of these are integration secrets; ask the team for the real
|
|
# values. Anything left blank disables the corresponding feature
|
|
# (e.g. no STRIPE_SECRET_KEY → Stripe billing endpoints return 503).
|
|
# ─────────────────────────────────────────────────────────────────────────
|
|
|
|
# ─── Core ────────────────────────────────────────────────────────────────
|
|
PORT=3300
|
|
HUB_PUBLIC_URL=https://msg.gigafibre.ca
|
|
HUB_INTERNAL_TOKEN= # shared secret for hub→hub & flow auth
|
|
JWT_SECRET= # 32+ chars random — signs magic links
|
|
|
|
# ─── ERPNext ─────────────────────────────────────────────────────────────
|
|
ERP_URL=http://erpnext-backend:8000
|
|
ERP_TOKEN= # api_key:api_secret with admin scope
|
|
MAIL_FROM=noreply@gigafibre.ca
|
|
|
|
# ─── Authentik (SSO) ─────────────────────────────────────────────────────
|
|
# Used by /auth/users (invite, list, group sync) on the staff instance.
|
|
AUTHENTIK_URL=https://auth.targo.ca
|
|
AUTHENTIK_TOKEN= # API token, scope: write:user write:group
|
|
|
|
# ─── Authentication adapters ─────────────────────────────────────────────
|
|
# Used by /auth/sync-legacy to pull staff from the old MySQL DB.
|
|
LEGACY_DB_HOST=
|
|
LEGACY_DB_USER=
|
|
LEGACY_DB_PASS=
|
|
LEGACY_DB_NAME=
|
|
|
|
# ─── Email (Mailjet via SMTP) ────────────────────────────────────────────
|
|
# Mailjet relay — same creds as ERPNext. Used for invites, voice-agent
|
|
# transcripts, quotation sends, etc.
|
|
SMTP_HOST=in-v3.mailjet.com
|
|
SMTP_PORT=587
|
|
SMTP_USER=
|
|
SMTP_PASS=
|
|
|
|
# ─── Twilio (SMS + voice) ────────────────────────────────────────────────
|
|
TWILIO_ACCOUNT_SID=
|
|
TWILIO_AUTH_TOKEN=
|
|
TWILIO_API_KEY=
|
|
TWILIO_API_SECRET=
|
|
TWILIO_TWIML_APP_SID=
|
|
TWILIO_FROM=+14382313838 # the Targo SMS number
|
|
|
|
# ─── Stripe ──────────────────────────────────────────────────────────────
|
|
STRIPE_SECRET_KEY= # sk_live_… or sk_test_…
|
|
STRIPE_WEBHOOK_SECRET= # whsec_… for /payments/webhook signature
|
|
|
|
# ─── Traccar (GPS) ───────────────────────────────────────────────────────
|
|
# Hub uses TRACCAR_TOKEN as Bearer; falls back to user/pass basic auth.
|
|
TRACCAR_URL=https://gps.targo.ca
|
|
TRACCAR_TOKEN=
|
|
TRACCAR_USER=
|
|
|
|
# ─── DocuSeal (e-signature) ──────────────────────────────────────────────
|
|
DOCUSEAL_URL=https://docs.gigafibre.ca
|
|
DOCUSEAL_API_KEY=
|
|
|
|
# ─── Fonoster (voice/PBX) ────────────────────────────────────────────────
|
|
FONOSTER_API_URL=https://fn.targo.ca
|
|
FONOSTER_EMAIL=
|
|
FONOSTER_PASSWORD=
|
|
FONOSTER_ALLOW_INSECURE=false
|
|
FNIDENTITY_DB_URL=postgres://... # internal Fonoster identity DB
|
|
ROUTR_DB_URL=postgres://... # internal Routr DB
|
|
|
|
# ─── 3CX PBX poller (legacy, usually disabled) ───────────────────────────
|
|
PBX_ENABLED=0
|
|
PBX_URL=
|
|
PBX_USER=
|
|
PBX_PASS=
|
|
PBX_POLL_INTERVAL=120
|
|
|
|
# ─── OLT SNMP poller ─────────────────────────────────────────────────────
|
|
# Comma-separated list of "name:ip:vendor" entries (vendor = tplink|raisecom)
|
|
OLT_LIST=
|
|
OLT_POLL_INTERVAL=300
|
|
|
|
# ─── AI / voice agent ────────────────────────────────────────────────────
|
|
# Anthropic / OpenAI / Groq — pick one. AI_API_KEY is read by lib/ai.js.
|
|
AI_API_KEY=
|
|
AI_MODEL=claude-sonnet-4-5
|
|
DEFAULT_MODEM_PASS= # default password for ONT remote admin
|
|
|
|
# ─── Oktopus (decommissioned) ────────────────────────────────────────────
|
|
# Set to 1 (default) to keep the integration disabled. Flip to 0 only
|
|
# if you re-deploy the Oktopus stack and want the hub to talk to it.
|
|
OKTOPUS_DISABLED=1
|
|
OKTOPUS_URL=
|
|
OKTOPUS_USER=
|
|
OKTOPUS_PASS=
|
|
|
|
# ─── Customer portal ─────────────────────────────────────────────────────
|
|
CLIENT_PORTAL_URL=https://targo.lovable.app
|
|
|
|
# ─── Cache redis (optional) ──────────────────────────────────────────────
|
|
CACHE_DB_URL=redis://localhost:6379
|