mirror of
https://github.com/acepanel/panel.git
synced 2026-02-06 14:47:18 +08:00
refactor: 应用支持依赖注入
This commit is contained in:
@@ -38,13 +38,13 @@ func initCli() (*app.Cli, error) {
|
||||
userRepo := data.NewUserRepo(db)
|
||||
settingRepo := data.NewSettingRepo(db, koanf, taskRepo)
|
||||
databaseServerRepo := data.NewDatabaseServerRepo(db, logger)
|
||||
databaseUserRepo := data.NewDatabaseUserRepo(databaseServerRepo)
|
||||
databaseRepo := data.NewDatabaseRepo(databaseServerRepo, databaseUserRepo)
|
||||
databaseUserRepo := data.NewDatabaseUserRepo(db, databaseServerRepo)
|
||||
databaseRepo := data.NewDatabaseRepo(db, databaseServerRepo, databaseUserRepo)
|
||||
certRepo := data.NewCertRepo(db)
|
||||
certAccountRepo := data.NewCertAccountRepo(db, userRepo)
|
||||
websiteRepo := data.NewWebsiteRepo(db, cacheRepo, databaseRepo, databaseServerRepo, databaseUserRepo, certRepo, certAccountRepo)
|
||||
backupRepo := data.NewBackupRepo(db, settingRepo, websiteRepo)
|
||||
cliService := service.NewCliService(koanf, appRepo, cacheRepo, userRepo, settingRepo, backupRepo, websiteRepo, databaseServerRepo)
|
||||
cliService := service.NewCliService(koanf, db, appRepo, cacheRepo, userRepo, settingRepo, backupRepo, websiteRepo, databaseServerRepo)
|
||||
cli := route.NewCli(cliService)
|
||||
command := bootstrap.NewCli(cli)
|
||||
appCli := app.NewCli(command)
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/google/wire"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/apps"
|
||||
"github.com/TheTNB/panel/internal/bootstrap"
|
||||
"github.com/TheTNB/panel/internal/data"
|
||||
"github.com/TheTNB/panel/internal/http/middleware"
|
||||
@@ -16,5 +17,5 @@ import (
|
||||
|
||||
// initWeb init application.
|
||||
func initWeb() (*app.Web, error) {
|
||||
panic(wire.Build(bootstrap.ProviderSet, middleware.ProviderSet, route.ProviderSet, service.ProviderSet, data.ProviderSet, job.ProviderSet, app.NewWeb))
|
||||
panic(wire.Build(bootstrap.ProviderSet, middleware.ProviderSet, route.ProviderSet, service.ProviderSet, data.ProviderSet, apps.ProviderSet, job.ProviderSet, app.NewWeb))
|
||||
}
|
||||
|
||||
@@ -8,6 +8,25 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/apps"
|
||||
"github.com/TheTNB/panel/internal/apps/benchmark"
|
||||
"github.com/TheTNB/panel/internal/apps/docker"
|
||||
"github.com/TheTNB/panel/internal/apps/fail2ban"
|
||||
"github.com/TheTNB/panel/internal/apps/frp"
|
||||
"github.com/TheTNB/panel/internal/apps/gitea"
|
||||
"github.com/TheTNB/panel/internal/apps/memcached"
|
||||
"github.com/TheTNB/panel/internal/apps/mysql"
|
||||
"github.com/TheTNB/panel/internal/apps/nginx"
|
||||
"github.com/TheTNB/panel/internal/apps/php"
|
||||
"github.com/TheTNB/panel/internal/apps/phpmyadmin"
|
||||
"github.com/TheTNB/panel/internal/apps/podman"
|
||||
"github.com/TheTNB/panel/internal/apps/postgresql"
|
||||
"github.com/TheTNB/panel/internal/apps/pureftpd"
|
||||
"github.com/TheTNB/panel/internal/apps/redis"
|
||||
"github.com/TheTNB/panel/internal/apps/rsync"
|
||||
"github.com/TheTNB/panel/internal/apps/s3fs"
|
||||
"github.com/TheTNB/panel/internal/apps/supervisor"
|
||||
"github.com/TheTNB/panel/internal/apps/toolbox"
|
||||
"github.com/TheTNB/panel/internal/bootstrap"
|
||||
"github.com/TheTNB/panel/internal/data"
|
||||
"github.com/TheTNB/panel/internal/http/middleware"
|
||||
@@ -45,8 +64,8 @@ func initWeb() (*app.Web, error) {
|
||||
userRepo := data.NewUserRepo(db)
|
||||
userService := service.NewUserService(koanf, manager, userRepo)
|
||||
databaseServerRepo := data.NewDatabaseServerRepo(db, logger)
|
||||
databaseUserRepo := data.NewDatabaseUserRepo(databaseServerRepo)
|
||||
databaseRepo := data.NewDatabaseRepo(databaseServerRepo, databaseUserRepo)
|
||||
databaseUserRepo := data.NewDatabaseUserRepo(db, databaseServerRepo)
|
||||
databaseRepo := data.NewDatabaseRepo(db, databaseServerRepo, databaseUserRepo)
|
||||
certRepo := data.NewCertRepo(db)
|
||||
certAccountRepo := data.NewCertAccountRepo(db, userRepo)
|
||||
websiteRepo := data.NewWebsiteRepo(db, cacheRepo, databaseRepo, databaseServerRepo, databaseUserRepo, certRepo, certAccountRepo)
|
||||
@@ -85,10 +104,29 @@ func initWeb() (*app.Web, error) {
|
||||
monitorService := service.NewMonitorService(settingRepo, monitorRepo)
|
||||
settingService := service.NewSettingService(settingRepo)
|
||||
systemctlService := service.NewSystemctlService()
|
||||
http := route.NewHttp(userService, dashboardService, taskService, websiteService, databaseService, databaseServerService, databaseUserService, backupService, certService, certDNSService, certAccountService, appService, cronService, processService, safeService, firewallService, sshService, containerService, containerNetworkService, containerImageService, containerVolumeService, fileService, monitorService, settingService, systemctlService)
|
||||
benchmarkApp := benchmark.NewApp()
|
||||
dockerApp := docker.NewApp()
|
||||
fail2banApp := fail2ban.NewApp(websiteRepo)
|
||||
frpApp := frp.NewApp()
|
||||
giteaApp := gitea.NewApp()
|
||||
memcachedApp := memcached.NewApp()
|
||||
mysqlApp := mysql.NewApp(settingRepo)
|
||||
nginxApp := nginx.NewApp()
|
||||
phpApp := php.NewApp(taskRepo)
|
||||
phpmyadminApp := phpmyadmin.NewApp()
|
||||
podmanApp := podman.NewApp()
|
||||
postgresqlApp := postgresql.NewApp()
|
||||
pureftpdApp := pureftpd.NewApp()
|
||||
redisApp := redis.NewApp()
|
||||
rsyncApp := rsync.NewApp()
|
||||
s3fsApp := s3fs.NewApp(settingRepo)
|
||||
supervisorApp := supervisor.NewApp()
|
||||
toolboxApp := toolbox.NewApp()
|
||||
loader := apps.NewLoader(benchmarkApp, dockerApp, fail2banApp, frpApp, giteaApp, memcachedApp, mysqlApp, nginxApp, phpApp, phpmyadminApp, podmanApp, postgresqlApp, pureftpdApp, redisApp, rsyncApp, s3fsApp, supervisorApp, toolboxApp)
|
||||
http := route.NewHttp(userService, dashboardService, taskService, websiteService, databaseService, databaseServerService, databaseUserService, backupService, certService, certDNSService, certAccountService, appService, cronService, processService, safeService, firewallService, sshService, containerService, containerNetworkService, containerImageService, containerVolumeService, fileService, monitorService, settingService, systemctlService, loader)
|
||||
wsService := service.NewWsService(koanf, sshRepo)
|
||||
ws := route.NewWs(wsService)
|
||||
mux, err := bootstrap.NewRouter(koanf, db, logger, manager, middlewares, http, ws)
|
||||
mux, err := bootstrap.NewRouter(middlewares, http, ws)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
1
go.mod
1
go.mod
@@ -5,7 +5,6 @@ go 1.23
|
||||
require (
|
||||
github.com/bddjr/hlfhr v1.3.5
|
||||
github.com/beevik/ntp v1.4.3
|
||||
github.com/cloudflare/tableflip v1.2.3
|
||||
github.com/creack/pty v1.1.24
|
||||
github.com/expr-lang/expr v1.16.9
|
||||
github.com/glebarez/sqlite v1.11.0
|
||||
|
||||
3
go.sum
3
go.sum
@@ -6,8 +6,6 @@ github.com/bddjr/hlfhr v1.3.5 h1:nBbye1k7XQ+4KJIGKQADk6lIuDUV+fcXG+TUUsFihPk=
|
||||
github.com/bddjr/hlfhr v1.3.5/go.mod h1:oyIv4Q9JpCgZFdtH3KyTNWp7YYRWl4zl8k4ozrMAB4g=
|
||||
github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho=
|
||||
github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q=
|
||||
github.com/cloudflare/tableflip v1.2.3 h1:8I+B99QnnEWPHOY3fWipwVKxS70LGgUsslG7CSfmHMw=
|
||||
github.com/cloudflare/tableflip v1.2.3/go.mod h1:P4gRehmV6Z2bY5ao5ml9Pd8u6kuEnlB37pUFMmv7j2E=
|
||||
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@@ -190,7 +188,6 @@ golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
Orm *gorm.DB
|
||||
)
|
||||
|
||||
// 面板状态常量
|
||||
const (
|
||||
StatusNormal = iota
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/bddjr/hlfhr"
|
||||
"github.com/cloudflare/tableflip"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"github.com/gookit/validate"
|
||||
@@ -51,73 +44,18 @@ func (r *Web) Run() error {
|
||||
fmt.Println("[CRON] cron scheduler started")
|
||||
|
||||
// run http server
|
||||
if runtime.GOOS != "windows" {
|
||||
return r.runServer()
|
||||
}
|
||||
|
||||
return r.runServerFallback()
|
||||
}
|
||||
|
||||
// runServer graceful run server
|
||||
func (r *Web) runServer() error {
|
||||
upg, err := tableflip.New(tableflip.Options{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer upg.Stop()
|
||||
|
||||
// By prefixing PID to log, easy to interrupt from another process.
|
||||
log.SetPrefix(fmt.Sprintf("[PID %d]", os.Getpid()))
|
||||
|
||||
// Listen for the process signal to trigger the tableflip upgrade.
|
||||
go func() {
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, syscall.SIGHUP)
|
||||
for range sig {
|
||||
if err = upg.Upgrade(); err != nil {
|
||||
log.Println("[Graceful] upgrade failed:", err)
|
||||
}
|
||||
if r.conf.Bool("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")
|
||||
if err := r.server.ListenAndServeTLS(cert, key); !errors.Is(err, http.ErrServerClosed) {
|
||||
return err
|
||||
}
|
||||
}()
|
||||
|
||||
ln, err := upg.Listen("tcp", r.conf.MustString("http.address"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ln.Close()
|
||||
|
||||
fmt.Println("[HTTP] listening and serving on", r.conf.MustString("http.address"))
|
||||
go func() {
|
||||
if err = r.server.Serve(ln); !errors.Is(err, http.ErrServerClosed) {
|
||||
log.Println("[HTTP] server error:", err)
|
||||
} else {
|
||||
fmt.Println("[HTTP] listening and serving on port", r.conf.MustInt("http.port"))
|
||||
if err := r.server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
|
||||
return err
|
||||
}
|
||||
}()
|
||||
|
||||
// tableflip ready
|
||||
if err = upg.Ready(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("[Graceful] ready for upgrade")
|
||||
<-upg.Exit()
|
||||
|
||||
// Make sure to set a deadline on exiting the process
|
||||
// after upg.Exit() is closed. No new upgrades can be
|
||||
// performed if the parent doesn't exit.
|
||||
time.AfterFunc(60*time.Second, func() {
|
||||
log.Println("[Graceful] shutdown timeout, force exit")
|
||||
os.Exit(1)
|
||||
})
|
||||
|
||||
// Wait for connections to drain.
|
||||
return r.server.Shutdown(context.Background())
|
||||
}
|
||||
|
||||
// runServerFallback fallback for windows
|
||||
func (r *Web) runServerFallback() error {
|
||||
fmt.Println("[HTTP] listening and serving on", r.conf.MustString("http.address"))
|
||||
if err := r.server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
170
internal/apps/apps.go
Normal file
170
internal/apps/apps.go
Normal file
@@ -0,0 +1,170 @@
|
||||
package apps
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/wire"
|
||||
|
||||
"github.com/TheTNB/panel/internal/apps/benchmark"
|
||||
"github.com/TheTNB/panel/internal/apps/docker"
|
||||
"github.com/TheTNB/panel/internal/apps/fail2ban"
|
||||
"github.com/TheTNB/panel/internal/apps/frp"
|
||||
"github.com/TheTNB/panel/internal/apps/gitea"
|
||||
"github.com/TheTNB/panel/internal/apps/memcached"
|
||||
"github.com/TheTNB/panel/internal/apps/mysql"
|
||||
"github.com/TheTNB/panel/internal/apps/nginx"
|
||||
"github.com/TheTNB/panel/internal/apps/php"
|
||||
"github.com/TheTNB/panel/internal/apps/phpmyadmin"
|
||||
"github.com/TheTNB/panel/internal/apps/podman"
|
||||
"github.com/TheTNB/panel/internal/apps/postgresql"
|
||||
"github.com/TheTNB/panel/internal/apps/pureftpd"
|
||||
"github.com/TheTNB/panel/internal/apps/redis"
|
||||
"github.com/TheTNB/panel/internal/apps/rsync"
|
||||
"github.com/TheTNB/panel/internal/apps/s3fs"
|
||||
"github.com/TheTNB/panel/internal/apps/supervisor"
|
||||
"github.com/TheTNB/panel/internal/apps/toolbox"
|
||||
)
|
||||
|
||||
var ProviderSet = wire.NewSet(
|
||||
NewLoader,
|
||||
benchmark.NewApp,
|
||||
docker.NewApp,
|
||||
fail2ban.NewApp,
|
||||
frp.NewApp,
|
||||
gitea.NewApp,
|
||||
memcached.NewApp,
|
||||
mysql.NewApp,
|
||||
nginx.NewApp,
|
||||
php.NewApp,
|
||||
phpmyadmin.NewApp,
|
||||
podman.NewApp,
|
||||
postgresql.NewApp,
|
||||
pureftpd.NewApp,
|
||||
redis.NewApp,
|
||||
rsync.NewApp,
|
||||
s3fs.NewApp,
|
||||
supervisor.NewApp,
|
||||
toolbox.NewApp,
|
||||
)
|
||||
|
||||
var slugs []string
|
||||
|
||||
type Loader struct {
|
||||
benchmark *benchmark.App
|
||||
docker *docker.App
|
||||
fail2ban *fail2ban.App
|
||||
frp *frp.App
|
||||
gitea *gitea.App
|
||||
memcached *memcached.App
|
||||
mysql *mysql.App
|
||||
nginx *nginx.App
|
||||
php *php.App
|
||||
phpmyadmin *phpmyadmin.App
|
||||
podman *podman.App
|
||||
postgresql *postgresql.App
|
||||
pureftpd *pureftpd.App
|
||||
redis *redis.App
|
||||
rsync *rsync.App
|
||||
s3fs *s3fs.App
|
||||
supervisor *supervisor.App
|
||||
toolbox *toolbox.App
|
||||
}
|
||||
|
||||
func NewLoader(
|
||||
benchmark *benchmark.App,
|
||||
docker *docker.App,
|
||||
fail2ban *fail2ban.App,
|
||||
frp *frp.App,
|
||||
gitea *gitea.App,
|
||||
memcached *memcached.App,
|
||||
mysql *mysql.App,
|
||||
nginx *nginx.App,
|
||||
php *php.App,
|
||||
phpmyadmin *phpmyadmin.App,
|
||||
podman *podman.App,
|
||||
postgresql *postgresql.App,
|
||||
pureftpd *pureftpd.App,
|
||||
redis *redis.App,
|
||||
rsync *rsync.App,
|
||||
s3fs *s3fs.App,
|
||||
supervisor *supervisor.App,
|
||||
toolbox *toolbox.App,
|
||||
) *Loader {
|
||||
loader := &Loader{
|
||||
benchmark: benchmark,
|
||||
docker: docker,
|
||||
fail2ban: fail2ban,
|
||||
frp: frp,
|
||||
gitea: gitea,
|
||||
memcached: memcached,
|
||||
mysql: mysql,
|
||||
nginx: nginx,
|
||||
php: php,
|
||||
phpmyadmin: phpmyadmin,
|
||||
podman: podman,
|
||||
postgresql: postgresql,
|
||||
pureftpd: pureftpd,
|
||||
redis: redis,
|
||||
rsync: rsync,
|
||||
s3fs: s3fs,
|
||||
supervisor: supervisor,
|
||||
toolbox: toolbox,
|
||||
}
|
||||
|
||||
loader.initSlugs()
|
||||
return loader
|
||||
}
|
||||
|
||||
func (r *Loader) Register(mux chi.Router) {
|
||||
mux.Route("/benchmark", r.benchmark.Route)
|
||||
mux.Route("/docker", r.docker.Route)
|
||||
mux.Route("/fail2ban", r.fail2ban.Route)
|
||||
mux.Route("/frp", r.frp.Route)
|
||||
mux.Route("/gitea", r.gitea.Route)
|
||||
mux.Route("/memcached", r.memcached.Route)
|
||||
mux.Route("/mysql", r.mysql.Route)
|
||||
mux.Route("/nginx", r.nginx.Route)
|
||||
mux.Route("/php74", r.php.Route(74))
|
||||
mux.Route("/php80", r.php.Route(80))
|
||||
mux.Route("/php81", r.php.Route(81))
|
||||
mux.Route("/php82", r.php.Route(82))
|
||||
mux.Route("/php83", r.php.Route(83))
|
||||
mux.Route("/php84", r.php.Route(84))
|
||||
mux.Route("/phpmyadmin", r.phpmyadmin.Route)
|
||||
mux.Route("/podman", r.podman.Route)
|
||||
mux.Route("/postgresql", r.postgresql.Route)
|
||||
mux.Route("/pureftpd", r.pureftpd.Route)
|
||||
mux.Route("/redis", r.redis.Route)
|
||||
mux.Route("/rsync", r.rsync.Route)
|
||||
mux.Route("/s3fs", r.s3fs.Route)
|
||||
mux.Route("/supervisor", r.supervisor.Route)
|
||||
mux.Route("/toolbox", r.toolbox.Route)
|
||||
}
|
||||
|
||||
func (r *Loader) initSlugs() []string {
|
||||
if len(slugs) == 0 {
|
||||
v := reflect.Indirect(reflect.ValueOf(r))
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := v.Field(i)
|
||||
slug := strings.ToLower(v.Type().Field(i).Name)
|
||||
if !field.IsNil() {
|
||||
slugs = append(slugs, slug)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理php
|
||||
slugs = slices.DeleteFunc(slugs, func(slug string) bool {
|
||||
return slug == "php"
|
||||
})
|
||||
slugs = append(slugs, "php74", "php80", "php81", "php82", "php83", "php84")
|
||||
}
|
||||
|
||||
return slugs
|
||||
}
|
||||
|
||||
func Slugs() []string {
|
||||
return slugs
|
||||
}
|
||||
@@ -21,18 +21,24 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/internal/service"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
type App struct {
|
||||
}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Post("/test", s.Test)
|
||||
}
|
||||
|
||||
// Test 运行测试
|
||||
func (s *Service) Test(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Test(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Test](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -73,7 +79,7 @@ func (s *Service) Test(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// calculateCpuScore 计算CPU成绩
|
||||
func (s *Service) calculateCpuScore(duration time.Duration) int {
|
||||
func (s *App) calculateCpuScore(duration time.Duration) int {
|
||||
score := int((10 / duration.Seconds()) * float64(3000))
|
||||
|
||||
if score < 0 {
|
||||
@@ -83,7 +89,7 @@ func (s *Service) calculateCpuScore(duration time.Duration) int {
|
||||
}
|
||||
|
||||
// calculateScore 计算内存/硬盘成绩
|
||||
func (s *Service) calculateScore(duration time.Duration) int {
|
||||
func (s *App) calculateScore(duration time.Duration) int {
|
||||
score := int((20 / duration.Seconds()) * float64(30000))
|
||||
|
||||
if score < 0 {
|
||||
@@ -94,7 +100,7 @@ func (s *Service) calculateScore(duration time.Duration) int {
|
||||
|
||||
// 图像处理
|
||||
|
||||
func (s *Service) imageProcessing(multi bool) int {
|
||||
func (s *App) imageProcessing(multi bool) int {
|
||||
n := 1
|
||||
if multi {
|
||||
n = runtime.NumCPU()
|
||||
@@ -107,7 +113,7 @@ func (s *Service) imageProcessing(multi bool) int {
|
||||
return s.calculateCpuScore(duration)
|
||||
}
|
||||
|
||||
func (s *Service) imageProcessingTask(numThreads int) error {
|
||||
func (s *App) imageProcessingTask(numThreads int) error {
|
||||
img := image.NewRGBA(image.Rect(0, 0, 4000, 4000))
|
||||
for x := 0; x < 4000; x++ {
|
||||
for y := 0; y < 4000; y++ {
|
||||
@@ -156,7 +162,7 @@ func (s *Service) imageProcessingTask(numThreads int) error {
|
||||
|
||||
// 机器学习(矩阵乘法)
|
||||
|
||||
func (s *Service) machineLearning(multi bool) int {
|
||||
func (s *App) machineLearning(multi bool) int {
|
||||
n := 1
|
||||
if multi {
|
||||
n = runtime.NumCPU()
|
||||
@@ -167,7 +173,7 @@ func (s *Service) machineLearning(multi bool) int {
|
||||
return s.calculateCpuScore(duration)
|
||||
}
|
||||
|
||||
func (s *Service) machineLearningTask(numThreads int) {
|
||||
func (s *App) machineLearningTask(numThreads int) {
|
||||
size := 900
|
||||
a := make([][]float64, size)
|
||||
b := make([][]float64, size)
|
||||
@@ -214,7 +220,7 @@ func (s *Service) machineLearningTask(numThreads int) {
|
||||
|
||||
// 数学问题(计算斐波那契数)
|
||||
|
||||
func (s *Service) compileSimulationSingle(multi bool) int {
|
||||
func (s *App) compileSimulationSingle(multi bool) int {
|
||||
n := 1
|
||||
if multi {
|
||||
n = runtime.NumCPU()
|
||||
@@ -248,7 +254,7 @@ func (s *Service) compileSimulationSingle(multi bool) int {
|
||||
}
|
||||
|
||||
// 斐波那契函数
|
||||
func (s *Service) fib(n int) *big.Int {
|
||||
func (s *App) fib(n int) *big.Int {
|
||||
if n < 2 {
|
||||
return big.NewInt(int64(n))
|
||||
}
|
||||
@@ -265,7 +271,7 @@ func (s *Service) fib(n int) *big.Int {
|
||||
|
||||
// AES加密
|
||||
|
||||
func (s *Service) encryptionTest(multi bool) int {
|
||||
func (s *App) encryptionTest(multi bool) int {
|
||||
n := 1
|
||||
if multi {
|
||||
n = runtime.NumCPU()
|
||||
@@ -278,7 +284,7 @@ func (s *Service) encryptionTest(multi bool) int {
|
||||
return s.calculateCpuScore(duration)
|
||||
}
|
||||
|
||||
func (s *Service) encryptionTestTask(numThreads int) error {
|
||||
func (s *App) encryptionTestTask(numThreads int) error {
|
||||
key := []byte("abcdefghijklmnopqrstuvwxyz123456")
|
||||
dataSize := 1 * 1024 * 1024 * 1024 // 1GB
|
||||
plaintext := []byte(strings.Repeat("A", dataSize))
|
||||
@@ -320,7 +326,7 @@ func (s *Service) encryptionTestTask(numThreads int) error {
|
||||
|
||||
// 压缩/解压缩
|
||||
|
||||
func (s *Service) compressionTest(multi bool) int {
|
||||
func (s *App) compressionTest(multi bool) int {
|
||||
n := 1
|
||||
if multi {
|
||||
n = runtime.NumCPU()
|
||||
@@ -331,7 +337,7 @@ func (s *Service) compressionTest(multi bool) int {
|
||||
return s.calculateCpuScore(duration)
|
||||
}
|
||||
|
||||
func (s *Service) compressionTestTask(numThreads int) {
|
||||
func (s *App) compressionTestTask(numThreads int) {
|
||||
data := []byte(strings.Repeat("耗子面板", 50000000))
|
||||
chunkSize := len(data) / numThreads
|
||||
|
||||
@@ -381,7 +387,7 @@ func (s *Service) compressionTestTask(numThreads int) {
|
||||
|
||||
// 物理仿真(N体问题)
|
||||
|
||||
func (s *Service) physicsSimulation(multi bool) int {
|
||||
func (s *App) physicsSimulation(multi bool) int {
|
||||
n := 1
|
||||
if multi {
|
||||
n = runtime.NumCPU()
|
||||
@@ -392,7 +398,7 @@ func (s *Service) physicsSimulation(multi bool) int {
|
||||
return s.calculateCpuScore(duration)
|
||||
}
|
||||
|
||||
func (s *Service) physicsSimulationTask(numThreads int) {
|
||||
func (s *App) physicsSimulationTask(numThreads int) {
|
||||
const (
|
||||
numBodies = 4000
|
||||
steps = 30
|
||||
@@ -479,7 +485,7 @@ func (s *Service) physicsSimulationTask(numThreads int) {
|
||||
|
||||
// JSON解析
|
||||
|
||||
func (s *Service) jsonProcessing(multi bool) int {
|
||||
func (s *App) jsonProcessing(multi bool) int {
|
||||
n := 1
|
||||
if multi {
|
||||
n = runtime.NumCPU()
|
||||
@@ -490,7 +496,7 @@ func (s *Service) jsonProcessing(multi bool) int {
|
||||
return s.calculateCpuScore(duration)
|
||||
}
|
||||
|
||||
func (s *Service) jsonProcessingTask(numThreads int) {
|
||||
func (s *App) jsonProcessingTask(numThreads int) {
|
||||
numElements := 1000000
|
||||
elementsPerThread := numElements / numThreads
|
||||
|
||||
@@ -531,7 +537,7 @@ func (s *Service) jsonProcessingTask(numThreads int) {
|
||||
|
||||
// 内存性能
|
||||
|
||||
func (s *Service) memoryTestTask() map[string]any {
|
||||
func (s *App) memoryTestTask() map[string]any {
|
||||
results := make(map[string]any)
|
||||
dataSize := 500 * 1024 * 1024 // 500 MB
|
||||
data := make([]byte, dataSize)
|
||||
@@ -549,7 +555,7 @@ func (s *Service) memoryTestTask() map[string]any {
|
||||
return results
|
||||
}
|
||||
|
||||
func (s *Service) memoryBandwidthTest(data []byte) string {
|
||||
func (s *App) memoryBandwidthTest(data []byte) string {
|
||||
dataSize := len(data)
|
||||
|
||||
startTime := time.Now()
|
||||
@@ -566,7 +572,7 @@ func (s *Service) memoryBandwidthTest(data []byte) string {
|
||||
return fmt.Sprintf("%.2f MB/s", speed)
|
||||
}
|
||||
|
||||
func (s *Service) memoryLatencyTest(data []byte) string {
|
||||
func (s *App) memoryLatencyTest(data []byte) string {
|
||||
dataSize := len(data)
|
||||
indices := rand.Perm(dataSize)
|
||||
|
||||
@@ -585,7 +591,7 @@ func (s *Service) memoryLatencyTest(data []byte) string {
|
||||
|
||||
// 硬盘IO
|
||||
|
||||
func (s *Service) diskTestTask() map[string]any {
|
||||
func (s *App) diskTestTask() map[string]any {
|
||||
results := make(map[string]any)
|
||||
blockSizes := []int64{4 * 1024, 64 * 1024, 512 * 1024, 1 * 1024 * 1024} // 4K, 64K, 512K, 1M
|
||||
fileSize := int64(100 * 1024 * 1024) // 100MB 文件
|
||||
@@ -601,7 +607,7 @@ func (s *Service) diskTestTask() map[string]any {
|
||||
return results
|
||||
}
|
||||
|
||||
func (s *Service) diskIOTest(blockSize int64, fileSize int64) map[string]any {
|
||||
func (s *App) diskIOTest(blockSize int64, fileSize int64) map[string]any {
|
||||
result := make(map[string]any)
|
||||
tempFile := fmt.Sprintf("tempfile_%d", blockSize)
|
||||
defer os.Remove(tempFile)
|
||||
@@ -619,7 +625,7 @@ func (s *Service) diskIOTest(blockSize int64, fileSize int64) map[string]any {
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *Service) diskWriteTest(fileName string, blockSize int64, fileSize int64) (float64, float64) {
|
||||
func (s *App) diskWriteTest(fileName string, blockSize int64, fileSize int64) (float64, float64) {
|
||||
totalBlocks := fileSize / blockSize
|
||||
|
||||
data := make([]byte, blockSize)
|
||||
@@ -653,7 +659,7 @@ func (s *Service) diskWriteTest(fileName string, blockSize int64, fileSize int64
|
||||
return speed, iops
|
||||
}
|
||||
|
||||
func (s *Service) diskReadTest(fileName string, blockSize int64, fileSize int64) (float64, float64) {
|
||||
func (s *App) diskReadTest(fileName string, blockSize int64, fileSize int64) (float64, float64) {
|
||||
totalBlocks := fileSize / blockSize
|
||||
|
||||
data := make([]byte, blockSize)
|
||||
@@ -1,18 +0,0 @@
|
||||
package benchmark
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "benchmark",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Post("/test", service.Test)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -3,18 +3,25 @@ package docker
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/internal/service"
|
||||
"github.com/TheTNB/panel/pkg/io"
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
type App struct{}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/config", s.GetConfig)
|
||||
r.Post("/config", s.UpdateConfig)
|
||||
}
|
||||
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read("/etc/docker/daemon.json")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -24,7 +31,7 @@ func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,19 +0,0 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "docker",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-rat/chix"
|
||||
"github.com/go-rat/utils/str"
|
||||
"github.com/spf13/cast"
|
||||
@@ -17,18 +18,28 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/shell"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
type App struct {
|
||||
websiteRepo biz.WebsiteRepo
|
||||
}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{
|
||||
websiteRepo: nil, // TODO fixme
|
||||
func NewApp(website biz.WebsiteRepo) *App {
|
||||
return &App{
|
||||
websiteRepo: website,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/jails", s.List)
|
||||
r.Post("/jails", s.Create)
|
||||
r.Delete("/jails", s.Delete)
|
||||
r.Get("/jails/{name}", s.BanList)
|
||||
r.Post("/unban", s.Unban)
|
||||
r.Post("/whiteList", s.SetWhiteList)
|
||||
r.Get("/whiteList", s.GetWhiteList)
|
||||
}
|
||||
|
||||
// List 所有规则
|
||||
func (s *Service) List(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) List(w http.ResponseWriter, r *http.Request) {
|
||||
raw, err := io.Read("/etc/fail2ban/jail.local")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -75,7 +86,7 @@ func (s *Service) List(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Create 添加规则
|
||||
func (s *Service) Create(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Create(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Add](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -202,7 +213,7 @@ bantime = ` + jailBanTime + `
|
||||
}
|
||||
|
||||
// Delete 删除规则
|
||||
func (s *Service) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Delete](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -236,7 +247,7 @@ func (s *Service) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// BanList 获取封禁列表
|
||||
func (s *Service) BanList(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) BanList(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[BanList](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -281,7 +292,7 @@ func (s *Service) BanList(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Unban 解封
|
||||
func (s *Service) Unban(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Unban(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Unban](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -297,7 +308,7 @@ func (s *Service) Unban(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// SetWhiteList 设置白名单
|
||||
func (s *Service) SetWhiteList(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) SetWhiteList(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[SetWhiteList](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -331,7 +342,7 @@ func (s *Service) SetWhiteList(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// GetWhiteList 获取白名单
|
||||
func (s *Service) GetWhiteList(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetWhiteList(w http.ResponseWriter, r *http.Request) {
|
||||
raw, err := io.Read("/etc/fail2ban/jail.local")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,24 +0,0 @@
|
||||
package fail2ban
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "fail2ban",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/jails", service.List)
|
||||
r.Post("/jails", service.Create)
|
||||
r.Delete("/jails", service.Delete)
|
||||
r.Get("/jails/{name}", service.BanList)
|
||||
r.Post("/unban", service.Unban)
|
||||
r.Post("/whiteList", service.SetWhiteList)
|
||||
r.Get("/whiteList", service.GetWhiteList)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -4,19 +4,26 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/service"
|
||||
"github.com/TheTNB/panel/pkg/io"
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
type App struct{}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/config", s.GetConfig)
|
||||
r.Post("/config", s.UpdateConfig)
|
||||
}
|
||||
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Name](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -32,7 +39,7 @@ func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,19 +0,0 @@
|
||||
package frp
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "frp",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -4,24 +4,31 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/service"
|
||||
"github.com/TheTNB/panel/pkg/io"
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
type App struct{}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/config", s.GetConfig)
|
||||
r.Post("/config", s.UpdateConfig)
|
||||
}
|
||||
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, _ := io.Read(fmt.Sprintf("%s/server/gitea/app.ini", app.Root))
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,19 +0,0 @@
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "gitea",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package apps
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
_ "github.com/TheTNB/panel/internal/apps/benchmark"
|
||||
_ "github.com/TheTNB/panel/internal/apps/docker"
|
||||
_ "github.com/TheTNB/panel/internal/apps/fail2ban"
|
||||
_ "github.com/TheTNB/panel/internal/apps/frp"
|
||||
_ "github.com/TheTNB/panel/internal/apps/gitea"
|
||||
_ "github.com/TheTNB/panel/internal/apps/memcached"
|
||||
_ "github.com/TheTNB/panel/internal/apps/mysql"
|
||||
_ "github.com/TheTNB/panel/internal/apps/nginx"
|
||||
_ "github.com/TheTNB/panel/internal/apps/php"
|
||||
_ "github.com/TheTNB/panel/internal/apps/phpmyadmin"
|
||||
_ "github.com/TheTNB/panel/internal/apps/podman"
|
||||
_ "github.com/TheTNB/panel/internal/apps/postgresql"
|
||||
_ "github.com/TheTNB/panel/internal/apps/pureftpd"
|
||||
_ "github.com/TheTNB/panel/internal/apps/redis"
|
||||
_ "github.com/TheTNB/panel/internal/apps/rsync"
|
||||
_ "github.com/TheTNB/panel/internal/apps/s3fs"
|
||||
_ "github.com/TheTNB/panel/internal/apps/supervisor"
|
||||
_ "github.com/TheTNB/panel/internal/apps/toolbox"
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
)
|
||||
|
||||
func Boot(r chi.Router) {
|
||||
apploader.Boot(r)
|
||||
}
|
||||
@@ -6,19 +6,27 @@ import (
|
||||
"net/http"
|
||||
"regexp"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/internal/service"
|
||||
"github.com/TheTNB/panel/pkg/io"
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
type App struct{}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/load", s.Load)
|
||||
r.Get("/config", s.GetConfig)
|
||||
r.Post("/config", s.UpdateConfig)
|
||||
}
|
||||
|
||||
func (s *App) Load(w http.ResponseWriter, r *http.Request) {
|
||||
status, err := systemctl.Status("memcached")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "failed to get Memcached status: %v", err)
|
||||
@@ -66,7 +74,7 @@ func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, data)
|
||||
}
|
||||
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read("/etc/systemd/system/memcached.service")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -76,7 +84,7 @@ func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,20 +0,0 @@
|
||||
package memcached
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "memcached",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
@@ -19,18 +20,29 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
type App struct {
|
||||
settingRepo biz.SettingRepo
|
||||
}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{
|
||||
settingRepo: nil, // TODO fixme
|
||||
func NewApp(setting biz.SettingRepo) *App {
|
||||
return &App{
|
||||
settingRepo: setting,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/load", s.Load)
|
||||
r.Get("/config", s.GetConfig)
|
||||
r.Post("/config", s.UpdateConfig)
|
||||
r.Post("/clearErrorLog", s.ClearErrorLog)
|
||||
r.Get("/slowLog", s.SlowLog)
|
||||
r.Post("/clearSlowLog", s.ClearSlowLog)
|
||||
r.Get("/rootPassword", s.GetRootPassword)
|
||||
r.Post("/rootPassword", s.SetRootPassword)
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read(app.Root + "/server/mysql/conf/my.cnf")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "获取配置失败")
|
||||
@@ -41,7 +53,7 @@ func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UpdateConfig 保存配置
|
||||
func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -62,7 +74,7 @@ func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Load 获取负载
|
||||
func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Load(w http.ResponseWriter, r *http.Request) {
|
||||
rootPassword, err := s.settingRepo.Get(biz.SettingKeyMySQLRootPassword)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "获取root密码失败")
|
||||
@@ -142,7 +154,7 @@ func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// ClearErrorLog 清空错误日志
|
||||
func (s *Service) ClearErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ClearErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
if err := systemctl.LogsClear("mysqld"); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
@@ -152,12 +164,12 @@ func (s *Service) ClearErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// SlowLog 获取慢查询日志
|
||||
func (s *Service) SlowLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) SlowLog(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, fmt.Sprintf("%s/server/mysql/mysql-slow.log", app.Root))
|
||||
}
|
||||
|
||||
// ClearSlowLog 清空慢查询日志
|
||||
func (s *Service) ClearSlowLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ClearSlowLog(w http.ResponseWriter, r *http.Request) {
|
||||
if _, err := shell.Execf("echo '' > %s/server/mysql/mysql-slow.log", app.Root); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
@@ -167,7 +179,7 @@ func (s *Service) ClearSlowLog(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// GetRootPassword 获取root密码
|
||||
func (s *Service) GetRootPassword(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetRootPassword(w http.ResponseWriter, r *http.Request) {
|
||||
rootPassword, err := s.settingRepo.Get(biz.SettingKeyMySQLRootPassword)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "获取root密码失败")
|
||||
@@ -182,7 +194,7 @@ func (s *Service) GetRootPassword(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// SetRootPassword 设置root密码
|
||||
func (s *Service) SetRootPassword(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) SetRootPassword(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[SetRootPassword](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -212,7 +224,7 @@ func (s *Service) SetRootPassword(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) getSock() string {
|
||||
func (s *App) getSock() string {
|
||||
if io.Exists("/tmp/mysql.sock") {
|
||||
return "/tmp/mysql.sock"
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package mysql
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "mysql",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
r.Post("/clearErrorLog", service.ClearErrorLog)
|
||||
r.Get("/slowLog", service.SlowLog)
|
||||
r.Post("/clearSlowLog", service.ClearSlowLog)
|
||||
r.Get("/rootPassword", service.GetRootPassword)
|
||||
r.Post("/rootPassword", service.SetRootPassword)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
@@ -18,15 +19,23 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
type App struct {
|
||||
// Dependent services
|
||||
}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/load", s.Load)
|
||||
r.Get("/config", s.GetConfig)
|
||||
r.Post("/config", s.SaveConfig)
|
||||
r.Get("/errorLog", s.ErrorLog)
|
||||
r.Post("/clearErrorLog", s.ClearErrorLog)
|
||||
}
|
||||
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read(fmt.Sprintf("%s/server/nginx/conf/nginx.conf", app.Root))
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "获取配置失败")
|
||||
@@ -36,7 +45,7 @@ func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) SaveConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) SaveConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -57,11 +66,11 @@ func (s *Service) SaveConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) ErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, fmt.Sprintf("%s/%s", app.Root, "wwwlogs/nginx-error.log"))
|
||||
}
|
||||
|
||||
func (s *Service) ClearErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ClearErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
if _, err := shell.Execf("echo '' > %s/%s", app.Root, "wwwlogs/nginx-error.log"); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
@@ -70,7 +79,7 @@ func (s *Service) ClearErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Load(w http.ResponseWriter, r *http.Request) {
|
||||
client := resty.New().SetTimeout(10 * time.Second)
|
||||
resp, err := client.R().Get("http://127.0.0.1/nginx_status")
|
||||
if err != nil || !resp.IsSuccess() {
|
||||
@@ -1,22 +0,0 @@
|
||||
package nginx
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "nginx",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.SaveConfig)
|
||||
r.Get("/errorLog", service.ErrorLog)
|
||||
r.Post("/clearErrorLog", service.ClearErrorLog)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
@@ -19,19 +20,39 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
type App struct {
|
||||
version uint
|
||||
taskRepo biz.TaskRepo
|
||||
}
|
||||
|
||||
func NewService(version uint) *Service {
|
||||
return &Service{
|
||||
version: version,
|
||||
taskRepo: nil, // TODO fixme
|
||||
func NewApp(task biz.TaskRepo) *App {
|
||||
return &App{
|
||||
taskRepo: task,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) SetCli(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Route(version uint) func(r chi.Router) {
|
||||
return func(r chi.Router) {
|
||||
php := new(App)
|
||||
php.version = version
|
||||
php.taskRepo = s.taskRepo
|
||||
r.Post("/setCli", php.SetCli)
|
||||
r.Get("/config", php.GetConfig)
|
||||
r.Post("/config", php.UpdateConfig)
|
||||
r.Get("/fpmConfig", php.GetFPMConfig)
|
||||
r.Post("/fpmConfig", php.UpdateFPMConfig)
|
||||
r.Get("/load", php.Load)
|
||||
r.Get("/errorLog", php.ErrorLog)
|
||||
r.Get("/slowLog", php.SlowLog)
|
||||
r.Post("/clearErrorLog", php.ClearErrorLog)
|
||||
r.Post("/clearSlowLog", php.ClearSlowLog)
|
||||
r.Get("/extensions", php.ExtensionList)
|
||||
r.Post("/extensions", php.InstallExtension)
|
||||
r.Delete("/extensions", php.UninstallExtension)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *App) SetCli(w http.ResponseWriter, r *http.Request) {
|
||||
if _, err := shell.Execf("ln -sf %s/server/php/%d/bin/php /usr/bin/php", app.Root, s.version); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
@@ -40,7 +61,7 @@ func (s *Service) SetCli(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read(fmt.Sprintf("%s/server/php/%d/etc/php.ini", app.Root, s.version))
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -50,7 +71,7 @@ func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -65,7 +86,7 @@ func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) GetFPMConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetFPMConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read(fmt.Sprintf("%s/server/php/%d/etc/php-fpm.conf", app.Root, s.version))
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -75,7 +96,7 @@ func (s *Service) GetFPMConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateFPMConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateFPMConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -90,7 +111,7 @@ func (s *Service) UpdateFPMConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Load(w http.ResponseWriter, r *http.Request) {
|
||||
var raw map[string]any
|
||||
client := resty.New().SetTimeout(10 * time.Second)
|
||||
_, err := client.R().SetResult(&raw).Get(fmt.Sprintf("http://127.0.0.1/phpfpm_status/%d?json", s.version))
|
||||
@@ -116,15 +137,15 @@ func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, loads)
|
||||
}
|
||||
|
||||
func (s *Service) ErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, fmt.Sprintf("%s/server/php/%d/var/log/php-fpm.log", app.Root, s.version))
|
||||
}
|
||||
|
||||
func (s *Service) SlowLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) SlowLog(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, fmt.Sprintf("%s/server/php/%d/var/log/slow.log", app.Root, s.version))
|
||||
}
|
||||
|
||||
func (s *Service) ClearErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ClearErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
if _, err := shell.Execf("echo '' > %s/server/php/%d/var/log/php-fpm.log", app.Root, s.version); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
@@ -133,7 +154,7 @@ func (s *Service) ClearErrorLog(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) ClearSlowLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ClearSlowLog(w http.ResponseWriter, r *http.Request) {
|
||||
if _, err := shell.Execf("echo '' > %s/server/php/%d/var/log/slow.log", app.Root, s.version); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
@@ -142,7 +163,7 @@ func (s *Service) ClearSlowLog(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) ExtensionList(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ExtensionList(w http.ResponseWriter, r *http.Request) {
|
||||
extensions := s.getExtensions()
|
||||
raw, err := shell.Execf("%s/server/php/%d/bin/php -m", app.Root, s.version)
|
||||
if err != nil {
|
||||
@@ -165,7 +186,7 @@ func (s *Service) ExtensionList(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, extensions)
|
||||
}
|
||||
|
||||
func (s *Service) InstallExtension(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) InstallExtension(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[ExtensionSlug](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -196,7 +217,7 @@ func (s *Service) InstallExtension(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) UninstallExtension(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UninstallExtension(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[ExtensionSlug](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -227,7 +248,7 @@ func (s *Service) UninstallExtension(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) getExtensions() []Extension {
|
||||
func (s *App) getExtensions() []Extension {
|
||||
extensions := []Extension{
|
||||
{
|
||||
Name: "fileinfo",
|
||||
@@ -395,7 +416,7 @@ func (s *Service) getExtensions() []Extension {
|
||||
return extensions
|
||||
}
|
||||
|
||||
func (s *Service) checkExtension(slug string) bool {
|
||||
func (s *App) checkExtension(slug string) bool {
|
||||
extensions := s.getExtensions()
|
||||
|
||||
for _, item := range extensions {
|
||||
@@ -1,35 +0,0 @@
|
||||
package php
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
php := []uint{74, 80, 81, 82, 83, 84}
|
||||
for _, version := range php {
|
||||
apploader.Register(&types.App{
|
||||
Slug: fmt.Sprintf("php%d", version),
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService(version)
|
||||
r.Post("/setCli", service.SetCli)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
r.Get("/fpmConfig", service.GetFPMConfig)
|
||||
r.Post("/fpmConfig", service.UpdateFPMConfig)
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/errorLog", service.ErrorLog)
|
||||
r.Get("/slowLog", service.SlowLog)
|
||||
r.Post("/clearErrorLog", service.ClearErrorLog)
|
||||
r.Post("/clearSlowLog", service.ClearSlowLog)
|
||||
r.Get("/extensions", service.ExtensionList)
|
||||
r.Post("/extensions", service.InstallExtension)
|
||||
r.Delete("/extensions", service.UninstallExtension)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-rat/chix"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
@@ -17,13 +18,20 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
type App struct{}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *Service) Info(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/info", s.Info)
|
||||
r.Post("/port", s.UpdatePort)
|
||||
r.Get("/config", s.GetConfig)
|
||||
r.Post("/config", s.UpdateConfig)
|
||||
}
|
||||
|
||||
func (s *App) Info(w http.ResponseWriter, r *http.Request) {
|
||||
files, err := io.ReadDir(fmt.Sprintf("%s/server/phpmyadmin", app.Root))
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "找不到 phpMyAdmin 目录")
|
||||
@@ -58,7 +66,7 @@ func (s *Service) Info(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) UpdatePort(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdatePort(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdatePort](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -98,7 +106,7 @@ func (s *Service) UpdatePort(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read(fmt.Sprintf("%s/server/vhost/phpmyadmin.conf", app.Root))
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -108,7 +116,7 @@ func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,21 +0,0 @@
|
||||
package phpmyadmin
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "phpmyadmin",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/info", service.Info)
|
||||
r.Post("/port", service.UpdatePort)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -3,18 +3,27 @@ package podman
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/internal/service"
|
||||
"github.com/TheTNB/panel/pkg/io"
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
type App struct{}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *Service) GetRegistryConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/registryConfig", s.GetRegistryConfig)
|
||||
r.Post("/registryConfig", s.UpdateRegistryConfig)
|
||||
r.Get("/storageConfig", s.GetStorageConfig)
|
||||
r.Post("/storageConfig", s.UpdateStorageConfig)
|
||||
}
|
||||
|
||||
func (s *App) GetRegistryConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read("/etc/containers/registries.conf")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -24,7 +33,7 @@ func (s *Service) GetRegistryConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateRegistryConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateRegistryConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -44,7 +53,7 @@ func (s *Service) UpdateRegistryConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) GetStorageConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetStorageConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read("/etc/containers/storage.conf")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -54,7 +63,7 @@ func (s *Service) GetStorageConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateStorageConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateStorageConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,21 +0,0 @@
|
||||
package podman
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "podman",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/registryConfig", service.GetRegistryConfig)
|
||||
r.Post("/registryConfig", service.UpdateRegistryConfig)
|
||||
r.Get("/storageConfig", service.GetStorageConfig)
|
||||
r.Post("/storageConfig", service.UpdateStorageConfig)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/service"
|
||||
"github.com/TheTNB/panel/pkg/io"
|
||||
@@ -13,14 +15,24 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
type App struct{}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/config", s.GetConfig)
|
||||
r.Post("/config", s.UpdateConfig)
|
||||
r.Get("/userConfig", s.GetUserConfig)
|
||||
r.Post("/userConfig", s.UpdateUserConfig)
|
||||
r.Get("/load", s.Load)
|
||||
r.Get("/log", s.Log)
|
||||
r.Post("/clearLog", s.ClearLog)
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
// 获取配置
|
||||
config, err := io.Read(fmt.Sprintf("%s/server/postgresql/data/postgresql.conf", app.Root))
|
||||
if err != nil {
|
||||
@@ -32,7 +44,7 @@ func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UpdateConfig 保存配置
|
||||
func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -53,7 +65,7 @@ func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// GetUserConfig 获取用户配置
|
||||
func (s *Service) GetUserConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetUserConfig(w http.ResponseWriter, r *http.Request) {
|
||||
// 获取配置
|
||||
config, err := io.Read(fmt.Sprintf("%s/server/postgresql/data/pg_hba.conf", app.Root))
|
||||
if err != nil {
|
||||
@@ -65,7 +77,7 @@ func (s *Service) GetUserConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UpdateUserConfig 保存用户配置
|
||||
func (s *Service) UpdateUserConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateUserConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -86,7 +98,7 @@ func (s *Service) UpdateUserConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Load 获取负载
|
||||
func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Load(w http.ResponseWriter, r *http.Request) {
|
||||
status, _ := systemctl.Status("postgresql")
|
||||
if !status {
|
||||
service.Success(w, []types.NV{})
|
||||
@@ -131,12 +143,12 @@ func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Log 获取日志
|
||||
func (s *Service) Log(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Log(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, fmt.Sprintf("%s/server/postgresql/logs/postgresql-%s.log", app.Root, time.Now().Format(time.DateOnly)))
|
||||
}
|
||||
|
||||
// ClearLog 清空日志
|
||||
func (s *Service) ClearLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ClearLog(w http.ResponseWriter, r *http.Request) {
|
||||
if _, err := shell.Execf("rm -rf %s/server/postgresql/logs/postgresql-*.log", app.Root); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
@@ -1,24 +0,0 @@
|
||||
package postgresql
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "postgresql",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
r.Get("/userConfig", service.GetUserConfig)
|
||||
r.Post("/userConfig", service.UpdateUserConfig)
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/log", service.Log)
|
||||
r.Post("/clearLog", service.ClearLog)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-rat/chix"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
@@ -16,14 +17,23 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
type App struct{}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/users", s.List)
|
||||
r.Post("/users", s.Create)
|
||||
r.Delete("/users/{username}", s.Delete)
|
||||
r.Post("/users/{username}/password", s.ChangePassword)
|
||||
r.Get("/port", s.GetPort)
|
||||
r.Post("/port", s.UpdatePort)
|
||||
}
|
||||
|
||||
// List 获取用户列表
|
||||
func (s *Service) List(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) List(w http.ResponseWriter, r *http.Request) {
|
||||
listRaw, err := shell.Execf("pure-pw list")
|
||||
if err != nil {
|
||||
service.Success(w, chix.M{
|
||||
@@ -55,7 +65,7 @@ func (s *Service) List(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Create 创建用户
|
||||
func (s *Service) Create(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Create(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Create](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -91,7 +101,7 @@ func (s *Service) Create(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Delete 删除用户
|
||||
func (s *Service) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Delete](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -111,7 +121,7 @@ func (s *Service) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// ChangePassword 修改密码
|
||||
func (s *Service) ChangePassword(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ChangePassword(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[ChangePassword](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -131,7 +141,7 @@ func (s *Service) ChangePassword(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// GetPort 获取端口
|
||||
func (s *Service) GetPort(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetPort(w http.ResponseWriter, r *http.Request) {
|
||||
port, err := shell.Execf(`cat %s/server/pure-ftpd/etc/pure-ftpd.conf | grep "Bind" | awk '{print $2}' | awk -F "," '{print $2}'`, app.Root)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "获取PureFtpd端口失败")
|
||||
@@ -142,7 +152,7 @@ func (s *Service) GetPort(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UpdatePort 设置端口
|
||||
func (s *Service) UpdatePort(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdatePort(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdatePort](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,23 +0,0 @@
|
||||
package pureftpd
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "pureftpd",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/users", service.List)
|
||||
r.Post("/users", service.Create)
|
||||
r.Delete("/users/{username}", service.Delete)
|
||||
r.Post("/users/{username}/password", service.ChangePassword)
|
||||
r.Get("/port", service.GetPort)
|
||||
r.Post("/port", service.UpdatePort)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/service"
|
||||
"github.com/TheTNB/panel/pkg/io"
|
||||
@@ -13,13 +15,19 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
type App struct{}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/load", s.Load)
|
||||
r.Get("/config", s.GetConfig)
|
||||
r.Post("/config", s.UpdateConfig)
|
||||
}
|
||||
|
||||
func (s *App) Load(w http.ResponseWriter, r *http.Request) {
|
||||
status, err := systemctl.Status("redis")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "获取 Redis 状态失败")
|
||||
@@ -65,7 +73,7 @@ func (s *Service) Load(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, data)
|
||||
}
|
||||
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read(fmt.Sprintf("%s/server/redis/redis.conf", app.Root))
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -75,7 +83,7 @@ func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,20 +0,0 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "redis",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-rat/chix"
|
||||
"github.com/go-rat/utils/str"
|
||||
|
||||
@@ -15,13 +16,22 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
type App struct{}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *Service) List(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/modules", s.List)
|
||||
r.Post("/modules", s.Create)
|
||||
r.Post("/modules/{name}", s.Update)
|
||||
r.Delete("/modules/{name}", s.Delete)
|
||||
r.Get("/config", s.GetConfig)
|
||||
r.Post("/config", s.UpdateConfig)
|
||||
}
|
||||
|
||||
func (s *App) List(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read("/etc/rsyncd.conf")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -86,7 +96,7 @@ func (s *Service) List(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) Create(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Create(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Create](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -131,7 +141,7 @@ secrets file = /etc/rsyncd.secrets
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Delete](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -173,7 +183,7 @@ func (s *Service) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) Update(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Update(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Update](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -229,7 +239,7 @@ secrets file = /etc/rsyncd.secrets
|
||||
service.Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := io.Read("/etc/rsyncd.conf")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -239,7 +249,7 @@ func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, config)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,23 +0,0 @@
|
||||
package rsync
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "rsync",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/modules", service.List)
|
||||
r.Post("/modules", service.Create)
|
||||
r.Post("/modules/{name}", service.Update)
|
||||
r.Delete("/modules/{name}", service.Delete)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-rat/chix"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
@@ -15,18 +16,24 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/shell"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
type App struct {
|
||||
settingRepo biz.SettingRepo
|
||||
}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{
|
||||
settingRepo: nil, // TODO fixme
|
||||
func NewApp(setting biz.SettingRepo) *App {
|
||||
return &App{
|
||||
settingRepo: setting,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/mounts", s.List)
|
||||
r.Post("/mounts", s.Create)
|
||||
r.Delete("/mounts", s.Delete)
|
||||
}
|
||||
|
||||
// List 所有 S3fs 挂载
|
||||
func (s *Service) List(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) List(w http.ResponseWriter, r *http.Request) {
|
||||
var s3fsList []Mount
|
||||
list, err := s.settingRepo.Get("s3fs", "[]")
|
||||
if err != nil {
|
||||
@@ -48,7 +55,7 @@ func (s *Service) List(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Create 添加 S3fs 挂载
|
||||
func (s *Service) Create(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Create(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Create](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -133,7 +140,7 @@ func (s *Service) Create(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Delete 删除 S3fs 挂载
|
||||
func (s *Service) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Delete](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,20 +0,0 @@
|
||||
package s3fs
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "s3fs",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/mounts", service.List)
|
||||
r.Post("/mounts", service.Create)
|
||||
r.Delete("/mounts", service.Delete)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-rat/chix"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
@@ -14,11 +15,11 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/systemctl"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
type App struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func NewService() *Service {
|
||||
func NewApp() *App {
|
||||
var name string
|
||||
if os.IsRHEL() {
|
||||
name = "supervisord"
|
||||
@@ -26,18 +27,35 @@ func NewService() *Service {
|
||||
name = "supervisor"
|
||||
}
|
||||
|
||||
return &Service{
|
||||
return &App{
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/service", s.Service)
|
||||
r.Post("/clearLog", s.ClearLog)
|
||||
r.Get("/config", s.GetConfig)
|
||||
r.Post("/config", s.UpdateConfig)
|
||||
r.Get("/processes", s.Processes)
|
||||
r.Post("/processes/{process}/start", s.StartProcess)
|
||||
r.Post("/processes/{process}/stop", s.StopProcess)
|
||||
r.Post("/processes/{process}/restart", s.RestartProcess)
|
||||
r.Get("/processes/{process}/log", s.ProcessLog)
|
||||
r.Post("/processes/{process}/clearLog", s.ClearProcessLog)
|
||||
r.Get("/processes/{process}", s.ProcessConfig)
|
||||
r.Post("/processes/{process}", s.UpdateProcessConfig)
|
||||
r.Delete("/processes/{process}", s.DeleteProcess)
|
||||
r.Post("/processes", s.CreateProcess)
|
||||
}
|
||||
|
||||
// Service 获取服务名称
|
||||
func (s *Service) Service(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Service(w http.ResponseWriter, r *http.Request) {
|
||||
service.Success(w, s.name)
|
||||
}
|
||||
|
||||
// ClearLog 清空日志
|
||||
func (s *Service) ClearLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ClearLog(w http.ResponseWriter, r *http.Request) {
|
||||
if _, err := shell.Execf(`echo "" > /var/log/supervisor/supervisord.log`); err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
@@ -47,7 +65,7 @@ func (s *Service) ClearLog(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// GetConfig 获取配置
|
||||
func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
var config string
|
||||
var err error
|
||||
if os.IsRHEL() {
|
||||
@@ -65,7 +83,7 @@ func (s *Service) GetConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UpdateConfig 保存配置
|
||||
func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -92,7 +110,7 @@ func (s *Service) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Processes 进程列表
|
||||
func (s *Service) Processes(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) Processes(w http.ResponseWriter, r *http.Request) {
|
||||
out, err := shell.Execf(`supervisorctl status | awk '{print $1}'`)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -131,7 +149,7 @@ func (s *Service) Processes(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// StartProcess 启动进程
|
||||
func (s *Service) StartProcess(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) StartProcess(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[ProcessName](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -147,7 +165,7 @@ func (s *Service) StartProcess(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// StopProcess 停止进程
|
||||
func (s *Service) StopProcess(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) StopProcess(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[ProcessName](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -163,7 +181,7 @@ func (s *Service) StopProcess(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// RestartProcess 重启进程
|
||||
func (s *Service) RestartProcess(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) RestartProcess(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[ProcessName](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -179,7 +197,7 @@ func (s *Service) RestartProcess(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// ProcessLog 进程日志
|
||||
func (s *Service) ProcessLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ProcessLog(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[ProcessName](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -202,7 +220,7 @@ func (s *Service) ProcessLog(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// ClearProcessLog 清空进程日志
|
||||
func (s *Service) ClearProcessLog(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ClearProcessLog(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[ProcessName](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -230,7 +248,7 @@ func (s *Service) ClearProcessLog(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// ProcessConfig 获取进程配置
|
||||
func (s *Service) ProcessConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) ProcessConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[ProcessName](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -253,7 +271,7 @@ func (s *Service) ProcessConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UpdateProcessConfig 保存进程配置
|
||||
func (s *Service) UpdateProcessConfig(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateProcessConfig(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[UpdateProcessConfig](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -279,7 +297,7 @@ func (s *Service) UpdateProcessConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// CreateProcess 添加进程
|
||||
func (s *Service) CreateProcess(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) CreateProcess(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[CreateProcess](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -318,7 +336,7 @@ stdout_logfile_maxbytes=2MB
|
||||
}
|
||||
|
||||
// DeleteProcess 删除进程
|
||||
func (s *Service) DeleteProcess(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) DeleteProcess(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[ProcessName](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,31 +0,0 @@
|
||||
package supervisor
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "supervisor",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/service", service.Service)
|
||||
r.Post("/clearLog", service.ClearLog)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
r.Get("/processes", service.Processes)
|
||||
r.Post("/processes/{process}/start", service.StartProcess)
|
||||
r.Post("/processes/{process}/stop", service.StopProcess)
|
||||
r.Post("/processes/{process}/restart", service.RestartProcess)
|
||||
r.Get("/processes/{process}/log", service.ProcessLog)
|
||||
r.Post("/processes/{process}/clearLog", service.ClearProcessLog)
|
||||
r.Get("/processes/{process}", service.ProcessConfig)
|
||||
r.Post("/processes/{process}", service.UpdateProcessConfig)
|
||||
r.Delete("/processes/{process}", service.DeleteProcess)
|
||||
r.Post("/processes", service.CreateProcess)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-rat/chix"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
@@ -18,14 +19,30 @@ import (
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
type Service struct{}
|
||||
type App struct{}
|
||||
|
||||
func NewService() *Service {
|
||||
return &Service{}
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
}
|
||||
|
||||
func (s *App) Route(r chi.Router) {
|
||||
r.Get("/dns", s.GetDNS)
|
||||
r.Post("/dns", s.UpdateDNS)
|
||||
r.Get("/swap", s.GetSWAP)
|
||||
r.Post("/swap", s.UpdateSWAP)
|
||||
r.Get("/timezone", s.GetTimezone)
|
||||
r.Post("/timezone", s.UpdateTimezone)
|
||||
r.Post("/time", s.UpdateTime)
|
||||
r.Post("/syncTime", s.SyncTime)
|
||||
r.Get("/hostname", s.GetHostname)
|
||||
r.Post("/hostname", s.UpdateHostname)
|
||||
r.Get("/hosts", s.GetHosts)
|
||||
r.Post("/hosts", s.UpdateHosts)
|
||||
r.Post("/rootPassword", s.UpdateRootPassword)
|
||||
}
|
||||
|
||||
// GetDNS 获取 DNS 信息
|
||||
func (s *Service) GetDNS(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetDNS(w http.ResponseWriter, r *http.Request) {
|
||||
raw, err := io.Read("/etc/resolv.conf")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -46,7 +63,7 @@ func (s *Service) GetDNS(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UpdateDNS 设置 DNS 信息
|
||||
func (s *Service) UpdateDNS(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateDNS(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[DNS](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -66,7 +83,7 @@ func (s *Service) UpdateDNS(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// GetSWAP 获取 SWAP 信息
|
||||
func (s *Service) GetSWAP(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetSWAP(w http.ResponseWriter, r *http.Request) {
|
||||
var total, used, free string
|
||||
var size int64
|
||||
if io.Exists(filepath.Join(app.Root, "swap")) {
|
||||
@@ -104,7 +121,7 @@ func (s *Service) GetSWAP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UpdateSWAP 设置 SWAP 信息
|
||||
func (s *Service) UpdateSWAP(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateSWAP(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[SWAP](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -172,7 +189,7 @@ func (s *Service) UpdateSWAP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// GetTimezone 获取时区
|
||||
func (s *Service) GetTimezone(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetTimezone(w http.ResponseWriter, r *http.Request) {
|
||||
raw, err := shell.Execf("timedatectl | grep zone")
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "获取时区信息失败")
|
||||
@@ -207,7 +224,7 @@ func (s *Service) GetTimezone(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UpdateTimezone 设置时区
|
||||
func (s *Service) UpdateTimezone(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateTimezone(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Timezone](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -223,7 +240,7 @@ func (s *Service) UpdateTimezone(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UpdateTime 设置时间
|
||||
func (s *Service) UpdateTime(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateTime(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Time](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -240,7 +257,7 @@ func (s *Service) UpdateTime(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// SyncTime 同步时间
|
||||
func (s *Service) SyncTime(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) SyncTime(w http.ResponseWriter, r *http.Request) {
|
||||
now, err := ntp.Now()
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -256,13 +273,13 @@ func (s *Service) SyncTime(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// GetHostname 获取主机名
|
||||
func (s *Service) GetHostname(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetHostname(w http.ResponseWriter, r *http.Request) {
|
||||
hostname, _ := io.Read("/etc/hostname")
|
||||
service.Success(w, strings.TrimSpace(hostname))
|
||||
}
|
||||
|
||||
// UpdateHostname 设置主机名
|
||||
func (s *Service) UpdateHostname(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateHostname(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Hostname](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -281,13 +298,13 @@ func (s *Service) UpdateHostname(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// GetHosts 获取 hosts 信息
|
||||
func (s *Service) GetHosts(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) GetHosts(w http.ResponseWriter, r *http.Request) {
|
||||
hosts, _ := io.Read("/etc/hosts")
|
||||
service.Success(w, hosts)
|
||||
}
|
||||
|
||||
// UpdateHosts 设置 hosts 信息
|
||||
func (s *Service) UpdateHosts(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateHosts(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Hosts](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -303,7 +320,7 @@ func (s *Service) UpdateHosts(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UpdateRootPassword 设置 root 密码
|
||||
func (s *Service) UpdateRootPassword(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *App) UpdateRootPassword(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := service.Bind[Password](r)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -1,30 +0,0 @@
|
||||
package toolbox
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "toolbox",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService()
|
||||
r.Get("/dns", service.GetDNS)
|
||||
r.Post("/dns", service.UpdateDNS)
|
||||
r.Get("/swap", service.GetSWAP)
|
||||
r.Post("/swap", service.UpdateSWAP)
|
||||
r.Get("/timezone", service.GetTimezone)
|
||||
r.Post("/timezone", service.UpdateTimezone)
|
||||
r.Post("/time", service.UpdateTime)
|
||||
r.Post("/syncTime", service.SyncTime)
|
||||
r.Get("/hostname", service.GetHostname)
|
||||
r.Post("/hostname", service.UpdateHostname)
|
||||
r.Get("/hosts", service.GetHosts)
|
||||
r.Post("/hosts", service.UpdateHosts)
|
||||
r.Post("/rootPassword", service.UpdateRootPassword)
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -28,5 +28,4 @@ type TaskRepo interface {
|
||||
Delete(id uint) error
|
||||
UpdateStatus(id uint, status TaskStatus) error
|
||||
Push(task *Task) error
|
||||
DispatchWaiting()
|
||||
}
|
||||
|
||||
@@ -2,20 +2,18 @@ package bootstrap
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log/slog"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/bddjr/hlfhr"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-rat/sessions"
|
||||
"github.com/knadh/koanf/v2"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/TheTNB/panel/internal/http/middleware"
|
||||
"github.com/TheTNB/panel/internal/route"
|
||||
)
|
||||
|
||||
func NewRouter(conf *koanf.Koanf, db *gorm.DB, log *slog.Logger, session *sessions.Manager, middlewares *middleware.Middlewares, http *route.Http, ws *route.Ws) (*chi.Mux, error) {
|
||||
func NewRouter(middlewares *middleware.Middlewares, http *route.Http, ws *route.Ws) (*chi.Mux, error) {
|
||||
r := chi.NewRouter()
|
||||
|
||||
// add middleware
|
||||
@@ -30,7 +28,7 @@ func NewRouter(conf *koanf.Koanf, db *gorm.DB, log *slog.Logger, session *sessio
|
||||
|
||||
func NewHttp(conf *koanf.Koanf, r *chi.Mux) (*hlfhr.Server, error) {
|
||||
srv := hlfhr.New(&http.Server{
|
||||
Addr: conf.MustString("http.address"),
|
||||
Addr: fmt.Sprintf(":%d", conf.MustInt("http.port")),
|
||||
Handler: http.AllowQuerySemicolons(r),
|
||||
MaxHeaderBytes: 2048 << 20,
|
||||
})
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/apps"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/pkg/api"
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
)
|
||||
|
||||
type cacheRepo struct {
|
||||
@@ -58,8 +58,7 @@ func (r *cacheRepo) UpdateApps() error {
|
||||
|
||||
// 去除本地不存在的应用
|
||||
*remote = slices.Clip(slices.DeleteFunc(*remote, func(app *api.App) bool {
|
||||
_, err = apploader.Get(app.Slug)
|
||||
return err != nil
|
||||
return !slices.Contains(apps.Slugs(), app.Slug)
|
||||
}))
|
||||
|
||||
encoded, err := json.Marshal(remote)
|
||||
|
||||
@@ -5,24 +5,30 @@ import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
"github.com/TheTNB/panel/pkg/db"
|
||||
)
|
||||
|
||||
type databaseRepo struct {
|
||||
db *gorm.DB
|
||||
server biz.DatabaseServerRepo
|
||||
user biz.DatabaseUserRepo
|
||||
}
|
||||
|
||||
func NewDatabaseRepo(server biz.DatabaseServerRepo, user biz.DatabaseUserRepo) biz.DatabaseRepo {
|
||||
return &databaseRepo{server: server, user: user}
|
||||
func NewDatabaseRepo(db *gorm.DB, server biz.DatabaseServerRepo, user biz.DatabaseUserRepo) biz.DatabaseRepo {
|
||||
return &databaseRepo{
|
||||
db: db,
|
||||
server: server,
|
||||
user: user,
|
||||
}
|
||||
}
|
||||
|
||||
func (r databaseRepo) List(page, limit uint) ([]*biz.Database, int64, error) {
|
||||
var databaseServer []*biz.DatabaseServer
|
||||
if err := app.Orm.Model(&biz.DatabaseServer{}).Order("id desc").Find(&databaseServer).Error; err != nil {
|
||||
if err := r.db.Model(&biz.DatabaseServer{}).Order("id desc").Find(&databaseServer).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
"github.com/TheTNB/panel/pkg/db"
|
||||
@@ -120,7 +119,7 @@ func (r databaseServerRepo) Delete(id uint) error {
|
||||
|
||||
// ClearUsers 删除指定服务器的所有用户,只是删除面板记录,不会实际删除
|
||||
func (r databaseServerRepo) ClearUsers(serverID uint) error {
|
||||
return app.Orm.Where("server_id = ?", serverID).Delete(&biz.DatabaseUser{}).Error
|
||||
return r.db.Where("server_id = ?", serverID).Delete(&biz.DatabaseUser{}).Error
|
||||
}
|
||||
|
||||
func (r databaseServerRepo) Sync(id uint) error {
|
||||
|
||||
@@ -4,23 +4,28 @@ import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
"github.com/TheTNB/panel/pkg/db"
|
||||
)
|
||||
|
||||
type databaseUserRepo struct {
|
||||
db *gorm.DB
|
||||
server biz.DatabaseServerRepo
|
||||
}
|
||||
|
||||
func NewDatabaseUserRepo(server biz.DatabaseServerRepo) biz.DatabaseUserRepo {
|
||||
return &databaseUserRepo{server: server}
|
||||
func NewDatabaseUserRepo(db *gorm.DB, server biz.DatabaseServerRepo) biz.DatabaseUserRepo {
|
||||
return &databaseUserRepo{
|
||||
db: db,
|
||||
server: server,
|
||||
}
|
||||
}
|
||||
|
||||
func (r databaseUserRepo) Count() (int64, error) {
|
||||
var count int64
|
||||
if err := app.Orm.Model(&biz.DatabaseUser{}).Count(&count).Error; err != nil {
|
||||
if err := r.db.Model(&biz.DatabaseUser{}).Count(&count).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -30,7 +35,7 @@ func (r databaseUserRepo) Count() (int64, error) {
|
||||
func (r databaseUserRepo) List(page, limit uint) ([]*biz.DatabaseUser, int64, error) {
|
||||
var user []*biz.DatabaseUser
|
||||
var total int64
|
||||
err := app.Orm.Model(&biz.DatabaseUser{}).Preload("Server").Order("id desc").Count(&total).Offset(int((page - 1) * limit)).Limit(int(limit)).Find(&user).Error
|
||||
err := r.db.Model(&biz.DatabaseUser{}).Preload("Server").Order("id desc").Count(&total).Offset(int((page - 1) * limit)).Limit(int(limit)).Find(&user).Error
|
||||
|
||||
for u := range slices.Values(user) {
|
||||
r.fillUser(u)
|
||||
@@ -41,7 +46,7 @@ func (r databaseUserRepo) List(page, limit uint) ([]*biz.DatabaseUser, int64, er
|
||||
|
||||
func (r databaseUserRepo) Get(id uint) (*biz.DatabaseUser, error) {
|
||||
user := new(biz.DatabaseUser)
|
||||
if err := app.Orm.Preload("Server").Where("id = ?", id).First(user).Error; err != nil {
|
||||
if err := r.db.Preload("Server").Where("id = ?", id).First(user).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -97,14 +102,14 @@ func (r databaseUserRepo) Create(req *request.DatabaseUserCreate) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err = app.Orm.FirstOrInit(user, user).Error; err != nil {
|
||||
if err = r.db.FirstOrInit(user, user).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
user.Password = req.Password
|
||||
user.Remark = req.Remark
|
||||
|
||||
return app.Orm.Save(user).Error
|
||||
return r.db.Save(user).Error
|
||||
}
|
||||
|
||||
func (r databaseUserRepo) Update(req *request.DatabaseUserUpdate) error {
|
||||
@@ -156,7 +161,7 @@ func (r databaseUserRepo) Update(req *request.DatabaseUserUpdate) error {
|
||||
user.Password = req.Password
|
||||
user.Remark = req.Remark
|
||||
|
||||
return app.Orm.Save(user).Error
|
||||
return r.db.Save(user).Error
|
||||
}
|
||||
|
||||
func (r databaseUserRepo) UpdateRemark(req *request.DatabaseUserUpdateRemark) error {
|
||||
@@ -167,7 +172,7 @@ func (r databaseUserRepo) UpdateRemark(req *request.DatabaseUserUpdateRemark) er
|
||||
|
||||
user.Remark = req.Remark
|
||||
|
||||
return app.Orm.Save(user).Error
|
||||
return r.db.Save(user).Error
|
||||
}
|
||||
|
||||
func (r databaseUserRepo) Delete(id uint) error {
|
||||
@@ -198,7 +203,7 @@ func (r databaseUserRepo) Delete(id uint) error {
|
||||
_ = postgres.UserDrop(user.Username)
|
||||
}
|
||||
|
||||
return app.Orm.Where("id = ?", id).Delete(&biz.DatabaseUser{}).Error
|
||||
return r.db.Where("id = ?", id).Delete(&biz.DatabaseUser{}).Error
|
||||
}
|
||||
|
||||
func (r databaseUserRepo) DeleteByNames(serverID uint, names []string) error {
|
||||
@@ -215,7 +220,7 @@ func (r databaseUserRepo) DeleteByNames(serverID uint, names []string) error {
|
||||
}
|
||||
defer mysql.Close()
|
||||
users := make([]*biz.DatabaseUser, 0)
|
||||
if err = app.Orm.Where("server_id = ? AND username IN ?", serverID, names).Find(&users).Error; err != nil {
|
||||
if err = r.db.Where("server_id = ? AND username IN ?", serverID, names).Find(&users).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
for name := range slices.Values(names) {
|
||||
@@ -239,7 +244,7 @@ func (r databaseUserRepo) DeleteByNames(serverID uint, names []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
return app.Orm.Where("server_id = ? AND username IN ?", serverID, names).Delete(&biz.DatabaseUser{}).Error
|
||||
return r.db.Where("server_id = ? AND username IN ?", serverID, names).Delete(&biz.DatabaseUser{}).Error
|
||||
}
|
||||
|
||||
func (r databaseUserRepo) fillUser(user *biz.DatabaseUser) {
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/spf13/cast"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/http/request"
|
||||
)
|
||||
@@ -53,12 +52,12 @@ func (r monitorRepo) UpdateSetting(setting *request.MonitorSetting) error {
|
||||
}
|
||||
|
||||
func (r monitorRepo) Clear() error {
|
||||
return app.Orm.Where("1 = 1").Delete(&biz.Monitor{}).Error
|
||||
return r.db.Where("1 = 1").Delete(&biz.Monitor{}).Error
|
||||
}
|
||||
|
||||
func (r monitorRepo) List(start, end time.Time) ([]*biz.Monitor, error) {
|
||||
var monitors []*biz.Monitor
|
||||
if err := app.Orm.Where("created_at BETWEEN ? AND ?", start, end).Find(&monitors).Error; err != nil {
|
||||
if err := r.db.Where("created_at BETWEEN ? AND ?", start, end).Find(&monitors).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/internal/queuejob"
|
||||
"github.com/TheTNB/panel/pkg/queue"
|
||||
@@ -70,31 +69,3 @@ func (r *taskRepo) Push(task *biz.Task) error {
|
||||
task.ID,
|
||||
})
|
||||
}
|
||||
|
||||
// TODO 修复此功能
|
||||
func (r *taskRepo) DispatchWaiting() {
|
||||
// cli下不处理
|
||||
if app.IsCli {
|
||||
return
|
||||
}
|
||||
|
||||
if err := r.db.Model(&biz.Task{}).Where("status = ?", biz.TaskStatusRunning).Update("status", biz.TaskStatusFailed).Error; err != nil {
|
||||
r.log.Warn("failed to mark running tasks as failed", slog.Any("err", err))
|
||||
return
|
||||
}
|
||||
|
||||
var tasks []biz.Task
|
||||
if err := r.db.Where("status = ?", biz.TaskStatusWaiting).Find(&tasks).Error; err != nil {
|
||||
r.log.Warn("failed to get pending tasks", slog.Any("err", err))
|
||||
return
|
||||
}
|
||||
|
||||
for _, task := range tasks {
|
||||
if err := r.queue.Push(queuejob.NewProcessTask(r.log, r), []any{
|
||||
task.ID,
|
||||
}); err != nil {
|
||||
r.log.Warn("failed to push task", slog.Any("err", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,6 @@ func (r *Monitoring) Run() {
|
||||
return
|
||||
}
|
||||
|
||||
// 将等待中的任务分发
|
||||
//task := data.NewTaskRepo()
|
||||
//_ = task.DispatchWaiting()
|
||||
|
||||
monitor, err := r.settingRepo.Get(biz.SettingKeyMonitor)
|
||||
if err != nil || !cast.ToBool(monitor) {
|
||||
return
|
||||
|
||||
@@ -40,6 +40,7 @@ type Http struct {
|
||||
monitor *service.MonitorService
|
||||
setting *service.SettingService
|
||||
systemctl *service.SystemctlService
|
||||
apps *apps.Loader
|
||||
}
|
||||
|
||||
func NewHttp(
|
||||
@@ -68,6 +69,7 @@ func NewHttp(
|
||||
monitor *service.MonitorService,
|
||||
setting *service.SettingService,
|
||||
systemctl *service.SystemctlService,
|
||||
apps *apps.Loader,
|
||||
) *Http {
|
||||
return &Http{
|
||||
user: user,
|
||||
@@ -95,6 +97,7 @@ func NewHttp(
|
||||
monitor: monitor,
|
||||
setting: setting,
|
||||
systemctl: systemctl,
|
||||
apps: apps,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,7 +347,7 @@ func (route *Http) Register(r *chi.Mux) {
|
||||
})
|
||||
|
||||
r.Route("/apps", func(r chi.Router) {
|
||||
apps.Boot(r)
|
||||
route.apps.Register(r)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ type CliService struct {
|
||||
hr string
|
||||
api *api.API
|
||||
conf *koanf.Koanf
|
||||
db *gorm.DB
|
||||
appRepo biz.AppRepo
|
||||
cacheRepo biz.CacheRepo
|
||||
userRepo biz.UserRepo
|
||||
@@ -44,11 +45,12 @@ type CliService struct {
|
||||
hash hash.Hasher
|
||||
}
|
||||
|
||||
func NewCliService(conf *koanf.Koanf, appRepo biz.AppRepo, cache biz.CacheRepo, user biz.UserRepo, setting biz.SettingRepo, backup biz.BackupRepo, website biz.WebsiteRepo, databaseServer biz.DatabaseServerRepo) *CliService {
|
||||
func NewCliService(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 {
|
||||
return &CliService{
|
||||
hr: `+----------------------------------------------------`,
|
||||
api: api.NewAPI(app.Version),
|
||||
conf: conf,
|
||||
db: db,
|
||||
appRepo: appRepo,
|
||||
cacheRepo: cache,
|
||||
userRepo: user,
|
||||
@@ -120,7 +122,7 @@ func (s *CliService) Fix(ctx context.Context, cmd *cli.Command) error {
|
||||
|
||||
func (s *CliService) Info(ctx context.Context, cmd *cli.Command) error {
|
||||
user := new(biz.User)
|
||||
if err := app.Orm.Where("id", 1).First(user).Error; err != nil {
|
||||
if err := s.db.Where("id", 1).First(user).Error; err != nil {
|
||||
return fmt.Errorf("获取管理员信息失败:%v", err)
|
||||
}
|
||||
|
||||
@@ -135,7 +137,7 @@ func (s *CliService) Info(ctx context.Context, cmd *cli.Command) error {
|
||||
user.Email = str.Random(8) + "@example.com"
|
||||
}
|
||||
|
||||
if err = app.Orm.Save(user).Error; err != nil {
|
||||
if err = s.db.Save(user).Error; err != nil {
|
||||
return fmt.Errorf("管理员信息保存失败:%v", err)
|
||||
}
|
||||
|
||||
@@ -185,7 +187,7 @@ func (s *CliService) Info(ctx context.Context, cmd *cli.Command) error {
|
||||
|
||||
func (s *CliService) UserList(ctx context.Context, cmd *cli.Command) error {
|
||||
users := make([]biz.User, 0)
|
||||
if err := app.Orm.Find(&users).Error; err != nil {
|
||||
if err := s.db.Find(&users).Error; err != nil {
|
||||
return fmt.Errorf("获取用户列表失败:%v", err)
|
||||
}
|
||||
|
||||
@@ -207,7 +209,7 @@ func (s *CliService) UserName(ctx context.Context, cmd *cli.Command) error {
|
||||
return fmt.Errorf("新用户名不能为空")
|
||||
}
|
||||
|
||||
if err := app.Orm.Where("username", oldUsername).First(user).Error; err != nil {
|
||||
if err := s.db.Where("username", oldUsername).First(user).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fmt.Errorf("用户不存在")
|
||||
} else {
|
||||
@@ -216,7 +218,7 @@ func (s *CliService) UserName(ctx context.Context, cmd *cli.Command) error {
|
||||
}
|
||||
|
||||
user.Username = newUsername
|
||||
if err := app.Orm.Save(user).Error; err != nil {
|
||||
if err := s.db.Save(user).Error; err != nil {
|
||||
return fmt.Errorf("用户名修改失败:%v", err)
|
||||
}
|
||||
|
||||
@@ -235,7 +237,7 @@ func (s *CliService) UserPassword(ctx context.Context, cmd *cli.Command) error {
|
||||
return fmt.Errorf("密码长度不能小于6")
|
||||
}
|
||||
|
||||
if err := app.Orm.Where("username", username).First(user).Error; err != nil {
|
||||
if err := s.db.Where("username", username).First(user).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fmt.Errorf("用户不存在")
|
||||
} else {
|
||||
@@ -248,7 +250,7 @@ func (s *CliService) UserPassword(ctx context.Context, cmd *cli.Command) error {
|
||||
return fmt.Errorf("密码生成失败:%v", err)
|
||||
}
|
||||
user.Password = hashed
|
||||
if err = app.Orm.Save(user).Error; err != nil {
|
||||
if err = s.db.Save(user).Error; err != nil {
|
||||
return fmt.Errorf("密码修改失败:%v", err)
|
||||
}
|
||||
|
||||
@@ -702,7 +704,7 @@ func (s *CliService) AppWrite(ctx context.Context, cmd *cli.Command) error {
|
||||
}
|
||||
|
||||
newApp := new(biz.App)
|
||||
if err := app.Orm.Where("slug", slug).First(newApp).Error; err != nil {
|
||||
if err := s.db.Where("slug", slug).First(newApp).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fmt.Errorf("获取应用失败:%v", err)
|
||||
}
|
||||
@@ -710,7 +712,7 @@ func (s *CliService) AppWrite(ctx context.Context, cmd *cli.Command) error {
|
||||
newApp.Slug = slug
|
||||
newApp.Channel = channel
|
||||
newApp.Version = version
|
||||
if err := app.Orm.Save(newApp).Error; err != nil {
|
||||
if err := s.db.Save(newApp).Error; err != nil {
|
||||
return fmt.Errorf("应用保存失败:%v", err)
|
||||
}
|
||||
|
||||
@@ -723,7 +725,7 @@ func (s *CliService) AppRemove(ctx context.Context, cmd *cli.Command) error {
|
||||
return fmt.Errorf("参数不能为空")
|
||||
}
|
||||
|
||||
if err := app.Orm.Where("slug", slug).Delete(&biz.App{}).Error; err != nil {
|
||||
if err := s.db.Where("slug", slug).Delete(&biz.App{}).Error; err != nil {
|
||||
return fmt.Errorf("应用删除失败:%v", err)
|
||||
}
|
||||
|
||||
@@ -745,7 +747,7 @@ func (s *CliService) SyncTime(ctx context.Context, cmd *cli.Command) error {
|
||||
}
|
||||
|
||||
func (s *CliService) ClearTask(ctx context.Context, cmd *cli.Command) error {
|
||||
if err := app.Orm.Model(&biz.Task{}).
|
||||
if err := s.db.Model(&biz.Task{}).
|
||||
Where("status", biz.TaskStatusRunning).Or("status", biz.TaskStatusWaiting).
|
||||
Update("status", biz.TaskStatusFailed).
|
||||
Error; err != nil {
|
||||
@@ -763,7 +765,7 @@ func (s *CliService) GetSetting(ctx context.Context, cmd *cli.Command) error {
|
||||
}
|
||||
|
||||
setting := new(biz.Setting)
|
||||
if err := app.Orm.Where("key", key).First(setting).Error; err != nil {
|
||||
if err := s.db.Where("key", key).First(setting).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fmt.Errorf("设置不存在")
|
||||
}
|
||||
@@ -783,14 +785,14 @@ func (s *CliService) WriteSetting(ctx context.Context, cmd *cli.Command) error {
|
||||
}
|
||||
|
||||
setting := new(biz.Setting)
|
||||
if err := app.Orm.Where("key", key).First(setting).Error; err != nil {
|
||||
if err := s.db.Where("key", key).First(setting).Error; err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fmt.Errorf("获取设置失败:%v", err)
|
||||
}
|
||||
}
|
||||
setting.Key = biz.SettingKey(key)
|
||||
setting.Value = value
|
||||
if err := app.Orm.Save(setting).Error; err != nil {
|
||||
if err := s.db.Save(setting).Error; err != nil {
|
||||
return fmt.Errorf("设置保存失败:%v", err)
|
||||
}
|
||||
|
||||
@@ -803,7 +805,7 @@ func (s *CliService) RemoveSetting(ctx context.Context, cmd *cli.Command) error
|
||||
return fmt.Errorf("参数不能为空")
|
||||
}
|
||||
|
||||
if err := app.Orm.Where("key", key).Delete(&biz.Setting{}).Error; err != nil {
|
||||
if err := s.db.Where("key", key).Delete(&biz.Setting{}).Error; err != nil {
|
||||
return fmt.Errorf("设置删除失败:%v", err)
|
||||
}
|
||||
|
||||
@@ -812,7 +814,7 @@ func (s *CliService) RemoveSetting(ctx context.Context, cmd *cli.Command) error
|
||||
|
||||
func (s *CliService) Init(ctx context.Context, cmd *cli.Command) error {
|
||||
var check biz.User
|
||||
if err := app.Orm.First(&check).Error; err == nil {
|
||||
if err := s.db.First(&check).Error; err == nil {
|
||||
return fmt.Errorf("已经初始化过了")
|
||||
}
|
||||
|
||||
@@ -824,7 +826,7 @@ func (s *CliService) Init(ctx context.Context, cmd *cli.Command) error {
|
||||
{Key: biz.SettingKeyWebsitePath, Value: filepath.Join(app.Root, "wwwroot")},
|
||||
{Key: biz.SettingKeyVersion, Value: app.Version},
|
||||
}
|
||||
if err := app.Orm.Create(&settings).Error; err != nil {
|
||||
if err := s.db.Create(&settings).Error; err != nil {
|
||||
return fmt.Errorf("初始化失败:%v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
// Package apploader 面板应用加载器
|
||||
package apploader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/types"
|
||||
)
|
||||
|
||||
var apps sync.Map
|
||||
|
||||
func Register(app *types.App) {
|
||||
if _, ok := apps.Load(app.Slug); ok {
|
||||
log.Fatalf("app %s already exists", app.Slug)
|
||||
}
|
||||
apps.Store(app.Slug, app)
|
||||
}
|
||||
|
||||
func Get(slug string) (*types.App, error) {
|
||||
if app, ok := apps.Load(slug); ok {
|
||||
return app.(*types.App), nil
|
||||
}
|
||||
return nil, fmt.Errorf("app %s not found", slug)
|
||||
}
|
||||
|
||||
func All() []*types.App {
|
||||
var list []*types.App
|
||||
apps.Range(func(_, app any) bool {
|
||||
if p, ok := app.(*types.App); ok {
|
||||
list = append(list, p)
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// 排序
|
||||
/*slices.SortFunc(list, func(a, b *types.App) int {
|
||||
return cmp.Compare(a.Order, b.Order)
|
||||
})*/
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
func Boot(r chi.Router) {
|
||||
apps.Range(func(_, app any) bool {
|
||||
if p, ok := app.(*types.App); ok {
|
||||
r.Route(fmt.Sprintf("/%s", p.Slug), p.Route)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user