Files

129 lines
3.3 KiB
Go

package handler
import (
"encoding/json"
"errors"
"net/http"
"strconv"
"github.com/panelhosting/panel/internal/auth"
"github.com/panelhosting/panel/internal/middleware"
"github.com/panelhosting/panel/internal/sitesvc"
)
type SiteHandler struct {
svc *sitesvc.Service
}
func NewSiteHandler(svc *sitesvc.Service) *SiteHandler {
return &SiteHandler{svc: svc}
}
type createSiteRequest struct {
Name string `json:"name"`
Domain string `json:"domain"`
PHPVersion string `json:"php_version"`
SSLEmail string `json:"ssl_email"`
ServerID int64 `json:"server_id,omitempty"`
IssueSSL *bool `json:"issue_ssl"`
}
type reissueSSLRequest struct {
SSLEmail string `json:"ssl_email"`
}
func (h *SiteHandler) List(w http.ResponseWriter, r *http.Request) {
user, ok := middleware.UserFromContext(r.Context())
if !ok {
writeError(w, http.StatusUnauthorized, "unauthorized")
return
}
sites, err := h.svc.List(r.Context(), user, middleware.IsAdmin(user))
if err != nil {
writeError(w, http.StatusInternalServerError, "failed to list sites")
return
}
writeJSON(w, http.StatusOK, map[string]any{"sites": sites})
}
func (h *SiteHandler) Create(w http.ResponseWriter, r *http.Request) {
user, ok := middleware.UserFromContext(r.Context())
if !ok {
writeError(w, http.StatusUnauthorized, "unauthorized")
return
}
var req createSiteRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "invalid json")
return
}
issueSSL := true
if req.IssueSSL != nil {
issueSSL = *req.IssueSSL
}
site, err := h.svc.Create(r.Context(), sitesvc.CreateInput{
Name: req.Name,
Domain: req.Domain,
PHPVersion: req.PHPVersion,
SSLEmail: req.SSLEmail,
ServerID: req.ServerID,
OwnerID: user.ID,
IsAdmin: middleware.IsAdmin(user),
IssueSSL: issueSSL,
})
if err != nil {
switch {
case errors.Is(err, sitesvc.ErrInvalidSiteName),
errors.Is(err, sitesvc.ErrInvalidDomain),
errors.Is(err, sitesvc.ErrInvalidPHPVersion),
errors.Is(err, sitesvc.ErrInvalidSSLEmail),
errors.Is(err, sitesvc.ErrSSLEmailRequired):
writeError(w, http.StatusBadRequest, err.Error())
default:
writeError(w, http.StatusInternalServerError, "failed to create site: "+err.Error())
}
return
}
writeJSON(w, http.StatusCreated, map[string]any{"site": site})
}
func (h *SiteHandler) PHPVersions(w http.ResponseWriter, r *http.Request) {
versions, err := h.svc.ListPHPVersions(r.Context())
if err != nil {
writeError(w, http.StatusInternalServerError, "failed to list php versions")
return
}
writeJSON(w, http.StatusOK, map[string]any{"versions": versions})
}
func (h *SiteHandler) ReissueSSL(w http.ResponseWriter, r *http.Request) {
_, ok := middleware.UserFromContext(r.Context())
if !ok {
writeError(w, http.StatusUnauthorized, "unauthorized")
return
}
siteID, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
if err != nil {
writeError(w, http.StatusBadRequest, "invalid site id")
return
}
var req reissueSSLRequest
_ = json.NewDecoder(r.Body).Decode(&req)
if req.SSLEmail != "" {
if err := auth.ValidateEmail(req.SSLEmail); err != nil {
writeError(w, http.StatusBadRequest, "invalid ssl email")
return
}
}
h.svc.ReissueSSLAsync(siteID, req.SSLEmail)
writeJSON(w, http.StatusOK, map[string]string{"message": "ssl issuance started"})
}