refactor: 对齐 libtnb/chi-skeleton 最新脚手架

- 依赖注入换到 libtnb/wire v0.3.0,各层包导出 Module 并逐类型 Export,
  wire.Struct 改用 Struct[T](),cleanup 签名改为 func() error
- 测试断言换到 libtnb/assert 的 must/check,20 个 testify suite 拆成标准测试函数
- mock 改用 matryer 模板输出到 internal/mocks,wire 走 go.mod tool 指令,
  mockery 用 go run 调用,避免它的依赖树污染 go.mod
- 引入 .golangci.yml 并修完全部告警,darwin 与 linux 双平台 0 issues
- 工作流改用 go-version-file、govulncheck 官方 action,
  wire 校验移入 test.yml,mockery 由自动提交改为 PR 校验

顺带修复:pkg/db 四处漏查 rows.Err()(DatabaseExists 查询出错会被当成库不存在)、
websitestat 负值转 uint64 污染流量统计、pty 终端尺寸超 uint16 截断、
文件权限位超 32 位静默截断、面板与 ACME challenge 服务器缺 ReadHeaderTimeout、
GetDefault 丢失操作人、三处对结构体值恒成立的假断言、两处带空格而失效的 nolint

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
耗子
2026-09-14 23:36:21 +08:00
co-authored by Claude Opus 5
parent 4a8df98a56
commit fe7cce6201
279 changed files with 22627 additions and 27103 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ jobs:
uses: actions/setup-go@v7
with:
cache: true
go-version: 'stable'
go-version-file: go.mod
- name: Install dependencies
run: go mod tidy
- name: Download frontend
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
uses: actions/setup-go@v7
with:
cache: true
go-version: 'stable'
go-version-file: go.mod
- name: Setup pnpm
uses: pnpm/action-setup@v6
with:
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
uses: actions/setup-go@v7
with:
cache: true
go-version: 'stable'
go-version-file: go.mod
- name: Install gettext
run: |
sudo apt-get install -y gettext
+5 -17
View File
@@ -8,7 +8,7 @@ permissions:
contents: read
jobs:
golangci:
name: golanci-lint
name: golangci-lint
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -17,31 +17,19 @@ jobs:
uses: actions/setup-go@v7
with:
cache: true
go-version: 'stable'
- name: Check Wire generated code
run: |
go generate ./cmd/ace ./cmd/cli
git diff --exit-code -- cmd/ace/wire_gen.go cmd/cli/wire_gen.go
go-version-file: go.mod
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v9
with:
skip-cache: true
version: latest
args: --timeout=30m ./...
govulncheck:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup Go
uses: actions/setup-go@v7
with:
cache: true
go-version: 'stable'
- name: Install Govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@latest
- name: Run Govulncheck
run: govulncheck ./...
uses: golang/govulncheck-action@v1
with:
go-version-file: go.mod
frontend:
runs-on: ubuntu-latest
steps:
+8 -19
View File
@@ -3,11 +3,9 @@ on:
push:
branches:
- main
concurrency:
group: codegen
cancel-in-progress: false
pull_request:
permissions:
contents: write
contents: read
jobs:
mockery:
runs-on: ubuntu-latest
@@ -18,19 +16,10 @@ jobs:
uses: actions/setup-go@v7
with:
cache: true
go-version: 'stable'
- name: Install Mockery
go-version-file: go.mod
- name: Generate Mocks
run: go run github.com/vektra/mockery/v3@v3.8.0
- name: Verify mocks are up to date
run: |
go install github.com/vektra/mockery/v3@latest
- name: Generate mocks and commit
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
~/go/bin/mockery
if [ -z "$(git status --porcelain)" ]; then
echo "mock 无变更,跳过提交"
exit 0
fi
git add -A
git commit -m "chore: update mocks"
git push origin HEAD:main
git add -N .
git diff --exit-code
+4 -5
View File
@@ -16,17 +16,16 @@ jobs:
uses: actions/setup-go@v7
with:
cache: true
go-version: 'stable'
go-version-file: go.mod
- name: Install dependencies
run: sudo apt-get install -y curl jq
# https://github.com/golang/go/issues/75031
- name: Set toolchain version
run: go env -w GOTOOLCHAIN=go1.25.1+auto
- name: Set up environment
run: |
cp config.example.yml config.yml
- name: Verify dependency injection
run: go tool wire check ./...
- name: Run tests
run: sudo go test -v -coverprofile="coverage.out" ./...
run: sudo go test -v -race -coverprofile="coverage.out" ./...
- name: Upload coverage report to Codecov
uses: codecov/codecov-action@v7
with:
+87
View File
@@ -0,0 +1,87 @@
version: "2"
# 大量代码带 linux 构建约束,golangci-lint 只分析当前 GOOS,本地需 GOOS=linux 才能复现 CI 结果
linters:
# 标准集之外只开能抓真实缺陷的低噪声 linter,纯风格偏好类不开
default: standard
enable:
# bugs and correctness
- asasalint
- bidichk
- bodyclose
- contextcheck
- copyloopvar
- durationcheck
- errchkjson
- errorlint
- exhaustive
- fatcontext
- forcetypeassert
- gocheckcompilerdirectives
- gosec
- loggercheck
- makezero
- nilerr
- nilnesserr
- noctx
- reassign
- recvcheck
- rowserrcheck
- sqlclosecheck
- unparam
# simplification and consistency
- dupword
- exptostd
- goconst
- gocritic
- intrange
- mirror
- misspell
- nakedret
- nolintlint
- nosprintfhostport
- perfsprint
- predeclared
- sloglint
- unconvert
- usestdlibvars
- usetesting
- whitespace
# tests
- thelper
- tparallel
settings:
exhaustive:
default-signifies-exhaustive: true
goconst:
# 只报重复的数字;字符串在测试和提示语里天然重复
ignore-string-values:
- '.+'
gosec:
# 面板以 root 代管整机,执行外部命令与任意路径读写是本职工作,这几类整类不适用(见 AGENTS.md)
excludes:
- G204 # 执行外部命令
- G301 # 创建目录的权限
- G302 # 打开文件的权限
- G304 # 用变量拼路径读文件
- G306 # 写文件的权限
- G702 # 命令注入的污点分析
- G703 # 路径遍历
# proxy_pass、token 目录这类领域词撞上凭据名正则,误报远多于命中
- G101 # 硬编码凭据
exclusions:
generated: lax
paths:
# mockery 输出目录
- internal/mocks
rules:
# 处理器测试里 httptest.NewRequest 不带 context 是惯例
- path: _test\.go
linters:
- noctx
issues:
# 默认同类截断 3 条、单 linter 截断 50 条,会让人以为修完可见的就干净了
max-same-issues: 0
max-issues-per-linter: 0
+2 -2
View File
@@ -1,5 +1,5 @@
template: testify
dir: mocks/biz
template: matryer
dir: internal/mocks/{{.InterfaceDirRelative | trimPrefix "internal/"}}
structname: "{{.InterfaceName}}"
pkgname: "{{.SrcPackageName}}"
filename: "{{.InterfaceName}}.go"
+7 -4
View File
@@ -88,13 +88,16 @@ pnpm build
- 封装数据库、缓存等操作
- 处理数据持久化逻辑
- **`internal/http/`**: HTTP 相关
- `middleware/`: 自定义中间件
- `request/`: 请求结构体定义
- `rule/`: 自定义验证规则
- **`internal/middleware/`**: 自定义中间件
- **`internal/request/`**: 请求结构体定义
- **`internal/rule/`**: 自定义验证规则
- **`internal/apps/`**: 面板子应用实现
- **`internal/mocks/`**: mockery 生成的 biz 接口 mock,改接口后跑 `go run github.com/vektra/mockery/v3@v3.8.0` 重新生成
- **`internal/bootstrap/`**: 各模块启动引导
- **`internal/migration/`**: 数据库迁移
+3 -3
View File
@@ -1,3 +1,5 @@
//go:generate go tool wire generate .
package main
import (
@@ -26,9 +28,7 @@ func run() error {
if err != nil {
return err
}
if cleanup != nil {
defer cleanup()
}
defer func() { _ = cleanup() }()
return ace.Run()
}
+5 -13
View File
@@ -3,7 +3,7 @@
package main
import (
"github.com/google/wire"
"github.com/libtnb/wire"
"github.com/acepanel/panel/v3/internal/app"
"github.com/acepanel/panel/v3/internal/apps"
@@ -15,15 +15,7 @@ import (
"github.com/acepanel/panel/v3/internal/service"
)
func initAce() (*app.Ace, func(), error) {
panic(wire.Build(
bootstrap.ProviderSet,
apps.ProviderSet,
biz.ProviderSet,
data.ProviderSet,
service.ProviderSet,
route.ProviderSet,
job.ProviderSet,
app.NewAce,
))
}
var initAce = wire.New().
Include(bootstrap.Module, apps.Module, biz.Module, data.Module, service.Module, route.Module, job.Module).
Provide(app.NewAce).
Injector[func() (*app.Ace, func() error, error)]()
+585 -313
View File
@@ -1,12 +1,12 @@
// Code generated by Wire. DO NOT EDIT.
//go:generate go run -mod=mod github.com/google/wire/cmd/wire
// Code generated by wire. DO NOT EDIT.
//go:build !wireinject
// +build !wireinject
package main
import (
"errors"
"sync"
"github.com/acepanel/panel/v3/internal/app"
"github.com/acepanel/panel/v3/internal/apps/apache"
"github.com/acepanel/panel/v3/internal/apps/caddy"
@@ -51,330 +51,602 @@ import (
"github.com/acepanel/panel/v3/pkg/websitestat"
)
import (
_ "time/tzdata"
)
func initAce() (*app.Ace, func() error, error) {
var wireZero0 *app.Ace
// Injectors from wire.go:
wireCleanup := &wireLifecycle{}
wireCommitted := false
defer wireRollbackOnPanic(&wireCommitted, wireCleanup.close)
func initAce() (*app.Ace, func(), error) {
config, err := bootstrap.NewConf()
if err != nil {
return nil, nil, err
wireValue0_0, wireErr0 := bootstrap.NewConf()
if wireErr0 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr0, cleanupErr)
}
locale := bootstrap.NewT(config)
apacheApp := apache.NewApp(locale)
caddyApp := caddy.NewApp(locale)
db, err := bootstrap.NewDB(config)
if err != nil {
return nil, nil, err
wireValue1_0 := bootstrap.NewT(wireValue0_0)
wireValue17_0 := apache.NewApp(wireValue1_0)
wireValue18_0 := caddy.NewApp(wireValue1_0)
wireValue4_0, wireErr4 := bootstrap.NewDB(wireValue0_0)
if wireErr4 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr4, cleanupErr)
}
databaseServerRepo := data.NewDatabaseServerRepo(db)
settingRepo := data.NewSettingRepo(config, db)
clickhouseApp := clickhouse.NewApp(locale, databaseServerRepo, settingRepo)
codeserverApp := codeserver.NewApp()
dockerApp := docker.NewApp()
elasticsearchApp := elasticsearch.NewApp(locale)
websiteRepo := data.NewWebsiteRepo(db, locale, settingRepo)
fail2banApp := fail2ban.NewApp(locale, websiteRepo)
frpApp := frp.NewApp(locale)
giteaApp := gitea.NewApp()
grafanaApp := grafana.NewApp(locale)
kafkaApp := kafka.NewApp(locale)
logger, cleanup, err := bootstrap.NewLogger(config)
if err != nil {
return nil, nil, err
wireValue106_0 := data.NewDatabaseServerRepo(wireValue4_0)
wireValue116_0 := data.NewSettingRepo(wireValue0_0, wireValue4_0)
wireValue19_0 := clickhouse.NewApp(wireValue1_0, wireValue106_0, wireValue116_0)
wireValue20_0 := codeserver.NewApp()
wireValue21_0 := docker.NewApp()
wireValue22_0 := elasticsearch.NewApp(wireValue1_0)
wireValue125_0 := data.NewWebsiteRepo(wireValue4_0, wireValue1_0, wireValue116_0)
wireValue23_0 := fail2ban.NewApp(wireValue1_0, wireValue125_0)
wireValue24_0 := frp.NewApp(wireValue1_0)
wireValue25_0 := gitea.NewApp()
wireValue26_0 := grafana.NewApp(wireValue1_0)
wireValue27_0 := kafka.NewApp(wireValue1_0)
wireValue2_0, wireResourceCleanup2, wireErr2 := bootstrap.NewLogger(wireValue0_0)
if wireErr2 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr2, cleanupErr)
}
slogLogger := bootstrap.NewSlog(logger)
notifyChannelRepo := data.NewNotifyChannelRepo(db)
notifyUsecase := biz.NewNotifyUsecase(locale, slogLogger, notifyChannelRepo, settingRepo)
taskRunner := bootstrap.NewRunner(notifyUsecase, db, locale, slogLogger)
taskRepo := data.NewTaskRepo(db, locale, slogLogger, taskRunner)
mysqlApp := mysql.NewApp(locale, databaseServerRepo, settingRepo, taskRepo)
mariadbApp := mariadb.NewApp(mysqlApp)
memcachedApp := memcached.NewApp(locale)
minioApp := minio.NewApp()
mongodbApp := mongodb.NewApp(locale, databaseServerRepo, settingRepo)
nginxApp := nginx.NewApp(locale)
openlitespeedApp := openlitespeed.NewApp(locale)
openrestyApp := openresty.NewApp(nginxApp)
opensearchApp := opensearch.NewApp(locale)
perconaApp := percona.NewApp(mysqlApp)
pgadminApp := pgadmin.NewApp(config, locale, databaseServerRepo)
phpmyadminApp := phpmyadmin.NewApp(config, locale, databaseServerRepo, settingRepo)
podmanApp := podman.NewApp()
postgresqlApp := postgresql.NewApp(locale, config, databaseServerRepo, settingRepo, taskRepo)
prometheusApp := prometheus.NewApp(config, locale, taskRepo)
pureftpdApp := pureftpd.NewApp(locale)
redisApp := redis.NewApp(locale, databaseServerRepo, taskRepo)
rocketmqApp := rocketmq.NewApp(locale)
rsyncApp := rsync.NewApp(locale)
s3fsApp := s3fs.NewApp(locale)
supervisorApp := supervisor.NewApp(locale)
valkeyApp := valkey.NewApp(locale, databaseServerRepo, taskRepo)
loader := bootstrap.NewLoader(apacheApp, caddyApp, clickhouseApp, codeserverApp, dockerApp, elasticsearchApp, fail2banApp, frpApp, giteaApp, grafanaApp, kafkaApp, mariadbApp, memcachedApp, minioApp, mongodbApp, mysqlApp, nginxApp, openlitespeedApp, openrestyApp, opensearchApp, perconaApp, pgadminApp, phpmyadminApp, podmanApp, postgresqlApp, prometheusApp, pureftpdApp, redisApp, rocketmqApp, rsyncApp, s3fsApp, supervisorApp, valkeyApp)
manager, err := bootstrap.NewSession(config, db, slogLogger)
if err != nil {
cleanup()
return nil, nil, err
wireCleanup.arm(wireResourceCleanup2)
wireValue3_0 := bootstrap.NewSlog(wireValue2_0)
wireValue112_0 := data.NewNotifyChannelRepo(wireValue4_0)
wireValue73_0 := biz.NewNotifyUsecase(wireValue1_0, wireValue3_0, wireValue112_0, wireValue116_0)
wireValue7_0 := bootstrap.NewRunner(wireValue73_0, wireValue4_0, wireValue1_0, wireValue3_0)
wireValue119_0 := data.NewTaskRepo(wireValue4_0, wireValue1_0, wireValue3_0, wireValue7_0)
wireValue32_0 := mysql.NewApp(wireValue1_0, wireValue106_0, wireValue116_0, wireValue119_0)
wireValue28_0 := mariadb.NewApp(wireValue32_0)
wireValue29_0 := memcached.NewApp(wireValue1_0)
wireValue30_0 := minio.NewApp()
wireValue31_0 := mongodb.NewApp(wireValue1_0, wireValue106_0, wireValue116_0)
wireValue33_0 := nginx.NewApp(wireValue1_0)
wireValue34_0 := openlitespeed.NewApp(wireValue1_0)
wireValue35_0 := openresty.NewApp(wireValue33_0)
wireValue36_0 := opensearch.NewApp(wireValue1_0)
wireValue37_0 := percona.NewApp(wireValue32_0)
wireValue38_0 := pgadmin.NewApp(wireValue0_0, wireValue1_0, wireValue106_0)
wireValue39_0 := phpmyadmin.NewApp(wireValue0_0, wireValue1_0, wireValue106_0, wireValue116_0)
wireValue40_0 := podman.NewApp()
wireValue41_0 := postgresql.NewApp(wireValue1_0, wireValue0_0, wireValue106_0, wireValue116_0, wireValue119_0)
wireValue42_0 := prometheus.NewApp(wireValue0_0, wireValue1_0, wireValue119_0)
wireValue43_0 := pureftpd.NewApp(wireValue1_0)
wireValue44_0 := redis.NewApp(wireValue1_0, wireValue106_0, wireValue119_0)
wireValue45_0 := rocketmq.NewApp(wireValue1_0)
wireValue46_0 := rsync.NewApp(wireValue1_0)
wireValue47_0 := s3fs.NewApp(wireValue1_0)
wireValue48_0 := supervisor.NewApp(wireValue1_0)
wireValue49_0 := valkey.NewApp(wireValue1_0, wireValue106_0, wireValue119_0)
wireValue10_0 := bootstrap.NewLoader(wireValue17_0, wireValue18_0, wireValue19_0, wireValue20_0, wireValue21_0, wireValue22_0, wireValue23_0, wireValue24_0, wireValue25_0, wireValue26_0, wireValue27_0, wireValue28_0, wireValue29_0, wireValue30_0, wireValue31_0, wireValue32_0, wireValue33_0, wireValue34_0, wireValue35_0, wireValue36_0, wireValue37_0, wireValue38_0, wireValue39_0, wireValue40_0, wireValue41_0, wireValue42_0, wireValue43_0, wireValue44_0, wireValue45_0, wireValue46_0, wireValue47_0, wireValue48_0, wireValue49_0)
wireValue6_0, wireErr6 := bootstrap.NewSession(wireValue0_0, wireValue4_0, wireValue3_0)
if wireErr6 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr6, cleanupErr)
}
appRepo := data.NewAppRepo(config, db, locale, slogLogger)
userTokenRepo := data.NewUserTokenRepo(config, db, locale)
middlewares, err := middleware.NewMiddlewares(config, locale, manager, appRepo, userTokenRepo)
if err != nil {
cleanup()
return nil, nil, err
wireValue90_0 := data.NewAppRepo(wireValue0_0, wireValue4_0, wireValue1_0, wireValue3_0)
wireValue123_0 := data.NewUserTokenRepo(wireValue0_0, wireValue4_0, wireValue1_0)
wireValue9_0, wireErr9 := middleware.NewMiddlewares(wireValue0_0, wireValue1_0, wireValue6_0, wireValue90_0, wireValue123_0)
if wireErr9 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr9, cleanupErr)
}
validator := bootstrap.NewValidator(config, db, locale)
alertRepo, err := data.NewAlertRepo(db)
if err != nil {
cleanup()
return nil, nil, err
wireValue8_0 := bootstrap.NewValidator(wireValue0_0, wireValue4_0, wireValue1_0)
wireValue89_0, wireErr89 := data.NewAlertRepo(wireValue4_0)
if wireErr89 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr89, cleanupErr)
}
containerRepo := data.NewContainerRepo()
alertUsecase := biz.NewAlertUsecase(notifyUsecase, loader, locale, slogLogger, alertRepo, appRepo, containerRepo, databaseServerRepo, settingRepo)
alertService := service.NewAlertService(alertUsecase)
cacheRepo := data.NewCacheRepo(db)
appUsecase := biz.NewAppUsecase(locale, appRepo, cacheRepo, taskRepo)
cacheUsecase := biz.NewCacheUsecase(cacheRepo)
settingUsecase := biz.NewSettingUsecase(locale, slogLogger, settingRepo, taskRepo)
appService := service.NewAppService(loader, appUsecase, cacheUsecase, settingUsecase, locale)
backupRepo := data.NewBackupRepo(config, db, locale, slogLogger, settingRepo, websiteRepo)
backupUsecase := biz.NewBackupUsecase(notifyUsecase, locale, slogLogger, backupRepo)
taskUsecase := biz.NewTaskUsecase(taskRepo)
backupService := service.NewBackupService(backupUsecase, taskUsecase, locale)
backupAccountRepo := data.NewBackupAccountRepo(db)
backupAccountUsecase := biz.NewBackupAccountUsecase(locale, slogLogger, backupAccountRepo, settingRepo)
backupStorageService := service.NewBackupStorageService(backupAccountUsecase, locale)
certRepo := data.NewCertRepo(db, locale, slogLogger)
certUsecase := biz.NewCertUsecase(locale, slogLogger, certRepo, settingRepo)
certService := service.NewCertService(certUsecase, locale)
certAccountRepo := data.NewCertAccountRepo(db, locale, slogLogger)
userRepo := data.NewUserRepo(db, locale)
certAccountUsecase := biz.NewCertAccountUsecase(locale, slogLogger, certAccountRepo, userRepo)
certAccountService := service.NewCertAccountService(certAccountUsecase)
certDNSRepo := data.NewCertDNSRepo(db)
certDNSUsecase := biz.NewCertDNSUsecase(certDNSRepo, slogLogger)
certDNSService := service.NewCertDNSService(certDNSUsecase)
containerUsecase := biz.NewContainerUsecase(locale, containerRepo, settingRepo, taskRepo)
containerService := service.NewContainerService(containerUsecase)
containerComposeRepo := data.NewContainerComposeRepo()
containerComposeUsecase := biz.NewContainerComposeUsecase(containerComposeRepo)
containerComposeService := service.NewContainerComposeService(containerComposeUsecase)
containerImageRepo := data.NewContainerImageRepo()
containerImageUsecase := biz.NewContainerImageUsecase(locale, containerImageRepo, settingRepo, taskRepo)
containerImageService := service.NewContainerImageService(containerImageUsecase)
containerNetworkRepo := data.NewContainerNetworkRepo()
containerNetworkUsecase := biz.NewContainerNetworkUsecase(containerNetworkRepo, settingRepo)
containerNetworkService := service.NewContainerNetworkService(containerNetworkUsecase)
containerVolumeRepo := data.NewContainerVolumeRepo()
containerVolumeUsecase := biz.NewContainerVolumeUsecase(containerVolumeRepo, settingRepo)
containerVolumeService := service.NewContainerVolumeService(containerVolumeUsecase)
cronRepo := data.NewCronRepo(db, locale)
cronUsecase := biz.NewCronUsecase(cronRepo, slogLogger)
cronService := service.NewCronService(cronUsecase)
databaseUserRepo := data.NewDatabaseUserRepo(db)
databaseUserUsecase := biz.NewDatabaseUserUsecase(slogLogger, databaseServerRepo, databaseUserRepo)
databaseRepo := data.NewDatabaseRepo(db)
databaseUsecase := biz.NewDatabaseUsecase(databaseUserUsecase, locale, slogLogger, databaseRepo, databaseServerRepo)
databaseService := service.NewDatabaseService(databaseUsecase)
databaseElasticsearchRepo := data.NewDatabaseElasticsearchRepo(db, locale, slogLogger)
databaseElasticsearchUsecase := biz.NewDatabaseElasticsearchUsecase(databaseElasticsearchRepo)
databaseElasticsearchService := service.NewDatabaseElasticsearchService(databaseElasticsearchUsecase)
databaseRedisRepo := data.NewDatabaseRedisRepo(db, locale, slogLogger)
databaseRedisUsecase := biz.NewDatabaseRedisUsecase(databaseRedisRepo)
databaseRedisService := service.NewDatabaseRedisService(databaseRedisUsecase)
databaseServerUsecase := biz.NewDatabaseServerUsecase(locale, slogLogger, databaseServerRepo)
databaseServerService := service.NewDatabaseServerService(databaseServerUsecase)
databaseUserService := service.NewDatabaseUserService(databaseUserUsecase)
environmentRepo := data.NewEnvironmentRepo(config, locale)
environmentUsecase := biz.NewEnvironmentUsecase(locale, cacheRepo, environmentRepo, taskRepo)
environmentService := service.NewEnvironmentService(environmentUsecase, taskUsecase, locale)
environmentDotnetService := service.NewEnvironmentDotnetService(environmentUsecase, locale)
environmentGoService := service.NewEnvironmentGoService(environmentUsecase, locale)
environmentJavaService := service.NewEnvironmentJavaService(environmentUsecase, locale)
environmentNodejsService := service.NewEnvironmentNodejsService(environmentUsecase, locale)
environmentPHPService := service.NewEnvironmentPHPService(environmentUsecase, taskUsecase, config, locale)
environmentPythonService := service.NewEnvironmentPythonService(environmentUsecase, locale)
tamperRepo, err := data.NewTamperRepo(db)
if err != nil {
cleanup()
return nil, nil, err
wireValue97_0 := data.NewContainerRepo()
wireValue50_0 := biz.NewAlertUsecase(wireValue73_0, wireValue10_0, wireValue1_0, wireValue3_0, wireValue89_0, wireValue90_0, wireValue97_0, wireValue106_0, wireValue116_0)
wireValue130_0 := service.NewAlertService(wireValue50_0)
wireValue93_0 := data.NewCacheRepo(wireValue4_0)
wireValue51_0 := biz.NewAppUsecase(wireValue1_0, wireValue90_0, wireValue93_0, wireValue119_0)
wireValue54_0 := biz.NewCacheUsecase(wireValue93_0)
wireValue77_0 := biz.NewSettingUsecase(wireValue1_0, wireValue3_0, wireValue116_0, wireValue119_0)
wireValue131_0 := service.NewAppService(wireValue10_0, wireValue51_0, wireValue54_0, wireValue77_0, wireValue1_0)
wireValue91_0 := data.NewBackupRepo(wireValue0_0, wireValue4_0, wireValue1_0, wireValue3_0, wireValue116_0, wireValue125_0)
wireValue52_0 := biz.NewBackupUsecase(wireValue73_0, wireValue1_0, wireValue3_0, wireValue91_0)
wireValue80_0 := biz.NewTaskUsecase(wireValue119_0)
wireValue132_0 := service.NewBackupService(wireValue52_0, wireValue80_0, wireValue1_0)
wireValue92_0 := data.NewBackupAccountRepo(wireValue4_0)
wireValue53_0 := biz.NewBackupAccountUsecase(wireValue1_0, wireValue3_0, wireValue92_0, wireValue116_0)
wireValue133_0 := service.NewBackupStorageService(wireValue53_0, wireValue1_0)
wireValue94_0 := data.NewCertRepo(wireValue4_0, wireValue1_0, wireValue3_0)
wireValue55_0 := biz.NewCertUsecase(wireValue1_0, wireValue3_0, wireValue94_0, wireValue116_0)
wireValue134_0 := service.NewCertService(wireValue55_0, wireValue1_0)
wireValue95_0 := data.NewCertAccountRepo(wireValue4_0, wireValue1_0, wireValue3_0)
wireValue121_0 := data.NewUserRepo(wireValue4_0, wireValue1_0)
wireValue56_0 := biz.NewCertAccountUsecase(wireValue1_0, wireValue3_0, wireValue95_0, wireValue121_0)
wireValue135_0 := service.NewCertAccountService(wireValue56_0)
wireValue96_0 := data.NewCertDNSRepo(wireValue4_0)
wireValue57_0 := biz.NewCertDNSUsecase(wireValue96_0, wireValue3_0)
wireValue136_0 := service.NewCertDNSService(wireValue57_0)
wireValue58_0 := biz.NewContainerUsecase(wireValue1_0, wireValue97_0, wireValue116_0, wireValue119_0)
wireValue138_0 := service.NewContainerService(wireValue58_0)
wireValue98_0 := data.NewContainerComposeRepo()
wireValue59_0 := biz.NewContainerComposeUsecase(wireValue98_0)
wireValue139_0 := service.NewContainerComposeService(wireValue59_0)
wireValue99_0 := data.NewContainerImageRepo()
wireValue60_0 := biz.NewContainerImageUsecase(wireValue1_0, wireValue99_0, wireValue116_0, wireValue119_0)
wireValue140_0 := service.NewContainerImageService(wireValue60_0)
wireValue100_0 := data.NewContainerNetworkRepo()
wireValue61_0 := biz.NewContainerNetworkUsecase(wireValue100_0, wireValue116_0)
wireValue141_0 := service.NewContainerNetworkService(wireValue61_0)
wireValue101_0 := data.NewContainerVolumeRepo()
wireValue62_0 := biz.NewContainerVolumeUsecase(wireValue101_0, wireValue116_0)
wireValue142_0 := service.NewContainerVolumeService(wireValue62_0)
wireValue102_0 := data.NewCronRepo(wireValue4_0, wireValue1_0)
wireValue63_0 := biz.NewCronUsecase(wireValue102_0, wireValue3_0)
wireValue143_0 := service.NewCronService(wireValue63_0)
wireValue107_0 := data.NewDatabaseUserRepo(wireValue4_0)
wireValue68_0 := biz.NewDatabaseUserUsecase(wireValue3_0, wireValue106_0, wireValue107_0)
wireValue103_0 := data.NewDatabaseRepo(wireValue4_0)
wireValue64_0 := biz.NewDatabaseUsecase(wireValue68_0, wireValue1_0, wireValue3_0, wireValue103_0, wireValue106_0)
wireValue144_0 := service.NewDatabaseService(wireValue64_0)
wireValue105_0 := data.NewDatabaseElasticsearchRepo(wireValue4_0, wireValue1_0, wireValue3_0)
wireValue66_0 := biz.NewDatabaseElasticsearchUsecase(wireValue105_0)
wireValue146_0 := service.NewDatabaseElasticsearchService(wireValue66_0)
wireValue104_0 := data.NewDatabaseRedisRepo(wireValue4_0, wireValue1_0, wireValue3_0)
wireValue65_0 := biz.NewDatabaseRedisUsecase(wireValue104_0)
wireValue145_0 := service.NewDatabaseRedisService(wireValue65_0)
wireValue67_0 := biz.NewDatabaseServerUsecase(wireValue1_0, wireValue3_0, wireValue106_0)
wireValue147_0 := service.NewDatabaseServerService(wireValue67_0)
wireValue148_0 := service.NewDatabaseUserService(wireValue68_0)
wireValue108_0 := data.NewEnvironmentRepo(wireValue0_0, wireValue1_0)
wireValue69_0 := biz.NewEnvironmentUsecase(wireValue1_0, wireValue93_0, wireValue108_0, wireValue119_0)
wireValue149_0 := service.NewEnvironmentService(wireValue69_0, wireValue80_0, wireValue1_0)
wireValue155_0 := service.NewEnvironmentDotnetService(wireValue69_0, wireValue1_0)
wireValue150_0 := service.NewEnvironmentGoService(wireValue69_0, wireValue1_0)
wireValue151_0 := service.NewEnvironmentJavaService(wireValue69_0, wireValue1_0)
wireValue152_0 := service.NewEnvironmentNodejsService(wireValue69_0, wireValue1_0)
wireValue153_0 := service.NewEnvironmentPHPService(wireValue69_0, wireValue80_0, wireValue0_0, wireValue1_0)
wireValue154_0 := service.NewEnvironmentPythonService(wireValue69_0, wireValue1_0)
wireValue118_0, wireErr118 := data.NewTamperRepo(wireValue4_0)
if wireErr118 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr118, cleanupErr)
}
tamperUsecase := biz.NewTamperUsecase(notifyUsecase, settingUsecase, locale, slogLogger, tamperRepo)
fileService := service.NewFileService(containerUsecase, tamperUsecase, taskUsecase, locale)
fileShareRepo := data.NewFileShareRepo(db, locale)
fileShareUsecase := biz.NewFileShareUsecase(slogLogger, fileShareRepo)
fileShareService := service.NewFileShareService(fileShareUsecase, locale)
firewallService := service.NewFirewallService(locale)
scanEventRepo, err := data.NewScanEventRepo()
if err != nil {
cleanup()
return nil, nil, err
wireValue79_0 := biz.NewTamperUsecase(wireValue73_0, wireValue77_0, wireValue1_0, wireValue3_0, wireValue118_0)
wireValue156_0 := service.NewFileService(wireValue58_0, wireValue79_0, wireValue80_0, wireValue1_0)
wireValue109_0 := data.NewFileShareRepo(wireValue4_0, wireValue1_0)
wireValue70_0 := biz.NewFileShareUsecase(wireValue3_0, wireValue109_0)
wireValue157_0 := service.NewFileShareService(wireValue70_0, wireValue1_0)
wireValue158_0 := service.NewFirewallService(wireValue1_0)
wireValue115_0, wireErr115 := data.NewScanEventRepo()
if wireErr115 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr115, cleanupErr)
}
scanEventUsecase := biz.NewScanEventUsecase(scanEventRepo, settingRepo)
firewallScanService := service.NewFirewallScanService(scanEventUsecase)
projectRepo := data.NewProjectRepo(db, locale)
projectUsecase := biz.NewProjectUsecase(locale, slogLogger, projectRepo)
websiteStatRepo, err := data.NewWebsiteStatRepo()
if err != nil {
cleanup()
return nil, nil, err
wireValue76_0 := biz.NewScanEventUsecase(wireValue115_0, wireValue116_0)
wireValue159_0 := service.NewFirewallScanService(wireValue76_0)
wireValue113_0 := data.NewProjectRepo(wireValue4_0, wireValue1_0)
wireValue74_0 := biz.NewProjectUsecase(wireValue1_0, wireValue3_0, wireValue113_0)
wireValue126_0, wireErr126 := data.NewWebsiteStatRepo()
if wireErr126 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr126, cleanupErr)
}
websiteStatUsecase := biz.NewWebsiteStatUsecase(websiteStatRepo)
websiteUsecase := biz.NewWebsiteUsecase(certAccountUsecase, certUsecase, databaseUsecase, databaseUserUsecase, tamperUsecase, websiteStatUsecase, locale, slogLogger, databaseServerRepo, websiteRepo)
homeService := service.NewHomeService(appUsecase, backupUsecase, containerUsecase, cronUsecase, databaseServerUsecase, environmentUsecase, projectUsecase, settingUsecase, taskUsecase, websiteUsecase, config, locale)
logRepo := data.NewLogRepo(db)
logUsecase := biz.NewLogUsecase(logRepo)
logService := service.NewLogService(logUsecase, locale)
monitorRepo, err := data.NewMonitorRepo()
if err != nil {
cleanup()
return nil, nil, err
wireValue87_0 := biz.NewWebsiteStatUsecase(wireValue126_0)
wireValue86_0 := biz.NewWebsiteUsecase(wireValue56_0, wireValue55_0, wireValue64_0, wireValue68_0, wireValue79_0, wireValue87_0, wireValue1_0, wireValue3_0, wireValue106_0, wireValue125_0)
wireValue160_0 := service.NewHomeService(wireValue51_0, wireValue52_0, wireValue58_0, wireValue63_0, wireValue67_0, wireValue69_0, wireValue74_0, wireValue77_0, wireValue80_0, wireValue86_0, wireValue0_0, wireValue1_0)
wireValue110_0 := data.NewLogRepo(wireValue4_0)
wireValue71_0 := biz.NewLogUsecase(wireValue110_0)
wireValue161_0 := service.NewLogService(wireValue71_0, wireValue1_0)
wireValue111_0, wireErr111 := data.NewMonitorRepo()
if wireErr111 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr111, cleanupErr)
}
monitorUsecase := biz.NewMonitorUsecase(monitorRepo, settingRepo)
monitorService := service.NewMonitorService(monitorUsecase, settingUsecase)
notifyService := service.NewNotifyService(notifyUsecase)
processService := service.NewProcessService()
projectService := service.NewProjectService(projectUsecase, settingUsecase)
safeRepo := data.NewSafeRepo()
safeUsecase := biz.NewSafeUsecase(safeRepo, slogLogger)
safeService := service.NewSafeService(safeUsecase)
settingService := service.NewSettingService(certAccountUsecase, certUsecase, settingUsecase, db, locale)
sshRepo := data.NewSSHRepo(db, locale)
sshUsecase := biz.NewSSHUsecase(sshRepo, slogLogger)
sshService := service.NewSSHService(sshUsecase)
systemctlService := service.NewSystemctlService(locale)
tamperService := service.NewTamperService(tamperUsecase, locale)
taskService := service.NewTaskService(taskUsecase)
templateRepo := data.NewTemplateRepo(slogLogger)
templateUsecase := biz.NewTemplateUsecase(locale, cacheRepo, templateRepo)
templateService := service.NewTemplateService(settingUsecase, templateUsecase, locale)
toolboxBenchmarkService := service.NewToolboxBenchmarkService(locale)
toolboxDiskService := service.NewToolboxDiskService(locale)
toolboxLogService := service.NewToolboxLogService(containerImageUsecase, settingUsecase, db, locale)
migrationSourceRepo := data.NewMigrationSourceRepo(locale)
migrationRemoteRepo := data.NewMigrationRemoteRepo(locale)
migrationArchiveRepo := data.NewMigrationArchiveRepo()
toolboxMigrationUsecase := biz.NewToolboxMigrationUsecase(locale, slogLogger, migrationSourceRepo, migrationRemoteRepo, migrationArchiveRepo, settingUsecase, websiteUsecase, databaseUsecase, databaseServerUsecase, databaseUserUsecase, backupUsecase, projectUsecase, appUsecase, environmentUsecase)
toolboxMigrationService := service.NewToolboxMigrationService(toolboxMigrationUsecase, config, locale, slogLogger)
toolboxNetworkService := service.NewToolboxNetworkService(locale)
toolboxSSHService := service.NewToolboxSSHService(locale)
toolboxSystemService := service.NewToolboxSystemService(locale)
userUsecase := biz.NewUserUsecase(locale, slogLogger, userRepo)
userService := service.NewUserService(notifyUsecase, userUsecase, config, locale, manager)
userPasskeyRepo := data.NewUserPasskeyRepo(db)
userPasskeyUsecase := biz.NewUserPasskeyUsecase(userPasskeyRepo)
userPasskeyService := service.NewUserPasskeyService(notifyUsecase, userPasskeyUsecase, userUsecase, config, locale, manager)
userTokenUsecase := biz.NewUserTokenUsecase(userTokenRepo)
userTokenService := service.NewUserTokenService(userTokenUsecase, locale)
webHookRepo := data.NewWebHookRepo(db, locale)
webHookUsecase := biz.NewWebHookUsecase(locale, slogLogger, webHookRepo)
webHookService := service.NewWebHookService(webHookUsecase)
websiteService := service.NewWebsiteService(settingUsecase, websiteUsecase, locale)
aggregator := websitestat.NewAggregator()
websiteStatService := service.NewWebsiteStatService(settingUsecase, websiteStatUsecase, websiteUsecase, aggregator)
wsService := service.NewWsService(backupUsecase, certUsecase, sshUsecase, settingUsecase, taskUsecase, config, locale, slogLogger)
services := &route.Services{
Alert: alertService,
App: appService,
Backup: backupService,
BackupStorage: backupStorageService,
Cert: certService,
CertAccount: certAccountService,
CertDNS: certDNSService,
Container: containerService,
ContainerCompose: containerComposeService,
ContainerImage: containerImageService,
ContainerNetwork: containerNetworkService,
ContainerVolume: containerVolumeService,
Cron: cronService,
Database: databaseService,
DatabaseElasticsearch: databaseElasticsearchService,
DatabaseRedis: databaseRedisService,
DatabaseServer: databaseServerService,
DatabaseUser: databaseUserService,
Environment: environmentService,
EnvironmentDotnet: environmentDotnetService,
EnvironmentGo: environmentGoService,
EnvironmentJava: environmentJavaService,
EnvironmentNodejs: environmentNodejsService,
EnvironmentPHP: environmentPHPService,
EnvironmentPython: environmentPythonService,
File: fileService,
FileShare: fileShareService,
Firewall: firewallService,
FirewallScan: firewallScanService,
Home: homeService,
Log: logService,
Monitor: monitorService,
Notify: notifyService,
Process: processService,
Project: projectService,
Safe: safeService,
Setting: settingService,
SSH: sshService,
Systemctl: systemctlService,
Tamper: tamperService,
Task: taskService,
Template: templateService,
ToolboxBenchmark: toolboxBenchmarkService,
ToolboxDisk: toolboxDiskService,
ToolboxLog: toolboxLogService,
ToolboxMigration: toolboxMigrationService,
ToolboxNetwork: toolboxNetworkService,
ToolboxSSH: toolboxSSHService,
ToolboxSystem: toolboxSystemService,
User: userService,
UserPasskey: userPasskeyService,
UserToken: userTokenService,
WebHook: webHookService,
Website: websiteService,
WebsiteStat: websiteStatService,
Ws: wsService,
wireValue72_0 := biz.NewMonitorUsecase(wireValue111_0, wireValue116_0)
wireValue162_0 := service.NewMonitorService(wireValue72_0, wireValue77_0)
wireValue163_0 := service.NewNotifyService(wireValue73_0)
wireValue164_0 := service.NewProcessService()
wireValue165_0 := service.NewProjectService(wireValue74_0, wireValue77_0)
wireValue114_0 := data.NewSafeRepo()
wireValue75_0 := biz.NewSafeUsecase(wireValue114_0, wireValue3_0)
wireValue166_0 := service.NewSafeService(wireValue75_0)
wireValue167_0 := service.NewSettingService(wireValue56_0, wireValue55_0, wireValue77_0, wireValue4_0, wireValue1_0)
wireValue117_0 := data.NewSSHRepo(wireValue4_0, wireValue1_0)
wireValue78_0 := biz.NewSSHUsecase(wireValue117_0, wireValue3_0)
wireValue168_0 := service.NewSSHService(wireValue78_0)
wireValue169_0 := service.NewSystemctlService(wireValue1_0)
wireValue170_0 := service.NewTamperService(wireValue79_0, wireValue1_0)
wireValue171_0 := service.NewTaskService(wireValue80_0)
wireValue120_0 := data.NewTemplateRepo(wireValue3_0)
wireValue81_0 := biz.NewTemplateUsecase(wireValue1_0, wireValue93_0, wireValue120_0)
wireValue172_0 := service.NewTemplateService(wireValue77_0, wireValue81_0, wireValue1_0)
wireValue181_0 := service.NewToolboxBenchmarkService(wireValue1_0)
wireValue183_0 := service.NewToolboxDiskService(wireValue1_0)
wireValue184_0 := service.NewToolboxLogService(wireValue60_0, wireValue77_0, wireValue4_0, wireValue1_0)
wireValue127_0 := data.NewMigrationSourceRepo(wireValue1_0)
wireValue128_0 := data.NewMigrationRemoteRepo(wireValue1_0)
wireValue129_0 := data.NewMigrationArchiveRepo()
wireValue88_0 := biz.NewToolboxMigrationUsecase(wireValue1_0, wireValue3_0, wireValue127_0, wireValue128_0, wireValue129_0, wireValue77_0, wireValue86_0, wireValue64_0, wireValue67_0, wireValue68_0, wireValue52_0, wireValue74_0, wireValue51_0, wireValue69_0)
wireValue185_0 := service.NewToolboxMigrationService(wireValue88_0, wireValue0_0, wireValue1_0, wireValue3_0)
wireValue179_0 := service.NewToolboxNetworkService(wireValue1_0)
wireValue182_0 := service.NewToolboxSSHService(wireValue1_0)
wireValue180_0 := service.NewToolboxSystemService(wireValue1_0)
wireValue82_0 := biz.NewUserUsecase(wireValue1_0, wireValue3_0, wireValue121_0)
wireValue173_0 := service.NewUserService(wireValue73_0, wireValue82_0, wireValue0_0, wireValue1_0, wireValue6_0)
wireValue122_0 := data.NewUserPasskeyRepo(wireValue4_0)
wireValue83_0 := biz.NewUserPasskeyUsecase(wireValue122_0)
wireValue174_0 := service.NewUserPasskeyService(wireValue73_0, wireValue83_0, wireValue82_0, wireValue0_0, wireValue1_0, wireValue6_0)
wireValue84_0 := biz.NewUserTokenUsecase(wireValue123_0)
wireValue175_0 := service.NewUserTokenService(wireValue84_0, wireValue1_0)
wireValue124_0 := data.NewWebHookRepo(wireValue4_0, wireValue1_0)
wireValue85_0 := biz.NewWebHookUsecase(wireValue1_0, wireValue3_0, wireValue124_0)
wireValue176_0 := service.NewWebHookService(wireValue85_0)
wireValue177_0 := service.NewWebsiteService(wireValue77_0, wireValue86_0, wireValue1_0)
wireValue16_0 := websitestat.NewAggregator()
wireValue178_0 := service.NewWebsiteStatService(wireValue77_0, wireValue87_0, wireValue86_0, wireValue16_0)
wireValue186_0 := service.NewWsService(wireValue52_0, wireValue55_0, wireValue78_0, wireValue77_0, wireValue80_0, wireValue0_0, wireValue1_0, wireValue3_0)
wireValue187_1 := &route.Services{
Alert: wireValue130_0,
App: wireValue131_0,
Backup: wireValue132_0,
BackupStorage: wireValue133_0,
Cert: wireValue134_0,
CertAccount: wireValue135_0,
CertDNS: wireValue136_0,
Container: wireValue138_0,
ContainerCompose: wireValue139_0,
ContainerImage: wireValue140_0,
ContainerNetwork: wireValue141_0,
ContainerVolume: wireValue142_0,
Cron: wireValue143_0,
Database: wireValue144_0,
DatabaseElasticsearch: wireValue146_0,
DatabaseRedis: wireValue145_0,
DatabaseServer: wireValue147_0,
DatabaseUser: wireValue148_0,
Environment: wireValue149_0,
EnvironmentDotnet: wireValue155_0,
EnvironmentGo: wireValue150_0,
EnvironmentJava: wireValue151_0,
EnvironmentNodejs: wireValue152_0,
EnvironmentPHP: wireValue153_0,
EnvironmentPython: wireValue154_0,
File: wireValue156_0,
FileShare: wireValue157_0,
Firewall: wireValue158_0,
FirewallScan: wireValue159_0,
Home: wireValue160_0,
Log: wireValue161_0,
Monitor: wireValue162_0,
Notify: wireValue163_0,
Process: wireValue164_0,
Project: wireValue165_0,
Safe: wireValue166_0,
Setting: wireValue167_0,
SSH: wireValue168_0,
Systemctl: wireValue169_0,
Tamper: wireValue170_0,
Task: wireValue171_0,
Template: wireValue172_0,
ToolboxBenchmark: wireValue181_0,
ToolboxDisk: wireValue183_0,
ToolboxLog: wireValue184_0,
ToolboxMigration: wireValue185_0,
ToolboxNetwork: wireValue179_0,
ToolboxSSH: wireValue182_0,
ToolboxSystem: wireValue180_0,
User: wireValue173_0,
UserPasskey: wireValue174_0,
UserToken: wireValue175_0,
WebHook: wireValue176_0,
Website: wireValue177_0,
WebsiteStat: wireValue178_0,
Ws: wireValue186_0,
}
v := route.NewEndpoints(services)
mux, err := bootstrap.NewRouter(loader, config, locale, middlewares, validator, v)
if err != nil {
cleanup()
return nil, nil, err
wireValue188_0 := route.NewEndpoints(wireValue187_1)
wireValue11_0, wireErr11 := bootstrap.NewRouter(wireValue10_0, wireValue0_0, wireValue1_0, wireValue9_0, wireValue8_0, wireValue188_0)
if wireErr11 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr11, cleanupErr)
}
dependencies := &job.Dependencies{
Alert: alertUsecase,
Backup: backupUsecase,
Cache: cacheUsecase,
Cert: certUsecase,
CertAccount: certAccountUsecase,
FileShare: fileShareUsecase,
Monitor: monitorUsecase,
Notify: notifyUsecase,
ScanEvent: scanEventUsecase,
Setting: settingUsecase,
Tamper: tamperUsecase,
Task: taskUsecase,
Website: websiteUsecase,
WebsiteStat: websiteStatUsecase,
Conf: config,
DB: db,
T: locale,
Log: slogLogger,
Aggregator: aggregator,
wireValue189_1 := &job.Dependencies{
Alert: wireValue50_0,
Backup: wireValue52_0,
Cache: wireValue54_0,
Cert: wireValue55_0,
CertAccount: wireValue56_0,
FileShare: wireValue70_0,
Monitor: wireValue72_0,
Notify: wireValue73_0,
ScanEvent: wireValue76_0,
Setting: wireValue77_0,
Tamper: wireValue79_0,
Task: wireValue80_0,
Website: wireValue86_0,
WebsiteStat: wireValue87_0,
Conf: wireValue0_0,
DB: wireValue4_0,
T: wireValue1_0,
Log: wireValue3_0,
Aggregator: wireValue16_0,
}
v2 := job.NewJobs(dependencies)
cron, err := bootstrap.NewCron(slogLogger, v2)
if err != nil {
cleanup()
return nil, nil, err
wireValue190_0 := job.NewJobs(wireValue189_1)
wireValue14_0, wireErr14 := bootstrap.NewCron(wireValue3_0, wireValue190_0)
if wireErr14 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr14, cleanupErr)
}
gormigrate := bootstrap.NewMigrate(db)
reloader, err := bootstrap.NewTLSReloader(config)
if err != nil {
cleanup()
return nil, nil, err
wireValue5_0 := bootstrap.NewMigrate(wireValue4_0)
wireValue12_0, wireErr12 := bootstrap.NewTLSReloader(wireValue0_0)
if wireErr12 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr12, cleanupErr)
}
server := bootstrap.NewHttp(mux, config, reloader)
ace := app.NewAce(mux, config, cron, gormigrate, server, reloader, taskRunner)
return ace, func() {
cleanup()
}, nil
wireValue13_0 := bootstrap.NewHttp(wireValue11_0, wireValue0_0, wireValue12_0)
wireValue191_0 := app.NewAce(wireValue11_0, wireValue0_0, wireValue14_0, wireValue5_0, wireValue13_0, wireValue12_0, wireValue7_0)
wireCommitted = true
return wireValue191_0, wireCleanup.close, nil
}
func wireRunCleanup(cleanup func() error) (err error, panicValue any) {
defer func() { panicValue = recover() }()
err = cleanup()
return err, nil
}
func wireRollbackOnPanic(finalized *bool, rollback func() error) {
if *finalized {
return
}
panicValue := recover()
func() {
defer func() { _ = recover() }()
_ = rollback()
}()
if panicValue != nil {
panic(panicValue)
}
}
type wireLifecycle struct {
cancel func()
children func() error
cleanups []func() error
once sync.Once
err error
panicValue any
}
func (l *wireLifecycle) arm(cleanup func() error) {
if cleanup != nil {
l.cleanups = append(l.cleanups, cleanup)
}
}
func (l *wireLifecycle) close() error {
l.once.Do(func() {
var errs []error
if l.cancel != nil {
l.cancel()
}
if l.children != nil {
err, panicValue := wireRunCleanup(l.children)
if err != nil {
errs = append(errs, err)
}
l.panicValue = panicValue
}
for index := len(l.cleanups) - 1; index >= 0; index-- {
err, panicValue := wireRunCleanup(l.cleanups[index])
if err != nil {
errs = append(errs, err)
}
if panicValue != nil && l.panicValue == nil {
l.panicValue = panicValue
}
}
l.err = errors.Join(errs...)
})
if l.panicValue != nil {
panic(l.panicValue)
}
return l.err
}
+3 -3
View File
@@ -1,3 +1,5 @@
//go:generate go tool wire generate .
package main
import (
@@ -24,9 +26,7 @@ func run() error {
if err != nil {
return err
}
if cleanup != nil {
defer cleanup()
}
defer func() { _ = cleanup() }()
return cli.Run()
}
+5 -11
View File
@@ -3,7 +3,7 @@
package main
import (
"github.com/google/wire"
"github.com/libtnb/wire"
"github.com/acepanel/panel/v3/internal/app"
"github.com/acepanel/panel/v3/internal/biz"
@@ -13,13 +13,7 @@ import (
"github.com/acepanel/panel/v3/internal/service"
)
func initCli() (*app.Cli, func(), error) {
panic(wire.Build(
bootstrap.ProviderSet,
biz.ProviderSet,
data.ProviderSet,
service.ProviderSet,
command.ProviderSet,
app.NewCli,
))
}
var initCli = wire.New().
Include(bootstrap.Module, biz.Module, data.Module, service.Module, command.Module).
Provide(app.NewCli).
Injector[func() (*app.Cli, func() error, error)]()
+188 -69
View File
@@ -1,12 +1,12 @@
// Code generated by Wire. DO NOT EDIT.
//go:generate go run -mod=mod github.com/google/wire/cmd/wire
// Code generated by wire. DO NOT EDIT.
//go:build !wireinject
// +build !wireinject
package main
import (
"errors"
"sync"
"github.com/acepanel/panel/v3/internal/app"
"github.com/acepanel/panel/v3/internal/biz"
"github.com/acepanel/panel/v3/internal/bootstrap"
@@ -15,76 +15,195 @@ import (
"github.com/acepanel/panel/v3/internal/service"
)
import (
_ "time/tzdata"
)
func initCli() (*app.Cli, func() error, error) {
var wireZero0 *app.Cli
// Injectors from wire.go:
wireCleanup := &wireLifecycle{}
wireCommitted := false
defer wireRollbackOnPanic(&wireCommitted, wireCleanup.close)
func initCli() (*app.Cli, func(), error) {
config, err := bootstrap.NewConf()
if err != nil {
return nil, nil, err
wireValue0_0, wireErr0 := bootstrap.NewConf()
if wireErr0 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr0, cleanupErr)
}
locale := bootstrap.NewT(config)
db, err := bootstrap.NewDB(config)
if err != nil {
return nil, nil, err
wireValue1_0 := bootstrap.NewT(wireValue0_0)
wireValue4_0, wireErr4 := bootstrap.NewDB(wireValue0_0)
if wireErr4 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr4, cleanupErr)
}
logger, cleanup, err := bootstrap.NewLogger(config)
if err != nil {
return nil, nil, err
wireValue2_0, wireResourceCleanup2, wireErr2 := bootstrap.NewLogger(wireValue0_0)
if wireErr2 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr2, cleanupErr)
}
slogLogger := bootstrap.NewSlog(logger)
appRepo := data.NewAppRepo(config, db, locale, slogLogger)
cacheRepo := data.NewCacheRepo(db)
notifyChannelRepo := data.NewNotifyChannelRepo(db)
settingRepo := data.NewSettingRepo(config, db)
notifyUsecase := biz.NewNotifyUsecase(locale, slogLogger, notifyChannelRepo, settingRepo)
taskRunner := bootstrap.NewRunner(notifyUsecase, db, locale, slogLogger)
taskRepo := data.NewTaskRepo(db, locale, slogLogger, taskRunner)
appUsecase := biz.NewAppUsecase(locale, appRepo, cacheRepo, taskRepo)
websiteRepo := data.NewWebsiteRepo(db, locale, settingRepo)
backupRepo := data.NewBackupRepo(config, db, locale, slogLogger, settingRepo, websiteRepo)
backupUsecase := biz.NewBackupUsecase(notifyUsecase, locale, slogLogger, backupRepo)
cacheUsecase := biz.NewCacheUsecase(cacheRepo)
certAccountRepo := data.NewCertAccountRepo(db, locale, slogLogger)
userRepo := data.NewUserRepo(db, locale)
certAccountUsecase := biz.NewCertAccountUsecase(locale, slogLogger, certAccountRepo, userRepo)
certRepo := data.NewCertRepo(db, locale, slogLogger)
certUsecase := biz.NewCertUsecase(locale, slogLogger, certRepo, settingRepo)
cronRepo := data.NewCronRepo(db, locale)
cronUsecase := biz.NewCronUsecase(cronRepo, slogLogger)
databaseServerRepo := data.NewDatabaseServerRepo(db)
databaseServerUsecase := biz.NewDatabaseServerUsecase(locale, slogLogger, databaseServerRepo)
settingUsecase := biz.NewSettingUsecase(locale, slogLogger, settingRepo, taskRepo)
userPasskeyRepo := data.NewUserPasskeyRepo(db)
userPasskeyUsecase := biz.NewUserPasskeyUsecase(userPasskeyRepo)
userUsecase := biz.NewUserUsecase(locale, slogLogger, userRepo)
databaseUserRepo := data.NewDatabaseUserRepo(db)
databaseUserUsecase := biz.NewDatabaseUserUsecase(slogLogger, databaseServerRepo, databaseUserRepo)
databaseRepo := data.NewDatabaseRepo(db)
databaseUsecase := biz.NewDatabaseUsecase(databaseUserUsecase, locale, slogLogger, databaseRepo, databaseServerRepo)
tamperRepo, err := data.NewTamperRepo(db)
if err != nil {
cleanup()
return nil, nil, err
wireCleanup.arm(wireResourceCleanup2)
wireValue3_0 := bootstrap.NewSlog(wireValue2_0)
wireValue57_0 := data.NewAppRepo(wireValue0_0, wireValue4_0, wireValue1_0, wireValue3_0)
wireValue60_0 := data.NewCacheRepo(wireValue4_0)
wireValue79_0 := data.NewNotifyChannelRepo(wireValue4_0)
wireValue83_0 := data.NewSettingRepo(wireValue0_0, wireValue4_0)
wireValue40_0 := biz.NewNotifyUsecase(wireValue1_0, wireValue3_0, wireValue79_0, wireValue83_0)
wireValue7_0 := bootstrap.NewRunner(wireValue40_0, wireValue4_0, wireValue1_0, wireValue3_0)
wireValue86_0 := data.NewTaskRepo(wireValue4_0, wireValue1_0, wireValue3_0, wireValue7_0)
wireValue18_0 := biz.NewAppUsecase(wireValue1_0, wireValue57_0, wireValue60_0, wireValue86_0)
wireValue92_0 := data.NewWebsiteRepo(wireValue4_0, wireValue1_0, wireValue83_0)
wireValue58_0 := data.NewBackupRepo(wireValue0_0, wireValue4_0, wireValue1_0, wireValue3_0, wireValue83_0, wireValue92_0)
wireValue19_0 := biz.NewBackupUsecase(wireValue40_0, wireValue1_0, wireValue3_0, wireValue58_0)
wireValue21_0 := biz.NewCacheUsecase(wireValue60_0)
wireValue62_0 := data.NewCertAccountRepo(wireValue4_0, wireValue1_0, wireValue3_0)
wireValue88_0 := data.NewUserRepo(wireValue4_0, wireValue1_0)
wireValue23_0 := biz.NewCertAccountUsecase(wireValue1_0, wireValue3_0, wireValue62_0, wireValue88_0)
wireValue61_0 := data.NewCertRepo(wireValue4_0, wireValue1_0, wireValue3_0)
wireValue22_0 := biz.NewCertUsecase(wireValue1_0, wireValue3_0, wireValue61_0, wireValue83_0)
wireValue69_0 := data.NewCronRepo(wireValue4_0, wireValue1_0)
wireValue30_0 := biz.NewCronUsecase(wireValue69_0, wireValue3_0)
wireValue73_0 := data.NewDatabaseServerRepo(wireValue4_0)
wireValue34_0 := biz.NewDatabaseServerUsecase(wireValue1_0, wireValue3_0, wireValue73_0)
wireValue44_0 := biz.NewSettingUsecase(wireValue1_0, wireValue3_0, wireValue83_0, wireValue86_0)
wireValue89_0 := data.NewUserPasskeyRepo(wireValue4_0)
wireValue50_0 := biz.NewUserPasskeyUsecase(wireValue89_0)
wireValue49_0 := biz.NewUserUsecase(wireValue1_0, wireValue3_0, wireValue88_0)
wireValue74_0 := data.NewDatabaseUserRepo(wireValue4_0)
wireValue35_0 := biz.NewDatabaseUserUsecase(wireValue3_0, wireValue73_0, wireValue74_0)
wireValue70_0 := data.NewDatabaseRepo(wireValue4_0)
wireValue31_0 := biz.NewDatabaseUsecase(wireValue35_0, wireValue1_0, wireValue3_0, wireValue70_0, wireValue73_0)
wireValue85_0, wireErr85 := data.NewTamperRepo(wireValue4_0)
if wireErr85 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr85, cleanupErr)
}
tamperUsecase := biz.NewTamperUsecase(notifyUsecase, settingUsecase, locale, slogLogger, tamperRepo)
websiteStatRepo, err := data.NewWebsiteStatRepo()
if err != nil {
cleanup()
return nil, nil, err
wireValue46_0 := biz.NewTamperUsecase(wireValue40_0, wireValue44_0, wireValue1_0, wireValue3_0, wireValue85_0)
wireValue93_0, wireErr93 := data.NewWebsiteStatRepo()
if wireErr93 != nil {
wireCommitted = true
cleanupErr := wireCleanup.close()
return wireZero0, nil, errors.Join(wireErr93, cleanupErr)
}
websiteStatUsecase := biz.NewWebsiteStatUsecase(websiteStatRepo)
websiteUsecase := biz.NewWebsiteUsecase(certAccountUsecase, certUsecase, databaseUsecase, databaseUserUsecase, tamperUsecase, websiteStatUsecase, locale, slogLogger, databaseServerRepo, websiteRepo)
validator := bootstrap.NewValidator(config, db, locale)
cliService := service.NewCliService(appUsecase, backupUsecase, cacheUsecase, certAccountUsecase, certUsecase, cronUsecase, databaseServerUsecase, notifyUsecase, settingUsecase, userPasskeyUsecase, userUsecase, websiteUsecase, config, db, locale, validator)
v := command.Commands(locale, cliService)
cliCommand := bootstrap.NewCli(locale, v)
gormigrate := bootstrap.NewMigrate(db)
cli := app.NewCli(cliCommand, gormigrate)
return cli, func() {
cleanup()
}, nil
wireValue54_0 := biz.NewWebsiteStatUsecase(wireValue93_0)
wireValue53_0 := biz.NewWebsiteUsecase(wireValue23_0, wireValue22_0, wireValue31_0, wireValue35_0, wireValue46_0, wireValue54_0, wireValue1_0, wireValue3_0, wireValue73_0, wireValue92_0)
wireValue8_0 := bootstrap.NewValidator(wireValue0_0, wireValue4_0, wireValue1_0)
wireValue104_0 := service.NewCliService(wireValue18_0, wireValue19_0, wireValue21_0, wireValue23_0, wireValue22_0, wireValue30_0, wireValue34_0, wireValue40_0, wireValue44_0, wireValue50_0, wireValue49_0, wireValue53_0, wireValue0_0, wireValue4_0, wireValue1_0, wireValue8_0)
wireValue154_0 := command.Commands(wireValue1_0, wireValue104_0)
wireValue15_0 := bootstrap.NewCli(wireValue1_0, wireValue154_0)
wireValue5_0 := bootstrap.NewMigrate(wireValue4_0)
wireValue155_0 := app.NewCli(wireValue15_0, wireValue5_0)
wireCommitted = true
return wireValue155_0, wireCleanup.close, nil
}
func wireRunCleanup(cleanup func() error) (err error, panicValue any) {
defer func() { panicValue = recover() }()
err = cleanup()
return err, nil
}
func wireRollbackOnPanic(finalized *bool, rollback func() error) {
if *finalized {
return
}
panicValue := recover()
func() {
defer func() { _ = recover() }()
_ = rollback()
}()
if panicValue != nil {
panic(panicValue)
}
}
type wireLifecycle struct {
cancel func()
children func() error
cleanups []func() error
once sync.Once
err error
panicValue any
}
func (l *wireLifecycle) arm(cleanup func() error) {
if cleanup != nil {
l.cleanups = append(l.cleanups, cleanup)
}
}
func (l *wireLifecycle) close() error {
l.once.Do(func() {
var errs []error
if l.cancel != nil {
l.cancel()
}
if l.children != nil {
err, panicValue := wireRunCleanup(l.children)
if err != nil {
errs = append(errs, err)
}
l.panicValue = panicValue
}
for index := len(l.cleanups) - 1; index >= 0; index-- {
err, panicValue := wireRunCleanup(l.cleanups[index])
if err != nil {
errs = append(errs, err)
}
if panicValue != nil && l.panicValue == nil {
l.panicValue = panicValue
}
}
l.err = errors.Join(errs...)
})
if l.panicValue != nil {
panic(l.panicValue)
}
return l.err
}
+5 -10
View File
@@ -20,7 +20,7 @@ require (
github.com/go-sql-driver/mysql v1.10.1
github.com/go-webauthn/webauthn v0.18.1
github.com/gomodule/redigo v1.9.3
github.com/google/wire v0.7.0
github.com/google/go-cmp v0.7.0
github.com/gookit/color v1.6.1
github.com/hashicorp/go-version v1.9.0
github.com/klauspost/compress v1.20.0
@@ -36,6 +36,7 @@ require (
github.com/libdns/porkbun v1.1.0
github.com/libdns/tencentcloud v1.4.3
github.com/libdns/westcn v1.0.2
github.com/libtnb/assert v0.4.2
github.com/libtnb/chix/v2 v2.1.1
github.com/libtnb/cron v0.6.0
github.com/libtnb/gormstore v1.3.0
@@ -45,6 +46,7 @@ require (
github.com/libtnb/utils v1.2.2
github.com/libtnb/validator v0.5.0
github.com/libtnb/validator/contrib/openapi v0.3.0
github.com/libtnb/wire v0.3.0
github.com/medama-io/go-useragent v1.2.4
github.com/mholt/acmez/v3 v3.1.6
github.com/moby/moby/api v1.56.0
@@ -58,7 +60,6 @@ require (
github.com/sethvargo/go-limiter v1.2.0
github.com/shirou/gopsutil/v4 v4.26.8
github.com/spf13/cast v1.10.0
github.com/stretchr/testify v1.12.1
github.com/studio-b12/gowebdav v0.13.0
github.com/urfave/cli/v3 v3.11.0
github.com/valyala/fastjson v1.6.10
@@ -99,7 +100,6 @@ require (
github.com/gofiber/utils/v2 v2.2.0 // indirect
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
github.com/google/go-tpm v0.9.8 // indirect
github.com/google/subcommands v1.2.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/jaevor/go-nanoid v1.4.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
@@ -113,12 +113,10 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/philhofer/fwd v1.2.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/richardlehane/mscfb v1.0.7 // indirect
github.com/richardlehane/msoleps v1.0.6 // indirect
github.com/stretchr/objx v0.5.3 // indirect
github.com/tiendc/go-deepcopy v1.7.2 // indirect
github.com/tinylib/msgp v1.6.4 // indirect
github.com/tklauser/go-sysconf v0.3.16 // indirect
@@ -142,9 +140,6 @@ require (
modernc.org/memory v1.12.1 // indirect
)
replace (
github.com/mholt/acmez/v3 => github.com/libtnb/acmez/v3 v3.0.0-20260406165834-a264acd02292
github.com/stretchr/testify => github.com/libtnb/testify v0.0.0-20260406170114-25da2dad39e7
)
replace github.com/mholt/acmez/v3 => github.com/libtnb/acmez/v3 v3.0.0-20260406165834-a264acd02292
tool github.com/google/wire/cmd/wire
tool github.com/libtnb/wire/cmd/wire
+12 -10
View File
@@ -29,6 +29,7 @@ github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj
github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w=
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/captcha v1.1.0 h1:2kt47EoYUUkaISobUdTbqwx55xvKOJxyScVfw25xzhQ=
github.com/dchest/captcha v1.1.0/go.mod h1:7zoElIawLp7GUMLcj54K9kbw+jEyvz2K0FDdRRYhvWo=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
@@ -95,12 +96,8 @@ github.com/google/go-tpm-tools v0.3.13-0.20230620182252-4639ecce2aba h1:qJEJcuLz
github.com/google/go-tpm-tools v0.3.13-0.20230620182252-4639ecce2aba/go.mod h1:EFYHy8/1y2KfgTAsx7Luu7NGhoxtuVHnNo8jE7FikKc=
github.com/google/pprof v0.0.0-20260802141513-ef3492d7dac3 h1:LMLX+LgTNWpfvCBdFebv6EsYotImrt/Ppc5cXIriCSo=
github.com/google/pprof v0.0.0-20260802141513-ef3492d7dac3/go.mod h1:jl5iWTm0/hd5PjEYEOuwAJ57L/CibdZfrqZ5XA5GrCk=
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
github.com/google/wire v0.7.0/go.mod h1:n6YbUQD9cPKTnHXEBN2DXlOp/mVADhVErcMFb0v3J18=
github.com/gookit/assert v0.1.1 h1:lh3GcawXe/p+cU7ESTZ5Ui3Sm/x8JWpIis4/1aF0mY0=
github.com/gookit/assert v0.1.1/go.mod h1:jS5bmIVQZTIwk42uXl4lyj4iaaxx32tqH16CFj0VX2E=
github.com/gookit/color v1.6.1 h1:KoTnDxJPRgrL0SoX0f8rCFg2zI0t4E3GZZBMo2nN8LU=
@@ -159,6 +156,8 @@ github.com/libdns/westcn v1.0.2 h1:PA2M3tME5/0T3klPMzSHvGk1EWnGNNkJiKxaJjFalnM=
github.com/libdns/westcn v1.0.2/go.mod h1:iKpk8jjOU+793Yp8nHoihPTCR6N1KWtm4/r8BB9mVnk=
github.com/libtnb/acmez/v3 v3.0.0-20260406165834-a264acd02292 h1:FF1ZlwFFjpwT6CtBodr/NV4OMJPMC7plTmfzqhXrlSk=
github.com/libtnb/acmez/v3 v3.0.0-20260406165834-a264acd02292/go.mod h1:5nTPosTGosLxF3+LU4ygbgMRFDhbAVpqMI4+a4aHLBY=
github.com/libtnb/assert v0.4.2 h1:g3uKq896kFhOwV9pGHPCX69wdHXtGD5GH1mXvXi6+BQ=
github.com/libtnb/assert v0.4.2/go.mod h1:bUoeNvAxyTPnJNWmNQQcCADyqkh+8spsh+1aCPTke2g=
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.6.0 h1:li/YbLyfmC2S+xlVEniB9qLvURgYaLwAEEFREve6yXs=
@@ -173,14 +172,14 @@ github.com/libtnb/sessions v1.5.0 h1:gvTRkSR8lpp1PB0Nms/kc+gh1BwJ411fxLjnZLYItLs
github.com/libtnb/sessions v1.5.0/go.mod h1:/Q/+lO7DcnJJEU1nL59ScPV/V8ct34F8BjoEMwwxjRw=
github.com/libtnb/sqlite v1.2.2 h1:Ku5hAPP5B3A4kQcDn4Z3qyNMafKzuAbnFZX4oD9wR4I=
github.com/libtnb/sqlite v1.2.2/go.mod h1:JkAuxM7HHo0tc7dQENjIGpp/yIfrLX5nKr5ME9wuvmI=
github.com/libtnb/testify v0.0.0-20260406170114-25da2dad39e7 h1:ZzONsNhw69uC/wJQlMj66n1zfsRgKAElfJ//E9G380U=
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.5.0 h1:1jiUBwDskUxaSQCoS9k8Ua96wofU3aZ5vttKAmEfFUU=
github.com/libtnb/validator v0.5.0/go.mod h1:yssIkchUNzAQc8EeP99rwIeYbFE2usrYbN1Ki5pamfQ=
github.com/libtnb/validator/contrib/openapi v0.3.0 h1:3yqF52Naa3BanMHAnpXpLJ23ilGPuQcb27fw89zChi4=
github.com/libtnb/validator/contrib/openapi v0.3.0/go.mod h1:NrRAZg/IvkdEPMn3WhtDdwVPgKmnVj7J0yogBKYTygo=
github.com/libtnb/wire v0.3.0 h1:AXNLM/J5z8DymfJNbJtet85bydN124orgQUL9jhXziQ=
github.com/libtnb/wire v0.3.0/go.mod h1:LiM46FF18IcKFV/a6mauzKSkBlm2Hp+r/1xKx4MqTww=
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/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
@@ -217,8 +216,7 @@ github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/pkg/sftp v1.13.11 h1:0N92SLTB8JqASJB14ZLHHzFnBV8mG9zw4K7jghEFWuE=
github.com/pkg/sftp v1.13.11/go.mod h1:uNkH9roSXglNJqM+glJJi+TQXQUm0fXFWqCFmT8hsN0=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
@@ -241,8 +239,10 @@ github.com/shirou/gopsutil/v4 v4.26.8 h1:YQMTF/1J50B5+Y0vlo1eDRf5DoR7Gk69hY+8wjY
github.com/shirou/gopsutil/v4 v4.26.8/go.mod h1:5O9FjBiXoTDFatIWjZZosqj4pV0DRtLx598xGbBehzM=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
github.com/studio-b12/gowebdav v0.13.0 h1:OcwSg6IQHOFNdYHn3bPOHwSE8looG8N56Y5xTT1asqQ=
github.com/studio-b12/gowebdav v0.13.0/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
github.com/tiendc/go-deepcopy v1.7.2 h1:Ut2yYR7W9tWjTQitganoIue4UGxZwCcJy3orjrrIj44=
@@ -287,6 +287,8 @@ go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
go.yaml.in/yaml/v4 v4.0.0-rc.6 h1:1h7H1ohdUh93/FyE4YaDa1Zh64K6VVbjF4K6WUxMtH4=
go.yaml.in/yaml/v4 v4.0.0-rc.6/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M=
+75 -85
View File
@@ -3,177 +3,167 @@ package confval
import (
"testing"
"github.com/stretchr/testify/suite"
"github.com/libtnb/assert/check"
)
type ConfValTestSuite struct {
suite.Suite
}
func TestConfValTestSuite(t *testing.T) {
suite.Run(t, new(ConfValTestSuite))
}
func (s *ConfValTestSuite) TestDirectiveGet() {
func TestDirectiveGet(t *testing.T) {
conf := "# comment\nbind 127.0.0.1 ::1\nport 6379\n\n# maxmemory 100mb\n"
s.Equal("127.0.0.1 ::1", Directive.Get(conf, "bind"))
s.Equal("6379", Directive.Get(conf, "port"))
check.Equal(t, Directive.Get(conf, "bind"), "127.0.0.1 ::1")
check.Equal(t, Directive.Get(conf, "port"), "6379")
// 注释掉的项不应被读出
s.Empty(Directive.Get(conf, "maxmemory"))
s.Empty(Directive.Get(conf, "absent"))
check.Empty(t, Directive.Get(conf, "maxmemory"))
check.Empty(t, Directive.Get(conf, "absent"))
}
func (s *ConfValTestSuite) TestDirectiveSetReplaces() {
s.Equal("port 6380", Directive.Set("port 6379", "port", "6380"))
func TestDirectiveSetReplaces(t *testing.T) {
check.Equal(t, Directive.Set("port 6379", "port", "6380"), "port 6380")
}
func (s *ConfValTestSuite) TestDirectiveSetAppendsWhenMissing() {
s.Equal("port 6379\ntimeout 30", Directive.Set("port 6379", "timeout", "30"))
func TestDirectiveSetAppendsWhenMissing(t *testing.T) {
check.Equal(t, Directive.Set("port 6379", "timeout", "30"), "port 6379\ntimeout 30")
}
func (s *ConfValTestSuite) TestDirectiveSetCommentsOutEmptyValue() {
s.Equal("# port 6379", Directive.Set("port 6379", "port", ""))
func TestDirectiveSetCommentsOutEmptyValue(t *testing.T) {
check.Equal(t, Directive.Set("port 6379", "port", ""), "# port 6379")
// 已注释的保持原样,不重复加注释符
s.Equal("# port 6379", Directive.Set("# port 6379", "port", ""))
check.Equal(t, Directive.Set("# port 6379", "port", ""), "# port 6379")
}
func (s *ConfValTestSuite) TestDirectiveSetReenablesCommented() {
s.Equal("maxmemory 200mb", Directive.Set("# maxmemory 100mb", "maxmemory", "200mb"))
func TestDirectiveSetReenablesCommented(t *testing.T) {
check.Equal(t, Directive.Set("# maxmemory 100mb", "maxmemory", "200mb"), "maxmemory 200mb")
}
func (s *ConfValTestSuite) TestDirectiveSetOnlyKeepsFirstMatch() {
s.Equal("port 6380", Directive.Set("port 6379\nport 7000", "port", "6380"))
func TestDirectiveSetOnlyKeepsFirstMatch(t *testing.T) {
check.Equal(t, Directive.Set("port 6379\nport 7000", "port", "6380"), "port 6380")
}
func (s *ConfValTestSuite) TestSetStripsNewlinesFromValue() {
s.Equal("port 63opq79", Directive.Set("port 1", "port", "63\nopq\r79"))
func TestSetStripsNewlinesFromValue(t *testing.T) {
check.Equal(t, Directive.Set("port 1", "port", "63\nopq\r79"), "port 63opq79")
}
func (s *ConfValTestSuite) TestFTPRequiresValueToMatch() {
func TestFTPRequiresValueToMatch(t *testing.T) {
// 裸键行不算配置项,避免把开关误判为键值对
s.Empty(FTP.Get("NoAnonymous\n", "NoAnonymous"))
s.Equal("yes", FTP.Get("NoAnonymous yes\n", "NoAnonymous"))
check.Empty(t, FTP.Get("NoAnonymous\n", "NoAnonymous"))
check.Equal(t, FTP.Get("NoAnonymous yes\n", "NoAnonymous"), "yes")
}
func (s *ConfValTestSuite) TestPropertiesRoundTrip() {
func TestPropertiesRoundTrip(t *testing.T) {
conf := "# broker\nnum.network.threads=3\n"
s.Equal("3", Properties.Get(conf, "num.network.threads"))
s.Equal("# broker\nnum.network.threads=5\n", Properties.Set(conf, "num.network.threads", "5"))
check.Equal(t, Properties.Get(conf, "num.network.threads"), "3")
check.Equal(t, Properties.Set(conf, "num.network.threads", "5"), "# broker\nnum.network.threads=5\n")
}
func (s *ConfValTestSuite) TestNginxTerminatorAndIndent() {
func TestNginxTerminatorAndIndent(t *testing.T) {
conf := "http {\n keepalive_timeout 60;\n}"
s.Equal("60", Nginx.Get(conf, "keepalive_timeout"))
check.Equal(t, Nginx.Get(conf, "keepalive_timeout"), "60")
// 缩进保留,行尾分号补回
s.Equal("http {\n keepalive_timeout 75;\n}", Nginx.Set(conf, "keepalive_timeout", "75"))
check.Equal(t, Nginx.Set(conf, "keepalive_timeout", "75"), "http {\n keepalive_timeout 75;\n}")
}
func (s *ConfValTestSuite) TestNginxIgnoresLinesWithoutTerminator() {
s.Empty(Nginx.Get("http {\n keepalive_timeout 60\n}", "keepalive_timeout"))
func TestNginxIgnoresLinesWithoutTerminator(t *testing.T) {
check.Empty(t, Nginx.Get("http {\n keepalive_timeout 60\n}", "keepalive_timeout"))
}
func (s *ConfValTestSuite) TestNginxKeepsTrailingComment() {
func TestNginxKeepsTrailingComment(t *testing.T) {
conf := "http {\n keepalive_timeout 60; # 保持连接\n}"
// 注释在分号之后,读取时不能混进值里
s.Equal("60", Nginx.Get(conf, "keepalive_timeout"))
s.Equal("http {\n keepalive_timeout 75; # 保持连接\n}", Nginx.Set(conf, "keepalive_timeout", "75"))
check.Equal(t, Nginx.Get(conf, "keepalive_timeout"), "60")
check.Equal(t, Nginx.Set(conf, "keepalive_timeout", "75"), "http {\n keepalive_timeout 75; # 保持连接\n}")
}
func (s *ConfValTestSuite) TestCommentOutKeepsWholeLine() {
func TestCommentOutKeepsWholeLine(t *testing.T) {
// 注释掉时整行保留,行尾注释不丢
s.Equal("# max_connections = 100 # note", Postgres.Set("max_connections = 100 # note", "max_connections", ""))
check.Equal(t, Postgres.Set("max_connections = 100 # note", "max_connections", ""), "# max_connections = 100 # note")
}
func (s *ConfValTestSuite) TestNginxAppendsWithIndent() {
s.Equal("a b;\n c d;", Nginx.Set("a b;", "c", "d"))
func TestNginxAppendsWithIndent(t *testing.T) {
check.Equal(t, Nginx.Set("a b;", "c", "d"), "a b;\n c d;")
}
func (s *ConfValTestSuite) TestPostgresQuotesAndInlineComment() {
func TestPostgresQuotesAndInlineComment(t *testing.T) {
conf := "max_connections = 100 # note\nlisten_addresses = '*'\n"
s.Equal("100", Postgres.Get(conf, "max_connections"))
s.Equal("*", Postgres.Get(conf, "listen_addresses"))
check.Equal(t, Postgres.Get(conf, "max_connections"), "100")
check.Equal(t, Postgres.Get(conf, "listen_addresses"), "*")
// 只替换值,行尾注释保留
s.Equal("max_connections = '200' # note\nlisten_addresses = '*'\n", Postgres.Set(conf, "max_connections", "200"))
check.Equal(t, Postgres.Set(conf, "max_connections", "200"), "max_connections = '200' # note\nlisten_addresses = '*'\n")
}
func (s *ConfValTestSuite) TestInlineCommentNotAppliedWhereUnsupported() {
func TestInlineCommentNotAppliedWhereUnsupported(t *testing.T) {
// redis.conf 不支持行尾注释,密码里的 # 是数据不能当注释切掉
s.Equal("p@ss#word", Directive.Get("requirepass p@ss#word\n", "requirepass"))
s.Equal("requirepass a#b", Directive.Set("requirepass p@ss#word", "requirepass", "a#b"))
check.Equal(t, Directive.Get("requirepass p@ss#word\n", "requirepass"), "p@ss#word")
check.Equal(t, Directive.Set("requirepass p@ss#word", "requirepass", "a#b"), "requirepass a#b")
// java properties 同理
s.Equal("a#b", Properties.Get("pass=a#b\n", "pass"))
check.Equal(t, Properties.Get("pass=a#b\n", "pass"), "a#b")
}
func (s *ConfValTestSuite) TestQuotedCommentCharIsData() {
s.Equal("a#b", Postgres.Get("password = 'a#b' # real note\n", "password"))
s.Equal("password = 'x#y' # real note", Postgres.Set("password = 'a#b' # real note", "password", "x#y"))
func TestQuotedCommentCharIsData(t *testing.T) {
check.Equal(t, Postgres.Get("password = 'a#b' # real note\n", "password"), "a#b")
check.Equal(t, Postgres.Set("password = 'a#b' # real note", "password", "x#y"), "password = 'x#y' # real note")
}
func (s *ConfValTestSuite) TestINIIgnoresSectionHeaders() {
func TestINIIgnoresSectionHeaders(t *testing.T) {
conf := "[mysqld]\nport = 3306\n; skip-name-resolve = 1\n"
s.Equal("3306", INI.Get(conf, "port"))
s.Empty(INI.Get(conf, "mysqld"))
check.Equal(t, INI.Get(conf, "port"), "3306")
check.Empty(t, INI.Get(conf, "mysqld"))
// 分号注释同样能被重新启用
s.Equal("[mysqld]\nport = 3306\nskip-name-resolve = 2\n", INI.Set(conf, "skip-name-resolve", "2"))
check.Equal(t, INI.Set(conf, "skip-name-resolve", "2"), "[mysqld]\nport = 3306\nskip-name-resolve = 2\n")
}
func (s *ConfValTestSuite) TestSectionINIMatchesOnlyTargetSection() {
func TestSectionINIMatchesOnlyTargetSection(t *testing.T) {
conf := "[server]\nhttp_port = 3000\n\n[database]\nhttp_port = 9999\n"
s.Equal("3000", SectionINI.GetIn(conf, "server", "http_port"))
s.Equal("9999", SectionINI.GetIn(conf, "database", "http_port"))
s.Empty(SectionINI.GetIn(conf, "absent", "http_port"))
check.Equal(t, SectionINI.GetIn(conf, "server", "http_port"), "3000")
check.Equal(t, SectionINI.GetIn(conf, "database", "http_port"), "9999")
check.Empty(t, SectionINI.GetIn(conf, "absent", "http_port"))
got := SectionINI.SetIn(conf, "database", "http_port", "8888")
s.Equal("3000", SectionINI.GetIn(got, "server", "http_port"))
s.Equal("8888", SectionINI.GetIn(got, "database", "http_port"))
check.Equal(t, SectionINI.GetIn(got, "server", "http_port"), "3000")
check.Equal(t, SectionINI.GetIn(got, "database", "http_port"), "8888")
}
func (s *ConfValTestSuite) TestSectionINIInsertsInsideSection() {
func TestSectionINIInsertsInsideSection(t *testing.T) {
conf := "[server]\nhttp_port = 3000\n\n[database]\ntype = sqlite3\n"
got := SectionINI.SetIn(conf, "server", "domain", "example.com")
s.Equal("example.com", SectionINI.GetIn(got, "server", "domain"))
check.Equal(t, SectionINI.GetIn(got, "server", "domain"), "example.com")
// 新项必须落在 server 段内,不能漏进 database 段
s.Empty(SectionINI.GetIn(got, "database", "domain"))
check.Empty(t, SectionINI.GetIn(got, "database", "domain"))
}
func (s *ConfValTestSuite) TestSectionINICreatesMissingSection() {
func TestSectionINICreatesMissingSection(t *testing.T) {
got := SectionINI.SetIn("[server]\nhttp_port = 3000\n", "smtp", "host", "localhost:25")
s.Equal("localhost:25", SectionINI.GetIn(got, "smtp", "host"))
s.Equal("3000", SectionINI.GetIn(got, "server", "http_port"))
check.Equal(t, SectionINI.GetIn(got, "smtp", "host"), "localhost:25")
check.Equal(t, SectionINI.GetIn(got, "server", "http_port"), "3000")
}
func (s *ConfValTestSuite) TestPHPINICommentsWithSemicolon() {
s.Equal("; memory_limit = 128M", PHPINI.Set("memory_limit = 128M", "memory_limit", ""))
func TestPHPINICommentsWithSemicolon(t *testing.T) {
check.Equal(t, PHPINI.Set("memory_limit = 128M", "memory_limit", ""), "; memory_limit = 128M")
}
func (s *ConfValTestSuite) TestGetYAMLFlatAndNested() {
s.Equal("single-node", GetYAML(map[string]any{"discovery.type": "single-node"}, "discovery.type"))
s.Equal("single-node", GetYAML(map[string]any{"discovery": map[string]any{"type": "single-node"}}, "discovery.type"))
s.Empty(GetYAML(map[string]any{}, "discovery.type"))
func TestGetYAMLFlatAndNested(t *testing.T) {
check.Equal(t, GetYAML(map[string]any{"discovery.type": "single-node"}, "discovery.type"), "single-node")
check.Equal(t, GetYAML(map[string]any{"discovery": map[string]any{"type": "single-node"}}, "discovery.type"), "single-node")
check.Empty(t, GetYAML(map[string]any{}, "discovery.type"))
}
func (s *ConfValTestSuite) TestSetYAMLFlattensAndClearsNested() {
func TestSetYAMLFlattensAndClearsNested(t *testing.T) {
cfg := map[string]any{"discovery": map[string]any{"type": "old"}}
SetYAML(cfg, "discovery.type", "single-node")
s.Equal("single-node", cfg["discovery.type"])
// 嵌套键清空后整个父键一并移除
_, ok := cfg["discovery"]
s.False(ok)
// 扁平键写入,嵌套键清空后整个父键一并移除
check.DeepEqual(t, cfg, map[string]any{"discovery.type": "single-node"})
}
func (s *ConfValTestSuite) TestSetYAMLIgnoresEmptyValue() {
func TestSetYAMLIgnoresEmptyValue(t *testing.T) {
cfg := map[string]any{}
SetYAML(cfg, "discovery.type", "")
s.Empty(cfg)
check.Empty(t, cfg)
}
+31 -39
View File
@@ -3,82 +3,74 @@ package confval
import (
"testing"
"github.com/stretchr/testify/suite"
"github.com/libtnb/assert/check"
)
type TOMLTestSuite struct {
suite.Suite
}
func TestTOMLTestSuite(t *testing.T) {
suite.Run(t, new(TOMLTestSuite))
}
func (s *TOMLTestSuite) TestGetDottedKey() {
func TestGetDottedKey(t *testing.T) {
conf := "bindPort = 7000\nauth.token = \"12345678\"\n# maxPortsPerClient = 0\n"
s.Equal("7000", GetTOML(conf, "bindPort"))
s.Equal("12345678", GetTOML(conf, "auth.token"))
check.Equal(t, GetTOML(conf, "bindPort"), "7000")
check.Equal(t, GetTOML(conf, "auth.token"), "12345678")
// 注释掉的项视为未设置
s.Empty(GetTOML(conf, "maxPortsPerClient"))
s.Empty(GetTOML(conf, "absent"))
check.Empty(t, GetTOML(conf, "maxPortsPerClient"))
check.Empty(t, GetTOML(conf, "absent"))
}
func (s *TOMLTestSuite) TestGetSectionKey() {
func TestGetSectionKey(t *testing.T) {
conf := "bindPort = 7000\n\n[auth]\nmethod = \"token\"\ntoken = \"abc\"\n"
s.Equal("token", GetTOML(conf, "auth.method"))
s.Equal("abc", GetTOML(conf, "auth.token"))
check.Equal(t, GetTOML(conf, "auth.method"), "token")
check.Equal(t, GetTOML(conf, "auth.token"), "abc")
}
func (s *TOMLTestSuite) TestGetIgnoresProxyBlock() {
func TestGetIgnoresProxyBlock(t *testing.T) {
conf := "serverAddr = \"1.1.1.1\"\n\n[[proxies]]\nname = \"ssh\"\nserverAddr = \"2.2.2.2\"\n"
s.Equal("1.1.1.1", GetTOML(conf, "serverAddr"))
check.Equal(t, GetTOML(conf, "serverAddr"), "1.1.1.1")
}
func (s *TOMLTestSuite) TestSetReplacesInPlace() {
func TestSetReplacesInPlace(t *testing.T) {
conf := "# 监听端口\nbindPort = 7000 # 默认\nauth.token = \"old\"\n"
s.Equal("# 监听端口\nbindPort = 7001 # 默认\nauth.token = \"old\"\n", SetTOML(conf, "bindPort", 7001))
s.Equal("# 监听端口\nbindPort = 7000 # 默认\nauth.token = \"new\"\n", SetTOML(conf, "auth.token", "new"))
check.Equal(t, SetTOML(conf, "bindPort", 7001), "# 监听端口\nbindPort = 7001 # 默认\nauth.token = \"old\"\n")
check.Equal(t, SetTOML(conf, "auth.token", "new"), "# 监听端口\nbindPort = 7000 # 默认\nauth.token = \"new\"\n")
}
func (s *TOMLTestSuite) TestSetReplacesInSection() {
func TestSetReplacesInSection(t *testing.T) {
conf := "bindPort = 7000\n\n[auth]\ntoken = \"old\"\n"
s.Equal("bindPort = 7000\n\n[auth]\ntoken = \"new\"\n", SetTOML(conf, "auth.token", "new"))
check.Equal(t, SetTOML(conf, "auth.token", "new"), "bindPort = 7000\n\n[auth]\ntoken = \"new\"\n")
}
func (s *TOMLTestSuite) TestSetInsertsBeforeFirstTable() {
func TestSetInsertsBeforeFirstTable(t *testing.T) {
conf := "bindPort = 7000\n\n[[proxies]]\nname = \"ssh\"\n"
s.Equal("bindPort = 7000\n\nauth.token = \"abc\"\n[[proxies]]\nname = \"ssh\"\n", SetTOML(conf, "auth.token", "abc"))
check.Equal(t, SetTOML(conf, "auth.token", "abc"), "bindPort = 7000\n\nauth.token = \"abc\"\n[[proxies]]\nname = \"ssh\"\n")
}
func (s *TOMLTestSuite) TestSetAppendsWhenNoTable() {
s.Equal("bindPort = 7000\nauth.token = \"abc\"", SetTOML("bindPort = 7000", "auth.token", "abc"))
func TestSetAppendsWhenNoTable(t *testing.T) {
check.Equal(t, SetTOML("bindPort = 7000", "auth.token", "abc"), "bindPort = 7000\nauth.token = \"abc\"")
}
func (s *TOMLTestSuite) TestSetCommentsOutEmptyValue() {
s.Equal("# bindPort = 7000", SetTOML("bindPort = 7000", "bindPort", ""))
s.Equal("# bindPort = 7000", SetTOML("# bindPort = 7000", "bindPort", ""))
func TestSetCommentsOutEmptyValue(t *testing.T) {
check.Equal(t, SetTOML("bindPort = 7000", "bindPort", ""), "# bindPort = 7000")
check.Equal(t, SetTOML("# bindPort = 7000", "bindPort", ""), "# bindPort = 7000")
// 键不存在时不应插入空值
s.Equal("bindPort = 7000", SetTOML("bindPort = 7000", "auth.token", ""))
check.Equal(t, SetTOML("bindPort = 7000", "auth.token", ""), "bindPort = 7000")
}
func (s *TOMLTestSuite) TestSetReenablesCommented() {
s.Equal("maxPortsPerClient = 5", SetTOML("# maxPortsPerClient = 0", "maxPortsPerClient", 5))
func TestSetReenablesCommented(t *testing.T) {
check.Equal(t, SetTOML("# maxPortsPerClient = 0", "maxPortsPerClient", 5), "maxPortsPerClient = 5")
}
func (s *TOMLTestSuite) TestSetBool() {
s.Equal("bindPort = 7000\ntransport.tls.force = true", SetTOML("bindPort = 7000", "transport.tls.force", true))
func TestSetBool(t *testing.T) {
check.Equal(t, SetTOML("bindPort = 7000", "transport.tls.force", true), "bindPort = 7000\ntransport.tls.force = true")
}
func (s *TOMLTestSuite) TestSetDoesNotTouchProxyBlock() {
func TestSetDoesNotTouchProxyBlock(t *testing.T) {
conf := "serverAddr = \"1.1.1.1\"\n\n[[proxies]]\n# 手写的隧道\nname = \"ssh\"\nserverPort = 22\n"
s.Equal("serverAddr = \"2.2.2.2\"\n\n[[proxies]]\n# 手写的隧道\nname = \"ssh\"\nserverPort = 22\n", SetTOML(conf, "serverAddr", "2.2.2.2"))
check.Equal(t, SetTOML(conf, "serverAddr", "2.2.2.2"), "serverAddr = \"2.2.2.2\"\n\n[[proxies]]\n# 手写的隧道\nname = \"ssh\"\nserverPort = 22\n")
// serverPort 只存在于 proxies 表内,不应被改写,而是插到首个表头前
s.Equal("serverAddr = \"1.1.1.1\"\n\nserverPort = 7000\n[[proxies]]\n# 手写的隧道\nname = \"ssh\"\nserverPort = 22\n", SetTOML(conf, "serverPort", 7000))
check.Equal(t, SetTOML(conf, "serverPort", 7000), "serverAddr = \"1.1.1.1\"\n\nserverPort = 7000\n[[proxies]]\n# 手写的隧道\nname = \"ssh\"\nserverPort = 22\n")
}
+2 -1
View File
@@ -51,7 +51,8 @@ func (s *App) Load(w http.ResponseWriter, r *http.Request) {
return
}
conn, err := net.Dial("tcp", "127.0.0.1:11211")
var dialer net.Dialer
conn, err := dialer.DialContext(r.Context(), "tcp", "127.0.0.1:11211")
if err != nil {
service.Success(w, []types.NV{})
return
+4
View File
@@ -471,6 +471,10 @@ func (s *App) TransactionList(w http.ResponseWriter, r *http.Request) {
}
result.LockWaits = append(result.LockWaits, item)
}
if lockRows.Err() != nil {
// 锁等待表结构不兼容,丢弃不完整结果
result.LockWaits = nil
}
}
service.Success(w, result)
-1
View File
@@ -26,7 +26,6 @@ type App struct {
}
func NewApp(t *gotext.Locale) *App {
return &App{
t: t,
}
-1
View File
@@ -27,7 +27,6 @@ type App struct {
}
func NewApp(t *gotext.Locale) *App {
return &App{t: t}
}
+3 -4
View File
@@ -194,15 +194,14 @@ func escapePgpass(s string) string {
}
// existingServers 只读 pgAdmin 配置库查询 Servers 组内已注册的服务器
// CLI 每次调用都要冷启动整个 pgAdmin 应用,直读库快数个量级
func (s *App) existingServers(email string) (map[string]struct{}, error) {
func (s *App) existingServers(ctx context.Context, email string) (map[string]struct{}, error) {
db, err := sql.Open("sqlite", fmt.Sprintf("file:%s/data/pgadmin.db?mode=ro", s.path()))
if err != nil {
return nil, err
}
defer func() { _ = db.Close() }()
rows, err := db.Query(`SELECT s.host, s.port, s.username FROM server s
rows, err := db.QueryContext(ctx, `SELECT s.host, s.port, s.username FROM server s
JOIN servergroup g ON s.servergroup_id = g.id
JOIN "user" u ON s.user_id = u.id
WHERE u.email = ? AND g.name = 'Servers'`, email)
@@ -295,7 +294,7 @@ func (s *App) syncServers(ctx context.Context, email string) error {
}
// 查询 pgAdmin 已有服务器用于查缺,直读配置库,异常时回退 CLI 导出
existing, err := s.existingServers(email)
existing, err := s.existingServers(ctx, email)
if err != nil {
existing = s.dumpExistingServers(email)
}
-1
View File
@@ -31,7 +31,6 @@ type App struct {
}
func NewApp(conf *config.Config, t *gotext.Locale, taskRepo biz.TaskRepo) *App {
return &App{t: t, conf: conf, taskRepo: taskRepo}
}
-1
View File
@@ -27,7 +27,6 @@ type App struct {
}
func NewApp(t *gotext.Locale) *App {
return &App{
t: t,
}
-1
View File
@@ -21,7 +21,6 @@ type App struct {
}
func NewApp(t *gotext.Locale) *App {
return &App{t: t}
}
-1
View File
@@ -19,7 +19,6 @@ type App struct {
}
func NewApp(t *gotext.Locale) *App {
return &App{
t: t,
}
-1
View File
@@ -24,7 +24,6 @@ type App struct {
}
func NewApp(t *gotext.Locale) *App {
return &App{
t: t,
}
+71 -13
View File
@@ -1,7 +1,9 @@
//go:build wireinject
package apps
import (
"github.com/google/wire"
"github.com/libtnb/wire"
"github.com/acepanel/panel/v3/internal/apps/apache"
"github.com/acepanel/panel/v3/internal/apps/caddy"
@@ -38,15 +40,71 @@ import (
"github.com/acepanel/panel/v3/internal/apps/valkey"
)
var ProviderSet = wire.NewSet(
apache.NewApp, caddy.NewApp, clickhouse.NewApp, codeserver.NewApp,
docker.NewApp, elasticsearch.NewApp, fail2ban.NewApp,
frp.NewApp, gitea.NewApp, grafana.NewApp,
kafka.NewApp, mariadb.NewApp, memcached.NewApp,
minio.NewApp, mongodb.NewApp, mysql.NewApp,
nginx.NewApp, openlitespeed.NewApp, openresty.NewApp, opensearch.NewApp,
percona.NewApp, pgadmin.NewApp, phpmyadmin.NewApp, podman.NewApp,
postgresql.NewApp, prometheus.NewApp, pureftpd.NewApp,
redis.NewApp, rocketmq.NewApp, rsync.NewApp,
s3fs.NewApp, supervisor.NewApp, valkey.NewApp,
)
// Module 装配全部子应用
var Module = wire.New().
Provide(apache.NewApp).
Provide(caddy.NewApp).
Provide(clickhouse.NewApp).
Provide(codeserver.NewApp).
Provide(docker.NewApp).
Provide(elasticsearch.NewApp).
Provide(fail2ban.NewApp).
Provide(frp.NewApp).
Provide(gitea.NewApp).
Provide(grafana.NewApp).
Provide(kafka.NewApp).
Provide(mariadb.NewApp).
Provide(memcached.NewApp).
Provide(minio.NewApp).
Provide(mongodb.NewApp).
Provide(mysql.NewApp).
Provide(nginx.NewApp).
Provide(openlitespeed.NewApp).
Provide(openresty.NewApp).
Provide(opensearch.NewApp).
Provide(percona.NewApp).
Provide(pgadmin.NewApp).
Provide(phpmyadmin.NewApp).
Provide(podman.NewApp).
Provide(postgresql.NewApp).
Provide(prometheus.NewApp).
Provide(pureftpd.NewApp).
Provide(redis.NewApp).
Provide(rocketmq.NewApp).
Provide(rsync.NewApp).
Provide(s3fs.NewApp).
Provide(supervisor.NewApp).
Provide(valkey.NewApp).
Export[*apache.App]().
Export[*caddy.App]().
Export[*clickhouse.App]().
Export[*codeserver.App]().
Export[*docker.App]().
Export[*elasticsearch.App]().
Export[*fail2ban.App]().
Export[*frp.App]().
Export[*gitea.App]().
Export[*grafana.App]().
Export[*kafka.App]().
Export[*mariadb.App]().
Export[*memcached.App]().
Export[*minio.App]().
Export[*mongodb.App]().
Export[*mysql.App]().
Export[*nginx.App]().
Export[*openlitespeed.App]().
Export[*openresty.App]().
Export[*opensearch.App]().
Export[*percona.App]().
Export[*pgadmin.App]().
Export[*phpmyadmin.App]().
Export[*podman.App]().
Export[*postgresql.App]().
Export[*prometheus.App]().
Export[*pureftpd.App]().
Export[*redis.App]().
Export[*rocketmq.App]().
Export[*rsync.App]().
Export[*s3fs.App]().
Export[*supervisor.App]().
Export[*valkey.App]()
+1 -1
View File
@@ -368,7 +368,7 @@ func (uc *AlertUsecase) evaluateMetric(ctx context.Context, rule *AlertRule, met
uc.mu.Unlock()
return
}
silence := time.Duration(rule.Silence) * time.Minute
silence := time.Duration(rule.Silence) * time.Minute //nolint:gosec
uc.silenced[key] = now.Add(silence)
uc.mu.Unlock()
+2 -2
View File
@@ -29,7 +29,7 @@ type BackupRepo interface {
Create(ctx context.Context, typ BackupType, target string, account uint) error
CreatePanel() error
Delete(typ BackupType, name string) error
Restore(typ BackupType, backup, target string) error
Restore(ctx context.Context, typ BackupType, backup, target string) error
ClearExpired(path, prefix string, save uint) error
ClearStorageExpired(account uint, dir, prefix string, save uint) error
CutoffLog(path, target string) (string, error)
@@ -94,7 +94,7 @@ func (uc *BackupUsecase) Delete(ctx context.Context, typ BackupType, name string
}
func (uc *BackupUsecase) Restore(ctx context.Context, typ BackupType, backup, target string) error {
if err := uc.repo.Restore(typ, backup, target); err != nil {
if err := uc.repo.Restore(ctx, typ, backup, target); err != nil {
return err
}
+2
View File
@@ -76,6 +76,7 @@ func (r *BackupStorage) BeforeSave(tx *gorm.DB) error {
return err
}
return nil
default:
}
return nil
@@ -125,6 +126,7 @@ func (r *BackupStorage) AfterFind(tx *gorm.DB) error {
r.Info.Password = string(password)
}
return nil
default:
}
return nil
-18
View File
@@ -1,18 +0,0 @@
package biz
import "github.com/google/wire"
var ProviderSet = wire.NewSet(
NewAlertUsecase, NewAppUsecase, NewBackupUsecase, NewBackupAccountUsecase,
NewCacheUsecase, NewCertUsecase, NewCertAccountUsecase,
NewCertDNSUsecase, NewContainerUsecase, NewContainerComposeUsecase,
NewContainerImageUsecase, NewContainerNetworkUsecase, NewContainerVolumeUsecase,
NewCronUsecase, NewDatabaseUsecase, NewDatabaseRedisUsecase,
NewDatabaseElasticsearchUsecase, NewDatabaseServerUsecase, NewDatabaseUserUsecase,
NewEnvironmentUsecase, NewFileShareUsecase, NewLogUsecase, NewMonitorUsecase,
NewNotifyUsecase, NewProjectUsecase, NewSafeUsecase, NewScanEventUsecase,
NewSettingUsecase, NewSSHUsecase, NewTamperUsecase, NewTaskUsecase,
NewTemplateUsecase, NewUserUsecase, NewUserPasskeyUsecase,
NewUserTokenUsecase, NewWebHookUsecase, NewWebsiteUsecase,
NewWebsiteStatUsecase, NewToolboxMigrationUsecase,
)
+3 -11
View File
@@ -175,10 +175,6 @@ func (uc *CertUsecase) Delete(ctx context.Context, id uint) error {
return nil
}
func (uc *CertUsecase) ObtainAuto(id uint) (*acme.Certificate, error) {
return uc.ObtainAutoWithProgressCallback(context.Background(), id, nil)
}
func (uc *CertUsecase) ObtainAutoWithProgressCallback(ctx context.Context, id uint, progressCallback func(string)) (*acme.Certificate, error) {
report := func(msg string) {
if progressCallback != nil {
@@ -298,10 +294,6 @@ func (uc *CertUsecase) ObtainSelfSigned(id uint) error {
return nil
}
func (uc *CertUsecase) Renew(id uint) (*acme.Certificate, error) {
return uc.RenewWithProgressCallback(context.Background(), id, nil)
}
func (uc *CertUsecase) RenewWithProgressCallback(ctx context.Context, id uint, progressCallback func(string)) (*acme.Certificate, error) {
report := func(msg string) {
if progressCallback != nil {
@@ -380,7 +372,7 @@ func (uc *CertUsecase) RenewWithProgressCallback(ctx context.Context, id uint, p
return &ssl, nil
}
func (uc *CertUsecase) RefreshRenewalInfo(id uint) (mholtacme.RenewalInfo, error) {
func (uc *CertUsecase) RefreshRenewalInfo(ctx context.Context, id uint) (mholtacme.RenewalInfo, error) {
cert, err := uc.repo.Get(id)
if err != nil {
return mholtacme.RenewalInfo{}, err
@@ -395,9 +387,9 @@ func (uc *CertUsecase) RefreshRenewalInfo(id uint) (mholtacme.RenewalInfo, error
return mholtacme.RenewalInfo{}, err
}
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
infoCtx, cancel := context.WithTimeout(ctx, 1*time.Minute)
defer cancel()
renewInfo, err := client.GetRenewalInfo(ctx, crt)
renewInfo, err := client.GetRenewalInfo(infoCtx, crt)
if err != nil {
return mholtacme.RenewalInfo{}, err
}
+2 -2
View File
@@ -59,7 +59,7 @@ func (uc *CertAccountUsecase) List(page, limit uint) ([]*CertAccount, int64, err
return uc.repo.List(page, limit)
}
func (uc *CertAccountUsecase) GetDefault(userID uint) (*CertAccount, error) {
func (uc *CertAccountUsecase) GetDefault(ctx context.Context, userID uint) (*CertAccount, error) {
user, err := uc.userRepo.Get(userID)
if err != nil {
return nil, err
@@ -76,7 +76,7 @@ func (uc *CertAccountUsecase) GetDefault(userID uint) (*CertAccount, error) {
KeyType: string(acme.KeyEC256),
}
return uc.Create(context.Background(), req)
return uc.Create(ctx, req)
}
func (uc *CertAccountUsecase) Get(id uint) (*CertAccount, error) {
+13 -4
View File
@@ -93,7 +93,7 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
return mongoErr
}
defer mongo.Close()
if mongoErr = mongo.DatabaseCreate(req.Name); mongoErr != nil {
if mongoErr = mongo.DatabaseCreate(req.Name); mongoErr != nil { //nolint:contextcheck
return mongoErr
}
uc.log.Info("database created", slog.String("type", OperationTypeDatabase), slog.Uint64("operator_id", operatorID(ctx)), slog.String("name", req.Name), slog.Uint64("server_id", uint64(req.ServerID)))
@@ -154,7 +154,11 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
return err
}
}
if err = operator.(*db.Postgres).DatabaseComment(req.Name, req.Comment); err != nil {
pg, ok := operator.(*db.Postgres)
if !ok {
return errors.New(uc.t.Get("%s does not support database comment", server.Type))
}
if err = pg.DatabaseComment(req.Name, req.Comment); err != nil { //nolint:contextcheck
return err
}
case DatabaseTypeClickHouse:
@@ -175,6 +179,7 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
return err
}
}
default:
}
// 记录日志
@@ -214,7 +219,7 @@ func (uc *DatabaseUsecase) Delete(ctx context.Context, serverID uint, name strin
return mongoErr
}
defer mongo.Close()
if mongoErr = mongo.DatabaseDrop(name); mongoErr != nil {
if mongoErr = mongo.DatabaseDrop(name); mongoErr != nil { //nolint:contextcheck
return mongoErr
}
case DatabaseTypeSQLite:
@@ -249,7 +254,11 @@ func (uc *DatabaseUsecase) Comment(ctx context.Context, req *request.DatabaseCom
return opErr
}
defer operator.Close()
return operator.(*db.Postgres).DatabaseComment(req.Name, req.Comment)
pg, ok := operator.(*db.Postgres)
if !ok {
return errors.New(uc.t.Get("%s does not support database comment", server.Type))
}
return pg.DatabaseComment(req.Name, req.Comment) //nolint:contextcheck
default:
return errors.New(uc.t.Get("%s does not support database comment", server.Type))
}
+3 -2
View File
@@ -50,7 +50,6 @@ func (r *DatabaseServer) BeforeSave(tx *gorm.DB) error {
}
return nil
}
func (r *DatabaseServer) AfterFind(tx *gorm.DB) error {
@@ -182,7 +181,8 @@ func (uc *DatabaseServerUsecase) Sync(ctx context.Context, id uint) error {
// 非 Operator 类型不支持用户同步
switch server.Type {
case DatabaseTypeRedis, DatabaseTypeMongoDB, DatabaseTypeSQLite, DatabaseTypeElasticsearch:
case DatabaseTypeMysql, DatabaseTypePostgresql, DatabaseTypeClickHouse:
default:
return fmt.Errorf("sync is not supported for %s", server.Type)
}
@@ -256,6 +256,7 @@ func (uc *DatabaseServerUsecase) Sync(ctx context.Context, id uint) error {
}
}
}
default:
}
return nil
+1 -1
View File
@@ -48,7 +48,6 @@ func (r *DatabaseUser) BeforeSave(tx *gorm.DB) error {
}
return nil
}
func (r *DatabaseUser) AfterFind(tx *gorm.DB) error {
@@ -263,6 +262,7 @@ func (uc *DatabaseUserUsecase) DeleteByNames(ctx context.Context, serverID uint,
for name := range slices.Values(names) {
_ = operator.UserDrop(name)
}
default:
}
return uc.repo.DeleteByServerNames(serverID, names)
+1
View File
@@ -46,6 +46,7 @@ func (uc *FileShareUsecase) List() ([]*FileShare, error) {
// Create 创建分享,同一路径可重复分享为多条独立记录
func (uc *FileShareUsecase) Create(ctx context.Context, req *request.FileShareCreate) (*FileShare, error) {
//nolint:gosec
share, err := uc.repo.Create(req.Path, req.MaxDownloads, time.Now().Add(time.Duration(req.ExpireHours)*time.Hour))
if err != nil {
return nil, err
+2
View File
@@ -221,6 +221,8 @@ func (uc *NotifyUsecase) Send(ctx context.Context, channelIDs []uint, subject, b
// SendEvent 发送系统事件通知,不阻塞业务流程
// 待发送数超过上限时丢弃并告知,避免慢渠道拖垮调用方
//
//nolint:contextcheck,nolintlint
func (uc *NotifyUsecase) SendEvent(event NotifyEvent, subject, body string) {
select {
case uc.pending <- struct{}{}:
+1 -1
View File
@@ -33,7 +33,7 @@ type ProjectRepo interface {
Create(project *Project, req *request.ProjectCreate) error
Save(project *Project) error
Delete(project *Project) error
RenameUnitFile(old, new string) error
RenameUnitFile(oldName, newName string) error
RemoveUnitFile(name string) error
UpdateUnitFile(name string, req *request.ProjectUpdate) error
}
+2 -2
View File
@@ -218,7 +218,7 @@ func (uc *SettingUsecase) UpdatePanel(ctx context.Context, req *request.SettingP
}
}
if needGen {
crt, key, err := cert.GenerateSelfSigned(tools.CollectLocalNames())
crt, key, err := cert.GenerateSelfSigned(tools.CollectLocalNames()) //nolint:contextcheck
if err != nil {
return false, errors.New(uc.t.Get("failed to generate self-signed certificate: %v", err))
}
@@ -258,7 +258,7 @@ func (uc *SettingUsecase) UpdatePanel(ctx context.Context, req *request.SettingP
}
if req.Port != conf.HTTP.Port {
if os.TCPPortInUse(req.Port) {
if os.TCPPortInUse(req.Port) { //nolint:contextcheck
return false, errors.New(uc.t.Get("port is already in use"))
}
// 放行端口
+3 -2
View File
@@ -1,6 +1,7 @@
package biz
import (
"context"
"errors"
"fmt"
"log/slog"
@@ -99,8 +100,8 @@ func (uc *TamperUsecase) DetectEBPF() tamper.EBPFStatus {
}
// EnableBPFLSMGrub 修改 grub 激活 bpf LSM(需重启系统生效)
func (uc *TamperUsecase) EnableBPFLSMGrub() error {
return tamper.EnableBPFLSMGrub()
func (uc *TamperUsecase) EnableBPFLSMGrub(ctx context.Context) error {
return tamper.EnableBPFLSMGrub(ctx)
}
// GetSetting 读取全局设置
+6 -2
View File
@@ -355,6 +355,8 @@ func (uc *ToolboxMigrationUsecase) importProject(ctx context.Context, detail *ty
)), nil
case types.ProjectTypeGeneral:
return append(warnings, uc.t.Get("the project was not started; start it manually")), nil
default:
// 其余类型依赖随文件一起迁移,可直接启动
}
if project.Enabled {
_, _ = shell.Exec("systemctl enable " + strconv.Quote(detail.Item.TargetName))
@@ -413,6 +415,8 @@ func (uc *ToolboxMigrationUsecase) rewriteExecStart(project *types.MigrationProj
case "npm", "npx", "corepack":
executable = filepath.Join(app.Root, "server", "nodejs", slug, "bin", base)
}
default:
// 通用类型没有面板托管的运行时,不改写启动命令
}
if executable == "" {
return execStart
@@ -490,9 +494,9 @@ func (uc *ToolboxMigrationUsecase) removeDependencies(root string, typ types.Pro
}
_ = filepath.WalkDir(root, func(path string, entry os.DirEntry, err error) error {
if err != nil || !entry.IsDir() || path == root || !slices.Contains(names, entry.Name()) {
return nil
return nil //nolint:nilerr
}
_ = os.RemoveAll(path)
_ = os.RemoveAll(path) //nolint:gosec
return filepath.SkipDir
})
}
+2 -2
View File
@@ -262,7 +262,7 @@ func (uc *WebsiteUsecase) ObtainCert(ctx context.Context, id uint, dnsID uint) e
return errors.New(uc.t.Get("wildcard domains require DNS verification, please select a DNS provider"))
}
account, err := uc.certAccount.GetDefault(cast.ToUint(ctx.Value("user_id")))
account, err := uc.certAccount.GetDefault(ctx, cast.ToUint(ctx.Value("user_id")))
if err != nil {
return err
}
@@ -291,7 +291,7 @@ func (uc *WebsiteUsecase) ObtainCert(ctx context.Context, id uint, dnsID uint) e
return err
}
_, err = uc.cert.ObtainAuto(newCert.ID)
_, err = uc.cert.ObtainAutoWithProgressCallback(ctx, newCert.ID, nil)
if err != nil {
return err
}
+86
View File
@@ -0,0 +1,86 @@
//go:build wireinject
package biz
import "github.com/libtnb/wire"
// Module 装配业务逻辑层
var Module = wire.New().
Provide(NewAlertUsecase).
Provide(NewAppUsecase).
Provide(NewBackupUsecase).
Provide(NewBackupAccountUsecase).
Provide(NewCacheUsecase).
Provide(NewCertUsecase).
Provide(NewCertAccountUsecase).
Provide(NewCertDNSUsecase).
Provide(NewContainerUsecase).
Provide(NewContainerComposeUsecase).
Provide(NewContainerImageUsecase).
Provide(NewContainerNetworkUsecase).
Provide(NewContainerVolumeUsecase).
Provide(NewCronUsecase).
Provide(NewDatabaseUsecase).
Provide(NewDatabaseRedisUsecase).
Provide(NewDatabaseElasticsearchUsecase).
Provide(NewDatabaseServerUsecase).
Provide(NewDatabaseUserUsecase).
Provide(NewEnvironmentUsecase).
Provide(NewFileShareUsecase).
Provide(NewLogUsecase).
Provide(NewMonitorUsecase).
Provide(NewNotifyUsecase).
Provide(NewProjectUsecase).
Provide(NewSafeUsecase).
Provide(NewScanEventUsecase).
Provide(NewSettingUsecase).
Provide(NewSSHUsecase).
Provide(NewTamperUsecase).
Provide(NewTaskUsecase).
Provide(NewTemplateUsecase).
Provide(NewUserUsecase).
Provide(NewUserPasskeyUsecase).
Provide(NewUserTokenUsecase).
Provide(NewWebHookUsecase).
Provide(NewWebsiteUsecase).
Provide(NewWebsiteStatUsecase).
Provide(NewToolboxMigrationUsecase).
Export[*AlertUsecase]().
Export[*AppUsecase]().
Export[*BackupUsecase]().
Export[*BackupAccountUsecase]().
Export[*CacheUsecase]().
Export[*CertUsecase]().
Export[*CertAccountUsecase]().
Export[*CertDNSUsecase]().
Export[*ContainerUsecase]().
Export[*ContainerComposeUsecase]().
Export[*ContainerImageUsecase]().
Export[*ContainerNetworkUsecase]().
Export[*ContainerVolumeUsecase]().
Export[*CronUsecase]().
Export[*DatabaseUsecase]().
Export[*DatabaseRedisUsecase]().
Export[*DatabaseElasticsearchUsecase]().
Export[*DatabaseServerUsecase]().
Export[*DatabaseUserUsecase]().
Export[*EnvironmentUsecase]().
Export[*FileShareUsecase]().
Export[*LogUsecase]().
Export[*MonitorUsecase]().
Export[*NotifyUsecase]().
Export[*ProjectUsecase]().
Export[*SafeUsecase]().
Export[*ScanEventUsecase]().
Export[*SettingUsecase]().
Export[*SSHUsecase]().
Export[*TamperUsecase]().
Export[*TaskUsecase]().
Export[*TemplateUsecase]().
Export[*UserUsecase]().
Export[*UserPasskeyUsecase]().
Export[*UserTokenUsecase]().
Export[*WebHookUsecase]().
Export[*WebsiteUsecase]().
Export[*WebsiteStatUsecase]().
Export[*ToolboxMigrationUsecase]()
-29
View File
@@ -1,29 +0,0 @@
package bootstrap
import (
"github.com/google/wire"
"github.com/acepanel/panel/v3/internal/middleware"
"github.com/acepanel/panel/v3/pkg/websitestat"
)
// ProviderSet 装配基础设施层
var ProviderSet = wire.NewSet(
NewConf,
NewT,
NewLogger,
NewSlog,
NewDB,
NewMigrate,
NewSession,
NewRunner,
NewValidator,
middleware.NewMiddlewares,
NewLoader,
NewRouter,
NewTLSReloader,
NewHttp,
NewCron,
NewCli,
websitestat.NewAggregator,
)
-1
View File
@@ -10,7 +10,6 @@ import (
)
func NewCli(t *gotext.Locale, commands []*cli.Command) *cli.Command {
cli.RootCommandHelpTemplate = strings.ReplaceAll(cli.RootCommandHelpTemplate, "NAME", t.Get("NAME"))
cli.RootCommandHelpTemplate = strings.ReplaceAll(cli.RootCommandHelpTemplate, "USAGE", t.Get("USAGE"))
cli.RootCommandHelpTemplate = strings.ReplaceAll(cli.RootCommandHelpTemplate, "VERSION", t.Get("VERSION"))
-1
View File
@@ -17,7 +17,6 @@ import (
)
func NewDB(conf *config.Config) (*gorm.DB, error) {
// db 日志写入轮转文件
w, err := logrotate.New(filepath.Join(app.Root, "panel/storage/logs/db.log"),
logrotate.WithMaxSize(10*logrotate.MB),
+5 -5
View File
@@ -10,6 +10,7 @@ import (
"net/http"
"path/filepath"
"strings"
"time"
"github.com/bddjr/hlfhr"
"github.com/go-chi/chi/v5"
@@ -80,7 +81,6 @@ func NewRouter(loader *apploader.Loader, conf *config.Config, t *gotext.Locale,
}
func NewTLSReloader(conf *config.Config) (*tlscert.Reloader, error) {
if !conf.HTTP.IsHTTPS() {
return nil, nil
}
@@ -95,13 +95,13 @@ func NewTLSReloader(conf *config.Config) (*tlscert.Reloader, error) {
}
func NewHttp(router *chi.Mux, conf *config.Config, reloader *tlscert.Reloader) *hlfhr.Server {
mux := router
srv := hlfhr.New(&http.Server{
Addr: fmt.Sprintf(":%d", conf.HTTP.Port),
Handler: mux,
MaxHeaderBytes: 4 << 20,
Addr: fmt.Sprintf(":%d", conf.HTTP.Port),
Handler: mux,
MaxHeaderBytes: 4 << 20,
ReadHeaderTimeout: 30 * time.Second,
})
srv.Listen80RedirectTo443 = true
+2 -3
View File
@@ -16,7 +16,7 @@ type Logger struct {
}
// NewLogger 构建写入轮转文件的应用日志。
func NewLogger(conf *config.Config) (*Logger, func(), error) {
func NewLogger(conf *config.Config) (*Logger, func() error, error) {
w, err := logrotate.New(filepath.Join(app.Root, "panel/storage/logs/app.log"),
logrotate.WithMaxSize(10*logrotate.MB),
logrotate.WithMaxAge(30*logrotate.Day),
@@ -38,8 +38,7 @@ func NewLogger(conf *config.Config) (*Logger, func(), error) {
}))
slog.SetDefault(log)
cleanup := func() { _ = w.Close() }
return &Logger{Logger: log}, cleanup, nil
return &Logger{Logger: log}, w.Close, nil
}
// NewSlog 解包出纯 *slog.Logger 供应用其余部分使用。
-1
View File
@@ -8,7 +8,6 @@ import (
)
func NewT(conf *config.Config) *gotext.Locale {
l := gotext.NewLocaleFSWithPath(conf.App.Locale, embed.LocalesFS, "locales")
l.AddDomain("backend")
+60
View File
@@ -0,0 +1,60 @@
//go:build wireinject
package bootstrap
import (
"log/slog"
"github.com/bddjr/hlfhr"
"github.com/go-chi/chi/v5"
"github.com/go-gormigrate/gormigrate/v2"
"github.com/leonelquinteros/gotext"
"github.com/libtnb/cron"
"github.com/libtnb/sessions"
"github.com/libtnb/validator"
"github.com/libtnb/wire"
"github.com/urfave/cli/v3"
"gorm.io/gorm"
"github.com/acepanel/panel/v3/internal/middleware"
"github.com/acepanel/panel/v3/pkg/apploader"
"github.com/acepanel/panel/v3/pkg/config"
"github.com/acepanel/panel/v3/pkg/tlscert"
"github.com/acepanel/panel/v3/pkg/types"
"github.com/acepanel/panel/v3/pkg/websitestat"
)
// Module 装配基础设施层,*Logger 与 *middleware.Middlewares 仅本层内部使用,不导出
var Module = wire.New().
Provide(NewConf).
Provide(NewT).
Provide(NewLogger).
Provide(NewSlog).
Provide(NewDB).
Provide(NewMigrate).
Provide(NewSession).
Provide(NewRunner).
Provide(NewValidator).
Provide(middleware.NewMiddlewares).
Provide(NewLoader).
Provide(NewRouter).
Provide(NewTLSReloader).
Provide(NewHttp).
Provide(NewCron).
Provide(NewCli).
Provide(websitestat.NewAggregator).
Export[*config.Config]().
Export[*gotext.Locale]().
Export[*slog.Logger]().
Export[*gorm.DB]().
Export[*gormigrate.Gormigrate]().
Export[*sessions.Manager]().
Export[types.TaskRunner]().
Export[*validator.Validator]().
Export[*apploader.Loader]().
Export[*chi.Mux]().
Export[*tlscert.Reloader]().
Export[*hlfhr.Server]().
Export[*cron.Cron]().
Export[*cli.Command]().
Export[*websitestat.Aggregator]()
-1
View File
@@ -11,7 +11,6 @@ import (
// AppCommand 应用管理命令组
func AppCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "app",
Usage: t.Get("Application management"),
-1
View File
@@ -11,7 +11,6 @@ import (
// BackupCommand 数据备份命令组
func BackupCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "backup",
Usage: t.Get("Data backup"),
-1
View File
@@ -11,7 +11,6 @@ import (
// CertCommand 证书管理命令组
func CertCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "cert",
Usage: t.Get("Certificate management"),
-3
View File
@@ -1,15 +1,12 @@
package command
import (
"github.com/google/wire"
"github.com/leonelquinteros/gotext"
"github.com/urfave/cli/v3"
"github.com/acepanel/panel/v3/internal/service"
)
var ProviderSet = wire.NewSet(Commands)
// Commands 组装全部 CLI 命令。
func Commands(t *gotext.Locale, cliService *service.CliService) []*cli.Command {
return []*cli.Command{
-1
View File
@@ -11,7 +11,6 @@ import (
// CronCommand 计划任务命令组
func CronCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "cron",
Usage: t.Get("Cron task"),
-1
View File
@@ -11,7 +11,6 @@ import (
// CutoffCommand 日志切割命令组
func CutoffCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "cutoff",
Usage: t.Get("Log rotation"),
-1
View File
@@ -11,7 +11,6 @@ import (
// DatabaseCommand 数据库管理命令组
func DatabaseCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "database",
Usage: t.Get("Database management"),
-4
View File
@@ -11,7 +11,6 @@ import (
// EntranceCommand 访问入口管理命令组
func EntranceCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "entrance",
Usage: t.Get("Operate AcePanel access entrance"),
@@ -37,7 +36,6 @@ func EntranceCommand(t *gotext.Locale, cliService *service.CliService) *cli.Comm
// BindDomainCommand 域名绑定管理命令组
func BindDomainCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "bind-domain",
Usage: t.Get("Operate AcePanel domain binding"),
@@ -63,7 +61,6 @@ func BindDomainCommand(t *gotext.Locale, cliService *service.CliService) *cli.Co
// BindIPCommand IP 绑定管理命令组
func BindIPCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "bind-ip",
Usage: t.Get("Operate AcePanel IP binding"),
@@ -89,7 +86,6 @@ func BindIPCommand(t *gotext.Locale, cliService *service.CliService) *cli.Comman
// BindUACommand UA 绑定管理命令组
func BindUACommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "bind-ua",
Usage: t.Get("Operate AcePanel UA binding"),
-1
View File
@@ -11,7 +11,6 @@ import (
// FirewallCommand 防火墙管理命令组
func FirewallCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "firewall",
Usage: t.Get("Firewall management"),
-1
View File
@@ -11,7 +11,6 @@ import (
// HttpsCommand 面板 HTTPS 管理命令组
func HttpsCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "https",
Usage: t.Get("Operate AcePanel HTTPS"),
-8
View File
@@ -11,7 +11,6 @@ import (
// UpdateCommand 更新面板
func UpdateCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "update",
Usage: t.Get("Update AcePanel to the latest version"),
@@ -23,7 +22,6 @@ func UpdateCommand(t *gotext.Locale, cliService *service.CliService) *cli.Comman
// SyncCommand 同步云端缓存数据
func SyncCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "sync",
Usage: t.Get("Sync AcePanel cached data with cloud"),
@@ -35,7 +33,6 @@ func SyncCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command
// FixCommand 修复升级问题
func FixCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "fix",
Usage: t.Get("Fix AcePanel upgrade issues"),
@@ -47,7 +44,6 @@ func FixCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
// InfoCommand 输出面板基础信息
func InfoCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "info",
Usage: t.Get("Output AcePanel basic information"),
@@ -71,7 +67,6 @@ func InfoCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command
// PortCommand 修改监听端口
func PortCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "port",
Usage: t.Get("Change the AcePanel listening port"),
@@ -91,7 +86,6 @@ func PortCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command
// SyncTimeCommand 通过 NTP 同步系统时间
func SyncTimeCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "sync-time",
Usage: t.Get("Sync server time with NTP"),
@@ -103,7 +97,6 @@ func SyncTimeCommand(t *gotext.Locale, cliService *service.CliService) *cli.Comm
// ClearTaskCommand 清理卡住的任务队列
func ClearTaskCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "clear-task",
Usage: t.Get("Clear all tasks in the task queue if they are stuck (use only under guidance)"),
@@ -116,7 +109,6 @@ func ClearTaskCommand(t *gotext.Locale, cliService *service.CliService) *cli.Com
// InitCommand 初始化面板
func InitCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "init",
Usage: t.Get("Initialize AcePanel (use only under guidance)"),
-1
View File
@@ -11,7 +11,6 @@ import (
// RestoreCommand 数据恢复命令组
func RestoreCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "restore",
Usage: t.Get("Data restore"),
-4
View File
@@ -11,7 +11,6 @@ import (
// StatusCommand 查询服务状态
func StatusCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "status",
Usage: t.Get("Get AcePanel service status"),
@@ -23,7 +22,6 @@ func StatusCommand(t *gotext.Locale, cliService *service.CliService) *cli.Comman
// RestartCommand 重启服务
func RestartCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "restart",
Usage: t.Get("Restart AcePanel service"),
@@ -35,7 +33,6 @@ func RestartCommand(t *gotext.Locale, cliService *service.CliService) *cli.Comma
// StopCommand 停止服务
func StopCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "stop",
Usage: t.Get("Stop AcePanel service"),
@@ -47,7 +44,6 @@ func StopCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command
// StartCommand 启动服务
func StartCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "start",
Usage: t.Get("Start AcePanel service"),
-1
View File
@@ -11,7 +11,6 @@ import (
// SettingCommand 面板设置管理命令组
func SettingCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "setting",
Usage: t.Get("Setting management"),
-1
View File
@@ -11,7 +11,6 @@ import (
// UserCommand 用户管理命令组
func UserCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "user",
Usage: t.Get("Operate AcePanel users"),
-1
View File
@@ -11,7 +11,6 @@ import (
// WebsiteCommand 网站管理命令组
func WebsiteCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
return &cli.Command{
Name: "website",
Usage: t.Get("Website management"),
+13
View File
@@ -0,0 +1,13 @@
//go:build wireinject
package command
import (
"github.com/libtnb/wire"
"github.com/urfave/cli/v3"
)
// Module 装配 CLI 命令
var Module = wire.New().
Provide(Commands).
Export[[]*cli.Command]()
-1
View File
@@ -48,7 +48,6 @@ func (r *appRepo) Installed() ([]*biz.App, error) {
}
return apps, nil
}
func (r *appRepo) GetInstalled(slug string) (*biz.App, error) {
+23 -23
View File
@@ -142,9 +142,9 @@ func (r *backupRepo) Create(ctx context.Context, typ biz.BackupType, target stri
case biz.BackupTypeWebsite:
err = r.createWebsite(name, client, target)
case biz.BackupTypeMySQL:
err = r.createMySQL(name, client, target)
err = r.createMySQL(ctx, name, client, target)
case biz.BackupTypePostgres:
err = r.createPostgres(name, client, target)
err = r.createPostgres(ctx, name, client, target)
case biz.BackupTypeClickHouse:
err = r.createClickHouse(name, client, target)
case biz.BackupTypeRedis:
@@ -251,7 +251,7 @@ func (r *backupRepo) Delete(typ biz.BackupType, name string) error {
// typ 备份类型
// backup 备份压缩包,可以是绝对路径或者相对路径
// target 目标名称
func (r *backupRepo) Restore(typ biz.BackupType, backup, target string) error {
func (r *backupRepo) Restore(ctx context.Context, typ biz.BackupType, backup, target string) error {
if !io.Exists(backup) {
backup = filepath.Join(r.GetDefaultPath(typ), backup)
}
@@ -274,11 +274,11 @@ func (r *backupRepo) Restore(typ biz.BackupType, backup, target string) error {
case biz.BackupTypeWebsite:
err = r.restoreWebsite(backup, target)
case biz.BackupTypeMySQL:
err = r.restoreMySQL(backup, target)
err = r.restoreMySQL(ctx, backup, target)
case biz.BackupTypePostgres:
err = r.restorePostgres(backup, target)
err = r.restorePostgres(ctx, backup, target)
case biz.BackupTypeClickHouse:
err = r.restoreClickHouse(backup, target)
err = r.restoreClickHouse(ctx, backup, target)
case biz.BackupTypeRedis:
err = r.restoreRedisLike(backup, "redis")
case biz.BackupTypeValkey:
@@ -574,12 +574,12 @@ func (r *backupRepo) createWebsite(name string, storage storage.Storage, target
}
// createMySQL 创建 MySQL 备份
func (r *backupRepo) createMySQL(name string, storage storage.Storage, target string) error {
func (r *backupRepo) createMySQL(ctx context.Context, name string, storage storage.Storage, target string) error {
rootPassword, err := r.setting.Get(biz.SettingKeyMySQLRootPassword)
if err != nil {
return err
}
mysql, err := db.NewMySQL(context.Background(), "root", rootPassword, db.MySQLSocket(app.Root), "unix")
mysql, err := db.NewMySQL(ctx, "root", rootPassword, db.MySQLSocket(app.Root), "unix")
if err != nil {
return err
}
@@ -641,13 +641,13 @@ func (r *backupRepo) createMySQL(name string, storage storage.Storage, target st
}
// createPostgres 创建 PostgreSQL 备份
func (r *backupRepo) createPostgres(name string, storage storage.Storage, target string) error {
func (r *backupRepo) createPostgres(ctx context.Context, name string, storage storage.Storage, target string) error {
postgresPassword, err := r.setting.Get(biz.SettingKeyPostgresPassword)
if err != nil {
return err
}
port := db.PostgresPort(app.Root)
postgres, err := db.NewPostgres(context.Background(), "postgres", postgresPassword, "127.0.0.1", port)
postgres, err := db.NewPostgres(ctx, "postgres", postgresPassword, "127.0.0.1", port)
if err != nil {
return err
}
@@ -927,7 +927,7 @@ func (r *backupRepo) restoreWebsite(backup, target string) error {
// importFile 把备份文件喂给数据库客户端 stdin,并按秒级周期打印大致进度
// pipe 有背压,已写入字节数 ≈ 客户端已消费字节数,足以作为进度参考
func (r *backupRepo) importFile(path, name string, env, args []string) error {
func (r *backupRepo) importFile(ctx context.Context, path, name string, env, args []string) error {
f, err := os.Open(path)
if err != nil {
return err
@@ -954,17 +954,17 @@ func (r *backupRepo) importFile(path, name string, env, args []string) error {
}
}
_, err = shell.ExecWithStdinProgress(context.Background(), name, args, env, f, total, 5*time.Second, progress)
_, err = shell.ExecWithStdinProgress(ctx, name, args, env, f, total, 5*time.Second, progress)
return err
}
// restoreMySQL 恢复 MySQL 备份
func (r *backupRepo) restoreMySQL(backup, target string) error {
func (r *backupRepo) restoreMySQL(ctx context.Context, backup, target string) error {
rootPassword, err := r.setting.Get(biz.SettingKeyMySQLRootPassword)
if err != nil {
return err
}
mysql, err := db.NewMySQL(context.Background(), "root", rootPassword, db.MySQLSocket(app.Root), "unix")
mysql, err := db.NewMySQL(ctx, "root", rootPassword, db.MySQLSocket(app.Root), "unix")
if err != nil {
return err
}
@@ -987,17 +987,17 @@ func (r *backupRepo) restoreMySQL(backup, target string) error {
if app.IsCli {
fmt.Println(r.t.Get("|-Importing SQL into database..."))
}
return r.importFile(backup, "mysql", []string{"MYSQL_PWD=" + rootPassword}, []string{"-u", "root", "--max-allowed-packet=1G", "--database=" + target})
return r.importFile(ctx, backup, "mysql", []string{"MYSQL_PWD=" + rootPassword}, []string{"-u", "root", "--max-allowed-packet=1G", "--database=" + target})
}
// restorePostgres 恢复 PostgreSQL 备份
func (r *backupRepo) restorePostgres(backup, target string) error {
func (r *backupRepo) restorePostgres(ctx context.Context, backup, target string) error {
postgresPassword, err := r.setting.Get(biz.SettingKeyPostgresPassword)
if err != nil {
return err
}
port := db.PostgresPort(app.Root)
postgres, err := db.NewPostgres(context.Background(), "postgres", postgresPassword, "127.0.0.1", port)
postgres, err := db.NewPostgres(ctx, "postgres", postgresPassword, "127.0.0.1", port)
if err != nil {
return err
}
@@ -1026,19 +1026,19 @@ func (r *backupRepo) restorePostgres(backup, target string) error {
fmt.Println(r.t.Get("|-Importing PostgreSQL backup..."))
}
if archive {
command := exec.Command("pg_restore", "--exit-on-error", "-h", "127.0.0.1", "-p", cast.ToString(port), "-U", "postgres", "--dbname="+target, backup)
command := exec.CommandContext(ctx, "pg_restore", "--exit-on-error", "-h", "127.0.0.1", "-p", cast.ToString(port), "-U", "postgres", "--dbname="+target, backup)
shell.ApplyEnv(command, "PGPASSWORD="+postgresPassword)
if output, restoreErr := command.CombinedOutput(); restoreErr != nil {
return fmt.Errorf("%w: %s", restoreErr, strings.TrimSpace(string(output)))
}
return nil
}
return r.importFile(backup, "psql", []string{"PGPASSWORD=" + postgresPassword},
return r.importFile(ctx, backup, "psql", []string{"PGPASSWORD=" + postgresPassword},
[]string{"-h", "127.0.0.1", "-p", cast.ToString(port), "-U", "postgres", "-v", "ON_ERROR_STOP=1", "--single-transaction", "--dbname=" + target})
}
// restoreClickHouse 恢复 ClickHouse 备份
func (r *backupRepo) restoreClickHouse(backup, target string) error {
func (r *backupRepo) restoreClickHouse(ctx context.Context, backup, target string) error {
password, err := r.setting.Get(biz.SettingKeyClickHouseDefaultPassword)
if err != nil {
return err
@@ -1060,7 +1060,7 @@ func (r *backupRepo) restoreClickHouse(backup, target string) error {
if app.IsCli {
fmt.Println(r.t.Get("|-Importing SQL into database..."))
}
return r.importFile(backup, "clickhouse-client", nil, append(slices.Clone(connArgs), "--database", target, "--multiquery"))
return r.importFile(ctx, backup, "clickhouse-client", nil, append(slices.Clone(connArgs), "--database", target, "--multiquery"))
}
// 解压到临时目录
@@ -1084,7 +1084,7 @@ func (r *backupRepo) restoreClickHouse(backup, target string) error {
if app.IsCli {
fmt.Println(r.t.Get("|-Restoring schema..."))
}
if err = r.importFile(schemaPath, "clickhouse-client", nil, append(slices.Clone(connArgs), "--database", target, "--multiquery")); err != nil {
if err = r.importFile(ctx, schemaPath, "clickhouse-client", nil, append(slices.Clone(connArgs), "--database", target, "--multiquery")); err != nil {
return err
}
}
@@ -1103,7 +1103,7 @@ func (r *backupRepo) restoreClickHouse(backup, target string) error {
fmt.Println(r.t.Get("|-Importing table: %s", tbl))
}
query := fmt.Sprintf("INSERT INTO `%s` FORMAT Native", tbl)
if err = r.importFile(filepath.Join(tmpDir, entry.Name()), "clickhouse-client", nil, append(slices.Clone(connArgs), "--database", target, "--query", query)); err != nil {
if err = r.importFile(ctx, filepath.Join(tmpDir, entry.Name()), "clickhouse-client", nil, append(slices.Clone(connArgs), "--database", target, "--query", query)); err != nil {
return err
}
}
+8 -2
View File
@@ -82,7 +82,10 @@ func (r certAccountRepo) GetGoogleEAB() (*acme.EAB, error) {
if err != nil || !resp.IsStatusSuccess() {
return &acme.EAB{}, errors.New(r.t.Get("failed to get Google EAB: %v", err))
}
eab := resp.Result().(*data)
eab, ok := resp.Result().(*data)
if !ok {
return &acme.EAB{}, errors.New(r.t.Get("failed to get Google EAB: %s", r.t.Get("invalid response")))
}
if eab.Msg != "success" {
return &acme.EAB{}, errors.New(r.t.Get("failed to get Google EAB: %s", eab.Msg))
}
@@ -108,7 +111,10 @@ func (r certAccountRepo) GetZeroSSLEAB(email string) (*acme.EAB, error) {
if err != nil || !resp.IsStatusSuccess() {
return &acme.EAB{}, errors.New(r.t.Get("failed to get ZeroSSL EAB: %v", err))
}
eab := resp.Result().(*data)
eab, ok := resp.Result().(*data)
if !ok {
return &acme.EAB{}, errors.New(r.t.Get("failed to get ZeroSSL EAB"))
}
if !eab.Success {
return &acme.EAB{}, errors.New(r.t.Get("failed to get ZeroSSL EAB"))
}
+3 -3
View File
@@ -57,11 +57,11 @@ func (r *containerRepo) ListAll(sock string) ([]types.Container, error) {
}
}
slices.SortFunc(ports, func(a, b types.ContainerPort) int {
aOffset := int64(a.HostStart) - int64(a.ContainerStart)
aOffset := int64(a.HostStart) - int64(a.ContainerStart) //nolint:gosec
if a.HostStart == 0 {
aOffset = 0
}
bOffset := int64(b.HostStart) - int64(b.ContainerStart)
bOffset := int64(b.HostStart) - int64(b.ContainerStart) //nolint:gosec
if b.HostStart == 0 {
bOffset = 0
}
@@ -142,7 +142,7 @@ func (r *containerRepo) Create(sock string, req *request.ContainerCreate) (strin
// 获取镜像信息
image, err := apiClient.ImageInspect(ctx, req.Image)
if err != nil {
return "", fmt.Errorf("failed to inspect image: %v", err)
return "", fmt.Errorf("failed to inspect image: %w", err)
}
// 兼容一些没有指定命令和入口点的镜像
if image.Config != nil {
+1 -1
View File
@@ -93,7 +93,7 @@ func (r *containerImageRepo) Pull(sock string, req *request.ContainerImagePull)
Username: req.Username,
Password: req.Password,
}
encodedJSON, err := json.Marshal(authConfig)
encodedJSON, err := json.Marshal(authConfig) //nolint:gosec
if err != nil {
return err
}
-20
View File
@@ -1,20 +0,0 @@
package data
import "github.com/google/wire"
var ProviderSet = wire.NewSet(
NewAlertRepo, NewAppRepo, NewBackupRepo, NewBackupAccountRepo,
NewCacheRepo, NewCertRepo, NewCertAccountRepo,
NewCertDNSRepo, NewContainerRepo, NewContainerComposeRepo,
NewContainerImageRepo, NewContainerNetworkRepo, NewContainerVolumeRepo,
NewCronRepo, NewDatabaseRepo, NewDatabaseRedisRepo,
NewDatabaseElasticsearchRepo, NewDatabaseServerRepo, NewDatabaseUserRepo,
NewEnvironmentRepo, NewFileShareRepo, NewLogRepo, NewMonitorRepo,
NewNotifyChannelRepo,
NewProjectRepo, NewSafeRepo, NewScanEventRepo,
NewSettingRepo, NewSSHRepo, NewTamperRepo, NewTaskRepo,
NewTemplateRepo, NewUserRepo, NewUserPasskeyRepo,
NewUserTokenRepo, NewWebHookRepo, NewWebsiteRepo,
NewWebsiteStatRepo,
NewMigrationSourceRepo, NewMigrationRemoteRepo, NewMigrationArchiveRepo,
)
+3 -3
View File
@@ -43,7 +43,7 @@ func (r *databaseRepo) DatabasesOf(ctx context.Context, server *biz.DatabaseServ
if err != nil {
return nil, err
}
if databases, err := mongo.Databases(); err == nil {
if databases, err := mongo.Databases(); err == nil { //nolint:contextcheck
for item := range slices.Values(databases) {
database = append(database, &biz.Database{
Type: server.Type,
@@ -55,11 +55,11 @@ func (r *databaseRepo) DatabasesOf(ctx context.Context, server *biz.DatabaseServ
}
mongo.Close()
case biz.DatabaseTypeSQLite:
sqlite, err := db.NewSQLite(server.Host)
sqlite, err := db.NewSQLite(server.Host) //nolint:contextcheck
if err != nil {
return nil, err
}
if tables, err := sqlite.Tables(); err == nil {
if tables, err := sqlite.Tables(); err == nil { //nolint:contextcheck
for table := range slices.Values(tables) {
database = append(database, &biz.Database{
Type: server.Type,
+1 -1
View File
@@ -146,7 +146,7 @@ func (r *databaseServerRepo) CheckServer(ctx context.Context, server *biz.Databa
return true
}
case biz.DatabaseTypeSQLite:
sqlite, err := db.NewSQLite(server.Host)
sqlite, err := db.NewSQLite(server.Host) //nolint:contextcheck
if err == nil {
sqlite.Close()
server.Status = biz.DatabaseServerStatusValid
+1
View File
@@ -178,6 +178,7 @@ func (r *databaseUserRepo) fillUser(ctx context.Context, user *biz.DatabaseUser)
} else {
user.Status = biz.DatabaseUserStatusInvalid
}
default:
}
}
+6 -3
View File
@@ -2,6 +2,7 @@ package data
import (
"encoding/json"
"errors"
"github.com/samber/lo"
"gorm.io/gorm"
@@ -88,13 +89,15 @@ func (r *notifyChannelRepo) Delete(id uint) error {
func (r *notifyChannelRepo) removeEventChannel(tx *gorm.DB, id uint) error {
setting := new(biz.Setting)
if err := tx.Where("key = ?", biz.SettingKeyNotifyEventChannels).First(setting).Error; err != nil {
// 未配置过事件通知
return nil
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil
}
return err
}
channels := make([]uint, 0)
if json.Unmarshal([]byte(setting.Value), &channels) != nil {
return nil
return nil //nolint:nilerr
}
remain := lo.Without(channels, id)
+3 -3
View File
@@ -105,9 +105,9 @@ func (r *projectRepo) Save(project *biz.Project) error {
}
// RenameUnitFile 重命名 systemd unit 文件
func (r *projectRepo) RenameUnitFile(old, new string) error {
oldPath := r.unitFilePath(old)
newPath := r.unitFilePath(new)
func (r *projectRepo) RenameUnitFile(oldName, newName string) error {
oldPath := r.unitFilePath(oldName)
newPath := r.unitFilePath(newName)
if err := os.Rename(oldPath, newPath); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("%s: %w", r.t.Get("failed to rename systemd config"), err)
}
+1 -1
View File
@@ -105,7 +105,7 @@ func (r *scanEventRepo) List(start, end, sourceIP string, port uint, location st
return nil, 0, err
}
return items, uint(total), nil
return items, uint(total), nil //nolint:gosec
}
func (r *scanEventRepo) Summary(start, end string) (*biz.ScanSummary, error) {
-1
View File
@@ -17,7 +17,6 @@ type tamperRepo struct {
// NewTamperRepo 创建防篡改数据访问实例
func NewTamperRepo(db *gorm.DB) (biz.TamperRepo, error) {
logDB, err := openSharedDB("tamper")
if err != nil {
return nil, err
+1 -1
View File
@@ -196,7 +196,7 @@ func (c *migrationClient) download(ctx context.Context, remote, local string, pr
func (c *migrationClient) client(timeout time.Duration) *resty.Client {
return resty.New().
SetBaseURL(c.origin()).
SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}). //nolint:gosec
SetTimeout(timeout)
}
+1 -1
View File
@@ -40,7 +40,7 @@ func (r *migrationArchiveRepo) Extract(ctx context.Context, archive, target stri
}
entries, err := os.ReadDir(target)
if err != nil || len(entries) != 1 || !entries[0].IsDir() {
return target, nil
return target, nil //nolint:nilerr
}
return filepath.Join(target, entries[0].Name()), nil
}
+6 -6
View File
@@ -2,7 +2,7 @@ package data
import (
"context"
"crypto/md5"
"crypto/md5" //nolint:gosec
"encoding/hex"
"encoding/json"
"errors"
@@ -47,8 +47,8 @@ func newBaotaClient(conn *request.ToolboxMigrationConnection) *migrationClient {
// 认证一律走 query,resty 在签名时还未确定请求方法,无法按方法分流
sign: func(req *resty.Request) {
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
secret := md5.Sum([]byte(conn.APIKey))
token := md5.Sum([]byte(timestamp + hex.EncodeToString(secret[:])))
secret := md5.Sum([]byte(conn.APIKey)) //nolint:gosec
token := md5.Sum([]byte(timestamp + hex.EncodeToString(secret[:]))) //nolint:gosec
req.SetQueryParams(map[string]string{"request_time": timestamp, "request_token": hex.EncodeToString(token[:])})
},
// 宝塔失败响应为 {status: false, msg: "..."},部分接口的业务数据也含 status 字段,需同时判断 msg
@@ -287,7 +287,7 @@ func (a *baotaAdapter) Detail(ctx context.Context, item types.MigrationItem) (*t
var err error
switch item.Type {
case "website":
detail.Website, err = a.websiteDetail(ctx, item)
detail.Website = a.websiteDetail(ctx, item)
case "database":
detail.Database, err = a.databaseDetail(ctx, item)
case "database_user":
@@ -300,7 +300,7 @@ func (a *baotaAdapter) Detail(ctx context.Context, item types.MigrationItem) (*t
return detail, err
}
func (a *baotaAdapter) websiteDetail(ctx context.Context, item types.MigrationItem) (*types.MigrationWebsite, error) {
func (a *baotaAdapter) websiteDetail(ctx context.Context, item types.MigrationItem) *types.MigrationWebsite {
website := &types.MigrationWebsite{
Type: item.Subtype, Path: item.SourcePath, Root: item.SourcePath,
Domains: []string{item.Name}, Listens: []string{"80"},
@@ -367,7 +367,7 @@ func (a *baotaAdapter) websiteDetail(ctx context.Context, item types.MigrationIt
}
website.Redirects = a.redirects(ctx, item.Name)
a.applySSL(ctx, item.Name, website)
return website, nil
return website
}
// domains 读取站点绑定的域名与端口
+2 -2
View File
@@ -2,7 +2,7 @@ package data
import (
"context"
"crypto/md5"
"crypto/md5" //nolint:gosec
"encoding/hex"
"encoding/json"
"errors"
@@ -37,7 +37,7 @@ func newOnePanelClient(conn *request.ToolboxMigrationConnection) *migrationClien
url: conn.URL,
sign: func(req *resty.Request) {
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
token := md5.Sum([]byte("1panel" + conn.APIKey + timestamp))
token := md5.Sum([]byte("1panel" + conn.APIKey + timestamp)) //nolint:gosec
req.SetHeader("1Panel-Timestamp", timestamp).SetHeader("1Panel-Token", hex.EncodeToString(token[:]))
},
unwrap: func(body []byte) (any, error) {
+1 -1
View File
@@ -44,7 +44,7 @@ func NewMigrationRemoteRepo(t *gotext.Locale) biz.MigrationRemoteRepo {
func (r *migrationRemoteRepo) client(conn *request.ToolboxMigrationConnection, timeout time.Duration) *resty.Client {
client := resty.New().
SetBaseURL(strings.TrimRight(conn.URL, "/")).
SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}).
SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}). //nolint:gosec
SetHeader("Content-Type", "application/json")
if timeout > 0 {
client.SetTimeout(timeout)
+2 -2
View File
@@ -118,9 +118,9 @@ func (r *webhookRepo) Call(key string) (string, error) {
// 执行脚本
var cmd *exec.Cmd
if webhook.User == "" || webhook.User == "root" {
cmd = exec.Command("bash", scriptFile)
cmd = exec.Command("bash", scriptFile) //nolint:noctx
} else {
cmd = exec.Command("su", "-s", "/bin/bash", "-c", "bash "+scriptFile, webhook.User)
cmd = exec.Command("su", "-s", "/bin/bash", "-c", "bash "+scriptFile, webhook.User) //nolint:noctx
}
shell.ApplyEnv(cmd)
+7 -2
View File
@@ -47,12 +47,12 @@ func NewWebsiteRepo(db *gorm.DB, t *gotext.Locale, settingRepo biz.SettingRepo)
func (r *websiteRepo) GetRewrites() (map[string]string, error) {
d, err := r.dialect()
if err != nil {
return make(map[string]string), nil
return make(map[string]string), nil //nolint:nilerr
}
entries, err := embed.RewritesFS.ReadDir(filepath.Join("rewrites", d.RewritesDir()))
if err != nil {
return make(map[string]string), nil
return make(map[string]string), nil //nolint:nilerr
}
rw := make(map[string]string)
@@ -548,6 +548,8 @@ func (r *websiteRepo) SwitchType(req *request.WebsiteSwitchType) (*biz.Website,
Location: "^~ /",
Pass: req.Proxy,
}}
default:
// 静态站点沿用默认配置
}
configDir := filepath.Join(app.Root, "sites", website.Name, "config")
@@ -1189,6 +1191,7 @@ func (r *websiteRepo) ResetConfig(id uint) error {
Pass: setting.Proxies[0].Pass,
}}
}
default:
}
if website.Type == biz.WebsiteTypePHP {
@@ -1462,6 +1465,8 @@ func writeTypeConfigs(d webserver.Dialect, vhost webservertypes.Vhost, typ biz.W
return vhost.SetConfig("010-cache.conf", webservertypes.ScopeSite, d.PHPCacheConf())
case biz.WebsiteTypeStatic:
return vhost.SetRawConfig("800-spa.conf", webservertypes.ScopeSite, d.SPAConf())
default:
// 反代站点无需额外片段
}
return nil
+4 -4
View File
@@ -263,7 +263,7 @@ func (r *websiteStatRepo) TopIPs(start, end string, sites []string, page, limit
}
offset := (page - 1) * limit
err := dataQ.Group("ip").Order("requests DESC").Offset(int(offset)).Limit(int(limit)).Scan(&items).Error
return items, uint(total), err
return items, uint(total), err //nolint:gosec
}
func (r *websiteStatRepo) ClearIPsBefore(date string) error {
@@ -341,7 +341,7 @@ func (r *websiteStatRepo) TopURIs(start, end string, sites []string, page, limit
}
offset := (page - 1) * limit
err := dataQ.Group("uri").Order("requests DESC").Offset(int(offset)).Limit(int(limit)).Scan(&items).Error
return items, uint(total), err
return items, uint(total), err //nolint:gosec
}
func (r *websiteStatRepo) ClearURIsBefore(date string) error {
@@ -383,7 +383,7 @@ func (r *websiteStatRepo) TopSlowURIs(start, end string, sites []string, thresho
err := dataQ.Group("uri").Having(having, havingArgs...).
Order("CAST(SUM(request_time_sum) AS REAL) / SUM(request_time_count) DESC").
Offset(int(offset)).Limit(int(limit)).Scan(&items).Error
return items, uint(total), err
return items, uint(total), err //nolint:gosec
}
// ========== 错误日志查询 ==========
@@ -405,7 +405,7 @@ func (r *websiteStatRepo) ListErrors(start, end string, sites []string, status i
var items []*biz.WebsiteErrorLog
offset := (page - 1) * limit
err := q.Order("created_at DESC").Offset(int(offset)).Limit(int(limit)).Find(&items).Error
return items, uint(total), err
return items, uint(total), err //nolint:gosec
}
// ========== 网站维度汇总 ==========
+94
View File
@@ -0,0 +1,94 @@
//go:build wireinject
package data
import (
"github.com/libtnb/wire"
"github.com/acepanel/panel/v3/internal/biz"
)
// Module 装配数据访问层,对外导出 biz 中定义的仓储接口
var Module = wire.New().
Provide(NewAlertRepo).
Provide(NewAppRepo).
Provide(NewBackupRepo).
Provide(NewBackupAccountRepo).
Provide(NewCacheRepo).
Provide(NewCertRepo).
Provide(NewCertAccountRepo).
Provide(NewCertDNSRepo).
Provide(NewContainerRepo).
Provide(NewContainerComposeRepo).
Provide(NewContainerImageRepo).
Provide(NewContainerNetworkRepo).
Provide(NewContainerVolumeRepo).
Provide(NewCronRepo).
Provide(NewDatabaseRepo).
Provide(NewDatabaseRedisRepo).
Provide(NewDatabaseElasticsearchRepo).
Provide(NewDatabaseServerRepo).
Provide(NewDatabaseUserRepo).
Provide(NewEnvironmentRepo).
Provide(NewFileShareRepo).
Provide(NewLogRepo).
Provide(NewMonitorRepo).
Provide(NewNotifyChannelRepo).
Provide(NewProjectRepo).
Provide(NewSafeRepo).
Provide(NewScanEventRepo).
Provide(NewSettingRepo).
Provide(NewSSHRepo).
Provide(NewTamperRepo).
Provide(NewTaskRepo).
Provide(NewTemplateRepo).
Provide(NewUserRepo).
Provide(NewUserPasskeyRepo).
Provide(NewUserTokenRepo).
Provide(NewWebHookRepo).
Provide(NewWebsiteRepo).
Provide(NewWebsiteStatRepo).
Provide(NewMigrationSourceRepo).
Provide(NewMigrationRemoteRepo).
Provide(NewMigrationArchiveRepo).
Export[biz.AlertRepo]().
Export[biz.AppRepo]().
Export[biz.BackupRepo]().
Export[biz.BackupAccountRepo]().
Export[biz.CacheRepo]().
Export[biz.CertRepo]().
Export[biz.CertAccountRepo]().
Export[biz.CertDNSRepo]().
Export[biz.ContainerRepo]().
Export[biz.ContainerComposeRepo]().
Export[biz.ContainerImageRepo]().
Export[biz.ContainerNetworkRepo]().
Export[biz.ContainerVolumeRepo]().
Export[biz.CronRepo]().
Export[biz.DatabaseRepo]().
Export[biz.DatabaseRedisRepo]().
Export[biz.DatabaseElasticsearchRepo]().
Export[biz.DatabaseServerRepo]().
Export[biz.DatabaseUserRepo]().
Export[biz.EnvironmentRepo]().
Export[biz.FileShareRepo]().
Export[biz.LogRepo]().
Export[biz.MonitorRepo]().
Export[biz.NotifyChannelRepo]().
Export[biz.ProjectRepo]().
Export[biz.SafeRepo]().
Export[biz.ScanEventRepo]().
Export[biz.SettingRepo]().
Export[biz.SSHRepo]().
Export[biz.TamperRepo]().
Export[biz.TaskRepo]().
Export[biz.TemplateRepo]().
Export[biz.UserRepo]().
Export[biz.UserPasskeyRepo]().
Export[biz.UserTokenRepo]().
Export[biz.WebHookRepo]().
Export[biz.WebsiteRepo]().
Export[biz.WebsiteStatRepo]().
Export[biz.MigrationSourceRepo]().
Export[biz.MigrationRemoteRepo]().
Export[biz.MigrationArchiveRepo]()
+5 -5
View File
@@ -48,7 +48,7 @@ func NewCertRenew(certAccountUsecase *biz.CertAccountUsecase, certUsecase *biz.C
}
}
func (r *CertRenew) Run(_ context.Context) error {
func (r *CertRenew) Run(ctx context.Context) error {
if app.Status != app.StatusNormal {
return nil
}
@@ -67,7 +67,7 @@ func (r *CertRenew) Run(_ context.Context) error {
// 刷新续签信息
if cert.RenewalInfo.NeedsRefresh() {
renewInfo, err := r.certRepo.RefreshRenewalInfo(cert.ID)
renewInfo, err := r.certRepo.RefreshRenewalInfo(ctx, cert.ID)
if err != nil {
r.log.Warn("failed to refresh renewal info", slog.String("type", biz.OperationTypeCert), slog.Uint64("operator_id", 0), slog.Any("err", err))
continue
@@ -77,7 +77,7 @@ func (r *CertRenew) Run(_ context.Context) error {
// 到达建议时间,续签证书
if time.Now().After(cert.RenewalInfo.SelectedTime) {
if _, err := r.certRepo.Renew(cert.ID); err != nil {
if _, err := r.certRepo.RenewWithProgressCallback(ctx, cert.ID, nil); err != nil {
r.log.Warn("failed to renew certificate", slog.String("type", biz.OperationTypeCert), slog.Uint64("operator_id", 0), slog.Any("err", err))
r.notifyFailed(strings.Join(cert.Domains, ", "), err)
}
@@ -98,7 +98,7 @@ func (r *CertRenew) Run(_ context.Context) error {
r.log.Warn("failed to parse panel certificate", slog.String("type", biz.OperationTypeCert), slog.Uint64("operator_id", 0), slog.Any("err", err))
}
newCrt, newKey, err := pkgcert.GenerateSelfSigned(tools.CollectLocalNames())
newCrt, newKey, err := pkgcert.GenerateSelfSigned(tools.CollectLocalNames()) //nolint:contextcheck
if err != nil {
r.log.Warn("failed to generate self-signed certificate", slog.String("type", biz.OperationTypeCert), slog.Uint64("operator_id", 0), slog.Any("err", err))
r.notifyFailed(r.t.Get("panel certificate"), err)
@@ -139,7 +139,7 @@ func (r *CertRenew) Run(_ context.Context) error {
r.log.Warn("failed to get a panel user", slog.String("type", biz.OperationTypeCert), slog.Uint64("operator_id", 0), slog.Any("err", err))
return nil
}
account, err := r.certAccountRepo.GetDefault(user.ID)
account, err := r.certAccountRepo.GetDefault(ctx, user.ID)
if err != nil {
r.log.Warn("failed to get panel ACME account", slog.String("type", biz.OperationTypeCert), slog.Uint64("operator_id", 0), slog.Any("err", err))
r.notifyFailed(r.t.Get("panel certificate"), err)
+3 -3
View File
@@ -72,7 +72,7 @@ func (r *FirewallScan) Run(_ context.Context) error {
if err != nil || !enabled {
// 未启用时,确保 scanner 已停止
r.stopScanner()
return nil
return nil //nolint:nilerr
}
// 确保 scanner 已启动
@@ -245,8 +245,8 @@ func (r *FirewallScan) autoBlock() {
// 解析白名单
whitelist := parseWhitelist(setting.Whitelist)
now := time.Now()
window := time.Duration(setting.BlockWindow) * time.Minute
duration := time.Duration(setting.BlockDuration) * time.Hour
window := time.Duration(setting.BlockWindow) * time.Minute //nolint:gosec
duration := time.Duration(setting.BlockDuration) * time.Hour //nolint:gosec
var toBlock []struct {
ip string
-3
View File
@@ -3,7 +3,6 @@ package job
import (
"log/slog"
"github.com/google/wire"
"github.com/leonelquinteros/gotext"
"github.com/libtnb/cron"
"gorm.io/gorm"
@@ -20,8 +19,6 @@ type Job struct {
Immediate bool // 调度器启动后立即执行一次,不等首个调度点
}
var ProviderSet = wire.NewSet(wire.Struct(new(Dependencies), "*"), NewJobs)
// Dependencies 汇总定时任务依赖,Wire 会在生成期校验完整性。
type Dependencies struct {
Alert *biz.AlertUsecase
+2 -2
View File
@@ -40,7 +40,7 @@ func (r *Monitoring) Run(_ context.Context) error {
monitor, err := r.settingRepo.Get(biz.SettingKeyMonitor)
if err != nil || !cast.ToBool(monitor) {
return nil
return nil //nolint:nilerr
}
// 根据采集间隔判断是否该采集
@@ -77,7 +77,7 @@ func (r *Monitoring) Run(_ context.Context) error {
dayStr, err := r.settingRepo.Get(biz.SettingKeyMonitorDays)
if err != nil {
return nil
return nil //nolint:nilerr
}
day := cast.ToInt(dayStr)
if day <= 0 || app.Status != app.StatusNormal {
+5 -5
View File
@@ -123,7 +123,7 @@ func (r *PanelTask) Run(_ context.Context) error {
// 更新分类缓存
func (r *PanelTask) updateCategories() {
time.AfterFunc(time.Duration(rand.IntN(300))*time.Second, func() {
time.AfterFunc(time.Duration(rand.IntN(300))*time.Second, func() { //nolint:gosec
if err := r.cacheRepo.UpdateCategories(); err != nil {
r.log.Warn("failed to update categories cache", slog.String("type", biz.OperationTypePanel), slog.Uint64("operator_id", 0), slog.Any("err", err))
}
@@ -132,7 +132,7 @@ func (r *PanelTask) updateCategories() {
// 更新商店缓存
func (r *PanelTask) updateApps() {
time.AfterFunc(time.Duration(rand.IntN(300))*time.Second, func() {
time.AfterFunc(time.Duration(rand.IntN(300))*time.Second, func() { //nolint:gosec
if err := r.cacheRepo.UpdateApps(); err != nil {
r.log.Warn("failed to update apps cache", slog.String("type", biz.OperationTypePanel), slog.Uint64("operator_id", 0), slog.Any("err", err))
}
@@ -141,7 +141,7 @@ func (r *PanelTask) updateApps() {
// 更新运行环境缓存
func (r *PanelTask) updateEnvironments() {
time.AfterFunc(time.Duration(rand.IntN(300))*time.Second, func() {
time.AfterFunc(time.Duration(rand.IntN(300))*time.Second, func() { //nolint:gosec
if err := r.cacheRepo.UpdateEnvironments(); err != nil {
r.log.Warn("failed to update environment cache", slog.String("type", biz.OperationTypePanel), slog.Uint64("operator_id", 0), slog.Any("err", err))
}
@@ -150,7 +150,7 @@ func (r *PanelTask) updateEnvironments() {
// 更新模版缓存
func (r *PanelTask) updateTemplates() {
time.AfterFunc(time.Duration(rand.IntN(300))*time.Second, func() {
time.AfterFunc(time.Duration(rand.IntN(300))*time.Second, func() { //nolint:gosec
if err := r.cacheRepo.UpdateTemplates(); err != nil {
r.log.Warn("failed to update template cache", slog.String("type", biz.OperationTypePanel), slog.Uint64("operator_id", 0), slog.Any("err", err))
}
@@ -166,7 +166,7 @@ func (r *PanelTask) updatePanel() {
channel, _ := r.settingRepo.Get(biz.SettingKeyChannel)
// 加 360 秒确保在缓存更新后才更新面板
time.AfterFunc(time.Duration(rand.IntN(300))*time.Second+360*time.Second, func() {
time.AfterFunc(time.Duration(rand.IntN(300))*time.Second+360*time.Second, func() { //nolint:gosec
panel, err := r.api.LatestVersion(channel)
if err != nil {
return
+11
View File
@@ -0,0 +1,11 @@
//go:build wireinject
package job
import "github.com/libtnb/wire"
// Module 装配定时任务
var Module = wire.New().
Struct[Dependencies]().
Provide(NewJobs).
Export[[]Job]()
+3 -1
View File
@@ -79,6 +79,7 @@ func MustLogin(t *gotext.Locale, conf *config.Config, session *sessions.Manager,
if time.Now().Unix()-refreshAt > 600 {
sess.Put("refresh_at", time.Now().Unix())
// 重新设置 Cookie
//nolint:gosec
http.SetCookie(w, &http.Cookie{
Name: sess.GetName(),
Value: sess.GetID(),
@@ -96,7 +97,8 @@ func MustLogin(t *gotext.Locale, conf *config.Config, session *sessions.Manager,
return
}
r = r.WithContext(context.WithValue(r.Context(), "user_id", userID)) // nolint:staticcheck
//nolint:staticcheck
r = r.WithContext(context.WithValue(r.Context(), "user_id", userID))
next.ServeHTTP(w, r)
})
}

Some files were not shown because too many files have changed in this diff Show More