2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 12:40:25 +08:00

feat(证书管理): 补全更新和显示接口

This commit is contained in:
耗子
2023-11-07 02:05:50 +08:00
parent c6263ebe73
commit 70601dfb00
21 changed files with 1920 additions and 246 deletions

View File

@@ -3,8 +3,8 @@ package controllers
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/facades"
requests "panel/app/http/requests/cert"
requests "panel/app/http/requests/cert"
commonrequests "panel/app/http/requests/common"
responses "panel/app/http/responses/cert"
"panel/app/models"
@@ -147,26 +147,26 @@ func (r *CertController) UserList(ctx http.Context) http.Response {
})
}
// UserAdd
// UserStore
// @Summary 添加 ACME 用户
// @Description 添加 ACME 用户到面板证书管理
// @Tags 证书
// @Accept json
// @Produce json
// @Security BearerToken
// @Param data body requests.UserAdd true "用户信息"
// @Param data body requests.UserStore true "用户信息"
// @Success 200 {object} SuccessResponse
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/users [post]
func (r *CertController) UserAdd(ctx http.Context) http.Response {
var addRequest requests.UserAdd
sanitize := Sanitize(ctx, &addRequest)
func (r *CertController) UserStore(ctx http.Context) http.Response {
var storeRequest requests.UserStore
sanitize := Sanitize(ctx, &storeRequest)
if sanitize != nil {
return sanitize
}
err := r.cert.UserAdd(addRequest)
err := r.cert.UserStore(storeRequest)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"error": err.Error(),
@@ -177,7 +177,69 @@ func (r *CertController) UserAdd(ctx http.Context) http.Response {
return Success(ctx, nil)
}
// UserDelete
// UserUpdate
// @Summary 更新 ACME 用户
// @Description 更新面板证书管理的 ACME 用户
// @Tags 证书
// @Accept json
// @Produce json
// @Security BearerToken
// @Param id path int true "用户 ID"
// @Param data body requests.UserUpdate true "用户信息"
// @Success 200 {object} SuccessResponse
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/users/{id} [put]
func (r *CertController) UserUpdate(ctx http.Context) http.Response {
var updateRequest requests.UserUpdate
sanitize := Sanitize(ctx, &updateRequest)
if sanitize != nil {
return sanitize
}
err := r.cert.UserUpdate(updateRequest)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"userID": updateRequest.ID,
"error": err.Error(),
}).Error("更新ACME用户失败")
return ErrorSystem(ctx)
}
return Success(ctx, nil)
}
// UserShow
// @Summary 获取 ACME 用户
// @Description 获取面板证书管理的 ACME 用户
// @Tags 证书
// @Produce json
// @Security BearerToken
// @Param id path int true "用户 ID"
// @Success 200 {object} SuccessResponse{data=models.CertUser}
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/users/{id} [get]
func (r *CertController) UserShow(ctx http.Context) http.Response {
var showAndDestroyRequest requests.UserShowAndDestroy
sanitize := Sanitize(ctx, &showAndDestroyRequest)
if sanitize != nil {
return sanitize
}
user, err := r.cert.UserShow(showAndDestroyRequest.ID)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"userID": showAndDestroyRequest.ID,
"error": err.Error(),
}).Error("获取ACME用户失败")
return ErrorSystem(ctx)
}
return Success(ctx, user)
}
// UserDestroy
// @Summary 删除 ACME 用户
// @Description 删除面板证书管理的 ACME 用户
// @Tags 证书
@@ -189,13 +251,17 @@ func (r *CertController) UserAdd(ctx http.Context) http.Response {
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/users/{id} [delete]
func (r *CertController) UserDelete(ctx http.Context) http.Response {
userID := ctx.Request().InputInt("id")
func (r *CertController) UserDestroy(ctx http.Context) http.Response {
var showAndDestroyRequest requests.UserShowAndDestroy
sanitize := Sanitize(ctx, &showAndDestroyRequest)
if sanitize != nil {
return sanitize
}
err := r.cert.UserDelete(uint(userID))
err := r.cert.UserDestroy(showAndDestroyRequest.ID)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"userID": userID,
"userID": showAndDestroyRequest.ID,
"error": err.Error(),
}).Error("删除ACME用户失败")
return ErrorSystem(ctx)
@@ -237,26 +303,26 @@ func (r *CertController) DNSList(ctx http.Context) http.Response {
})
}
// DNSAdd
// DNSStore
// @Summary 添加 DNS 接口
// @Description 添加 DNS 接口到面板证书管理
// @Tags 证书
// @Accept json
// @Produce json
// @Security BearerToken
// @Param data body requests.DNSAdd true "DNS 接口信息"
// @Param data body requests.DNSStore true "DNS 接口信息"
// @Success 200 {object} SuccessResponse
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/dns [post]
func (r *CertController) DNSAdd(ctx http.Context) http.Response {
var addRequest requests.DNSAdd
sanitize := Sanitize(ctx, &addRequest)
func (r *CertController) DNSStore(ctx http.Context) http.Response {
var storeRequest requests.DNSStore
sanitize := Sanitize(ctx, &storeRequest)
if sanitize != nil {
return sanitize
}
err := r.cert.DNSAdd(addRequest)
err := r.cert.DNSStore(storeRequest)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"error": err.Error(),
@@ -267,7 +333,69 @@ func (r *CertController) DNSAdd(ctx http.Context) http.Response {
return Success(ctx, nil)
}
// DNSDelete
// DNSShow
// @Summary 获取 DNS 接口
// @Description 获取面板证书管理的 DNS 接口
// @Tags 证书
// @Produce json
// @Security BearerToken
// @Param id path int true "DNS 接口 ID"
// @Success 200 {object} SuccessResponse{data=models.CertDNS}
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/dns/{id} [get]
func (r *CertController) DNSShow(ctx http.Context) http.Response {
var showAndDestroyRequest requests.DNSShowAndDestroy
sanitize := Sanitize(ctx, &showAndDestroyRequest)
if sanitize != nil {
return sanitize
}
dns, err := r.cert.DNSShow(showAndDestroyRequest.ID)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"dnsID": showAndDestroyRequest.ID,
"error": err.Error(),
}).Error("获取DNS接口失败")
return ErrorSystem(ctx)
}
return Success(ctx, dns)
}
// DNSUpdate
// @Summary 更新 DNS 接口
// @Description 更新面板证书管理的 DNS 接口
// @Tags 证书
// @Accept json
// @Produce json
// @Security BearerToken
// @Param id path int true "DNS 接口 ID"
// @Param data body requests.DNSUpdate true "DNS 接口信息"
// @Success 200 {object} SuccessResponse
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/dns/{id} [put]
func (r *CertController) DNSUpdate(ctx http.Context) http.Response {
var updateRequest requests.DNSUpdate
sanitize := Sanitize(ctx, &updateRequest)
if sanitize != nil {
return sanitize
}
err := r.cert.DNSUpdate(updateRequest)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"dnsID": updateRequest.ID,
"error": err.Error(),
}).Error("更新DNS接口失败")
return ErrorSystem(ctx)
}
return Success(ctx, nil)
}
// DNSDestroy
// @Summary 删除 DNS 接口
// @Description 删除面板证书管理的 DNS 接口
// @Tags 证书
@@ -279,13 +407,17 @@ func (r *CertController) DNSAdd(ctx http.Context) http.Response {
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/dns/{id} [delete]
func (r *CertController) DNSDelete(ctx http.Context) http.Response {
dnsID := ctx.Request().InputInt("id")
func (r *CertController) DNSDestroy(ctx http.Context) http.Response {
var showAndDestroyRequest requests.DNSShowAndDestroy
sanitize := Sanitize(ctx, &showAndDestroyRequest)
if sanitize != nil {
return sanitize
}
err := r.cert.DNSDelete(uint(dnsID))
err := r.cert.DNSDestroy(showAndDestroyRequest.ID)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"dnsID": dnsID,
"dnsID": showAndDestroyRequest.ID,
"error": err.Error(),
}).Error("删除DNS接口失败")
return ErrorSystem(ctx)
@@ -327,26 +459,26 @@ func (r *CertController) CertList(ctx http.Context) http.Response {
})
}
// CertAdd
// CertStore
// @Summary 添加证书
// @Description 添加证书到面板证书管理
// @Tags 证书
// @Accept json
// @Produce json
// @Security BearerToken
// @Param data body requests.CertAdd true "证书信息"
// @Param data body requests.CertStore true "证书信息"
// @Success 200 {object} SuccessResponse
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/certs [post]
func (r *CertController) CertAdd(ctx http.Context) http.Response {
var addRequest requests.CertAdd
sanitize := Sanitize(ctx, &addRequest)
func (r *CertController) CertStore(ctx http.Context) http.Response {
var storeRequest requests.CertStore
sanitize := Sanitize(ctx, &storeRequest)
if sanitize != nil {
return sanitize
}
err := r.cert.CertAdd(addRequest)
err := r.cert.CertStore(storeRequest)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"error": err.Error(),
@@ -357,7 +489,69 @@ func (r *CertController) CertAdd(ctx http.Context) http.Response {
return Success(ctx, nil)
}
// CertDelete
// CertUpdate
// @Summary 更新证书
// @Description 更新面板证书管理的证书
// @Tags 证书
// @Accept json
// @Produce json
// @Security BearerToken
// @Param id path int true "证书 ID"
// @Param data body requests.CertUpdate true "证书信息"
// @Success 200 {object} SuccessResponse
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/certs/{id} [put]
func (r *CertController) CertUpdate(ctx http.Context) http.Response {
var updateRequest requests.CertUpdate
sanitize := Sanitize(ctx, &updateRequest)
if sanitize != nil {
return sanitize
}
err := r.cert.CertUpdate(updateRequest)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"certID": updateRequest.ID,
"error": err.Error(),
}).Error("更新证书失败")
return ErrorSystem(ctx)
}
return Success(ctx, nil)
}
// CertShow
// @Summary 获取证书
// @Description 获取面板证书管理的证书
// @Tags 证书
// @Produce json
// @Security BearerToken
// @Param id path int true "证书 ID"
// @Success 200 {object} SuccessResponse{data=models.Cert}
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/certs/{id} [get]
func (r *CertController) CertShow(ctx http.Context) http.Response {
var showAndDestroyRequest requests.CertShowAndDestroy
sanitize := Sanitize(ctx, &showAndDestroyRequest)
if sanitize != nil {
return sanitize
}
cert, err := r.cert.CertShow(showAndDestroyRequest.ID)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"certID": showAndDestroyRequest.ID,
"error": err.Error(),
}).Error("获取证书失败")
return ErrorSystem(ctx)
}
return Success(ctx, cert)
}
// CertDestroy
// @Summary 删除证书
// @Description 删除面板证书管理的证书
// @Tags 证书
@@ -369,13 +563,17 @@ func (r *CertController) CertAdd(ctx http.Context) http.Response {
// @Failure 401 {object} ErrorResponse "登录已过期"
// @Failure 500 {object} ErrorResponse "系统内部错误"
// @Router /panel/cert/certs/{id} [delete]
func (r *CertController) CertDelete(ctx http.Context) http.Response {
certID := ctx.Request().InputInt("id")
func (r *CertController) CertDestroy(ctx http.Context) http.Response {
var showAndDestroyRequest requests.CertShowAndDestroy
sanitize := Sanitize(ctx, &showAndDestroyRequest)
if sanitize != nil {
return sanitize
}
err := r.cert.CertDelete(uint(certID))
err := r.cert.CertDestroy(showAndDestroyRequest.ID)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"certID": certID,
"certID": showAndDestroyRequest.ID,
"error": err.Error(),
}).Error("删除证书失败")
return ErrorSystem(ctx)
@@ -403,7 +601,7 @@ func (r *CertController) Obtain(ctx http.Context) http.Response {
return sanitize
}
cert, err := r.cert.GetByID(obtainRequest.ID)
cert, err := r.cert.CertShow(obtainRequest.ID)
if err != nil {
facades.Log().Request(ctx.Request()).Tags("面板", "证书管理").With(map[string]any{
"certID": obtainRequest.ID,

View File

@@ -1,49 +0,0 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type CertAdd struct {
Type string `form:"type" json:"type"`
Domains []string `form:"domains" json:"domains"`
AutoRenew bool `form:"auto_renew" json:"auto_renew"`
UserID uint `form:"user_id" json:"user_id"`
DNSID *uint `form:"dns_id" json:"dns_id"`
WebsiteID *uint `form:"website_id" json:"website_id"`
}
func (r *CertAdd) Authorize(ctx http.Context) error {
return nil
}
func (r *CertAdd) Rules(ctx http.Context) map[string]string {
return map[string]string{
"type": "required|in:P256,P384,2048,4096",
"domains": "required|array",
"auto_renew": "required|bool",
"user_id": "required|exists:cert_users,id",
}
}
func (r *CertAdd) Messages(ctx http.Context) map[string]string {
return map[string]string{
"type.required": "类型不能为空",
"type.in": "类型必须为 P256, P384, 2048, 4096 中的一个",
"domains.required": "域名不能为空",
"domains.array": "域名必须为数组",
"auto_renew.required": "自动续签不能为空",
"auto_renew.bool": "自动续签必须为布尔值",
"user_id.required": "ACME 用户 ID 不能为空",
"user_id.exists": "ACME 用户 ID 不存在",
}
}
func (r *CertAdd) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *CertAdd) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,34 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type CertDeploy struct {
ID uint `form:"id" json:"id"`
WebsiteID uint `form:"website_id" json:"website_id"`
}
func (r *CertDeploy) Authorize(ctx http.Context) error {
return nil
}
func (r *CertDeploy) Rules(ctx http.Context) map[string]string {
return map[string]string{
"id": "required|uint|min:1|exists:certs,id",
"website_id": "required|uint|min:1|exists:websites,id",
}
}
func (r *CertDeploy) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *CertDeploy) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *CertDeploy) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,32 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type CertShowAndDestroy struct {
ID uint `form:"id" json:"id"`
}
func (r *CertShowAndDestroy) Authorize(ctx http.Context) error {
return nil
}
func (r *CertShowAndDestroy) Rules(ctx http.Context) map[string]string {
return map[string]string{
"id": "required|uint|min:1|exists:certs,id",
}
}
func (r *CertShowAndDestroy) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *CertShowAndDestroy) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *CertShowAndDestroy) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,40 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type CertStore struct {
Type string `form:"type" json:"type"`
Domains []string `form:"domains" json:"domains"`
AutoRenew bool `form:"auto_renew" json:"auto_renew"`
UserID uint `form:"user_id" json:"user_id"`
DNSID *uint `form:"dns_id" json:"dns_id"`
WebsiteID *uint `form:"website_id" json:"website_id"`
}
func (r *CertStore) Authorize(ctx http.Context) error {
return nil
}
func (r *CertStore) Rules(ctx http.Context) map[string]string {
return map[string]string{
"type": "required|in:P256,P384,2048,4096",
"domains": "required|array",
"auto_renew": "required|bool",
"user_id": "required|exists:cert_users,id",
}
}
func (r *CertStore) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *CertStore) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *CertStore) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,42 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type CertUpdate struct {
ID uint `form:"id" json:"id"`
Type string `form:"type" json:"type"`
Domains []string `form:"domains" json:"domains"`
AutoRenew bool `form:"auto_renew" json:"auto_renew"`
UserID uint `form:"user_id" json:"user_id"`
DNSID *uint `form:"dns_id" json:"dns_id"`
WebsiteID *uint `form:"website_id" json:"website_id"`
}
func (r *CertUpdate) Authorize(ctx http.Context) error {
return nil
}
func (r *CertUpdate) Rules(ctx http.Context) map[string]string {
return map[string]string{
"id": "required|uint|min:1|exists:certs,id",
"type": "required|in:P256,P384,2048,4096",
"domains": "required|array",
"auto_renew": "required|bool",
"user_id": "required|exists:cert_users,id",
}
}
func (r *CertUpdate) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *CertUpdate) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *CertUpdate) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -1,54 +0,0 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
"panel/pkg/acme"
)
type DNSAdd struct {
Type string `form:"type" json:"type"`
Name string `form:"name" json:"name"`
Data acme.DNSParam `form:"data" json:"data"`
}
func (r *DNSAdd) Authorize(ctx http.Context) error {
return nil
}
func (r *DNSAdd) Rules(ctx http.Context) map[string]string {
return map[string]string{
"type": "required|in:dnspod,aliyun,cloudflare",
"name": "required",
"data": "required",
"data.id": "required_if:type,dnspod",
"data.token": "required_if:type,dnspod",
"data.access_key": "required_if:type,aliyun",
"data.secret_key": "required_if:type,aliyun",
"data.email": "required_if:type,cloudflare",
"data.api_key": "required_if:type,cloudflare",
}
}
func (r *DNSAdd) Messages(ctx http.Context) map[string]string {
return map[string]string{
"type.required": "类型不能为空",
"type.in": "类型必须为 dnspod, aliyun, cloudflare 中的一个",
"name.required": "备注名称不能为空",
"data.required": "数据不能为空",
"data.id.required_if": "ID 不能为空",
"data.token.required_if": "Token 不能为空",
"data.access_key.required": "Access Key 不能为空",
"data.secret_key.required": "Secret Key 不能为空",
"data.email.required": "Email 不能为空",
"data.api_key.required": "API Key 不能为空",
}
}
func (r *DNSAdd) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *DNSAdd) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,32 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type DNSShowAndDestroy struct {
ID uint `form:"id" json:"id"`
}
func (r *DNSShowAndDestroy) Authorize(ctx http.Context) error {
return nil
}
func (r *DNSShowAndDestroy) Rules(ctx http.Context) map[string]string {
return map[string]string{
"id": "required|uint|min:1|exists:cert_dns,id",
}
}
func (r *DNSShowAndDestroy) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *DNSShowAndDestroy) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *DNSShowAndDestroy) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,44 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
"panel/pkg/acme"
)
type DNSStore struct {
Type string `form:"type" json:"type"`
Name string `form:"name" json:"name"`
Data acme.DNSParam `form:"data" json:"data"`
}
func (r *DNSStore) Authorize(ctx http.Context) error {
return nil
}
func (r *DNSStore) Rules(ctx http.Context) map[string]string {
return map[string]string{
"type": "required|in:dnspod,aliyun,cloudflare",
"name": "required",
"data": "required",
"data.id": "required_if:type,dnspod",
"data.token": "required_if:type,dnspod",
"data.access_key": "required_if:type,aliyun",
"data.secret_key": "required_if:type,aliyun",
"data.email": "required_if:type,cloudflare",
"data.api_key": "required_if:type,cloudflare",
}
}
func (r *DNSStore) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *DNSStore) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *DNSStore) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,46 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
"panel/pkg/acme"
)
type DNSUpdate struct {
ID uint `form:"id" json:"id"`
Type string `form:"type" json:"type"`
Name string `form:"name" json:"name"`
Data acme.DNSParam `form:"data" json:"data"`
}
func (r *DNSUpdate) Authorize(ctx http.Context) error {
return nil
}
func (r *DNSUpdate) Rules(ctx http.Context) map[string]string {
return map[string]string{
"id": "required|uint|min:1|exists:cert_dns,id",
"type": "required|in:dnspod,aliyun,cloudflare",
"name": "required",
"data": "required",
"data.id": "required_if:type,dnspod",
"data.token": "required_if:type,dnspod",
"data.access_key": "required_if:type,aliyun",
"data.secret_key": "required_if:type,aliyun",
"data.email": "required_if:type,cloudflare",
"data.api_key": "required_if:type,cloudflare",
}
}
func (r *DNSUpdate) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *DNSUpdate) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *DNSUpdate) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -20,10 +20,7 @@ func (r *Obtain) Rules(ctx http.Context) map[string]string {
}
func (r *Obtain) Messages(ctx http.Context) map[string]string {
return map[string]string{
"id.required": "证书 ID 不能为空",
"id.exists": "证书 ID 不存在",
}
return map[string]string{}
}
func (r *Obtain) Attributes(ctx http.Context) map[string]string {

View File

@@ -20,10 +20,7 @@ func (r *Renew) Rules(ctx http.Context) map[string]string {
}
func (r *Renew) Messages(ctx http.Context) map[string]string {
return map[string]string{
"id.required": "证书 ID 不能为空",
"id.exists": "证书 ID 不存在",
}
return map[string]string{}
}
func (r *Renew) Attributes(ctx http.Context) map[string]string {

View File

@@ -1,49 +0,0 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type UserAdd struct {
CA string `form:"ca" json:"ca"`
Email string `form:"email" json:"email"`
Kid string `form:"kid" json:"kid"`
HmacEncoded string `form:"hmac_encoded" json:"hmac_encoded"`
KeyType string `form:"key_type" json:"key_type"`
}
func (r *UserAdd) Authorize(ctx http.Context) error {
return nil
}
func (r *UserAdd) Rules(ctx http.Context) map[string]string {
return map[string]string{
"ca": "required|in:letsencrypt,zerossl,sslcom,google,buypass",
"email": "required|email",
"kid": "required_unless:ca,letsencrypt,buypass",
"hmac_encoded": "required_unless:ca,letsencrypt,buypass",
"key_type": "required|in:P256,P384,2048,4096",
}
}
func (r *UserAdd) Messages(ctx http.Context) map[string]string {
return map[string]string{
"ca.required": "CA 不能为空",
"ca.in": "CA 必须为 letsencrypt, zerossl, sslcom, google, buypass 中的一个",
"email.required": "邮箱不能为空",
"email.email": "邮箱格式不正确",
"kid.required_unless": "KID 不能为空",
"hmac_encoded.required": "HMAC Encoded 不能为空",
"key_type.required": "密钥类型不能为空",
"key_type.in": "密钥类型必须为 P256, P384, 2048, 4096 中的一个",
}
}
func (r *UserAdd) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *UserAdd) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,32 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type UserShowAndDestroy struct {
ID uint `form:"id" json:"id"`
}
func (r *UserShowAndDestroy) Authorize(ctx http.Context) error {
return nil
}
func (r *UserShowAndDestroy) Rules(ctx http.Context) map[string]string {
return map[string]string{
"id": "required|uint|min:1|exists:cert_users,id",
}
}
func (r *UserShowAndDestroy) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *UserShowAndDestroy) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *UserShowAndDestroy) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,40 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type UserStore struct {
CA string `form:"ca" json:"ca"`
Email string `form:"email" json:"email"`
Kid string `form:"kid" json:"kid"`
HmacEncoded string `form:"hmac_encoded" json:"hmac_encoded"`
KeyType string `form:"key_type" json:"key_type"`
}
func (r *UserStore) Authorize(ctx http.Context) error {
return nil
}
func (r *UserStore) Rules(ctx http.Context) map[string]string {
return map[string]string{
"ca": "required|in:letsencrypt,zerossl,sslcom,google,buypass",
"email": "required|email",
"kid": "required_unless:ca,letsencrypt,buypass",
"hmac_encoded": "required_unless:ca,letsencrypt,buypass",
"key_type": "required|in:P256,P384,2048,4096",
}
}
func (r *UserStore) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *UserStore) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *UserStore) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -0,0 +1,42 @@
package requests
import (
"github.com/goravel/framework/contracts/http"
"github.com/goravel/framework/contracts/validation"
)
type UserUpdate struct {
ID uint `form:"id" json:"id"`
CA string `form:"ca" json:"ca"`
Email string `form:"email" json:"email"`
Kid string `form:"kid" json:"kid"`
HmacEncoded string `form:"hmac_encoded" json:"hmac_encoded"`
KeyType string `form:"key_type" json:"key_type"`
}
func (r *UserUpdate) Authorize(ctx http.Context) error {
return nil
}
func (r *UserUpdate) Rules(ctx http.Context) map[string]string {
return map[string]string{
"id": "required|uint|min:1|exists:cert_users,id",
"ca": "required|in:letsencrypt,zerossl,sslcom,google,buypass",
"email": "required|email",
"kid": "required_unless:ca,letsencrypt,buypass",
"hmac_encoded": "required_unless:ca,letsencrypt,buypass",
"key_type": "required|in:P256,P384,2048,4096",
}
}
func (r *UserUpdate) Messages(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *UserUpdate) Attributes(ctx http.Context) map[string]string {
return map[string]string{}
}
func (r *UserUpdate) PrepareForValidation(ctx http.Context, data validation.Data) error {
return nil
}

