chore: 清理代码

This commit is contained in:
耗子
2026-08-15 07:30:59 +08:00
parent dbc44f1d17
commit 2bde7f7a73
110 changed files with 291 additions and 353 deletions
+2 -2
View File
@@ -42,7 +42,7 @@ func (s *App) Status() string {
}
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
config, err := io.Read(fmt.Sprintf("%s/server/apache/conf/httpd.conf", app.Root))
config, err := io.Read(app.Root + "/server/apache/conf/httpd.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -58,7 +58,7 @@ func (s *App) SaveConfig(w http.ResponseWriter, r *http.Request) {
return
}
if err = io.Write(fmt.Sprintf("%s/server/apache/conf/httpd.conf", app.Root), req.Config, 0600); err != nil {
if err = io.Write(app.Root+"/server/apache/conf/httpd.conf", req.Config, 0600); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
+4 -3
View File
@@ -2,6 +2,7 @@ package clickhouse
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"net/http"
"strings"
@@ -218,7 +219,7 @@ func (s *App) SetDefaultPassword(w http.ResponseWriter, r *http.Request) {
// 计算 SHA256 哈希
hash := sha256.Sum256([]byte(req.Password))
hexHash := fmt.Sprintf("%x", hash)
hexHash := hex.EncodeToString(hash[:])
// 读取 users.d/default.yaml 并更新密码
raw, _ := io.Read(s.usersConfigPath())
@@ -262,12 +263,12 @@ func (s *App) SetDefaultPassword(w http.ResponseWriter, r *http.Request) {
// configPath 返回主配置文件路径
func (s *App) configPath() string {
return fmt.Sprintf("%s/server/clickhouse/config/config.yaml", app.Root)
return app.Root + "/server/clickhouse/config/config.yaml"
}
// usersConfigPath 返回用户密码配置文件路径(users.d/ 由 ConfigProcessor 自动合并到 users.yaml
func (s *App) usersConfigPath() string {
return fmt.Sprintf("%s/server/clickhouse/config/users.d/default.yaml", app.Root)
return app.Root + "/server/clickhouse/config/users.d/default.yaml"
}
// getPort 从配置中获取 HTTP 端口
+3 -3
View File
@@ -202,17 +202,17 @@ func (s *App) UpdateConfigTune(w http.ResponseWriter, r *http.Request) {
// configPath 返回配置文件路径
func (s *App) configPath() string {
return fmt.Sprintf("%s/server/elasticsearch/config/elasticsearch.yml", app.Root)
return app.Root + "/server/elasticsearch/config/elasticsearch.yml"
}
// jvmOptionsPath 返回 JVM 选项文件路径
func (s *App) jvmOptionsPath() string {
return fmt.Sprintf("%s/server/elasticsearch/config/jvm.options", app.Root)
return app.Root + "/server/elasticsearch/config/jvm.options"
}
// jvmHeapOptionsPath 返回 JVM 堆内存配置文件路径(ES 9.x 推荐方式)
func (s *App) jvmHeapOptionsPath() string {
return fmt.Sprintf("%s/server/elasticsearch/config/jvm.options.d/heap.options", app.Root)
return app.Root + "/server/elasticsearch/config/jvm.options.d/heap.options"
}
// getPort 从配置中获取 HTTP 端口
+4 -2
View File
@@ -1,9 +1,9 @@
package fail2ban
import (
"fmt"
"net/http"
"regexp"
"strconv"
"strings"
"github.com/go-chi/chi/v5"
@@ -126,11 +126,13 @@ func (s *App) Create(w http.ResponseWriter, r *http.Request) {
return
}
var ports string
var portsSb strings.Builder
for _, listen := range website.Listens {
if port, err := cast.ToIntE(listen.Address); err == nil {
ports += fmt.Sprintf("%d", port) + ","
portsSb.WriteString(strconv.Itoa(port) + ",")
}
}
ports += portsSb.String()
ports = strings.TrimSuffix(ports, ",")
rule := `
+9 -8
View File
@@ -114,18 +114,19 @@ func (s *App) UpdateUser(w http.ResponseWriter, r *http.Request) {
hasGroup := groupRegex.MatchString(content)
// 替换或添加 User 和 Group 配置
if hasUser && hasGroup {
switch {
case hasUser && hasGroup:
// 两者都存在,分别替换
content = userRegex.ReplaceAllString(content, fmt.Sprintf("User=%s", req.User))
content = groupRegex.ReplaceAllString(content, fmt.Sprintf("Group=%s", req.Group))
} else if hasUser && !hasGroup {
content = userRegex.ReplaceAllString(content, "User="+req.User)
content = groupRegex.ReplaceAllString(content, "Group="+req.Group)
case hasUser:
// 只有 User,替换 User 并添加 Group
content = userRegex.ReplaceAllString(content, fmt.Sprintf("User=%s\nGroup=%s", req.User, req.Group))
} else if !hasUser && hasGroup {
case hasGroup:
// 只有 Group,添加 User 并替换 Group
content = serviceRegex.ReplaceAllString(content, fmt.Sprintf("[Service]\nUser=%s", req.User))
content = groupRegex.ReplaceAllString(content, fmt.Sprintf("Group=%s", req.Group))
} else {
content = serviceRegex.ReplaceAllString(content, "[Service]\nUser="+req.User)
content = groupRegex.ReplaceAllString(content, "Group="+req.Group)
default:
// 两者都不存在,在 [Service] 后添加两者
content = serviceRegex.ReplaceAllString(content, fmt.Sprintf("[Service]\nUser=%s\nGroup=%s", req.User, req.Group))
}
+2 -3
View File
@@ -1,7 +1,6 @@
package gitea
import (
"fmt"
"net/http"
"github.com/go-chi/chi/v5"
@@ -30,7 +29,7 @@ func (s *App) Status() string {
}
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
config, _ := io.Read(fmt.Sprintf("%s/server/gitea/app.ini", app.Root))
config, _ := io.Read(app.Root + "/server/gitea/app.ini")
service.Success(w, config)
}
@@ -41,7 +40,7 @@ func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
return
}
if err = io.Write(fmt.Sprintf("%s/server/gitea/app.ini", app.Root), req.Config, 0644); err != nil {
if err = io.Write(app.Root+"/server/gitea/app.ini", req.Config, 0644); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
+2 -2
View File
@@ -328,7 +328,7 @@ func (s *App) DeleteDataSource(w http.ResponseWriter, r *http.Request) {
// configPath 返回 Grafana 主配置文件路径
func (s *App) configPath() string {
return fmt.Sprintf("%s/server/grafana/conf/defaults.ini", app.Root)
return app.Root + "/server/grafana/conf/defaults.ini"
}
// getINIValue 从 INI 配置中获取指定 section 下的 key 值
@@ -436,7 +436,7 @@ func (s *App) setINIValue(content string, section string, key string, value stri
// datasourcePath 返回 provisioning 数据源文件路径
func (s *App) datasourcePath() string {
return fmt.Sprintf("%s/server/grafana/conf/provisioning/datasources/panel.yml", app.Root)
return app.Root + "/server/grafana/conf/provisioning/datasources/panel.yml"
}
// readDatasources 读取 provisioning 文件
+2 -2
View File
@@ -150,12 +150,12 @@ func (s *App) UpdateConfigTune(w http.ResponseWriter, r *http.Request) {
// configPath 返回配置文件路径
func (s *App) configPath() string {
return fmt.Sprintf("%s/server/kafka/config/server.properties", app.Root)
return app.Root + "/server/kafka/config/server.properties"
}
// heapEnvPath 返回 JVM 堆内存配置文件路径
func (s *App) heapEnvPath() string {
return fmt.Sprintf("%s/server/kafka/config/heap.env", app.Root)
return app.Root + "/server/kafka/config/heap.env"
}
// getPropertiesValue 从 properties 内容中获取指定键的值
+1 -2
View File
@@ -2,7 +2,6 @@ package mongodb
import (
"encoding/json"
"fmt"
"net/http"
"strings"
@@ -240,7 +239,7 @@ func (s *App) SetAdminPassword(w http.ResponseWriter, r *http.Request) {
// configPath 返回配置文件路径
func (s *App) configPath() string {
return fmt.Sprintf("%s/server/mongodb/mongod.conf", app.Root)
return app.Root + "/server/mongodb/mongod.conf"
}
// getYAMLValue 获取嵌套 YAML 值,支持 dot notation
+1 -1
View File
@@ -199,7 +199,7 @@ func (s *App) Load(w http.ResponseWriter, r *http.Request) {
// SlowLog 获取慢查询日志
func (s *App) SlowLog(w http.ResponseWriter, r *http.Request) {
service.Success(w, fmt.Sprintf("%s/server/mysql/mysql-slow.log", app.Root))
service.Success(w, app.Root+"/server/mysql/mysql-slow.log")
}
// GetRootPassword 获取root密码
+4 -4
View File
@@ -57,7 +57,7 @@ func (s *App) Status() string {
}
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
config, err := io.Read(fmt.Sprintf("%s/server/nginx/conf/nginx.conf", app.Root))
config, err := io.Read(app.Root + "/server/nginx/conf/nginx.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -73,7 +73,7 @@ func (s *App) SaveConfig(w http.ResponseWriter, r *http.Request) {
return
}
if err = io.Write(fmt.Sprintf("%s/server/nginx/conf/nginx.conf", app.Root), req.Config, 0600); err != nil {
if err = io.Write(app.Root+"/server/nginx/conf/nginx.conf", req.Config, 0600); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -178,7 +178,7 @@ func (s *App) Load(w http.ResponseWriter, r *http.Request) {
// GetConfigTune 获取 Nginx 配置调整参数
func (s *App) GetConfigTune(w http.ResponseWriter, r *http.Request) {
config, err := io.Read(fmt.Sprintf("%s/server/nginx/conf/nginx.conf", app.Root))
config, err := io.Read(app.Root + "/server/nginx/conf/nginx.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -226,7 +226,7 @@ func (s *App) UpdateConfigTune(w http.ResponseWriter, r *http.Request) {
return
}
confPath := fmt.Sprintf("%s/server/nginx/conf/nginx.conf", app.Root)
confPath := app.Root + "/server/nginx/conf/nginx.conf"
config, err := io.Read(confPath)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
+10 -9
View File
@@ -1,6 +1,7 @@
package nginx
import (
"errors"
"fmt"
"net/http"
"os"
@@ -36,7 +37,7 @@ func (s *App) CreateStreamServer(w http.ResponseWriter, r *http.Request) {
return
}
configPath := filepath.Join(s.streamDir(), fmt.Sprintf("%s.conf", req.Name))
configPath := filepath.Join(s.streamDir(), req.Name+".conf")
if _, statErr := os.Stat(configPath); statErr == nil {
service.Error(w, http.StatusConflict, s.t.Get("stream server config already exists: %s", req.Name))
return
@@ -70,7 +71,7 @@ func (s *App) UpdateStreamServer(w http.ResponseWriter, r *http.Request) {
return
}
configPath := filepath.Join(s.streamDir(), fmt.Sprintf("%s.conf", name))
configPath := filepath.Join(s.streamDir(), name+".conf")
if _, statErr := os.Stat(configPath); os.IsNotExist(statErr) {
service.Error(w, http.StatusNotFound, s.t.Get("stream server not found: %s", name))
return
@@ -78,7 +79,7 @@ func (s *App) UpdateStreamServer(w http.ResponseWriter, r *http.Request) {
newConfigPath := configPath
if req.Name != name {
newConfigPath = filepath.Join(s.streamDir(), fmt.Sprintf("%s.conf", req.Name))
newConfigPath = filepath.Join(s.streamDir(), req.Name+".conf")
if _, statErr := os.Stat(newConfigPath); statErr == nil {
service.Error(w, http.StatusConflict, s.t.Get("stream server config already exists: %s", req.Name))
return
@@ -110,7 +111,7 @@ func (s *App) DeleteStreamServer(w http.ResponseWriter, r *http.Request) {
return
}
configPath := filepath.Join(s.streamDir(), fmt.Sprintf("%s.conf", name))
configPath := filepath.Join(s.streamDir(), name+".conf")
if _, statErr := os.Stat(configPath); os.IsNotExist(statErr) {
service.Error(w, http.StatusNotFound, s.t.Get("stream server not found: %s", name))
return
@@ -411,24 +412,24 @@ func (s *App) parseStreamUpstreamFile(filePath string, expectedName string) (*St
cfg := p.Config()
if cfg == nil || cfg.Block == nil {
return nil, fmt.Errorf("invalid config")
return nil, errors.New("invalid config")
}
// 查找 upstream 块
upstreamDirectives := cfg.Block.FindDirectives("upstream")
if len(upstreamDirectives) == 0 {
return nil, fmt.Errorf("no upstream block found")
return nil, errors.New("no upstream block found")
}
upstreamDir := upstreamDirectives[0]
params := upstreamDir.GetParameters()
if len(params) == 0 {
return nil, fmt.Errorf("upstream name not found")
return nil, errors.New("upstream name not found")
}
name := params[0].Value
if expectedName != "" && name != expectedName {
return nil, fmt.Errorf("upstream name mismatch")
return nil, errors.New("upstream name mismatch")
}
upstream := &StreamUpstream{
@@ -439,7 +440,7 @@ func (s *App) parseStreamUpstreamFile(filePath string, expectedName string) (*St
upstreamBlock := upstreamDir.GetBlock()
if upstreamBlock == nil {
return nil, fmt.Errorf("upstream block is empty")
return nil, errors.New("upstream block is empty")
}
// 解析 upstream 块中的指令
+2 -2
View File
@@ -194,11 +194,11 @@ func (s *App) UpdateConfigTune(w http.ResponseWriter, r *http.Request) {
}
func (s *App) configPath() string {
return fmt.Sprintf("%s/server/opensearch/config/opensearch.yml", app.Root)
return app.Root + "/server/opensearch/config/opensearch.yml"
}
func (s *App) jvmOptionsPath() string {
return fmt.Sprintf("%s/server/opensearch/config/jvm.options", app.Root)
return app.Root + "/server/opensearch/config/jvm.options"
}
func (s *App) getPort() string {
+6 -6
View File
@@ -86,12 +86,12 @@ func (s *App) Status() string {
}
func (s *App) path() string {
return fmt.Sprintf("%s/server/pgadmin", app.Root)
return app.Root + "/server/pgadmin"
}
// port 从 systemd 环境文件中解析监听端口
func (s *App) port() (uint, error) {
conf, err := io.Read(fmt.Sprintf("%s/pgadmin.conf", s.path()))
conf, err := io.Read(s.path() + "/pgadmin.conf")
if err != nil {
return 0, err
}
@@ -105,7 +105,7 @@ func (s *App) port() (uint, error) {
// credential 读取安装时生成的初始凭据(邮箱与密码)
func (s *App) credential() (string, string) {
raw, err := io.Read(fmt.Sprintf("%s/credential", s.path()))
raw, err := io.Read(s.path() + "/credential")
if err != nil {
return "", ""
}
@@ -139,7 +139,7 @@ func (s *App) UpdatePort(w http.ResponseWriter, r *http.Request) {
return
}
conf := fmt.Sprintf("%s/pgadmin.conf", s.path())
conf := s.path() + "/pgadmin.conf"
content, err := io.Read(conf)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
@@ -507,7 +507,7 @@ func (s *App) UpdateUsername(w http.ResponseWriter, r *http.Request) {
}
// 更新凭据文件,下次登录按新账号重新同步
if err = io.Write(fmt.Sprintf("%s/credential", s.path()), req.Username+"\n"+password+"\n", 0600); err != nil {
if err = io.Write(s.path()+"/credential", req.Username+"\n"+password+"\n", 0600); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -539,7 +539,7 @@ func (s *App) ResetPassword(w http.ResponseWriter, r *http.Request) {
return
}
if err = io.Write(fmt.Sprintf("%s/credential", s.path()), email+"\n"+req.Password+"\n", 0600); err != nil {
if err = io.Write(s.path()+"/credential", email+"\n"+req.Password+"\n", 0600); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
+6 -6
View File
@@ -59,7 +59,7 @@ func (s *App) Status() string {
// info 获取 phpMyAdmin 的访问目录与端口
func (s *App) info() (string, int, error) {
files, err := os.ReadDir(fmt.Sprintf("%s/server/phpmyadmin", app.Root))
files, err := os.ReadDir(app.Root + "/server/phpmyadmin")
if err != nil {
return "", 0, errors.New(s.t.Get("phpMyAdmin directory not found"))
}
@@ -74,7 +74,7 @@ func (s *App) info() (string, int, error) {
return "", 0, errors.New(s.t.Get("phpMyAdmin directory not found"))
}
conf, err := io.Read(fmt.Sprintf("%s/sites/phpmyadmin/config/nginx.conf", app.Root))
conf, err := io.Read(app.Root + "/sites/phpmyadmin/config/nginx.conf")
if err != nil {
return "", 0, err
}
@@ -248,13 +248,13 @@ func (s *App) UpdatePort(w http.ResponseWriter, r *http.Request) {
return
}
conf, err := io.Read(fmt.Sprintf("%s/sites/phpmyadmin/config/nginx.conf", app.Root))
conf, err := io.Read(app.Root + "/sites/phpmyadmin/config/nginx.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
conf = regexp.MustCompile(`listen\s+(\d+);`).ReplaceAllString(conf, "listen "+cast.ToString(req.Port)+";")
if err = io.Write(fmt.Sprintf("%s/sites/phpmyadmin/config/nginx.conf", app.Root), conf, 0600); err != nil {
if err = io.Write(app.Root+"/sites/phpmyadmin/config/nginx.conf", conf, 0600); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -282,7 +282,7 @@ func (s *App) UpdatePort(w http.ResponseWriter, r *http.Request) {
}
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
config, err := io.Read(fmt.Sprintf("%s/sites/phpmyadmin/config/nginx.conf", app.Root))
config, err := io.Read(app.Root + "/sites/phpmyadmin/config/nginx.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -298,7 +298,7 @@ func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
return
}
if err = io.Write(fmt.Sprintf("%s/sites/phpmyadmin/config/nginx.conf", app.Root), req.Config, 0600); err != nil {
if err = io.Write(app.Root+"/sites/phpmyadmin/config/nginx.conf", req.Config, 0600); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
+4 -5
View File
@@ -1,7 +1,6 @@
package postgresql
import (
"fmt"
"net/http"
"os"
"path/filepath"
@@ -93,7 +92,7 @@ func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
// GetUserConfig 获取用户配置
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))
config, err := io.Read(app.Root + "/server/postgresql/data/pg_hba.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -110,7 +109,7 @@ func (s *App) UpdateUserConfig(w http.ResponseWriter, r *http.Request) {
return
}
if err = io.Write(fmt.Sprintf("%s/server/postgresql/data/pg_hba.conf", app.Root), req.Config, 0644); err != nil {
if err = io.Write(app.Root+"/server/postgresql/data/pg_hba.conf", req.Config, 0644); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -183,7 +182,7 @@ func (s *App) Load(w http.ResponseWriter, r *http.Request) {
// Log 获取应用日志路径列表
func (s *App) Log(w http.ResponseWriter, r *http.Request) {
paths, err := filepath.Glob(fmt.Sprintf("%s/server/postgresql/logs/postgresql-*.log", app.Root))
paths, err := filepath.Glob(app.Root + "/server/postgresql/logs/postgresql-*.log")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -337,7 +336,7 @@ func (s *App) UpdateConfigTune(w http.ResponseWriter, r *http.Request) {
}
func (s *App) configPath() string {
return fmt.Sprintf("%s/server/postgresql/data/postgresql.conf", app.Root)
return app.Root + "/server/postgresql/data/postgresql.conf"
}
// getPort 读取 PostgreSQL 端口
+6 -6
View File
@@ -105,7 +105,7 @@ func (s *App) Load(w http.ResponseWriter, r *http.Request) {
}
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
conf, _ := io.Read(fmt.Sprintf("%s/server/prometheus/prometheus.yml", app.Root))
conf, _ := io.Read(app.Root + "/server/prometheus/prometheus.yml")
service.Success(w, conf)
}
@@ -116,7 +116,7 @@ func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
return
}
if err = io.Write(fmt.Sprintf("%s/server/prometheus/prometheus.yml", app.Root), req.Config, 0644); err != nil {
if err = io.Write(app.Root+"/server/prometheus/prometheus.yml", req.Config, 0644); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -131,7 +131,7 @@ func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
// GetConfigTune 获取 Prometheus 全局配置调整参数
func (s *App) GetConfigTune(w http.ResponseWriter, r *http.Request) {
conf, _ := io.Read(fmt.Sprintf("%s/server/prometheus/prometheus.yml", app.Root))
conf, _ := io.Read(app.Root + "/server/prometheus/prometheus.yml")
var cfg struct {
Global struct {
@@ -159,7 +159,7 @@ func (s *App) UpdateConfigTune(w http.ResponseWriter, r *http.Request) {
return
}
confPath := fmt.Sprintf("%s/server/prometheus/prometheus.yml", app.Root)
confPath := app.Root + "/server/prometheus/prometheus.yml"
raw, _ := io.Read(confPath)
var cfg map[string]any
@@ -205,7 +205,7 @@ func (s *App) UpdateConfigTune(w http.ResponseWriter, r *http.Request) {
// GetAlertmanagerConfig 获取 Alertmanager 配置
func (s *App) GetAlertmanagerConfig(w http.ResponseWriter, r *http.Request) {
conf, _ := io.Read(fmt.Sprintf("%s/server/prometheus/alertmanager/alertmanager.yml", app.Root))
conf, _ := io.Read(app.Root + "/server/prometheus/alertmanager/alertmanager.yml")
service.Success(w, conf)
}
@@ -217,7 +217,7 @@ func (s *App) UpdateAlertmanagerConfig(w http.ResponseWriter, r *http.Request) {
return
}
if err = io.Write(fmt.Sprintf("%s/server/prometheus/alertmanager/alertmanager.yml", app.Root), req.Config, 0644); err != nil {
if err = io.Write(app.Root+"/server/prometheus/alertmanager/alertmanager.yml", req.Config, 0644); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
+4 -4
View File
@@ -148,7 +148,7 @@ func (s *App) ChangePassword(w http.ResponseWriter, r *http.Request) {
// GetPort 获取端口
func (s *App) GetPort(w http.ResponseWriter, r *http.Request) {
config, err := io.Read(fmt.Sprintf("%s/server/pure-ftpd/etc/pure-ftpd.conf", app.Root))
config, err := io.Read(app.Root + "/server/pure-ftpd/etc/pure-ftpd.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to get port: %v", err))
return
@@ -171,7 +171,7 @@ func (s *App) UpdatePort(w http.ResponseWriter, r *http.Request) {
return
}
confPath := fmt.Sprintf("%s/server/pure-ftpd/etc/pure-ftpd.conf", app.Root)
confPath := app.Root + "/server/pure-ftpd/etc/pure-ftpd.conf"
config, err := io.Read(confPath)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
@@ -206,7 +206,7 @@ func (s *App) UpdatePort(w http.ResponseWriter, r *http.Request) {
// GetConfigTune 获取 Pure-FTPd 配置调整参数
func (s *App) GetConfigTune(w http.ResponseWriter, r *http.Request) {
config, err := io.Read(fmt.Sprintf("%s/server/pure-ftpd/etc/pure-ftpd.conf", app.Root))
config, err := io.Read(app.Root + "/server/pure-ftpd/etc/pure-ftpd.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -234,7 +234,7 @@ func (s *App) UpdateConfigTune(w http.ResponseWriter, r *http.Request) {
return
}
confPath := fmt.Sprintf("%s/server/pure-ftpd/etc/pure-ftpd.conf", app.Root)
confPath := app.Root + "/server/pure-ftpd/etc/pure-ftpd.conf"
config, err := io.Read(confPath)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
+5 -6
View File
@@ -1,7 +1,6 @@
package redis
import (
"fmt"
"net/http"
"regexp"
"strings"
@@ -59,7 +58,7 @@ func (s *App) Load(w http.ResponseWriter, r *http.Request) {
// 检查 Redis 密码
withPassword := ""
config, err := io.Read(fmt.Sprintf("%s/server/redis/redis.conf", app.Root))
config, err := io.Read(app.Root + "/server/redis/redis.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -104,7 +103,7 @@ func (s *App) Load(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))
config, err := io.Read(app.Root + "/server/redis/redis.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -120,7 +119,7 @@ func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
return
}
if err = io.Write(fmt.Sprintf("%s/server/redis/redis.conf", app.Root), req.Config, 0644); err != nil {
if err = io.Write(app.Root+"/server/redis/redis.conf", req.Config, 0644); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -135,7 +134,7 @@ func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
// GetConfigTune 获取 Redis 配置调整参数
func (s *App) GetConfigTune(w http.ResponseWriter, r *http.Request) {
config, err := io.Read(fmt.Sprintf("%s/server/redis/redis.conf", app.Root))
config, err := io.Read(app.Root + "/server/redis/redis.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -165,7 +164,7 @@ func (s *App) UpdateConfigTune(w http.ResponseWriter, r *http.Request) {
return
}
confPath := fmt.Sprintf("%s/server/redis/redis.conf", app.Root)
confPath := app.Root + "/server/redis/redis.conf"
config, err := io.Read(confPath)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
+2 -2
View File
@@ -175,12 +175,12 @@ func (s *App) restartServices() error {
// configPath 返回 broker 配置文件路径
func (s *App) configPath() string {
return fmt.Sprintf("%s/server/rocketmq/conf/broker.conf", app.Root)
return app.Root + "/server/rocketmq/conf/broker.conf"
}
// heapEnvPath 返回 JVM 堆内存配置文件路径
func (s *App) heapEnvPath() string {
return fmt.Sprintf("%s/server/rocketmq/conf/heap.env", app.Root)
return app.Root + "/server/rocketmq/conf/heap.env"
}
// getPropertiesValue 从 properties 内容中获取指定键的值
+5 -6
View File
@@ -1,7 +1,6 @@
package valkey
import (
"fmt"
"net/http"
"regexp"
"strings"
@@ -59,7 +58,7 @@ func (s *App) Load(w http.ResponseWriter, r *http.Request) {
// 检查 Valkey 密码
withPassword := ""
config, err := io.Read(fmt.Sprintf("%s/server/valkey/valkey.conf", app.Root))
config, err := io.Read(app.Root + "/server/valkey/valkey.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -104,7 +103,7 @@ func (s *App) Load(w http.ResponseWriter, r *http.Request) {
}
func (s *App) GetConfig(w http.ResponseWriter, r *http.Request) {
config, err := io.Read(fmt.Sprintf("%s/server/valkey/valkey.conf", app.Root))
config, err := io.Read(app.Root + "/server/valkey/valkey.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -120,7 +119,7 @@ func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
return
}
if err = io.Write(fmt.Sprintf("%s/server/valkey/valkey.conf", app.Root), req.Config, 0644); err != nil {
if err = io.Write(app.Root+"/server/valkey/valkey.conf", req.Config, 0644); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -135,7 +134,7 @@ func (s *App) UpdateConfig(w http.ResponseWriter, r *http.Request) {
// GetConfigTune 获取 Valkey 配置调整参数
func (s *App) GetConfigTune(w http.ResponseWriter, r *http.Request) {
config, err := io.Read(fmt.Sprintf("%s/server/valkey/valkey.conf", app.Root))
config, err := io.Read(app.Root + "/server/valkey/valkey.conf")
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -165,7 +164,7 @@ func (s *App) UpdateConfigTune(w http.ResponseWriter, r *http.Request) {
return
}
confPath := fmt.Sprintf("%s/server/valkey/valkey.conf", app.Root)
confPath := app.Root + "/server/valkey/valkey.conf"
config, err := io.Read(confPath)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
+5 -5
View File
@@ -85,8 +85,8 @@ func (uc *CertUsecase) Get(id uint) (*Cert, error) {
return uc.repo.Get(id)
}
func (uc *CertUsecase) GetByWebsite(WebsiteID uint) (*Cert, error) {
return uc.repo.GetByWebsite(WebsiteID)
func (uc *CertUsecase) GetByWebsite(websiteID uint) (*Cert, error) {
return uc.repo.GetByWebsite(websiteID)
}
func (uc *CertUsecase) Upload(ctx context.Context, req *request.CertUpload) (*Cert, error) {
@@ -394,8 +394,8 @@ func (uc *CertUsecase) RefreshRenewalInfo(id uint) (mholtacme.RenewalInfo, error
return renewInfo, nil
}
func (uc *CertUsecase) Deploy(ID, WebsiteID uint, enableHTTPS bool) error {
cert, err := uc.repo.Get(ID)
func (uc *CertUsecase) Deploy(id, websiteID uint, enableHTTPS bool) error {
cert, err := uc.repo.Get(id)
if err != nil {
return err
}
@@ -404,7 +404,7 @@ func (uc *CertUsecase) Deploy(ID, WebsiteID uint, enableHTTPS bool) error {
return errors.New(uc.t.Get("this certificate has not been obtained successfully and cannot be deployed"))
}
website, err := uc.repo.LoadWebsite(WebsiteID)
website, err := uc.repo.LoadWebsite(websiteID)
if err != nil {
return err
}
+1 -2
View File
@@ -2,7 +2,6 @@ package biz
import (
"context"
"fmt"
"strings"
"github.com/spf13/cast"
@@ -28,7 +27,7 @@ func containerSock(setting SettingRepo) string {
}
// 自动补全 scheme
if !strings.Contains(sock, "://") {
sock = fmt.Sprintf("unix://%s", sock)
sock = "unix://" + sock
}
return sock
}
+2 -2
View File
@@ -2,7 +2,7 @@ package biz
import (
"context"
"fmt"
"errors"
"log/slog"
)
@@ -31,7 +31,7 @@ func (uc *SafeUsecase) UpdatePingStatus(ctx context.Context, status bool) error
return err
}
if !running {
return fmt.Errorf("failed to update ping status: firewall is not running")
return errors.New("failed to update ping status: firewall is not running")
}
if err = uc.repo.SetPingStatus(status); err != nil {
+2 -2
View File
@@ -224,10 +224,10 @@ func (uc *ToolboxMigrationUsecase) pushWebsite(
return listen.Address, !slices.Contains(listen.Args, "ssl")
})
create := &request.WebsiteCreate{
Type: string(website.Type), Name: item.TargetName, Domains: website.Domains, Path: targetPath, PHP: website.PHP,
Type: website.Type, Name: item.TargetName, Domains: website.Domains, Path: targetPath, PHP: website.PHP,
Listens: lo.Ternary(len(listens) > 0, listens, []string{"80"}),
}
if string(website.Type) == "proxy" && len(website.Proxies) > 0 {
if website.Type == "proxy" && len(website.Proxies) > 0 {
create.Proxy = website.Proxies[0].Pass
}
if _, err = uc.remote.Request(ctx, conn, "POST", "/api/website", create); err != nil {
+1 -2
View File
@@ -3,7 +3,6 @@ package biz
import (
"context"
"errors"
"fmt"
"log/slog"
"path/filepath"
"slices"
@@ -147,7 +146,7 @@ func (uc *WebsiteUsecase) Create(ctx context.Context, req *request.WebsiteCreate
Username: req.DBUser,
Password: req.DBPassword,
Host: "localhost",
Comment: fmt.Sprintf("website %s", req.Name),
Comment: "website " + req.Name,
}); err != nil {
return nil, err
}
+10 -10
View File
@@ -544,7 +544,7 @@ func (r *backupRepo) createWebsite(name string, storage storage.Storage, target
}
// 压缩网站
name = name + r.backupExt()
name += r.backupExt()
if err = io.Compress(website.Path, nil, filepath.Join(tmpDir, name)); err != nil {
return err
}
@@ -594,7 +594,7 @@ func (r *backupRepo) createMySQL(name string, storage storage.Storage, target st
}
// 导出数据库
name = name + ".sql"
name += ".sql"
_ = os.Setenv("MYSQL_PWD", rootPassword)
if _, err = shell.Execf(`mysqldump -u root --single-transaction --quick '%s' > '%s'`, target, filepath.Join(tmpDir, name)); err != nil {
return err
@@ -607,7 +607,7 @@ func (r *backupRepo) createMySQL(name string, storage storage.Storage, target st
}
// 上传备份文件到存储器
name = name + r.backupExt()
name += r.backupExt()
file, err := os.Open(filepath.Join(tmpDir, name))
if err != nil {
return err
@@ -652,7 +652,7 @@ func (r *backupRepo) createPostgres(name string, storage storage.Storage, target
}
// 导出数据库
name = name + ".sql"
name += ".sql"
_ = os.Setenv("PGPASSWORD", postgresPassword)
if _, err = shell.Execf(`pg_dump -h 127.0.0.1 -U postgres '%s' > '%s'`, target, filepath.Join(tmpDir, name)); err != nil {
return err
@@ -665,7 +665,7 @@ func (r *backupRepo) createPostgres(name string, storage storage.Storage, target
}
// 上传备份文件到存储器
name = name + r.backupExt()
name += r.backupExt()
file, err := os.Open(filepath.Join(tmpDir, name))
if err != nil {
return err
@@ -734,7 +734,7 @@ func (r *backupRepo) createClickHouse(name string, storage storage.Storage, targ
}
stmt := strings.TrimSpace(create)
stmt = strings.ReplaceAll(stmt, fmt.Sprintf("`%s`.", target), "")
stmt = strings.ReplaceAll(stmt, fmt.Sprintf("%s.", target), "")
stmt = strings.ReplaceAll(stmt, target+".", "")
schema.WriteString(stmt)
schema.WriteString(";\n")
}
@@ -753,7 +753,7 @@ func (r *backupRepo) createClickHouse(name string, storage storage.Storage, targ
}
// 压缩备份文件
name = name + r.backupExt()
name += r.backupExt()
if err = io.Compress(tmpDir, files, filepath.Join(tmpDir, name)); err != nil {
return err
}
@@ -817,7 +817,7 @@ func (r *backupRepo) createPath(name string, storage storage.Storage, target str
}
// 压缩目录
name = name + r.backupExt()
name += r.backupExt()
if err = io.Compress(target, nil, filepath.Join(tmpDir, name)); err != nil {
return err
}
@@ -1185,7 +1185,7 @@ func (r *backupRepo) createRedisLike(name string, storage storage.Storage, kind
}
// 压缩备份文件
name = name + r.backupExt()
name += r.backupExt()
if err = io.Compress(tmpDir, []string{"dump.rdb"}, filepath.Join(tmpDir, name)); err != nil {
return err
}
@@ -1697,7 +1697,7 @@ func (r *backupRepo) FixPanel() error {
if err = io.Remove(filepath.Join(app.Root, "panel")); err != nil {
return errors.New(r.t.Get("Remove panel file failed: %v", err))
}
if err = io.Mv(filepath.Join("/tmp/panel-fix", "panel"), filepath.Join(app.Root)); err != nil {
if err = io.Mv(filepath.Join("/tmp/panel-fix", "panel"), filepath.Clean(app.Root)); err != nil {
return errors.New(r.t.Get("Move panel file failed: %v", err))
}
if io.Exists(keep) {
+6 -6
View File
@@ -72,9 +72,9 @@ func (r *certRepo) List(page, limit uint) ([]*types.CertList, int64, error) {
item.Issuer = decode.Issuer.CommonName
item.OCSPServer = decode.OCSPServer
// 合并 DNSNames 和 IPAddresses
item.DNSNames = append(decode.DNSNames, lo.Map(decode.IPAddresses, func(ip net.IP, _ int) string {
item.DNSNames = slices.Concat(decode.DNSNames, lo.Map(decode.IPAddresses, func(ip net.IP, _ int) string {
return ip.String()
})...)
}))
}
return item
})
@@ -88,9 +88,9 @@ func (r *certRepo) Get(id uint) (*biz.Cert, error) {
return cert, err
}
func (r *certRepo) GetByWebsite(WebsiteID uint) (*biz.Cert, error) {
func (r *certRepo) GetByWebsite(websiteID uint) (*biz.Cert, error) {
cert := new(biz.Cert)
err := r.db.Model(&biz.Cert{}).Preload("Website").Preload("Account").Preload("DNS").Where("website_id = ?", WebsiteID).First(cert).Error
err := r.db.Model(&biz.Cert{}).Preload("Website").Preload("Account").Preload("DNS").Where("website_id = ?", websiteID).First(cert).Error
return cert, err
}
@@ -166,9 +166,9 @@ func (r *certRepo) ObtainPanel(account *biz.CertAccount, names []string, webServ
}
// LoadWebsite 根据 ID 加载网站
func (r *certRepo) LoadWebsite(WebsiteID uint) (*biz.Website, error) {
func (r *certRepo) LoadWebsite(websiteID uint) (*biz.Website, error) {
website := new(biz.Website)
if err := r.db.Where("id", WebsiteID).First(website).Error; err != nil {
if err := r.db.Where("id", websiteID).First(website).Error; err != nil {
return nil, err
}
return website, nil
+2 -1
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"cmp"
"context"
"errors"
"fmt"
"net/netip"
"slices"
@@ -239,7 +240,7 @@ func (r *containerRepo) Create(sock string, req *request.ContainerCreate) (strin
return "", fmt.Errorf("container port and host port count do not match (container: %d host: %d)", port.ContainerStart-port.ContainerEnd, port.HostStart-port.HostEnd)
}
if port.ContainerStart > port.ContainerEnd || port.HostStart > port.HostEnd || port.ContainerStart < 1 || port.HostStart < 1 {
return "", fmt.Errorf("port range is invalid")
return "", errors.New("port range is invalid")
}
count := uint(0)
+2 -2
View File
@@ -71,8 +71,8 @@ func (r *cronRepo) Delete(cron *biz.Cron) error {
// WriteNewScript 生成随机脚本文件并返回脚本与日志路径
func (r *cronRepo) WriteNewScript(script string) (string, string, error) {
shellDir := fmt.Sprintf("%s/server/cron/", app.Root)
shellLogDir := fmt.Sprintf("%s/server/cron/logs/", app.Root)
shellDir := app.Root + "/server/cron/"
shellLogDir := app.Root + "/server/cron/logs/"
shellFile := str.Random(16)
if err := io.Write(filepath.Join(shellDir, shellFile+".sh"), script, 0700); err != nil {
return "", "", errors.New(err.Error())
+1 -1
View File
@@ -129,7 +129,7 @@ func (r *projectRepo) Delete(project *biz.Project) error {
// unitFilePath 返回 systemd unit 文件路径
func (r *projectRepo) unitFilePath(name string) string {
return filepath.Join("/etc/systemd/system", fmt.Sprintf("%s.service", name))
return filepath.Join("/etc/systemd/system", name+".service")
}
// ParseDetail 从数据库记录和 systemd unit 文件解析项目详情
+1 -1
View File
@@ -112,7 +112,7 @@ func (a *baotaAdapter) websiteItems(ctx context.Context) ([]types.MigrationItem,
continue
}
// PHP / WP2 为 PHP 站点,HTML 为静态站点,Proxy 为反代站点,其余是项目
subtype := ""
var subtype string
switch strings.ToLower(cast.ToString(row["project_type"])) {
case "php", "wp2":
subtype = lo.Ternary(cast.ToString(row["php_version"]) == "静态", "static", "php")
-17
View File
@@ -201,20 +201,3 @@ func (r *userRepo) UpdateTwoFA(id uint, code, secret string) error {
user.TwoFA = secret
return r.db.Save(user).Error
}
func (r *userRepo) CheckTwoFA(id uint, code string) (bool, error) {
user, err := r.Get(id)
if err != nil {
return false, err
}
if user.TwoFA == "" {
return true, nil // 未开启2FA,无需验证
}
if valid := totp.Validate(code, user.TwoFA); !valid {
return false, errors.New(r.t.Get("invalid 2FA code"))
}
return true, nil
}
+1 -1
View File
@@ -119,7 +119,7 @@ func (r *webhookRepo) Call(key string) (string, error) {
if webhook.User == "" || webhook.User == "root" {
cmd = exec.Command("bash", scriptFile)
} else {
cmd = exec.Command("su", "-s", "/bin/bash", "-c", fmt.Sprintf("bash %s", scriptFile), webhook.User)
cmd = exec.Command("su", "-s", "/bin/bash", "-c", "bash "+scriptFile, webhook.User)
}
output, err := cmd.CombinedOutput()
+3 -5
View File
@@ -921,11 +921,9 @@ func (r *websiteRepo) applyUpdate(req *request.WebsiteUpdate, website *biz.Websi
}
}
_, _ = shell.Execf(`chattr +i '%s'`, userIni)
} else {
if io.Exists(userIni) {
if err = io.Remove(userIni); err != nil {
return err
}
} else if io.Exists(userIni) {
if err = io.Remove(userIni); err != nil {
return err
}
}
}
+4 -3
View File
@@ -15,11 +15,12 @@ func MustInstall(t *gotext.Locale, app biz.AppRepo) func(next http.Handler) http
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var slugs []string
if strings.HasPrefix(r.URL.Path, "/api/website") {
switch {
case strings.HasPrefix(r.URL.Path, "/api/website"):
slugs = append(slugs, "nginx", "openresty", "apache", "openlitespeed", "caddy")
} else if strings.HasPrefix(r.URL.Path, "/api/container") {
case strings.HasPrefix(r.URL.Path, "/api/container"):
slugs = append(slugs, "podman", "docker")
} else if strings.HasPrefix(r.URL.Path, "/api/apps/") {
case strings.HasPrefix(r.URL.Path, "/api/apps/"):
pathArr := strings.Split(r.URL.Path, "/")
if len(pathArr) < 4 {
Abort(w, http.StatusForbidden, t.Get("app not found"))
+1 -1
View File
@@ -34,7 +34,7 @@ func MustLogin(t *gotext.Locale, conf *config.Config, session *sessions.Manager,
return
}
userID := uint(0)
var userID uint
if r.Header.Get("Authorization") != "" {
// 禁止访问 ws 相关的接口
if strings.HasPrefix(r.URL.Path, "/api/ws") {
+2 -4
View File
@@ -1,8 +1,6 @@
package rule
import (
"fmt"
"github.com/libtnb/validator"
"gorm.io/gorm"
)
@@ -36,9 +34,9 @@ func (r *Exists) Passes(f validator.Field) bool {
tableName := args[0]
fieldNames := args[1:]
query := r.db.Table(tableName).Where(fmt.Sprintf("%s = ?", fieldNames[0]), val)
query := r.db.Table(tableName).Where(fieldNames[0]+" = ?", val)
for _, fieldName := range fieldNames[1:] {
query = query.Or(fmt.Sprintf("%s = ?", fieldName), val)
query = query.Or(fieldName+" = ?", val)
}
var count int64
+2 -4
View File
@@ -1,8 +1,6 @@
package rule
import (
"fmt"
"github.com/libtnb/validator"
"gorm.io/gorm"
)
@@ -36,9 +34,9 @@ func (r *NotExists) Passes(f validator.Field) bool {
tableName := args[0]
fieldNames := args[1:]
query := r.db.Table(tableName).Where(fmt.Sprintf("%s = ?", fieldNames[0]), val)
query := r.db.Table(tableName).Where(fieldNames[0]+" = ?", val)
for _, fieldName := range fieldNames[1:] {
query = query.Or(fmt.Sprintf("%s = ?", fieldName), val)
query = query.Or(fieldName+" = ?", val)
}
var count int64
+16 -15
View File
@@ -5,6 +5,7 @@ import (
"net/http"
"net/url"
"slices"
"strconv"
"strings"
"time"
@@ -44,7 +45,7 @@ func (s *EnvironmentPHPService) SetCli(w http.ResponseWriter, r *http.Request) {
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -64,7 +65,7 @@ func (s *EnvironmentPHPService) PHPInfo(w http.ResponseWriter, r *http.Request)
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -85,7 +86,7 @@ func (s *EnvironmentPHPService) GetConfig(w http.ResponseWriter, r *http.Request
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -105,7 +106,7 @@ func (s *EnvironmentPHPService) UpdateConfig(w http.ResponseWriter, r *http.Requ
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -124,7 +125,7 @@ func (s *EnvironmentPHPService) GetFPMConfig(w http.ResponseWriter, r *http.Requ
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -144,7 +145,7 @@ func (s *EnvironmentPHPService) UpdateFPMConfig(w http.ResponseWriter, r *http.R
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -163,7 +164,7 @@ func (s *EnvironmentPHPService) Load(w http.ResponseWriter, r *http.Request) {
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -228,7 +229,7 @@ func (s *EnvironmentPHPService) Log(w http.ResponseWriter, r *http.Request) {
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -242,7 +243,7 @@ func (s *EnvironmentPHPService) SlowLog(w http.ResponseWriter, r *http.Request)
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -256,7 +257,7 @@ func (s *EnvironmentPHPService) ModuleList(w http.ResponseWriter, r *http.Reques
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -289,7 +290,7 @@ func (s *EnvironmentPHPService) InstallModule(w http.ResponseWriter, r *http.Req
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -324,7 +325,7 @@ func (s *EnvironmentPHPService) UninstallModule(w http.ResponseWriter, r *http.R
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -607,7 +608,7 @@ func (s *EnvironmentPHPService) GetConfigTune(w http.ResponseWriter, r *http.Req
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -666,7 +667,7 @@ func (s *EnvironmentPHPService) UpdateConfigTune(w http.ResponseWriter, r *http.
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
@@ -729,7 +730,7 @@ func (s *EnvironmentPHPService) CleanSession(w http.ResponseWriter, r *http.Requ
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
if !s.environmentRepo.IsInstalled("php", fmt.Sprintf("%d", req.Version)) {
if !s.environmentRepo.IsInstalled("php", strconv.FormatUint(uint64(req.Version), 10)) {
Error(w, http.StatusUnprocessableEntity, s.t.Get("PHP-%d is not installed", req.Version))
return
}
+7 -21
View File
@@ -4,6 +4,7 @@ package service
import (
"bufio"
"cmp"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
@@ -682,38 +683,23 @@ func (s *FileService) List(w http.ResponseWriter, r *http.Request) {
}
}
var cmp int
var order int
switch sortKey {
case "size":
// 按大小排序
if a.info.Size() < b.info.Size() {
cmp = -1
} else if a.info.Size() > b.info.Size() {
cmp = 1
} else {
cmp = 0
}
order = cmp.Compare(a.info.Size(), b.info.Size())
case "modify":
// 按修改时间排序
if a.info.ModTime().Before(b.info.ModTime()) {
cmp = -1
} else if a.info.ModTime().After(b.info.ModTime()) {
cmp = 1
} else {
cmp = 0
}
case "name":
// 按名称排序
cmp = strings.Compare(strings.ToLower(a.info.Name()), strings.ToLower(b.info.Name()))
order = a.info.ModTime().Compare(b.info.ModTime())
default:
// 默认按名称排序
cmp = strings.Compare(strings.ToLower(a.info.Name()), strings.ToLower(b.info.Name()))
order = strings.Compare(strings.ToLower(a.info.Name()), strings.ToLower(b.info.Name()))
}
if sortDesc {
cmp = -cmp
order = -order
}
return cmp
return order
})
// 转换回 DirEntry 列表
+2 -1
View File
@@ -1,6 +1,7 @@
package service
import (
"net/http"
"net/http/httptest"
"testing"
)
@@ -25,7 +26,7 @@ func TestClientIP(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
r := httptest.NewRequest("POST", "/api/user/login", nil)
r := httptest.NewRequest(http.MethodPost, "/api/user/login", nil)
r.RemoteAddr = c.remoteAddr
if c.value != "" {
r.Header.Set(c.header, c.value)
+6 -6
View File
@@ -232,32 +232,32 @@ func (s *HomeService) InstalledEnvironment(w http.ResponseWriter, r *http.Reques
// Go 版本
goData := lo.Map(s.environmentRepo.InstalledSlugs("go"), func(slug string, _ int) types.LV {
return types.LV{Value: slug, Label: fmt.Sprintf("Go %s", s.environmentRepo.InstalledVersion("go", slug))}
return types.LV{Value: slug, Label: "Go " + s.environmentRepo.InstalledVersion("go", slug)}
})
// Java 版本
javaData := lo.Map(s.environmentRepo.InstalledSlugs("java"), func(slug string, _ int) types.LV {
return types.LV{Value: slug, Label: fmt.Sprintf("Java %s", s.environmentRepo.InstalledVersion("java", slug))}
return types.LV{Value: slug, Label: "Java " + s.environmentRepo.InstalledVersion("java", slug)}
})
// Node.js 版本
nodejsData := lo.Map(s.environmentRepo.InstalledSlugs("nodejs"), func(slug string, _ int) types.LV {
return types.LV{Value: slug, Label: fmt.Sprintf("Node.js %s", s.environmentRepo.InstalledVersion("nodejs", slug))}
return types.LV{Value: slug, Label: "Node.js " + s.environmentRepo.InstalledVersion("nodejs", slug)}
})
// PHP 版本
phpData := lo.Map(s.environmentRepo.InstalledSlugs("php"), func(slug string, _ int) types.LVInt {
return types.LVInt{Value: cast.ToInt(slug), Label: fmt.Sprintf("PHP %s", s.environmentRepo.InstalledVersion("php", slug))}
return types.LVInt{Value: cast.ToInt(slug), Label: "PHP " + s.environmentRepo.InstalledVersion("php", slug)}
})
// Python 版本
pythonData := lo.Map(s.environmentRepo.InstalledSlugs("python"), func(slug string, _ int) types.LV {
return types.LV{Value: slug, Label: fmt.Sprintf("Python %s", s.environmentRepo.InstalledVersion("python", slug))}
return types.LV{Value: slug, Label: "Python " + s.environmentRepo.InstalledVersion("python", slug)}
})
// .NET 版本
dotnetData := lo.Map(s.environmentRepo.InstalledSlugs("dotnet"), func(slug string, _ int) types.LV {
return types.LV{Value: slug, Label: fmt.Sprintf(".NET %s", s.environmentRepo.InstalledVersion("dotnet", slug))}
return types.LV{Value: slug, Label: ".NET " + s.environmentRepo.InstalledVersion("dotnet", slug)}
})
// 数据库
+2 -2
View File
@@ -49,8 +49,8 @@ func (s *SettingService) Update(w http.ResponseWriter, r *http.Request) {
return
}
restart := false
if restart, err = s.settingRepo.UpdatePanel(r.Context(), req); err != nil {
restart, err := s.settingRepo.UpdatePanel(r.Context(), req)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
+2 -1
View File
@@ -18,6 +18,7 @@ import (
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
@@ -430,7 +431,7 @@ func (s *ToolboxBenchmarkService) diskTestTask() map[string]any {
for _, blockSize := range blockSizes {
blockSizeKB := blockSize / 1024
result := s.diskIOTest(testFile, blockSize)
results[fmt.Sprintf("%d", blockSizeKB)] = result
results[strconv.FormatInt(blockSizeKB, 10)] = result
}
duration := time.Since(start)
results["score"] = s.calculateScore(duration)
+11 -9
View File
@@ -1111,13 +1111,14 @@ func (s *ToolboxDiskService) parseAdaptec(output string) ([]raidController, []ra
}
if inLogicalDev && currentArray != nil {
if strings.HasPrefix(trimmed, "RAID level") {
switch {
case strings.HasPrefix(trimmed, "RAID level"):
currentArray.RaidLevel = s.extractAdaptecValue(trimmed)
} else if strings.HasPrefix(trimmed, "Size") {
case strings.HasPrefix(trimmed, "Size"):
currentArray.Size = s.extractAdaptecValue(trimmed)
} else if strings.HasPrefix(trimmed, "Status of Logical Device") || strings.HasPrefix(trimmed, "Status of logical device") {
case strings.HasPrefix(trimmed, "Status of Logical Device"), strings.HasPrefix(trimmed, "Status of logical device"):
currentArray.State = s.extractAdaptecValue(trimmed)
} else if strings.HasPrefix(trimmed, "Stripe-size") || strings.HasPrefix(trimmed, "Strip Size") {
case strings.HasPrefix(trimmed, "Stripe-size"), strings.HasPrefix(trimmed, "Strip Size"):
currentArray.StripSize = s.extractAdaptecValue(trimmed)
}
}
@@ -1132,15 +1133,16 @@ func (s *ToolboxDiskService) parseAdaptec(output string) ([]raidController, []ra
}
if inPhysicalDev && currentDev != nil {
if strings.HasPrefix(trimmed, "State") {
switch {
case strings.HasPrefix(trimmed, "State"):
currentDev.State = s.extractAdaptecValue(trimmed)
} else if strings.HasPrefix(trimmed, "Size") {
case strings.HasPrefix(trimmed, "Size"):
currentDev.Size = s.extractAdaptecValue(trimmed)
} else if strings.HasPrefix(trimmed, "Model") {
case strings.HasPrefix(trimmed, "Model"):
currentDev.Model = s.extractAdaptecValue(trimmed)
} else if strings.HasPrefix(trimmed, "Serial number") || strings.HasPrefix(trimmed, "Serial Number") {
case strings.HasPrefix(trimmed, "Serial number"), strings.HasPrefix(trimmed, "Serial Number"):
currentDev.Serial = s.extractAdaptecValue(trimmed)
} else if strings.HasPrefix(trimmed, "Reported Channel,Device") {
case strings.HasPrefix(trimmed, "Reported Channel,Device"):
currentDev.Slot = s.extractAdaptecValue(trimmed)
}
}
+6 -7
View File
@@ -2,7 +2,6 @@ package service
import (
"cmp"
"fmt"
"net/http"
"slices"
"strconv"
@@ -410,23 +409,23 @@ func (s *WebsiteStatService) UpdateSetting(w http.ResponseWriter, r *http.Reques
return
}
if err = s.setting.Set(biz.SettingKeyWebsiteStatDays, fmt.Sprintf("%d", req.Days)); err != nil {
if err = s.setting.Set(biz.SettingKeyWebsiteStatDays, strconv.FormatUint(uint64(req.Days), 10)); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
if req.ErrBufMax > 0 {
_ = s.setting.Set(biz.SettingKeyWebsiteStatErrBufMax, fmt.Sprintf("%d", req.ErrBufMax))
_ = s.setting.Set(biz.SettingKeyWebsiteStatErrBufMax, strconv.Itoa(req.ErrBufMax))
}
if req.UVMaxKeys > 0 {
_ = s.setting.Set(biz.SettingKeyWebsiteStatUVMaxKeys, fmt.Sprintf("%d", req.UVMaxKeys))
_ = s.setting.Set(biz.SettingKeyWebsiteStatUVMaxKeys, strconv.Itoa(req.UVMaxKeys))
}
if req.IPMaxKeys > 0 {
_ = s.setting.Set(biz.SettingKeyWebsiteStatIPMaxKeys, fmt.Sprintf("%d", req.IPMaxKeys))
_ = s.setting.Set(biz.SettingKeyWebsiteStatIPMaxKeys, strconv.Itoa(req.IPMaxKeys))
}
if req.DetailMaxKeys > 0 {
_ = s.setting.Set(biz.SettingKeyWebsiteStatDetailMaxKeys, fmt.Sprintf("%d", req.DetailMaxKeys))
_ = s.setting.Set(biz.SettingKeyWebsiteStatDetailMaxKeys, strconv.Itoa(req.DetailMaxKeys))
}
_ = s.setting.Set(biz.SettingKeyWebsiteStatBodyEnabled, fmt.Sprintf("%t", req.BodyEnabled))
_ = s.setting.Set(biz.SettingKeyWebsiteStatBodyEnabled, strconv.FormatBool(req.BodyEnabled))
Success(w, nil)
}
+1 -1
View File
@@ -594,7 +594,7 @@ func (s *WsService) getContainerSock() string {
sock = "/var/run/docker.sock"
}
if !strings.Contains(sock, "://") {
sock = fmt.Sprintf("unix://%s", sock)
sock = "unix://" + sock
}
return sock
}
+6 -6
View File
@@ -39,8 +39,8 @@ const (
type EAB = acme.EAB
func NewRegisterAccount(ctx context.Context, email, CA string, eab *EAB, keyType KeyType, log *slog.Logger) (*Client, error) {
client, err := getClient(CA, log)
func NewRegisterAccount(ctx context.Context, email, ca string, eab *EAB, keyType KeyType, log *slog.Logger) (*Client, error) {
client, err := getClient(ca, log)
if err != nil {
return nil, err
}
@@ -69,8 +69,8 @@ func NewRegisterAccount(ctx context.Context, email, CA string, eab *EAB, keyType
return &Client{Account: account, zClient: client}, nil
}
func NewPrivateKeyAccount(email string, privateKey string, CA string, eab *EAB, log *slog.Logger) (*Client, error) {
client, err := getClient(CA, log)
func NewPrivateKeyAccount(email string, privateKey string, ca string, eab *EAB, log *slog.Logger) (*Client, error) {
client, err := getClient(ca, log)
if err != nil {
return nil, err
}
@@ -117,10 +117,10 @@ func generatePrivateKey(keyType KeyType) (crypto.Signer, error) {
return nil, errors.New("unsupported key type")
}
func getClient(CA string, log *slog.Logger) (acmez.Client, error) {
func getClient(ca string, log *slog.Logger) (acmez.Client, error) {
client := acmez.Client{
Client: &acme.Client{
Directory: CA,
Directory: ca,
HTTPClient: http.DefaultClient,
Logger: log,
},
+1 -1
View File
@@ -434,7 +434,7 @@ func (s *dnsSolver) Present(ctx context.Context, challenge acme.Challenge) error
return fmt.Errorf("failed to get DNS provider: %w", err)
}
s.report(fmt.Sprintf("setting DNS TXT record %s", dnsName))
s.report("setting DNS TXT record " + dnsName)
// 同时签主域 + 通配符(如 example.com 与 *.example.com)会产生两个 challenge
// 它们落在同一个 _acme-challenge.example.com TXT 名下,但 keyAuth 不同
-25
View File
@@ -1,25 +0,0 @@
package api
import "fmt"
type EAB struct {
KeyID string `json:"key_id"`
MacKey string `json:"mac_key"`
}
func (r *API) GoogleEAB() (*EAB, error) {
resp, err := r.client.R().SetResult(&Response{}).Get("/acme/googleEAB")
if err != nil {
return nil, err
}
if !resp.IsStatusSuccess() {
return nil, fmt.Errorf("failed to get google eab: %s", resp.String())
}
eab, err := getResponseData[EAB](resp)
if err != nil {
return nil, err
}
return eab, nil
}
+1 -1
View File
@@ -48,7 +48,7 @@ func (r *API) Apps() (*Apps, error) {
// AppBySlug 根据slug返回应用
func (r *API) AppBySlug(slug string) (*App, error) {
resp, err := r.client.R().SetResult(&Response{}).Get(fmt.Sprintf("/apps/%s", slug))
resp, err := r.client.R().SetResult(&Response{}).Get("/apps/" + slug)
if err != nil {
return nil, err
}
+1 -1
View File
@@ -75,7 +75,7 @@ func (r *API) Templates() (*Templates, error) {
// TemplateBySlug 根据slug返回模版
func (r *API) TemplateBySlug(slug string) (*Template, error) {
resp, err := r.client.R().SetResult(&Response{}).Get(fmt.Sprintf("/templates/%s", slug))
resp, err := r.client.R().SetResult(&Response{}).Get("/templates/" + slug)
if err != nil {
return nil, err
}
+2 -2
View File
@@ -109,7 +109,7 @@ func GenerateSelfSigned(names []string) (cert []byte, key []byte, err error) {
}
}
if len(dnsNames) == 0 && len(ipAddrs) == 0 {
return nil, nil, fmt.Errorf("names is empty: SAN must not be empty")
return nil, nil, errors.New("names is empty: SAN must not be empty")
}
// 3) 随机 128 位序列号
@@ -172,7 +172,7 @@ func GenerateSelfSignedRSA(hosts []string) (certPEM []byte, keyPEM []byte, err e
}
}
if len(dnsNames) == 0 && len(ipAddrs) == 0 {
return nil, nil, fmt.Errorf("hosts is empty: SAN must not be empty")
return nil, nil, errors.New("hosts is empty: SAN must not be empty")
}
// 3) 随机 128 位序列号
+4 -3
View File
@@ -3,6 +3,7 @@ package db
import (
"context"
"database/sql"
"errors"
"fmt"
"strings"
@@ -20,7 +21,7 @@ type ClickHouse struct {
// NewClickHouse 创建 ClickHouse 连接(HTTP API
func NewClickHouse(ctx context.Context, username, password, address string) (*ClickHouse, error) {
client := resty.New()
client.SetBaseURL(fmt.Sprintf("http://%s", address))
client.SetBaseURL("http://" + address)
client.SetTimeout(10 * 1000 * 1000 * 1000) // 10s
ch := &ClickHouse{
@@ -66,7 +67,7 @@ func (r *ClickHouse) ping(ctx context.Context) error {
}
func (r *ClickHouse) Query(query string, args ...any) (*sql.Rows, error) {
return nil, fmt.Errorf("clickhouse HTTP API does not support sql.Rows")
return nil, errors.New("clickhouse HTTP API does not support sql.Rows")
}
func (r *ClickHouse) QueryRow(query string, args ...any) *sql.Row {
@@ -79,7 +80,7 @@ func (r *ClickHouse) Exec(query string, args ...any) (sql.Result, error) {
}
func (r *ClickHouse) Prepare(query string) (*sql.Stmt, error) {
return nil, fmt.Errorf("clickhouse HTTP API does not support Prepare")
return nil, errors.New("clickhouse HTTP API does not support Prepare")
}
func (r *ClickHouse) DatabaseCreate(name string) error {
+1 -1
View File
@@ -33,7 +33,7 @@ type ESDocument struct {
// NewElasticsearch 创建 Elasticsearch 连接
func NewElasticsearch(ctx context.Context, address, username, password string) (*Elasticsearch, error) {
client := resty.New()
client.SetBaseURL(fmt.Sprintf("http://%s", address))
client.SetBaseURL("http://" + address)
client.SetTimeout(10 * 1000 * 1000 * 1000) // 10s
if username != "" && password != "" {
client.SetBasicAuth(username, password)
+2 -1
View File
@@ -3,6 +3,7 @@ package db
import (
"context"
"encoding/json"
"errors"
"fmt"
"time"
@@ -125,7 +126,7 @@ func (r *Redis) Get(key string) (*RedisKV, error) {
return nil, fmt.Errorf("key not found: %v", err)
}
if keyType == "none" {
return nil, fmt.Errorf("key not found")
return nil, errors.New("key not found")
}
kv := &RedisKV{Key: key, Type: keyType}
+5 -4
View File
@@ -225,7 +225,7 @@ func (r *firewalld) Port(rule FireInfo, operation Operation) error {
func (r *firewalld) RichRules(rule FireInfo, operation Operation) error {
// 出站规则下,必须指定具体的地址,否则会添加成入站规则
if rule.Direction == "out" && rule.Address == "" {
return fmt.Errorf("outbound rules must specify an address")
return errors.New("outbound rules must specify an address")
}
for _, protocol := range buildProtocols(rule.Protocol) {
@@ -351,14 +351,15 @@ func (r *firewalld) parseRichRule(line string) (FireInfo, error) {
}
ports := strings.Split(match[4], "-")
if len(ports) == 2 { // 添加端口范围
switch {
case len(ports) == 2: // 添加端口范围
fireInfo.PortStart = cast.ToUint(ports[0])
fireInfo.PortEnd = cast.ToUint(ports[1])
} else if len(ports) == 1 && ports[0] != "" { // 添加单个端口
case len(ports) == 1 && ports[0] != "": // 添加单个端口
port := cast.ToUint(ports[0])
fireInfo.PortStart = port
fireInfo.PortEnd = port
} else if len(ports) == 1 && ports[0] == "" { // 未添加端口规则,表示所有端口
case len(ports) == 1 && ports[0] == "": // 未添加端口规则,表示所有端口
fireInfo.PortStart = 1
fireInfo.PortEnd = 65535
}
+5 -4
View File
@@ -2,10 +2,12 @@ package firewall
import (
"cmp"
"errors"
"fmt"
"os"
"regexp"
"slices"
"strconv"
"strings"
"github.com/spf13/cast"
@@ -123,8 +125,7 @@ func (r *ufw) parseRule(target, action, direction, source string) *FireInfo {
// target 的 /tcp 是端口协议规格(如 80/tcp),不能剥离
source = strings.TrimSpace(source)
target = strings.TrimSpace(target)
sourceProto := ""
source, sourceProto = stripProtocolSuffix(source)
source, sourceProto := stripProtocolSuffix(source)
// target 仅在 "Anywhere/tcp" 形式下才需要剥离协议后缀
targetProto := ""
@@ -273,7 +274,7 @@ func (r *ufw) deletePort(rule FireInfo) error {
// formatPort 格式化端口(单端口或范围)
func (r *ufw) formatPort(rule FireInfo) string {
if rule.PortStart == rule.PortEnd {
return fmt.Sprintf("%d", rule.PortStart)
return strconv.FormatUint(uint64(rule.PortStart), 10)
}
return fmt.Sprintf("%d:%d", rule.PortStart, rule.PortEnd)
}
@@ -312,7 +313,7 @@ func (r *ufw) buildPortCmd(rule FireInfo, protocol string, operation Operation)
func (r *ufw) RichRules(rule FireInfo, operation Operation) error {
// 出站规则下,必须指定具体的地址
if rule.Direction == "out" && rule.Address == "" {
return fmt.Errorf("outbound rules must specify an address")
return errors.New("outbound rules must specify an address")
}
if rule.Protocol == "" {
+7 -5
View File
@@ -2,6 +2,7 @@ package ntp
import (
"bufio"
"errors"
"fmt"
"regexp"
"slices"
@@ -99,7 +100,7 @@ func SetSystemNTPServers(servers []string) error {
case NTPServiceChrony:
return setChronyServers(servers)
default:
return fmt.Errorf("unsupported NTP service type")
return errors.New("unsupported NTP service type")
}
}
@@ -155,13 +156,14 @@ func setTimesyncdServers(servers []string) error {
hasTimeSection := strings.Contains(content, "[Time]")
ntpRegex := regexp.MustCompile(`(?m)^\s*#?\s*NTP\s*=.*$`)
if ntpRegex.MatchString(content) {
switch {
case ntpRegex.MatchString(content):
// 替换现有的 NTP= 行
content = ntpRegex.ReplaceAllString(content, ntpLine)
} else if hasTimeSection {
case hasTimeSection:
// 在 [Time] 段后添加 NTP= 行
content = strings.Replace(content, "[Time]", "[Time]\n"+ntpLine, 1)
} else {
default:
// 添加 [Time] 段和 NTP= 行
if content != "" && !strings.HasSuffix(content, "\n") {
content += "\n"
@@ -294,6 +296,6 @@ func RestartNTPService() error {
}
return nil
default:
return fmt.Errorf("unsupported NTP service type")
return errors.New("unsupported NTP service type")
}
}
+2 -1
View File
@@ -3,6 +3,7 @@ package passkey
import (
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"net"
"net/http"
@@ -60,7 +61,7 @@ func (u *User) WebAuthnCredentials() []webauthn.Credential {
// ParseUserID 从 WebAuthnID 字节还原 user ID
func ParseUserID(userHandle []byte) (uint, error) {
if len(userHandle) != 8 {
return 0, fmt.Errorf("invalid user handle")
return 0, errors.New("invalid user handle")
}
return uint(binary.BigEndian.Uint64(userHandle)), nil
}
-21
View File
@@ -24,27 +24,6 @@ type ClientConfig struct {
Timeout time.Duration `json:"timeout"`
}
func ClientConfigPassword(host, user, password string) *ClientConfig {
return &ClientConfig{
Timeout: 10 * time.Second,
AuthMethod: PASSWORD,
Host: host,
User: user,
Password: password,
}
}
func ClientConfigPublicKey(host, user, key, passphrase string) *ClientConfig {
return &ClientConfig{
Timeout: 10 * time.Second,
AuthMethod: PUBLICKEY,
Host: host,
User: user,
Key: key,
Passphrase: passphrase,
}
}
func NewSSHClient(conf ClientConfig) (*ssh.Client, error) {
if conf.Timeout == 0 {
conf.Timeout = 10 * time.Second
+1 -1
View File
@@ -199,5 +199,5 @@ func (e *apiError) Error() string {
if trimmed := bytes.TrimSpace(e.body); len(trimmed) > 0 {
return fmt.Sprintf("s3: unexpected status %s: %s", e.statusText, trimmed)
}
return fmt.Sprintf("s3: unexpected status %s", e.statusText)
return "s3: unexpected status " + e.statusText
}
+2 -1
View File
@@ -1,6 +1,7 @@
package storage
import (
"errors"
"fmt"
"io"
"os"
@@ -37,7 +38,7 @@ func NewSFTP(config SFTPConfig) (Storage, error) {
config.BasePath = strings.TrimSuffix(config.BasePath, "/")
if config.Username == "" || (config.Password == "" && config.PrivateKey == "") {
return nil, fmt.Errorf("username and either password or private key must be provided")
return nil, errors.New("username and either password or private key must be provided")
}
return &SFTP{config: config}, nil
+1 -1
View File
@@ -248,7 +248,7 @@ func generateRedirectConfig(redirect types.Redirect) string {
cfg.Append(Dir("RewriteRule", "^(.*)$", to, fmt.Sprintf("[R=%d,L]", statusCode)))
case types.RedirectType404:
cfg.Append(Cmt(fmt.Sprintf("404 redirect -> %s", redirect.To)))
cfg.Append(Cmt("404 redirect -> " + redirect.To))
cfg.Append(Dir("ErrorDocument", "404", redirect.To))
}
+4 -3
View File
@@ -1,6 +1,7 @@
package apache
import (
"errors"
"fmt"
"os"
"path/filepath"
@@ -37,7 +38,7 @@ type baseVhost struct {
// newBaseVhost 创建基础虚拟主机实例
func newBaseVhost(configDir string) (*baseVhost, error) {
if configDir == "" {
return nil, fmt.Errorf("config directory is required")
return nil, errors.New("config directory is required")
}
v := &baseVhost{
@@ -76,7 +77,7 @@ func newBaseVhost(configDir string) (*baseVhost, error) {
// defaultConf 返回替换好站点名的默认配置模板
func (v *baseVhost) defaultConf() string {
return strings.ReplaceAll(DefaultVhostConf, "/opt/ace/sites/default", fmt.Sprintf("/opt/ace/sites/%s", v.siteName))
return strings.ReplaceAll(DefaultVhostConf, "/opt/ace/sites/default", "/opt/ace/sites/"+v.siteName)
}
// NewStaticVhost 创建纯静态虚拟主机实例
@@ -359,7 +360,7 @@ func (v *baseVhost) SSLConfig() *types.SSLConfig {
func (v *baseVhost) SetSSLConfig(cfg *types.SSLConfig) error {
if cfg == nil {
return fmt.Errorf("SSL config cannot be nil")
return errors.New("SSL config cannot be nil")
}
v.vhost.Set("SSLEngine", "on")
+1 -1
View File
@@ -20,7 +20,7 @@ type Parser struct {
// NewParser 使用网站名创建解析器,将默认配置中的 default 替换为实际网站名
func NewParser(siteName string) (*Parser, error) {
str := strings.ReplaceAll(DefaultConf, "/opt/ace/sites/default", fmt.Sprintf("/opt/ace/sites/%s", siteName))
str := strings.ReplaceAll(DefaultConf, "/opt/ace/sites/default", "/opt/ace/sites/"+siteName)
p := parser.NewStringParser(str, parser.WithSkipIncludeParsingErr(), parser.WithSkipValidDirectivesErr())
cfg, err := p.Parse()
+1 -1
View File
@@ -93,7 +93,7 @@ func formatBytesToNginx(bytes int64) string {
if bytes%1024 == 0 {
return fmt.Sprintf("%dk", bytes/1024)
}
return fmt.Sprintf("%d", bytes)
return strconv.FormatInt(bytes, 10)
}
// formatDurationToNginx 格式化 time.Duration 为 Nginx 时间格式
+6 -4
View File
@@ -2,10 +2,12 @@ package nginx
import (
"bufio"
"errors"
"fmt"
"os"
"path/filepath"
"slices"
"strconv"
"strings"
"github.com/samber/lo"
@@ -39,7 +41,7 @@ type baseVhost struct {
// newBaseVhost 创建基础虚拟主机实例
func newBaseVhost(configDir string) (*baseVhost, error) {
if configDir == "" {
return nil, fmt.Errorf("config directory is required")
return nil, errors.New("config directory is required")
}
v := &baseVhost{
@@ -485,7 +487,7 @@ func (v *baseVhost) SSLConfig() *types.SSLConfig {
func (v *baseVhost) SetSSLConfig(cfg *types.SSLConfig) error {
if cfg == nil {
return fmt.Errorf("SSL config cannot be nil")
return errors.New("SSL config cannot be nil")
}
if err := v.ClearSSL(); err != nil {
@@ -628,13 +630,13 @@ func (v *baseVhost) SetRateLimit(limit *types.RateLimit) error {
if limit.PerServer > 0 {
directives = append(directives, &config.Directive{
Name: "limit_conn",
Parameters: []config.Parameter{{Value: "perserver"}, {Value: fmt.Sprintf("%d", limit.PerServer)}},
Parameters: []config.Parameter{{Value: "perserver"}, {Value: strconv.Itoa(limit.PerServer)}},
})
}
if limit.PerIP > 0 {
directives = append(directives, &config.Directive{
Name: "limit_conn",
Parameters: []config.Parameter{{Value: "perip"}, {Value: fmt.Sprintf("%d", limit.PerIP)}},
Parameters: []config.Parameter{{Value: "perip"}, {Value: strconv.Itoa(limit.PerIP)}},
})
}
if len(directives) > 0 {
+6 -7
View File
@@ -13,19 +13,18 @@ func ParseUA(rawUA string) (browser, os string) {
// 浏览器:名称 + 主版本号
bName := string(agent.Browser())
bMajor := agent.BrowserVersionMajor()
if bName == "" {
switch {
case bName == "":
browser = "Other"
} else if bMajor == "" {
case bMajor == "":
browser = bName
} else {
default:
browser = bName + " " + bMajor
}
// 操作系统
osName := string(agent.OS())
if osName == "" {
os = "Other"
} else {
os = "Other"
if osName := string(agent.OS()); osName != "" {
os = osName
}
+12
View File
@@ -0,0 +1,12 @@
import base from './eslint.config'
export default [
...(base as any),
{
name: 'unused-check',
files: ['**/*.{ts,mts,tsx,vue}'],
rules: {
'@typescript-eslint/no-unused-vars': ['error', { args: 'none', varsIgnorePattern: '^_', caughtErrors: 'none' }],
},
},
]
@@ -47,7 +47,6 @@ const onSelectMore = (key: string) => {
if (!action) return
if (action.confirm) {
//
const { useConfirm } = (window as any).__useConfirm || {}
void invokeWithConfirm(action)
} else {
void action.onClick(props.row)
+1 -1
View File
@@ -6,7 +6,7 @@ interface Props {
fallbackDescription?: string
}
const props = withDefaults(defineProps<Props>(), {
withDefaults(defineProps<Props>(), {
fallbackTitle: undefined,
fallbackDescription: undefined,
})
+1 -1
View File
@@ -8,7 +8,7 @@ interface Props {
tooltip?: string
}
const props = withDefaults(defineProps<Props>(), {
withDefaults(defineProps<Props>(), {
loading: false,
size: 'small',
variant: 'icon',
+1 -1
View File
@@ -159,7 +159,7 @@ const { data: categories } = useRequest(app.categories, {
initialData: [],
})
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) =>
app.list(page, pageSize, selectedCategory.value || undefined, searchQuery.value || undefined),
{
+1 -1
View File
@@ -155,7 +155,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) =>
environment.list(
page,
+1 -1
View File
@@ -27,7 +27,7 @@ const searchQuery = ref<string>('')
const deployModalShow = ref(false)
const selectedTemplate = ref<Template | null>(null)
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) =>
template.list(
page,
+1 -1
View File
@@ -161,7 +161,7 @@ const getWebsiteList = async (page: number, limit: number) => {
addJailModel.value.website_name = websites.value[0]?.value
}
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => fail2ban.jails(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -91,7 +91,7 @@ const userColumns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => pureftpd.list(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -105,7 +105,7 @@ const processColumns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => rsync.modules(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -58,7 +58,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => s3fs.mounts(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -183,7 +183,7 @@ const processColumns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => supervisor.processes(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -110,7 +110,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => backup.list(type.value, page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -130,7 +130,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => storage.list(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -117,7 +117,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => cert.accounts(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -371,7 +371,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => cert.certs(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -113,7 +113,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => cert.dns(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -213,7 +213,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => container.composeList(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -262,7 +262,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => container.containerList(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -117,7 +117,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => container.imageList(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -133,7 +133,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => container.networkList(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -86,7 +86,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => container.volumeList(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -91,7 +91,7 @@ const columns: any = computed(() => {
return cols
})
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => database.list(page, pageSize, props.type),
{
initialData: { total: 0, list: [] },
@@ -205,7 +205,7 @@ const docColumns: any = [
]
//
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) =>
database.esData(selectedServer.value || 0, selectedIndex.value, page, pageSize, search.value),
{
+1 -1
View File
@@ -186,7 +186,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) =>
database.redisData(selectedServer.value || 0, selectedDB.value, page, pageSize, search.value),
{
+1 -1
View File
@@ -252,7 +252,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => database.serverList(page, pageSize, props.type),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -169,7 +169,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => database.userList(page, pageSize, props.type),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -101,7 +101,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => firewall.forwards(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -143,7 +143,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => firewall.ipRules(page, pageSize),
{
initialData: { total: 0, list: [] },
+1 -1
View File
@@ -283,7 +283,7 @@ const columns: any = [
},
]
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
const { loading, data, page, total, pageSize, refresh } = usePagination(
(page, pageSize) => firewall.rules(page, pageSize),
{
initialData: { total: 0, list: [] },

Some files were not shown because too many files have changed in this diff Show More