Adds accounting-service PATCH/archive, fiscal helpers, COA templates and setup status, plus SuperApp Accounting UI (DS, scoreboard, masters, vouchers, ledger, ops modules) with session refresh and HTTPS public API URLs. Co-authored-by: Cursor <cursoragent@cursor.com>
112 lines
3.8 KiB
Python
112 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Deploy auto-SSL provisioner + nginx wildcard + enable Celery SSL env."""
|
|
from __future__ import annotations
|
|
|
|
import base64
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import paramiko
|
|
|
|
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
PASS = "Moli@5404"
|
|
REMOTE = "/home/morteza/torbatyar"
|
|
|
|
|
|
def connect(host: str, user: str):
|
|
c = paramiko.SSHClient()
|
|
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
c.connect(host, username=user, password=PASS, timeout=30, allow_agent=False, look_for_keys=False)
|
|
return c
|
|
|
|
|
|
def run(c, cmd: str, *, sudo: bool = False, timeout: int = 300) -> str:
|
|
if sudo:
|
|
b64 = base64.b64encode(cmd.encode()).decode()
|
|
full = f"echo {PASS!r} | sudo -S -p '' bash -c 'echo {b64} | base64 -d | bash'"
|
|
else:
|
|
full = cmd
|
|
_, o, e = c.exec_command(full, timeout=timeout, get_pty=True)
|
|
text = (o.read() + e.read()).decode("utf-8", "replace")
|
|
print(text[-8000:] if len(text) > 8000 else text)
|
|
return text
|
|
|
|
|
|
def put_b64(c, remote_path: str, content: str) -> None:
|
|
b64 = base64.b64encode(content.encode("utf-8")).decode("ascii")
|
|
run(c, f"mkdir -p $(dirname {remote_path}) && echo {b64} | base64 -d > {remote_path}")
|
|
|
|
|
|
def main() -> None:
|
|
ngx = connect("192.168.10.156", "torbatyaruser")
|
|
put_b64(ngx, "/tmp/torbatyar.ir.conf", (ROOT / "infrastructure/nginx/torbatyar.ir.conf").read_text(encoding="utf-8"))
|
|
put_b64(
|
|
ngx,
|
|
"/tmp/torbatyar-tenant-ssl.map",
|
|
(ROOT / "infrastructure/nginx/torbatyar-tenant-ssl.map").read_text(encoding="utf-8"),
|
|
)
|
|
put_b64(
|
|
ngx,
|
|
"/tmp/provision_ssl.py",
|
|
(ROOT / "infrastructure/nginx/provision_ssl.py").read_text(encoding="utf-8"),
|
|
)
|
|
run(
|
|
ngx,
|
|
"""
|
|
set -e
|
|
cp /tmp/torbatyar.ir.conf /etc/nginx/conf.d/torbatyar.ir.conf
|
|
cp /tmp/torbatyar-tenant-ssl.map /etc/nginx/conf.d/torbatyar-tenant-ssl.map
|
|
mkdir -p /opt/torbatyar/bin
|
|
cp /tmp/provision_ssl.py /opt/torbatyar/bin/provision_ssl.py
|
|
chmod 755 /opt/torbatyar/bin/provision_ssl.py
|
|
nginx -t
|
|
systemctl reload nginx
|
|
echo NGX_OK
|
|
python3 /opt/torbatyar/bin/provision_ssl.py torbatkaracademy.torbatyar.ir
|
|
""",
|
|
sudo=True,
|
|
timeout=360,
|
|
)
|
|
ngx.close()
|
|
|
|
app = connect("192.168.10.162", "morteza")
|
|
for rel in [
|
|
"backend/core-service/app/core/config.py",
|
|
"backend/core-service/app/services/ssl_provision.py",
|
|
"backend/core-service/app/services/onboarding_service.py",
|
|
"backend/core-service/app/services/domain_service.py",
|
|
"backend/core-service/app/workers/tasks.py",
|
|
"backend/core-service/requirements.txt",
|
|
"infrastructure/nginx/torbatyar.ir.conf",
|
|
"infrastructure/nginx/torbatyar-tenant-ssl.map",
|
|
"infrastructure/nginx/provision_ssl.py",
|
|
".env.example",
|
|
"infrastructure/deploy/.env.production.example",
|
|
".env",
|
|
]:
|
|
put_b64(app, f"{REMOTE}/{rel}", (ROOT / rel).read_text(encoding="utf-8"))
|
|
print("uploaded", rel)
|
|
|
|
run(
|
|
app,
|
|
f"""
|
|
set -e
|
|
cd {REMOTE}
|
|
docker compose exec -T celery-worker pip install -q 'paramiko==3.4.1' || true
|
|
docker compose up -d --force-recreate core-service celery-worker celery-beat
|
|
sleep 12
|
|
docker compose exec -T celery-worker pip install -q 'paramiko==3.4.1'
|
|
docker compose exec -T celery-worker python -c "from app.workers.tasks import provision_domain_ssl; r=provision_domain_ssl.delay('torbatkaracademy.torbatyar.ir'); print('task', r.id); print(r.get(timeout=180))"
|
|
curl -sS -m 10 http://127.0.0.1:8000/health || true
|
|
echo
|
|
echo DEPLOY_SSL_DONE
|
|
""",
|
|
timeout=420,
|
|
)
|
|
app.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|