feat: SSL wildcard certificate picker from NPM

- NPM client: ListCertificates endpoint
- API: GET /api/settings/npm-certificates (wildcard-only filter)
- Settings UI: EntityPicker for selecting wildcard certs
- Deployer: applies certificate_id + ssl_forced to proxy hosts
- Uses HTTPS subdomain URLs when SSL cert is configured
This commit is contained in:
2026-03-29 13:07:58 +03:00
parent e94c4f9116
commit 9f284932a1
13 changed files with 253 additions and 21 deletions
+9
View File
@@ -154,6 +154,15 @@ func (c *Client) FindProxyHostByDomain(ctx context.Context, domain string) (Prox
return ProxyHost{}, false, nil
}
// ListCertificates returns all SSL certificates from NPM.
func (c *Client) ListCertificates(ctx context.Context) ([]Certificate, error) {
var certs []Certificate
if err := c.doJSON(ctx, http.MethodGet, "/nginx/certificates", nil, &certs); err != nil {
return nil, fmt.Errorf("list certificates: %w", err)
}
return certs, nil
}
// doJSON performs an authenticated JSON API request. If the token is expired or a 401
// is received, it automatically re-authenticates and retries the request once.
func (c *Client) doJSON(ctx context.Context, method, path string, reqBody any, result any) error {
+9
View File
@@ -50,6 +50,15 @@ type ProxyHost struct {
ModifiedOn string `json:"modified_on"`
}
// Certificate represents an SSL certificate as returned by the NPM API.
type Certificate struct {
ID int `json:"id"`
NiceName string `json:"nice_name"`
DomainNames []string `json:"domain_names"`
ExpiresOn string `json:"expires_on"`
Provider string `json:"provider"`
}
// boolInt handles the NPM API's inconsistent use of 0/1 integers for boolean fields.
type boolInt bool