mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 19:37:18 +08:00
feat: update dependencies
This commit is contained in:
@@ -25,7 +25,6 @@ func (receiver *ValidationServiceProvider) rules() []validation.Rule {
|
||||
return []validation.Rule{
|
||||
&rules.Exists{},
|
||||
&rules.NotExists{},
|
||||
&rules.Captcha{},
|
||||
&rules.PathExists{},
|
||||
&rules.PathNotExists{},
|
||||
}
|
||||
|
||||
@@ -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 ""
|
||||
}
|
||||
@@ -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",
|
||||
})
|
||||
}
|
||||
5
go.mod
5
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
|
||||
|
||||
12
go.sum
12
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=
|
||||
|
||||
@@ -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 连接网络
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user