View File

@@ -15,13 +15,18 @@ import (
)
type Cert interface {
GetByID(ID uint) (models.Cert, error)
UserAdd(request requests.UserAdd) error
UserDelete(ID uint) error
DNSAdd(request requests.DNSAdd) error
DNSDelete(ID uint) error
CertAdd(request requests.CertAdd) error
CertDelete(ID uint) error
UserStore(request requests.UserStore) error
UserUpdate(request requests.UserUpdate) error
UserShow(ID uint) (models.CertUser, error)
UserDestroy(ID uint) error
DNSStore(request requests.DNSStore) error
DNSUpdate(request requests.DNSUpdate) error
DNSShow(ID uint) (models.CertDNS, error)
DNSDestroy(ID uint) error
CertStore(request requests.CertStore) error
CertUpdate(request requests.CertUpdate) error
CertShow(ID uint) (models.Cert, error)
CertDestroy(ID uint) error
ObtainAuto(ID uint) (certificate.Resource, error)
ObtainManual(ID uint) (certificate.Resource, error)
ManualDNS(ID uint) (map[string]acme.Resolve, error)
@@ -35,15 +40,8 @@ func NewCertImpl() *CertImpl {
return &CertImpl{}
}
// GetByID 根据 ID 获取证书
func (s *CertImpl) GetByID(ID uint) (models.Cert, error) {
var cert models.Cert
err := facades.Orm().Query().With("User").With("DNS").With("Website").Where("id = ?", ID).First(&cert)
return cert, err
}
// UserAdd 添加用户
func (s *CertImpl) UserAdd(request requests.UserAdd) error {
// UserStore 添加用户
func (s *CertImpl) UserStore(request requests.UserStore) error {
var user models.CertUser
user.CA = request.CA
user.Email = request.Email
@@ -81,8 +79,59 @@ func (s *CertImpl) UserAdd(request requests.UserAdd) error {
return facades.Orm().Query().Create(&user)
}
// UserDelete 删除用户
func (s *CertImpl) UserDelete(ID uint) error {
// UserUpdate 更新用户
func (s *CertImpl) UserUpdate(request requests.UserUpdate) error {
var user models.CertUser
err := facades.Orm().Query().Where("id = ?", request.ID).First(&user)
if err != nil {
return err
}
user.CA = request.CA
user.Email = request.Email
user.Kid = &request.Kid
user.HmacEncoded = &request.HmacEncoded
user.KeyType = request.KeyType
var client *acme.Client
switch user.CA {
case "letsencrypt":
client, err = acme.NewRegisterClient(user.Email, acme.CALetEncrypt, certcrypto.KeyType(user.KeyType))
case "buypass":
client, err = acme.NewRegisterClient(user.Email, acme.CABuypass, certcrypto.KeyType(user.KeyType))
case "zerossl":
client, err = acme.NewRegisterWithExternalAccountBindingClient(user.Email, *user.Kid, *user.HmacEncoded, acme.CAZeroSSL, certcrypto.KeyType(user.KeyType))
case "sslcom":
client, err = acme.NewRegisterWithExternalAccountBindingClient(user.Email, *user.Kid, *user.HmacEncoded, acme.CASSLcom, certcrypto.KeyType(user.KeyType))
case "google":
client, err = acme.NewRegisterWithExternalAccountBindingClient(user.Email, *user.Kid, *user.HmacEncoded, acme.CAGoogle, certcrypto.KeyType(user.KeyType))
default:
return errors.New("CA 提供商不支持")
}
if err != nil {
return errors.New("向 CA 注册账号失败,请检查参数是否正确")
}
privateKey, err := acme.GetPrivateKey(client.User.GetPrivateKey(), acme.KeyType(user.KeyType))
if err != nil {
return errors.New("获取私钥失败")
}
user.PrivateKey = string(privateKey)
return facades.Orm().Query().Save(&user)
}
// UserShow 根据 ID 获取用户
func (s *CertImpl) UserShow(ID uint) (models.CertUser, error) {
var user models.CertUser
err := facades.Orm().Query().With("Certs").Where("id = ?", ID).First(&user)
return user, err
}
// UserDestroy 删除用户
func (s *CertImpl) UserDestroy(ID uint) error {
var user models.CertUser
err := facades.Orm().Query().With("Certs").Where("id = ?", ID).First(&user)
if err != nil {
@@ -97,8 +146,8 @@ func (s *CertImpl) UserDelete(ID uint) error {
return err
}
// DNSAdd 添加 DNS
func (s *CertImpl) DNSAdd(request requests.DNSAdd) error {
// DNSStore 添加 DNS
func (s *CertImpl) DNSStore(request requests.DNSStore) error {
var dns models.CertDNS
dns.Type = request.Type
dns.Name = request.Name
@@ -107,8 +156,31 @@ func (s *CertImpl) DNSAdd(request requests.DNSAdd) error {
return facades.Orm().Query().Create(&dns)
}
// DNSDelete 删除 DNS
func (s *CertImpl) DNSDelete(ID uint) error {
// DNSUpdate 更新 DNS
func (s *CertImpl) DNSUpdate(request requests.DNSUpdate) error {
var dns models.CertDNS
err := facades.Orm().Query().Where("id = ?", request.ID).First(&dns)
if err != nil {
return err
}
dns.Type = request.Type
dns.Name = request.Name
dns.Data = request.Data
return facades.Orm().Query().Save(&dns)
}
// DNSShow 根据 ID 获取 DNS
func (s *CertImpl) DNSShow(ID uint) (models.CertDNS, error) {
var dns models.CertDNS
err := facades.Orm().Query().With("Certs").Where("id = ?", ID).First(&dns)
return dns, err
}
// DNSDestroy 删除 DNS
func (s *CertImpl) DNSDestroy(ID uint) error {
var dns models.CertDNS
err := facades.Orm().Query().With("Certs").Where("id = ?", ID).First(&dns)
if err != nil {
@@ -123,8 +195,8 @@ func (s *CertImpl) DNSDelete(ID uint) error {
return err
}
// CertAdd 添加证书
func (s *CertImpl) CertAdd(request requests.CertAdd) error {
// CertStore 添加证书
func (s *CertImpl) CertStore(request requests.CertStore) error {
var cert models.Cert
cert.Type = request.Type
cert.Domains = request.Domains
@@ -141,8 +213,39 @@ func (s *CertImpl) CertAdd(request requests.CertAdd) error {
return facades.Orm().Query().Create(&cert)
}
// CertDelete 删除证书
func (s *CertImpl) CertDelete(ID uint) error {
// CertUpdate 更新证书
func (s *CertImpl) CertUpdate(request requests.CertUpdate) error {
var cert models.Cert
err := facades.Orm().Query().Where("id = ?", request.ID).First(&cert)
if err != nil {
return err
}
cert.Type = request.Type
cert.Domains = request.Domains
cert.AutoRenew = request.AutoRenew
cert.UserID = request.UserID
if request.DNSID != nil {
cert.DNSID = request.DNSID
}
if request.WebsiteID != nil {
cert.WebsiteID = request.WebsiteID
}
return facades.Orm().Query().Save(&cert)
}
// CertShow 根据 ID 获取证书
func (s *CertImpl) CertShow(ID uint) (models.Cert, error) {
var cert models.Cert
err := facades.Orm().Query().With("User").With("DNS").With("Website").Where("id = ?", ID).First(&cert)
return cert, err
}
// CertDestroy 删除证书
func (s *CertImpl) CertDestroy(ID uint) error {
var cert models.Cert
err := facades.Orm().Query().Where("id = ?", ID).First(&cert)
if err != nil {

View File

@@ -152,7 +152,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.CertAdd"
"$ref": "#/definitions/requests.CertStore"
}
}
],
@@ -179,6 +179,118 @@ const docTemplate = `{
}
},
"/panel/cert/certs/{id}": {
"get": {
"security": [
{
"BearerToken": []
}
],
"description": "获取面板证书管理的证书",
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "获取证书",
"parameters": [
{
"type": "integer",
"description": "证书 ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controllers.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.Cert"
}
}
}
]
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"put": {
"security": [
{
"BearerToken": []
}
],
"description": "更新面板证书管理的证书",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "更新证书",
"parameters": [
{
"type": "integer",
"description": "证书 ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "证书信息",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.CertUpdate"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controllers.SuccessResponse"
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"delete": {
"security": [
{
@@ -299,7 +411,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.DNSAdd"
"$ref": "#/definitions/requests.DNSStore"
}
}
],
@@ -326,6 +438,118 @@ const docTemplate = `{
}
},
"/panel/cert/dns/{id}": {
"get": {
"security": [
{
"BearerToken": []
}
],
"description": "获取面板证书管理的 DNS 接口",
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "获取 DNS 接口",
"parameters": [
{
"type": "integer",
"description": "DNS 接口 ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controllers.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.CertDNS"
}
}
}
]
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"put": {
"security": [
{
"BearerToken": []
}
],
"description": "更新面板证书管理的 DNS 接口",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "更新 DNS 接口",
"parameters": [
{
"type": "integer",
"description": "DNS 接口 ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "DNS 接口信息",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.DNSUpdate"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controllers.SuccessResponse"
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"delete": {
"security": [
{
@@ -645,7 +869,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.UserAdd"
"$ref": "#/definitions/requests.UserStore"
}
}
],
@@ -672,6 +896,118 @@ const docTemplate = `{
}
},
"/panel/cert/users/{id}": {
"get": {
"security": [
{
"BearerToken": []
}
],
"description": "获取面板证书管理的 ACME 用户",
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "获取 ACME 用户",
"parameters": [
{
"type": "integer",
"description": "用户 ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controllers.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.CertUser"
}
}
}
]
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"put": {
"security": [
{
"BearerToken": []
}
],
"description": "更新面板证书管理的 ACME 用户",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "更新 ACME 用户",
"parameters": [
{
"type": "integer",
"description": "用户 ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "用户信息",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.UserUpdate"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controllers.SuccessResponse"
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"delete": {
"security": [
{
@@ -765,6 +1101,23 @@ const docTemplate = `{
}
}
}
},
"/swagger": {
"get": {
"description": "Swagger UI",
"tags": [
"Swagger"
],
"summary": "Swagger UI",
"responses": {
"200": {
"description": "OK"
},
"500": {
"description": "Internal Server Error"
}
}
}
}
},
"definitions": {
@@ -907,6 +1260,10 @@ const docTemplate = `{
"id": {
"type": "integer"
},
"name": {
"description": "备注名称",
"type": "string"
},
"type": {
"description": "DNS 提供商 (dnspod, aliyun, cloudflare)",
"type": "string"
@@ -958,6 +1315,9 @@ const docTemplate = `{
"models.Website": {
"type": "object",
"properties": {
"cert": {
"$ref": "#/definitions/models.Cert"
},
"created_at": {
"type": "string"
},
@@ -987,7 +1347,7 @@ const docTemplate = `{
}
}
},
"requests.CertAdd": {
"requests.CertStore": {
"type": "object",
"properties": {
"auto_renew": {
@@ -1007,15 +1367,67 @@ const docTemplate = `{
},
"user_id": {
"type": "integer"
},
"website_id": {
"type": "integer"
}
}
},
"requests.DNSAdd": {
"requests.CertUpdate": {
"type": "object",
"properties": {
"auto_renew": {
"type": "boolean"
},
"dns_id": {
"type": "integer"
},
"domains": {
"type": "array",
"items": {
"type": "string"
}
},
"id": {
"type": "integer"
},
"type": {
"type": "string"
},
"user_id": {
"type": "integer"
},
"website_id": {
"type": "integer"
}
}
},
"requests.DNSStore": {
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/acme.DNSParam"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"requests.DNSUpdate": {
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/acme.DNSParam"
},
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
}
@@ -1048,7 +1460,7 @@ const docTemplate = `{
}
}
},
"requests.UserAdd": {
"requests.UserStore": {
"type": "object",
"properties": {
"ca": {
@@ -1068,6 +1480,29 @@ const docTemplate = `{
}
}
},
"requests.UserUpdate": {
"type": "object",
"properties": {
"ca": {
"type": "string"
},
"email": {
"type": "string"
},
"hmac_encoded": {
"type": "string"
},
"id": {
"type": "integer"
},
"key_type": {
"type": "string"
},
"kid": {
"type": "string"
}
}
},
"responses.CertList": {
"type": "object",
"properties": {

View File

@@ -145,7 +145,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.CertAdd"
"$ref": "#/definitions/requests.CertStore"
}
}
],
@@ -172,6 +172,118 @@
}
},
"/panel/cert/certs/{id}": {
"get": {
"security": [
{
"BearerToken": []
}
],
"description": "获取面板证书管理的证书",
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "获取证书",
"parameters": [
{
"type": "integer",
"description": "证书 ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controllers.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.Cert"
}
}
}
]
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"put": {
"security": [
{
"BearerToken": []
}
],
"description": "更新面板证书管理的证书",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "更新证书",
"parameters": [
{
"type": "integer",
"description": "证书 ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "证书信息",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.CertUpdate"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controllers.SuccessResponse"
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"delete": {
"security": [
{
@@ -292,7 +404,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.DNSAdd"
"$ref": "#/definitions/requests.DNSStore"
}
}
],
@@ -319,6 +431,118 @@
}
},
"/panel/cert/dns/{id}": {
"get": {
"security": [
{
"BearerToken": []
}
],
"description": "获取面板证书管理的 DNS 接口",
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "获取 DNS 接口",
"parameters": [
{
"type": "integer",
"description": "DNS 接口 ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controllers.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.CertDNS"
}
}
}
]
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"put": {
"security": [
{
"BearerToken": []
}
],
"description": "更新面板证书管理的 DNS 接口",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "更新 DNS 接口",
"parameters": [
{
"type": "integer",
"description": "DNS 接口 ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "DNS 接口信息",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.DNSUpdate"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controllers.SuccessResponse"
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"delete": {
"security": [
{
@@ -638,7 +862,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.UserAdd"
"$ref": "#/definitions/requests.UserStore"
}
}
],
@@ -665,6 +889,118 @@
}
},
"/panel/cert/users/{id}": {
"get": {
"security": [
{
"BearerToken": []
}
],
"description": "获取面板证书管理的 ACME 用户",
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "获取 ACME 用户",
"parameters": [
{
"type": "integer",
"description": "用户 ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/controllers.SuccessResponse"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.CertUser"
}
}
}
]
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"put": {
"security": [
{
"BearerToken": []
}
],
"description": "更新面板证书管理的 ACME 用户",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"证书"
],
"summary": "更新 ACME 用户",
"parameters": [
{
"type": "integer",
"description": "用户 ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "用户信息",
"name": "data",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/requests.UserUpdate"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/controllers.SuccessResponse"
}
},
"401": {
"description": "登录已过期",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
},
"500": {
"description": "系统内部错误",
"schema": {
"$ref": "#/definitions/controllers.ErrorResponse"
}
}
}
},
"delete": {
"security": [
{
@@ -758,6 +1094,23 @@
}
}
}
},
"/swagger": {
"get": {
"description": "Swagger UI",
"tags": [
"Swagger"
],
"summary": "Swagger UI",
"responses": {
"200": {
"description": "OK"
},
"500": {
"description": "Internal Server Error"
}
}
}
}
},
"definitions": {
@@ -900,6 +1253,10 @@
"id": {
"type": "integer"
},
"name": {
"description": "备注名称",
"type": "string"
},
"type": {
"description": "DNS 提供商 (dnspod, aliyun, cloudflare)",
"type": "string"
@@ -951,6 +1308,9 @@
"models.Website": {
"type": "object",
"properties": {
"cert": {
"$ref": "#/definitions/models.Cert"
},
"created_at": {
"type": "string"
},
@@ -980,7 +1340,7 @@
}
}
},
"requests.CertAdd": {
"requests.CertStore": {
"type": "object",
"properties": {
"auto_renew": {
@@ -1000,15 +1360,67 @@
},
"user_id": {
"type": "integer"
},
"website_id": {
"type": "integer"
}
}
},
"requests.DNSAdd": {
"requests.CertUpdate": {
"type": "object",
"properties": {
"auto_renew": {
"type": "boolean"
},
"dns_id": {
"type": "integer"
},
"domains": {
"type": "array",
"items": {
"type": "string"
}
},
"id": {
"type": "integer"
},
"type": {
"type": "string"
},
"user_id": {
"type": "integer"
},
"website_id": {
"type": "integer"
}
}
},
"requests.DNSStore": {
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/acme.DNSParam"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"requests.DNSUpdate": {
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/acme.DNSParam"
},
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
}
@@ -1041,7 +1453,7 @@
}
}
},
"requests.UserAdd": {
"requests.UserStore": {
"type": "object",
"properties": {
"ca": {
@@ -1061,6 +1473,29 @@
}
}
},
"requests.UserUpdate": {
"type": "object",
"properties": {
"ca": {
"type": "string"
},
"email": {
"type": "string"
},
"hmac_encoded": {
"type": "string"
},
"id": {
"type": "integer"
},
"key_type": {
"type": "string"
},
"kid": {
"type": "string"
}
}
},
"responses.CertList": {
"type": "object",
"properties": {

View File

@@ -94,6 +94,9 @@ definitions:
$ref: '#/definitions/acme.DNSParam'
id:
type: integer
name:
description: 备注名称
type: string
type:
description: DNS 提供商 (dnspod, aliyun, cloudflare)
type: string
@@ -128,6 +131,8 @@ definitions:
type: object
models.Website:
properties:
cert:
$ref: '#/definitions/models.Cert'
created_at:
type: string
id:
@@ -147,7 +152,7 @@ definitions:
updated_at:
type: string
type: object
requests.CertAdd:
requests.CertStore:
properties:
auto_renew:
type: boolean
@@ -161,11 +166,45 @@ definitions:
type: string
user_id:
type: integer
website_id:
type: integer
type: object
requests.DNSAdd:
requests.CertUpdate:
properties:
auto_renew:
type: boolean
dns_id:
type: integer
domains:
items:
type: string
type: array
id:
type: integer
type:
type: string
user_id:
type: integer
website_id:
type: integer
type: object
requests.DNSStore:
properties:
data:
$ref: '#/definitions/acme.DNSParam'
name:
type: string
type:
type: string
type: object
requests.DNSUpdate:
properties:
data:
$ref: '#/definitions/acme.DNSParam'
id:
type: integer
name:
type: string
type:
type: string
type: object
@@ -186,7 +225,7 @@ definitions:
id:
type: integer
type: object
requests.UserAdd:
requests.UserStore:
properties:
ca:
type: string
@@ -199,6 +238,21 @@ definitions:
kid:
type: string
type: object
requests.UserUpdate:
properties:
ca:
type: string
email:
type: string
hmac_encoded:
type: string
id:
type: integer
key_type:
type: string
kid:
type: string
type: object
responses.CertList:
properties:
items:
@@ -301,7 +355,7 @@ paths:
name: data
required: true
schema:
$ref: '#/definitions/requests.CertAdd'
$ref: '#/definitions/requests.CertStore'
produces:
- application/json
responses:
@@ -353,6 +407,75 @@ paths:
summary: 删除证书
tags:
- 证书
get:
description: 获取面板证书管理的证书
parameters:
- description: 证书 ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/controllers.SuccessResponse'
- properties:
data:
$ref: '#/definitions/models.Cert'
type: object
"401":
description: 登录已过期
schema:
$ref: '#/definitions/controllers.ErrorResponse'
"500":
description: 系统内部错误
schema:
$ref: '#/definitions/controllers.ErrorResponse'
security:
- BearerToken: []
summary: 获取证书
tags:
- 证书
put:
consumes:
- application/json
description: 更新面板证书管理的证书
parameters:
- description: 证书 ID
in: path
name: id
required: true
type: integer
- description: 证书信息
in: body
name: data
required: true
schema:
$ref: '#/definitions/requests.CertUpdate'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/controllers.SuccessResponse'
"401":
description: 登录已过期
schema:
$ref: '#/definitions/controllers.ErrorResponse'
"500":
description: 系统内部错误
schema:
$ref: '#/definitions/controllers.ErrorResponse'
security:
- BearerToken: []
summary: 更新证书
tags:
- 证书
/panel/cert/dns:
get:
description: 获取面板证书管理的 DNS 接口列表
@@ -391,7 +514,7 @@ paths:
name: data
required: true
schema:
$ref: '#/definitions/requests.DNSAdd'
$ref: '#/definitions/requests.DNSStore'
produces:
- application/json
responses:
@@ -443,6 +566,75 @@ paths:
summary: 删除 DNS 接口
tags:
- 证书
get:
description: 获取面板证书管理的 DNS 接口
parameters:
- description: DNS 接口 ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/controllers.SuccessResponse'
- properties:
data:
$ref: '#/definitions/models.CertDNS'
type: object
"401":
description: 登录已过期
schema:
$ref: '#/definitions/controllers.ErrorResponse'
"500":
description: 系统内部错误
schema:
$ref: '#/definitions/controllers.ErrorResponse'
security:
- BearerToken: []
summary: 获取 DNS 接口
tags:
- 证书
put:
consumes:
- application/json
description: 更新面板证书管理的 DNS 接口
parameters:
- description: DNS 接口 ID
in: path
name: id
required: true
type: integer
- description: DNS 接口信息
in: body
name: data
required: true
schema:
$ref: '#/definitions/requests.DNSUpdate'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/controllers.SuccessResponse'
"401":
description: 登录已过期
schema:
$ref: '#/definitions/controllers.ErrorResponse'
"500":
description: 系统内部错误
schema:
$ref: '#/definitions/controllers.ErrorResponse'
security:
- BearerToken: []
summary: 更新 DNS 接口
tags:
- 证书
/panel/cert/dnsProviders:
get:
description: 获取面板证书管理支持的 DNS 提供商
@@ -603,7 +795,7 @@ paths:
name: data
required: true
schema:
$ref: '#/definitions/requests.UserAdd'
$ref: '#/definitions/requests.UserStore'
produces:
- application/json
responses:
@@ -655,6 +847,75 @@ paths:
summary: 删除 ACME 用户
tags:
- 证书
get:
description: 获取面板证书管理的 ACME 用户
parameters:
- description: 用户 ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/controllers.SuccessResponse'
- properties:
data:
$ref: '#/definitions/models.CertUser'
type: object
"401":
description: 登录已过期
schema:
$ref: '#/definitions/controllers.ErrorResponse'
"500":
description: 系统内部错误
schema:
$ref: '#/definitions/controllers.ErrorResponse'
security:
- BearerToken: []
summary: 获取 ACME 用户
tags:
- 证书
put:
consumes:
- application/json
description: 更新面板证书管理的 ACME 用户
parameters:
- description: 用户 ID
in: path
name: id
required: true
type: integer
- description: 用户信息
in: body
name: data
required: true
schema:
$ref: '#/definitions/requests.UserUpdate'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/controllers.SuccessResponse'
"401":
description: 登录已过期
schema:
$ref: '#/definitions/controllers.ErrorResponse'
"500":
description: 系统内部错误
schema:
$ref: '#/definitions/controllers.ErrorResponse'
security:
- BearerToken: []
summary: 更新 ACME 用户
tags:
- 证书
/panel/user/login:
post:
consumes:
@@ -685,6 +946,17 @@ paths:
summary: 用户登录
tags:
- 用户
/swagger:
get:
description: Swagger UI
responses:
"200":
description: OK
"500":
description: Internal Server Error
summary: Swagger UI
tags:
- Swagger
securityDefinitions:
BearerToken:
in: header

View File

@@ -60,15 +60,20 @@ func Api() {
r.Get("dnsProviders", certController.DNSProviders)
r.Get("algorithms", certController.Algorithms)
r.Get("users", certController.UserList)
r.Post("users", certController.UserAdd)
r.Delete("users/{id}", certController.UserDelete)
r.Post("users", certController.UserStore)
r.Put("users/{id}", certController.UserUpdate)
r.Get("users/{id}", certController.UserShow)
r.Delete("users/{id}", certController.UserDestroy)
r.Get("dns", certController.DNSList)
r.Post("dns", certController.DNSAdd)
r.Delete("dns/{id}", certController.DNSDelete)
r.Post("dns", certController.DNSStore)
r.Put("dns/{id}", certController.DNSUpdate)
r.Get("dns/{id}", certController.DNSShow)
r.Delete("dns/{id}", certController.DNSDestroy)
r.Get("certs", certController.CertList)
r.Post("certs", certController.CertAdd)
r.Delete("certs/{id}", certController.CertDelete)
// r.Get("certs/{id}", certController.CertInfo)
r.Post("certs", certController.CertStore)
r.Put("certs/{id}", certController.CertUpdate)
r.Get("certs/{id}", certController.CertShow)
r.Delete("certs/{id}", certController.CertDestroy)
r.Post("obtain", certController.Obtain)
r.Post("renew", certController.Renew)
r.Post("manualDNS", certController.ManualDNS)