#!/bin/bash set -eu cd /root/aza-app/deploy docker compose build --no-cache aza-api docker compose up -d --force-recreate aza-api sleep 8 docker compose ps aza-api docker logs --tail 300 aza-api 2>&1 | tail -80 curl -s -o /dev/null -w 'HEALTH_HTTP=%{http_code}\n' https://api.aza-medwork.ch/health curl -s -o /dev/null -w 'EMPFANG_HTTP=%{http_code}\n' https://empfang.aza-medwork.ch/empfang/ curl -s https://api.aza-medwork.ch/openapi.json | tr ',' '\n' | grep -F '/empfang/shell/nav-open' | head -1 || true curl -s https://api.aza-medwork.ch/openapi.json | tr ',' '\n' | grep -F '/empfang/shell/context/me' | head -1 || true echo '--- smoke unauth ---' curl -s -o /dev/null -w 'nav_open_noauth=%{http_code}\n' -X POST https://api.aza-medwork.ch/empfang/shell/nav-open -H 'Content-Type: application/json' -d '{"nav_open_kind":"task"}' curl -s -o /dev/null -w 'context_me_noauth=%{http_code}\n' https://api.aza-medwork.ch/empfang/shell/context/me curl -s -o /dev/null -w 'nav_open_invalid_noauth=%{http_code}\n' -X POST https://api.aza-medwork.ch/empfang/shell/nav-open -H 'Content-Type: application/json' -d '{"nav_open_kind":"evil"}' python3 <<'PY' import json, urllib.request, http.cookiejar BASE = 'https://api.aza-medwork.ch/empfang' jar = http.cookiejar.CookieJar() opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar)) def req(method, path, data=None, headers=None): url = BASE + path body = None h = {'Content-Type': 'application/json'} if headers: h.update(headers) if data is not None: body = json.dumps(data).encode('utf-8') r = urllib.request.Request(url, data=body, headers=h, method=method) try: with opener.open(r, timeout=20) as resp: return resp.status, resp.read().decode('utf-8', errors='replace')[:500] except urllib.error.HTTPError as e: return e.code, e.read().decode('utf-8', errors='replace')[:500] # unauthenticated invalid kind should be 401 before validation in some stacks; report code only code, _ = req('POST', '/shell/nav-open', {'nav_open_kind': 'evil'}) print('nav_open_invalid_unauth=%s' % code) # Try login from local server env if available (no output of secrets) import os login = os.environ.get('AZA_SMOKE_LOGIN', '').strip() password = os.environ.get('AZA_SMOKE_PASSWORD', '').strip() if not login or not password: env_path = '/root/aza-app/deploy/.env' if os.path.isfile(env_path): for line in open(env_path, encoding='utf-8', errors='ignore'): line = line.strip() if line.startswith('AZA_SMOKE_LOGIN='): login = line.split('=', 1)[1].strip().strip('"').strip("'") elif line.startswith('AZA_SMOKE_PASSWORD='): password = line.split('=', 1)[1].strip().strip('"').strip("'") if login and password: code, body = req('POST', '/auth/login', {'login_name': login, 'password': password}) print('auth_login=%s' % code) if code == 200: for kind in ('task', 'letter'): code2, _ = req('POST', '/shell/nav-open', {'nav_open_kind': kind, 'nav_open_assignee': 'Smoke Test'}) print('nav_open_%s_auth=%s' % (kind, code2)) code3, body3 = req('GET', '/shell/context/me') print('context_me_auth=%s' % code3) try: j = json.loads(body3) k1 = bool(str(j.get('nav_open_kind') or '').strip()) print('context_has_nav_kind=%s' % k1) except Exception: print('context_has_nav_kind=parse_fail') code4, body4 = req('GET', '/shell/context/me') print('context_me_second=%s' % code4) try: j2 = json.loads(body4) k2 = bool(str(j2.get('nav_open_kind') or '').strip()) print('context_nav_consumed=%s' % (not k2)) except Exception: print('context_nav_consumed=parse_fail') code5, _ = req('POST', '/shell/nav-open', {'nav_open_kind': 'evil'}) print('nav_open_invalid_auth=%s' % code5) else: print('auth_smoke=skipped_no_credentials') PY echo '--- logs filter ---' docker logs --tail 400 aza-api 2>&1 | egrep -i 'traceback|error|exception|nav-open|shell/context|ImportError|sqlite' | tail -30 || true