mirror of
https://git.meshkee.com/Meshkee/backend.git
synced 2026-08-11 22:30:59 +04:30
Brand OTP SMS with business name and support local SMS proxy.
Append tenant Farsi name to verification SMS, allow optional domain on send-otp, and add SMS_PROXY_* for local delivery via production. Also include websites SSL sync agent/API wiring. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
77f3cb2a67
commit
8f05ee2b58
@@ -3,6 +3,7 @@
|
||||
# Endpoints (X-Deploy-Token):
|
||||
# POST /deploy { slug } — git pull + build + pm2 restart
|
||||
# POST /provision { slug, host, gitRepoUrl } — clone + nginx + ecosystem + allowlist
|
||||
# POST /ssl { host, slug? } — certbot for apex + www (nginx must exist)
|
||||
# GET /health
|
||||
#
|
||||
# Env (.env): PORT, DEPLOY_TOKEN, ALLOWED_SLUGS
|
||||
|
||||
@@ -176,6 +176,42 @@ const server = http.createServer(async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (req.method === 'POST' && req.url === '/ssl') {
|
||||
if (!assertAuth(req, res)) return;
|
||||
|
||||
let body;
|
||||
try {
|
||||
body = await readJson(req);
|
||||
} catch {
|
||||
return send(res, 400, { error: 'invalid json' });
|
||||
}
|
||||
|
||||
const host = String(body.host || '').trim().toLowerCase();
|
||||
const slug = String(body.slug || '').trim();
|
||||
|
||||
if (!host || !/^[a-z0-9.-]+$/.test(host)) {
|
||||
return send(res, 400, { error: 'valid host is required' });
|
||||
}
|
||||
|
||||
if (slug && !allowedSlugs().has(slug)) {
|
||||
return send(res, 400, { error: 'unknown or disallowed slug' });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await runScript('/opt/websites-agent/ssl.sh', [host]);
|
||||
return send(res, 200, {
|
||||
status: 'issued',
|
||||
host,
|
||||
log: (result.stdout || '').slice(-2000),
|
||||
});
|
||||
} catch (err) {
|
||||
return send(res, 500, {
|
||||
error: 'ssl issue failed',
|
||||
detail: err instanceof Error ? err.message.slice(0, 2000) : String(err),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return send(res, 404, { error: 'not found' });
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
# Issue / renew Let's Encrypt cert for a storefront apex (+ www) via nginx plugin.
|
||||
set -euo pipefail
|
||||
|
||||
HOST="${1:-}"
|
||||
|
||||
if [[ -z "$HOST" ]]; then
|
||||
echo "usage: ssl.sh <host>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! "$HOST" =~ ^[a-z0-9.-]+$ ]]; then
|
||||
echo "invalid host: $HOST" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NGINX_AVAILABLE="/etc/nginx/sites-available/$HOST"
|
||||
NGINX_ENABLED="/etc/nginx/sites-enabled/$HOST"
|
||||
LOG_DIR="/var/log/websites"
|
||||
mkdir -p "$LOG_DIR"
|
||||
LOG="$LOG_DIR/ssl-$HOST.log"
|
||||
exec >>"$LOG" 2>&1
|
||||
|
||||
echo "==== $(date -u +%Y-%m-%dT%H:%M:%SZ) ssl start: $HOST ===="
|
||||
|
||||
if [[ ! -f "$NGINX_AVAILABLE" && ! -f "$NGINX_ENABLED" ]]; then
|
||||
echo "missing nginx site for $HOST (run provision first)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v certbot >/dev/null 2>&1; then
|
||||
echo "certbot not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
certbot --nginx -d "$HOST" -d "www.$HOST" \
|
||||
--non-interactive --agree-tos --register-unsafely-without-email --redirect
|
||||
|
||||
echo "==== $(date -u +%Y-%m-%dT%H:%M:%SZ) ssl ok: $HOST ===="
|
||||
Reference in New Issue
Block a user