feat: print session log to stdout after TUI exits

CNs, passwords, URLs, and paths are collected during the session and
printed to the terminal once curses closes — including on crashes,
since _print_session_log runs in a finally block.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vlad Doloman
2026-06-24 18:31:44 +03:00
parent 9f339e9254
commit c610aed01d

View File

@@ -901,8 +901,26 @@ def show_main_screen(
class CursesApp:
def __init__(self) -> None:
self._session_log: list[str] = []
def _log(self, entry: str) -> None:
self._session_log.append(entry)
def _print_session_log(self) -> None:
if not self._session_log:
return
bar = "" * 64
print(f"\n{bar}")
for entry in self._session_log:
print(entry)
print(bar)
def run(self) -> None:
try:
curses.wrapper(self._main)
finally:
self._print_session_log()
def _main(self, stdscr) -> None:
curses.curs_set(0)
@@ -1020,11 +1038,25 @@ class CursesApp:
self._msg(stdscr,
f"Email sent to {form.email}\nConfig: {ovpn_path}",
wait=True)
self._log(
f"Certificate issued for: {final_cn}\n"
f" Config : {ovpn_path}\n"
f" URL : {one_time_url}\n"
f" Password : {form.password}\n"
f" Email sent to: {form.email}"
)
except RuntimeError as exc:
self._error(stdscr,
f"Email failed:\n{exc}\n\n"
f"URL : {one_time_url}\n"
f"Config: {ovpn_path}")
self._log(
f"Certificate issued for: {final_cn}\n"
f" Config : {ovpn_path}\n"
f" URL : {one_time_url}\n"
f" Password : {form.password}\n"
f" Email FAILED to: {form.email}"
)
else:
self._show_result(stdscr, final_cn, ovpn_path, form.password, one_time_url)
@@ -1039,6 +1071,7 @@ class CursesApp:
except EasyRSAError as exc:
self._error(stdscr, f"Revoke failed:\n{exc}")
return
self._log(f"{cn} revoked, CRL updated → {CRL_DEST_PATH}")
self._msg(stdscr, f"{cn} revoked and CRL updated → {CRL_DEST_PATH}", wait=True)
def _regen_crl(self, stdscr) -> None:
@@ -1049,6 +1082,7 @@ class CursesApp:
except EasyRSAError as exc:
self._error(stdscr, f"gen-crl failed:\n{exc}")
return
self._log(f"CRL regenerated → {CRL_DEST_PATH}")
self._msg(stdscr, f"CRL regenerated → {CRL_DEST_PATH}", wait=True)
# ── Display helpers ───────────────────────────────────────────────────────
@@ -1095,6 +1129,12 @@ class CursesApp:
def _show_result(
self, stdscr, cn: str, ovpn_path: str, password: str, one_time_url: str,
) -> None:
self._log(
f"Certificate issued for: {cn}\n"
f" Config : {ovpn_path}\n"
f" URL : {one_time_url}\n"
f" Password : {password}"
)
self._msg(
stdscr,
f"Certificate issued for: {cn}\n"