diff --git a/app/providers/validation_service_provider.go b/app/providers/validation_service_provider.go index 9b34c7fdc9..5215cd896b 100644 --- a/app/providers/validation_service_provider.go +++ b/app/providers/validation_service_provider.go @@ -25,7 +25,6 @@ func (receiver *ValidationServiceProvider) rules() []validation.Rule { return []validation.Rule{ &rules.Exists{}, &rules.NotExists{}, - &rules.Captcha{}, &rules.PathExists{}, &rules.PathNotExists{}, } diff --git a/app/rules/captcha.go b/app/rules/captcha.go deleted file mode 100644 index b901f3c510..0000000000 --- a/app/rules/captcha.go +++ /dev/null @@ -1,46 +0,0 @@ -package rules - -import ( - "strconv" - - "github.com/goravel/framework/contracts/validation" - - "github.com/TheTNB/panel/pkg/captcha" -) - -type Captcha struct { -} - -// Signature The name of the rule. -func (receiver *Captcha) Signature() string { - return "captcha" -} - -// Passes Determine if the validation rule passes. -func (receiver *Captcha) Passes(data validation.Data, val any, options ...any) bool { - captchaID, exist := data.Get("captcha_id") - if !exist { - return false - } - - // 第一个参数(如果有),是否清除验证码,如 false - clear := true - var err error - if len(options) > 0 { - clear, err = strconv.ParseBool(options[0].(string)) - if err != nil { - clear = true - } - } - - if !captcha.NewCaptcha().VerifyCaptcha(captchaID.(string), val.(string), clear) { - return false - } - - return true -} - -// Message Get the validation error message. -func (receiver *Captcha) Message() string { - return "" -} diff --git a/config/captcha.go b/config/captcha.go deleted file mode 100644 index 43f0896e31..0000000000 --- a/config/captcha.go +++ /dev/null @@ -1,34 +0,0 @@ -package config - -import ( - "github.com/goravel/framework/facades" -) - -func init() { - config := facades.Config() - config.Add("captcha", map[string]any{ - // 验证码图片高度 - "height": 60, - - // 验证码图片宽度 - "width": 120, - - // 验证码的长度 - "length": 6, - - // 数字的最大倾斜角度 - "maxskew": 0.6, - - // 图片背景里的混淆点数量 - "dotcount": 40, - - // 过期时间,单位是分钟 - "expire_time": 5, - - // debug 模式下的过期时间,方便本地开发调试 - "debug_expire_time": 3600, - - // 非 production 环境,使用此 key 可跳过验证,方便测试 - "testing_key": "captcha_skip_test", - }) -} diff --git a/go.mod b/go.mod index b636e30455..cd1602fcf8 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/go-resty/resty/v2 v2.13.1 github.com/go-sql-driver/mysql v1.8.1 github.com/gookit/validate v1.5.2 - github.com/goravel/framework v1.14.1-0.20240618022250-731b8d9930a3 + github.com/goravel/framework v1.14.1-0.20240627172353-91c3c46cf333 github.com/goravel/gin v1.2.1 github.com/gorilla/websocket v1.5.3 github.com/lib/pq v1.10.9 @@ -19,7 +19,6 @@ require ( github.com/libdns/libdns v0.2.2 github.com/mholt/acmez/v2 v2.0.1 github.com/mholt/archiver/v3 v3.5.1 - github.com/mojocn/base64Captcha v1.3.6 github.com/shirou/gopsutil v3.21.11+incompatible github.com/spf13/cast v1.6.0 github.com/stretchr/testify v1.9.0 @@ -98,7 +97,6 @@ require ( github.com/golang-module/carbon/v2 v2.3.12 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect - github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect @@ -190,7 +188,6 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect - golang.org/x/image v0.13.0 // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect diff --git a/go.sum b/go.sum index 320df9560d..d40c30f893 100644 --- a/go.sum +++ b/go.sum @@ -134,8 +134,6 @@ github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= -github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v27.0.2+incompatible h1:mNhCtgXNV1fIRns102grG7rdzIsGGCq1OlOD0KunZos= github.com/docker/docker v27.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -227,8 +225,6 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0kt github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -280,8 +276,8 @@ github.com/gookit/validate v1.5.2 h1:i5I2OQ7WYHFRPRATGu9QarR9snnNHydvwSuHXaRWAV0 github.com/gookit/validate v1.5.2/go.mod h1:yuPy2WwDlwGRa06fFJ5XIO8QEwhRnTC2LmxmBa5SE14= github.com/goravel/file-rotatelogs/v2 v2.4.2 h1:g68AzbePXcm0V2CpUMc9j4qVzcDn7+7aoWSjZ51C0m4= github.com/goravel/file-rotatelogs/v2 v2.4.2/go.mod h1:23VuSW8cBS4ax5cmbV+5AaiLpq25b8UJ96IhbAkdo8I= -github.com/goravel/framework v1.14.1-0.20240618022250-731b8d9930a3 h1:G9aMInp4s2pL/bpVXrUj+NUtnVU8i7T9t6vGUJ60NaM= -github.com/goravel/framework v1.14.1-0.20240618022250-731b8d9930a3/go.mod h1:RTwF0A7HySf5i+2jptT9oyFqmQAiQubWn1AQrJAzPWg= +github.com/goravel/framework v1.14.1-0.20240627172353-91c3c46cf333 h1:hOj1S1TQQ/19ng0JzpbTfscB128L5E5dIcx/mU1zofc= +github.com/goravel/framework v1.14.1-0.20240627172353-91c3c46cf333/go.mod h1:8Fz0+JHyqwnOLy8rFkFWPQXv0Bkk3JEB43OV/Wx7xCA= github.com/goravel/gin v1.2.1 h1:lnQX3NKUEaSx8x7AAJpoeVkXgi+MVQ9FXy4QywHQElo= github.com/goravel/gin v1.2.1/go.mod h1:Qt3NJysg/eoxXL4y/swwFUcfcIT7XG+xb0rWChweZfY= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= @@ -398,8 +394,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/mojocn/base64Captcha v1.3.6 h1:gZEKu1nsKpttuIAQgWHO+4Mhhls8cAKyiV2Ew03H+Tw= -github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DGY3Wh3dBpZ28E= github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= @@ -598,8 +592,6 @@ golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5D golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= -golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg= -golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= diff --git a/internal/services/container.go b/internal/services/container.go index e5d9f41f21..9e4623385c 100644 --- a/internal/services/container.go +++ b/internal/services/container.go @@ -118,7 +118,7 @@ func (r *Container) ContainerRename(id string, newName string) error { } // ContainerStats 查看容器状态 -func (r *Container) ContainerStats(id string) (types.ContainerStats, error) { +func (r *Container) ContainerStats(id string) (container.StatsResponseReader, error) { return r.client.ContainerStats(context.Background(), id, false) } @@ -167,8 +167,8 @@ func (r *Container) ContainerPrune() error { } // NetworkList 列出网络 -func (r *Container) NetworkList() ([]types.NetworkResource, error) { - return r.client.NetworkList(context.Background(), types.NetworkListOptions{}) +func (r *Container) NetworkList() ([]network.Inspect, error) { + return r.client.NetworkList(context.Background(), network.ListOptions{}) } // NetworkCreate 创建网络 @@ -189,8 +189,8 @@ func (r *Container) NetworkCreate(config requests.NetworkCreate) (string, error) }) } - options := types.NetworkCreate{ - EnableIPv6: config.Ipv6.Enabled, + options := network.CreateOptions{ + EnableIPv6: &config.Ipv6.Enabled, Driver: config.Driver, Options: r.KVToMap(config.Options), Labels: r.KVToMap(config.Labels), @@ -212,7 +212,7 @@ func (r *Container) NetworkRemove(id string) error { // NetworkExist 判断网络是否存在 func (r *Container) NetworkExist(name string) (bool, error) { - var options types.NetworkListOptions + var options network.ListOptions options.Filters = filters.NewArgs(filters.Arg("name", name)) networks, err := r.client.NetworkList(context.Background(), options) if err != nil { @@ -223,8 +223,8 @@ func (r *Container) NetworkExist(name string) (bool, error) { } // NetworkInspect 查看网络 -func (r *Container) NetworkInspect(id string) (types.NetworkResource, error) { - return r.client.NetworkInspect(context.Background(), id, types.NetworkInspectOptions{}) +func (r *Container) NetworkInspect(id string) (network.Inspect, error) { + return r.client.NetworkInspect(context.Background(), id, network.InspectOptions{}) } // NetworkConnect 连接网络 diff --git a/pkg/captcha/captcha.go b/pkg/captcha/captcha.go deleted file mode 100644 index 51185dc387..0000000000 --- a/pkg/captcha/captcha.go +++ /dev/null @@ -1,63 +0,0 @@ -// Package captcha 处理图片验证码逻辑 -package captcha - -import ( - "sync" - - "github.com/goravel/framework/facades" - "github.com/mojocn/base64Captcha" -) - -type Captcha struct { - Base64Captcha *base64Captcha.Captcha -} - -// once 确保 internalCaptcha 对象只初始化一次 -var once sync.Once - -// internalCaptcha 内部使用的 Captcha 对象 -var internalCaptcha *Captcha - -// NewCaptcha 单例模式获取 -func NewCaptcha() *Captcha { - once.Do(func() { - // 初始化 Captcha 对象 - internalCaptcha = &Captcha{} - - // 使用 Cache facade 进行存储,并配置存储 Key 的前缀 - store := CacheStore{ - KeyPrefix: facades.Config().GetString("app.name") + ":captcha:", - } - - // 配置 base64Captcha 驱动信息 - driver := base64Captcha.NewDriverDigit( - facades.Config().GetInt("captcha.height"), // 宽 - facades.Config().GetInt("captcha.width"), // 高 - facades.Config().GetInt("captcha.length"), // 长度 - facades.Config().Get("captcha.maxskew").(float64), // 数字的最大倾斜角度 - facades.Config().GetInt("captcha.dotcount"), // 图片背景里的混淆点数量 - ) - - // 实例化 base64Captcha 并赋值给内部使用的 internalCaptcha 对象 - internalCaptcha.Base64Captcha = base64Captcha.NewCaptcha(driver, &store) - }) - - return internalCaptcha -} - -// GenerateCaptcha 生成图片验证码 -func (c *Captcha) GenerateCaptcha() (id string, b64s string, err error) { - id, b64s, _, err = c.Base64Captcha.Generate() - return id, b64s, err -} - -// VerifyCaptcha 验证验证码是否正确 -func (c *Captcha) VerifyCaptcha(id string, answer string, clear bool) (match bool) { - - // 方便本地和 API 自动测试 - if facades.Config().GetBool("app.debug") && id == facades.Config().GetString("captcha.testing_key") { - return true - } - // 这样方便用户多次提交,防止表单提交错误需要多次输入图片验证码 - return c.Base64Captcha.Verify(id, answer, clear) -} diff --git a/pkg/captcha/captcha_test.go b/pkg/captcha/captcha_test.go deleted file mode 100644 index f64ba08464..0000000000 --- a/pkg/captcha/captcha_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package captcha - -import ( - "testing" - "time" - - "github.com/goravel/framework/testing/mock" - testifymock "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" -) - -type CaptchaTestSuite struct { - suite.Suite - captcha *Captcha -} - -func TestCaptchaTestSuite(t *testing.T) { - facade := mock.Factory() - mockConfig := facade.Config() - mockConfig.On("GetString", "app.name").Return("HaoZiPanel").Once() - mockConfig.On("GetInt", "captcha.height").Return(80).Once() - mockConfig.On("GetInt", "captcha.width").Return(240).Once() - mockConfig.On("GetInt", "captcha.length").Return(4).Once() - mockConfig.On("Get", "captcha.maxskew").Return(0.7).Once() - mockConfig.On("GetInt", "captcha.dotcount").Return(80).Once() - mockConfig.On("GetInt", "captcha.expire_time").Return(5).Once() - mockConfig.On("GetInt", "captcha.debug_expire_time").Return(10).Once() - mockConfig.On("GetBool", "app.debug").Return(true).Once() - mockCache := facade.Cache() - mockCache.On("Put", testifymock.Anything, testifymock.Anything, time.Minute*time.Duration(10)).Return(nil).Once() - - suite.Run(t, &CaptchaTestSuite{ - captcha: NewCaptcha(), - }) - - mockConfig.AssertExpectations(t) -} - -func (s *CaptchaTestSuite) TestGenerateCaptcha() { - id, base64, err := s.captcha.GenerateCaptcha() - - s.NotEmpty(id) - s.NotEmpty(base64) - s.Nil(err) -} diff --git a/pkg/captcha/store_cache.go b/pkg/captcha/store_cache.go deleted file mode 100644 index 5c348089bf..0000000000 --- a/pkg/captcha/store_cache.go +++ /dev/null @@ -1,45 +0,0 @@ -package captcha - -import ( - "time" - - "github.com/goravel/framework/facades" -) - -// CacheStore 实现 base64Captcha.Store interface -type CacheStore struct { - KeyPrefix string -} - -// Set 实现 base64Captcha.Store interface 的 Set 方法 -func (s *CacheStore) Set(key string, value string) error { - - ExpireTime := time.Minute * time.Duration(facades.Config().GetInt("captcha.expire_time")) - // 方便本地开发调试 - if facades.Config().GetBool("app.debug") { - ExpireTime = time.Minute * time.Duration(facades.Config().GetInt("captcha.debug_expire_time")) - } - - err := facades.Cache().Put(s.KeyPrefix+key, value, ExpireTime) - if err != nil { - return err - } - - return nil -} - -// Get 实现 base64Captcha.Store interface 的 Get 方法 -func (s *CacheStore) Get(key string, clear bool) string { - key = s.KeyPrefix + key - val := facades.Cache().Get(key, "").(string) - if clear { - facades.Cache().Forget(key) - } - return val -} - -// Verify 实现 base64Captcha.Store interface 的 Verify 方法 -func (s *CacheStore) Verify(key, answer string, clear bool) bool { - v := s.Get(key, clear) - return v == answer -}