fix bug: handle checking SSL validity before Apply to domain

This commit is contained in:
KaySar12 2024-11-25 14:59:40 +07:00
parent 941c4765f8
commit 9d36ce5c78
3 changed files with 131 additions and 6 deletions

View File

@ -317,7 +317,6 @@ func OnePanelUpdateWebsite(c *gin.Context) {
}
if search.Data.Items[0].Protocol != protocol && protocol == "http" {
//TODO disable HTTPS
if sslId > 0 {
var updateHttps, err = UpdateWebsiteHttps(false, acmeId, sslId, search.Data.Items[0].ID, headers)
if err != nil {
@ -428,6 +427,7 @@ func OnePanelCreateWebsite(c *gin.Context) {
}
if protocol == "https" {
//TODO Find SSL
var validSSL bool
var searchSSL model2.SearchSSLRequest
searchSSL.Page = 0
searchSSL.PageSize = 0
@ -459,6 +459,18 @@ func OnePanelCreateWebsite(c *gin.Context) {
})
return
}
if sslId > 0 {
validSSL, err = checkGlobalSSLStatus(sslId, headers, domain, 10)
if err != nil {
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.COMMAND_ERROR_INVALID_OPERATION,
Message: fmt.Sprintf("Fail to upgrade %s from http to https", domain),
Data: false,
})
return
}
}
} else {
sslId, err = IssueSelfSignedCert(domain, search.Data.Items[0].ID, headers, 3)
if err != nil {
@ -470,13 +482,23 @@ func OnePanelCreateWebsite(c *gin.Context) {
})
return
}
validSSL = true
}
}
if sslId < 0 || !validSSL {
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.COMMAND_ERROR_INVALID_OPERATION,
Message: fmt.Sprintf("Fail to Create SSL or domain %s is invalid to create global SSL", domain),
Data: false,
})
return
}
// TODO Enable HTTPS
var searchAcme model2.AcmeSearchRequest
acmeId := 0
searchAcme.Page = 0
searchAcme.PageSize = 0
searchAcme.Page = 1
searchAcme.PageSize = 1000
if sslProvider == "http" {
acme, err := service.MyService.OnePanel().AcmeAccountSearch(searchAcme, config.NextWebInfo.Server, headers)
if err != nil {
@ -531,6 +553,27 @@ func OnePanelCreateWebsite(c *gin.Context) {
Message: common_err.GetMsg(common_err.SUCCESS),
})
}
func checkGlobalSSLStatus(sslId int, headers map[string]string, domain string, retries int) (bool, error) {
if retries <= 0 {
return false, errors.New("timeout waiting for SSL certificate to become ready")
}
sslDetail, err := service.MyService.OnePanel().GetSSLDetail(sslId, config.NextWebInfo.Server, headers)
if err != nil {
return false, err
}
if sslDetail.Data.Status == "ready" {
return true, nil
}
if sslDetail.Data.Status == "applyError" {
return false, nil
}
time.Sleep(3 * time.Second)
return checkGlobalSSLStatus(sslId, headers, domain, retries-1)
}
func IssueSelfSignedCert(domain string, websiteId int, headers map[string]string, maxAttempts int) (int, error) {
if maxAttempts <= 0 {
return 0, errors.New("maximum attempts reached")
@ -593,8 +636,8 @@ func IssueSelfSignedCert(domain string, websiteId int, headers map[string]string
}
func OnePanelApplyWebsiteSSl(domain string, websiteId int, headers map[string]string) (int, error) {
var searchAcme model2.AcmeSearchRequest
searchAcme.Page = 0
searchAcme.PageSize = 0
searchAcme.Page = 1
searchAcme.PageSize = 10000
acme, err := service.MyService.OnePanel().AcmeAccountSearch(searchAcme, config.NextWebInfo.Server, headers)
if err != nil {
return 0, err

View File

@ -29,6 +29,7 @@ type OnePanelService interface {
SearchWebsiteSSl(m model2.SearchSSLRequest, baseUrl string, headers map[string]string) (model2.SearchSSLResponse, error)
UpdateWebsiteProtocol(m model2.WebsiteHttpsConfigRequest, baseUrl string, headers map[string]string) (model2.GenericResponse, error)
DeleteWebsiteSSL(m model2.DeleteSSLRequest, baseUrl string, headers map[string]string) (model2.GenericResponse, error)
GetSSLDetail(sslId int, baseUrl string, headers map[string]string) (model2.SSLDetail, error)
}
var (
@ -38,7 +39,32 @@ var (
type onePanelService struct {
}
// TODO A lot of redundant code need refactor
func (o *onePanelService) GetSSLDetail(sslId int, baseUrl string, headers map[string]string) (model2.SSLDetail, error) {
path := baseUrl + fmt.Sprintf("/api/v1/websites/ssl/%d", sslId)
req, err := http.NewRequest("GET", path, nil)
if err != nil {
return model2.SSLDetail{}, fmt.Errorf("error creating request: %v", err)
}
// Add headers to the request
for key, value := range headers {
req.Header.Set(key, value)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return model2.SSLDetail{}, fmt.Errorf("error making request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return model2.SSLDetail{}, fmt.Errorf("HTTP error: %s", resp.Status)
}
var result model2.SSLDetail
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return model2.SSLDetail{}, fmt.Errorf("error decoding response: %v", err)
}
return result, nil
}
func (o *onePanelService) DeleteWebsiteSSL(m model2.DeleteSSLRequest, baseUrl string, headers map[string]string) (model2.GenericResponse, error) {
path := baseUrl + "/api/v1/websites/ssl/del"
reqBody, err := json.Marshal(m)

View File

@ -282,3 +282,59 @@ type DNSAccount struct {
Name string `json:"name"`
Type string `json:"type"`
}
type SSLDetail struct {
Code int `json:"code"`
Message string `json:"message"`
Data struct {
ID int `json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
PrimaryDomain string `json:"primaryDomain"`
PrivateKey string `json:"privateKey"`
Pem string `json:"pem"`
Domains string `json:"domains"`
CertURL string `json:"certURL"`
Type string `json:"type"`
Provider string `json:"provider"`
Organization string `json:"organization"`
DNSAccountID int `json:"dnsAccountId"`
AcmeAccountID int `json:"acmeAccountId"`
CaID int `json:"caId"`
AutoRenew bool `json:"autoRenew"`
ExpireDate time.Time `json:"expireDate"`
StartDate time.Time `json:"startDate"`
Status string `json:"status"`
Message string `json:"message"`
KeyType string `json:"keyType"`
PushDir bool `json:"pushDir"`
Dir string `json:"dir"`
Description string `json:"description"`
SkipDNS bool `json:"skipDNS"`
Nameserver1 string `json:"nameserver1"`
Nameserver2 string `json:"nameserver2"`
DisableCNAME bool `json:"disableCNAME"`
ExecShell bool `json:"execShell"`
Shell string `json:"shell"`
AcmeAccount struct {
ID int `json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Email string `json:"email"`
URL string `json:"url"`
Type string `json:"type"`
EabKid string `json:"eabKid"`
EabHmacKey string `json:"eabHmacKey"`
KeyType string `json:"keyType"`
} `json:"acmeAccount"`
DNSAccount struct {
ID int `json:"id"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Name string `json:"name"`
Type string `json:"type"`
} `json:"dnsAccount"`
Websites interface{} `json:"websites"`
LogPath string `json:"logPath"`
} `json:"data"`
}