Refactor ACME module and add cert issuance conflict handling

- Move acme.sh utilities (_run_acme, _find_acme, etc.) from lib/state to lib/acme
- Rewrite _parse_list_output to support pipe, tab, and column-separated formats
- Add ConflictError (409) to block issuing when cert already exists
- Move _find_issuance helper to detect in-progress issuance per domain
- Update issue_cert to check existing certs and return issuance status
- Fix start_polling to accept event loop explicitly
- Add sudoers entry for chown on vacuum-wall.conf
- Extend systemd ReadWritePaths for /run/nginx.pid and /var/log/nginx
- Update frontend to handle 'existing' issuance status
This commit is contained in:
2026-06-27 00:38:49 +00:00
parent feaf253403
commit 398831b6e2
11 changed files with 268 additions and 176 deletions
+3 -1
View File
@@ -7,7 +7,7 @@ import logging
from flask import Blueprint, request
from daemon.client import BadRequest, NotFound, delete, get, post
from daemon.client import BadRequest, Conflict, NotFound, delete, get, post
from daemon.iface import (
DELETE_ACME_ACCOUNT_DEACTIVATE,
DELETE_ACME_REMOVE,
@@ -114,6 +114,8 @@ def issue_start():
except BadRequest as exc:
logger.info("Cert issue for '%s' rejected: %s", domain, exc)
return _error(str(exc), 400)
except Conflict as exc:
return _error(str(exc), 409)
except RuntimeError as exc:
logger.error("Failed to start cert issue for '%s': %s", domain, exc)
return _error(str(exc), 500)
+6 -1
View File
@@ -236,7 +236,12 @@ function _bindIssueButtons(inner, modalIdx) {
const body = { domain: _currentIssueState.domain };
const issueResp = await apiFetch('/api/certs/issue/start', { method: 'POST', body });
if (issueResp.ok) {
toast('Issuance started for ' + _currentIssueState.domain, 'success');
const status = issueResp.data?.status;
if (status === 'existing') {
toast('Issuance already in progress for ' + _currentIssueState.domain, 'warning');
} else {
toast('Issuance started for ' + _currentIssueState.domain, 'success');
}
closeModal(modalIdx);
const rid = issueResp.data?.request_id;
if (rid) pollCertIssue(rid);