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

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

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 23:36:21 +08:00

198 lines
5.3 KiB
Go

package command
import (
"context"
"github.com/leonelquinteros/gotext"
"github.com/urfave/cli/v3"
"github.com/acepanel/panel/v3/internal/service"
)
// WebsiteCommand 网站管理命令组
func WebsiteCommand(t *gotext.Locale, cliService *service.CliService) *cli.Command {
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: "type",
Usage: t.Get("Website type (proxy, static, php)"),
Aliases: []string{"t"},
Value: "static",
},
&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"},
Value: []string{"80"},
},
&cli.StringFlag{
Name: "path",
Usage: t.Get("Path where the website is hosted (default path if not filled)"),
Aliases: []string{"p"},
},
&cli.StringFlag{
Name: "proxy",
Usage: t.Get("Address to proxy to (required for proxy type)"),
},
&cli.UintFlag{
Name: "php",
Usage: t.Get("PHP version used by the website (not used if not filled, php type only)"),
},
&cli.StringFlag{
Name: "db",
Usage: t.Get("Create a database of the given type (mysql, postgresql), not created if not filled"),
},
&cli.StringFlag{
Name: "db-name",
Usage: t.Get("Database name (website name if not filled)"),
},
&cli.StringFlag{
Name: "db-user",
Usage: t.Get("Database username (website name if not filled)"),
},
&cli.StringFlag{
Name: "db-password",
Usage: t.Get("Database password (randomly generated if not filled)"),
},
&cli.StringFlag{
Name: "remark",
Usage: t.Get("Website remark"),
},
},
Action: func(ctx context.Context, cmd *cli.Command) error {
return cliService.WebsiteCreate(ctx, cmd)
},
},
{
Name: "rebuild",
Usage: t.Get("Rebuild all website configs for the current web server"),
Action: func(ctx context.Context, cmd *cli.Command) error {
return cliService.WebsiteRebuild(ctx, cmd)
},
},
{
Name: "remove",
Usage: t.Get("Remove website (keep website directory and database)"),
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 cliService.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 cliService.WebsiteDelete(ctx, cmd)
},
},
{
Name: "list",
Usage: t.Get("List all websites"),
Action: func(ctx context.Context, cmd *cli.Command) error {
return cliService.WebsiteList(ctx, cmd)
},
},
{
Name: "cert",
Usage: t.Get("Update website certificate from files"),
Flags: []cli.Flag{
&cli.StringFlag{
Name: "name",
Usage: t.Get("Website name"),
Aliases: []string{"n"},
Required: true,
},
&cli.StringFlag{
Name: "cert",
Usage: t.Get("Certificate file path (fullchain)"),
Aliases: []string{"c"},
Required: true,
},
&cli.StringFlag{
Name: "key",
Usage: t.Get("Private key file path"),
Aliases: []string{"k"},
Required: true,
},
},
Action: func(ctx context.Context, cmd *cli.Command) error {
return cliService.WebsiteCert(ctx, cmd)
},
},
{
Name: "write",
Usage: t.Get("Write website data to the panel database only, without creating directories and config files (use only under guidance)"),
Hidden: true,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "name",
Usage: t.Get("Website name"),
Aliases: []string{"n"},
Required: true,
},
&cli.StringFlag{
Name: "type",
Usage: t.Get("Website type (proxy, static, php)"),
Aliases: []string{"t"},
Value: "static",
},
&cli.StringFlag{
Name: "path",
Usage: t.Get("Path where the website is hosted (default path if not filled)"),
Aliases: []string{"p"},
},
&cli.BoolFlag{
Name: "status",
Usage: t.Get("Website status"),
Value: true,
},
&cli.BoolFlag{
Name: "ssl",
Usage: t.Get("Whether the website has SSL enabled"),
},
&cli.StringFlag{
Name: "remark",
Usage: t.Get("Website remark"),
},
},
Action: func(ctx context.Context, cmd *cli.Command) error {
return cliService.WebsiteWrite(ctx, cmd)
},
},
},
}
}