2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 06:47:20 +08:00

feat: 优化包大小

This commit is contained in:
2026-01-04 04:47:56 +08:00
parent b65a4249cb
commit 61b74b31d9
28 changed files with 315 additions and 395 deletions

View File

@@ -192,7 +192,6 @@ pnpm build
- 路由:`github.com/go-chi/chi/v5`
- ORM`gorm.io/gorm`
- 依赖注入:`github.com/google/wire`
- 配置管理:`github.com/knadh/koanf/v2`
- 验证:`github.com/gookit/validate`
### 助手函数service 层)

View File

@@ -43,42 +43,42 @@ import (
// initWeb init application.
func initWeb() (*app.Web, error) {
koanf, err := bootstrap.NewConf()
config, err := bootstrap.NewConf()
if err != nil {
return nil, err
}
locale, err := bootstrap.NewT(koanf)
locale, err := bootstrap.NewT(config)
if err != nil {
return nil, err
}
db, err := bootstrap.NewDB(koanf)
db, err := bootstrap.NewDB(config)
if err != nil {
return nil, err
}
manager, err := bootstrap.NewSession(koanf, db)
manager, err := bootstrap.NewSession(config, db)
if err != nil {
return nil, err
}
logger := bootstrap.NewLog(koanf)
logger := bootstrap.NewLog(config)
cacheRepo := data.NewCacheRepo(db)
queue := bootstrap.NewQueue()
taskRepo := data.NewTaskRepo(locale, db, logger, queue)
appRepo := data.NewAppRepo(locale, koanf, db, logger, cacheRepo, taskRepo)
userTokenRepo := data.NewUserTokenRepo(locale, koanf, db)
middlewares := middleware.NewMiddlewares(koanf, manager, appRepo, userTokenRepo)
appRepo := data.NewAppRepo(locale, config, db, logger, cacheRepo, taskRepo)
userTokenRepo := data.NewUserTokenRepo(locale, config, db)
middlewares := middleware.NewMiddlewares(config, manager, appRepo, userTokenRepo)
userRepo := data.NewUserRepo(locale, db)
userService := service.NewUserService(locale, koanf, manager, userRepo)
userService := service.NewUserService(locale, config, manager, userRepo)
userTokenService := service.NewUserTokenService(locale, userTokenRepo)
databaseServerRepo := data.NewDatabaseServerRepo(locale, db, logger)
databaseUserRepo := data.NewDatabaseUserRepo(locale, db, databaseServerRepo)
databaseRepo := data.NewDatabaseRepo(locale, db, databaseServerRepo, databaseUserRepo)
certRepo := data.NewCertRepo(locale, db, logger)
certAccountRepo := data.NewCertAccountRepo(locale, db, userRepo, logger)
settingRepo := data.NewSettingRepo(locale, db, koanf, taskRepo)
settingRepo := data.NewSettingRepo(locale, db, config, taskRepo)
websiteRepo := data.NewWebsiteRepo(locale, db, cacheRepo, databaseRepo, databaseServerRepo, databaseUserRepo, certRepo, certAccountRepo, settingRepo)
cronRepo := data.NewCronRepo(locale, db)
backupRepo := data.NewBackupRepo(locale, db, settingRepo, websiteRepo)
homeService := service.NewHomeService(locale, koanf, taskRepo, websiteRepo, appRepo, settingRepo, cronRepo, backupRepo)
homeService := service.NewHomeService(locale, config, taskRepo, websiteRepo, appRepo, settingRepo, cronRepo, backupRepo)
taskService := service.NewTaskService(taskRepo)
websiteService := service.NewWebsiteService(websiteRepo, settingRepo)
databaseService := service.NewDatabaseService(databaseRepo)
@@ -134,24 +134,24 @@ func initWeb() (*app.Web, error) {
s3fsApp := s3fs.NewApp(locale)
supervisorApp := supervisor.NewApp(locale)
loader := bootstrap.NewLoader(codeserverApp, dockerApp, fail2banApp, frpApp, giteaApp, memcachedApp, minioApp, mysqlApp, nginxApp, openrestyApp, perconaApp, phpmyadminApp, podmanApp, postgresqlApp, pureftpdApp, redisApp, rsyncApp, s3fsApp, supervisorApp)
http := route.NewHttp(koanf, userService, userTokenService, homeService, taskService, websiteService, databaseService, databaseServerService, databaseUserService, backupService, certService, certDNSService, certAccountService, appService, cronService, processService, safeService, firewallService, sshService, containerService, containerComposeService, containerNetworkService, containerImageService, containerVolumeService, fileService, monitorService, settingService, systemctlService, toolboxSystemService, toolboxBenchmarkService, loader)
wsService := service.NewWsService(locale, koanf, logger, sshRepo)
http := route.NewHttp(config, userService, userTokenService, homeService, taskService, websiteService, databaseService, databaseServerService, databaseUserService, backupService, certService, certDNSService, certAccountService, appService, cronService, processService, safeService, firewallService, sshService, containerService, containerComposeService, containerNetworkService, containerImageService, containerVolumeService, fileService, monitorService, settingService, systemctlService, toolboxSystemService, toolboxBenchmarkService, loader)
wsService := service.NewWsService(locale, config, logger, sshRepo)
ws := route.NewWs(wsService)
mux, err := bootstrap.NewRouter(locale, middlewares, http, ws)
if err != nil {
return nil, err
}
server, err := bootstrap.NewHttp(koanf, mux)
server, err := bootstrap.NewHttp(config, mux)
if err != nil {
return nil, err
}
gormigrate := bootstrap.NewMigrate(db)
jobs := job.NewJobs(db, logger, settingRepo, certRepo, backupRepo, cacheRepo, taskRepo)
cron, err := bootstrap.NewCron(koanf, logger, jobs)
cron, err := bootstrap.NewCron(config, logger, jobs)
if err != nil {
return nil, err
}
validation := bootstrap.NewValidator(koanf, db)
web := app.NewWeb(koanf, mux, server, gormigrate, cron, queue, validation)
validation := bootstrap.NewValidator(config, db)
web := app.NewWeb(config, mux, server, gormigrate, cron, queue, validation)
return web, nil
}

View File

@@ -41,25 +41,25 @@ import (
// initCli init command line.
func initCli() (*app.Cli, error) {
koanf, err := bootstrap.NewConf()
config, err := bootstrap.NewConf()
if err != nil {
return nil, err
}
locale, err := bootstrap.NewT(koanf)
locale, err := bootstrap.NewT(config)
if err != nil {
return nil, err
}
db, err := bootstrap.NewDB(koanf)
db, err := bootstrap.NewDB(config)
if err != nil {
return nil, err
}
logger := bootstrap.NewLog(koanf)
logger := bootstrap.NewLog(config)
cacheRepo := data.NewCacheRepo(db)
queue := bootstrap.NewQueue()
taskRepo := data.NewTaskRepo(locale, db, logger, queue)
appRepo := data.NewAppRepo(locale, koanf, db, logger, cacheRepo, taskRepo)
appRepo := data.NewAppRepo(locale, config, db, logger, cacheRepo, taskRepo)
userRepo := data.NewUserRepo(locale, db)
settingRepo := data.NewSettingRepo(locale, db, koanf, taskRepo)
settingRepo := data.NewSettingRepo(locale, db, config, taskRepo)
databaseServerRepo := data.NewDatabaseServerRepo(locale, db, logger)
databaseUserRepo := data.NewDatabaseUserRepo(locale, db, databaseServerRepo)
databaseRepo := data.NewDatabaseRepo(locale, db, databaseServerRepo, databaseUserRepo)
@@ -67,7 +67,7 @@ func initCli() (*app.Cli, error) {
certAccountRepo := data.NewCertAccountRepo(locale, db, userRepo, logger)
websiteRepo := data.NewWebsiteRepo(locale, db, cacheRepo, databaseRepo, databaseServerRepo, databaseUserRepo, certRepo, certAccountRepo, settingRepo)
backupRepo := data.NewBackupRepo(locale, db, settingRepo, websiteRepo)
cliService := service.NewCliService(locale, koanf, db, appRepo, cacheRepo, userRepo, settingRepo, backupRepo, websiteRepo, databaseServerRepo)
cliService := service.NewCliService(locale, config, db, appRepo, cacheRepo, userRepo, settingRepo, backupRepo, websiteRepo, databaseServerRepo)
cli := route.NewCli(locale, cliService)
command := bootstrap.NewCli(locale, cli)
gormigrate := bootstrap.NewMigrate(db)

21
go.mod
View File

@@ -3,6 +3,7 @@ module github.com/acepanel/panel
go 1.25
require (
github.com/DeRuina/timberjack v1.3.9
github.com/bddjr/hlfhr v1.4.0
github.com/beevik/ntp v1.5.0
github.com/coder/websocket v1.8.14
@@ -19,9 +20,6 @@ require (
github.com/gookit/validate v1.5.6
github.com/hashicorp/go-version v1.8.0
github.com/klauspost/compress v1.18.2
github.com/knadh/koanf/parsers/yaml v1.1.0
github.com/knadh/koanf/providers/file v1.2.1
github.com/knadh/koanf/v2 v2.3.0
github.com/leonelquinteros/gotext v1.7.2
github.com/lib/pq v1.10.9
github.com/libdns/alidns v1.0.6-beta.3
@@ -53,10 +51,9 @@ require (
github.com/stretchr/testify v1.11.1
github.com/tufanbarisyildirim/gonginx v0.0.0-20250620092546-c3e307e36701
github.com/urfave/cli/v3 v3.6.1
go.yaml.in/yaml/v3 v3.0.4
go.yaml.in/yaml/v4 v4.0.0-rc.3
golang.org/x/crypto v0.46.0
golang.org/x/net v0.48.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gorm.io/gorm v1.31.1
)
@@ -67,32 +64,25 @@ require (
github.com/boombuler/barcode v1.1.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/gofiber/schema v1.6.0 // indirect
github.com/gookit/filter v1.2.3 // indirect
github.com/gookit/goutil v0.7.1 // indirect
github.com/gookit/goutil v0.7.3 // indirect
github.com/imega/luaformatter v0.0.0-20211025140405-86b0a68d6bef // indirect
github.com/jaevor/go-nanoid v1.4.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/knadh/koanf/maps v0.1.2 // indirect
github.com/libtnb/securecookie v1.2.0 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/ncruces/julianday v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/objx v0.5.3 // indirect
github.com/tetratelabs/wazero v1.11.0 // indirect
github.com/timtadh/data-structures v0.6.2 // indirect
github.com/timtadh/lexmachine v0.2.3 // indirect
@@ -104,13 +94,12 @@ require (
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/text v0.32.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace (
github.com/mholt/acmez/v3 => github.com/libtnb/acmez/v3 v3.0.0-20260103184942-a835890fc93e
github.com/moby/moby/client => github.com/libtnb/moby/client v0.0.0-20260103192150-39cfd5376055
github.com/stretchr/testify => github.com/libtnb/testify v0.0.0-20260103194301-c7a63ea79696
)
tool github.com/google/wire

53
go.sum
View File

@@ -15,6 +15,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DeRuina/timberjack v1.3.9 h1:6UXZ1I7ExPGTX/1UNYawR58LlOJUHKBPiYC7WQ91eBo=
github.com/DeRuina/timberjack v1.3.9/go.mod h1:RLoeQrwrCGIEF8gO5nV5b/gMD0QIy7bzQhBUgpp1EqE=
github.com/G-Core/gcore-dns-sdk-go v0.3.3 h1:McILJSbJ5nOcT0MI0aBYhEuufCF329YbqKwFIN0RjCI=
github.com/G-Core/gcore-dns-sdk-go v0.3.3/go.mod h1:35t795gOfzfVanhzkFyUXEzaBuMXwETmJldPpP28MN4=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
@@ -52,8 +54,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
@@ -66,11 +66,11 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
github.com/expr-lang/expr v1.17.7 h1:Q0xY/e/2aCIp8g9s/LGvMDCC5PxYlvHgDZRQ4y16JX8=
github.com/expr-lang/expr v1.17.7/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -92,8 +92,6 @@ github.com/go-resty/resty/v2 v2.17.1/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2m
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gofiber/schema v1.6.0 h1:rAgVDFwhndtC+hgV7Vu5ItQCn7eC2mBA4Eu1/ZTiEYY=
github.com/gofiber/schema v1.6.0/go.mod h1:WNZWpQx8LlPSK7ZaX0OqOh+nQo/eW2OevsXs1VZfs/s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -130,8 +128,8 @@ github.com/gookit/color v1.6.0 h1:JjJXBTk1ETNyqyilJhkTXJYYigHG24TM9Xa2M1xAhRA=
github.com/gookit/color v1.6.0/go.mod h1:9ACFc7/1IpHGBW8RwuDm/0YEnhg3dwwXpoMsmtyHfjs=
github.com/gookit/filter v1.2.3 h1:Zo7cBOtsVzAoa/jtf+Ury6zlsbJXqInFdUpbbnB2vMM=
github.com/gookit/filter v1.2.3/go.mod h1:nFLJcOV8dRgS1iiX23gUQgmHUhpuS40qCvAGgIvA1pM=
github.com/gookit/goutil v0.7.1 h1:AaFJPN9mrdeYBv8HOybri26EHGCC34WJVT7jUStGJsI=
github.com/gookit/goutil v0.7.1/go.mod h1:vJS9HXctYTCLtCsZot5L5xF+O1oR17cDYO9R0HxBmnU=
github.com/gookit/goutil v0.7.3 h1:nXDd/AB17nEjqVCNDGioDhVL/gVqdlqRMfFergKDjHE=
github.com/gookit/goutil v0.7.3/go.mod h1:vJS9HXctYTCLtCsZot5L5xF+O1oR17cDYO9R0HxBmnU=
github.com/gookit/validate v1.5.6 h1:D6vbSZzreuKYpeeXm5FDDEJy3K5E4lcWsQE4saSMZbU=
github.com/gookit/validate v1.5.6/go.mod h1:WYEHndRNepIIkM+6CtgEX9MQ9ToIQRhXxmz5oLHF/fc=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -181,19 +179,10 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo=
github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
github.com/knadh/koanf/parsers/yaml v1.1.0 h1:3ltfm9ljprAHt4jxgeYLlFPmUaunuCgu1yILuTXRdM4=
github.com/knadh/koanf/parsers/yaml v1.1.0/go.mod h1:HHmcHXUrp9cOPcuC+2wrr44GTUB0EC+PyfN3HZD9tFg=
github.com/knadh/koanf/providers/file v1.2.1 h1:bEWbtQwYrA+W2DtdBrQWyXqJaJSG3KrP3AESOJYp9wM=
github.com/knadh/koanf/providers/file v1.2.1/go.mod h1:bp1PM5f83Q+TOUu10J/0ApLBd9uIzg+n9UgthfY+nRA=
github.com/knadh/koanf/v2 v2.3.0 h1:Qg076dDRFHvqnKG97ZEsi9TAg2/nFTa9hCdcSa1lvlM=
github.com/knadh/koanf/v2 v2.3.0/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -236,6 +225,8 @@ github.com/libtnb/securecookie v1.2.0 h1:2uc0PBDm0foeSTrcZ9QTX1IEjf6kFEwfgEYSIXQ
github.com/libtnb/securecookie v1.2.0/go.mod h1:ja+wNGnQzYqcqXQnJWu6icsaWi5JEBwNEMJ2ReTVDxA=
github.com/libtnb/sessions v1.2.2 h1:VTTzzeBDJEkJbaPaIU9C4bRj2oAqD0rgQ7UHFkkaNT4=
github.com/libtnb/sessions v1.2.2/go.mod h1:qw+FWtBtrPDYCf6MfX0Lk5EhTArpvT72z5Ei4RUMTRg=
github.com/libtnb/testify v0.0.0-20260103194301-c7a63ea79696 h1:GN0Y3DG27mMruX536k0jtCSLegjJb/gypzj5gZL6tRI=
github.com/libtnb/testify v0.0.0-20260103194301-c7a63ea79696/go.mod h1:HeQeTfKU6tj2Lx1z79UacwYeDioo6M4ZD7BDDI6+rrg=
github.com/libtnb/utils v1.2.1 h1:LJmReRREnpqfHyy9PZtNgBh3ZaIGct81b8ZaAsolMkM=
github.com/libtnb/utils v1.2.1/go.mod h1:o6LEDeC42PXI21uLWdWJWTVYvR9BtAZfzzTGJVQoQiU=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -244,8 +235,6 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
@@ -253,8 +242,6 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/moby/api v1.53.0-rc.1 h1:M5SUwRbTrNy+plCTiV6gn4ZiN/Csynk0imIsUmOgHGI=
@@ -280,7 +267,6 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=
@@ -325,16 +311,9 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
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/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA=
github.com/tetratelabs/wazero v1.11.0/go.mod h1:eV28rsN8Q+xwjogd7f4/Pp4xFxO7uOGbLcD/LzB1wiU=
@@ -366,8 +345,8 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go=
go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -493,22 +472,14 @@ google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=

View File

@@ -11,14 +11,14 @@ import (
"github.com/go-chi/chi/v5"
"github.com/go-gormigrate/gormigrate/v2"
"github.com/gookit/validate"
"github.com/knadh/koanf/v2"
"github.com/robfig/cron/v3"
"github.com/acepanel/panel/pkg/config"
"github.com/acepanel/panel/pkg/queue"
)
type Web struct {
conf *koanf.Koanf
conf *config.Config
router *chi.Mux
server *hlfhr.Server
migrator *gormigrate.Gormigrate
@@ -26,7 +26,7 @@ type Web struct {
queue *queue.Queue
}
func NewWeb(conf *koanf.Koanf, router *chi.Mux, server *hlfhr.Server, migrator *gormigrate.Gormigrate, cron *cron.Cron, queue *queue.Queue, _ *validate.Validation) *Web {
func NewWeb(conf *config.Config, router *chi.Mux, server *hlfhr.Server, migrator *gormigrate.Gormigrate, cron *cron.Cron, queue *queue.Queue, _ *validate.Validation) *Web {
return &Web{
conf: conf,
router: router,
@@ -52,15 +52,15 @@ func (r *Web) Run() error {
r.queue.Run(context.TODO())
// run http server
if r.conf.Bool("http.tls") {
if r.conf.HTTP.TLS {
cert := filepath.Join(Root, "panel/storage/cert.pem")
key := filepath.Join(Root, "panel/storage/cert.key")
fmt.Println("[HTTP] listening and serving on port", r.conf.MustInt("http.port"), "with tls")
fmt.Println("[HTTP] listening and serving on port", r.conf.HTTP.Port, "with tls")
if err := r.server.ListenAndServeTLS(cert, key); !errors.Is(err, http.ErrServerClosed) {
return err
}
} else {
fmt.Println("[HTTP] listening and serving on port", r.conf.MustInt("http.port"))
fmt.Println("[HTTP] listening and serving on port", r.conf.HTTP.Port)
if err := r.server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
return err
}

View File

@@ -4,22 +4,13 @@ import (
"log"
"time"
"github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/providers/file"
"github.com/knadh/koanf/v2"
"github.com/acepanel/panel/internal/app"
"github.com/acepanel/panel/pkg/io"
"github.com/acepanel/panel/pkg/config"
)
func NewConf() (*koanf.Koanf, error) {
config := "/opt/ace/panel/config.yml"
if !io.Exists(config) {
config = "config.yml"
}
conf := koanf.New(".")
if err := conf.Load(file.Provider(config), yaml.Parser()); err != nil {
func NewConf() (*config.Config, error) {
conf, err := config.Load()
if err != nil {
return nil, err
}
@@ -27,17 +18,17 @@ func NewConf() (*koanf.Koanf, error) {
return conf, nil
}
func initGlobal(conf *koanf.Koanf) {
app.Key = conf.MustString("app.key")
func initGlobal(conf *config.Config) {
app.Key = conf.App.Key
if len(app.Key) != 32 {
log.Fatalf("panel app key must be 32 characters")
}
app.Root = "/opt/ace"
app.Locale = conf.MustString("app.locale")
app.Locale = conf.App.Locale
// 初始化时区
loc, err := time.LoadLocation(conf.MustString("app.timezone"))
loc, err := time.LoadLocation(conf.App.Timezone)
if err != nil {
log.Fatalf("failed to load timezone: %v", err)
}

View File

@@ -3,15 +3,15 @@ package bootstrap
import (
"log/slog"
"github.com/knadh/koanf/v2"
"github.com/robfig/cron/v3"
"github.com/acepanel/panel/internal/job"
"github.com/acepanel/panel/pkg/config"
pkgcron "github.com/acepanel/panel/pkg/cron"
)
func NewCron(conf *koanf.Koanf, log *slog.Logger, jobs *job.Jobs) (*cron.Cron, error) {
logger := pkgcron.NewLogger(log, conf.Bool("app.debug"))
func NewCron(conf *config.Config, log *slog.Logger, jobs *job.Jobs) (*cron.Cron, error) {
logger := pkgcron.NewLogger(log, conf.App.Debug)
c := cron.New(
cron.WithParser(cron.NewParser(

View File

@@ -4,29 +4,29 @@ import (
"log/slog"
"path/filepath"
"github.com/DeRuina/timberjack"
"github.com/go-gormigrate/gormigrate/v2"
"github.com/knadh/koanf/v2"
_ "github.com/ncruces/go-sqlite3/embed"
"github.com/ncruces/go-sqlite3/gormlite"
sloggorm "github.com/orandin/slog-gorm"
"gopkg.in/natefinch/lumberjack.v2"
"gorm.io/gorm"
"github.com/acepanel/panel/internal/app"
"github.com/acepanel/panel/internal/migration"
"github.com/acepanel/panel/pkg/config"
)
func NewDB(conf *koanf.Koanf) (*gorm.DB, error) {
ljLogger := &lumberjack.Logger{
Filename: filepath.Join(app.Root, "panel/storage/logs/db.log"),
MaxSize: 10,
MaxAge: 30,
Compress: true,
func NewDB(conf *config.Config) (*gorm.DB, error) {
tjLogger := &timberjack.Logger{
Filename: filepath.Join(app.Root, "panel/storage/logs/db.log"),
MaxSize: 10,
MaxAge: 30,
Compression: "zstd",
}
handler := slog.New(slog.NewJSONHandler(ljLogger, nil)).Handler()
handler := slog.New(slog.NewJSONHandler(tjLogger, nil)).Handler()
options := []sloggorm.Option{sloggorm.WithHandler(handler)}
if conf.Bool("database.debug") {
if conf.Database.Debug {
options = append(options, sloggorm.WithTraceAll())
}

View File

@@ -7,11 +7,11 @@ import (
"github.com/bddjr/hlfhr"
"github.com/go-chi/chi/v5"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/acepanel/panel/internal/http/middleware"
"github.com/acepanel/panel/internal/route"
"github.com/acepanel/panel/pkg/config"
)
func NewRouter(t *gotext.Locale, middlewares *middleware.Middlewares, http *route.Http, ws *route.Ws) (*chi.Mux, error) {
@@ -27,15 +27,15 @@ func NewRouter(t *gotext.Locale, middlewares *middleware.Middlewares, http *rout
return r, nil
}
func NewHttp(conf *koanf.Koanf, mux *chi.Mux) (*hlfhr.Server, error) {
func NewHttp(conf *config.Config, mux *chi.Mux) (*hlfhr.Server, error) {
srv := hlfhr.New(&http.Server{
Addr: fmt.Sprintf(":%d", conf.MustInt("http.port")),
Addr: fmt.Sprintf(":%d", conf.HTTP.Port),
Handler: mux,
MaxHeaderBytes: 2048 << 20,
})
srv.Listen80RedirectTo443 = true
if conf.Bool("http.tls") {
if conf.HTTP.TLS {
srv.TLSConfig = &tls.Config{
MinVersion: tls.VersionTLS12,
}

View File

@@ -4,26 +4,26 @@ import (
"log/slog"
"path/filepath"
"github.com/knadh/koanf/v2"
"gopkg.in/natefinch/lumberjack.v2"
"github.com/DeRuina/timberjack"
"github.com/acepanel/panel/internal/app"
"github.com/acepanel/panel/pkg/config"
)
func NewLog(conf *koanf.Koanf) *slog.Logger {
ljLogger := &lumberjack.Logger{
Filename: filepath.Join(app.Root, "panel/storage/logs/app.log"),
MaxSize: 10,
MaxAge: 30,
Compress: true,
func NewLog(conf *config.Config) *slog.Logger {
tjLogger := &timberjack.Logger{
Filename: filepath.Join(app.Root, "panel/storage/logs/app.log"),
MaxSize: 10,
MaxAge: 30,
Compression: "zstd",
}
level := slog.LevelInfo
if conf.Bool("app.debug") {
if conf.App.Debug {
level = slog.LevelDebug
}
log := slog.New(slog.NewJSONHandler(ljLogger, &slog.HandlerOptions{
log := slog.New(slog.NewJSONHandler(tjLogger, &slog.HandlerOptions{
Level: level,
}))
slog.SetDefault(log)

View File

@@ -1,18 +1,18 @@
package bootstrap
import (
"github.com/knadh/koanf/v2"
"github.com/libtnb/gormstore"
"github.com/libtnb/sessions"
"gorm.io/gorm"
"github.com/acepanel/panel/pkg/config"
)
func NewSession(conf *koanf.Koanf, db *gorm.DB) (*sessions.Manager, error) {
func NewSession(conf *config.Config, db *gorm.DB) (*sessions.Manager, error) {
// initialize session manager
lifetime := conf.Int("session.lifetime")
manager, err := sessions.NewManager(&sessions.ManagerOptions{
Key: conf.MustString("app.key"),
Lifetime: lifetime,
Key: conf.App.Key,
Lifetime: int(conf.Session.Lifetime),
GcInterval: 5,
DisableDefaultDriver: true,
})

View File

@@ -1,15 +1,14 @@
package bootstrap
import (
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/acepanel/panel/pkg/config"
"github.com/acepanel/panel/pkg/embed"
)
func NewT(conf *koanf.Koanf) (*gotext.Locale, error) {
locale := conf.String("app.locale")
l := gotext.NewLocaleFSWithPath(locale, embed.LocalesFS, "locales")
func NewT(conf *config.Config) (*gotext.Locale, error) {
l := gotext.NewLocaleFSWithPath(conf.App.Locale, embed.LocalesFS, "locales")
l.AddDomain("backend")
return l, nil

View File

@@ -5,21 +5,23 @@ import (
"github.com/gookit/validate/locales/ruru"
"github.com/gookit/validate/locales/zhcn"
"github.com/gookit/validate/locales/zhtw"
"github.com/knadh/koanf/v2"
"gorm.io/gorm"
"github.com/acepanel/panel/internal/http/rule"
"github.com/acepanel/panel/pkg/config"
)
// NewValidator just for register global rules
func NewValidator(conf *koanf.Koanf, db *gorm.DB) *validate.Validation {
if conf.String("app.locale") == "zh_CN" {
func NewValidator(conf *config.Config, db *gorm.DB) *validate.Validation {
switch conf.App.Locale {
case "zh_CN":
zhcn.RegisterGlobal()
} else if conf.String("app.locale") == "zh_TW" {
case "zh_TW":
zhtw.RegisterGlobal()
} else if conf.String("app.locale") == "ru_RU" {
case "ru_RU":
ruru.RegisterGlobal()
}
validate.Config(func(opt *validate.GlobalOption) {
opt.StopOnError = false
opt.SkipOnEmpty = true

View File

@@ -9,7 +9,6 @@ import (
"github.com/expr-lang/expr"
"github.com/hashicorp/go-version"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/spf13/cast"
"gorm.io/gorm"
@@ -17,12 +16,13 @@ import (
"github.com/acepanel/panel/internal/app"
"github.com/acepanel/panel/internal/biz"
"github.com/acepanel/panel/pkg/api"
"github.com/acepanel/panel/pkg/config"
"github.com/acepanel/panel/pkg/shell"
)
type appRepo struct {
t *gotext.Locale
conf *koanf.Koanf
conf *config.Config
db *gorm.DB
log *slog.Logger
cache biz.CacheRepo
@@ -30,7 +30,7 @@ type appRepo struct {
api *api.API
}
func NewAppRepo(t *gotext.Locale, conf *koanf.Koanf, db *gorm.DB, log *slog.Logger, cache biz.CacheRepo, task biz.TaskRepo) biz.AppRepo {
func NewAppRepo(t *gotext.Locale, conf *config.Config, db *gorm.DB, log *slog.Logger, cache biz.CacheRepo, task biz.TaskRepo) biz.AppRepo {
return &appRepo{
t: t,
conf: conf,
@@ -172,7 +172,7 @@ func (r *appRepo) Install(channel, slug string) error {
continue
}
if ch.Slug == channel {
if vs.GreaterThan(panel) && !r.conf.Bool("app.debug") {
if vs.GreaterThan(panel) && !r.conf.App.Debug {
return errors.New(r.t.Get("app %s requires panel version %s, current version %s", item.Name, ch.Panel, app.Version))
}
shellUrl = ch.Install
@@ -232,7 +232,7 @@ func (r *appRepo) UnInstall(slug string) error {
continue
}
if ch.Slug == installed.Channel {
if vs.GreaterThan(panel) && !r.conf.Bool("app.debug") {
if vs.GreaterThan(panel) && !r.conf.App.Debug {
return errors.New(r.t.Get("app %s requires panel version %s, current version %s", item.Name, ch.Panel, app.Version))
}
shellUrl = ch.Uninstall
@@ -287,7 +287,7 @@ func (r *appRepo) Update(slug string) error {
continue
}
if ch.Slug == installed.Channel {
if vs.GreaterThan(panel) && !r.conf.Bool("app.debug") {
if vs.GreaterThan(panel) && !r.conf.App.Debug {
return errors.New(r.t.Get("app %s requires panel version %s, current version %s", item.Name, ch.Panel, app.Version))
}
shellUrl = ch.Update

View File

@@ -6,32 +6,30 @@ import (
"path/filepath"
"sync"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/spf13/cast"
"go.yaml.in/yaml/v3"
"gorm.io/gorm"
"github.com/acepanel/panel/internal/app"
"github.com/acepanel/panel/internal/biz"
"github.com/acepanel/panel/internal/http/request"
"github.com/acepanel/panel/pkg/cert"
"github.com/acepanel/panel/pkg/config"
"github.com/acepanel/panel/pkg/firewall"
"github.com/acepanel/panel/pkg/io"
"github.com/acepanel/panel/pkg/os"
"github.com/acepanel/panel/pkg/systemctl"
"github.com/acepanel/panel/pkg/types"
)
type settingRepo struct {
t *gotext.Locale
cache sync.Map
db *gorm.DB
conf *koanf.Koanf
conf *config.Config
task biz.TaskRepo
}
func NewSettingRepo(t *gotext.Locale, db *gorm.DB, conf *koanf.Koanf, task biz.TaskRepo) biz.SettingRepo {
func NewSettingRepo(t *gotext.Locale, db *gorm.DB, conf *config.Config, task biz.TaskRepo) biz.SettingRepo {
return &settingRepo{
t: t,
db: db,
@@ -236,19 +234,19 @@ func (r *settingRepo) GetPanel() (*request.SettingPanel, error) {
return &request.SettingPanel{
Name: name,
Channel: channel,
Locale: r.conf.String("app.locale"),
Entrance: r.conf.String("http.entrance"),
Locale: r.conf.App.Locale,
Entrance: r.conf.HTTP.Entrance,
OfflineMode: offlineMode,
AutoUpdate: autoUpdate,
Lifetime: uint(r.conf.Int("session.lifetime")),
IPHeader: r.conf.String("http.ip_header"),
BindDomain: r.conf.Strings("http.bind_domain"),
BindIP: r.conf.Strings("http.bind_ip"),
BindUA: r.conf.Strings("http.bind_ua"),
Lifetime: r.conf.Session.Lifetime,
IPHeader: r.conf.HTTP.IPHeader,
BindDomain: r.conf.HTTP.BindDomain,
BindIP: r.conf.HTTP.BindIP,
BindUA: r.conf.HTTP.BindUA,
WebsitePath: websitePath,
BackupPath: backupPath,
Port: uint(r.conf.Int("http.port")),
HTTPS: r.conf.Bool("http.tls"),
Port: r.conf.HTTP.Port,
HTTPS: r.conf.HTTP.TLS,
Cert: crt,
Key: key,
}, nil
@@ -299,16 +297,12 @@ func (r *settingRepo) UpdatePanel(req *request.SettingPanel) (bool, error) {
}
// 面板主配置
config := new(types.PanelConfig)
raw, err := io.Read("/usr/local/etc/panel/config.yml")
conf, err := config.Load()
if err != nil {
return false, err
}
if err = yaml.Unmarshal([]byte(raw), config); err != nil {
return false, err
}
if req.Port != config.HTTP.Port {
if req.Port != conf.HTTP.Port {
if os.TCPPortInUse(req.Port) {
return false, errors.New(r.t.Get("port is already in use"))
}
@@ -328,27 +322,24 @@ func (r *settingRepo) UpdatePanel(req *request.SettingPanel) (bool, error) {
}
}
config.App.Locale = req.Locale
config.HTTP.Port = req.Port
config.HTTP.Entrance = req.Entrance
config.HTTP.TLS = req.HTTPS
config.HTTP.IPHeader = req.IPHeader
config.HTTP.BindDomain = req.BindDomain
config.HTTP.BindIP = req.BindIP
config.HTTP.BindUA = req.BindUA
config.Session.Lifetime = req.Lifetime
conf.App.Locale = req.Locale
conf.HTTP.Port = req.Port
conf.HTTP.Entrance = req.Entrance
conf.HTTP.TLS = req.HTTPS
conf.HTTP.IPHeader = req.IPHeader
conf.HTTP.BindDomain = req.BindDomain
conf.HTTP.BindIP = req.BindIP
conf.HTTP.BindUA = req.BindUA
conf.Session.Lifetime = req.Lifetime
encoded, err := yaml.Marshal(config)
if err != nil {
return false, err
}
if raw != string(encoded) {
// 检查配置是否有变更
if same, _ := config.Check(conf); !same {
if r.task.HasRunningTask() {
return false, errors.New(r.t.Get("background task is running, modifying some settings is prohibited, please try again later"))
}
restartFlag = true
}
if err = io.Write("/usr/local/etc/panel/config.yml", string(encoded), 0644); err != nil {
if err = config.Save(conf); err != nil {
return false, err
}

View File

@@ -14,22 +14,22 @@ import (
"strings"
"time"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/libtnb/utils/str"
"github.com/spf13/cast"
"gorm.io/gorm"
"github.com/acepanel/panel/internal/biz"
"github.com/acepanel/panel/pkg/config"
)
type userTokenRepo struct {
t *gotext.Locale
conf *koanf.Koanf
conf *config.Config
db *gorm.DB
}
func NewUserTokenRepo(t *gotext.Locale, conf *koanf.Koanf, db *gorm.DB) biz.UserTokenRepo {
func NewUserTokenRepo(t *gotext.Locale, conf *config.Config, db *gorm.DB) biz.UserTokenRepo {
return &userTokenRepo{
t: t,
conf: conf,
@@ -144,7 +144,7 @@ func (r userTokenRepo) ValidateReq(req *http.Request) (uint, error) {
// 步骤六验证IP
if len(userToken.IPs) > 0 {
ip := req.RemoteAddr
ipHeader := r.conf.String("http.ip_header")
ipHeader := r.conf.HTTP.IPHeader
if ipHeader != "" && req.Header.Get(ipHeader) != "" {
ip = strings.Split(req.Header.Get(ipHeader), ",")[0]
}

View File

@@ -7,16 +7,16 @@ import (
"strings"
"github.com/go-chi/chi/v5"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/libtnb/chix"
"github.com/libtnb/sessions"
"github.com/acepanel/panel/pkg/config"
"github.com/acepanel/panel/pkg/punycode"
)
// Entrance 确保通过正确的入口访问
func Entrance(t *gotext.Locale, conf *koanf.Koanf, session *sessions.Manager) func(next http.Handler) http.Handler {
func Entrance(t *gotext.Locale, conf *config.Config, session *sessions.Manager) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
sess, err := session.GetSession(r)
@@ -25,7 +25,7 @@ func Entrance(t *gotext.Locale, conf *koanf.Koanf, session *sessions.Manager) fu
return
}
entrance := strings.TrimSuffix(conf.String("http.entrance"), "/")
entrance := strings.TrimSuffix(conf.HTTP.Entrance, "/")
if !strings.HasPrefix(entrance, "/") {
entrance = "/" + entrance
}
@@ -40,14 +40,14 @@ func Entrance(t *gotext.Locale, conf *koanf.Koanf, session *sessions.Manager) fu
host = decoded
}
}
if len(conf.Strings("http.bind_domain")) > 0 && !slices.Contains(conf.Strings("http.bind_domain"), host) {
if len(conf.HTTP.BindDomain) > 0 && !slices.Contains(conf.HTTP.BindDomain, host) {
Abort(w, http.StatusTeapot, t.Get("invalid request domain: %s", r.Host))
return
}
// 取请求 IP
ip := r.RemoteAddr
ipHeader := conf.String("http.ip_header")
ipHeader := conf.HTTP.IPHeader
if ipHeader != "" && r.Header.Get(ipHeader) != "" {
ip = strings.Split(r.Header.Get(ipHeader), ",")[0]
}
@@ -56,11 +56,11 @@ func Entrance(t *gotext.Locale, conf *koanf.Koanf, session *sessions.Manager) fu
ip = r.RemoteAddr
}
if len(conf.Strings("http.bind_ip")) > 0 {
if len(conf.HTTP.BindIP) > 0 {
allowed := false
requestIP := net.ParseIP(ip)
if requestIP != nil {
for _, allowedIP := range conf.Strings("http.bind_ip") {
for _, allowedIP := range conf.HTTP.BindIP {
if strings.Contains(allowedIP, "/") {
// CIDR
if _, ipNet, err := net.ParseCIDR(allowedIP); err == nil && ipNet.Contains(requestIP) {
@@ -81,7 +81,7 @@ func Entrance(t *gotext.Locale, conf *koanf.Koanf, session *sessions.Manager) fu
return
}
}
if len(conf.Strings("http.bind_ua")) > 0 && !slices.Contains(conf.Strings("http.bind_ua"), r.UserAgent()) {
if len(conf.HTTP.BindUA) > 0 && !slices.Contains(conf.HTTP.BindUA, r.UserAgent()) {
Abort(w, http.StatusTeapot, t.Get("invalid request user agent: %s", r.UserAgent()))
return
}
@@ -113,7 +113,7 @@ func Entrance(t *gotext.Locale, conf *koanf.Koanf, session *sessions.Manager) fu
}
// 情况四:非调试模式且未通过验证的请求,返回错误
if !conf.Bool("app.debug") &&
if !conf.App.Debug &&
sess.Missing("verify_entrance") &&
r.URL.Path != "/robots.txt" {
Abort(w, http.StatusTeapot, t.Get("invalid access entrance"))

View File

@@ -6,43 +6,43 @@ import (
"net/http"
"path/filepath"
"github.com/DeRuina/timberjack"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/httplog/v3"
"github.com/google/wire"
"github.com/klauspost/compress/gzip"
"github.com/klauspost/compress/zstd"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/libtnb/sessions"
sessionmiddleware "github.com/libtnb/sessions/middleware"
"gopkg.in/natefinch/lumberjack.v2"
"github.com/acepanel/panel/internal/app"
"github.com/acepanel/panel/internal/biz"
"github.com/acepanel/panel/pkg/config"
)
var ProviderSet = wire.NewSet(NewMiddlewares)
type Middlewares struct {
conf *koanf.Koanf
conf *config.Config
log *slog.Logger
session *sessions.Manager
appRepo biz.AppRepo
userToken biz.UserTokenRepo
}
func NewMiddlewares(conf *koanf.Koanf, session *sessions.Manager, appRepo biz.AppRepo, userToken biz.UserTokenRepo) *Middlewares {
ljLogger := &lumberjack.Logger{
Filename: filepath.Join(app.Root, "panel/storage/logs/http.log"),
MaxSize: 10,
MaxAge: 30,
Compress: true,
func NewMiddlewares(conf *config.Config, session *sessions.Manager, appRepo biz.AppRepo, userToken biz.UserTokenRepo) *Middlewares {
tjLogger := &timberjack.Logger{
Filename: filepath.Join(app.Root, "panel/storage/logs/http.log"),
MaxSize: 10,
MaxAge: 30,
Compression: "zstd",
}
return &Middlewares{
conf: conf,
log: slog.New(slog.NewJSONHandler(ljLogger, &slog.HandlerOptions{Level: slog.LevelInfo})),
log: slog.New(slog.NewJSONHandler(tjLogger, &slog.HandlerOptions{Level: slog.LevelInfo})),
session: session,
appRepo: appRepo,
userToken: userToken,

View File

@@ -10,16 +10,16 @@ import (
"strings"
"time"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/libtnb/sessions"
"github.com/spf13/cast"
"github.com/acepanel/panel/internal/biz"
"github.com/acepanel/panel/pkg/config"
)
// MustLogin 确保已登录
func MustLogin(t *gotext.Locale, conf *koanf.Koanf, session *sessions.Manager, userToken biz.UserTokenRepo) func(next http.Handler) http.Handler {
func MustLogin(t *gotext.Locale, conf *config.Config, session *sessions.Manager, userToken biz.UserTokenRepo) func(next http.Handler) http.Handler {
// 白名单
whiteList := []string{
"/api/user/key",
@@ -65,7 +65,7 @@ func MustLogin(t *gotext.Locale, conf *koanf.Koanf, session *sessions.Manager, u
if safeLogin {
// 取请求 IP
ip := r.RemoteAddr
ipHeader := conf.String("http.ip_header")
ipHeader := conf.HTTP.IPHeader
if ipHeader != "" && r.Header.Get(ipHeader) != "" {
ip = strings.Split(r.Header.Get(ipHeader), ",")[0]
}
@@ -94,7 +94,7 @@ func MustLogin(t *gotext.Locale, conf *koanf.Koanf, session *sessions.Manager, u
Expires: time.Now().Add(time.Duration(session.Lifetime) * time.Minute),
Path: "/",
HttpOnly: true,
Secure: conf.Bool("http.tls"),
Secure: conf.HTTP.TLS,
SameSite: http.SameSiteLaxMode,
})
}

View File

@@ -7,16 +7,16 @@ import (
"time"
"github.com/go-chi/chi/v5"
"github.com/knadh/koanf/v2"
"github.com/acepanel/panel/internal/http/middleware"
"github.com/acepanel/panel/internal/service"
"github.com/acepanel/panel/pkg/apploader"
"github.com/acepanel/panel/pkg/config"
"github.com/acepanel/panel/pkg/embed"
)
type Http struct {
conf *koanf.Koanf
conf *config.Config
user *service.UserService
userToken *service.UserTokenService
home *service.HomeService
@@ -50,7 +50,7 @@ type Http struct {
}
func NewHttp(
conf *koanf.Koanf,
conf *config.Config,
user *service.UserService,
userToken *service.UserTokenService,
home *service.HomeService,
@@ -121,7 +121,7 @@ func (route *Http) Register(r *chi.Mux) {
r.Route("/api", func(r chi.Router) {
r.Route("/user", func(r chi.Router) {
r.Get("/key", route.user.GetKey)
r.With(middleware.Throttle(route.conf.String("http.ip_header"), 5, time.Minute)).Post("/login", route.user.Login)
r.With(middleware.Throttle(route.conf.HTTP.IPHeader, 5, time.Minute)).Post("/login", route.user.Login)
r.Post("/logout", route.user.Logout)
r.Get("/is_login", route.user.IsLogin)
r.Get("/is_2fa", route.user.IsTwoFA)

View File

@@ -11,14 +11,12 @@ import (
"strings"
"time"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/libtnb/utils/collect"
"github.com/libtnb/utils/hash"
"github.com/libtnb/utils/str"
"github.com/spf13/cast"
"github.com/urfave/cli/v3"
"go.yaml.in/yaml/v3"
"gorm.io/gorm"
"github.com/acepanel/panel/internal/app"
@@ -26,20 +24,20 @@ import (
"github.com/acepanel/panel/internal/http/request"
"github.com/acepanel/panel/pkg/api"
"github.com/acepanel/panel/pkg/cert"
"github.com/acepanel/panel/pkg/config"
"github.com/acepanel/panel/pkg/firewall"
"github.com/acepanel/panel/pkg/io"
"github.com/acepanel/panel/pkg/ntp"
"github.com/acepanel/panel/pkg/os"
"github.com/acepanel/panel/pkg/systemctl"
"github.com/acepanel/panel/pkg/tools"
"github.com/acepanel/panel/pkg/types"
)
type CliService struct {
hr string
t *gotext.Locale
api *api.API
conf *koanf.Koanf
conf *config.Config
db *gorm.DB
appRepo biz.AppRepo
cacheRepo biz.CacheRepo
@@ -51,7 +49,7 @@ type CliService struct {
hash hash.Hasher
}
func NewCliService(t *gotext.Locale, conf *koanf.Koanf, db *gorm.DB, appRepo biz.AppRepo, cache biz.CacheRepo, user biz.UserRepo, setting biz.SettingRepo, backup biz.BackupRepo, website biz.WebsiteRepo, databaseServer biz.DatabaseServerRepo) *CliService {
func NewCliService(t *gotext.Locale, conf *config.Config, db *gorm.DB, appRepo biz.AppRepo, cache biz.CacheRepo, user biz.UserRepo, setting biz.SettingRepo, backup biz.BackupRepo, website biz.WebsiteRepo, databaseServer biz.DatabaseServerRepo) *CliService {
return &CliService{
hr: `+----------------------------------------------------`,
api: api.NewAPI(app.Version, app.Locale),
@@ -147,15 +145,15 @@ func (s *CliService) Info(ctx context.Context, cmd *cli.Command) error {
}
protocol := "http"
if s.conf.Bool("http.tls") {
if s.conf.HTTP.TLS {
protocol = "https"
}
port := s.conf.String("http.port")
if port == "" {
port := s.conf.HTTP.Port
if port == 0 {
return errors.New(s.t.Get("Failed to get port"))
}
entrance := s.conf.String("http.entrance")
entrance := s.conf.HTTP.Entrance
if entrance == "" {
return errors.New(s.t.Get("Failed to get entrance"))
}
@@ -307,23 +305,14 @@ func (s *CliService) UserTwoFA(ctx context.Context, cmd *cli.Command) error {
}
func (s *CliService) HTTPSOn(ctx context.Context, cmd *cli.Command) error {
config := new(types.PanelConfig)
raw, err := io.Read("/usr/local/etc/panel/config.yml")
if err != nil {
return err
}
if err = yaml.Unmarshal([]byte(raw), config); err != nil {
return err
}
config.HTTP.TLS = true
encoded, err := yaml.Marshal(config)
conf, err := config.Load()
if err != nil {
return err
}
if err = io.Write("/usr/local/etc/panel/config.yml", string(encoded), 0700); err != nil {
conf.HTTP.TLS = true
if err = config.Save(conf); err != nil {
return err
}
@@ -332,23 +321,14 @@ func (s *CliService) HTTPSOn(ctx context.Context, cmd *cli.Command) error {
}
func (s *CliService) HTTPSOff(ctx context.Context, cmd *cli.Command) error {
config := new(types.PanelConfig)
raw, err := io.Read("/usr/local/etc/panel/config.yml")
if err != nil {
return err
}
if err = yaml.Unmarshal([]byte(raw), config); err != nil {
return err
}
config.HTTP.TLS = false
encoded, err := yaml.Marshal(config)
conf, err := config.Load()
if err != nil {
return err
}
if err = io.Write("/usr/local/etc/panel/config.yml", string(encoded), 0700); err != nil {
conf.HTTP.TLS = false
if err = config.Save(conf); err != nil {
return err
}
@@ -388,49 +368,31 @@ func (s *CliService) HTTPSGenerate(ctx context.Context, cmd *cli.Command) error
}
func (s *CliService) EntranceOn(ctx context.Context, cmd *cli.Command) error {
config := new(types.PanelConfig)
raw, err := io.Read("/usr/local/etc/panel/config.yml")
if err != nil {
return err
}
if err = yaml.Unmarshal([]byte(raw), config); err != nil {
return err
}
config.HTTP.Entrance = "/" + str.Random(6)
encoded, err := yaml.Marshal(config)
conf, err := config.Load()
if err != nil {
return err
}
if err = io.Write("/usr/local/etc/panel/config.yml", string(encoded), 0700); err != nil {
conf.HTTP.Entrance = "/" + str.Random(6)
if err = config.Save(conf); err != nil {
return err
}
fmt.Println(s.t.Get("Entrance enabled"))
fmt.Println(s.t.Get("Entrance: %s", config.HTTP.Entrance))
fmt.Println(s.t.Get("Entrance: %s", conf.HTTP.Entrance))
return s.Restart(ctx, cmd)
}
func (s *CliService) EntranceOff(ctx context.Context, cmd *cli.Command) error {
config := new(types.PanelConfig)
raw, err := io.Read("/usr/local/etc/panel/config.yml")
if err != nil {
return err
}
if err = yaml.Unmarshal([]byte(raw), config); err != nil {
return err
}
config.HTTP.Entrance = "/"
encoded, err := yaml.Marshal(config)
conf, err := config.Load()
if err != nil {
return err
}
if err = io.Write("/usr/local/etc/panel/config.yml", string(encoded), 0700); err != nil {
conf.HTTP.Entrance = "/"
if err = config.Save(conf); err != nil {
return err
}
@@ -439,23 +401,14 @@ func (s *CliService) EntranceOff(ctx context.Context, cmd *cli.Command) error {
}
func (s *CliService) BindDomainOff(ctx context.Context, cmd *cli.Command) error {
config := new(types.PanelConfig)
raw, err := io.Read("/usr/local/etc/panel/config.yml")
if err != nil {
return err
}
if err = yaml.Unmarshal([]byte(raw), config); err != nil {
return err
}
config.HTTP.BindDomain = nil
encoded, err := yaml.Marshal(config)
conf, err := config.Load()
if err != nil {
return err
}
if err = io.Write("/usr/local/etc/panel/config.yml", string(encoded), 0700); err != nil {
conf.HTTP.BindDomain = nil
if err = config.Save(conf); err != nil {
return err
}
@@ -464,23 +417,14 @@ func (s *CliService) BindDomainOff(ctx context.Context, cmd *cli.Command) error
}
func (s *CliService) BindIPOff(ctx context.Context, cmd *cli.Command) error {
config := new(types.PanelConfig)
raw, err := io.Read("/usr/local/etc/panel/config.yml")
if err != nil {
return err
}
if err = yaml.Unmarshal([]byte(raw), config); err != nil {
return err
}
config.HTTP.BindIP = nil
encoded, err := yaml.Marshal(config)
conf, err := config.Load()
if err != nil {
return err
}
if err = io.Write("/usr/local/etc/panel/config.yml", string(encoded), 0700); err != nil {
conf.HTTP.BindIP = nil
if err = config.Save(conf); err != nil {
return err
}
@@ -489,23 +433,14 @@ func (s *CliService) BindIPOff(ctx context.Context, cmd *cli.Command) error {
}
func (s *CliService) BindUAOff(ctx context.Context, cmd *cli.Command) error {
config := new(types.PanelConfig)
raw, err := io.Read("/usr/local/etc/panel/config.yml")
if err != nil {
return err
}
if err = yaml.Unmarshal([]byte(raw), config); err != nil {
return err
}
config.HTTP.BindUA = nil
encoded, err := yaml.Marshal(config)
conf, err := config.Load()
if err != nil {
return err
}
if err = io.Write("/usr/local/etc/panel/config.yml", string(encoded), 0700); err != nil {
conf.HTTP.BindUA = nil
if err = config.Save(conf); err != nil {
return err
}
@@ -519,27 +454,18 @@ func (s *CliService) Port(ctx context.Context, cmd *cli.Command) error {
return errors.New(s.t.Get("Port range error"))
}
config := new(types.PanelConfig)
raw, err := io.Read("/usr/local/etc/panel/config.yml")
conf, err := config.Load()
if err != nil {
return err
}
if err = yaml.Unmarshal([]byte(raw), config); err != nil {
return err
}
if port != config.HTTP.Port {
if port != conf.HTTP.Port {
if os.TCPPortInUse(port) {
return errors.New(s.t.Get("Port already in use"))
}
}
config.HTTP.Port = port
encoded, err := yaml.Marshal(config)
if err != nil {
return err
}
conf.HTTP.Port = port
// 放行端口
if ok, _ := systemctl.IsEnabled("firewalld"); ok {
@@ -556,7 +482,7 @@ func (s *CliService) Port(ctx context.Context, cmd *cli.Command) error {
}
}
if err = io.Write("/usr/local/etc/panel/config.yml", string(encoded), 0700); err != nil {
if err = config.Save(conf); err != nil {
return err
}
@@ -968,17 +894,13 @@ func (s *CliService) Init(ctx context.Context, cmd *cli.Command) error {
return errors.New(s.t.Get("Initialization failed: %v", err))
}
config := new(types.PanelConfig)
raw, err := io.Read("/usr/local/etc/panel/config.yml")
conf, err := config.Load()
if err != nil {
return err
}
if err = yaml.Unmarshal([]byte(raw), config); err != nil {
return err
}
config.App.Key = str.Random(32)
config.HTTP.Entrance = "/" + str.Random(6)
conf.App.Key = str.Random(32)
conf.HTTP.Entrance = "/" + str.Random(6)
// 随机默认端口
checkPort:
@@ -986,7 +908,7 @@ checkPort:
if os.TCPPortInUse(port) {
goto checkPort
}
config.HTTP.Port = port
conf.HTTP.Port = port
// 放行端口
fw := firewall.NewFirewall()
@@ -998,11 +920,7 @@ checkPort:
Strategy: firewall.StrategyAccept,
}, firewall.OperationAdd)
encoded, err := yaml.Marshal(config)
if err != nil {
return err
}
if err = io.Write("/usr/local/etc/panel/config.yml", string(encoded), 0700); err != nil {
if err = config.Save(conf); err != nil {
return err
}

View File

@@ -8,7 +8,6 @@ import (
"strings"
"github.com/hashicorp/go-version"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/libtnb/chix"
"github.com/libtnb/utils/collect"
@@ -20,6 +19,7 @@ import (
"github.com/acepanel/panel/internal/biz"
"github.com/acepanel/panel/internal/http/request"
"github.com/acepanel/panel/pkg/api"
"github.com/acepanel/panel/pkg/config"
"github.com/acepanel/panel/pkg/db"
"github.com/acepanel/panel/pkg/shell"
"github.com/acepanel/panel/pkg/tools"
@@ -29,7 +29,7 @@ import (
type HomeService struct {
t *gotext.Locale
api *api.API
conf *koanf.Koanf
conf *config.Config
taskRepo biz.TaskRepo
websiteRepo biz.WebsiteRepo
appRepo biz.AppRepo
@@ -38,7 +38,7 @@ type HomeService struct {
backupRepo biz.BackupRepo
}
func NewHomeService(t *gotext.Locale, conf *koanf.Koanf, task biz.TaskRepo, website biz.WebsiteRepo, appRepo biz.AppRepo, setting biz.SettingRepo, cron biz.CronRepo, backupRepo biz.BackupRepo) *HomeService {
func NewHomeService(t *gotext.Locale, conf *config.Config, task biz.TaskRepo, website biz.WebsiteRepo, appRepo biz.AppRepo, setting biz.SettingRepo, cron biz.CronRepo, backupRepo biz.BackupRepo) *HomeService {
return &HomeService{
t: t,
api: api.NewAPI(app.Version, app.Locale),
@@ -60,7 +60,7 @@ func (s *HomeService) Panel(w http.ResponseWriter, r *http.Request) {
Success(w, chix.M{
"name": name,
"locale": s.conf.String("app.locale"),
"locale": s.conf.App.Locale,
})
}

View File

@@ -13,7 +13,6 @@ import (
"strings"
"time"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
"github.com/libtnb/chix"
"github.com/libtnb/sessions"
@@ -22,17 +21,18 @@ import (
"github.com/acepanel/panel/internal/biz"
"github.com/acepanel/panel/internal/http/request"
"github.com/acepanel/panel/pkg/config"
"github.com/acepanel/panel/pkg/rsacrypto"
)
type UserService struct {
t *gotext.Locale
conf *koanf.Koanf
conf *config.Config
session *sessions.Manager
userRepo biz.UserRepo
}
func NewUserService(t *gotext.Locale, conf *koanf.Koanf, session *sessions.Manager, user biz.UserRepo) *UserService {
func NewUserService(t *gotext.Locale, conf *config.Config, session *sessions.Manager, user biz.UserRepo) *UserService {
gob.Register(rsa.PrivateKey{}) // 必须注册 rsa.PrivateKey 类型否则无法反序列化 session 中的 key
return &UserService{
t: t,
@@ -108,7 +108,7 @@ func (s *UserService) Login(w http.ResponseWriter, r *http.Request) {
// 安全登录下,将当前客户端与会话绑定
// 安全登录只在未启用面板 HTTPS 时生效
ip := r.RemoteAddr
ipHeader := s.conf.String("http.ip_header")
ipHeader := s.conf.HTTP.IPHeader
if ipHeader != "" && r.Header.Get(ipHeader) != "" {
ip = strings.Split(r.Header.Get(ipHeader), ",")[0]
}
@@ -117,7 +117,7 @@ func (s *UserService) Login(w http.ResponseWriter, r *http.Request) {
ip = r.RemoteAddr
}
if req.SafeLogin && !s.conf.Bool("http.tls") {
if req.SafeLogin && !s.conf.HTTP.TLS {
sess.Put("safe_login", true)
sess.Put("safe_client", fmt.Sprintf("%x", sha256.Sum256([]byte(ip))))
} else {

View File

@@ -7,24 +7,24 @@ import (
"net/http"
"github.com/coder/websocket"
"github.com/knadh/koanf/v2"
"github.com/leonelquinteros/gotext"
stdssh "golang.org/x/crypto/ssh"
"github.com/acepanel/panel/internal/biz"
"github.com/acepanel/panel/internal/http/request"
"github.com/acepanel/panel/pkg/config"
"github.com/acepanel/panel/pkg/shell"
"github.com/acepanel/panel/pkg/ssh"
)
type WsService struct {
t *gotext.Locale
conf *koanf.Koanf
conf *config.Config
log *slog.Logger
sshRepo biz.SSHRepo
}
func NewWsService(t *gotext.Locale, conf *koanf.Koanf, log *slog.Logger, ssh biz.SSHRepo) *WsService {
func NewWsService(t *gotext.Locale, conf *config.Config, log *slog.Logger, ssh biz.SSHRepo) *WsService {
return &WsService{
t: t,
conf: conf,
@@ -120,7 +120,7 @@ func (s *WsService) upgrade(w http.ResponseWriter, r *http.Request) (*websocket.
}
// debug 模式下不校验 origin方便 vite 代理调试
if s.conf.Bool("app.debug") {
if s.conf.App.Debug {
opts.InsecureSkipVerify = true
}

95
pkg/config/config.go Normal file
View File

@@ -0,0 +1,95 @@
package config
import (
"os"
"go.yaml.in/yaml/v4"
"github.com/acepanel/panel/pkg/io"
)
const configPath = "/opt/ace/panel/storage/config.yml"
// Config 面板配置结构体
type Config struct {
App AppConfig `yaml:"app"`
HTTP HTTPConfig `yaml:"http"`
Database DatabaseConfig `yaml:"database"`
Session SessionConfig `yaml:"session"`
}
type AppConfig struct {
Debug bool `yaml:"debug"`
Key string `yaml:"key"`
Locale string `yaml:"locale"`
Timezone string `yaml:"timezone"`
Root string `yaml:"root"`
}
type HTTPConfig struct {
Debug bool `yaml:"debug"`
Port uint `yaml:"port"`
Entrance string `yaml:"entrance"`
TLS bool `yaml:"tls"`
IPHeader string `yaml:"ip_header"`
BindDomain []string `yaml:"bind_domain"`
BindIP []string `yaml:"bind_ip"`
BindUA []string `yaml:"bind_ua"`
}
type DatabaseConfig struct {
Debug bool `yaml:"debug"`
}
type SessionConfig struct {
Lifetime uint `yaml:"lifetime"`
}
func Load() (*Config, error) {
path := configPath
if !io.Exists(path) {
path = "config.yml" // For testing purpose
}
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer func() { _ = file.Close() }()
var conf Config
decoder := yaml.NewDecoder(file)
if err = decoder.Decode(&conf); err != nil {
return nil, err
}
return &conf, nil
}
func Save(conf *Config) error {
data, err := yaml.Marshal(conf)
if err != nil {
return err
}
return os.WriteFile(configPath, data, 0600)
}
func Check(conf *Config) (bool, error) {
currentConf, err := Load()
if err != nil {
return false, err
}
currentData, err := yaml.Marshal(currentConf)
if err != nil {
return false, err
}
newData, err := yaml.Marshal(conf)
if err != nil {
return false, err
}
return string(currentData) == string(newData), nil
}

View File

@@ -1,36 +0,0 @@
package types
// PanelConfig 面板配置结构体
type PanelConfig struct {
App PanelAppConfig `yaml:"app"`
HTTP PanelHTTPConfig `yaml:"http"`
Database PanelDatabaseConfig `yaml:"database"`
Session PanelSessionConfig `yaml:"session"`
}
type PanelAppConfig struct {
Debug bool `yaml:"debug"`
Key string `yaml:"key"`
Locale string `yaml:"locale"`
Timezone string `yaml:"timezone"`
Root string `yaml:"root"`
}
type PanelHTTPConfig struct {
Debug bool `yaml:"debug"`
Port uint `yaml:"port"`
Entrance string `yaml:"entrance"`
TLS bool `yaml:"tls"`
IPHeader string `yaml:"ip_header"`
BindDomain []string `yaml:"bind_domain"`
BindIP []string `yaml:"bind_ip"`
BindUA []string `yaml:"bind_ua"`
}
type PanelDatabaseConfig struct {
Debug bool `yaml:"debug"`
}
type PanelSessionConfig struct {
Lifetime uint `yaml:"lifetime"`
}

View File

@@ -7,8 +7,9 @@ import (
"slices"
"strings"
"github.com/acepanel/panel/pkg/webserver/types"
"github.com/tufanbarisyildirim/gonginx/config"
"github.com/acepanel/panel/pkg/webserver/types"
)
// StaticVhost 纯静态虚拟主机