diff --git a/go.mod b/go.mod index 4cbc90f2..78701e9d 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/go-rat/chix v1.1.4 github.com/go-rat/gormstore v1.0.6 github.com/go-rat/sessions v1.0.11 - github.com/go-rat/utils v1.0.3 + github.com/go-rat/utils v1.0.6 github.com/go-resty/resty/v2 v2.15.3 github.com/go-sql-driver/mysql v1.8.1 github.com/golang-cz/httplog v0.0.0-20241002114323-98e09d6f537a @@ -56,7 +56,7 @@ require ( github.com/devhaozi/huaweicloud-sdk-go-v3 v0.0.0-20241018211007-bbebb6de5db7 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.5 // indirect + github.com/gabriel-vasile/mimetype v1.4.6 // indirect github.com/glebarez/go-sqlite v1.22.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-rat/securecookie v1.0.1 // indirect diff --git a/go.sum b/go.sum index 32851bb6..43ba884d 100644 --- a/go.sum +++ b/go.sum @@ -23,6 +23,7 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4= github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4= +github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ= github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc= github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= @@ -51,6 +52,12 @@ github.com/go-rat/sessions v1.0.11 h1:2eTUvhEBtymrAtwv71LlGHNylz+Ad2SgY3jg/sSUbo github.com/go-rat/sessions v1.0.11/go.mod h1:Ray/GCbuhm4U9xpjFFSCfOTCEn91puEhAXX5creHE9g= github.com/go-rat/utils v1.0.3 h1:SqH/O0KYq4SBv8naSAjJA4hC45/d8NLNrTCONfqjbFM= github.com/go-rat/utils v1.0.3/go.mod h1:4WNPlrF57KmeGZN3HOeBgdBVLJL3xgba4QRP/t6pKrE= +github.com/go-rat/utils v1.0.4 h1:k9jkR4ddL0Fgex3P4qURvNCDx61S9u5LF0EZna+Reic= +github.com/go-rat/utils v1.0.4/go.mod h1:yokaqppXr7xSqhhxtioHG+txMXI9a9AGriPJnjki2ts= +github.com/go-rat/utils v1.0.5 h1:XHluZY4Cd+hrb0/9Jm1Uz38pFWrKEdh1fmW5vkPyw14= +github.com/go-rat/utils v1.0.5/go.mod h1:n22OGZrg9tp3L/T0tWo2OOMl6+jAUoBujmN0fEbDUtk= +github.com/go-rat/utils v1.0.6 h1:P70t4FWDDOT3JYVucELQFSdZR4ATGwsXPJM4wqJhBhU= +github.com/go-rat/utils v1.0.6/go.mod h1:n22OGZrg9tp3L/T0tWo2OOMl6+jAUoBujmN0fEbDUtk= github.com/go-resty/resty/v2 v2.15.3 h1:bqff+hcqAflpiF591hhJzNdkRsFhlB96CYfBwSFvql8= github.com/go-resty/resty/v2 v2.15.3/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= diff --git a/internal/apps/fail2ban/service.go b/internal/apps/fail2ban/service.go index eefdca6a..58af5d98 100644 --- a/internal/apps/fail2ban/service.go +++ b/internal/apps/fail2ban/service.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/go-rat/chix" + "github.com/go-rat/utils/str" "github.com/spf13/cast" "github.com/TheTNB/panel/internal/app" @@ -16,7 +17,6 @@ import ( "github.com/TheTNB/panel/pkg/io" "github.com/TheTNB/panel/pkg/os" "github.com/TheTNB/panel/pkg/shell" - "github.com/TheTNB/panel/pkg/str" ) type Service struct { diff --git a/internal/apps/rsync/service.go b/internal/apps/rsync/service.go index c545ed1c..fa50ad5d 100644 --- a/internal/apps/rsync/service.go +++ b/internal/apps/rsync/service.go @@ -7,11 +7,11 @@ import ( "strings" "github.com/go-rat/chix" + "github.com/go-rat/utils/str" "github.com/TheTNB/panel/internal/service" "github.com/TheTNB/panel/pkg/io" "github.com/TheTNB/panel/pkg/shell" - "github.com/TheTNB/panel/pkg/str" "github.com/TheTNB/panel/pkg/systemctl" ) diff --git a/internal/data/app.go b/internal/data/app.go index d2c0bb37..1b1e3e46 100644 --- a/internal/data/app.go +++ b/internal/data/app.go @@ -15,7 +15,6 @@ import ( "github.com/TheTNB/panel/pkg/api" "github.com/TheTNB/panel/pkg/apploader" "github.com/TheTNB/panel/pkg/shell" - "github.com/TheTNB/panel/pkg/str" ) type appRepo struct { @@ -65,7 +64,7 @@ func (r *appRepo) UpdateExist(slug string) bool { for channel := range slices.Values(item.Channels) { if channel.Slug == installed.Channel { - current := str.FirstElement(channel.Subs) + current := collect.First(channel.Subs) if current != nil && current.Version != installed.Version { return true } @@ -168,7 +167,7 @@ func (r *appRepo) Install(channel, slug string) error { } shellUrl = ch.Install shellChannel = ch.Slug - shellVersion = str.FirstElement(ch.Subs).Version + shellVersion = collect.First(ch.Subs).Version break } } @@ -278,7 +277,7 @@ func (r *appRepo) Update(slug string) error { } shellUrl = ch.Update shellChannel = ch.Slug - shellVersion = str.FirstElement(ch.Subs).Version + shellVersion = collect.First(ch.Subs).Version break } } diff --git a/internal/data/cron.go b/internal/data/cron.go index e6483763..b5e3c83e 100644 --- a/internal/data/cron.go +++ b/internal/data/cron.go @@ -7,13 +7,14 @@ import ( "strconv" "time" + "github.com/go-rat/utils/str" + "github.com/TheTNB/panel/internal/app" "github.com/TheTNB/panel/internal/biz" "github.com/TheTNB/panel/internal/http/request" "github.com/TheTNB/panel/pkg/io" "github.com/TheTNB/panel/pkg/os" "github.com/TheTNB/panel/pkg/shell" - "github.com/TheTNB/panel/pkg/str" "github.com/TheTNB/panel/pkg/systemctl" ) @@ -99,7 +100,7 @@ panel-cli cutoff clear -t website -f %s -s %d -p %s if !io.Exists(shellLogDir) { return errors.New("计划任务日志目录不存在") } - shellFile := strconv.Itoa(int(time.Now().Unix())) + str.RandomString(16) + shellFile := strconv.Itoa(int(time.Now().Unix())) + str.Random(16) if err := io.Write(filepath.Join(shellDir, shellFile+".sh"), script, 0700); err != nil { return errors.New(err.Error()) } diff --git a/internal/service/cli.go b/internal/service/cli.go index 06a8745c..94968726 100644 --- a/internal/service/cli.go +++ b/internal/service/cli.go @@ -7,7 +7,9 @@ import ( "path/filepath" "time" + "github.com/go-rat/utils/collect" "github.com/go-rat/utils/hash" + "github.com/go-rat/utils/str" "github.com/spf13/cast" "github.com/urfave/cli/v3" "gopkg.in/yaml.v3" @@ -21,7 +23,6 @@ import ( "github.com/TheTNB/panel/pkg/cert" "github.com/TheTNB/panel/pkg/io" "github.com/TheTNB/panel/pkg/ntp" - "github.com/TheTNB/panel/pkg/str" "github.com/TheTNB/panel/pkg/systemctl" "github.com/TheTNB/panel/pkg/tools" "github.com/TheTNB/panel/pkg/types" @@ -84,7 +85,7 @@ func (s *CliService) Update(ctx context.Context, cmd *cli.Command) error { return fmt.Errorf("获取最新版本失败:%v", err) } - download := str.FirstElement(panel.Downloads) + download := collect.First(panel.Downloads) if download == nil { return fmt.Errorf("下载地址为空") } @@ -103,15 +104,15 @@ func (s *CliService) Info(ctx context.Context, cmd *cli.Command) error { return fmt.Errorf("获取管理员信息失败:%v", err) } - password := str.RandomString(16) + password := str.Random(16) hashed, err := s.hash.Make(password) if err != nil { return fmt.Errorf("密码生成失败:%v", err) } - user.Username = str.RandomString(8) + user.Username = str.Random(8) user.Password = hashed if user.Email == "" { - user.Email = str.RandomString(8) + "@example.com" + user.Email = str.Random(8) + "@example.com" } if err = app.Orm.Save(user).Error; err != nil { @@ -326,7 +327,7 @@ func (s *CliService) EntranceOn(ctx context.Context, cmd *cli.Command) error { return err } - config.HTTP.Entrance = "/" + str.RandomString(6) + config.HTTP.Entrance = "/" + str.Random(6) encoded, err := yaml.Marshal(config) if err != nil { @@ -755,7 +756,7 @@ func (s *CliService) Init(ctx context.Context, cmd *cli.Command) error { return fmt.Errorf("初始化失败:%v", err) } - value, err := hash.NewArgon2id().Make(str.RandomString(32)) + value, err := hash.NewArgon2id().Make(str.Random(32)) if err != nil { return fmt.Errorf("初始化失败:%v", err) } @@ -779,8 +780,8 @@ func (s *CliService) Init(ctx context.Context, cmd *cli.Command) error { return err } - config.App.Key = str.RandomString(32) - config.HTTP.Entrance = "/" + str.RandomString(6) + config.App.Key = str.Random(32) + config.HTTP.Entrance = "/" + str.Random(6) encoded, err := yaml.Marshal(config) if err != nil { diff --git a/internal/service/dashboard.go b/internal/service/dashboard.go index 43898037..13e65465 100644 --- a/internal/service/dashboard.go +++ b/internal/service/dashboard.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/go-rat/chix" + "github.com/go-rat/utils/collect" "github.com/hashicorp/go-version" "github.com/shirou/gopsutil/disk" "github.com/shirou/gopsutil/host" @@ -20,7 +21,6 @@ import ( "github.com/TheTNB/panel/pkg/api" "github.com/TheTNB/panel/pkg/db" "github.com/TheTNB/panel/pkg/shell" - "github.com/TheTNB/panel/pkg/str" "github.com/TheTNB/panel/pkg/tools" "github.com/TheTNB/panel/pkg/types" ) @@ -295,7 +295,7 @@ func (s *DashboardService) Update(w http.ResponseWriter, r *http.Request) { return } - download := str.FirstElement(panel.Downloads) + download := collect.First(panel.Downloads) if download == nil { Error(w, http.StatusInternalServerError, "获取下载链接失败") return diff --git a/pkg/str/string.go b/pkg/str/string.go index 6842af05..286dd25c 100644 --- a/pkg/str/string.go +++ b/pkg/str/string.go @@ -1,57 +1,9 @@ package str import ( - "crypto/md5" - "crypto/rand" "fmt" - "io" - "log" - "strings" - "text/template" - "unicode/utf8" ) -// FirstElement 返回切片的第一个元素 -func FirstElement[T any](args []T) *T { - if len(args) > 0 { - return &args[0] - } - return nil -} - -// RandomNumber 生成长度为 length 随机数字字符串 -func RandomNumber(length int) string { - table := [...]byte{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'} - b := make([]byte, length) - n, err := io.ReadAtLeast(rand.Reader, b, length) - if n != length { - log.Panicf("failed to generate random number: %v", err) - } - for i := 0; i < len(b); i++ { - b[i] = table[int(b[i])%len(table)] - } - return string(b) -} - -// RandomString 生成长度为 length 的随机字符串 -func RandomString(length int) string { - b := make([]byte, length) - _, err := rand.Read(b) - if err != nil { - log.Panicf("failed to generate random string: %v", err) - } - letters := "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - for i, v := range b { - b[i] = letters[v%byte(len(letters))] - } - return string(b) -} - -// MD5 生成字符串的 MD5 值 -func MD5(str string) string { - return fmt.Sprintf("%x", md5.Sum([]byte(str))) -} - // FormatBytes 格式化bytes func FormatBytes(size float64) string { units := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} @@ -63,25 +15,3 @@ func FormatBytes(size float64) string { return fmt.Sprintf("%.2f %s", size, units[i]) } - -// Cut 裁剪字符串 -func Cut(str, begin, end string) string { - bIndex := strings.Index(str, begin) - eIndex := strings.Index(str, end) - if bIndex == -1 || eIndex == -1 || bIndex > eIndex { - return "" - } - - b := utf8.RuneCountInString(str[:bIndex]) + utf8.RuneCountInString(begin) - e := utf8.RuneCountInString(str[:eIndex]) - if b > e { - return "" - } - - return string([]rune(str)[b:e]) -} - -// Escape 转义字符串 -func Escape(str string) string { - return template.HTMLEscapeString(str) -} diff --git a/pkg/str/string_test.go b/pkg/str/string_test.go index f7c6ebdc..26b32cf2 100644 --- a/pkg/str/string_test.go +++ b/pkg/str/string_test.go @@ -14,22 +14,6 @@ func TestStringHelperTestSuite(t *testing.T) { suite.Run(t, &StringHelperTestSuite{}) } -func (s *StringHelperTestSuite) TestFirstElement() { - s.Equal("HaoZi", *FirstElement([]string{"HaoZi"})) -} - -func (s *StringHelperTestSuite) TestRandomNumber() { - s.Len(RandomNumber(10), 10) -} - -func (s *StringHelperTestSuite) TestRandomString() { - s.Len(RandomString(10), 10) -} - -func (s *StringHelperTestSuite) TestMD5() { - s.Equal("e10adc3949ba59abbe56e057f20f883e", MD5("123456")) -} - func (s *StringHelperTestSuite) TestFormatBytes() { s.Equal("1.00 B", FormatBytes(1)) s.Equal("1.00 KB", FormatBytes(1024)) @@ -41,7 +25,3 @@ func (s *StringHelperTestSuite) TestFormatBytes() { s.Equal("1.00 ZB", FormatBytes(1024*1024*1024*1024*1024*1024*1024)) s.Equal("1.00 YB", FormatBytes(1024*1024*1024*1024*1024*1024*1024*1024)) } - -func (s *StringHelperTestSuite) TestCut() { - s.Equal("aoZ", Cut("HaoZi", "H", "i")) -}