feat: add ACME account management with validation pipeline

- Register, view, and deactivate ACME accounts via API and UI
- 16-check validation framework for certificate issuance readiness
- DNS resolution, port, nginx, and firewall pre-flight checks
- External IP detection with NAT support and fallback providers
- Account card and settings modal in certificates page
- Guard certificate issuance behind account registration
- Update modal CSS to overlay-based approach
- 1000+ lines of tests for validation and account handlers
This commit is contained in:
2026-06-23 14:24:19 +00:00
parent 3a325504ec
commit 5025dfaf30
19 changed files with 2073 additions and 141 deletions
+68 -3
View File
@@ -905,19 +905,19 @@ Returns HTTP `404` if no certificate is found for the domain.
POST /api/certs/issue
```
Request a new certificate for a domain.
Request a new certificate for a domain. Returns HTTP `500` if issuance fails.
**Request Body:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `domain` | `string` | Yes | Domain to issue the certificate for |
| `email` | `string` | No | ACME contact email |
| `email` | `string` | No | ACME contact email **deprecated**, ignored in favor of the registered account email |
| `webroot` | `string` | No | Custom webroot path for HTTP-01 validation |
**Response:** `data` is `null` on success.
Returns HTTP `400` if the domain is missing. Returns HTTP `500` if issuance fails.
Returns HTTP `400` if the domain is missing. An ACME account must be registered before issuance (verified by the `account_registered` blocking check in the validation pipeline).
---
@@ -949,6 +949,71 @@ Returns HTTP `404` if the certificate is not found.
### Account
#### Get ACME Account Status
```
GET /api/certs/account
```
Return the ACME account registration status.
**Response (`data`):**
| Field | Type | Description |
|-------|------|-------------|
| `registered` | `boolean` | Whether an ACME account is registered |
| `email` | `string` | Registered contact email (empty if unregistered) |
| `ca` | `string` | CA provider (e.g., `"let's encrypt"`, `"ZeroSSL"`) (empty if unregistered) |
Returns HTTP `500` if the account status cannot be determined.
---
#### Register ACME Account
```
POST /api/certs/account/register
```
Register a new ACME account with the specified email and CA provider.
**Request Body:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `email` | `string` | Yes | Contact email address |
| `server` | `string` | No | CA provider: `"letsencrypt"` or `"zerossl"`. Default: `"letsencrypt"` |
**Response (`data`):**
| Field | Type | Description |
|-------|------|-------------|
| `registered` | `boolean` | Always `true` on success |
| `email` | `string` | Registered contact email |
| `ca` | `string` | CA provider |
Returns HTTP `400` if the email is missing or invalid. Returns HTTP `500` if registration fails. An ACME account must be registered before certificates can be issued.
---
#### Deactivate ACME Account
```
DELETE /api/certs/account
```
Deactivate the ACME account via `acme.sh --deactivate-account`. Clears the `email` and `ca` fields from `config/acme/config.json`.
**Response (`data`):**
| Field | Type | Description |
|-------|------|-------------|
| `email` | `string` | Empty string indicating the account was deactivated |
Returns HTTP `500` if deactivation fails.
---
#### Set ACME Contact Email
```