diff --git a/backend/app/api/v1/device.go b/backend/app/api/v1/device.go new file mode 100644 index 000000000..2769d73ca --- /dev/null +++ b/backend/app/api/v1/device.go @@ -0,0 +1,183 @@ +package v1 + +import ( + "encoding/base64" + + "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" + "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/gin-gonic/gin" +) + +// @Tags Device +// @Summary Load device base info +// @Description 获取设备基础信息 +// @Success 200 {object} dto.DeviceBaseInfo +// @Security ApiKeyAuth +// @Router /toolbox/device/base [get] +func (b *BaseApi) LoadDeviceBaseInfo(c *gin.Context) { + data, err := deviceService.LoadBaseInfo() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, data) +} + +// @Tags Device +// @Summary list time zone options +// @Description 获取系统可用时区选项 +// @Accept json +// @Success 200 {Array} string +// @Security ApiKeyAuth +// @Router /toolbox/device/zone/options [get] +func (b *BaseApi) LoadTimeOption(c *gin.Context) { + list, err := deviceService.LoadTimeZone() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, list) +} + +// @Tags Device +// @Summary load conf +// @Description 获取系统配置文件 +// @Accept json +// @Param request body dto.OperationWithName true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /toolbox/device/conf [post] +func (b *BaseApi) LoadDeviceConf(c *gin.Context) { + var req dto.OperationWithName + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + + list, err := deviceService.LoadConf(req.Name) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, list) +} + +// @Tags Device +// @Summary Update device conf by file +// @Description 通过文件修改配置 +// @Accept json +// @Param request body dto.UpdateByNameAndFile true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /toolbox/device/update/byconf [post] +func (b *BaseApi) UpdateDevicByFile(c *gin.Context) { + var req dto.UpdateByNameAndFile + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := deviceService.UpdateByConf(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, nil) +} + +// @Tags Device +// @Summary Update device +// @Description 修改系统参数 +// @Accept json +// @Param request body dto.SettingUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /toolbox/device/update/conf [post] +// @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改主机参数 [key] => [value]","formatEN":"update device conf [key] => [value]"} +func (b *BaseApi) UpdateDeviceConf(c *gin.Context) { + var req dto.SettingUpdate + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + + if err := deviceService.Update(req.Key, req.Value); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, nil) +} + +// @Tags Device +// @Summary Update device hosts +// @Description 修改系统 hosts +// @Success 200 +// @Security ApiKeyAuth +// @Router /toolbox/device/update/host [post] +// @x-panel-log {"bodyKeys":["key","value"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"修改主机 Host [key] => [value]","formatEN":"update device host [key] => [value]"} +func (b *BaseApi) UpdateDeviceHost(c *gin.Context) { + var req []dto.HostHelper + if err := helper.CheckBind(&req, c); err != nil { + return + } + + if err := deviceService.UpdateHosts(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, nil) +} + +// @Tags Device +// @Summary Update device passwd +// @Description 修改系统密码 +// @Accept json +// @Param request body dto.ChangePasswd true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /toolbox/device/update/passwd [post] +func (b *BaseApi) UpdateDevicPasswd(c *gin.Context) { + var req dto.ChangePasswd + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if len(req.Passwd) != 0 { + password, err := base64.StdEncoding.DecodeString(req.Passwd) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + req.Passwd = string(password) + } + if err := deviceService.UpdatePasswd(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, nil) +} + +// @Tags Device +// @Summary Check device DNS conf +// @Description 检查系统 DNS 配置可用性 +// @Accept json +// @Param request body dto.SettingUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /toolbox/device/check/dns [post] +func (b *BaseApi) CheckDNS(c *gin.Context) { + var req dto.SettingUpdate + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + + data, err := deviceService.CheckDNS(req.Key, req.Value) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + + helper.SuccessWithData(c, data) +} diff --git a/backend/app/api/v1/entry.go b/backend/app/api/v1/entry.go index 86e996167..d7c52e54e 100644 --- a/backend/app/api/v1/entry.go +++ b/backend/app/api/v1/entry.go @@ -33,6 +33,7 @@ var ( sshService = service.NewISSHService() firewallService = service.NewIFirewallService() + deviceService = service.NewIDeviceService() fail2banService = service.NewIFail2BanService() settingService = service.NewISettingService() diff --git a/backend/app/api/v1/setting.go b/backend/app/api/v1/setting.go index 6884f535f..4e3b27eed 100644 --- a/backend/app/api/v1/setting.go +++ b/backend/app/api/v1/setting.go @@ -217,43 +217,6 @@ func (b *BaseApi) HandlePasswordExpired(c *gin.Context) { helper.SuccessWithData(c, nil) } -// @Tags System Setting -// @Summary Load time zone options -// @Description 加载系统可用时区 -// @Success 200 -// @Security ApiKeyAuth -// @Router /settings/time/option [get] -func (b *BaseApi) LoadTimeZone(c *gin.Context) { - zones, err := settingService.LoadTimeZone() - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, zones) -} - -// @Tags System Setting -// @Summary Sync system time -// @Description 系统时间同步 -// @Accept json -// @Param request body dto.SyncTime true "request" -// @Success 200 {string} ntime -// @Security ApiKeyAuth -// @Router /settings/time/sync [post] -// @x-panel-log {"bodyKeys":["ntpSite"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"系统时间同步[ntpSite]","formatEN":"sync system time [ntpSite]"} -func (b *BaseApi) SyncTime(c *gin.Context) { - var req dto.SyncTime - if err := helper.CheckBindAndValidate(&req, c); err != nil { - return - } - - if err := settingService.SyncTime(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - // @Tags System Setting // @Summary Load local backup dir // @Description 获取安装根目录 diff --git a/backend/app/dto/common_req.go b/backend/app/dto/common_req.go index 02e9409c9..6aee5d73f 100644 --- a/backend/app/dto/common_req.go +++ b/backend/app/dto/common_req.go @@ -45,6 +45,11 @@ type UpdateByFile struct { File string `json:"file"` } +type UpdateByNameAndFile struct { + Name string `json:"name"` + File string `json:"file"` +} + type OperationWithNameAndType struct { Name string `json:"name"` Type string `json:"type" validate:"required"` diff --git a/backend/app/dto/device.go b/backend/app/dto/device.go new file mode 100644 index 000000000..3cbc4f843 --- /dev/null +++ b/backend/app/dto/device.go @@ -0,0 +1,26 @@ +package dto + +type DeviceBaseInfo struct { + DNS []string `json:"dns"` + Hosts []HostHelper `json:"hosts"` + Hostname string `json:"hostname"` + TimeZone string `json:"timeZone"` + LocalTime string `json:"localTime"` + Ntp string `json:"ntp"` + User string `json:"user"` +} + +type HostHelper struct { + IP string `json:"ip"` + Host string `json:"host"` +} + +type TimeZoneOptions struct { + From string `json:"from"` + Zones []string `json:"zones"` +} + +type ChangePasswd struct { + User string `json:"user"` + Passwd string `json:"passwd"` +} diff --git a/backend/app/service/device.go b/backend/app/service/device.go new file mode 100644 index 000000000..5f779e2be --- /dev/null +++ b/backend/app/service/device.go @@ -0,0 +1,293 @@ +package service + +import ( + "bufio" + "errors" + "fmt" + "net" + "os" + "strings" + "time" + + "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/global" + "github.com/1Panel-dev/1Panel/backend/utils/cmd" + "github.com/1Panel-dev/1Panel/backend/utils/common" + "github.com/1Panel-dev/1Panel/backend/utils/ntp" +) + +const defaultDNSPath = "/etc/resolv.conf" +const defaultHostPath = "/etc/hosts" + +type DeviceService struct{} + +type IDeviceService interface { + LoadBaseInfo() (dto.DeviceBaseInfo, error) + Update(key, value string) error + UpdateHosts(req []dto.HostHelper) error + UpdatePasswd(req dto.ChangePasswd) error + UpdateByConf(req dto.UpdateByNameAndFile) error + LoadTimeZone() ([]string, error) + CheckDNS(key, value string) (bool, error) + LoadConf(name string) (string, error) +} + +func NewIDeviceService() IDeviceService { + return &DeviceService{} +} + +func (u *DeviceService) LoadBaseInfo() (dto.DeviceBaseInfo, error) { + var baseInfo dto.DeviceBaseInfo + baseInfo.LocalTime = time.Now().Format("2006-01-02 15:04:05 MST -0700") + baseInfo.TimeZone = common.LoadTimeZoneByCmd() + baseInfo.DNS = loadDNS() + baseInfo.Hosts = loadHosts() + baseInfo.Hostname = loadHostname() + baseInfo.User = loadUser() + ntp, _ := settingRepo.Get(settingRepo.WithByKey("NtpSite")) + baseInfo.Ntp = ntp.Value + + return baseInfo, nil +} + +func (u *DeviceService) LoadTimeZone() ([]string, error) { + std, err := cmd.Exec("timedatectl list-timezones") + if err != nil { + return []string{}, err + } + return strings.Split(std, "\n"), nil +} + +func (u *DeviceService) CheckDNS(key, value string) (bool, error) { + content, err := os.ReadFile(defaultDNSPath) + if err != nil { + return false, err + } + defer func() { _ = u.UpdateByConf(dto.UpdateByNameAndFile{Name: "DNS", File: string(content)}) }() + if key == "form" { + if err := u.Update("DNS", value); err != nil { + return false, err + } + } else { + if err := u.UpdateByConf(dto.UpdateByNameAndFile{Name: "DNS", File: value}); err != nil { + return false, err + } + } + + conn, err := net.DialTimeout("ip4:icmp", "www.baidu.com", time.Second*2) + if err != nil { + return false, err + } + defer conn.Close() + + return true, nil +} + +func (u *DeviceService) Update(key, value string) error { + switch key { + case "TimeZone": + if err := ntp.UpdateSystemTimeZone(value); err != nil { + return err + } + go func() { + _, err := cmd.Exec("systemctl restart 1panel.service") + if err != nil { + global.LOG.Errorf("restart system for new time zone failed, err: %v", err) + } + }() + case "DNS": + if err := updateDNS(strings.Split(value, ",")); err != nil { + return err + } + case "Hostname": + std, err := cmd.Execf("%s hostnamectl set-hostname %s", cmd.SudoHandleCmd(), value) + if err != nil { + return errors.New(std) + } + case "LocalTime": + if err := settingRepo.Update("NtpSite", value); err != nil { + return err + } + ntime, err := ntp.GetRemoteTime(value) + if err != nil { + return err + } + ts := ntime.Format("2006-01-02 15:04:05") + if err := ntp.UpdateSystemTime(ts); err != nil { + return err + } + default: + return fmt.Errorf("not support such key %s", key) + } + return nil +} + +func (u *DeviceService) UpdateHosts(req []dto.HostHelper) error { + conf, err := os.ReadFile(defaultHostPath) + if err != nil { + return fmt.Errorf("read namesever conf of %s failed, err: %v", defaultHostPath, err) + } + lines := strings.Split(string(conf), "\n") + newFile := "" + for _, line := range lines { + if len(line) == 0 { + continue + } + parts := strings.Fields(line) + if len(parts) < 2 { + newFile += line + "\n" + continue + } + for index, item := range req { + if item.IP == parts[0] && item.Host == strings.Join(parts[1:], " ") { + newFile += line + "\n" + req = append(req[:index], req[index+1:]...) + break + } + } + } + for _, item := range req { + newFile += fmt.Sprintf("%s %s \n", item.IP, item.Host) + } + file, err := os.OpenFile(defaultHostPath, os.O_WRONLY|os.O_TRUNC, 0640) + if err != nil { + return err + } + defer file.Close() + write := bufio.NewWriter(file) + _, _ = write.WriteString(newFile) + write.Flush() + return nil +} + +func (u *DeviceService) UpdatePasswd(req dto.ChangePasswd) error { + std, err := cmd.Execf("%s echo '%s:%s' | %s chpasswd", cmd.SudoHandleCmd(), req.User, req.Passwd, cmd.SudoHandleCmd()) + if err != nil { + return errors.New(std) + } + return nil +} + +func (u *DeviceService) LoadConf(name string) (string, error) { + pathItem := "" + switch name { + case "DNS": + pathItem = defaultDNSPath + case "Hosts": + pathItem = defaultHostPath + default: + return "", fmt.Errorf("not support such name %s", name) + } + if _, err := os.Stat(pathItem); err != nil { + return "", err + } + content, err := os.ReadFile(pathItem) + if err != nil { + return "", err + } + return string(content), nil +} + +func (u *DeviceService) UpdateByConf(req dto.UpdateByNameAndFile) error { + if req.Name != "DNS" && req.Name != "Hosts" { + return fmt.Errorf("not support such name %s", req.Name) + } + path := defaultDNSPath + if req.Name == "Hosts" { + path = defaultHostPath + } + file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0640) + if err != nil { + return err + } + defer file.Close() + write := bufio.NewWriter(file) + _, _ = write.WriteString(req.File) + write.Flush() + return nil +} + +func loadDNS() []string { + var list []string + dnsConf, err := os.ReadFile(defaultDNSPath) + if err == nil { + lines := strings.Split(string(dnsConf), "\n") + for _, line := range lines { + if strings.HasPrefix(line, "nameserver ") { + list = append(list, strings.TrimPrefix(line, "nameserver ")) + } + } + } + return list +} + +func updateDNS(list []string) error { + conf, err := os.ReadFile(defaultDNSPath) + if err != nil { + return fmt.Errorf("read nameserver conf of %s failed, err: %v", defaultDNSPath, err) + } + lines := strings.Split(string(conf), "\n") + newFile := "" + for _, line := range lines { + if len(line) == 0 { + continue + } + parts := strings.Fields(line) + if len(parts) < 2 || parts[0] != "nameserver" { + newFile += line + "\n" + continue + } + itemNs := strings.Join(parts[1:], " ") + for index, item := range list { + if item == itemNs { + newFile += line + "\n" + list = append(list[:index], list[index+1:]...) + break + } + } + } + for _, item := range list { + newFile += fmt.Sprintf("nameserver %s \n", item) + } + file, err := os.OpenFile(defaultDNSPath, os.O_WRONLY|os.O_TRUNC, 0640) + if err != nil { + return err + } + defer file.Close() + write := bufio.NewWriter(file) + _, _ = write.WriteString(newFile) + write.Flush() + return nil +} + +func loadHosts() []dto.HostHelper { + var list []dto.HostHelper + hostConf, err := os.ReadFile(defaultHostPath) + if err == nil { + lines := strings.Split(string(hostConf), "\n") + for _, line := range lines { + parts := strings.Fields(line) + if len(parts) < 2 { + continue + } + list = append(list, dto.HostHelper{IP: parts[0], Host: strings.Join(parts[1:], " ")}) + } + } + return list +} + +func loadHostname() string { + std, err := cmd.Exec("hostname") + if err != nil { + return "" + } + return strings.ReplaceAll(std, "\n", "") +} + +func loadUser() string { + std, err := cmd.Exec("whoami") + if err != nil { + return "" + } + return strings.ReplaceAll(std, "\n", "") +} diff --git a/backend/app/service/setting.go b/backend/app/service/setting.go index 9001a14f3..d50dfc42d 100644 --- a/backend/app/service/setting.go +++ b/backend/app/service/setting.go @@ -21,7 +21,6 @@ import ( "github.com/1Panel-dev/1Panel/backend/utils/common" "github.com/1Panel-dev/1Panel/backend/utils/encrypt" "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/1Panel-dev/1Panel/backend/utils/ntp" "github.com/1Panel-dev/1Panel/backend/utils/ssl" "github.com/gin-gonic/gin" "github.com/robfig/cron/v3" @@ -32,7 +31,6 @@ type SettingService struct{} type ISettingService interface { GetSettingInfo() (*dto.SettingInfo, error) LoadInterfaceAddr() ([]string, error) - LoadTimeZone() ([]string, error) Update(key, value string) error UpdatePassword(c *gin.Context, old, new string) error UpdatePort(port uint) error @@ -40,7 +38,6 @@ type ISettingService interface { UpdateSSL(c *gin.Context, req dto.SSLUpdate) error LoadFromCert() (*dto.SSLInfo, error) HandlePasswordExpired(c *gin.Context, old, new string) error - SyncTime(req dto.SyncTime) error SystemScan() dto.CleanData SystemClean(req []dto.Clean) @@ -72,14 +69,6 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) { return &info, err } -func (u *SettingService) LoadTimeZone() ([]string, error) { - std, err := cmd.Exec("timedatectl list-timezones") - if err != nil { - return []string{}, nil - } - return strings.Split(std, "\n"), err -} - func (u *SettingService) Update(key, value string) error { switch key { case "MonitorStatus": @@ -107,10 +96,6 @@ func (u *SettingService) Update(key, value string) error { return err } } - case "TimeZone": - if err := ntp.UpdateSystemTimeZone(value); err != nil { - return err - } case "AppStoreLastModified": exist, _ := settingRepo.Get(settingRepo.WithByKey("AppStoreLastModified")) if exist.ID == 0 { @@ -129,13 +114,6 @@ func (u *SettingService) Update(key, value string) error { if err := settingRepo.Update("ExpirationTime", time.Now().AddDate(0, 0, timeout).Format("2006-01-02 15:04:05")); err != nil { return err } - case "TimeZone": - go func() { - _, err := cmd.Exec("systemctl restart 1panel.service") - if err != nil { - global.LOG.Errorf("restart system for new time zone failed, err: %v", err) - } - }() case "BindDomain": if len(value) != 0 { _ = global.SESSION.Clean() @@ -148,21 +126,6 @@ func (u *SettingService) Update(key, value string) error { return nil } -func (u *SettingService) SyncTime(req dto.SyncTime) error { - if err := settingRepo.Update("NtpSite", req.NtpSite); err != nil { - return err - } - ntime, err := ntp.GetRemoteTime(req.NtpSite) - if err != nil { - return err - } - ts := ntime.Format("2006-01-02 15:04:05") - if err := ntp.UpdateSystemTime(ts); err != nil { - return err - } - return nil -} - func (u *SettingService) LoadInterfaceAddr() ([]string, error) { addrMap := make(map[string]struct{}) addrs, err := net.InterfaceAddrs() diff --git a/backend/router/ro_setting.go b/backend/router/ro_setting.go index 9cb98ee50..6f5b6f829 100644 --- a/backend/router/ro_setting.go +++ b/backend/router/ro_setting.go @@ -29,8 +29,6 @@ func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) { settingRouter.GET("/ssl/info", baseApi.LoadFromCert) settingRouter.POST("/ssl/download", baseApi.DownloadSSL) settingRouter.POST("/password/update", baseApi.UpdatePassword) - settingRouter.GET("/time/option", baseApi.LoadTimeZone) - settingRouter.POST("/time/sync", baseApi.SyncTime) settingRouter.POST("/monitor/clean", baseApi.CleanMonitor) settingRouter.POST("/mfa", baseApi.LoadMFA) settingRouter.POST("/mfa/bind", baseApi.MFABind) diff --git a/backend/router/ro_toolbox.go b/backend/router/ro_toolbox.go index 6027e6669..64a58a63d 100644 --- a/backend/router/ro_toolbox.go +++ b/backend/router/ro_toolbox.go @@ -16,6 +16,15 @@ func (s *ToolboxRouter) InitToolboxRouter(Router *gin.RouterGroup) { Use(middleware.PasswordExpired()) baseApi := v1.ApiGroupApp.BaseApi { + toolboxRouter.GET("/device/base", baseApi.LoadDeviceBaseInfo) + toolboxRouter.GET("/device/zone/options", baseApi.LoadTimeOption) + toolboxRouter.POST("/device/update/conf", baseApi.UpdateDeviceConf) + toolboxRouter.POST("/device/update/host", baseApi.UpdateDeviceHost) + toolboxRouter.POST("/device/update/passwd", baseApi.UpdateDevicPasswd) + toolboxRouter.POST("/device/update/byconf", baseApi.UpdateDevicByFile) + toolboxRouter.POST("/device/check/dns", baseApi.CheckDNS) + toolboxRouter.POST("/device/conf", baseApi.LoadDeviceConf) + toolboxRouter.GET("/fail2ban/base", baseApi.LoadFail2BanBaseInfo) toolboxRouter.GET("/fail2ban/load/conf", baseApi.LoadFail2BanConf) toolboxRouter.POST("/fail2ban/search", baseApi.SearchFail2Ban) diff --git a/backend/utils/toolbox/fail2ban_test.go b/backend/utils/toolbox/fail2ban_test.go deleted file mode 100644 index a167e5ae5..000000000 --- a/backend/utils/toolbox/fail2ban_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package toolbox - -import ( - "fmt" - "os" - "strings" - "testing" - - "github.com/1Panel-dev/1Panel/backend/utils/ssh" -) - -func TestCds(t *testing.T) { - kk := ssh.ConnInfo{ - Port: 22, - AuthMode: "password", - User: "root", - } - sd, err := kk.Run("fail2ban-client get sshd ignoreip") - if err != nil { - fmt.Println(err) - } - sd = strings.ReplaceAll(sd, "|", "") - sd = strings.ReplaceAll(sd, "`", "") - sd = strings.ReplaceAll(sd, "\n", "") - - addrs := strings.Split(sd, "-") - for _, addr := range addrs { - if !strings.HasPrefix(addr, " ") { - continue - } - fmt.Println(strings.TrimPrefix(addr, " ")) - } -} - -func TestCdsxx(t *testing.T) { - initFile := `#DEFAULT-START -[DEFAULT] -ignoreip = 127.0.0.1/8,172.16.10.114,172.16.10.116 -bantime = 600 -findtime = 300 -maxretry = 5 -banaction = firewallcmd-ipset -action = %(action_mwl)s -#DEFAULT-END - -#sshd-START -[sshd] -enabled = true -filter = sshd -port = 22 -maxretry = 5 -findtime = 300 -bantime = 86400 -action = %(action_mwl)s -logpath = /var/log/secure -#sshd-END` - - if err := os.WriteFile("/Users/slooop/Downloads/tex.txt", []byte(initFile), 0640); err != nil { - fmt.Println(err) - } -} diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index 824afeecf..ebee5efb1 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -1,5 +1,5 @@ -// Package docs GENERATED BY SWAG; DO NOT EDIT -// This file was generated by swaggo/swag +// Code generated by swaggo/swag. DO NOT EDIT. + package docs import "github.com/swaggo/swag" @@ -9906,70 +9906,6 @@ const docTemplate = `{ } } }, - "/settings/time/option": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "加载系统可用时区", - "tags": [ - "System Setting" - ], - "summary": "Load time zone options", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/time/sync": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "系统时间同步", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Sync system time", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SyncTime" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "ntpSite" - ], - "formatEN": "sync system time [ntpSite]", - "formatZH": "系统时间同步[ntpSite]", - "paramKeys": [] - } - } - }, "/settings/update": { "post": { "security": [ @@ -10086,6 +10022,257 @@ const docTemplate = `{ } } }, + "/toolbox/device/base": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取设备基础信息", + "tags": [ + "Device" + ], + "summary": "Load device base info", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/dto.DeviceBaseInfo" + } + } + } + } + }, + "/toolbox/device/check/dns": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "检查系统 DNS 配置可用性", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "Check device DNS conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SettingUpdate" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/toolbox/device/conf": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取系统配置文件", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "load conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithName" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/toolbox/device/update/byconf": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "通过文件修改配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "Update device conf by file", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.UpdateByNameAndFile" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/toolbox/device/update/conf": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "修改系统参数", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "Update device", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SettingUpdate" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-panel-log": { + "BeforeFunctions": [], + "bodyKeys": [ + "key", + "value" + ], + "formatEN": "update device conf [key] =\u003e [value]", + "formatZH": "修改主机参数 [key] =\u003e [value]", + "paramKeys": [] + } + } + }, + "/toolbox/device/update/host": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "修改系统 hosts", + "tags": [ + "Device" + ], + "summary": "Update device hosts", + "responses": { + "200": { + "description": "OK" + } + }, + "x-panel-log": { + "BeforeFunctions": [], + "bodyKeys": [ + "key", + "value" + ], + "formatEN": "update device host [key] =\u003e [value]", + "formatZH": "修改主机 Host [key] =\u003e [value]", + "paramKeys": [] + } + } + }, + "/toolbox/device/update/passwd": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "修改系统密码", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "Update device passwd", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ChangePasswd" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/toolbox/device/zone/options": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取系统可用时区选项", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "list time zone options", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "Array" + } + } + } + } + }, "/toolbox/fail2ban/base": { "get": { "security": [ @@ -13094,6 +13281,17 @@ const docTemplate = `{ } } }, + "dto.ChangePasswd": { + "type": "object", + "properties": { + "passwd": { + "type": "string" + }, + "user": { + "type": "string" + } + } + }, "dto.ChangeRedisPass": { "type": "object", "required": [ @@ -14202,6 +14400,38 @@ const docTemplate = `{ } } }, + "dto.DeviceBaseInfo": { + "type": "object", + "properties": { + "dns": { + "type": "array", + "items": { + "type": "string" + } + }, + "hostname": { + "type": "string" + }, + "hosts": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.HostHelper" + } + }, + "localTime": { + "type": "string" + }, + "ntp": { + "type": "string" + }, + "timeZone": { + "type": "string" + }, + "user": { + "type": "string" + } + } + }, "dto.DiskInfo": { "type": "object", "properties": { @@ -14546,6 +14776,17 @@ const docTemplate = `{ } } }, + "dto.HostHelper": { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "ip": { + "type": "string" + } + } + }, "dto.HostOperate": { "type": "object", "required": [ @@ -16290,17 +16531,6 @@ const docTemplate = `{ } } }, - "dto.SyncTime": { - "type": "object", - "required": [ - "ntpSite" - ], - "properties": { - "ntpSite": { - "type": "string" - } - } - }, "dto.TreeChild": { "type": "object", "properties": { @@ -16320,6 +16550,17 @@ const docTemplate = `{ } } }, + "dto.UpdateByNameAndFile": { + "type": "object", + "properties": { + "file": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "dto.UpdateDescription": { "type": "object", "required": [ diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index 4570e39b6..c67779cf5 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -9899,70 +9899,6 @@ } } }, - "/settings/time/option": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "加载系统可用时区", - "tags": [ - "System Setting" - ], - "summary": "Load time zone options", - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/settings/time/sync": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "系统时间同步", - "consumes": [ - "application/json" - ], - "tags": [ - "System Setting" - ], - "summary": "Sync system time", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.SyncTime" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "string" - } - } - }, - "x-panel-log": { - "BeforeFunctions": [], - "bodyKeys": [ - "ntpSite" - ], - "formatEN": "sync system time [ntpSite]", - "formatZH": "系统时间同步[ntpSite]", - "paramKeys": [] - } - } - }, "/settings/update": { "post": { "security": [ @@ -10079,6 +10015,257 @@ } } }, + "/toolbox/device/base": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取设备基础信息", + "tags": [ + "Device" + ], + "summary": "Load device base info", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/dto.DeviceBaseInfo" + } + } + } + } + }, + "/toolbox/device/check/dns": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "检查系统 DNS 配置可用性", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "Check device DNS conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SettingUpdate" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/toolbox/device/conf": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取系统配置文件", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "load conf", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithName" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/toolbox/device/update/byconf": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "通过文件修改配置", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "Update device conf by file", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.UpdateByNameAndFile" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/toolbox/device/update/conf": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "修改系统参数", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "Update device", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SettingUpdate" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "x-panel-log": { + "BeforeFunctions": [], + "bodyKeys": [ + "key", + "value" + ], + "formatEN": "update device conf [key] =\u003e [value]", + "formatZH": "修改主机参数 [key] =\u003e [value]", + "paramKeys": [] + } + } + }, + "/toolbox/device/update/host": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "修改系统 hosts", + "tags": [ + "Device" + ], + "summary": "Update device hosts", + "responses": { + "200": { + "description": "OK" + } + }, + "x-panel-log": { + "BeforeFunctions": [], + "bodyKeys": [ + "key", + "value" + ], + "formatEN": "update device host [key] =\u003e [value]", + "formatZH": "修改主机 Host [key] =\u003e [value]", + "paramKeys": [] + } + } + }, + "/toolbox/device/update/passwd": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "修改系统密码", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "Update device passwd", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ChangePasswd" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/toolbox/device/zone/options": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取系统可用时区选项", + "consumes": [ + "application/json" + ], + "tags": [ + "Device" + ], + "summary": "list time zone options", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "Array" + } + } + } + } + }, "/toolbox/fail2ban/base": { "get": { "security": [ @@ -13087,6 +13274,17 @@ } } }, + "dto.ChangePasswd": { + "type": "object", + "properties": { + "passwd": { + "type": "string" + }, + "user": { + "type": "string" + } + } + }, "dto.ChangeRedisPass": { "type": "object", "required": [ @@ -14195,6 +14393,38 @@ } } }, + "dto.DeviceBaseInfo": { + "type": "object", + "properties": { + "dns": { + "type": "array", + "items": { + "type": "string" + } + }, + "hostname": { + "type": "string" + }, + "hosts": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.HostHelper" + } + }, + "localTime": { + "type": "string" + }, + "ntp": { + "type": "string" + }, + "timeZone": { + "type": "string" + }, + "user": { + "type": "string" + } + } + }, "dto.DiskInfo": { "type": "object", "properties": { @@ -14539,6 +14769,17 @@ } } }, + "dto.HostHelper": { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "ip": { + "type": "string" + } + } + }, "dto.HostOperate": { "type": "object", "required": [ @@ -16283,17 +16524,6 @@ } } }, - "dto.SyncTime": { - "type": "object", - "required": [ - "ntpSite" - ], - "properties": { - "ntpSite": { - "type": "string" - } - } - }, "dto.TreeChild": { "type": "object", "properties": { @@ -16313,6 +16543,17 @@ } } }, + "dto.UpdateByNameAndFile": { + "type": "object", + "properties": { + "file": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "dto.UpdateDescription": { "type": "object", "required": [ diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index dddad1fde..9499a6997 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -176,6 +176,13 @@ definitions: - groupID - id type: object + dto.ChangePasswd: + properties: + passwd: + type: string + user: + type: string + type: object dto.ChangeRedisPass: properties: value: @@ -923,6 +930,27 @@ definitions: - username - version type: object + dto.DeviceBaseInfo: + properties: + dns: + items: + type: string + type: array + hostname: + type: string + hosts: + items: + $ref: '#/definitions/dto.HostHelper' + type: array + localTime: + type: string + ntp: + type: string + timeZone: + type: string + user: + type: string + type: object dto.DiskInfo: properties: device: @@ -1158,6 +1186,13 @@ definitions: - port - user type: object + dto.HostHelper: + properties: + host: + type: string + ip: + type: string + type: object dto.HostOperate: properties: addr: @@ -2334,13 +2369,6 @@ definitions: required: - id type: object - dto.SyncTime: - properties: - ntpSite: - type: string - required: - - ntpSite - type: object dto.TreeChild: properties: id: @@ -2353,6 +2381,13 @@ definitions: file: type: string type: object + dto.UpdateByNameAndFile: + properties: + file: + type: string + name: + type: string + type: object dto.UpdateDescription: properties: description: @@ -10774,46 +10809,6 @@ paths: formatEN: update system ssl => [ssl] formatZH: 修改系统 ssl => [ssl] paramKeys: [] - /settings/time/option: - get: - description: 加载系统可用时区 - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Load time zone options - tags: - - System Setting - /settings/time/sync: - post: - consumes: - - application/json - description: 系统时间同步 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.SyncTime' - responses: - "200": - description: OK - schema: - type: string - security: - - ApiKeyAuth: [] - summary: Sync system time - tags: - - System Setting - x-panel-log: - BeforeFunctions: [] - bodyKeys: - - ntpSite - formatEN: sync system time [ntpSite] - formatZH: 系统时间同步[ntpSite] - paramKeys: [] /settings/update: post: consumes: @@ -10888,6 +10883,161 @@ paths: formatEN: upgrade service => [version] formatZH: 更新系统 => [version] paramKeys: [] + /toolbox/device/base: + get: + description: 获取设备基础信息 + responses: + "200": + description: OK + schema: + $ref: '#/definitions/dto.DeviceBaseInfo' + security: + - ApiKeyAuth: [] + summary: Load device base info + tags: + - Device + /toolbox/device/check/dns: + post: + consumes: + - application/json + description: 检查系统 DNS 配置可用性 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.SettingUpdate' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Check device DNS conf + tags: + - Device + /toolbox/device/conf: + post: + consumes: + - application/json + description: 获取系统配置文件 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperationWithName' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: load conf + tags: + - Device + /toolbox/device/update/byconf: + post: + consumes: + - application/json + description: 通过文件修改配置 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.UpdateByNameAndFile' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Update device conf by file + tags: + - Device + /toolbox/device/update/conf: + post: + consumes: + - application/json + description: 修改系统参数 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.SettingUpdate' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Update device + tags: + - Device + x-panel-log: + BeforeFunctions: [] + bodyKeys: + - key + - value + formatEN: update device conf [key] => [value] + formatZH: 修改主机参数 [key] => [value] + paramKeys: [] + /toolbox/device/update/host: + post: + description: 修改系统 hosts + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Update device hosts + tags: + - Device + x-panel-log: + BeforeFunctions: [] + bodyKeys: + - key + - value + formatEN: update device host [key] => [value] + formatZH: 修改主机 Host [key] => [value] + paramKeys: [] + /toolbox/device/update/passwd: + post: + consumes: + - application/json + description: 修改系统密码 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.ChangePasswd' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Update device passwd + tags: + - Device + /toolbox/device/zone/options: + get: + consumes: + - application/json + description: 获取系统可用时区选项 + responses: + "200": + description: OK + schema: + type: Array + security: + - ApiKeyAuth: [] + summary: list time zone options + tags: + - Device /toolbox/fail2ban/base: get: description: 获取 Fail2Ban 基础信息 diff --git a/frontend/src/api/interface/toolbox.ts b/frontend/src/api/interface/toolbox.ts index c4272d79c..cb793d35e 100644 --- a/frontend/src/api/interface/toolbox.ts +++ b/frontend/src/api/interface/toolbox.ts @@ -1,4 +1,22 @@ export namespace Toolbox { + export interface DeviceBaseInfo { + dns: Array; + hosts: Array; + hostname: string; + ntp: string; + user: string; + timeZone: string; + localTime: string; + } + export interface HostHelper { + ip: string; + host: string; + } + export interface TimeZoneOptions { + from: string; + zones: Array; + } + export interface Fail2banBaseInfo { isEnable: boolean; isActive: boolean; diff --git a/frontend/src/api/modules/toolbox.ts b/frontend/src/api/modules/toolbox.ts index 6da7ac86c..ced950fd7 100644 --- a/frontend/src/api/modules/toolbox.ts +++ b/frontend/src/api/modules/toolbox.ts @@ -1,6 +1,33 @@ import http from '@/api'; import { UpdateByFile } from '../interface'; import { Toolbox } from '../interface/toolbox'; +import { Base64 } from 'js-base64'; + +// device +export const getDeviceBase = () => { + return http.get(`/toolbox/device/base`); +}; +export const loadTimeZoneOptions = () => { + return http.get>(`/toolbox/device/zone/options`); +}; +export const updateDevice = (key: string, value: string) => { + return http.post(`/toolbox/device/update/conf`, { key: key, value: value }); +}; +export const updateDeviceHost = (param: Array) => { + return http.post(`/toolbox/device/update/host`, param); +}; +export const updateDevicePasswd = (user: string, passwd: string) => { + return http.post(`/toolbox/device/update/passwd`, { user: user, passwd: Base64.encode(passwd) }); +}; +export const updateDeviceByConf = (name: string, file: string) => { + return http.post(`/toolbox/device/update/byconf`, { name: name, file: file }); +}; +export const checkDNS = (key: string, value: string) => { + return http.post(`/toolbox/device/check/dns`, { key: key, value: value }); +}; +export const loadDeviceConf = (name: string) => { + return http.post(`/toolbox/device/conf`, { name: name }); +}; // fail2ban export const getFail2banBase = () => { diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 626a34432..fc7f6974d 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -873,6 +873,37 @@ const message = { emptyTerminal: 'No terminal is currently connected', }, toolbox: { + device: { + dnsHelper: 'Server Address Domain Resolution', + hostsHelper: 'Hostname Resolution', + hosts: 'Domain', + toolbox: 'Toolbox', + hostname: 'Hostname', + passwd: 'Host Password', + passwdHelper: 'Input characters cannot include $ and &', + timeZone: 'System Time Zone', + localTime: 'Server Time', + timeZoneChangeHelper: 'Modifying the system time zone requires restarting the service. Continue?', + timeZoneHelper: + 'Time zone modification depends on the timedatectl command. If not installed, the modification may fail.', + timeZoneCN: 'Beijing', + timeZoneAM: 'Los Angeles', + timeZoneNY: 'New York', + ntpALi: 'Alibaba', + ntpGoogle: 'Google', + syncSite: 'NTP Server', + hostnameHelper: + 'Hostname modification depends on the hostnamectl command. If not installed, the modification may fail.', + userHelper: + 'The username depends on the whoami command for retrieval. If not installed, retrieval may fail.', + passwordHelper: + 'Password modification depends on the chpasswd command. If not installed, the modification may fail.', + hostHelper: + 'There is an empty value in the provided content. Please check and try again after modification!', + dnsCheck: 'Test Availability', + dnsOK: 'DNS configuration information is available!', + dnsTestFailed: 'DNS configuration information is not available. Please modify and try again!', + }, fail2ban: { noFail2ban: 'Fail2Ban service not detected, please refer to the official documentation for installation', unActive: 'The Fail2Ban service is not enabled at present, please enable it first!', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 60c4b6c6d..7a8a19c8d 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -837,6 +837,32 @@ const message = { emptyTerminal: '暫無終端連接', }, toolbox: { + device: { + dnsHelper: '伺服器地址域名解析', + hostsHelper: '主機名解析', + hosts: '域名', + toolbox: '工具箱', + hostname: '主機名', + passwd: '主機密碼', + passwdHelper: '輸入的字符不能包含 $ 和 &', + timeZone: '系統時區', + localTime: '伺服器時間', + timeZoneChangeHelper: '修改系統時區需要重新啟動服務,是否繼續?', + timeZoneHelper: '時區修改依賴於 timedatectl 命令,如未安裝可能導致修改失敗', + timeZoneCN: '北京', + timeZoneAM: '洛杉磯', + timeZoneNY: '紐約', + ntpALi: '阿里', + ntpGoogle: '谷歌', + syncSite: 'NTP 伺服器', + hostnameHelper: '主機名修改依賴於 hostnamectl 命令,如未安裝可能導致修改失敗', + userHelper: '用戶名依賴於 whoami 命令獲取,如未安裝可能導致獲取失敗。', + passwordHelper: '密碼修改依賴於 chpasswd 命令,如未安裝可能導致修改失敗', + hostHelper: '填寫的內容中存在空值,請檢查修改後重試!', + dnsCheck: '測試可用性', + dnsOK: 'DNS 配置信息可用!', + dnsTestFailed: 'DNS 配置信息不可用,請修改後重試!', + }, fail2ban: { noFail2ban: '未檢測到 Fail2Ban 服務,請參考官方文檔進行安裝', unActive: '當前未開啟 Fail2Ban 服務,請先開啟!', @@ -1055,16 +1081,6 @@ const message = { systemIP: '服務器地址', systemIPWarning: '當前未設置服務器地址,請先在面板設置中設置!', defaultNetwork: '默認網卡', - syncTime: '服務器時間', - timeZone: '系統時區', - timeZoneChangeHelper: '系統時區修改需要重啟服務,是否繼續?', - timeZoneHelper: '時區修改依賴於系統 timedatectl 服務,重啟 1Panel 服務後生效。', - timeZoneCN: '北京', - timeZoneAM: '洛杉磯', - timeZoneNY: '紐約', - ntpALi: '阿裏', - ntpGoogle: '谷歌', - syncSite: 'NTP 服務器', syncSiteHelper: '該操作將使用 {0} 作為源進行系統時間同步,是否繼續?', changePassword: '密碼修改', oldPassword: '原密碼', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index e74ee472b..8047692e1 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -838,6 +838,32 @@ const message = { emptyTerminal: '暂无终端连接', }, toolbox: { + device: { + dnsHelper: '服务器地址域名解析', + hostsHelper: '主机名解析', + hosts: '域名', + toolbox: '工具箱', + hostname: '主机名', + passwd: '主机密码', + passwdHelper: '输入字符不能包含 $ 和 &', + timeZone: '系统时区', + localTime: '服务器时间', + timeZoneChangeHelper: '系统时区修改需要重启服务,是否继续?', + timeZoneHelper: '时区修改依赖于 timedatectl 命令,如未安装可能导致修改失败', + timeZoneCN: '北京', + timeZoneAM: '洛杉矶', + timeZoneNY: '纽约', + ntpALi: '阿里', + ntpGoogle: '谷歌', + syncSite: 'NTP 服务器', + hostnameHelper: '主机名修改依赖于 hostnamectl 命令,如未安装可能导致修改失败', + userHelper: '用户名依赖于 whoami 命令获取,如未安装可能导致获取失败。', + passwordHelper: '密码修改依赖于 chpasswd 命令,如未安装可能导致修改失败', + hostHelper: '填写的内容中存在空值,请检查修改后重试!', + dnsCheck: '测试可用性', + dnsOK: 'DNS 配置信息可用!', + dnsTestFailed: 'DNS 配置信息不可用,请修改后重试!', + }, fail2ban: { noFail2ban: '未检测到 Fail2Ban 服务,请参考官方文档进行安装', unActive: '当前未开启 Fail2Ban 服务,请先开启!', @@ -1056,16 +1082,6 @@ const message = { systemIP: '服务器地址', systemIPWarning: '当前未设置服务器地址,请先在面板设置中设置!', defaultNetwork: '默认网卡', - syncTime: '服务器时间', - timeZone: '系统时区', - timeZoneChangeHelper: '系统时区修改需要重启服务,是否继续?', - timeZoneHelper: '时区修改依赖于系统 timedatectl 服务,重启 1Panel 服务后生效。', - timeZoneCN: '北京', - timeZoneAM: '洛杉矶', - timeZoneNY: '纽约', - ntpALi: '阿里', - ntpGoogle: '谷歌', - syncSite: 'NTP 服务器', syncSiteHelper: '该操作将使用 {0} 作为源进行系统时间同步,是否继续?', changePassword: '密码修改', oldPassword: '原密码', diff --git a/frontend/src/routers/modules/toolbox.ts b/frontend/src/routers/modules/toolbox.ts index e56c61fa0..2da2d05c3 100644 --- a/frontend/src/routers/modules/toolbox.ts +++ b/frontend/src/routers/modules/toolbox.ts @@ -13,10 +13,20 @@ const toolboxRouter = { { path: '/toolbox', name: 'Toolbox', - redirect: '/toolbox/supervisor', + redirect: '/toolbox/device', component: () => import('@/views/toolbox/index.vue'), meta: {}, children: [ + { + path: 'device', + name: 'Device', + component: () => import('@/views/toolbox/device/index.vue'), + hidden: true, + meta: { + activeMenu: '/toolbox', + requiresAuth: false, + }, + }, { path: 'supervisor', name: 'Supervisor', diff --git a/frontend/src/views/setting/panel/index.vue b/frontend/src/views/setting/panel/index.vue index 5ddf9c83a..fd772c051 100644 --- a/frontend/src/views/setting/panel/index.vue +++ b/frontend/src/views/setting/panel/index.vue @@ -93,24 +93,6 @@ - - - - - - - - - -