63 lines
2.8 KiB
Python
63 lines
2.8 KiB
Python
"""Exercise disposable CI containers through the host's trusted proxy address.
|
|
|
|
The forwarded HTTPS header simulates Nginx TLS termination; this is never run
|
|
against an existing hotel database. Cookie values and credentials are not logged.
|
|
"""
|
|
import json
|
|
import os
|
|
import sys
|
|
from http.cookies import SimpleCookie
|
|
from urllib.request import Request, urlopen
|
|
from urllib.error import HTTPError
|
|
|
|
cookies = SimpleCookie()
|
|
csrf = ""
|
|
|
|
|
|
def request(path, method="GET", data=None, expected=200):
|
|
headers = {"X-Forwarded-Proto": "https", "Content-Type": "application/json",
|
|
"Cookie": "; ".join(f"{k}={v.value}" for k, v in cookies.items()),
|
|
"X-CSRF-TOKEN": csrf}
|
|
req = Request("http://127.0.0.1:8080" + path, method=method, headers=headers,
|
|
data=json.dumps(data).encode() if data is not None else None)
|
|
try:
|
|
response = urlopen(req, timeout=15)
|
|
except HTTPError as error:
|
|
response = error
|
|
assert response.status == expected, f"{method} {path}: {response.status}, expected {expected}"
|
|
for value in response.headers.get_all("Set-Cookie", []):
|
|
parsed = SimpleCookie(value)
|
|
for cookie in parsed.values():
|
|
assert cookie["secure"] and cookie["httponly"], "Authentication cookies must be secure and HttpOnly"
|
|
cookies.load(value)
|
|
body = response.read().decode()
|
|
return json.loads(body) if "application/json" in response.headers.get("Content-Type", "") else body
|
|
|
|
|
|
assert "root" in request("/"), "Container must serve the built React interface"
|
|
request("/api/hotel", expected=401)
|
|
session = request("/api/session")
|
|
assert session["preview"] is False and session["user"] is None
|
|
csrf = session["csrfToken"]
|
|
request("/api/auth/login", "POST", {"email": os.environ["BOOTSTRAP_EMAIL"], "password": os.environ["BOOTSTRAP_PASSWORD"]})
|
|
session = request("/api/session")
|
|
assert session["user"]["role"] == "Owner"
|
|
csrf = session["csrfToken"]
|
|
auto_status = request("/api/auto-replies/status")
|
|
assert auto_status["liveConfigured"] is False
|
|
request("/api/auto-replies/mode", "PUT", {"mode": "Live", "version": 0, "acceptanceConfirmed": True}, expected=400)
|
|
payment_status = request("/api/payments/status")
|
|
assert payment_status["configured"] is False and payment_status["createsConfigured"] is False
|
|
assert "securityKey" not in payment_status
|
|
request("/api/payments/controls", "PUT", {"version": 0, "enabled": True}, expected=400)
|
|
assert request("/api/payments/requests") == []
|
|
hotel = request("/api/hotel")
|
|
if "--read" in sys.argv:
|
|
assert hotel["signature"] == "Persisted across container restart"
|
|
else:
|
|
hotel["signature"] = "Persisted across container restart"
|
|
request("/api/hotel", "PUT", hotel)
|
|
request("/api/auth/logout", "POST")
|
|
request("/api/hotel", expected=401)
|
|
print("Production smoke checks passed: built UI, secure cookies, owner login, MongoDB settings and logout.")
|