new changes

This commit is contained in:
Niranjan
2026-04-07 10:12:30 +05:30
parent 8965233e8c
commit 8a3e3ce04b
2 changed files with 69 additions and 0 deletions

View File

@@ -13,6 +13,75 @@ from app.core.utils import path_safe_check, write_file, read_file, exec_shell_sy
DOMAIN_REGEX = re.compile(r"^([\w\-\*]{1,100}\.){1,8}([\w\-]{1,24}|[\w\-]{1,24}\.[\w\-]{1,24})$")
LETSENCRYPT_LIVE = "/etc/letsencrypt/live"
SSL_EXPIRING_DAYS = 14
def _backup_count(site_name: str, backup_dir: str) -> int:
if not backup_dir or not os.path.isdir(backup_dir):
return 0
prefix = f"{site_name}_"
n = 0
try:
for f in os.listdir(backup_dir):
if f.startswith(prefix) and f.endswith(".tar.gz"):
n += 1
except OSError:
return 0
return n
def _parse_cert_not_after(cert_path: str) -> datetime | None:
if not os.path.isfile(cert_path):
return None
out, _err = exec_shell_sync(f'openssl x509 -in "{cert_path}" -noout -enddate', timeout=5)
if not out or "notAfter=" not in out:
return None
val = out.strip().split("=", 1)[1].strip()
try:
dt = datetime.strptime(val, "%b %d %H:%M:%S %Y GMT")
return dt.replace(tzinfo=timezone.utc)
except ValueError:
return None
def _best_ssl_for_hostnames(hostnames: list[str]) -> dict:
"""Match LE certs by live/<domain>/fullchain.pem; pick longest validity."""
none = {"status": "none", "days_left": None, "cert_name": None}
live_root = LETSENCRYPT_LIVE
try:
if not os.path.isdir(live_root):
return none
best_days: int | None = None
best_name: str | None = None
for host in hostnames:
h = (host or "").split(":")[0].strip().lower()
if not h:
continue
folder = os.path.join(live_root, h)
if not os.path.isdir(folder):
continue
fullchain = os.path.join(folder, "fullchain.pem")
end = _parse_cert_not_after(fullchain)
if end is None:
continue
now = datetime.now(timezone.utc)
days = int((end - now).total_seconds() // 86400)
if best_days is None or days > best_days:
best_days = days
best_name = h
if best_days is None:
return none
if best_days < 0:
status = "expired"
elif best_days <= SSL_EXPIRING_DAYS:
status = "expiring"
else:
status = "active"
return {"status": status, "days_left": best_days, "cert_name": best_name}
except OSError:
return none
def _render_vhost(
template: str,