Mark CNs with no issued cert file in the TUI and CLI lists
Renewing such a CN now works (it skips the revoke), but the list gave no hint that it was a special case until the workflow printed its warning. Flag it at selection time instead. _load_current_certs() sets CertInfo.has_cert_file, so every view built on it — the TUI list, --list and --list-all — gets the flag for free. The stat happens after the per-CN dedup, so a CN with several V-lines in index.txt is checked once. TUI rows render "(no cert file)" between the CN and the email, placed before the email so a long address truncating at the right edge cannot push the marker off screen. --list/--list-all grow a trailing CERT column holding MISSING; the column is omitted entirely when every CN has its .crt, since it is pure noise on a healthy PKI. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -133,6 +133,10 @@ class CertInfo:
|
||||
expires: datetime # UTC
|
||||
days_left: int # negative = already expired
|
||||
email: str = ""
|
||||
# False when index.txt lists the CN but <PKI_DIR>/issued/<CN>.crt is gone
|
||||
# — see has_issued_cert(). Such a CN can still be re-issued, but nothing
|
||||
# can be revoked for it, so the list marks it.
|
||||
has_cert_file: bool = True
|
||||
|
||||
|
||||
def _parse_date(raw: str) -> datetime:
|
||||
@@ -194,7 +198,11 @@ def _load_current_certs(pki_dir: str) -> List[CertInfo]:
|
||||
days_left=(expiry - now).days,
|
||||
email=email,
|
||||
)
|
||||
return list(by_cn.values())
|
||||
certs = list(by_cn.values())
|
||||
# After the dedup, so a CN with several V-lines is stat'ed once.
|
||||
for c in certs:
|
||||
c.has_cert_file = has_issued_cert(pki_dir, c.cn)
|
||||
return certs
|
||||
|
||||
|
||||
def load_expiring_certs(
|
||||
@@ -994,7 +1002,11 @@ def show_main_screen(
|
||||
cert = certs[i]
|
||||
box = "[X]" if cert.cn in checked else "[ ]"
|
||||
lbl = _expiry_label(cert)
|
||||
line = f" {box} {lbl:<18} {cert.cn:<20} {cert.email}"
|
||||
# Sits before the email so a long address truncating at the
|
||||
# right edge can't push the marker off screen, and kept
|
||||
# short so a typical address still fits at 80 columns.
|
||||
note = "" if cert.has_cert_file else "(no cert) "
|
||||
line = f" {box} {lbl:<18} {cert.cn:<20} {note}{cert.email}"
|
||||
try:
|
||||
stdscr.addstr(row_y, 0, line.ljust(sw - 1)[:sw - 1], sel_attr)
|
||||
except curses.error:
|
||||
@@ -1365,18 +1377,33 @@ class CursesApp:
|
||||
|
||||
|
||||
def _format_cert_table(certs: List[CertInfo]) -> str:
|
||||
"""Render CN / expiry / email as an aligned table, like `ls -l`."""
|
||||
"""Render CN / expiry / email as an aligned table, like `ls -l`.
|
||||
|
||||
A trailing CERT column appears only when at least one CN has lost its
|
||||
issued .crt — it is pure noise on a healthy PKI.
|
||||
"""
|
||||
if not certs:
|
||||
return "(no certificates)"
|
||||
rows = [
|
||||
(c.cn, _expiry_label(c).strip(), get_email(EASYRSA_PKI_DIR, c.cn) or "(none)")
|
||||
(c.cn, _expiry_label(c).strip(), get_email(EASYRSA_PKI_DIR, c.cn) or "(none)",
|
||||
"" if c.has_cert_file else "MISSING")
|
||||
for c in certs
|
||||
]
|
||||
show_cert_col = any(r[3] for r in rows)
|
||||
cn_w = max(len("CN"), max(len(r[0]) for r in rows))
|
||||
exp_w = max(len("EXPIRES"), max(len(r[1]) for r in rows))
|
||||
lines = [f"{'CN':<{cn_w}} {'EXPIRES':<{exp_w}} EMAIL"]
|
||||
for cn, exp, email in rows:
|
||||
lines.append(f"{cn:<{cn_w}} {exp:<{exp_w}} {email}")
|
||||
if not show_cert_col:
|
||||
lines = [f"{'CN':<{cn_w}} {'EXPIRES':<{exp_w}} EMAIL"]
|
||||
for cn, exp, email, _ in rows:
|
||||
lines.append(f"{cn:<{cn_w}} {exp:<{exp_w}} {email}")
|
||||
return "\n".join(lines)
|
||||
|
||||
mail_w = max(len("EMAIL"), max(len(r[2]) for r in rows))
|
||||
lines = [f"{'CN':<{cn_w}} {'EXPIRES':<{exp_w}} {'EMAIL':<{mail_w}} CERT"]
|
||||
for cn, exp, email, cert in rows:
|
||||
lines.append(
|
||||
f"{cn:<{cn_w}} {exp:<{exp_w}} {email:<{mail_w}} {cert}".rstrip()
|
||||
)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user