chore(deps): Update non-major dependencies (#1750)

* chore(deps): Update non-major dependencies

* fix: 适配 libtnb validator v0.4.3 与 cron v0.5.4 新 API

- 自定义规则改经 WithRules/WithFallibleRules 注入,exists/not_exists 转为
  FallibleRule 让数据库错误上抛而非静默失败
- openapi contrib 移除运行时 Op,端点文档改为 Document 闭包在定义处捕获类型
- SetDefault 已移除,Bind 校验器改由 service.SetValidator 注入
- cron.New 现在返回 error

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: 耗子 <haozi@loli.email>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
renovate[bot]
2026-08-26 23:11:15 +08:00
committed by GitHub
parent be938a4814
commit 1df45f438b
55 changed files with 924 additions and 836 deletions
+10 -10
View File
@@ -1,6 +1,6 @@
module github.com/acepanel/panel/v3
go 1.27
go 1.27.0
require (
github.com/andybalholm/brotli v1.2.2
@@ -15,7 +15,7 @@ require (
github.com/distribution/reference v0.6.0
github.com/expr-lang/expr v1.17.8
github.com/fsnotify/fsnotify v1.10.1
github.com/go-chi/chi/v5 v5.3.1
github.com/go-chi/chi/v5 v5.3.2
github.com/go-chi/httplog/v3 v3.4.0
github.com/go-gormigrate/gormigrate/v2 v2.1.6
github.com/go-sql-driver/mysql v1.10.0
@@ -33,19 +33,19 @@ require (
github.com/libdns/gcore v0.0.0-20250427050847-9964da923833
github.com/libdns/huaweicloud v1.0.1
github.com/libdns/libdns v1.1.1
github.com/libdns/namesilo v1.0.0
github.com/libdns/namesilo v1.1.0
github.com/libdns/porkbun v1.1.0
github.com/libdns/tencentcloud v1.4.3
github.com/libdns/westcn v1.0.2
github.com/libtnb/chix/v2 v2.1.1
github.com/libtnb/cron v0.5.2
github.com/libtnb/cron v0.5.4
github.com/libtnb/gormstore v1.3.0
github.com/libtnb/logrotate v0.1.2
github.com/libtnb/logrotate v0.1.4
github.com/libtnb/sessions v1.5.0
github.com/libtnb/sqlite v1.2.2
github.com/libtnb/utils v1.2.2
github.com/libtnb/validator v0.4.1
github.com/libtnb/validator/contrib/openapi v0.2.0
github.com/libtnb/validator v0.4.3
github.com/libtnb/validator/contrib/openapi v0.2.2
github.com/medama-io/go-useragent v1.2.4
github.com/mholt/acmez/v3 v3.1.6
github.com/moby/moby/api v1.55.0
@@ -58,10 +58,10 @@ require (
github.com/sethvargo/go-limiter v1.2.0
github.com/shirou/gopsutil/v4 v4.26.7
github.com/spf13/cast v1.10.0
github.com/stretchr/testify v1.11.1
github.com/stretchr/testify v1.12.1
github.com/studio-b12/gowebdav v0.13.0
github.com/tufanbarisyildirim/gonginx v0.0.0-20260220081509-8e17ce617db3
github.com/urfave/cli/v3 v3.10.1
github.com/urfave/cli/v3 v3.11.0
github.com/valyala/fastjson v1.6.10
github.com/wneessen/go-mail v0.8.1
github.com/xuri/excelize/v2 v2.11.0
@@ -72,7 +72,7 @@ require (
golang.org/x/sys v0.47.0
golang.org/x/term v0.45.0
gorm.io/gorm v1.31.2
modernc.org/sqlite v1.56.0
modernc.org/sqlite v1.57.0
resty.dev/v3 v3.0.0-rc.3
)
+16 -16
View File
@@ -94,8 +94,8 @@ github.com/fxamacker/cbor/v2 v2.9.2/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj2
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-chi/chi/v5 v5.3.1 h1:3j4HZLGZQ3JpMCrPJF/Jl3mYJfWLKBfNJ6quurUGCf8=
github.com/go-chi/chi/v5 v5.3.1/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
github.com/go-chi/chi/v5 v5.3.2 h1:5YQkICvTCSZ25hoRsyJazN0scjzKGiu4VAUc7H1o1nY=
github.com/go-chi/chi/v5 v5.3.2/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
github.com/go-chi/httplog/v3 v3.4.0 h1:gO4fvt8HEtFwHq926HoKe1aV2DymfPJuZy4+U4zwT3I=
github.com/go-chi/httplog/v3 v3.4.0/go.mod h1:tDhJo9G+F4mioDgX4pKbyA0uVZwCtHejoSsDkvJkFkU=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -256,8 +256,8 @@ github.com/libdns/huaweicloud v1.0.1 h1:TdfpPY//3/QPhEGCyvR8u2DTlGxzpyaIsqofH5kY
github.com/libdns/huaweicloud v1.0.1/go.mod h1:lMHNSEqLZeuE4N28ytaqLZia3NPuaaz1ldAH/73bOQE=
github.com/libdns/libdns v1.1.1 h1:wPrHrXILoSHKWJKGd0EiAVmiJbFShguILTg9leS/P/U=
github.com/libdns/libdns v1.1.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
github.com/libdns/namesilo v1.0.0 h1:Shwbj9YnSp4NR617sBOSfDkFozEnWInWCxNwrDvPkCg=
github.com/libdns/namesilo v1.0.0/go.mod h1:qdojVsogA6eZDjDPdpIUIfv4ymiX+FuqcVV1eNmHDss=
github.com/libdns/namesilo v1.1.0 h1:cFG3V5SOTk3kpjiJZb1NPFZu2EACXfrOyNSqQ1xH1w4=
github.com/libdns/namesilo v1.1.0/go.mod h1:ndr1T+DizW+go/96J2cMhO9eFHQQNp70gZZQAK6bcGA=
github.com/libdns/porkbun v1.1.0 h1:X763NqXjW26VEl7GvBtF/3CGeuGt9JqoQ35mwIlx40E=
github.com/libdns/porkbun v1.1.0/go.mod h1:JL6NfXkkSlLr24AI5Fv0t3/Oa6PXOSOerVsOmr8+URs=
github.com/libdns/tencentcloud v1.4.3 h1:xJHYLL1TdPeOtUr6Bu6dHTd1TU6/VFm7BFc2EAzAlvc=
@@ -268,12 +268,12 @@ github.com/libtnb/acmez/v3 v3.0.0-20260406165834-a264acd02292 h1:FF1ZlwFFjpwT6Ct
github.com/libtnb/acmez/v3 v3.0.0-20260406165834-a264acd02292/go.mod h1:5nTPosTGosLxF3+LU4ygbgMRFDhbAVpqMI4+a4aHLBY=
github.com/libtnb/chix/v2 v2.1.1 h1:QQwHXUyPaUUp/KOwzXf2NB0IRKb9v2pqIdOIItzBPiE=
github.com/libtnb/chix/v2 v2.1.1/go.mod h1:OEY9v0976U/IJzP6n8VdhgXH17VL2muo3EQWsIUyxm8=
github.com/libtnb/cron v0.5.2 h1:Yy9a/S82bAS4KzE1SSMjNLtigPkejgMPUp9BHGeb1pw=
github.com/libtnb/cron v0.5.2/go.mod h1:nrOHxS4Ernkn1E//vs64xzC58hGfoL0+lYSW2zsROGI=
github.com/libtnb/cron v0.5.4 h1:sRJL2Xb2X+l1UvgGj0cxGyCXrGVXQG0rCFIPsIYB1RE=
github.com/libtnb/cron v0.5.4/go.mod h1:hVcFjf3S5YxxeCg4M/np9Eh3p6EU4xgo2KodRd9YA5I=
github.com/libtnb/gormstore v1.3.0 h1:OvVTYHZ9MCHI3Anf2ITtJLunAefyBQWG96EmHCE0eLM=
github.com/libtnb/gormstore v1.3.0/go.mod h1:Z/n6VlVdLPmvunSM8sYGNHVebTTN5yUSTZsyNxW2IZc=
github.com/libtnb/logrotate v0.1.2 h1:q9FLtYQYtzAlOB9bs91nPppqt3GNTUOonrBOivrtiOc=
github.com/libtnb/logrotate v0.1.2/go.mod h1:yqC9N3C5mg0fBlquK+cWLB7xG5plQrP0ma84hMRj3ic=
github.com/libtnb/logrotate v0.1.4 h1:ZSv5LbMjqJA/oLLbRS2ZRVzXGFU7Q+zqkNjTz8vZfI0=
github.com/libtnb/logrotate v0.1.4/go.mod h1:0IYk9Olsc8C59nsUm05DUvJBfG0YSSHtEgiAj470Rlw=
github.com/libtnb/securecookie v1.4.0 h1:SkKHO7T5I4aRGV7/6fnYYsleQDnnDzeAmTDA0GMPD98=
github.com/libtnb/securecookie v1.4.0/go.mod h1:mg1i9HfstsYBGwCfQdU+3Z1GuieyZRAxbkFUnrzchJU=
github.com/libtnb/sessions v1.5.0 h1:gvTRkSR8lpp1PB0Nms/kc+gh1BwJ411fxLjnZLYItLs=
@@ -284,10 +284,10 @@ github.com/libtnb/testify v0.0.0-20260406170114-25da2dad39e7 h1:ZzONsNhw69uC/wJQ
github.com/libtnb/testify v0.0.0-20260406170114-25da2dad39e7/go.mod h1:HeQeTfKU6tj2Lx1z79UacwYeDioo6M4ZD7BDDI6+rrg=
github.com/libtnb/utils v1.2.2 h1:HUqgAIb+TIrZPXRytYB5XqzkEXG2U4a4/ZGpprNtL5A=
github.com/libtnb/utils v1.2.2/go.mod h1:KUCx2+Phw3cLXOwuQDy6XwFOliaYuU1rpAuJQuHf+lQ=
github.com/libtnb/validator v0.4.1 h1:TYDC1C1yp93d02huzCqEc1aU/u5PAtC3jqGPtEdZchU=
github.com/libtnb/validator v0.4.1/go.mod h1:j08Lydxwy7ModkoKeYIHxvZvAtnzzdE8xi2J+SGVrgc=
github.com/libtnb/validator/contrib/openapi v0.2.0 h1:y47A16Lqtkc9/uifRIJ2XC+Rkgghj2fmHPrclcPXPtA=
github.com/libtnb/validator/contrib/openapi v0.2.0/go.mod h1:2vCdRniTmXWBtG4gro9B7s6ko4v3WdoSKjvhsWdTn3g=
github.com/libtnb/validator v0.4.3 h1:tq3nOOt9YIcrWgXmM9BQAr3ofjiUBAyeUDdHHlpip+o=
github.com/libtnb/validator v0.4.3/go.mod h1:yssIkchUNzAQc8EeP99rwIeYbFE2usrYbN1Ki5pamfQ=
github.com/libtnb/validator/contrib/openapi v0.2.2 h1:i+6l1ZvHsMQAOjfFgAR7wOHQMxQtORVqIHiYy8gScV4=
github.com/libtnb/validator/contrib/openapi v0.2.2/go.mod h1:8qT0y4bs8o400kv1YqD6K+4P04x128yPmnarLwWeHaQ=
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 h1:PwQumkgq4/acIiZhtifTV5OUqqiP82UAl0h87xj/l9k=
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -423,8 +423,8 @@ github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZ
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tufanbarisyildirim/gonginx v0.0.0-20260220081509-8e17ce617db3 h1:ClWHRIz18WRVT3RD9y9uTwEWU9eEi+VYFEIumg05FLk=
github.com/tufanbarisyildirim/gonginx v0.0.0-20260220081509-8e17ce617db3/go.mod h1:ALbEe81QPWOZjDKCKNWodG2iqCMtregG8+ebQgjx2+4=
github.com/urfave/cli/v3 v3.10.1 h1:7Kx9H50hrHbRbyxgO1KP6/BcbiGRz0uYh5YyQ30JEEY=
github.com/urfave/cli/v3 v3.10.1/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/urfave/cli/v3 v3.11.0 h1:P/euJp99kb9p0tlVY+iYTLYYTAQlfl0hR2gUO1Img1Q=
github.com/urfave/cli/v3 v3.11.0/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4=
github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE=
github.com/wneessen/go-mail v0.8.1 h1:tVcncj02/QySVFw3zr/kXOzZcuFQqBNT6K+Rbgm/pcM=
@@ -638,8 +638,8 @@ modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg=
modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.56.0 h1:/D8e2RfFqoy/Zc6PuC76U28zFwmI/sYx1Kjm4yEn9e0=
modernc.org/sqlite v1.56.0/go.mod h1:yCJ2cmAaIkHQ25oXWrF8H4O1lIfPYPR26yCEDj2P3pQ=
modernc.org/sqlite v1.57.0 h1:qNQP6xnx5M0ISNtlnxoOX0+cD5bJ0/gr9aMmndFczzg=
modernc.org/sqlite v1.57.0/go.mod h1:yCJ2cmAaIkHQ25oXWrF8H4O1lIfPYPR26yCEDj2P3pQ=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
+4 -1
View File
@@ -13,10 +13,13 @@ import (
func NewCron(log *slog.Logger, jobs []job.Job) (*cron.Cron, error) {
// 面板任务均为 5 段表达式,不启用 WithSecondsField
c := cron.New(
c, err := cron.New(
cron.WithLogger(log),
cron.WithChain(wrap.Recover(), wrap.SkipIfRunning()),
)
if err != nil {
return nil, err
}
for _, j := range jobs {
id, err := c.Add(j.Spec, j.Task)
+4 -3
View File
@@ -21,6 +21,7 @@ import (
"github.com/acepanel/panel/v3/internal/app"
"github.com/acepanel/panel/v3/internal/middleware"
"github.com/acepanel/panel/v3/internal/route"
"github.com/acepanel/panel/v3/internal/service"
"github.com/acepanel/panel/v3/pkg/apploader"
"github.com/acepanel/panel/v3/pkg/config"
"github.com/acepanel/panel/v3/pkg/embed"
@@ -30,8 +31,8 @@ import (
func NewRouter(loader *apploader.Loader, conf *config.Config, t *gotext.Locale, middlewares *middleware.Middlewares, v *validator.Validator, endpoints []route.Endpoints) (*chi.Mux, error) {
mws := middlewares
// 供 service.Bind / route.SpecJSON 使用
validator.SetDefault(v)
// 供 service.Bind 使用
service.SetValidator(v)
// 数据驱动的登录白名单
public := route.PublicPaths(endpoints)
@@ -49,7 +50,7 @@ func NewRouter(loader *apploader.Loader, conf *config.Config, t *gotext.Locale,
// 仅调试模式挂载 OpenAPI 文档
if conf.App.Debug {
spec, err := route.SpecJSON(endpoints, "AcePanel")
spec, err := route.SpecJSON(endpoints, "AcePanel", v)
if err != nil {
return nil, err
}
+6 -5
View File
@@ -12,7 +12,11 @@ import (
// NewValidator 构建校验器
func NewValidator(conf *config.Config, db *gorm.DB) *validator.Validator {
opts := []validator.Option{validator.WithStrictRequired()}
opts := []validator.Option{
validator.WithStrictRequired(),
validator.WithRules(rule.Rules()...),
validator.WithFallibleRules(rule.FallibleRules(db)...),
}
switch conf.App.Locale {
case "zh_CN":
opts = append(opts, validator.WithTranslation(translations.ZhHans()))
@@ -20,8 +24,5 @@ func NewValidator(conf *config.Config, db *gorm.DB) *validator.Validator {
opts = append(opts, validator.WithTranslation(translations.ZhHant()))
}
v := validator.NewValidator(opts...)
rule.RegisterRules(v, db)
return v
return validator.MustNew(opts...)
}
+13 -7
View File
@@ -14,13 +14,15 @@ import (
"github.com/acepanel/panel/v3/internal/rule"
)
// tagValidator mirrors service.NewValidator's rule set. db is nil: CheckRules and
// AddRules only compile expressions, they never invoke a rule's Passes or touch
// tagValidator mirrors bootstrap.NewValidator's rule set. db is nil: CheckType and
// AddRules only compile expressions, they never invoke a rule's Validate or touch
// the database.
func tagValidator() *validator.Validator {
v := validator.NewValidator(validator.WithStrictRequired())
rule.RegisterRules(v, nil)
return v
return validator.MustNew(
validator.WithStrictRequired(),
validator.WithRules(rule.Rules()...),
validator.WithFallibleRules(rule.FallibleRules(nil)...),
)
}
// TestCheckRulesKeyRequests runs the validator's own tag checker over the
@@ -35,7 +37,7 @@ func TestCheckRulesKeyRequests(t *testing.T) {
&SettingPanel{}, &UserTokenCreate{}, &FirewallScanSetting{},
&WebsiteStatDateRange{}, &BackupCreate{},
} {
if err := v.CheckRules(req); err != nil {
if err := v.CheckType(reflect.TypeOf(req)); err != nil {
t.Errorf("%T: %v", req, err)
}
}
@@ -77,7 +79,11 @@ func TestValidateTagsCompile(t *testing.T) {
name = field.Names[0].Name
}
seen++
if err := v.Map(map[string]any{}, nil).AddRules(name, expr); err != nil {
vd, err := v.Map(map[string]any{}, nil)
if err != nil {
t.Fatal(err)
}
if err = vd.AddRules(name, expr); err != nil {
t.Errorf("%s: %s `validate:%q`: %v", file, name, expr, err)
}
return true
+6 -6
View File
@@ -13,12 +13,12 @@ func AlertRoutes(alertService *service.AlertService) Endpoints {
svc := alertService
return Endpoints{
{Method: http.MethodGet, Path: "/api/alert/rule", Handler: svc.ListRules, Summary: "告警规则列表", Tags: []string{"告警"}, Request: request.Paginate{}, Response: service.Envelope[service.Page[*biz.AlertRule]]{}},
{Method: http.MethodPost, Path: "/api/alert/rule", Handler: svc.CreateRule, Summary: "创建告警规则", Tags: []string{"告警"}, Request: request.AlertRuleCreate{}, Response: service.Envelope[biz.AlertRule]{}},
{Method: http.MethodGet, Path: "/api/alert/rule/{id}", Handler: svc.GetRule, Summary: "获取告警规则", Tags: []string{"告警"}, Request: request.ID{}, Response: service.Envelope[biz.AlertRule]{}},
{Method: http.MethodPut, Path: "/api/alert/rule/{id}", Handler: svc.UpdateRule, Summary: "更新告警规则", Tags: []string{"告警"}, Request: request.AlertRuleUpdate{}},
{Method: http.MethodDelete, Path: "/api/alert/rule/{id}", Handler: svc.DeleteRule, Summary: "删除告警规则", Tags: []string{"告警"}, Request: request.ID{}},
{Method: http.MethodGet, Path: "/api/alert/record", Handler: svc.List, Summary: "告警记录列表", Tags: []string{"告警"}, Request: request.Paginate{}, Response: service.Envelope[service.Page[*biz.Alert]]{}},
{Method: http.MethodGet, Path: "/api/alert/rule", Handler: svc.ListRules, Summary: "告警规则列表", Tags: []string{"告警"}, Document: Describe[request.Paginate, service.Envelope[service.Page[*biz.AlertRule]]]()},
{Method: http.MethodPost, Path: "/api/alert/rule", Handler: svc.CreateRule, Summary: "创建告警规则", Tags: []string{"告警"}, Document: Describe[request.AlertRuleCreate, service.Envelope[biz.AlertRule]]()},
{Method: http.MethodGet, Path: "/api/alert/rule/{id}", Handler: svc.GetRule, Summary: "获取告警规则", Tags: []string{"告警"}, Document: Describe[request.ID, service.Envelope[biz.AlertRule]]()},
{Method: http.MethodPut, Path: "/api/alert/rule/{id}", Handler: svc.UpdateRule, Summary: "更新告警规则", Tags: []string{"告警"}, Document: DescribeReq[request.AlertRuleUpdate]()},
{Method: http.MethodDelete, Path: "/api/alert/rule/{id}", Handler: svc.DeleteRule, Summary: "删除告警规则", Tags: []string{"告警"}, Document: DescribeReq[request.ID]()},
{Method: http.MethodGet, Path: "/api/alert/record", Handler: svc.List, Summary: "告警记录列表", Tags: []string{"告警"}, Document: Describe[request.Paginate, service.Envelope[service.Page[*biz.Alert]]]()},
{Method: http.MethodPost, Path: "/api/alert/record/clear", Handler: svc.Clear, Summary: "清空告警记录", Tags: []string{"告警"}},
}
}
+8 -8
View File
@@ -17,21 +17,21 @@ func AppRoutes(appService *service.AppService) Endpoints {
{Method: http.MethodGet, Path: "/api/app/list", Handler: app.List,
Summary: "应用列表", Tags: []string{"应用"}},
{Method: http.MethodPost, Path: "/api/app/install", Handler: app.Install,
Summary: "安装应用", Tags: []string{"应用"}, Request: request.App{}},
Summary: "安装应用", Tags: []string{"应用"}, Document: DescribeReq[request.App]()},
{Method: http.MethodPost, Path: "/api/app/uninstall", Handler: app.Uninstall,
Summary: "卸载应用", Tags: []string{"应用"}, Request: request.AppSlug{}},
Summary: "卸载应用", Tags: []string{"应用"}, Document: DescribeReq[request.AppSlug]()},
{Method: http.MethodPost, Path: "/api/app/update", Handler: app.Update,
Summary: "更新应用", Tags: []string{"应用"}, Request: request.AppSlug{}},
Summary: "更新应用", Tags: []string{"应用"}, Document: DescribeReq[request.AppSlug]()},
{Method: http.MethodPost, Path: "/api/app/update_show", Handler: app.UpdateShow,
Summary: "更新应用首页显示", Tags: []string{"应用"}, Request: request.AppUpdateShow{}},
Summary: "更新应用首页显示", Tags: []string{"应用"}, Document: DescribeReq[request.AppUpdateShow]()},
{Method: http.MethodPost, Path: "/api/app/update_order", Handler: app.UpdateOrder,
Summary: "更新应用排序", Tags: []string{"应用"}, Request: request.AppUpdateOrder{}},
Summary: "更新应用排序", Tags: []string{"应用"}, Document: DescribeReq[request.AppUpdateOrder]()},
{Method: http.MethodGet, Path: "/api/app/is_installed", Handler: app.IsInstalled,
Summary: "检查应用是否已安装", Tags: []string{"应用"}, Request: request.AppSlugs{}},
Summary: "检查应用是否已安装", Tags: []string{"应用"}, Document: DescribeReq[request.AppSlugs]()},
{Method: http.MethodGet, Path: "/api/app/custom", Handler: app.GetCustom,
Summary: "获取自定义编译参数", Tags: []string{"应用"}, Request: request.AppSlug{}},
Summary: "获取自定义编译参数", Tags: []string{"应用"}, Document: DescribeReq[request.AppSlug]()},
{Method: http.MethodPost, Path: "/api/app/custom", Handler: app.SaveCustom,
Summary: "保存自定义编译参数", Tags: []string{"应用"}, Request: request.AppCustomSave{}},
Summary: "保存自定义编译参数", Tags: []string{"应用"}, Document: DescribeReq[request.AppCustomSave]()},
{Method: http.MethodGet, Path: "/api/app/update_cache", Handler: app.UpdateCache,
Summary: "更新应用缓存", Tags: []string{"应用"}},
}
+5 -5
View File
@@ -14,15 +14,15 @@ func BackupRoutes(backupService *service.BackupService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/backup/{type}", Handler: backup.List, Summary: "备份列表", Tags: []string{"备份"},
Request: request.BackupList{}, Response: service.Envelope[service.Page[*types.BackupFile]]{}},
Document: Describe[request.BackupList, service.Envelope[service.Page[*types.BackupFile]]]()},
{Method: http.MethodPost, Path: "/api/backup/{type}", Handler: backup.Create, Summary: "创建备份", Tags: []string{"备份"},
Request: request.BackupCreate{}},
Document: DescribeReq[request.BackupCreate]()},
{Method: http.MethodPost, Path: "/api/backup/{type}/upload", Handler: backup.Upload, Summary: "上传备份", Tags: []string{"备份"}},
{Method: http.MethodGet, Path: "/api/backup/{type}/download", Handler: backup.Download, Summary: "下载备份", Tags: []string{"备份"},
Request: request.BackupFile{}},
Document: DescribeReq[request.BackupFile]()},
{Method: http.MethodDelete, Path: "/api/backup/{type}/delete", Handler: backup.Delete, Summary: "删除备份", Tags: []string{"备份"},
Request: request.BackupFile{}},
Document: DescribeReq[request.BackupFile]()},
{Method: http.MethodPost, Path: "/api/backup/{type}/restore", Handler: backup.Restore, Summary: "恢复备份", Tags: []string{"备份"},
Request: request.BackupRestore{}},
Document: DescribeReq[request.BackupRestore]()},
}
}
+5 -5
View File
@@ -14,14 +14,14 @@ func BackupStorageRoutes(backupStorageService *service.BackupStorageService) End
return Endpoints{
{Method: http.MethodGet, Path: "/api/backup_storage", Handler: backupStorage.List, Summary: "备份存储列表", Tags: []string{"备份存储"},
Request: request.Paginate{}, Response: service.Envelope[service.Page[*biz.BackupStorage]]{}},
Document: Describe[request.Paginate, service.Envelope[service.Page[*biz.BackupStorage]]]()},
{Method: http.MethodPost, Path: "/api/backup_storage", Handler: backupStorage.Create, Summary: "创建备份存储", Tags: []string{"备份存储"},
Request: request.BackupStorageCreate{}, Response: service.Envelope[biz.BackupStorage]{}},
Document: Describe[request.BackupStorageCreate, service.Envelope[biz.BackupStorage]]()},
{Method: http.MethodPut, Path: "/api/backup_storage/{id}", Handler: backupStorage.Update, Summary: "更新备份存储", Tags: []string{"备份存储"},
Request: request.BackupStorageUpdate{}},
Document: DescribeReq[request.BackupStorageUpdate]()},
{Method: http.MethodGet, Path: "/api/backup_storage/{id}", Handler: backupStorage.Get, Summary: "获取备份存储", Tags: []string{"备份存储"},
Request: request.ID{}, Response: service.Envelope[biz.BackupStorage]{}},
Document: Describe[request.ID, service.Envelope[biz.BackupStorage]]()},
{Method: http.MethodDelete, Path: "/api/backup_storage/{id}", Handler: backupStorage.Delete, Summary: "删除备份存储", Tags: []string{"备份存储"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
}
}
+20 -20
View File
@@ -22,46 +22,46 @@ func CertRoutes(certAccountService *service.CertAccountService, certDNSService *
{Method: http.MethodGet, Path: "/api/cert/algorithms", Handler: cert.Algorithms, Summary: "密钥算法列表", Tags: []string{"证书"}},
// 证书
{Method: http.MethodGet, Path: "/api/cert/cert", Handler: cert.List, Summary: "证书列表", Tags: []string{"证书"},
Request: request.Paginate{}, Response: service.Envelope[service.Page[*types.CertList]]{}},
Document: Describe[request.Paginate, service.Envelope[service.Page[*types.CertList]]]()},
{Method: http.MethodPost, Path: "/api/cert/cert", Handler: cert.Create, Summary: "创建证书", Tags: []string{"证书"},
Request: request.CertCreate{}, Response: service.Envelope[biz.Cert]{}},
Document: Describe[request.CertCreate, service.Envelope[biz.Cert]]()},
{Method: http.MethodPost, Path: "/api/cert/cert/upload", Handler: cert.Upload, Summary: "上传证书", Tags: []string{"证书"},
Request: request.CertUpload{}, Response: service.Envelope[biz.Cert]{}},
Document: Describe[request.CertUpload, service.Envelope[biz.Cert]]()},
{Method: http.MethodPut, Path: "/api/cert/cert/{id}", Handler: cert.Update, Summary: "更新证书", Tags: []string{"证书"},
Request: request.CertUpdate{}},
Document: DescribeReq[request.CertUpdate]()},
{Method: http.MethodGet, Path: "/api/cert/cert/{id}", Handler: cert.Get, Summary: "获取证书", Tags: []string{"证书"},
Request: request.ID{}, Response: service.Envelope[biz.Cert]{}},
Document: Describe[request.ID, service.Envelope[biz.Cert]]()},
{Method: http.MethodDelete, Path: "/api/cert/cert/{id}", Handler: cert.Delete, Summary: "删除证书", Tags: []string{"证书"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
{Method: http.MethodPost, Path: "/api/cert/cert/{id}/obtain_auto", Handler: cert.ObtainAuto, Summary: "自动签发证书", Tags: []string{"证书"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
{Method: http.MethodPost, Path: "/api/cert/cert/{id}/obtain_self_signed", Handler: cert.ObtainSelfSigned, Summary: "签发自签名证书", Tags: []string{"证书"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
{Method: http.MethodPost, Path: "/api/cert/cert/{id}/renew", Handler: cert.Renew, Summary: "续签证书", Tags: []string{"证书"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
{Method: http.MethodPost, Path: "/api/cert/cert/{id}/deploy", Handler: cert.Deploy, Summary: "部署证书", Tags: []string{"证书"},
Request: request.CertDeploy{}},
Document: DescribeReq[request.CertDeploy]()},
// DNS
{Method: http.MethodGet, Path: "/api/cert/dns", Handler: certDNS.List, Summary: "DNS 列表", Tags: []string{"证书"},
Request: request.Paginate{}, Response: service.Envelope[service.Page[*biz.CertDNS]]{}},
Document: Describe[request.Paginate, service.Envelope[service.Page[*biz.CertDNS]]]()},
{Method: http.MethodPost, Path: "/api/cert/dns", Handler: certDNS.Create, Summary: "创建 DNS", Tags: []string{"证书"},
Request: request.CertDNSCreate{}, Response: service.Envelope[biz.CertDNS]{}},
Document: Describe[request.CertDNSCreate, service.Envelope[biz.CertDNS]]()},
{Method: http.MethodPut, Path: "/api/cert/dns/{id}", Handler: certDNS.Update, Summary: "更新 DNS", Tags: []string{"证书"},
Request: request.CertDNSUpdate{}},
Document: DescribeReq[request.CertDNSUpdate]()},
{Method: http.MethodGet, Path: "/api/cert/dns/{id}", Handler: certDNS.Get, Summary: "获取 DNS", Tags: []string{"证书"},
Request: request.ID{}, Response: service.Envelope[biz.CertDNS]{}},
Document: Describe[request.ID, service.Envelope[biz.CertDNS]]()},
{Method: http.MethodDelete, Path: "/api/cert/dns/{id}", Handler: certDNS.Delete, Summary: "删除 DNS", Tags: []string{"证书"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
// 账户
{Method: http.MethodGet, Path: "/api/cert/account", Handler: certAccount.List, Summary: "账户列表", Tags: []string{"证书"},
Request: request.Paginate{}, Response: service.Envelope[service.Page[*biz.CertAccount]]{}},
Document: Describe[request.Paginate, service.Envelope[service.Page[*biz.CertAccount]]]()},
{Method: http.MethodPost, Path: "/api/cert/account", Handler: certAccount.Create, Summary: "创建账户", Tags: []string{"证书"},
Request: request.CertAccountCreate{}, Response: service.Envelope[biz.CertAccount]{}},
Document: Describe[request.CertAccountCreate, service.Envelope[biz.CertAccount]]()},
{Method: http.MethodPut, Path: "/api/cert/account/{id}", Handler: certAccount.Update, Summary: "更新账户", Tags: []string{"证书"},
Request: request.CertAccountUpdate{}},
Document: DescribeReq[request.CertAccountUpdate]()},
{Method: http.MethodGet, Path: "/api/cert/account/{id}", Handler: certAccount.Get, Summary: "获取账户", Tags: []string{"证书"},
Request: request.ID{}, Response: service.Envelope[biz.CertAccount]{}},
Document: Describe[request.ID, service.Envelope[biz.CertAccount]]()},
{Method: http.MethodDelete, Path: "/api/cert/account/{id}", Handler: certAccount.Delete, Summary: "删除账户", Tags: []string{"证书"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
}
}
+30 -30
View File
@@ -20,108 +20,108 @@ func ContainerRoutes(containerComposeService *service.ContainerComposeService, c
// 容器
{Method: http.MethodGet, Path: "/api/container/container", Handler: container.List,
Summary: "容器列表", Tags: []string{"容器"},
Response: service.Envelope[service.Page[types.Container]]{}},
Document: DescribeResp[service.Envelope[service.Page[types.Container]]]()},
{Method: http.MethodGet, Path: "/api/container/container/search", Handler: container.Search,
Summary: "搜索容器", Tags: []string{"容器"},
Response: service.Envelope[service.Page[types.Container]]{}},
Document: DescribeResp[service.Envelope[service.Page[types.Container]]]()},
{Method: http.MethodGet, Path: "/api/container/container/{id}", Handler: container.Inspect,
Summary: "容器详情", Tags: []string{"容器"},
Request: request.ContainerID{}},
Document: DescribeReq[request.ContainerID]()},
{Method: http.MethodPost, Path: "/api/container/container", Handler: container.Create,
Summary: "创建容器", Tags: []string{"容器"},
Request: request.ContainerCreate{}},
Document: DescribeReq[request.ContainerCreate]()},
{Method: http.MethodPut, Path: "/api/container/container/{id}", Handler: container.Update,
Summary: "更新容器", Tags: []string{"容器"},
Request: request.ContainerCreate{}},
Document: DescribeReq[request.ContainerCreate]()},
{Method: http.MethodDelete, Path: "/api/container/container/{id}", Handler: container.Remove,
Summary: "删除容器", Tags: []string{"容器"},
Request: request.ContainerID{}},
Document: DescribeReq[request.ContainerID]()},
{Method: http.MethodPost, Path: "/api/container/container/{id}/start", Handler: container.Start,
Summary: "启动容器", Tags: []string{"容器"},
Request: request.ContainerID{}},
Document: DescribeReq[request.ContainerID]()},
{Method: http.MethodPost, Path: "/api/container/container/{id}/stop", Handler: container.Stop,
Summary: "停止容器", Tags: []string{"容器"},
Request: request.ContainerID{}},
Document: DescribeReq[request.ContainerID]()},
{Method: http.MethodPost, Path: "/api/container/container/{id}/restart", Handler: container.Restart,
Summary: "重启容器", Tags: []string{"容器"},
Request: request.ContainerID{}},
Document: DescribeReq[request.ContainerID]()},
{Method: http.MethodPost, Path: "/api/container/container/{id}/pause", Handler: container.Pause,
Summary: "暂停容器", Tags: []string{"容器"},
Request: request.ContainerID{}},
Document: DescribeReq[request.ContainerID]()},
{Method: http.MethodPost, Path: "/api/container/container/{id}/unpause", Handler: container.Unpause,
Summary: "恢复容器", Tags: []string{"容器"},
Request: request.ContainerID{}},
Document: DescribeReq[request.ContainerID]()},
{Method: http.MethodPost, Path: "/api/container/container/{id}/kill", Handler: container.Kill,
Summary: "杀死容器", Tags: []string{"容器"},
Request: request.ContainerID{}},
Document: DescribeReq[request.ContainerID]()},
{Method: http.MethodPost, Path: "/api/container/container/{id}/rename", Handler: container.Rename,
Summary: "重命名容器", Tags: []string{"容器"},
Request: request.ContainerRename{}},
Document: DescribeReq[request.ContainerRename]()},
{Method: http.MethodPost, Path: "/api/container/container/prune", Handler: container.Prune,
Summary: "清理容器", Tags: []string{"容器"}},
// 编排
{Method: http.MethodGet, Path: "/api/container/compose", Handler: compose.List,
Summary: "编排列表", Tags: []string{"容器编排"},
Response: service.Envelope[service.Page[types.ContainerCompose]]{}},
Document: DescribeResp[service.Envelope[service.Page[types.ContainerCompose]]]()},
{Method: http.MethodGet, Path: "/api/container/compose/{name}", Handler: compose.Get,
Summary: "获取编排", Tags: []string{"容器编排"},
Request: request.ContainerComposeGet{}},
Document: DescribeReq[request.ContainerComposeGet]()},
{Method: http.MethodPost, Path: "/api/container/compose", Handler: compose.Create,
Summary: "创建编排", Tags: []string{"容器编排"},
Request: request.ContainerComposeCreate{}},
Document: DescribeReq[request.ContainerComposeCreate]()},
{Method: http.MethodPut, Path: "/api/container/compose/{name}", Handler: compose.Update,
Summary: "更新编排", Tags: []string{"容器编排"},
Request: request.ContainerComposeUpdate{}},
Document: DescribeReq[request.ContainerComposeUpdate]()},
{Method: http.MethodPost, Path: "/api/container/compose/{name}/up", Handler: compose.Up,
Summary: "启动编排", Tags: []string{"容器编排"},
Request: request.ContainerComposeUp{}},
Document: DescribeReq[request.ContainerComposeUp]()},
{Method: http.MethodPost, Path: "/api/container/compose/{name}/down", Handler: compose.Down,
Summary: "停止编排", Tags: []string{"容器编排"},
Request: request.ContainerComposeDown{}},
Document: DescribeReq[request.ContainerComposeDown]()},
{Method: http.MethodDelete, Path: "/api/container/compose/{name}", Handler: compose.Remove,
Summary: "删除编排", Tags: []string{"容器编排"},
Request: request.ContainerComposeRemove{}},
Document: DescribeReq[request.ContainerComposeRemove]()},
// 网络
{Method: http.MethodGet, Path: "/api/container/network", Handler: network.List,
Summary: "网络列表", Tags: []string{"容器网络"},
Response: service.Envelope[service.Page[types.ContainerNetwork]]{}},
Document: DescribeResp[service.Envelope[service.Page[types.ContainerNetwork]]]()},
{Method: http.MethodPost, Path: "/api/container/network", Handler: network.Create,
Summary: "创建网络", Tags: []string{"容器网络"},
Request: request.ContainerNetworkCreate{}},
Document: DescribeReq[request.ContainerNetworkCreate]()},
{Method: http.MethodDelete, Path: "/api/container/network/{id}", Handler: network.Remove,
Summary: "删除网络", Tags: []string{"容器网络"},
Request: request.ContainerNetworkID{}},
Document: DescribeReq[request.ContainerNetworkID]()},
{Method: http.MethodPost, Path: "/api/container/network/prune", Handler: network.Prune,
Summary: "清理网络", Tags: []string{"容器网络"}},
// 镜像
{Method: http.MethodGet, Path: "/api/container/image", Handler: image.List,
Summary: "镜像列表", Tags: []string{"容器镜像"},
Response: service.Envelope[service.Page[types.ContainerImage]]{}},
Document: DescribeResp[service.Envelope[service.Page[types.ContainerImage]]]()},
{Method: http.MethodGet, Path: "/api/container/image/exist", Handler: image.Exist,
Summary: "镜像是否存在", Tags: []string{"容器镜像"},
Request: request.ContainerImagePull{}},
Document: DescribeReq[request.ContainerImagePull]()},
{Method: http.MethodPost, Path: "/api/container/image", Handler: image.Pull,
Summary: "拉取镜像", Tags: []string{"容器镜像"},
Request: request.ContainerImagePull{}},
Document: DescribeReq[request.ContainerImagePull]()},
{Method: http.MethodDelete, Path: "/api/container/image/{id}", Handler: image.Remove,
Summary: "删除镜像", Tags: []string{"容器镜像"},
Request: request.ContainerImageID{}},
Document: DescribeReq[request.ContainerImageID]()},
{Method: http.MethodPost, Path: "/api/container/image/prune", Handler: image.Prune,
Summary: "清理镜像", Tags: []string{"容器镜像"}},
// 存储卷
{Method: http.MethodGet, Path: "/api/container/volume", Handler: volume.List,
Summary: "存储卷列表", Tags: []string{"容器存储卷"},
Response: service.Envelope[service.Page[types.ContainerVolume]]{}},
Document: DescribeResp[service.Envelope[service.Page[types.ContainerVolume]]]()},
{Method: http.MethodPost, Path: "/api/container/volume", Handler: volume.Create,
Summary: "创建存储卷", Tags: []string{"容器存储卷"},
Request: request.ContainerVolumeCreate{}},
Document: DescribeReq[request.ContainerVolumeCreate]()},
{Method: http.MethodDelete, Path: "/api/container/volume/{id}", Handler: volume.Remove,
Summary: "删除存储卷", Tags: []string{"容器存储卷"},
Request: request.ContainerVolumeID{}},
Document: DescribeReq[request.ContainerVolumeID]()},
{Method: http.MethodPost, Path: "/api/container/volume/prune", Handler: volume.Prune,
Summary: "清理存储卷", Tags: []string{"容器存储卷"}},
}
+6 -6
View File
@@ -15,21 +15,21 @@ func CronRoutes(cronService *service.CronService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/cron", Handler: svc.List,
Summary: "计划任务列表", Tags: []string{"计划任务"},
Request: request.Paginate{}, Response: service.Envelope[service.Page[*biz.Cron]]{}},
Document: Describe[request.Paginate, service.Envelope[service.Page[*biz.Cron]]]()},
{Method: http.MethodPost, Path: "/api/cron", Handler: svc.Create,
Summary: "创建计划任务", Tags: []string{"计划任务"},
Request: request.CronCreate{}},
Document: DescribeReq[request.CronCreate]()},
{Method: http.MethodPut, Path: "/api/cron/{id}", Handler: svc.Update,
Summary: "更新计划任务", Tags: []string{"计划任务"},
Request: request.CronUpdate{}},
Document: DescribeReq[request.CronUpdate]()},
{Method: http.MethodGet, Path: "/api/cron/{id}", Handler: svc.Get,
Summary: "获取计划任务", Tags: []string{"计划任务"},
Request: request.ID{}, Response: service.Envelope[biz.Cron]{}},
Document: Describe[request.ID, service.Envelope[biz.Cron]]()},
{Method: http.MethodDelete, Path: "/api/cron/{id}", Handler: svc.Delete,
Summary: "删除计划任务", Tags: []string{"计划任务"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
{Method: http.MethodPost, Path: "/api/cron/{id}/status", Handler: svc.Status,
Summary: "设置计划任务状态", Tags: []string{"计划任务"},
Request: request.CronStatus{}},
Document: DescribeReq[request.CronStatus]()},
}
}
+4 -4
View File
@@ -15,15 +15,15 @@ func DatabaseRoutes(databaseService *service.DatabaseService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/database", Handler: svc.List,
Summary: "获取数据库列表", Tags: []string{"数据库"},
Request: request.DatabaseList{}, Response: service.Envelope[service.Page[*biz.Database]]{}},
Document: Describe[request.DatabaseList, service.Envelope[service.Page[*biz.Database]]]()},
{Method: http.MethodPost, Path: "/api/database", Handler: svc.Create,
Summary: "创建数据库", Tags: []string{"数据库"},
Request: request.DatabaseCreate{}},
Document: DescribeReq[request.DatabaseCreate]()},
{Method: http.MethodDelete, Path: "/api/database", Handler: svc.Delete,
Summary: "删除数据库", Tags: []string{"数据库"},
Request: request.DatabaseDelete{}},
Document: DescribeReq[request.DatabaseDelete]()},
{Method: http.MethodPost, Path: "/api/database/comment", Handler: svc.Comment,
Summary: "设置数据库注释", Tags: []string{"数据库"},
Request: request.DatabaseComment{}},
Document: DescribeReq[request.DatabaseComment]()},
}
}
+7 -7
View File
@@ -15,24 +15,24 @@ func DatabaseElasticsearchRoutes(databaseElasticsearchService *service.DatabaseE
return Endpoints{
{Method: http.MethodGet, Path: "/api/database_elasticsearch/indices", Handler: svc.Indices,
Summary: "获取索引列表", Tags: []string{"Elasticsearch"},
Request: request.DatabaseESIndices{}, Response: service.Envelope[[]db.ESIndex]{}},
Document: Describe[request.DatabaseESIndices, service.Envelope[[]db.ESIndex]]()},
{Method: http.MethodPost, Path: "/api/database_elasticsearch/index", Handler: svc.IndexCreate,
Summary: "创建索引", Tags: []string{"Elasticsearch"},
Request: request.DatabaseESIndexCreate{}},
Document: DescribeReq[request.DatabaseESIndexCreate]()},
{Method: http.MethodDelete, Path: "/api/database_elasticsearch/index", Handler: svc.IndexDelete,
Summary: "删除索引", Tags: []string{"Elasticsearch"},
Request: request.DatabaseESIndexDelete{}},
Document: DescribeReq[request.DatabaseESIndexDelete]()},
{Method: http.MethodGet, Path: "/api/database_elasticsearch/data", Handler: svc.Data,
Summary: "获取文档列表", Tags: []string{"Elasticsearch"},
Request: request.DatabaseESData{}, Response: service.Envelope[service.Page[db.ESDocument]]{}},
Document: Describe[request.DatabaseESData, service.Envelope[service.Page[db.ESDocument]]]()},
{Method: http.MethodGet, Path: "/api/database_elasticsearch/document", Handler: svc.DocumentGet,
Summary: "获取文档", Tags: []string{"Elasticsearch"},
Request: request.DatabaseESDocumentGet{}, Response: service.Envelope[db.ESDocument]{}},
Document: Describe[request.DatabaseESDocumentGet, service.Envelope[db.ESDocument]]()},
{Method: http.MethodPost, Path: "/api/database_elasticsearch/document", Handler: svc.DocumentSet,
Summary: "设置文档", Tags: []string{"Elasticsearch"},
Request: request.DatabaseESDocumentSet{}},
Document: DescribeReq[request.DatabaseESDocumentSet]()},
{Method: http.MethodDelete, Path: "/api/database_elasticsearch/document", Handler: svc.DocumentDelete,
Summary: "删除文档", Tags: []string{"Elasticsearch"},
Request: request.DatabaseESDocumentDelete{}},
Document: DescribeReq[request.DatabaseESDocumentDelete]()},
}
}
+8 -8
View File
@@ -15,27 +15,27 @@ func DatabaseRedisRoutes(databaseRedisService *service.DatabaseRedisService) End
return Endpoints{
{Method: http.MethodGet, Path: "/api/database_redis/databases", Handler: svc.Databases,
Summary: "获取数据库数量", Tags: []string{"Redis"},
Request: request.DatabaseRedisDatabases{}},
Document: DescribeReq[request.DatabaseRedisDatabases]()},
{Method: http.MethodGet, Path: "/api/database_redis/data", Handler: svc.Data,
Summary: "获取键值列表", Tags: []string{"Redis"},
Request: request.DatabaseRedisData{}, Response: service.Envelope[service.Page[db.RedisKV]]{}},
Document: Describe[request.DatabaseRedisData, service.Envelope[service.Page[db.RedisKV]]]()},
{Method: http.MethodGet, Path: "/api/database_redis/key", Handler: svc.KeyGet,
Summary: "获取键值", Tags: []string{"Redis"},
Request: request.DatabaseRedisKeyGet{}, Response: service.Envelope[db.RedisKV]{}},
Document: Describe[request.DatabaseRedisKeyGet, service.Envelope[db.RedisKV]]()},
{Method: http.MethodPost, Path: "/api/database_redis/key", Handler: svc.KeySet,
Summary: "设置键值", Tags: []string{"Redis"},
Request: request.DatabaseRedisKeySet{}},
Document: DescribeReq[request.DatabaseRedisKeySet]()},
{Method: http.MethodDelete, Path: "/api/database_redis/key", Handler: svc.KeyDelete,
Summary: "删除键值", Tags: []string{"Redis"},
Request: request.DatabaseRedisKeyDelete{}},
Document: DescribeReq[request.DatabaseRedisKeyDelete]()},
{Method: http.MethodPost, Path: "/api/database_redis/key/ttl", Handler: svc.KeyTTL,
Summary: "设置键值过期时间", Tags: []string{"Redis"},
Request: request.DatabaseRedisKeyTTL{}},
Document: DescribeReq[request.DatabaseRedisKeyTTL]()},
{Method: http.MethodPost, Path: "/api/database_redis/key/rename", Handler: svc.KeyRename,
Summary: "重命名键值", Tags: []string{"Redis"},
Request: request.DatabaseRedisKeyRename{}},
Document: DescribeReq[request.DatabaseRedisKeyRename]()},
{Method: http.MethodPost, Path: "/api/database_redis/clear", Handler: svc.Clear,
Summary: "清空数据库", Tags: []string{"Redis"},
Request: request.DatabaseRedisClear{}},
Document: DescribeReq[request.DatabaseRedisClear]()},
}
}
+7 -7
View File
@@ -15,24 +15,24 @@ func DatabaseServerRoutes(databaseServerService *service.DatabaseServerService)
return Endpoints{
{Method: http.MethodGet, Path: "/api/database_server", Handler: svc.List,
Summary: "获取服务器列表", Tags: []string{"数据库服务器"},
Request: request.DatabaseList{}, Response: service.Envelope[service.Page[*biz.DatabaseServer]]{}},
Document: Describe[request.DatabaseList, service.Envelope[service.Page[*biz.DatabaseServer]]]()},
{Method: http.MethodPost, Path: "/api/database_server", Handler: svc.Create,
Summary: "创建服务器", Tags: []string{"数据库服务器"},
Request: request.DatabaseServerCreate{}},
Document: DescribeReq[request.DatabaseServerCreate]()},
{Method: http.MethodGet, Path: "/api/database_server/{id}", Handler: svc.Get,
Summary: "获取服务器", Tags: []string{"数据库服务器"},
Request: request.ID{}, Response: service.Envelope[biz.DatabaseServer]{}},
Document: Describe[request.ID, service.Envelope[biz.DatabaseServer]]()},
{Method: http.MethodPut, Path: "/api/database_server/{id}", Handler: svc.Update,
Summary: "更新服务器", Tags: []string{"数据库服务器"},
Request: request.DatabaseServerUpdate{}},
Document: DescribeReq[request.DatabaseServerUpdate]()},
{Method: http.MethodPut, Path: "/api/database_server/{id}/remark", Handler: svc.UpdateRemark,
Summary: "更新服务器备注", Tags: []string{"数据库服务器"},
Request: request.DatabaseServerUpdateRemark{}},
Document: DescribeReq[request.DatabaseServerUpdateRemark]()},
{Method: http.MethodDelete, Path: "/api/database_server/{id}", Handler: svc.Delete,
Summary: "删除服务器", Tags: []string{"数据库服务器"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
{Method: http.MethodPost, Path: "/api/database_server/{id}/sync", Handler: svc.Sync,
Summary: "同步服务器用户", Tags: []string{"数据库服务器"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
}
}
+6 -6
View File
@@ -15,21 +15,21 @@ func DatabaseUserRoutes(databaseUserService *service.DatabaseUserService) Endpoi
return Endpoints{
{Method: http.MethodGet, Path: "/api/database_user", Handler: svc.List,
Summary: "获取用户列表", Tags: []string{"数据库用户"},
Request: request.DatabaseList{}, Response: service.Envelope[service.Page[*biz.DatabaseUser]]{}},
Document: Describe[request.DatabaseList, service.Envelope[service.Page[*biz.DatabaseUser]]]()},
{Method: http.MethodPost, Path: "/api/database_user", Handler: svc.Create,
Summary: "创建用户", Tags: []string{"数据库用户"},
Request: request.DatabaseUserCreate{}},
Document: DescribeReq[request.DatabaseUserCreate]()},
{Method: http.MethodGet, Path: "/api/database_user/{id}", Handler: svc.Get,
Summary: "获取用户", Tags: []string{"数据库用户"},
Request: request.ID{}, Response: service.Envelope[biz.DatabaseUser]{}},
Document: Describe[request.ID, service.Envelope[biz.DatabaseUser]]()},
{Method: http.MethodPut, Path: "/api/database_user/{id}", Handler: svc.Update,
Summary: "更新用户", Tags: []string{"数据库用户"},
Request: request.DatabaseUserUpdate{}},
Document: DescribeReq[request.DatabaseUserUpdate]()},
{Method: http.MethodPut, Path: "/api/database_user/{id}/remark", Handler: svc.UpdateRemark,
Summary: "更新用户备注", Tags: []string{"数据库用户"},
Request: request.DatabaseUserUpdateRemark{}},
Document: DescribeReq[request.DatabaseUserUpdateRemark]()},
{Method: http.MethodDelete, Path: "/api/database_user/{id}", Handler: svc.Delete,
Summary: "删除用户", Tags: []string{"数据库用户"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
}
}
+36 -36
View File
@@ -26,88 +26,88 @@ func EnvironmentRoutes(environmentDotnetService *service.EnvironmentDotnetServic
{Method: http.MethodGet, Path: "/api/environment/list", Handler: environment.List,
Summary: "运行环境列表", Tags: tags},
{Method: http.MethodPost, Path: "/api/environment/install", Handler: environment.Install,
Summary: "安装运行环境", Tags: tags, Request: request.EnvironmentAction{}},
Summary: "安装运行环境", Tags: tags, Document: DescribeReq[request.EnvironmentAction]()},
{Method: http.MethodPost, Path: "/api/environment/uninstall", Handler: environment.Uninstall,
Summary: "卸载运行环境", Tags: tags, Request: request.EnvironmentAction{}},
Summary: "卸载运行环境", Tags: tags, Document: DescribeReq[request.EnvironmentAction]()},
{Method: http.MethodPost, Path: "/api/environment/update", Handler: environment.Update,
Summary: "更新运行环境", Tags: tags, Request: request.EnvironmentAction{}},
Summary: "更新运行环境", Tags: tags, Document: DescribeReq[request.EnvironmentAction]()},
{Method: http.MethodGet, Path: "/api/environment/is_installed", Handler: environment.IsInstalled,
Summary: "检查运行环境是否已安装", Tags: tags, Request: request.EnvironmentAction{}},
Summary: "检查运行环境是否已安装", Tags: tags, Document: DescribeReq[request.EnvironmentAction]()},
// Go
{Method: http.MethodPost, Path: "/api/environment/go/{slug}/set_cli", Handler: environmentGo.SetCli,
Summary: "设置 Go 命令行", Tags: tags, Request: request.EnvironmentSlug{}},
Summary: "设置 Go 命令行", Tags: tags, Document: DescribeReq[request.EnvironmentSlug]()},
{Method: http.MethodGet, Path: "/api/environment/go/{slug}/proxy", Handler: environmentGo.GetProxy,
Summary: "获取 Go 代理", Tags: tags, Request: request.EnvironmentSlug{}},
Summary: "获取 Go 代理", Tags: tags, Document: DescribeReq[request.EnvironmentSlug]()},
{Method: http.MethodPost, Path: "/api/environment/go/{slug}/proxy", Handler: environmentGo.SetProxy,
Summary: "设置 Go 代理", Tags: tags, Request: request.EnvironmentProxy{}},
Summary: "设置 Go 代理", Tags: tags, Document: DescribeReq[request.EnvironmentProxy]()},
// Java
{Method: http.MethodPost, Path: "/api/environment/java/{slug}/set_cli", Handler: environmentJava.SetCli,
Summary: "设置 Java 命令行", Tags: tags, Request: request.EnvironmentSlug{}},
Summary: "设置 Java 命令行", Tags: tags, Document: DescribeReq[request.EnvironmentSlug]()},
// Node.js
{Method: http.MethodPost, Path: "/api/environment/nodejs/{slug}/set_cli", Handler: environmentNodejs.SetCli,
Summary: "设置 Node.js 命令行", Tags: tags, Request: request.EnvironmentSlug{}},
Summary: "设置 Node.js 命令行", Tags: tags, Document: DescribeReq[request.EnvironmentSlug]()},
{Method: http.MethodGet, Path: "/api/environment/nodejs/{slug}/registry", Handler: environmentNodejs.GetRegistry,
Summary: "获取 Node.js 镜像源", Tags: tags, Request: request.EnvironmentSlug{}},
Summary: "获取 Node.js 镜像源", Tags: tags, Document: DescribeReq[request.EnvironmentSlug]()},
{Method: http.MethodPost, Path: "/api/environment/nodejs/{slug}/registry", Handler: environmentNodejs.SetRegistry,
Summary: "设置 Node.js 镜像源", Tags: tags, Request: request.EnvironmentRegistry{}},
Summary: "设置 Node.js 镜像源", Tags: tags, Document: DescribeReq[request.EnvironmentRegistry]()},
// PHP
{Method: http.MethodPost, Path: "/api/environment/php/{version}/set_cli", Handler: environmentPHP.SetCli,
Summary: "设置 PHP 命令行", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "设置 PHP 命令行", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodGet, Path: "/api/environment/php/{version}/phpinfo", Handler: environmentPHP.PHPInfo,
Summary: "获取 phpinfo", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "获取 phpinfo", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodGet, Path: "/api/environment/php/{version}/config", Handler: environmentPHP.GetConfig,
Summary: "获取 PHP 配置", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "获取 PHP 配置", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodPost, Path: "/api/environment/php/{version}/config", Handler: environmentPHP.UpdateConfig,
Summary: "更新 PHP 配置", Tags: tags, Request: request.EnvironmentPHPUpdateConfig{}},
Summary: "更新 PHP 配置", Tags: tags, Document: DescribeReq[request.EnvironmentPHPUpdateConfig]()},
{Method: http.MethodGet, Path: "/api/environment/php/{version}/fpm_config", Handler: environmentPHP.GetFPMConfig,
Summary: "获取 PHP-FPM 配置", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "获取 PHP-FPM 配置", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodPost, Path: "/api/environment/php/{version}/fpm_config", Handler: environmentPHP.UpdateFPMConfig,
Summary: "更新 PHP-FPM 配置", Tags: tags, Request: request.EnvironmentPHPUpdateConfig{}},
Summary: "更新 PHP-FPM 配置", Tags: tags, Document: DescribeReq[request.EnvironmentPHPUpdateConfig]()},
{Method: http.MethodGet, Path: "/api/environment/php/{version}/load", Handler: environmentPHP.Load,
Summary: "获取 PHP-FPM 负载", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "获取 PHP-FPM 负载", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodGet, Path: "/api/environment/php/{version}/log", Handler: environmentPHP.Log,
Summary: "获取 PHP 日志路径", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "获取 PHP 日志路径", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodGet, Path: "/api/environment/php/{version}/slow_log", Handler: environmentPHP.SlowLog,
Summary: "获取 PHP 慢日志路径", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "获取 PHP 慢日志路径", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodGet, Path: "/api/environment/php/{version}/modules", Handler: environmentPHP.ModuleList,
Summary: "PHP 扩展列表", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "PHP 扩展列表", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodPost, Path: "/api/environment/php/{version}/modules", Handler: environmentPHP.InstallModule,
Summary: "安装 PHP 扩展", Tags: tags, Request: request.EnvironmentPHPModule{}},
Summary: "安装 PHP 扩展", Tags: tags, Document: DescribeReq[request.EnvironmentPHPModule]()},
{Method: http.MethodDelete, Path: "/api/environment/php/{version}/modules", Handler: environmentPHP.UninstallModule,
Summary: "卸载 PHP 扩展", Tags: tags, Request: request.EnvironmentPHPModule{}},
Summary: "卸载 PHP 扩展", Tags: tags, Document: DescribeReq[request.EnvironmentPHPModule]()},
{Method: http.MethodGet, Path: "/api/environment/php/{version}/config_tune", Handler: environmentPHP.GetConfigTune,
Summary: "获取 PHP 配置调优", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "获取 PHP 配置调优", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodPost, Path: "/api/environment/php/{version}/config_tune", Handler: environmentPHP.UpdateConfigTune,
Summary: "更新 PHP 配置调优", Tags: tags, Request: request.EnvironmentPHPConfigTune{}},
Summary: "更新 PHP 配置调优", Tags: tags, Document: DescribeReq[request.EnvironmentPHPConfigTune]()},
{Method: http.MethodPost, Path: "/api/environment/php/{version}/clean_session", Handler: environmentPHP.CleanSession,
Summary: "清理 PHP Session", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "清理 PHP Session", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodGet, Path: "/api/environment/php/{version}/processes", Handler: environmentPHP.Processes,
Summary: "获取 PHP-FPM 进程列表", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "获取 PHP-FPM 进程列表", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodGet, Path: "/api/environment/php/{version}/opcache", Handler: environmentPHP.Opcache,
Summary: "获取 OPcache 状态", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "获取 OPcache 状态", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodPost, Path: "/api/environment/php/{version}/opcache/reset", Handler: environmentPHP.ResetOpcache,
Summary: "重置 OPcache", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "重置 OPcache", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodGet, Path: "/api/environment/php/{version}/composer", Handler: environmentPHP.Composer,
Summary: "获取 Composer 状态", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "获取 Composer 状态", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodPost, Path: "/api/environment/php/{version}/composer/install", Handler: environmentPHP.InstallComposer,
Summary: "安装 Composer", Tags: tags, Request: request.EnvironmentPHPVersion{}},
Summary: "安装 Composer", Tags: tags, Document: DescribeReq[request.EnvironmentPHPVersion]()},
{Method: http.MethodPost, Path: "/api/environment/php/{version}/composer/mirror", Handler: environmentPHP.SetComposerMirror,
Summary: "设置 Composer 镜像源", Tags: tags, Request: request.EnvironmentPHPComposerMirror{}},
Summary: "设置 Composer 镜像源", Tags: tags, Document: DescribeReq[request.EnvironmentPHPComposerMirror]()},
// Python
{Method: http.MethodPost, Path: "/api/environment/python/{slug}/set_cli", Handler: environmentPython.SetCli,
Summary: "设置 Python 命令行", Tags: tags, Request: request.EnvironmentSlug{}},
Summary: "设置 Python 命令行", Tags: tags, Document: DescribeReq[request.EnvironmentSlug]()},
{Method: http.MethodGet, Path: "/api/environment/python/{slug}/mirror", Handler: environmentPython.GetMirror,
Summary: "获取 Python 镜像源", Tags: tags, Request: request.EnvironmentSlug{}},
Summary: "获取 Python 镜像源", Tags: tags, Document: DescribeReq[request.EnvironmentSlug]()},
{Method: http.MethodPost, Path: "/api/environment/python/{slug}/mirror", Handler: environmentPython.SetMirror,
Summary: "设置 Python 镜像源", Tags: tags, Request: request.EnvironmentMirror{}},
Summary: "设置 Python 镜像源", Tags: tags, Document: DescribeReq[request.EnvironmentMirror]()},
// .NET
{Method: http.MethodPost, Path: "/api/environment/dotnet/{slug}/set_cli", Handler: environmentDotnet.SetCli,
Summary: "设置 .NET 命令行", Tags: tags, Request: request.EnvironmentSlug{}},
Summary: "设置 .NET 命令行", Tags: tags, Document: DescribeReq[request.EnvironmentSlug]()},
}
}
+16 -16
View File
@@ -14,22 +14,22 @@ func FileRoutes(fileService *service.FileService) Endpoints {
return Endpoints{
{Method: http.MethodPost, Path: "/api/file/create", Handler: file.Create,
Summary: "创建文件或目录", Tags: []string{"文件"},
Request: request.FileCreate{}},
Document: DescribeReq[request.FileCreate]()},
{Method: http.MethodGet, Path: "/api/file/content", Handler: file.Content,
Summary: "读取文件内容", Tags: []string{"文件"},
Request: request.FilePath{}},
Document: DescribeReq[request.FilePath]()},
{Method: http.MethodGet, Path: "/api/file/tail", Handler: file.Tail,
Summary: "反向分页读取日志", Tags: []string{"文件"},
Request: request.FileTail{}},
Document: DescribeReq[request.FileTail]()},
{Method: http.MethodPost, Path: "/api/file/save", Handler: file.Save,
Summary: "保存文件", Tags: []string{"文件"},
Request: request.FileSave{}},
Document: DescribeReq[request.FileSave]()},
{Method: http.MethodPost, Path: "/api/file/truncate", Handler: file.Truncate,
Summary: "截断文件", Tags: []string{"文件"},
Request: request.FilePath{}},
Document: DescribeReq[request.FilePath]()},
{Method: http.MethodPost, Path: "/api/file/delete", Handler: file.Delete,
Summary: "删除文件", Tags: []string{"文件"},
Request: request.FilePath{}},
Document: DescribeReq[request.FilePath]()},
{Method: http.MethodPost, Path: "/api/file/upload", Handler: file.Upload,
Summary: "上传文件", Tags: []string{"文件"}},
{Method: http.MethodPost, Path: "/api/file/exist", Handler: file.Exist,
@@ -40,35 +40,35 @@ func FileRoutes(fileService *service.FileService) Endpoints {
Summary: "复制文件", Tags: []string{"文件"}},
{Method: http.MethodGet, Path: "/api/file/download", Handler: file.Download,
Summary: "下载文件", Tags: []string{"文件"},
Request: request.FilePath{}},
Document: DescribeReq[request.FilePath]()},
{Method: http.MethodPost, Path: "/api/file/remote_download", Handler: file.RemoteDownload,
Summary: "远程下载文件", Tags: []string{"文件"},
Request: request.FileRemoteDownload{}},
Document: DescribeReq[request.FileRemoteDownload]()},
{Method: http.MethodGet, Path: "/api/file/info", Handler: file.Info,
Summary: "获取文件信息", Tags: []string{"文件"},
Request: request.FilePath{}},
Document: DescribeReq[request.FilePath]()},
{Method: http.MethodGet, Path: "/api/file/size", Handler: file.Size,
Summary: "计算文件或目录大小", Tags: []string{"文件"},
Request: request.FilePath{}},
Document: DescribeReq[request.FilePath]()},
{Method: http.MethodPost, Path: "/api/file/permission", Handler: file.Permission,
Summary: "设置文件权限", Tags: []string{"文件"},
Request: request.FilePermission{}},
Document: DescribeReq[request.FilePermission]()},
{Method: http.MethodPost, Path: "/api/file/compress", Handler: file.Compress,
Summary: "压缩文件", Tags: []string{"文件"},
Request: request.FileCompress{}},
Document: DescribeReq[request.FileCompress]()},
{Method: http.MethodPost, Path: "/api/file/un_compress", Handler: file.UnCompress,
Summary: "解压文件", Tags: []string{"文件"},
Request: request.FileUnCompress{}},
Document: DescribeReq[request.FileUnCompress]()},
{Method: http.MethodGet, Path: "/api/file/list", Handler: file.List,
Summary: "文件列表", Tags: []string{"文件"},
Request: request.FileList{}},
Document: DescribeReq[request.FileList]()},
{Method: http.MethodPost, Path: "/api/file/chunk/start", Handler: file.ChunkUploadStart,
Summary: "开始分块上传", Tags: []string{"文件"},
Request: request.ChunkUploadStart{}},
Document: DescribeReq[request.ChunkUploadStart]()},
{Method: http.MethodPost, Path: "/api/file/chunk/upload", Handler: file.ChunkUploadChunk,
Summary: "上传分块", Tags: []string{"文件"}},
{Method: http.MethodPost, Path: "/api/file/chunk/finish", Handler: file.ChunkUploadFinish,
Summary: "完成分块上传", Tags: []string{"文件"},
Request: request.ChunkUploadFinish{}},
Document: DescribeReq[request.ChunkUploadFinish]()},
}
}
+3 -3
View File
@@ -15,13 +15,13 @@ func FileShareRoutes(fileShareService *service.FileShareService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/file_share", Handler: svc.List,
Summary: "文件分享列表", Tags: []string{"文件"},
Response: service.Envelope[[]*biz.FileShare]{}},
Document: DescribeResp[service.Envelope[[]*biz.FileShare]]()},
{Method: http.MethodPost, Path: "/api/file_share", Handler: svc.Create,
Summary: "创建文件分享", Tags: []string{"文件"},
Request: request.FileShareCreate{}, Response: service.Envelope[biz.FileShare]{}},
Document: Describe[request.FileShareCreate, service.Envelope[biz.FileShare]]()},
{Method: http.MethodDelete, Path: "/api/file_share/{id}", Handler: svc.Delete,
Summary: "取消文件分享", Tags: []string{"文件"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
// 顶层免登录下载
{Method: http.MethodGet, Path: "/download/{token}", Handler: svc.Download},
}
+15 -15
View File
@@ -19,7 +19,7 @@ func FirewallRoutes(firewallScanService *service.FirewallScanService, firewallSe
Summary: "获取防火墙状态", Tags: []string{"防火墙"}},
{Method: http.MethodPost, Path: "/api/firewall/status", Handler: svc.UpdateStatus,
Summary: "设置防火墙状态", Tags: []string{"防火墙"},
Request: request.FirewallStatus{}},
Document: DescribeReq[request.FirewallStatus]()},
{Method: http.MethodGet, Path: "/api/firewall/rule", Handler: svc.GetRules,
Summary: "获取端口规则", Tags: []string{"防火墙"}},
{Method: http.MethodGet, Path: "/api/firewall/rule/port_usage", Handler: svc.GetPortUsage,
@@ -30,53 +30,53 @@ func FirewallRoutes(firewallScanService *service.FirewallScanService, firewallSe
Summary: "导入端口规则", Tags: []string{"防火墙"}},
{Method: http.MethodPost, Path: "/api/firewall/rule", Handler: svc.CreateRule,
Summary: "创建端口规则", Tags: []string{"防火墙"},
Request: request.FirewallRule{}},
Document: DescribeReq[request.FirewallRule]()},
{Method: http.MethodPut, Path: "/api/firewall/rule", Handler: svc.UpdateRule,
Summary: "更新端口规则", Tags: []string{"防火墙"},
Request: request.FirewallRuleUpdate{}},
Document: DescribeReq[request.FirewallRuleUpdate]()},
{Method: http.MethodDelete, Path: "/api/firewall/rule", Handler: svc.DeleteRule,
Summary: "删除端口规则", Tags: []string{"防火墙"},
Request: request.FirewallRule{}},
Document: DescribeReq[request.FirewallRule]()},
{Method: http.MethodGet, Path: "/api/firewall/ip_rule", Handler: svc.GetIPRules,
Summary: "获取 IP 规则", Tags: []string{"防火墙"}},
{Method: http.MethodPost, Path: "/api/firewall/ip_rule", Handler: svc.CreateIPRule,
Summary: "创建 IP 规则", Tags: []string{"防火墙"},
Request: request.FirewallIPRule{}},
Document: DescribeReq[request.FirewallIPRule]()},
{Method: http.MethodDelete, Path: "/api/firewall/ip_rule", Handler: svc.DeleteIPRule,
Summary: "删除 IP 规则", Tags: []string{"防火墙"},
Request: request.FirewallIPRule{}},
Document: DescribeReq[request.FirewallIPRule]()},
{Method: http.MethodGet, Path: "/api/firewall/forward", Handler: svc.GetForwards,
Summary: "获取端口转发", Tags: []string{"防火墙"}},
{Method: http.MethodPost, Path: "/api/firewall/forward", Handler: svc.CreateForward,
Summary: "创建端口转发", Tags: []string{"防火墙"},
Request: request.FirewallForward{}},
Document: DescribeReq[request.FirewallForward]()},
{Method: http.MethodDelete, Path: "/api/firewall/forward", Handler: svc.DeleteForward,
Summary: "删除端口转发", Tags: []string{"防火墙"},
Request: request.FirewallForward{}},
Document: DescribeReq[request.FirewallForward]()},
// /api/firewall/scan
{Method: http.MethodGet, Path: "/api/firewall/scan/setting", Handler: scan.GetSetting,
Summary: "获取扫描感知设置", Tags: []string{"防火墙"},
Response: service.Envelope[biz.ScanSetting]{}},
Document: DescribeResp[service.Envelope[biz.ScanSetting]]()},
{Method: http.MethodPost, Path: "/api/firewall/scan/setting", Handler: scan.UpdateSetting,
Summary: "更新扫描感知设置", Tags: []string{"防火墙"},
Request: request.FirewallScanSetting{}},
Document: DescribeReq[request.FirewallScanSetting]()},
{Method: http.MethodGet, Path: "/api/firewall/scan/interfaces", Handler: scan.GetInterfaces,
Summary: "获取可用网卡", Tags: []string{"防火墙"}},
{Method: http.MethodGet, Path: "/api/firewall/scan/summary", Handler: scan.GetSummary,
Summary: "获取扫描汇总", Tags: []string{"防火墙"},
Response: service.Envelope[biz.ScanSummary]{}},
Document: DescribeResp[service.Envelope[biz.ScanSummary]]()},
{Method: http.MethodGet, Path: "/api/firewall/scan/trend", Handler: scan.GetTrend,
Summary: "获取扫描趋势", Tags: []string{"防火墙"},
Response: service.Envelope[[]*biz.ScanDayTrend]{}},
Document: DescribeResp[service.Envelope[[]*biz.ScanDayTrend]]()},
{Method: http.MethodGet, Path: "/api/firewall/scan/top_ips", Handler: scan.GetTopSourceIPs,
Summary: "获取 Top 扫描源 IP", Tags: []string{"防火墙"},
Response: service.Envelope[[]*biz.ScanSourceRank]{}},
Document: DescribeResp[service.Envelope[[]*biz.ScanSourceRank]]()},
{Method: http.MethodGet, Path: "/api/firewall/scan/top_ports", Handler: scan.GetTopPorts,
Summary: "获取 Top 被扫描端口", Tags: []string{"防火墙"},
Response: service.Envelope[[]*biz.ScanPortRank]{}},
Document: DescribeResp[service.Envelope[[]*biz.ScanPortRank]]()},
{Method: http.MethodGet, Path: "/api/firewall/scan/events", Handler: scan.ListEvents,
Summary: "获取扫描事件列表", Tags: []string{"防火墙"},
Response: service.Envelope[service.Page[*biz.ScanEvent]]{}},
Document: DescribeResp[service.Envelope[service.Page[*biz.ScanEvent]]]()},
{Method: http.MethodPost, Path: "/api/firewall/scan/clear", Handler: scan.Clear,
Summary: "清空扫描数据", Tags: []string{"防火墙"}},
}
+2 -2
View File
@@ -14,7 +14,7 @@ func HomeRoutes(homeService *service.HomeService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/home/panel", Handler: svc.Panel, Summary: "获取面板基础信息", Tags: []string{"首页"}, Public: true},
{Method: http.MethodGet, Path: "/api/home/apps", Handler: svc.Apps, Summary: "获取首页展示应用", Tags: []string{"首页"}},
{Method: http.MethodPost, Path: "/api/home/current", Handler: svc.Current, Summary: "获取实时负载", Tags: []string{"首页"}, Request: request.HomeCurrent{}},
{Method: http.MethodPost, Path: "/api/home/current", Handler: svc.Current, Summary: "获取实时负载", Tags: []string{"首页"}, Document: DescribeReq[request.HomeCurrent]()},
{Method: http.MethodGet, Path: "/api/home/system_info", Handler: svc.SystemInfo, Summary: "获取系统信息", Tags: []string{"首页"}},
{Method: http.MethodGet, Path: "/api/home/count_info", Handler: svc.CountInfo, Summary: "获取统计信息", Tags: []string{"首页"}},
{Method: http.MethodGet, Path: "/api/home/installed_environment", Handler: svc.InstalledEnvironment, Summary: "获取已安装环境", Tags: []string{"首页"}},
@@ -22,7 +22,7 @@ func HomeRoutes(homeService *service.HomeService) Endpoints {
{Method: http.MethodGet, Path: "/api/home/update_info", Handler: svc.UpdateInfo, Summary: "获取更新信息", Tags: []string{"首页"}},
{Method: http.MethodPost, Path: "/api/home/update", Handler: svc.Update, Summary: "更新面板", Tags: []string{"首页"}},
{Method: http.MethodPost, Path: "/api/home/restart", Handler: svc.Restart, Summary: "重启面板", Tags: []string{"首页"}},
{Method: http.MethodGet, Path: "/api/home/top_processes", Handler: svc.TopProcesses, Summary: "获取占用最高进程", Tags: []string{"首页"}, Request: request.HomeTopProcesses{}},
{Method: http.MethodGet, Path: "/api/home/top_processes", Handler: svc.TopProcesses, Summary: "获取占用最高进程", Tags: []string{"首页"}, Document: DescribeReq[request.HomeTopProcesses]()},
{Method: http.MethodPost, Path: "/api/home/restart_server", Handler: svc.RestartServer, Summary: "重启服务器", Tags: []string{"首页"}},
{Method: http.MethodGet, Path: "/api/home/runtime_info", Handler: svc.RuntimeInfo, Summary: "获取运行时信息", Tags: []string{"首页"}},
{Method: http.MethodGet, Path: "/api/home/goroutines", Handler: svc.Goroutines, Summary: "获取协程堆栈", Tags: []string{"首页"}},
+2 -2
View File
@@ -12,8 +12,8 @@ func LogRoutes(logService *service.LogService) Endpoints {
svc := logService
return Endpoints{
{Method: http.MethodGet, Path: "/api/log/list", Handler: svc.List, Summary: "日志列表", Tags: []string{"日志"}, Request: request.LogList{}},
{Method: http.MethodGet, Path: "/api/log/dates", Handler: svc.Dates, Summary: "日志日期列表", Tags: []string{"日志"}, Request: request.LogDates{}},
{Method: http.MethodGet, Path: "/api/log/list", Handler: svc.List, Summary: "日志列表", Tags: []string{"日志"}, Document: DescribeReq[request.LogList]()},
{Method: http.MethodGet, Path: "/api/log/dates", Handler: svc.Dates, Summary: "日志日期列表", Tags: []string{"日志"}, Document: DescribeReq[request.LogDates]()},
{Method: http.MethodGet, Path: "/api/log/ssh", Handler: svc.SSH, Summary: "SSH 登录日志", Tags: []string{"日志"}},
}
}
+2 -2
View File
@@ -13,8 +13,8 @@ func MonitorRoutes(monitorService *service.MonitorService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/monitor/setting", Handler: svc.GetSetting, Summary: "获取监控设置", Tags: []string{"监控"}},
{Method: http.MethodPost, Path: "/api/monitor/setting", Handler: svc.UpdateSetting, Summary: "更新监控设置", Tags: []string{"监控"}, Request: request.MonitorSetting{}},
{Method: http.MethodPost, Path: "/api/monitor/setting", Handler: svc.UpdateSetting, Summary: "更新监控设置", Tags: []string{"监控"}, Document: DescribeReq[request.MonitorSetting]()},
{Method: http.MethodPost, Path: "/api/monitor/clear", Handler: svc.Clear, Summary: "清空监控数据", Tags: []string{"监控"}},
{Method: http.MethodGet, Path: "/api/monitor/list", Handler: svc.List, Summary: "监控数据列表", Tags: []string{"监控"}, Request: request.MonitorList{}},
{Method: http.MethodGet, Path: "/api/monitor/list", Handler: svc.List, Summary: "监控数据列表", Tags: []string{"监控"}, Document: DescribeReq[request.MonitorList]()},
}
}
+9 -9
View File
@@ -13,14 +13,14 @@ func NotifyRoutes(notifyService *service.NotifyService) Endpoints {
svc := notifyService
return Endpoints{
{Method: http.MethodGet, Path: "/api/notify/channel", Handler: svc.List, Summary: "通知渠道列表", Tags: []string{"通知"}, Request: request.Paginate{}, Response: service.Envelope[service.Page[*biz.NotifyChannel]]{}},
{Method: http.MethodGet, Path: "/api/notify/channel/all", Handler: svc.All, Summary: "全部通知渠道", Tags: []string{"通知"}, Response: service.Envelope[[]*biz.NotifyChannel]{}},
{Method: http.MethodPost, Path: "/api/notify/channel", Handler: svc.Create, Summary: "创建通知渠道", Tags: []string{"通知"}, Request: request.NotifyChannelCreate{}, Response: service.Envelope[biz.NotifyChannel]{}},
{Method: http.MethodGet, Path: "/api/notify/channel/{id}", Handler: svc.Get, Summary: "获取通知渠道", Tags: []string{"通知"}, Request: request.ID{}, Response: service.Envelope[biz.NotifyChannel]{}},
{Method: http.MethodPut, Path: "/api/notify/channel/{id}", Handler: svc.Update, Summary: "更新通知渠道", Tags: []string{"通知"}, Request: request.NotifyChannelUpdate{}},
{Method: http.MethodDelete, Path: "/api/notify/channel/{id}", Handler: svc.Delete, Summary: "删除通知渠道", Tags: []string{"通知"}, Request: request.ID{}},
{Method: http.MethodPost, Path: "/api/notify/channel/{id}/test", Handler: svc.Test, Summary: "测试通知渠道", Tags: []string{"通知"}, Request: request.ID{}},
{Method: http.MethodGet, Path: "/api/notify/setting", Handler: svc.GetSetting, Summary: "获取事件通知设置", Tags: []string{"通知"}, Response: service.Envelope[request.NotifySetting]{}},
{Method: http.MethodPost, Path: "/api/notify/setting", Handler: svc.UpdateSetting, Summary: "更新事件通知设置", Tags: []string{"通知"}, Request: request.NotifySetting{}},
{Method: http.MethodGet, Path: "/api/notify/channel", Handler: svc.List, Summary: "通知渠道列表", Tags: []string{"通知"}, Document: Describe[request.Paginate, service.Envelope[service.Page[*biz.NotifyChannel]]]()},
{Method: http.MethodGet, Path: "/api/notify/channel/all", Handler: svc.All, Summary: "全部通知渠道", Tags: []string{"通知"}, Document: DescribeResp[service.Envelope[[]*biz.NotifyChannel]]()},
{Method: http.MethodPost, Path: "/api/notify/channel", Handler: svc.Create, Summary: "创建通知渠道", Tags: []string{"通知"}, Document: Describe[request.NotifyChannelCreate, service.Envelope[biz.NotifyChannel]]()},
{Method: http.MethodGet, Path: "/api/notify/channel/{id}", Handler: svc.Get, Summary: "获取通知渠道", Tags: []string{"通知"}, Document: Describe[request.ID, service.Envelope[biz.NotifyChannel]]()},
{Method: http.MethodPut, Path: "/api/notify/channel/{id}", Handler: svc.Update, Summary: "更新通知渠道", Tags: []string{"通知"}, Document: DescribeReq[request.NotifyChannelUpdate]()},
{Method: http.MethodDelete, Path: "/api/notify/channel/{id}", Handler: svc.Delete, Summary: "删除通知渠道", Tags: []string{"通知"}, Document: DescribeReq[request.ID]()},
{Method: http.MethodPost, Path: "/api/notify/channel/{id}/test", Handler: svc.Test, Summary: "测试通知渠道", Tags: []string{"通知"}, Document: DescribeReq[request.ID]()},
{Method: http.MethodGet, Path: "/api/notify/setting", Handler: svc.GetSetting, Summary: "获取事件通知设置", Tags: []string{"通知"}, Document: DescribeResp[service.Envelope[request.NotifySetting]]()},
{Method: http.MethodPost, Path: "/api/notify/setting", Handler: svc.UpdateSetting, Summary: "更新事件通知设置", Tags: []string{"通知"}, Document: DescribeReq[request.NotifySetting]()},
}
}
+4 -4
View File
@@ -14,15 +14,15 @@ func ProcessRoutes(processService *service.ProcessService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/process", Handler: svc.List,
Summary: "进程列表", Tags: []string{"进程"},
Request: request.ProcessList{}},
Document: DescribeReq[request.ProcessList]()},
{Method: http.MethodGet, Path: "/api/process/detail", Handler: svc.Detail,
Summary: "进程详情", Tags: []string{"进程"},
Request: request.ProcessDetail{}},
Document: DescribeReq[request.ProcessDetail]()},
{Method: http.MethodPost, Path: "/api/process/kill", Handler: svc.Kill,
Summary: "结束进程", Tags: []string{"进程"},
Request: request.ProcessKill{}},
Document: DescribeReq[request.ProcessKill]()},
{Method: http.MethodPost, Path: "/api/process/signal", Handler: svc.Signal,
Summary: "向进程发送信号", Tags: []string{"进程"},
Request: request.ProcessSignal{}},
Document: DescribeReq[request.ProcessSignal]()},
}
}
+5 -5
View File
@@ -15,16 +15,16 @@ func ProjectRoutes(projectService *service.ProjectService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/project", Handler: svc.List,
Summary: "项目列表", Tags: []string{"项目"},
Request: request.Paginate{}, Response: service.Envelope[service.Page[*types.ProjectDetail]]{}},
Document: Describe[request.Paginate, service.Envelope[service.Page[*types.ProjectDetail]]]()},
{Method: http.MethodPost, Path: "/api/project", Handler: svc.Create,
Summary: "创建项目", Tags: []string{"项目"},
Request: request.ProjectCreate{}, Response: service.Envelope[types.ProjectDetail]{}},
Document: Describe[request.ProjectCreate, service.Envelope[types.ProjectDetail]]()},
{Method: http.MethodGet, Path: "/api/project/{id}", Handler: svc.Get,
Summary: "获取项目详情", Tags: []string{"项目"},
Request: request.ID{}, Response: service.Envelope[types.ProjectDetail]{}},
Document: Describe[request.ID, service.Envelope[types.ProjectDetail]]()},
{Method: http.MethodPut, Path: "/api/project/{id}", Handler: svc.Update,
Summary: "更新项目", Tags: []string{"项目"}, Request: request.ProjectUpdate{}},
Summary: "更新项目", Tags: []string{"项目"}, Document: DescribeReq[request.ProjectUpdate]()},
{Method: http.MethodDelete, Path: "/api/project/{id}", Handler: svc.Delete,
Summary: "删除项目", Tags: []string{"项目"}, Request: request.ID{}},
Summary: "删除项目", Tags: []string{"项目"}, Document: DescribeReq[request.ID]()},
}
}
+38 -17
View File
@@ -7,6 +7,7 @@ import (
"github.com/go-chi/chi/v5"
"github.com/google/wire"
"github.com/libtnb/validator"
"github.com/libtnb/validator/contrib/openapi"
"github.com/acepanel/panel/v3/internal/middleware"
@@ -130,17 +131,39 @@ type ThrottleRule struct {
Interval time.Duration
}
// Endpoint 声明一个 HTTP 端点:如何服务,以及(经 Request/Response 样本)如何生成文档
// 无 Request/Response 的端点(探针、WebSocket)不进 OpenAPI 文档。
// Documentation 将端点登记到 OpenAPI 生成器
type Documentation func(g *openapi.Generator, method, path, summary string, tags []string) error
// Describe 以请求与响应样本类型登记文档,响应固定 200。
func Describe[Request, Response any]() Documentation {
return func(g *openapi.Generator, method, path, summary string, tags []string) error {
return g.Add[Request](method, path,
openapi.WithSummary(summary),
openapi.WithTags(tags...),
openapi.WithResponse[Response](http.StatusOK),
)
}
}
// DescribeReq 登记只有请求体的端点。
func DescribeReq[Request any]() Documentation {
return Describe[Request, openapi.NoBody]()
}
// DescribeResp 登记只有响应体的端点。
func DescribeResp[Response any]() Documentation {
return Describe[openapi.NoBody, Response]()
}
// Endpoint 声明一个 HTTP 端点:如何服务,以及(经 Document)如何生成文档。
// 无 Document 的端点(探针、WebSocket)不进 OpenAPI 文档。
type Endpoint struct {
Method string
Path string // 绝对路径,如 "/api/users"
Handler http.HandlerFunc
Summary string
Tags []string
Request any // request.* 样本
Response any // service.Envelope[...] 样本
Status int
Document Documentation
Public bool // 登录白名单(MustLogin 放行)
Throttle *ThrottleRule // 非 nil 时端点级限流
}
@@ -181,24 +204,22 @@ func PublicPaths(groups []Endpoints) []string {
return paths
}
// SpecJSON 从每个带文档样本的端点组装 OpenAPI 3 文档。
func SpecJSON(groups []Endpoints, title string) ([]byte, error) {
g := openapi.New(title, buildVersion(),
openapi.WithType(time.Time{}, &openapi.Schema{Type: "string", Format: "date-time"}),
// SpecJSON 从每个带文档的端点组装 OpenAPI 3 文档。
func SpecJSON(groups []Endpoints, title string, v *validator.Validator) ([]byte, error) {
g, err := openapi.New(title, buildVersion(),
openapi.WithValidator(v),
openapi.WithSchema[time.Time](&openapi.Schema{Type: "string", Format: "date-time"}),
)
if err != nil {
return nil, err
}
for _, endpoints := range groups {
for _, e := range endpoints {
if e.Request == nil && e.Response == nil {
if e.Document == nil {
continue
}
if err := g.Add(e.Method, e.Path, openapi.Op{
Summary: e.Summary,
Tags: e.Tags,
Request: e.Request,
Response: e.Response,
Status: e.Status,
}); err != nil {
if err = e.Document(g, e.Method, e.Path, e.Summary, e.Tags); err != nil {
return nil, err
}
}
+27
View File
@@ -0,0 +1,27 @@
package route
import (
"testing"
"github.com/libtnb/validator"
"github.com/acepanel/panel/v3/internal/rule"
)
// TestSpecJSON 全量端点文档生成防线:任何端点的 Document 定义或 validate tag
// 与 OpenAPI 生成器不兼容都会在此暴露,而不是等到 debug 模式启动时才炸。
func TestSpecJSON(t *testing.T) {
v := validator.MustNew(
validator.WithStrictRequired(),
validator.WithRules(rule.Rules()...),
validator.WithFallibleRules(rule.FallibleRules(nil)...),
)
spec, err := SpecJSON(NewEndpoints(&Services{}), "AcePanel", v)
if err != nil {
t.Fatal(err)
}
if len(spec) == 0 {
t.Fatal("生成的 OpenAPI 文档为空")
}
}
+1 -1
View File
@@ -13,6 +13,6 @@ func SafeRoutes(safeService *service.SafeService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/safe/ping", Handler: svc.GetPingStatus, Summary: "获取 Ping 状态", Tags: []string{"安全"}},
{Method: http.MethodPost, Path: "/api/safe/ping", Handler: svc.UpdatePingStatus, Summary: "更新 Ping 状态", Tags: []string{"安全"}, Request: request.SafeUpdatePingStatus{}},
{Method: http.MethodPost, Path: "/api/safe/ping", Handler: svc.UpdatePingStatus, Summary: "更新 Ping 状态", Tags: []string{"安全"}, Document: DescribeReq[request.SafeUpdatePingStatus]()},
}
}
+3 -3
View File
@@ -13,10 +13,10 @@ func SettingRoutes(settingService *service.SettingService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/setting", Handler: svc.Get, Summary: "获取面板设置", Tags: []string{"设置"}},
{Method: http.MethodPost, Path: "/api/setting", Handler: svc.Update, Summary: "更新面板设置", Tags: []string{"设置"}, Request: request.SettingPanel{}},
{Method: http.MethodPost, Path: "/api/setting/cert", Handler: svc.UpdateCert, Summary: "更新面板证书", Tags: []string{"设置"}, Request: request.SettingCert{}},
{Method: http.MethodPost, Path: "/api/setting", Handler: svc.Update, Summary: "更新面板设置", Tags: []string{"设置"}, Document: DescribeReq[request.SettingPanel]()},
{Method: http.MethodPost, Path: "/api/setting/cert", Handler: svc.UpdateCert, Summary: "更新面板证书", Tags: []string{"设置"}, Document: DescribeReq[request.SettingCert]()},
{Method: http.MethodPost, Path: "/api/setting/obtain_cert", Handler: svc.ObtainCert, Summary: "签发面板证书", Tags: []string{"设置"}},
{Method: http.MethodGet, Path: "/api/setting/memo", Handler: svc.GetMemo, Summary: "获取便签", Tags: []string{"设置"}},
{Method: http.MethodPost, Path: "/api/setting/memo", Handler: svc.UpdateMemo, Summary: "更新便签", Tags: []string{"设置"}, Request: request.SettingMemo{}},
{Method: http.MethodPost, Path: "/api/setting/memo", Handler: svc.UpdateMemo, Summary: "更新便签", Tags: []string{"设置"}, Document: DescribeReq[request.SettingMemo]()},
}
}
+7 -7
View File
@@ -15,24 +15,24 @@ func SSHRoutes(sshService *service.SSHService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/ssh", Handler: svc.List,
Summary: "SSH 列表", Tags: []string{"SSH"},
Request: request.Paginate{}, Response: service.Envelope[service.Page[*biz.SSH]]{}},
Document: Describe[request.Paginate, service.Envelope[service.Page[*biz.SSH]]]()},
{Method: http.MethodPost, Path: "/api/ssh", Handler: svc.Create,
Summary: "创建 SSH", Tags: []string{"SSH"},
Request: request.SSHCreate{}},
Document: DescribeReq[request.SSHCreate]()},
{Method: http.MethodPut, Path: "/api/ssh/{id}", Handler: svc.Update,
Summary: "更新 SSH", Tags: []string{"SSH"},
Request: request.SSHUpdate{}},
Document: DescribeReq[request.SSHUpdate]()},
{Method: http.MethodGet, Path: "/api/ssh/{id}", Handler: svc.Get,
Summary: "获取 SSH", Tags: []string{"SSH"},
Request: request.ID{}, Response: service.Envelope[biz.SSH]{}},
Document: Describe[request.ID, service.Envelope[biz.SSH]]()},
{Method: http.MethodDelete, Path: "/api/ssh/{id}", Handler: svc.Delete,
Summary: "删除 SSH", Tags: []string{"SSH"},
Request: request.ID{}},
Document: DescribeReq[request.ID]()},
{Method: http.MethodGet, Path: "/api/ssh/{id}/file", Handler: svc.ListFiles,
Summary: "浏览主机文件", Tags: []string{"SSH"},
Request: request.SSHFile{}, Response: service.Envelope[[]*biz.SSHFileInfo]{}},
Document: Describe[request.SSHFile, service.Envelope[[]*biz.SSHFileInfo]]()},
{Method: http.MethodPost, Path: "/api/ssh/{id}/mkdir", Handler: svc.Mkdir,
Summary: "创建主机目录", Tags: []string{"SSH"},
Request: request.SSHFile{}},
Document: DescribeReq[request.SSHFile]()},
}
}
+9 -9
View File
@@ -14,30 +14,30 @@ func SystemctlRoutes(systemctlService *service.SystemctlService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/systemctl/status", Handler: svc.Status,
Summary: "获取服务运行状态", Tags: []string{"系统服务"},
Request: request.SystemctlService{}},
Document: DescribeReq[request.SystemctlService]()},
{Method: http.MethodGet, Path: "/api/systemctl/is_enabled", Handler: svc.IsEnabled,
Summary: "获取服务自启状态", Tags: []string{"系统服务"},
Request: request.SystemctlService{}},
Document: DescribeReq[request.SystemctlService]()},
{Method: http.MethodPost, Path: "/api/systemctl/enable", Handler: svc.Enable,
Summary: "启用服务自启", Tags: []string{"系统服务"},
Request: request.SystemctlService{}},
Document: DescribeReq[request.SystemctlService]()},
{Method: http.MethodPost, Path: "/api/systemctl/disable", Handler: svc.Disable,
Summary: "禁用服务自启", Tags: []string{"系统服务"},
Request: request.SystemctlService{}},
Document: DescribeReq[request.SystemctlService]()},
{Method: http.MethodPost, Path: "/api/systemctl/restart", Handler: svc.Restart,
Summary: "重启服务", Tags: []string{"系统服务"},
Request: request.SystemctlService{}},
Document: DescribeReq[request.SystemctlService]()},
{Method: http.MethodPost, Path: "/api/systemctl/reload", Handler: svc.Reload,
Summary: "重载服务", Tags: []string{"系统服务"},
Request: request.SystemctlService{}},
Document: DescribeReq[request.SystemctlService]()},
{Method: http.MethodPost, Path: "/api/systemctl/start", Handler: svc.Start,
Summary: "启动服务", Tags: []string{"系统服务"},
Request: request.SystemctlService{}},
Document: DescribeReq[request.SystemctlService]()},
{Method: http.MethodPost, Path: "/api/systemctl/stop", Handler: svc.Stop,
Summary: "停止服务", Tags: []string{"系统服务"},
Request: request.SystemctlService{}},
Document: DescribeReq[request.SystemctlService]()},
{Method: http.MethodPost, Path: "/api/systemctl/clear_log", Handler: svc.ClearLog,
Summary: "清空服务日志", Tags: []string{"系统服务"},
Request: request.SystemctlService{}},
Document: DescribeReq[request.SystemctlService]()},
}
}
+7 -7
View File
@@ -17,23 +17,23 @@ func TamperRoutes(tamperService *service.TamperService) Endpoints {
{Method: http.MethodGet, Path: "/api/tamper/setting", Handler: svc.GetSetting,
Summary: "获取设置", Tags: []string{"防篡改"}},
{Method: http.MethodPost, Path: "/api/tamper/setting", Handler: svc.SaveSetting,
Summary: "保存设置", Tags: []string{"防篡改"}, Request: request.TamperSetting{}},
Summary: "保存设置", Tags: []string{"防篡改"}, Document: DescribeReq[request.TamperSetting]()},
{Method: http.MethodPost, Path: "/api/tamper/activate_ebpf", Handler: svc.ActivateEBPF,
Summary: "激活 eBPF 并重启", Tags: []string{"防篡改"}},
{Method: http.MethodPost, Path: "/api/tamper/check_paths", Handler: svc.CheckPaths,
Summary: "查询路径保护状态", Tags: []string{"防篡改"}, Request: request.TamperCheckPaths{}},
Summary: "查询路径保护状态", Tags: []string{"防篡改"}, Document: DescribeReq[request.TamperCheckPaths]()},
{Method: http.MethodPost, Path: "/api/tamper/protect", Handler: svc.Protect,
Summary: "切换路径保护", Tags: []string{"防篡改"}, Request: request.TamperProtect{}},
Summary: "切换路径保护", Tags: []string{"防篡改"}, Document: DescribeReq[request.TamperProtect]()},
{Method: http.MethodGet, Path: "/api/tamper/rule", Handler: svc.ListRules,
Summary: "规则列表", Tags: []string{"防篡改"}, Request: request.Paginate{}},
Summary: "规则列表", Tags: []string{"防篡改"}, Document: DescribeReq[request.Paginate]()},
{Method: http.MethodPost, Path: "/api/tamper/rule", Handler: svc.CreateRule,
Summary: "新增规则", Tags: []string{"防篡改"}, Request: request.TamperRuleCreate{}},
Summary: "新增规则", Tags: []string{"防篡改"}, Document: DescribeReq[request.TamperRuleCreate]()},
{Method: http.MethodPut, Path: "/api/tamper/rule/{id}", Handler: svc.UpdateRule,
Summary: "更新规则", Tags: []string{"防篡改"}, Request: request.TamperRuleUpdate{}},
Summary: "更新规则", Tags: []string{"防篡改"}, Document: DescribeReq[request.TamperRuleUpdate]()},
{Method: http.MethodDelete, Path: "/api/tamper/rule/{id}", Handler: svc.DeleteRule,
Summary: "删除规则", Tags: []string{"防篡改"}},
{Method: http.MethodGet, Path: "/api/tamper/log", Handler: svc.ListLogs,
Summary: "拦截日志", Tags: []string{"防篡改"}, Request: request.Paginate{}},
Summary: "拦截日志", Tags: []string{"防篡改"}, Document: DescribeReq[request.Paginate]()},
{Method: http.MethodDelete, Path: "/api/tamper/log", Handler: svc.ClearLogs,
Summary: "清空日志", Tags: []string{"防篡改"}},
}
+4 -4
View File
@@ -14,9 +14,9 @@ func TaskRoutes(taskService *service.TaskService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/task/status", Handler: svc.Status, Summary: "获取任务运行状态", Tags: []string{"任务"}},
{Method: http.MethodGet, Path: "/api/task", Handler: svc.List, Summary: "获取任务列表", Tags: []string{"任务"}, Request: request.Paginate{}, Response: service.Envelope[service.Page[*biz.Task]]{}},
{Method: http.MethodGet, Path: "/api/task/{id}", Handler: svc.Get, Summary: "获取任务详情", Tags: []string{"任务"}, Request: request.ID{}, Response: service.Envelope[biz.Task]{}},
{Method: http.MethodDelete, Path: "/api/task/{id}", Handler: svc.Delete, Summary: "删除任务", Tags: []string{"任务"}, Request: request.ID{}},
{Method: http.MethodPost, Path: "/api/task/{id}/cancel", Handler: svc.Cancel, Summary: "取消任务", Tags: []string{"任务"}, Request: request.ID{}},
{Method: http.MethodGet, Path: "/api/task", Handler: svc.List, Summary: "获取任务列表", Tags: []string{"任务"}, Document: Describe[request.Paginate, service.Envelope[service.Page[*biz.Task]]]()},
{Method: http.MethodGet, Path: "/api/task/{id}", Handler: svc.Get, Summary: "获取任务详情", Tags: []string{"任务"}, Document: Describe[request.ID, service.Envelope[biz.Task]]()},
{Method: http.MethodDelete, Path: "/api/task/{id}", Handler: svc.Delete, Summary: "删除任务", Tags: []string{"任务"}, Document: DescribeReq[request.ID]()},
{Method: http.MethodPost, Path: "/api/task/{id}/cancel", Handler: svc.Cancel, Summary: "取消任务", Tags: []string{"任务"}, Document: DescribeReq[request.ID]()},
}
}
+3 -3
View File
@@ -13,8 +13,8 @@ func TemplateRoutes(templateService *service.TemplateService) Endpoints {
return Endpoints{
{Method: http.MethodGet, Path: "/api/template", Handler: svc.List, Summary: "模板列表", Tags: []string{"模板"}},
{Method: http.MethodGet, Path: "/api/template/{slug}", Handler: svc.Get, Summary: "获取模板", Tags: []string{"模板"}, Request: request.TemplateSlug{}},
{Method: http.MethodPost, Path: "/api/template", Handler: svc.Create, Summary: "使用模板创建编排", Tags: []string{"模板"}, Request: request.TemplateCreate{}},
{Method: http.MethodPost, Path: "/api/template/{slug}/callback", Handler: svc.Callback, Summary: "模板下载回调", Tags: []string{"模板"}, Request: request.TemplateSlug{}},
{Method: http.MethodGet, Path: "/api/template/{slug}", Handler: svc.Get, Summary: "获取模板", Tags: []string{"模板"}, Document: DescribeReq[request.TemplateSlug]()},
{Method: http.MethodPost, Path: "/api/template", Handler: svc.Create, Summary: "使用模板创建编排", Tags: []string{"模板"}, Document: DescribeReq[request.TemplateCreate]()},
{Method: http.MethodPost, Path: "/api/template/{slug}/callback", Handler: svc.Callback, Summary: "模板下载回调", Tags: []string{"模板"}, Document: DescribeReq[request.TemplateSlug]()},
}
}
+11 -11
View File
@@ -18,25 +18,25 @@ func UserRoutes(userPasskeyService *service.UserPasskeyService, userService *ser
// 认证
{Method: http.MethodGet, Path: "/api/user/key", Handler: svc.GetKey, Summary: "获取登录公钥", Tags: []string{"用户"}, Public: true},
{Method: http.MethodGet, Path: "/api/user/captcha", Handler: svc.GetCaptcha, Summary: "获取登录验证码", Tags: []string{"用户"}, Public: true},
{Method: http.MethodPost, Path: "/api/user/login", Handler: svc.Login, Summary: "登录", Tags: []string{"用户"}, Request: request.UserLogin{}, Public: true, Throttle: &ThrottleRule{Tokens: 5, Interval: time.Minute}},
{Method: http.MethodPost, Path: "/api/user/login", Handler: svc.Login, Summary: "登录", Tags: []string{"用户"}, Document: DescribeReq[request.UserLogin](), Public: true, Throttle: &ThrottleRule{Tokens: 5, Interval: time.Minute}},
{Method: http.MethodPost, Path: "/api/user/logout", Handler: svc.Logout, Summary: "登出", Tags: []string{"用户"}, Public: true},
{Method: http.MethodGet, Path: "/api/user/is_login", Handler: svc.IsLogin, Summary: "是否已登录", Tags: []string{"用户"}, Public: true},
{Method: http.MethodGet, Path: "/api/user/is_2fa", Handler: svc.IsTwoFA, Summary: "是否开启两步验证", Tags: []string{"用户"}, Request: request.UserIsTwoFA{}, Public: true},
{Method: http.MethodGet, Path: "/api/user/is_2fa", Handler: svc.IsTwoFA, Summary: "是否开启两步验证", Tags: []string{"用户"}, Document: DescribeReq[request.UserIsTwoFA](), Public: true},
{Method: http.MethodGet, Path: "/api/user/info", Handler: svc.Info, Summary: "获取当前用户信息", Tags: []string{"用户"}},
// 通行密钥
{Method: http.MethodGet, Path: "/api/user/passkey/enabled", Handler: passkey.Enabled, Summary: "是否启用通行密钥", Tags: []string{"通行密钥"}, Public: true},
{Method: http.MethodPost, Path: "/api/user/passkey/register", Handler: passkey.BeginRegister, Summary: "开始注册通行密钥", Tags: []string{"通行密钥"}},
{Method: http.MethodPut, Path: "/api/user/passkey/register", Handler: passkey.FinishRegister, Summary: "完成注册通行密钥", Tags: []string{"通行密钥"}, Response: service.Envelope[biz.UserPasskey]{}},
{Method: http.MethodPut, Path: "/api/user/passkey/register", Handler: passkey.FinishRegister, Summary: "完成注册通行密钥", Tags: []string{"通行密钥"}, Document: DescribeResp[service.Envelope[biz.UserPasskey]]()},
{Method: http.MethodPost, Path: "/api/user/passkey/login", Handler: passkey.BeginLogin, Summary: "开始通行密钥登录", Tags: []string{"通行密钥"}, Public: true, Throttle: &ThrottleRule{Tokens: 5, Interval: time.Minute}},
{Method: http.MethodPut, Path: "/api/user/passkey/login", Handler: passkey.FinishLogin, Summary: "完成通行密钥登录", Tags: []string{"通行密钥"}, Public: true},
// 用户管理
{Method: http.MethodGet, Path: "/api/users", Handler: svc.List, Summary: "获取用户列表", Tags: []string{"用户"}, Request: request.Paginate{}, Response: service.Envelope[service.Page[*biz.User]]{}},
{Method: http.MethodPost, Path: "/api/users", Handler: svc.Create, Summary: "创建用户", Tags: []string{"用户"}, Request: request.UserCreate{}, Response: service.Envelope[biz.User]{}},
{Method: http.MethodPost, Path: "/api/users/{id}/username", Handler: svc.UpdateUsername, Summary: "修改用户名", Tags: []string{"用户"}, Request: request.UserUpdateUsername{}},
{Method: http.MethodPost, Path: "/api/users/{id}/password", Handler: svc.UpdatePassword, Summary: "修改密码", Tags: []string{"用户"}, Request: request.UserUpdatePassword{}},
{Method: http.MethodPost, Path: "/api/users/{id}/email", Handler: svc.UpdateEmail, Summary: "修改邮箱", Tags: []string{"用户"}, Request: request.UserUpdateEmail{}},
{Method: http.MethodGet, Path: "/api/users/{id}/2fa", Handler: svc.GenerateTwoFA, Summary: "生成两步验证密钥", Tags: []string{"用户"}, Request: request.UserID{}},
{Method: http.MethodPost, Path: "/api/users/{id}/2fa", Handler: svc.UpdateTwoFA, Summary: "更新两步验证", Tags: []string{"用户"}, Request: request.UserUpdateTwoFA{}},
{Method: http.MethodDelete, Path: "/api/users/{id}", Handler: svc.Delete, Summary: "删除用户", Tags: []string{"用户"}, Request: request.UserID{}},
{Method: http.MethodGet, Path: "/api/users", Handler: svc.List, Summary: "获取用户列表", Tags: []string{"用户"}, Document: Describe[request.Paginate, service.Envelope[service.Page[*biz.User]]]()},
{Method: http.MethodPost, Path: "/api/users", Handler: svc.Create, Summary: "创建用户", Tags: []string{"用户"}, Document: Describe[request.UserCreate, service.Envelope[biz.User]]()},
{Method: http.MethodPost, Path: "/api/users/{id}/username", Handler: svc.UpdateUsername, Summary: "修改用户名", Tags: []string{"用户"}, Document: DescribeReq[request.UserUpdateUsername]()},
{Method: http.MethodPost, Path: "/api/users/{id}/password", Handler: svc.UpdatePassword, Summary: "修改密码", Tags: []string{"用户"}, Document: DescribeReq[request.UserUpdatePassword]()},
{Method: http.MethodPost, Path: "/api/users/{id}/email", Handler: svc.UpdateEmail, Summary: "修改邮箱", Tags: []string{"用户"}, Document: DescribeReq[request.UserUpdateEmail]()},
{Method: http.MethodGet, Path: "/api/users/{id}/2fa", Handler: svc.GenerateTwoFA, Summary: "生成两步验证密钥", Tags: []string{"用户"}, Document: DescribeReq[request.UserID]()},
{Method: http.MethodPost, Path: "/api/users/{id}/2fa", Handler: svc.UpdateTwoFA, Summary: "更新两步验证", Tags: []string{"用户"}, Document: DescribeReq[request.UserUpdateTwoFA]()},
{Method: http.MethodDelete, Path: "/api/users/{id}", Handler: svc.Delete, Summary: "删除用户", Tags: []string{"用户"}, Document: DescribeReq[request.UserID]()},
}
}
+2 -2
View File
@@ -13,8 +13,8 @@ func UserPasskeyRoutes(userPasskeyService *service.UserPasskeyService) Endpoints
svc := userPasskeyService
return Endpoints{
{Method: http.MethodGet, Path: "/api/user_passkeys", Handler: svc.List, Summary: "获取通行密钥列表", Tags: []string{"通行密钥"}, Request: request.UserPasskeyList{}, Response: service.Envelope[service.Page[*biz.UserPasskey]]{}},
{Method: http.MethodGet, Path: "/api/user_passkeys", Handler: svc.List, Summary: "获取通行密钥列表", Tags: []string{"通行密钥"}, Document: Describe[request.UserPasskeyList, service.Envelope[service.Page[*biz.UserPasskey]]]()},
{Method: http.MethodGet, Path: "/api/user_passkeys/supported", Handler: svc.Supported, Summary: "是否支持通行密钥", Tags: []string{"通行密钥"}},
{Method: http.MethodDelete, Path: "/api/user_passkeys/{id}", Handler: svc.Delete, Summary: "删除通行密钥", Tags: []string{"通行密钥"}, Request: request.UserPasskeyDelete{}},
{Method: http.MethodDelete, Path: "/api/user_passkeys/{id}", Handler: svc.Delete, Summary: "删除通行密钥", Tags: []string{"通行密钥"}, Document: DescribeReq[request.UserPasskeyDelete]()},
}
}
+4 -4
View File
@@ -13,9 +13,9 @@ func UserTokenRoutes(userTokenService *service.UserTokenService) Endpoints {
svc := userTokenService
return Endpoints{
{Method: http.MethodGet, Path: "/api/user_tokens", Handler: svc.List, Summary: "获取用户令牌列表", Tags: []string{"用户令牌"}, Request: request.UserTokenList{}, Response: service.Envelope[service.Page[*biz.UserToken]]{}},
{Method: http.MethodPost, Path: "/api/user_tokens", Handler: svc.Create, Summary: "创建用户令牌", Tags: []string{"用户令牌"}, Request: request.UserTokenCreate{}, Response: service.Envelope[biz.UserToken]{}},
{Method: http.MethodPut, Path: "/api/user_tokens/{id}", Handler: svc.Update, Summary: "更新用户令牌", Tags: []string{"用户令牌"}, Request: request.UserTokenUpdate{}, Response: service.Envelope[biz.UserToken]{}},
{Method: http.MethodDelete, Path: "/api/user_tokens/{id}", Handler: svc.Delete, Summary: "删除用户令牌", Tags: []string{"用户令牌"}, Request: request.ID{}},
{Method: http.MethodGet, Path: "/api/user_tokens", Handler: svc.List, Summary: "获取用户令牌列表", Tags: []string{"用户令牌"}, Document: Describe[request.UserTokenList, service.Envelope[service.Page[*biz.UserToken]]]()},
{Method: http.MethodPost, Path: "/api/user_tokens", Handler: svc.Create, Summary: "创建用户令牌", Tags: []string{"用户令牌"}, Document: Describe[request.UserTokenCreate, service.Envelope[biz.UserToken]]()},
{Method: http.MethodPut, Path: "/api/user_tokens/{id}", Handler: svc.Update, Summary: "更新用户令牌", Tags: []string{"用户令牌"}, Document: Describe[request.UserTokenUpdate, service.Envelope[biz.UserToken]]()},
{Method: http.MethodDelete, Path: "/api/user_tokens/{id}", Handler: svc.Delete, Summary: "删除用户令牌", Tags: []string{"用户令牌"}, Document: DescribeReq[request.ID]()},
}
}
+5 -5
View File
@@ -13,11 +13,11 @@ func WebHookRoutes(webHookService *service.WebHookService) Endpoints {
svc := webHookService
return Endpoints{
{Method: http.MethodGet, Path: "/api/webhook", Handler: svc.List, Summary: "WebHook 列表", Tags: []string{"WebHook"}, Request: request.Paginate{}, Response: service.Envelope[service.Page[*biz.WebHook]]{}},
{Method: http.MethodPost, Path: "/api/webhook", Handler: svc.Create, Summary: "创建 WebHook", Tags: []string{"WebHook"}, Request: request.WebHookCreate{}, Response: service.Envelope[biz.WebHook]{}},
{Method: http.MethodPut, Path: "/api/webhook/{id}", Handler: svc.Update, Summary: "更新 WebHook", Tags: []string{"WebHook"}, Request: request.WebHookUpdate{}},
{Method: http.MethodGet, Path: "/api/webhook/{id}", Handler: svc.Get, Summary: "获取 WebHook", Tags: []string{"WebHook"}, Request: request.ID{}, Response: service.Envelope[biz.WebHook]{}},
{Method: http.MethodDelete, Path: "/api/webhook/{id}", Handler: svc.Delete, Summary: "删除 WebHook", Tags: []string{"WebHook"}, Request: request.ID{}},
{Method: http.MethodGet, Path: "/api/webhook", Handler: svc.List, Summary: "WebHook 列表", Tags: []string{"WebHook"}, Document: Describe[request.Paginate, service.Envelope[service.Page[*biz.WebHook]]]()},
{Method: http.MethodPost, Path: "/api/webhook", Handler: svc.Create, Summary: "创建 WebHook", Tags: []string{"WebHook"}, Document: Describe[request.WebHookCreate, service.Envelope[biz.WebHook]]()},
{Method: http.MethodPut, Path: "/api/webhook/{id}", Handler: svc.Update, Summary: "更新 WebHook", Tags: []string{"WebHook"}, Document: DescribeReq[request.WebHookUpdate]()},
{Method: http.MethodGet, Path: "/api/webhook/{id}", Handler: svc.Get, Summary: "获取 WebHook", Tags: []string{"WebHook"}, Document: Describe[request.ID, service.Envelope[biz.WebHook]]()},
{Method: http.MethodDelete, Path: "/api/webhook/{id}", Handler: svc.Delete, Summary: "删除 WebHook", Tags: []string{"WebHook"}, Document: DescribeReq[request.ID]()},
// 顶层回调
{Method: http.MethodGet, Path: "/webhook/{key}", Handler: svc.Call},
{Method: http.MethodPost, Path: "/webhook/{key}", Handler: svc.Call},
+14 -14
View File
@@ -19,36 +19,36 @@ func WebsiteRoutes(websiteService *service.WebsiteService) Endpoints {
{Method: http.MethodGet, Path: "/api/website/default_config", Handler: svc.GetDefaultConfig,
Summary: "获取默认配置", Tags: []string{"网站"}},
{Method: http.MethodPost, Path: "/api/website/default_config", Handler: svc.UpdateDefaultConfig,
Summary: "保存默认配置", Tags: []string{"网站"}, Request: request.WebsiteDefaultConfig{}},
Summary: "保存默认配置", Tags: []string{"网站"}, Document: DescribeReq[request.WebsiteDefaultConfig]()},
{Method: http.MethodGet, Path: "/api/website/default_site", Handler: svc.GetDefaultSite,
Summary: "获取默认站点", Tags: []string{"网站"}},
{Method: http.MethodPost, Path: "/api/website/default_site", Handler: svc.UpdateDefaultSite,
Summary: "设置默认站点", Tags: []string{"网站"}, Request: request.WebsiteDefaultSite{}},
Summary: "设置默认站点", Tags: []string{"网站"}, Document: DescribeReq[request.WebsiteDefaultSite]()},
{Method: http.MethodPost, Path: "/api/website/cert", Handler: svc.UpdateCert,
Summary: "更新证书", Tags: []string{"网站"}, Request: request.WebsiteUpdateCert{}},
Summary: "更新证书", Tags: []string{"网站"}, Document: DescribeReq[request.WebsiteUpdateCert]()},
{Method: http.MethodGet, Path: "/api/website", Handler: svc.List,
Summary: "网站列表", Tags: []string{"网站"},
Request: request.WebsiteList{}, Response: service.Envelope[service.Page[*biz.Website]]{}},
Document: Describe[request.WebsiteList, service.Envelope[service.Page[*biz.Website]]]()},
{Method: http.MethodPost, Path: "/api/website", Handler: svc.Create,
Summary: "创建网站", Tags: []string{"网站"}, Request: request.WebsiteCreate{}},
Summary: "创建网站", Tags: []string{"网站"}, Document: DescribeReq[request.WebsiteCreate]()},
{Method: http.MethodGet, Path: "/api/website/{id}", Handler: svc.Get,
Summary: "获取网站配置", Tags: []string{"网站"},
Request: request.ID{}, Response: service.Envelope[types.WebsiteSetting]{}},
Document: Describe[request.ID, service.Envelope[types.WebsiteSetting]]()},
{Method: http.MethodPut, Path: "/api/website/{id}", Handler: svc.Update,
Summary: "保存网站配置", Tags: []string{"网站"}, Request: request.WebsiteUpdate{}},
Summary: "保存网站配置", Tags: []string{"网站"}, Document: DescribeReq[request.WebsiteUpdate]()},
{Method: http.MethodPost, Path: "/api/website/{id}/switch_type", Handler: svc.SwitchType,
Summary: "切换网站类型", Tags: []string{"网站"}, Request: request.WebsiteSwitchType{}},
Summary: "切换网站类型", Tags: []string{"网站"}, Document: DescribeReq[request.WebsiteSwitchType]()},
{Method: http.MethodDelete, Path: "/api/website/{id}", Handler: svc.Delete,
Summary: "删除网站", Tags: []string{"网站"}, Request: request.WebsiteDelete{}},
Summary: "删除网站", Tags: []string{"网站"}, Document: DescribeReq[request.WebsiteDelete]()},
{Method: http.MethodPost, Path: "/api/website/{id}/update_remark", Handler: svc.UpdateRemark,
Summary: "更新备注", Tags: []string{"网站"}, Request: request.WebsiteUpdateRemark{}},
Summary: "更新备注", Tags: []string{"网站"}, Document: DescribeReq[request.WebsiteUpdateRemark]()},
{Method: http.MethodPost, Path: "/api/website/{id}/reset_config", Handler: svc.ResetConfig,
Summary: "重置配置", Tags: []string{"网站"}, Request: request.ID{}},
Summary: "重置配置", Tags: []string{"网站"}, Document: DescribeReq[request.ID]()},
{Method: http.MethodPost, Path: "/api/website/{id}/status", Handler: svc.UpdateStatus,
Summary: "修改状态", Tags: []string{"网站"}, Request: request.WebsiteUpdateStatus{}},
Summary: "修改状态", Tags: []string{"网站"}, Document: DescribeReq[request.WebsiteUpdateStatus]()},
{Method: http.MethodPost, Path: "/api/website/{id}/expire_at", Handler: svc.UpdateExpireAt,
Summary: "修改到期时间", Tags: []string{"网站"}, Request: request.WebsiteUpdateExpireAt{}},
Summary: "修改到期时间", Tags: []string{"网站"}, Document: DescribeReq[request.WebsiteUpdateExpireAt]()},
{Method: http.MethodPost, Path: "/api/website/{id}/obtain_cert", Handler: svc.ObtainCert,
Summary: "签发证书", Tags: []string{"网站"}, Request: request.WebsiteObtainCert{}},
Summary: "签发证书", Tags: []string{"网站"}, Document: DescribeReq[request.WebsiteObtainCert]()},
}
}
+10 -10
View File
@@ -13,29 +13,29 @@ func WebsiteStatRoutes(websiteStatService *service.WebsiteStatService) Endpoints
return Endpoints{
{Method: http.MethodGet, Path: "/api/website/stat/overview", Handler: svc.Overview,
Summary: "统计概览", Tags: []string{"网站统计"}, Request: request.WebsiteStatDateRange{}},
Summary: "统计概览", Tags: []string{"网站统计"}, Document: DescribeReq[request.WebsiteStatDateRange]()},
{Method: http.MethodGet, Path: "/api/website/stat/realtime", Handler: svc.Realtime,
Summary: "实时统计", Tags: []string{"网站统计"}},
{Method: http.MethodGet, Path: "/api/website/stat/sites", Handler: svc.SiteStats,
Summary: "网站维度汇总", Tags: []string{"网站统计"}, Request: request.WebsiteStatDateRange{}},
Summary: "网站维度汇总", Tags: []string{"网站统计"}, Document: DescribeReq[request.WebsiteStatDateRange]()},
{Method: http.MethodGet, Path: "/api/website/stat/spiders", Handler: svc.SpiderStats,
Summary: "蜘蛛统计", Tags: []string{"网站统计"}, Request: request.WebsiteStatDateRange{}},
Summary: "蜘蛛统计", Tags: []string{"网站统计"}, Document: DescribeReq[request.WebsiteStatDateRange]()},
{Method: http.MethodGet, Path: "/api/website/stat/clients", Handler: svc.ClientStats,
Summary: "客户端统计", Tags: []string{"网站统计"}, Request: request.WebsiteStatDateRange{}},
Summary: "客户端统计", Tags: []string{"网站统计"}, Document: DescribeReq[request.WebsiteStatDateRange]()},
{Method: http.MethodGet, Path: "/api/website/stat/ips", Handler: svc.IPStats,
Summary: "IP 统计", Tags: []string{"网站统计"}, Request: request.WebsiteStatPaginate{}},
Summary: "IP 统计", Tags: []string{"网站统计"}, Document: DescribeReq[request.WebsiteStatPaginate]()},
{Method: http.MethodGet, Path: "/api/website/stat/geos", Handler: svc.GeoStats,
Summary: "地理位置统计", Tags: []string{"网站统计"}, Request: request.WebsiteStatGeo{}},
Summary: "地理位置统计", Tags: []string{"网站统计"}, Document: DescribeReq[request.WebsiteStatGeo]()},
{Method: http.MethodGet, Path: "/api/website/stat/uris", Handler: svc.URIStats,
Summary: "URI 统计", Tags: []string{"网站统计"}, Request: request.WebsiteStatPaginate{}},
Summary: "URI 统计", Tags: []string{"网站统计"}, Document: DescribeReq[request.WebsiteStatPaginate]()},
{Method: http.MethodGet, Path: "/api/website/stat/slow_uris", Handler: svc.SlowURIStats,
Summary: "慢请求 URI 统计", Tags: []string{"网站统计"}, Request: request.WebsiteStatSlowURIs{}},
Summary: "慢请求 URI 统计", Tags: []string{"网站统计"}, Document: DescribeReq[request.WebsiteStatSlowURIs]()},
{Method: http.MethodGet, Path: "/api/website/stat/errors", Handler: svc.ErrorStats,
Summary: "错误统计", Tags: []string{"网站统计"}, Request: request.WebsiteStatErrors{}},
Summary: "错误统计", Tags: []string{"网站统计"}, Document: DescribeReq[request.WebsiteStatErrors]()},
{Method: http.MethodGet, Path: "/api/website/stat/setting", Handler: svc.GetSetting,
Summary: "获取统计设置", Tags: []string{"网站统计"}},
{Method: http.MethodPost, Path: "/api/website/stat/setting", Handler: svc.UpdateSetting,
Summary: "保存统计设置", Tags: []string{"网站统计"}, Request: request.WebsiteStatSetting{}},
Summary: "保存统计设置", Tags: []string{"网站统计"}, Document: DescribeReq[request.WebsiteStatSetting]()},
{Method: http.MethodPost, Path: "/api/website/stat/clear", Handler: svc.Clear,
Summary: "清空统计", Tags: []string{"网站统计"}},
}
+3 -3
View File
@@ -22,9 +22,9 @@ func (s *Cron) Signature() string { return "cron" }
func (s *Cron) Message() string { return "{field} must be a valid cron expression" }
func (s *Cron) Passes(f validator.Field) bool {
if validator.IsEmptyValue(f.Val()) {
func (s *Cron) Passes(f *validator.Field) bool {
if validator.IsEmptyValue(f.Reflect()) {
return true
}
return s.re.MatchString(cast.ToString(f.Val().Interface()))
return s.re.MatchString(cast.ToString(f.Reflect().Interface()))
}
+6 -6
View File
@@ -20,14 +20,14 @@ func (r *Exists) Signature() string { return "exists" }
func (r *Exists) Message() string { return "{field} is not exists" }
func (r *Exists) Passes(f validator.Field) bool {
rv := f.Val()
func (r *Exists) Validate(f *validator.Field) (bool, error) {
rv := f.Reflect()
if validator.IsEmptyValue(rv) {
return true
return true, nil
}
args := f.Attrs()
if len(args) < 2 {
return false
return false, nil
}
val := rv.Interface()
@@ -41,8 +41,8 @@ func (r *Exists) Passes(f validator.Field) bool {
var count int64
if err := query.Count(&count).Error; err != nil {
return false
return false, err
}
return count != 0
return count != 0, nil
}
+3 -3
View File
@@ -18,11 +18,11 @@ func (r *IPCIDR) Signature() string { return "ipcidr" }
func (r *IPCIDR) Message() string { return "{field} must be a valid IP address or CIDR notation" }
func (r *IPCIDR) Passes(f validator.Field) bool {
if validator.IsEmptyValue(f.Val()) {
func (r *IPCIDR) Passes(f *validator.Field) bool {
if validator.IsEmptyValue(f.Reflect()) {
return true
}
str := cast.ToString(f.Val().Interface())
str := cast.ToString(f.Reflect().Interface())
if net.ParseIP(str) != nil {
return true
}
+6 -6
View File
@@ -20,14 +20,14 @@ func (r *NotExists) Signature() string { return "not_exists" }
func (r *NotExists) Message() string { return "{field} is exists" }
func (r *NotExists) Passes(f validator.Field) bool {
rv := f.Val()
func (r *NotExists) Validate(f *validator.Field) (bool, error) {
rv := f.Reflect()
if validator.IsEmptyValue(rv) {
return true
return true, nil
}
args := f.Attrs()
if len(args) < 2 {
return false
return false, nil
}
val := rv.Interface()
@@ -41,8 +41,8 @@ func (r *NotExists) Passes(f validator.Field) bool {
var count int64
if err := query.Count(&count).Error; err != nil {
return false
return false, err
}
return count == 0
return count == 0, nil
}
+3 -3
View File
@@ -20,11 +20,11 @@ func (r *Password) Message() string {
return "{field} must be 8-20 characters long and contain at least two types of characters: uppercase letters, lowercase letters, numbers, and special characters"
}
func (r *Password) Passes(f validator.Field) bool {
if validator.IsEmptyValue(f.Val()) {
func (r *Password) Passes(f *validator.Field) bool {
if validator.IsEmptyValue(f.Reflect()) {
return true
}
password := cast.ToString(f.Val().Interface())
password := cast.ToString(f.Reflect().Interface())
if len(password) < 8 || len(password) > 20 {
return false
}
+16 -8
View File
@@ -5,12 +5,20 @@ import (
"gorm.io/gorm"
)
// RegisterRules 注册面板自定义规则到验证器实例
func RegisterRules(v *validator.Validator, db *gorm.DB) {
v.RegisterRule(NewExists(db))
v.RegisterRule(NewNotExists(db))
v.RegisterRule(NewPassword())
v.RegisterRule(NewCron())
v.RegisterRule(NewIPCIDR())
v.RegisterRule(NewUnixPath())
// Rules 面板自定义校验规则
func Rules() []validator.Rule {
return []validator.Rule{
NewPassword(),
NewCron(),
NewIPCIDR(),
NewUnixPath(),
}
}
// FallibleRules 依赖数据库查询的校验规则
func FallibleRules(db *gorm.DB) []validator.FallibleRule {
return []validator.FallibleRule{
NewExists(db),
NewNotExists(db),
}
}
+3 -3
View File
@@ -22,9 +22,9 @@ func (r *UnixPath) Signature() string { return "unix_path" }
func (r *UnixPath) Message() string { return "{field} must be a valid Unix absolute path" }
func (r *UnixPath) Passes(f validator.Field) bool {
if validator.IsEmptyValue(f.Val()) {
func (r *UnixPath) Passes(f *validator.Field) bool {
if validator.IsEmptyValue(f.Reflect()) {
return true
}
return r.re.MatchString(cast.ToString(f.Val().Interface()))
return r.re.MatchString(cast.ToString(f.Reflect().Interface()))
}
+7 -2
View File
@@ -1677,8 +1677,13 @@ func (s *CliService) CronFailed(ctx context.Context, cmd *cli.Command) error {
// validate 校验请求结构体,CLI 不走 HTTP 绑定,需要单独调用
func (s *CliService) validate(ctx context.Context, req any) error {
vd := s.validator.Struct(req)
vd.Validate(ctx)
vd, err := s.validator.Struct(req)
if err != nil {
return err
}
if err = vd.Validate(ctx); err != nil {
return err
}
if vd.Fails() {
return errors.New(vd.Errors().One())
}
+5 -2
View File
@@ -37,8 +37,11 @@ func (s *CliTestSuite) SetupTest() {
s.Require().NoError(db.Create(&biz.Website{Name: "taken", Type: biz.WebsiteTypeStatic, Path: "/www/taken"}).Error)
// 与 bootstrap.NewValidator 等价的构建方式,此处不能导入 bootstrap(会与 apps 形成循环)
v := validator.NewValidator(validator.WithStrictRequired())
rule.RegisterRules(v, db)
v := validator.MustNew(
validator.WithStrictRequired(),
validator.WithRules(rule.Rules()...),
validator.WithFallibleRules(rule.FallibleRules(db)...),
)
s.cli = &CliService{
t: gotext.NewLocale("", ""),
+15 -2
View File
@@ -15,6 +15,14 @@ import (
"github.com/acepanel/panel/v3/internal/request"
)
// defaultValidator Bind 使用的校验器,启动时经 SetValidator 换成带自定义规则的实例
var defaultValidator = validator.Default()
// SetValidator 设置 Bind 使用的校验器
func SetValidator(v *validator.Validator) {
defaultValidator = v
}
// clientIP 提取客户端 IP,优先取配置的真实 IP 头
// 代理头通常给的是裸 IP,只有 RemoteAddr 带端口,两种形态都要能解析
func clientIP(r *http.Request, ipHeader string) string {
@@ -113,7 +121,10 @@ func Bind[T any](r *http.Request) (*T, error) {
}
}
vd := validator.Default().Struct(req)
vd, err := defaultValidator.Struct(req)
if err != nil {
return nil, err
}
if reqWithRules, ok := any(req).(request.WithRules); ok {
if rules := reqWithRules.Rules(r); rules != nil {
for key, value := range rules {
@@ -134,7 +145,9 @@ func Bind[T any](r *http.Request) (*T, error) {
}
// 开始验证
vd.Validate(r.Context())
if err = vd.Validate(r.Context()); err != nil {
return nil, err
}
if vd.Fails() {
return nil, errors.New(vd.Errors().One())
}
+14 -14
View File
@@ -40,7 +40,7 @@
"@xterm/addon-web-links": "0.12.0",
"@xterm/addon-webgl": "0.19.0",
"@xterm/xterm": "6.0.0",
"alova": "3.5.4",
"alova": "3.5.5",
"anser": "2.3.5",
"echarts": "6.1.0",
"highlight.js": "11.12.0",
@@ -65,36 +65,36 @@
"@iconify/vue": "5.0.1",
"@tsconfig/node24": "24.0.5",
"@types/lodash-es": "4.17.12",
"@types/luxon": "3.7.4",
"@types/luxon": "3.7.5",
"@types/node": "24.13.3",
"@types/node-forge": "1.3.14",
"@unocss/eslint-config": "66.7.5",
"@unocss/eslint-config": "66.8.1",
"@vitejs/plugin-vue": "6.0.8",
"@vue/eslint-config-typescript": "14.9.0",
"@vue/tsconfig": "0.9.1",
"colord": "2.9.3",
"colord": "2.10.0",
"cpx2": "9.0.0",
"eslint": "10.8.1",
"eslint": "10.9.1",
"eslint-config-prettier": "10.1.8",
"eslint-plugin-oxlint": "1.78.0",
"eslint-plugin-oxlint": "1.80.0",
"eslint-plugin-vue": "10.10.0",
"naive-ui": "2.44.1",
"naive-ui": "2.45.2",
"npm-run-all2": "9.0.3",
"oxfmt": "0.63.0",
"oxlint": "1.78.0",
"sass": "1.102.0",
"oxfmt": "0.65.0",
"oxlint": "1.80.0",
"sass": "1.103.1",
"tsx": "4.23.12",
"typescript": "6.0.3",
"unocss": "66.7.5",
"unocss": "66.8.1",
"unplugin-auto-import": "21.1.0",
"unplugin-icons": "23.0.1",
"unplugin-vue-components": "32.1.0",
"vite": "8.2.1",
"vite": "8.2.2",
"vite-plugin-compression2": "2.5.3",
"vite-plugin-html": "3.2.2",
"vite-plugin-mock": "3.0.2",
"vite-plugin-vue-devtools": "8.2.1",
"vue-tsc": "3.3.10"
"vue-tsc": "3.3.11"
},
"packageManager": "pnpm@11.21.0"
"packageManager": "pnpm@11.24.0"
}
+439 -439
View File
File diff suppressed because it is too large Load Diff