Template
154 lines
4.1 KiB
Go
154 lines
4.1 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
"github.com/panelhosting/panel/internal/models"
|
|
"github.com/panelhosting/panel/internal/phpversions"
|
|
)
|
|
|
|
type SiteRepository struct {
|
|
pool *pgxpool.Pool
|
|
}
|
|
|
|
func NewSiteRepository(pool *pgxpool.Pool) *SiteRepository {
|
|
return &SiteRepository{pool: pool}
|
|
}
|
|
|
|
type SiteWithDomain struct {
|
|
models.Site
|
|
PrimaryDomain string `json:"primary_domain"`
|
|
}
|
|
|
|
func (r *SiteRepository) Create(ctx context.Context, serverID, ownerID int64, name, documentRoot, phpVersion, domain string) (*SiteWithDomain, error) {
|
|
tx, err := r.pool.Begin(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer tx.Rollback(ctx)
|
|
|
|
const siteQ = `
|
|
INSERT INTO sites (server_id, owner_id, name, document_root, php_version, status)
|
|
VALUES ($1, $2, $3, $4, $5, 'active')
|
|
RETURNING id, uuid, server_id, owner_id, name, document_root, php_version, status,
|
|
settings, disk_quota_mb, created_at, updated_at
|
|
`
|
|
var s models.Site
|
|
var phpVer *string
|
|
if phpVersion != "" {
|
|
phpVer = &phpVersion
|
|
}
|
|
err = tx.QueryRow(ctx, siteQ, serverID, ownerID, name, documentRoot, phpVer).Scan(
|
|
&s.ID, &s.UUID, &s.ServerID, &s.OwnerID, &s.Name, &s.DocumentRoot, &s.PHPVersion, &s.Status,
|
|
&s.Settings, &s.DiskQuotaMB, &s.CreatedAt, &s.UpdatedAt,
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("create site: %w", err)
|
|
}
|
|
|
|
const domainQ = `
|
|
INSERT INTO domains (site_id, domain, is_primary, ssl_enabled)
|
|
VALUES ($1, $2, true, true)
|
|
`
|
|
if _, err = tx.Exec(ctx, domainQ, s.ID, domain); err != nil {
|
|
return nil, fmt.Errorf("create domain: %w", err)
|
|
}
|
|
|
|
if err = tx.Commit(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &SiteWithDomain{Site: s, PrimaryDomain: domain}, nil
|
|
}
|
|
|
|
func (r *SiteRepository) ListForUser(ctx context.Context, userID int64, isAdmin bool) ([]SiteWithDomain, error) {
|
|
var q string
|
|
var args []any
|
|
if isAdmin {
|
|
q = siteListQuery + ` ORDER BY s.created_at DESC`
|
|
} else {
|
|
q = siteListQuery + ` WHERE s.owner_id = $1 ORDER BY s.created_at DESC`
|
|
args = append(args, userID)
|
|
}
|
|
|
|
rows, err := r.pool.Query(ctx, q, args...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("list sites: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
return scanSiteList(rows)
|
|
}
|
|
|
|
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, '')
|
|
FROM sites s
|
|
LEFT JOIN domains d ON d.site_id = s.id AND d.is_primary = true
|
|
`
|
|
|
|
func scanSiteList(rows pgx.Rows) ([]SiteWithDomain, error) {
|
|
var list []SiteWithDomain
|
|
for rows.Next() {
|
|
var item SiteWithDomain
|
|
err := rows.Scan(
|
|
&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,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
list = append(list, item)
|
|
}
|
|
return list, rows.Err()
|
|
}
|
|
|
|
type PHPVersionRepository struct {
|
|
pool *pgxpool.Pool
|
|
}
|
|
|
|
func NewPHPVersionRepository(pool *pgxpool.Pool) *PHPVersionRepository {
|
|
return &PHPVersionRepository{pool: pool}
|
|
}
|
|
|
|
func (r *PHPVersionRepository) ListActive(ctx context.Context) ([]string, error) {
|
|
rows, err := r.pool.Query(ctx, `
|
|
SELECT version FROM php_versions WHERE is_active = true ORDER BY sort_order
|
|
`)
|
|
if err != nil {
|
|
return phpversions.Defaults, nil
|
|
}
|
|
defer rows.Close()
|
|
|
|
var versions []string
|
|
for rows.Next() {
|
|
var v string
|
|
if err := rows.Scan(&v); err != nil {
|
|
return phpversions.Defaults, nil
|
|
}
|
|
versions = append(versions, v)
|
|
}
|
|
if err := rows.Err(); err != nil || len(versions) == 0 {
|
|
return phpversions.Defaults, nil
|
|
}
|
|
return versions, nil
|
|
}
|
|
|
|
func (r *PHPVersionRepository) IsActive(ctx context.Context, version string) (bool, error) {
|
|
var active bool
|
|
err := r.pool.QueryRow(ctx, `SELECT is_active FROM php_versions WHERE version = $1`, version).Scan(&active)
|
|
if err != nil {
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return phpversions.Contains(version), nil
|
|
}
|
|
return phpversions.Contains(version), nil
|
|
}
|
|
return active, nil
|
|
}
|