mirror of
https://github.com/tnb-labs/panel.git
synced 2026-08-30 17:05:19 +08:00
refactor!: 迁移至 samber/do 依赖注入与三层架构
依赖注入:
- 移除 google/wire(含 wire.go/wire_gen.go 与全部 ProviderSet),
改用 samber/do v2 单注入器 + 双入口惰性构建
- 贡献模型替代命令式注册:路由 routes:、命令 commands:、
任务 jobs: 前缀经 internal/registry 收集与校验
- 构造函数统一 func NewXxx(i do.Injector) (T, error)
三层架构:
- 补全用例层:每个 biz.XxxRepo 配 XxxUsecase,
service/command/job 表现层只依赖用例,不再直接引用仓储
路由与文档:
- route/http.go 按域拆为声明式 Endpoint 贡献,
Endpoint 承载登录白名单与端点限流语义
- 调试模式下提供 OpenAPI 3.1 文档:/openapi.json 与 /docs(Scalar),
从 validate 标签生成
目录与依赖:
- internal/http/{middleware,request,rule} 拍平至 internal/*
- CLI 命令拆至 internal/command
- 日志轮转 timberjack 换为 libtnb/logrotate
- 升级 validator/cron/sessions/gormstore/sqlite/securecookie
- 数据库迁移保持 gormigrate 不变
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/service"
|
||||
)
|
||||
|
||||
// AppCommand 应用管理命令组
|
||||
func AppCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "app",
|
||||
Usage: t.Get("Application management"),
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "install",
|
||||
Usage: t.Get("Install application"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).AppInstall(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "uninstall",
|
||||
Usage: t.Get("Uninstall application"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).AppUnInstall(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "update",
|
||||
Usage: t.Get("Update application"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).AppUpdate(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "write",
|
||||
Usage: t.Get("Add panel application mark (use only under guidance)"),
|
||||
Hidden: true,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).AppWrite(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "remove",
|
||||
Usage: t.Get("Remove panel application mark (use only under guidance)"),
|
||||
Hidden: true,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).AppRemove(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/service"
|
||||
)
|
||||
|
||||
// BackupCommand 数据备份命令组
|
||||
func BackupCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "backup",
|
||||
Usage: t.Get("Data backup"),
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "website",
|
||||
Usage: t.Get("Backup website"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Aliases: []string{"n"},
|
||||
Usage: t.Get("Website name"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "storage",
|
||||
Aliases: []string{"s"},
|
||||
Usage: t.Get("Storage ID (local storage if not filled)"),
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).BackupWebsite(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "database",
|
||||
Usage: t.Get("Backup database"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "type",
|
||||
Aliases: []string{"t"},
|
||||
Usage: t.Get("Database type"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Aliases: []string{"n"},
|
||||
Usage: t.Get("Database name"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "storage",
|
||||
Aliases: []string{"s"},
|
||||
Usage: t.Get("Storage ID (local storage if not filled)"),
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).BackupDatabase(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "path",
|
||||
Usage: t.Get("Backup directory"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "path",
|
||||
Aliases: []string{"p"},
|
||||
Usage: t.Get("Directory path"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "storage",
|
||||
Aliases: []string{"s"},
|
||||
Usage: t.Get("Storage ID (local storage if not filled)"),
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).BackupPath(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "panel",
|
||||
Usage: t.Get("Backup panel"),
|
||||
Flags: []cli.Flag{},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).BackupPanel(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "clear",
|
||||
Usage: t.Get("Clear backups"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "type",
|
||||
Aliases: []string{"t"},
|
||||
Usage: t.Get("Backup type"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "file",
|
||||
Aliases: []string{"f"},
|
||||
Usage: t.Get("Backup file"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "keep",
|
||||
Aliases: []string{"k"},
|
||||
Usage: t.Get("Number of backups to keep"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "storage",
|
||||
Aliases: []string{"s"},
|
||||
Usage: t.Get("Storage ID (local storage if not filled)"),
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).BackupClear(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/registry"
|
||||
)
|
||||
|
||||
const Prefix = "commands:"
|
||||
|
||||
var Package = do.Package(
|
||||
do.LazyNamed(Prefix+"status", StatusCommand), do.LazyNamed(Prefix+"restart", RestartCommand),
|
||||
do.LazyNamed(Prefix+"stop", StopCommand), do.LazyNamed(Prefix+"start", StartCommand),
|
||||
do.LazyNamed(Prefix+"update", UpdateCommand), do.LazyNamed(Prefix+"sync", SyncCommand),
|
||||
do.LazyNamed(Prefix+"fix", FixCommand), do.LazyNamed(Prefix+"info", InfoCommand),
|
||||
do.LazyNamed(Prefix+"port", PortCommand), do.LazyNamed(Prefix+"sync-time", SyncTimeCommand),
|
||||
do.LazyNamed(Prefix+"clear-task", ClearTaskCommand), do.LazyNamed(Prefix+"init", InitCommand),
|
||||
do.LazyNamed(Prefix+"user", UserCommand), do.LazyNamed(Prefix+"https", HttpsCommand),
|
||||
do.LazyNamed(Prefix+"entrance", EntranceCommand), do.LazyNamed(Prefix+"bind-domain", BindDomainCommand),
|
||||
do.LazyNamed(Prefix+"bind-ip", BindIPCommand), do.LazyNamed(Prefix+"bind-ua", BindUACommand),
|
||||
do.LazyNamed(Prefix+"website", WebsiteCommand), do.LazyNamed(Prefix+"database", DatabaseCommand),
|
||||
do.LazyNamed(Prefix+"backup", BackupCommand), do.LazyNamed(Prefix+"cutoff", CutoffCommand),
|
||||
do.LazyNamed(Prefix+"app", AppCommand), do.LazyNamed(Prefix+"setting", SettingCommand),
|
||||
)
|
||||
|
||||
// Commands 收集全部命令贡献。
|
||||
func Commands(i do.Injector) ([]*cli.Command, error) {
|
||||
return registry.Collect[*cli.Command](i, Prefix)
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/service"
|
||||
)
|
||||
|
||||
// CutoffCommand 日志切割命令组
|
||||
func CutoffCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "cutoff",
|
||||
Usage: t.Get("Log rotation"),
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "website",
|
||||
Usage: t.Get("Website"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Aliases: []string{"n"},
|
||||
Usage: t.Get("Website name"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "storage",
|
||||
Aliases: []string{"s"},
|
||||
Usage: t.Get("Storage ID (local storage if not filled)"),
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).CutoffWebsite(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "container",
|
||||
Usage: t.Get("Container"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Aliases: []string{"n"},
|
||||
Usage: t.Get("Container name"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "storage",
|
||||
Aliases: []string{"s"},
|
||||
Usage: t.Get("Storage ID (local storage if not filled)"),
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).CutoffContainer(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "clear",
|
||||
Usage: t.Get("Clear rotated logs"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "type",
|
||||
Aliases: []string{"t"},
|
||||
Usage: t.Get("Rotation type"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Aliases: []string{"n"},
|
||||
Usage: t.Get("Target name"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "keep",
|
||||
Aliases: []string{"k"},
|
||||
Usage: t.Get("Number of logs to keep"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "storage",
|
||||
Aliases: []string{"s"},
|
||||
Usage: t.Get("Storage ID (local storage if not filled)"),
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).CutoffClear(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/service"
|
||||
)
|
||||
|
||||
// DatabaseCommand 数据库管理命令组
|
||||
func DatabaseCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "database",
|
||||
Usage: t.Get("Database management"),
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "add-server",
|
||||
Usage: t.Get("Add database server"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "type",
|
||||
Usage: t.Get("Server type"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: t.Get("Server name"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "host",
|
||||
Usage: t.Get("Server address"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "port",
|
||||
Usage: t.Get("Server port"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "username",
|
||||
Usage: t.Get("Server username"),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "password",
|
||||
Usage: t.Get("Server password"),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "remark",
|
||||
Usage: t.Get("Server remark"),
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).DatabaseAddServer(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "delete-server",
|
||||
Usage: t.Get("Delete database server"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: t.Get("Server name"),
|
||||
Aliases: []string{"n"},
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).DatabaseDeleteServer(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/service"
|
||||
)
|
||||
|
||||
// EntranceCommand 访问入口管理命令组
|
||||
func EntranceCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "entrance",
|
||||
Usage: t.Get("Operate AcePanel access entrance"),
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "on",
|
||||
Usage: t.Get("Enable access entrance"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).EntranceOn(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "off",
|
||||
Usage: t.Get("Disable access entrance"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).EntranceOff(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BindDomainCommand 域名绑定管理命令组
|
||||
func BindDomainCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "bind-domain",
|
||||
Usage: t.Get("Operate AcePanel domain binding"),
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "off",
|
||||
Usage: t.Get("Disable domain binding"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).BindDomainOff(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BindIPCommand IP 绑定管理命令组
|
||||
func BindIPCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "bind-ip",
|
||||
Usage: t.Get("Operate AcePanel IP binding"),
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "off",
|
||||
Usage: t.Get("Disable IP binding"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).BindIPOff(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BindUACommand UA 绑定管理命令组
|
||||
func BindUACommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "bind-ua",
|
||||
Usage: t.Get("Operate AcePanel UA binding"),
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "off",
|
||||
Usage: t.Get("Disable UA binding"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).BindUAOff(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/service"
|
||||
)
|
||||
|
||||
// HttpsCommand 面板 HTTPS 管理命令组
|
||||
func HttpsCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "https",
|
||||
Usage: t.Get("Operate AcePanel HTTPS"),
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "on",
|
||||
Usage: t.Get("Enable HTTPS"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).HTTPSOn(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "off",
|
||||
Usage: t.Get("Disable HTTPS"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).HTTPSOff(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "generate",
|
||||
Usage: t.Get("Obtain a free certificate or generate a self-signed certificate"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).HTTPSGenerate(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/service"
|
||||
)
|
||||
|
||||
// UpdateCommand 更新面板
|
||||
func UpdateCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "update",
|
||||
Usage: t.Get("Update AcePanel to the latest version"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).Update(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SyncCommand 同步云端缓存数据
|
||||
func SyncCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "sync",
|
||||
Usage: t.Get("Sync AcePanel cached data with cloud"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).Sync(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// FixCommand 修复升级问题
|
||||
func FixCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "fix",
|
||||
Usage: t.Get("Fix AcePanel upgrade issues"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).Fix(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// InfoCommand 输出面板基础信息
|
||||
func InfoCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "info",
|
||||
Usage: t.Get("Output AcePanel basic information"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "force",
|
||||
Aliases: []string{"f"},
|
||||
Usage: t.Get("Force reset password"),
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).Info(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PortCommand 修改监听端口
|
||||
func PortCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "port",
|
||||
Usage: t.Get("Change the AcePanel listening port"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).Port(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SyncTimeCommand 通过 NTP 同步系统时间
|
||||
func SyncTimeCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "sync-time",
|
||||
Usage: t.Get("Sync server time with NTP"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).SyncTime(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ClearTaskCommand 清理卡住的任务队列
|
||||
func ClearTaskCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "clear-task",
|
||||
Usage: t.Get("Clear all tasks in the task queue if they are stuck (use only under guidance)"),
|
||||
Hidden: true,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).ClearTask(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// InitCommand 初始化面板
|
||||
func InitCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "init",
|
||||
Usage: t.Get("Initialize AcePanel (use only under guidance)"),
|
||||
Hidden: true,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).Init(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/service"
|
||||
)
|
||||
|
||||
// StatusCommand 查询服务状态
|
||||
func StatusCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "status",
|
||||
Usage: t.Get("Get AcePanel service status"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).Status(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RestartCommand 重启服务
|
||||
func RestartCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "restart",
|
||||
Usage: t.Get("Restart AcePanel service"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).Restart(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// StopCommand 停止服务
|
||||
func StopCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "stop",
|
||||
Usage: t.Get("Stop AcePanel service"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).Stop(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// StartCommand 启动服务
|
||||
func StartCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "start",
|
||||
Usage: t.Get("Start AcePanel service"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).Start(ctx, cmd)
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/service"
|
||||
)
|
||||
|
||||
// SettingCommand 面板设置管理命令组
|
||||
func SettingCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "setting",
|
||||
Usage: t.Get("Setting management"),
|
||||
Hidden: true,
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "get",
|
||||
Usage: t.Get("Get panel setting (use only under guidance)"),
|
||||
Hidden: true,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).GetSetting(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "write",
|
||||
Usage: t.Get("Write panel setting (use only under guidance)"),
|
||||
Hidden: true,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).WriteSetting(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "remove",
|
||||
Usage: t.Get("Remove panel setting (use only under guidance)"),
|
||||
Hidden: true,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).RemoveSetting(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/service"
|
||||
)
|
||||
|
||||
// UserCommand 用户管理命令组
|
||||
func UserCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "user",
|
||||
Usage: t.Get("Operate AcePanel users"),
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "list",
|
||||
Usage: t.Get("List all users"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).UserList(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "username",
|
||||
Usage: t.Get("Change a user's username"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).UserName(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "password",
|
||||
Usage: t.Get("Change a user's password"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).UserPassword(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "2fa",
|
||||
Usage: t.Get("Toggle two-factor authentication for a user"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).UserTwoFA(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "passkey",
|
||||
Usage: t.Get("Clear all passkeys for a user"),
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).UserPasskey(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/samber/do/v2"
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"github.com/acepanel/panel/v3/internal/service"
|
||||
)
|
||||
|
||||
// WebsiteCommand 网站管理命令组
|
||||
func WebsiteCommand(i do.Injector) (*cli.Command, error) {
|
||||
t := do.MustInvoke[*gotext.Locale](i)
|
||||
return &cli.Command{
|
||||
Name: "website",
|
||||
Usage: t.Get("Website management"),
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "create",
|
||||
Usage: t.Get("Create new website"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: t.Get("Website name"),
|
||||
Aliases: []string{"n"},
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "domains",
|
||||
Usage: t.Get("List of domains associated with the website"),
|
||||
Aliases: []string{"d"},
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "listens",
|
||||
Usage: t.Get("List of listening addresses associated with the website"),
|
||||
Aliases: []string{"l"},
|
||||
Required: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "path",
|
||||
Usage: t.Get("Path where the website is hosted (default path if not filled)"),
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "php",
|
||||
Usage: t.Get("PHP version used by the website (not used if not filled)"),
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).WebsiteCreate(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "remove",
|
||||
Usage: t.Get("Remove website"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: t.Get("Website name"),
|
||||
Aliases: []string{"n"},
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).WebsiteRemove(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "delete",
|
||||
Usage: t.Get("Delete website (including website directory, database with the same name)"),
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: t.Get("Website name"),
|
||||
Aliases: []string{"n"},
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).WebsiteDelete(ctx, cmd)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "write",
|
||||
Usage: t.Get("Write website data (use only under guidance)"),
|
||||
Hidden: true,
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
return do.MustInvoke[*service.CliService](i).WebsiteWrite(ctx, cmd)
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user