feat: Let's Encrypt SSL on site creation
This commit is contained in:
@@ -22,9 +22,13 @@ func NewSiteRepository(pool *pgxpool.Pool) *SiteRepository {
|
||||
type SiteWithDomain struct {
|
||||
models.Site
|
||||
PrimaryDomain string `json:"primary_domain"`
|
||||
DomainID int64 `json:"domain_id,omitempty"`
|
||||
SSLID int64 `json:"ssl_id,omitempty"`
|
||||
SSLStatus string `json:"ssl_status,omitempty"`
|
||||
SSLError string `json:"ssl_error,omitempty"`
|
||||
}
|
||||
|
||||
func (r *SiteRepository) Create(ctx context.Context, serverID, ownerID int64, name, documentRoot, phpVersion, domain string) (*SiteWithDomain, error) {
|
||||
func (r *SiteRepository) Create(ctx context.Context, serverID, ownerID int64, name, documentRoot, phpVersion, domain string, issueSSL bool) (*SiteWithDomain, error) {
|
||||
tx, err := r.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -52,17 +56,33 @@ func (r *SiteRepository) Create(ctx context.Context, serverID, ownerID int64, na
|
||||
|
||||
const domainQ = `
|
||||
INSERT INTO domains (site_id, domain, is_primary, ssl_enabled)
|
||||
VALUES ($1, $2, true, true)
|
||||
VALUES ($1, $2, true, $3)
|
||||
RETURNING id
|
||||
`
|
||||
if _, err = tx.Exec(ctx, domainQ, s.ID, domain); err != nil {
|
||||
var domainID int64
|
||||
if err = tx.QueryRow(ctx, domainQ, s.ID, domain, issueSSL).Scan(&domainID); err != nil {
|
||||
return nil, fmt.Errorf("create domain: %w", err)
|
||||
}
|
||||
|
||||
result := &SiteWithDomain{Site: s, PrimaryDomain: domain, DomainID: domainID}
|
||||
|
||||
if issueSSL {
|
||||
const sslQ = `
|
||||
INSERT INTO ssl_certificates (domain_id, type, status, auto_renew)
|
||||
VALUES ($1, 'letsencrypt', 'pending', true)
|
||||
RETURNING id
|
||||
`
|
||||
if err = tx.QueryRow(ctx, sslQ, domainID).Scan(&result.SSLID); err != nil {
|
||||
return nil, fmt.Errorf("create ssl cert: %w", err)
|
||||
}
|
||||
result.SSLStatus = "pending"
|
||||
}
|
||||
|
||||
if err = tx.Commit(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SiteWithDomain{Site: s, PrimaryDomain: domain}, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *SiteRepository) ListForUser(ctx context.Context, userID int64, isAdmin bool) ([]SiteWithDomain, error) {
|
||||
@@ -87,9 +107,16 @@ func (r *SiteRepository) ListForUser(ctx context.Context, userID int64, isAdmin
|
||||
const siteListQuery = `
|
||||
SELECT s.id, s.uuid, s.server_id, s.owner_id, s.name, s.document_root, s.php_version, s.status,
|
||||
s.settings, s.disk_quota_mb, s.created_at, s.updated_at,
|
||||
COALESCE(d.domain::text, '')
|
||||
COALESCE(d.domain::text, ''),
|
||||
COALESCE(d.id, 0),
|
||||
COALESCE(ssl.status::text, 'none'),
|
||||
COALESCE(ssl.error_message, '')
|
||||
FROM sites s
|
||||
LEFT JOIN domains d ON d.site_id = s.id AND d.is_primary = true
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT status, error_message FROM ssl_certificates
|
||||
WHERE domain_id = d.id ORDER BY id DESC LIMIT 1
|
||||
) ssl ON true
|
||||
`
|
||||
|
||||
func scanSiteList(rows pgx.Rows) ([]SiteWithDomain, error) {
|
||||
@@ -100,6 +127,7 @@ func scanSiteList(rows pgx.Rows) ([]SiteWithDomain, error) {
|
||||
&item.ID, &item.UUID, &item.ServerID, &item.OwnerID, &item.Name, &item.DocumentRoot,
|
||||
&item.PHPVersion, &item.Status, &item.Settings, &item.DiskQuotaMB,
|
||||
&item.CreatedAt, &item.UpdatedAt, &item.PrimaryDomain,
|
||||
&item.DomainID, &item.SSLStatus, &item.SSLError,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user