mirror of
https://gitee.com/admpub/nging.git
synced 2025-12-06 07:49:32 +08:00
update
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package formbuilder
|
||||
|
||||
import (
|
||||
"github.com/webx-top/echo"
|
||||
"errors"
|
||||
|
||||
"github.com/webx-top/echo/formfilter"
|
||||
"github.com/webx-top/validation"
|
||||
)
|
||||
|
||||
type MethodHook func() error
|
||||
@@ -17,7 +19,7 @@ func (hooks MethodHooks) On(method string, funcs ...MethodHook) {
|
||||
|
||||
func (hooks MethodHooks) Off(methods ...string) {
|
||||
for _, method := range methods {
|
||||
if _, ok := hooks[method]; !ok {
|
||||
if _, ok := hooks[method]; ok {
|
||||
delete(hooks, method)
|
||||
}
|
||||
}
|
||||
@@ -31,35 +33,34 @@ func (hooks MethodHooks) OffAll() {
|
||||
|
||||
func (hooks MethodHooks) Fire(method string) error {
|
||||
funcs, ok := hooks[method]
|
||||
if ok {
|
||||
for _, fn := range funcs {
|
||||
if err := fn(); err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
var err error
|
||||
for _, fn := range funcs {
|
||||
if err = fn(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func BindModel(ctx echo.Context, form *FormBuilder) MethodHook {
|
||||
func BindModel(form *FormBuilder) MethodHook {
|
||||
return func() error {
|
||||
opts := []formfilter.Options{formfilter.Include(form.Config().GetNames()...)}
|
||||
if customs, ok := ctx.Internal().Get(`formfilter.Options`).([]formfilter.Options); ok {
|
||||
opts = append(opts, customs...)
|
||||
}
|
||||
return ctx.MustBind(form.Model, formfilter.Build(opts...))
|
||||
opts = append(opts, form.filters...)
|
||||
return form.ctx.MustBind(form.Model, formfilter.Build(opts...))
|
||||
}
|
||||
}
|
||||
|
||||
func ValidModel(ctx echo.Context, form *FormBuilder) MethodHook {
|
||||
func ValidModel(form *FormBuilder) MethodHook {
|
||||
return func() error {
|
||||
form.ValidFromConfig()
|
||||
valid := form.Validate()
|
||||
var err error
|
||||
if valid.HasError() {
|
||||
err = valid.Errors[0]
|
||||
ctx.Data().SetInfo(valid.Errors[0].Message, 0).SetZone(valid.Errors[0].Field)
|
||||
err := form.Validate().Error()
|
||||
if !errors.Is(err, validation.NoError) {
|
||||
form.ctx.Data().SetInfo(err.Message, 0).SetZone(err.Field)
|
||||
return err
|
||||
}
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,12 @@ import (
|
||||
"github.com/coscms/forms/common"
|
||||
"github.com/coscms/forms/config"
|
||||
"github.com/coscms/forms/fields"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/webx-top/db/lib/factory"
|
||||
"github.com/webx-top/echo"
|
||||
"github.com/webx-top/echo/formfilter"
|
||||
echoMw "github.com/webx-top/echo/middleware"
|
||||
"github.com/webx-top/echo/middleware/render/driver"
|
||||
)
|
||||
|
||||
@@ -27,8 +30,8 @@ func New(ctx echo.Context, model interface{}, options ...Option) *FormBuilder {
|
||||
ctx: ctx,
|
||||
}
|
||||
defaultHooks := []MethodHook{
|
||||
BindModel(ctx, f),
|
||||
ValidModel(ctx, f),
|
||||
BindModel(f),
|
||||
ValidModel(f),
|
||||
}
|
||||
f.OnPost(defaultHooks...)
|
||||
f.OnPut(defaultHooks...)
|
||||
@@ -38,7 +41,7 @@ func New(ctx echo.Context, model interface{}, options ...Option) *FormBuilder {
|
||||
if option == nil {
|
||||
continue
|
||||
}
|
||||
option(ctx, f)
|
||||
option(f)
|
||||
}
|
||||
f.SetLabelFunc(func(txt string) string {
|
||||
return ctx.T(txt)
|
||||
@@ -49,10 +52,9 @@ func New(ctx echo.Context, model interface{}, options ...Option) *FormBuilder {
|
||||
f.Elements(fields.HiddenField(echo.DefaultNextURLVarName).SetValue(nextURL))
|
||||
}
|
||||
})
|
||||
csrfToken, ok := ctx.Get(`csrf`).(string)
|
||||
if ok {
|
||||
if csrfToken := ctx.Internal().String(echoMw.DefaultCSRFConfig.ContextKey); len(csrfToken) > 0 {
|
||||
f.AddBeforeRender(func() {
|
||||
f.Elements(fields.HiddenField(`csrf`).SetValue(csrfToken))
|
||||
f.Elements(fields.HiddenField(echoMw.DefaultCSRFConfig.ContextKey).SetValue(csrfToken))
|
||||
})
|
||||
}
|
||||
ctx.Set(`forms`, f.Forms)
|
||||
@@ -69,6 +71,7 @@ type FormBuilder struct {
|
||||
configFile string
|
||||
dbi *factory.DBI
|
||||
defaults map[string]string
|
||||
filters []formfilter.Options
|
||||
}
|
||||
|
||||
// Exited 是否需要退出后续处理。此时一般有err值,用于记录错误原因
|
||||
@@ -103,35 +106,63 @@ func (f *FormBuilder) Error() error {
|
||||
}
|
||||
|
||||
// ParseConfigFile 解析配置文件 xxx.form.json
|
||||
func (f *FormBuilder) ParseConfigFile() error {
|
||||
jsonFile := f.configFile
|
||||
func (f *FormBuilder) ParseConfigFile(jsonformat ...bool) error {
|
||||
configFile := f.configFile + `.form`
|
||||
var cfg *config.Config
|
||||
renderer := f.ctx.Renderer().(driver.Driver)
|
||||
jsonFile += `.form.json`
|
||||
jsonFile = renderer.TmplPath(f.ctx, jsonFile)
|
||||
if len(jsonFile) == 0 {
|
||||
renderer, ok := f.ctx.Renderer().(driver.Driver)
|
||||
if !ok {
|
||||
return fmt.Errorf(`FormBuilder: Expected renderer is "driver.Driver", but got "%T"`, f.ctx.Renderer())
|
||||
}
|
||||
var isJSON bool
|
||||
if len(jsonformat) > 0 {
|
||||
isJSON = jsonformat[0]
|
||||
}
|
||||
if isJSON {
|
||||
configFile += `.json`
|
||||
} else {
|
||||
configFile += `.yaml`
|
||||
}
|
||||
configFile = renderer.TmplPath(f.ctx, configFile)
|
||||
if len(configFile) == 0 {
|
||||
return ErrJSONConfigFileNameInvalid
|
||||
}
|
||||
b, err := renderer.RawContent(jsonFile)
|
||||
b, err := renderer.RawContent(configFile)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) /* && !strings.Contains(err.Error(), `file does not exist`)*/ || renderer.Manager() == nil {
|
||||
return fmt.Errorf(`read file %s: %w`, jsonFile, err)
|
||||
if !os.IsNotExist(err) || renderer.Manager() == nil {
|
||||
return fmt.Errorf(`read file %s: %w`, configFile, err)
|
||||
}
|
||||
cfg = f.ToConfig()
|
||||
var jsonb []byte
|
||||
jsonb, err = f.ToJSONBlob(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`[form.ToJSONBlob] %s: %w`, jsonFile, err)
|
||||
if isJSON {
|
||||
b, err = f.ToJSONBlob(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`[form.ToJSONBlob] %s: %w`, configFile, err)
|
||||
}
|
||||
} else {
|
||||
b, err = yaml.Marshal(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`[form:yaml.Marshal] %s: %w`, configFile, err)
|
||||
}
|
||||
}
|
||||
err = renderer.Manager().SetTemplate(jsonFile, jsonb)
|
||||
err = renderer.Manager().SetTemplate(configFile, b)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`%s: %w`, jsonFile, err)
|
||||
return fmt.Errorf(`%s: %w`, configFile, err)
|
||||
}
|
||||
f.ctx.Logger().Infof(f.ctx.T(`生成表单配置文件“%v”成功。`), jsonFile)
|
||||
f.ctx.Logger().Infof(f.ctx.T(`生成表单配置文件“%v”成功。`), configFile)
|
||||
} else {
|
||||
cfg, err = forms.Unmarshal(b, jsonFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`[forms.Unmarshal] %s: %w`, jsonFile, err)
|
||||
if isJSON {
|
||||
cfg, err = forms.Unmarshal(b, configFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`[forms.Unmarshal] %s: %w`, configFile, err)
|
||||
}
|
||||
} else {
|
||||
cfg, err = common.GetOrSetCachedConfig(configFile, func() (*config.Config, error) {
|
||||
cfg := &config.Config{}
|
||||
err := yaml.Unmarshal(b, cfg)
|
||||
return cfg, err
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf(`[form:yaml.Unmarshal] %s: %w`, configFile, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if cfg == nil {
|
||||
@@ -188,12 +219,13 @@ func (f *FormBuilder) DefaultValue(fieldName string) string {
|
||||
|
||||
// RecvSubmission 接收客户端的提交
|
||||
func (f *FormBuilder) RecvSubmission() error {
|
||||
method := strings.ToUpper(f.ctx.Method())
|
||||
ctx := f.ctx
|
||||
method := strings.ToUpper(ctx.Method())
|
||||
if f.err = f.on.Fire(method); f.err != nil {
|
||||
return f.err
|
||||
}
|
||||
f.err = f.on.Fire(`*`)
|
||||
if f.ctx.Response().Committed() {
|
||||
if ctx.Response().Committed() {
|
||||
f.exit = true
|
||||
}
|
||||
return f.err
|
||||
|
||||
107
application/library/formbuilder/formbuilder_test.go
Normal file
107
application/library/formbuilder/formbuilder_test.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package formbuilder_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/admpub/log"
|
||||
"github.com/admpub/nging/v5/application/dbschema"
|
||||
"github.com/admpub/nging/v5/application/library/formbuilder"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/webx-top/com"
|
||||
"github.com/webx-top/echo"
|
||||
"github.com/webx-top/echo/defaults"
|
||||
"github.com/webx-top/echo/middleware/render"
|
||||
"github.com/webx-top/echo/param"
|
||||
)
|
||||
|
||||
var (
|
||||
_ echo.BeforeValidate = &TestRequest{}
|
||||
_ echo.AfterValidate = &TestRequest{}
|
||||
)
|
||||
|
||||
type TestRequest struct {
|
||||
Name string `json:"name"`
|
||||
Age uint `json:"age"`
|
||||
}
|
||||
|
||||
func (t *TestRequest) BeforeValidate(ctx echo.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TestRequest) AfterValidate(ctx echo.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestFormbuilder(t *testing.T) {
|
||||
defer log.Close()
|
||||
com.MkdirAll(`testdata/template`, os.ModePerm)
|
||||
d := render.New(`standard`, `testdata/template`)
|
||||
d.Init()
|
||||
defaults.Use(render.Middleware(d))
|
||||
|
||||
bean := &TestRequest{}
|
||||
ctx := defaults.NewMockContext()
|
||||
ctx.SetRenderer(d)
|
||||
form := formbuilder.New(ctx, bean,
|
||||
formbuilder.DBI(dbschema.DBI),
|
||||
formbuilder.ConfigFile(`test`))
|
||||
form.OnPost(func() error {
|
||||
var err error
|
||||
fmt.Printf("%#v\n", bean)
|
||||
return err
|
||||
})
|
||||
form.Generate()
|
||||
//fmt.Printf("%#v\n", ctx.Get(`forms`))
|
||||
assert.Equal(t, form.Forms, ctx.Get(`forms`))
|
||||
htmlResult := string(form.Render())
|
||||
var spaceClearRegex = regexp.MustCompile(`(>)[\s]+(&|<)`)
|
||||
htmlResult = spaceClearRegex.ReplaceAllString(htmlResult, `$1$2`)
|
||||
expected := `<form generator="forms" class="form-horizontal" id="Forms" role="form" method="POST" action="" required-redstar="true">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Name</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" name="Name" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Age</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" name="Age" class="form-control" value="0">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group form-submit-group">
|
||||
<div class="col-md-offset-2 col-md-10">
|
||||
<button type="submit" class='btn btn-lg btn-primary'>
|
||||
<i class="fa fa-check"></i>
|
||||
Submit
|
||||
</button>
|
||||
|
||||
<button type="reset" class='btn btn-lg'>
|
||||
<i class="fa fa-undo"></i>
|
||||
Reset
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>`
|
||||
expected = spaceClearRegex.ReplaceAllString(expected, `$1$2`)
|
||||
//assert.Equal(t, expected, htmlResult)
|
||||
|
||||
// -----
|
||||
expectedReq := &TestRequest{
|
||||
Name: `test`,
|
||||
Age: 123,
|
||||
}
|
||||
ctx.Request().SetMethod(`POST`)
|
||||
ctx.Request().Form().Set(`name`, expectedReq.Name)
|
||||
ctx.Request().Form().Set(`age`, param.AsString(expectedReq.Age))
|
||||
err := form.RecvSubmission()
|
||||
if form.Exited() {
|
||||
err = form.Error()
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expectedReq, bean)
|
||||
}
|
||||
@@ -2,43 +2,35 @@ package formbuilder
|
||||
|
||||
import (
|
||||
"github.com/webx-top/db/lib/factory"
|
||||
"github.com/webx-top/echo"
|
||||
"github.com/webx-top/echo/formfilter"
|
||||
)
|
||||
|
||||
type Option func(echo.Context, *FormBuilder)
|
||||
type Option func(*FormBuilder)
|
||||
|
||||
// IgnoreFields 疏略某些字段的验证
|
||||
func IgnoreFields(ignoreFields ...string) Option {
|
||||
return func(_ echo.Context, form *FormBuilder) {
|
||||
return func(form *FormBuilder) {
|
||||
form.CloseValid(ignoreFields...)
|
||||
}
|
||||
}
|
||||
|
||||
// ValidFields 指定仅仅验证某些字段
|
||||
func ValidFields(validFields ...string) Option {
|
||||
return func(c echo.Context, form *FormBuilder) {
|
||||
c.Internal().Set(`formbuilder.validFields`, validFields)
|
||||
}
|
||||
}
|
||||
|
||||
// Theme 设置forms模板风格
|
||||
func Theme(theme string) Option {
|
||||
return func(_ echo.Context, form *FormBuilder) {
|
||||
return func(form *FormBuilder) {
|
||||
form.Theme = theme
|
||||
}
|
||||
}
|
||||
|
||||
// FormFilter 设置表单过滤
|
||||
func FormFilter(filters ...formfilter.Options) Option {
|
||||
return func(c echo.Context, _ *FormBuilder) {
|
||||
c.Internal().Set(`formfilter.Options`, filters)
|
||||
return func(form *FormBuilder) {
|
||||
form.filters = filters
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigFile 指定要解析的配置文件。如果silent=true则仅仅设置配置文件而不解析
|
||||
func ConfigFile(jsonFile string, silent ...bool) Option {
|
||||
return func(_ echo.Context, f *FormBuilder) {
|
||||
return func(f *FormBuilder) {
|
||||
f.configFile = jsonFile
|
||||
if len(silent) > 0 && silent[0] {
|
||||
return
|
||||
@@ -51,14 +43,14 @@ func ConfigFile(jsonFile string, silent ...bool) Option {
|
||||
|
||||
// RenderBefore 设置渲染表单前的钩子函数
|
||||
func RenderBefore(fn func()) Option {
|
||||
return func(_ echo.Context, f *FormBuilder) {
|
||||
return func(f *FormBuilder) {
|
||||
f.AddBeforeRender(fn)
|
||||
}
|
||||
}
|
||||
|
||||
// DBI 指定模型数据表所属DBI(数据库信息)
|
||||
func DBI(dbi *factory.DBI) Option {
|
||||
return func(_ echo.Context, f *FormBuilder) {
|
||||
return func(f *FormBuilder) {
|
||||
f.dbi = dbi
|
||||
}
|
||||
}
|
||||
|
||||
6
go.mod
6
go.mod
@@ -84,7 +84,7 @@ require (
|
||||
github.com/aws/aws-sdk-go v1.45.12
|
||||
github.com/caddy-plugins/webdav v1.2.10
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/coscms/forms v1.12.1
|
||||
github.com/coscms/forms v1.12.2
|
||||
github.com/coscms/go-imgparse v0.0.0-20150925144422-3e3a099f7856
|
||||
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
|
||||
github.com/edwingeng/doublejump v1.0.1 // indirect
|
||||
@@ -124,7 +124,7 @@ require (
|
||||
github.com/webx-top/codec v0.3.0
|
||||
github.com/webx-top/com v1.0.1
|
||||
github.com/webx-top/db v1.27.0
|
||||
github.com/webx-top/echo v2.38.4+incompatible
|
||||
github.com/webx-top/echo v2.39.2+incompatible
|
||||
github.com/webx-top/image v0.1.0
|
||||
github.com/webx-top/pagination v0.2.7 // indirect
|
||||
golang.org/x/crypto v0.13.0
|
||||
@@ -158,6 +158,7 @@ require (
|
||||
github.com/webx-top/validation v0.0.3
|
||||
github.com/webx-top/validator v0.2.0
|
||||
golang.org/x/text v0.13.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -374,6 +375,5 @@ require (
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
rsc.io/qr v0.2.0 // indirect
|
||||
)
|
||||
|
||||
8
go.sum
8
go.sum
@@ -813,8 +813,8 @@ github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/coscms/forms v1.12.1 h1:eBaLlNE+rVFShEq2qflMWn0LhtFLTJmrBwGQ/gKYlf4=
|
||||
github.com/coscms/forms v1.12.1/go.mod h1:WsTYDKG+4cXt1wBNsqv9hFJ34sdkRHai9n/scu4ap2g=
|
||||
github.com/coscms/forms v1.12.2 h1:ag3NvoXNWiVTUcbeO4cukkMPhe5XAMYbq462ZG8x2Zg=
|
||||
github.com/coscms/forms v1.12.2/go.mod h1:WsTYDKG+4cXt1wBNsqv9hFJ34sdkRHai9n/scu4ap2g=
|
||||
github.com/coscms/go-imgparse v0.0.0-20150925144422-3e3a099f7856 h1:P8+R76nNN/kIx12ptxkfbwhhiuDVwf5hLA6qVZSfe5M=
|
||||
github.com/coscms/go-imgparse v0.0.0-20150925144422-3e3a099f7856/go.mod h1:hMGWSVn9gPkG9ERZdzfh1DIP5Yvued94t9cgVzErOC0=
|
||||
github.com/coscms/webauthn v0.2.7 h1:bIPnIgld0sXf7nV79UZp5DGA3NVzDuyPNXHnjU8iFNg=
|
||||
@@ -2074,8 +2074,8 @@ github.com/webx-top/db v1.27.0/go.mod h1:roceE5x2EX0eKOcQpW4URy+8iNfqKGiP6n+wrgj
|
||||
github.com/webx-top/echo v2.18.3+incompatible/go.mod h1:ufVP//GwP1suggBSQW7l8G9XcKxZM+FIfCMElLAQqF8=
|
||||
github.com/webx-top/echo v2.33.3+incompatible/go.mod h1:ufVP//GwP1suggBSQW7l8G9XcKxZM+FIfCMElLAQqF8=
|
||||
github.com/webx-top/echo v2.35.2+incompatible/go.mod h1:ufVP//GwP1suggBSQW7l8G9XcKxZM+FIfCMElLAQqF8=
|
||||
github.com/webx-top/echo v2.38.4+incompatible h1:xX3T+WdGu/Obgw09C+MiKSFQ5f7bkvP+UsFq5QEWDeg=
|
||||
github.com/webx-top/echo v2.38.4+incompatible/go.mod h1:ufVP//GwP1suggBSQW7l8G9XcKxZM+FIfCMElLAQqF8=
|
||||
github.com/webx-top/echo v2.39.2+incompatible h1:qJ8ln154yd+WQDmhGO9UtsSz7fqvtWsyoqCqMdYekFw=
|
||||
github.com/webx-top/echo v2.39.2+incompatible/go.mod h1:ufVP//GwP1suggBSQW7l8G9XcKxZM+FIfCMElLAQqF8=
|
||||
github.com/webx-top/echo-prometheus v1.0.7/go.mod h1:d+/TpxZTP8k7yG1vo1Nlxyk5YVQ4p9Mow0mjqJUk1uU=
|
||||
github.com/webx-top/echo-prometheus v1.1.1 h1:Z41F5A7R4pC/oLlQta/1uEZybOfnY1BCUvNC3dM5RZg=
|
||||
github.com/webx-top/echo-prometheus v1.1.1/go.mod h1:T4mJg71spjV3J8IJQ+2EN/hQUB+FgWWsSXZCQ0KoalE=
|
||||
|
||||
2
updatemod.sh
Executable file
2
updatemod.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
9
vendor/github.com/coscms/forms/common/tplfunc.go
generated
vendored
9
vendor/github.com/coscms/forms/common/tplfunc.go
generated
vendored
@@ -16,13 +16,14 @@
|
||||
|
||||
*/
|
||||
|
||||
//Package common This package provides basic constants used by forms packages.
|
||||
// Package common This package provides basic constants used by forms packages.
|
||||
package common
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
@@ -35,7 +36,7 @@ func ParseFiles(files ...string) (*template.Template, error) {
|
||||
return ParseFS(FileSystem, files...)
|
||||
}
|
||||
name := filepath.Base(files[0])
|
||||
b, err := ioutil.ReadFile(files[0])
|
||||
b, err := os.ReadFile(files[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -56,7 +57,7 @@ func ParseFS(fs fs.FS, files ...string) (*template.Template, error) {
|
||||
if err != nil {
|
||||
return tmpl, err
|
||||
}
|
||||
b, err := ioutil.ReadAll(fp)
|
||||
b, err := io.ReadAll(fp)
|
||||
fp.Close()
|
||||
if err != nil {
|
||||
return tmpl, err
|
||||
|
||||
44
vendor/github.com/coscms/forms/forms.go
generated
vendored
44
vendor/github.com/coscms/forms/forms.go
generated
vendored
@@ -343,23 +343,29 @@ func (f *Form) GenChoicesForField(name string, lenType interface{}, fnType inter
|
||||
}
|
||||
|
||||
// GenChoices generate choices
|
||||
// type Data struct{
|
||||
// ID string
|
||||
// Name string
|
||||
// }
|
||||
// data:=[]*Data{
|
||||
// &Data{ID:"a",Name:"One"},
|
||||
// &Data{ID:"b",Name:"Two"},
|
||||
// }
|
||||
// GenChoices(len(data), func(index int) (string, string, bool){
|
||||
// return data[index].ID,data[index].Name,false
|
||||
// })
|
||||
//
|
||||
// type Data struct{
|
||||
// ID string
|
||||
// Name string
|
||||
// }
|
||||
//
|
||||
// data:=[]*Data{
|
||||
// &Data{ID:"a",Name:"One"},
|
||||
// &Data{ID:"b",Name:"Two"},
|
||||
// }
|
||||
//
|
||||
// GenChoices(len(data), func(index int) (string, string, bool){
|
||||
// return data[index].ID,data[index].Name,false
|
||||
// })
|
||||
//
|
||||
// or
|
||||
// GenChoices(map[string]int{
|
||||
// "":len(data),
|
||||
// }, func(group string,index int) (string, string, bool){
|
||||
// return data[index].ID,data[index].Name,false
|
||||
// })
|
||||
//
|
||||
// GenChoices(map[string]int{
|
||||
// "":len(data),
|
||||
// }, func(group string,index int) (string, string, bool){
|
||||
//
|
||||
// return data[index].ID,data[index].Name,false
|
||||
// })
|
||||
func (f *Form) GenChoices(lenType interface{}, fnType interface{}) interface{} {
|
||||
return GenChoices(lenType, fnType)
|
||||
}
|
||||
@@ -396,9 +402,9 @@ func (form *Form) unWindStructure(m interface{}, baseName string) ([]interface{}
|
||||
options[opt] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, ok := options["-"]; ok {
|
||||
continue
|
||||
if _, ok := options["-"]; ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
widget := common.TagVal(t, i, "form_widget")
|
||||
var f fields.FieldInterface
|
||||
|
||||
4
vendor/github.com/coscms/forms/json.go
generated
vendored
4
vendor/github.com/coscms/forms/json.go
generated
vendored
@@ -18,8 +18,8 @@ package forms
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
@@ -41,7 +41,7 @@ func UnmarshalFile(filename string) (r *config.Config, err error) {
|
||||
return
|
||||
}
|
||||
return common.GetOrSetCachedConfig(filename, func() (*config.Config, error) {
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
b, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
3
vendor/github.com/webx-top/echo/engine/fasthttp/request.go
generated
vendored
3
vendor/github.com/webx-top/echo/engine/fasthttp/request.go
generated
vendored
@@ -8,7 +8,6 @@ import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -122,7 +121,7 @@ func (r *Request) SetMethod(method string) {
|
||||
}
|
||||
|
||||
func (r *Request) Body() io.ReadCloser {
|
||||
return ioutil.NopCloser(bytes.NewBuffer(r.context.PostBody()))
|
||||
return io.NopCloser(bytes.NewBuffer(r.context.PostBody()))
|
||||
}
|
||||
|
||||
// SetBody implements `engine.Request#SetBody` function.
|
||||
|
||||
3
vendor/github.com/webx-top/echo/engine/mock/response.go
generated
vendored
3
vendor/github.com/webx-top/echo/engine/mock/response.go
generated
vendored
@@ -4,7 +4,6 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -239,7 +238,7 @@ func (r *Response) StdResponseWriter() http.ResponseWriter {
|
||||
|
||||
func NewResponseWriter(w *http.Response) http.ResponseWriter {
|
||||
b := bytes.NewBuffer(nil)
|
||||
w.Body = ioutil.NopCloser(b)
|
||||
w.Body = io.NopCloser(b)
|
||||
return &ResponseWriter{
|
||||
Response: w,
|
||||
bytes: b,
|
||||
|
||||
3
vendor/github.com/webx-top/echo/engine/standard/request.go
generated
vendored
3
vendor/github.com/webx-top/echo/engine/standard/request.go
generated
vendored
@@ -3,7 +3,6 @@ package standard
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"sync"
|
||||
@@ -119,7 +118,7 @@ func (r *Request) SetBody(reader io.Reader) {
|
||||
if readCloser, ok := reader.(io.ReadCloser); ok {
|
||||
r.request.Body = readCloser
|
||||
} else {
|
||||
r.request.Body = ioutil.NopCloser(reader)
|
||||
r.request.Body = io.NopCloser(reader)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
4
vendor/github.com/webx-top/echo/error.go
generated
vendored
4
vendor/github.com/webx-top/echo/error.go
generated
vendored
@@ -23,8 +23,8 @@ import (
|
||||
"fmt"
|
||||
"html"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -378,7 +378,7 @@ func (p *PanicError) AddTrace(trace *Trace, content ...string) *PanicError {
|
||||
}
|
||||
|
||||
func (p *PanicError) ExtractFileSnippets(file string, curLineNum int, index int) error {
|
||||
content, err := ioutil.ReadFile(file)
|
||||
content, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
4
vendor/github.com/webx-top/echo/middleware/bindata/manager.go
generated
vendored
4
vendor/github.com/webx-top/echo/middleware/bindata/manager.go
generated
vendored
@@ -20,7 +20,7 @@ package bindata
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/webx-top/echo/middleware/render/driver"
|
||||
@@ -46,6 +46,6 @@ func (a *TmplManager) GetTemplate(fileName string) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
b, err := ioutil.ReadAll(file)
|
||||
b, err := io.ReadAll(file)
|
||||
return b, err
|
||||
}
|
||||
|
||||
5
vendor/github.com/webx-top/echo/middleware/compress.go
generated
vendored
5
vendor/github.com/webx-top/echo/middleware/compress.go
generated
vendored
@@ -4,7 +4,6 @@ import (
|
||||
"bufio"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -135,7 +134,7 @@ func GzipWithConfig(config *GzipConfig) echo.MiddlewareFunc {
|
||||
// nothing is written to body or error is returned.
|
||||
// See issue #424, #407.
|
||||
resp.SetWriter(rw)
|
||||
w.Reset(ioutil.Discard)
|
||||
w.Reset(io.Discard)
|
||||
}
|
||||
w.Close()
|
||||
pool.Put(w)
|
||||
@@ -150,7 +149,7 @@ func GzipWithConfig(config *GzipConfig) echo.MiddlewareFunc {
|
||||
func gzipCompressPool(config *GzipConfig) sync.Pool {
|
||||
return sync.Pool{
|
||||
New: func() interface{} {
|
||||
w, err := gzip.NewWriterLevel(ioutil.Discard, config.Level)
|
||||
w, err := gzip.NewWriterLevel(io.Discard, config.Level)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
83
vendor/github.com/webx-top/echo/middleware/csrf.go
generated
vendored
83
vendor/github.com/webx-top/echo/middleware/csrf.go
generated
vendored
@@ -34,29 +34,9 @@ type (
|
||||
// Optional. Default value "csrf".
|
||||
ContextKey string `json:"context_key"`
|
||||
|
||||
// Name of the CSRF cookie. This cookie will store CSRF token.
|
||||
// Optional. Default value "csrf".
|
||||
CookieName string `json:"cookie_name"`
|
||||
|
||||
// Domain of the CSRF cookie.
|
||||
// Optional. Default value none.
|
||||
CookieDomain string `json:"cookie_domain"`
|
||||
|
||||
// Path of the CSRF cookie.
|
||||
// Optional. Default value none.
|
||||
CookiePath string `json:"cookie_path"`
|
||||
|
||||
// Max age (in seconds) of the CSRF cookie.
|
||||
// Optional. Default value 86400 (24hr).
|
||||
CookieMaxAge int `json:"cookie_max_age"`
|
||||
|
||||
// Indicates if CSRF cookie is secure.
|
||||
// Optional. Default value false.
|
||||
CookieSecure bool `json:"cookie_secure"`
|
||||
|
||||
// Indicates if CSRF cookie is HTTP only.
|
||||
// Optional. Default value false.
|
||||
CookieHTTPOnly bool `json:"cookie_http_only"`
|
||||
// Name of the CSRF session. This session will store CSRF token.
|
||||
// Optional. Default value "_csrf".
|
||||
SessionName string `json:"session_name"`
|
||||
}
|
||||
|
||||
// csrfTokenExtractor defines a function that takes `echo.Context` and returns
|
||||
@@ -67,12 +47,11 @@ type (
|
||||
var (
|
||||
// DefaultCSRFConfig is the default CSRF middleware config.
|
||||
DefaultCSRFConfig = CSRFConfig{
|
||||
Skipper: echo.DefaultSkipper,
|
||||
TokenLength: 32,
|
||||
TokenLookup: "header:" + echo.HeaderXCSRFToken,
|
||||
ContextKey: "csrf",
|
||||
CookieName: "_csrf",
|
||||
CookieMaxAge: 86400,
|
||||
Skipper: echo.DefaultSkipper,
|
||||
TokenLength: 32,
|
||||
TokenLookup: "header:" + echo.HeaderXCSRFToken,
|
||||
ContextKey: "csrf",
|
||||
SessionName: "_csrf",
|
||||
}
|
||||
ErrCSRFTokenInvalid = errors.New("csrf token is invalid")
|
||||
ErrCSRFTokenIsEmpty = errors.New("empty csrf token")
|
||||
@@ -102,21 +81,19 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFuncd {
|
||||
if config.ContextKey == "" {
|
||||
config.ContextKey = DefaultCSRFConfig.ContextKey
|
||||
}
|
||||
if config.CookieName == "" {
|
||||
config.CookieName = DefaultCSRFConfig.CookieName
|
||||
if config.SessionName == "" {
|
||||
config.SessionName = DefaultCSRFConfig.SessionName
|
||||
}
|
||||
if config.CookieMaxAge == 0 {
|
||||
config.CookieMaxAge = DefaultCSRFConfig.CookieMaxAge
|
||||
}
|
||||
|
||||
// Initialize
|
||||
parts := strings.Split(config.TokenLookup, ":")
|
||||
parts := strings.SplitN(config.TokenLookup, ":", 2)
|
||||
extractor := csrfTokenFromHeader(parts[1])
|
||||
switch parts[0] {
|
||||
case "form":
|
||||
extractor = csrfTokenFromForm(parts[1])
|
||||
case "query":
|
||||
extractor = csrfTokenFromQuery(parts[1])
|
||||
case "any":
|
||||
extractor = csrfTokenFromAny(parts[1])
|
||||
}
|
||||
|
||||
return func(next echo.Handler) echo.HandlerFunc {
|
||||
@@ -125,8 +102,7 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFuncd {
|
||||
return next.Handle(c)
|
||||
}
|
||||
req := c.Request()
|
||||
token := c.GetCookie(config.CookieName)
|
||||
|
||||
token, _ := c.Session().Get(config.SessionName).(string)
|
||||
if len(token) == 0 {
|
||||
// Generate token
|
||||
token = random.String(config.TokenLength)
|
||||
@@ -144,20 +120,12 @@ func CSRFWithConfig(config CSRFConfig) echo.MiddlewareFuncd {
|
||||
return echo.NewHTTPError(http.StatusForbidden, ErrCSRFTokenInvalid.Error()).SetRaw(ErrCSRFTokenInvalid)
|
||||
}
|
||||
}
|
||||
// Set CSRF cookie
|
||||
cookie := echo.NewCookie(config.CookieName, token, c.CookieOptions())
|
||||
if len(config.CookiePath) > 0 {
|
||||
cookie.Path = config.CookiePath
|
||||
}
|
||||
if len(config.CookieDomain) > 0 {
|
||||
cookie.Domain = config.CookieDomain
|
||||
}
|
||||
echo.CookieMaxAge(cookie, config.CookieMaxAge)
|
||||
cookie.Secure = config.CookieSecure
|
||||
cookie.HttpOnly = config.CookieHTTPOnly
|
||||
|
||||
// Store CSRF
|
||||
c.Session().Set(config.SessionName, token)
|
||||
|
||||
// Store token in the context
|
||||
c.Set(config.ContextKey, token)
|
||||
c.Internal().Set(config.ContextKey, token)
|
||||
|
||||
// Protect clients from caching the response
|
||||
c.Response().Header().Add(echo.HeaderVary, echo.HeaderCookie)
|
||||
@@ -199,6 +167,21 @@ func csrfTokenFromQuery(param string) csrfTokenExtractor {
|
||||
}
|
||||
}
|
||||
|
||||
func csrfTokenFromAny(key string) csrfTokenExtractor {
|
||||
return func(c echo.Context) (string, error) {
|
||||
token := c.Request().Header().Get(key)
|
||||
if len(token) > 0 {
|
||||
return token, nil
|
||||
}
|
||||
token = c.Form(key)
|
||||
if len(token) > 0 {
|
||||
return token, nil
|
||||
}
|
||||
token = c.Query(key)
|
||||
return token, nil
|
||||
}
|
||||
}
|
||||
|
||||
func validateCSRFToken(token, clientToken string) bool {
|
||||
return subtle.ConstantTimeCompare([]byte(token), []byte(clientToken)) == 1
|
||||
}
|
||||
|
||||
13
vendor/github.com/webx-top/echo/middleware/render/manager/manager.go
generated
vendored
13
vendor/github.com/webx-top/echo/middleware/render/manager/manager.go
generated
vendored
@@ -20,7 +20,6 @@ package manager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -254,7 +253,7 @@ func (m *Manager) watch() error {
|
||||
}
|
||||
m.onChange(ev.Name, "file", "create")
|
||||
if m.allowCached(ev.Name) {
|
||||
content, err := ioutil.ReadFile(ev.Name)
|
||||
content, err := os.ReadFile(ev.Name)
|
||||
if err != nil {
|
||||
m.Logger.Infof("loaded template %v failed: %v", ev.Name, err)
|
||||
return
|
||||
@@ -279,7 +278,7 @@ func (m *Manager) watch() error {
|
||||
}
|
||||
m.onChange(ev.Name, "file", "modify")
|
||||
if m.allowCached(ev.Name) {
|
||||
content, err := ioutil.ReadFile(ev.Name)
|
||||
content, err := os.ReadFile(ev.Name)
|
||||
if err != nil {
|
||||
m.Logger.Errorf("reloaded template %v failed: %v", ev.Name, err)
|
||||
return
|
||||
@@ -324,7 +323,7 @@ func (m *Manager) cacheAll(rootDir string) error {
|
||||
return nil
|
||||
}
|
||||
if _, ok := m.ignores[filepath.Base(f)]; !ok {
|
||||
content, err := ioutil.ReadFile(f)
|
||||
content, err := os.ReadFile(f)
|
||||
if err != nil {
|
||||
m.Logger.Debugf("load template %s error: %v", f, err)
|
||||
return err
|
||||
@@ -348,7 +347,7 @@ func (m *Manager) GetTemplate(tmpl string) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
if !m.allowCached(tmplPath) {
|
||||
return ioutil.ReadFile(tmplPath)
|
||||
return os.ReadFile(tmplPath)
|
||||
}
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
@@ -356,7 +355,7 @@ func (m *Manager) GetTemplate(tmpl string) ([]byte, error) {
|
||||
m.Logger.Debugf("load template %v from cache", tmplPath)
|
||||
return content, nil
|
||||
}
|
||||
content, err := ioutil.ReadFile(tmplPath)
|
||||
content, err := os.ReadFile(tmplPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -372,7 +371,7 @@ func (m *Manager) SetTemplate(tmpl string, content []byte) error {
|
||||
}
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
err = ioutil.WriteFile(tmplPath, content, 0666)
|
||||
err = os.WriteFile(tmplPath, content, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
4
vendor/github.com/webx-top/echo/middleware/render/standard/standard.go
generated
vendored
4
vendor/github.com/webx-top/echo/middleware/render/standard/standard.go
generated
vendored
@@ -27,7 +27,7 @@ import (
|
||||
"fmt"
|
||||
htmlTpl "html/template"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -572,7 +572,7 @@ func (a *Standard) RawContent(tmpl string) (b []byte, e error) {
|
||||
if a.TemplateMgr != nil {
|
||||
b, e = a.TemplateMgr.GetTemplate(tmpl)
|
||||
} else {
|
||||
b, e = ioutil.ReadFile(tmpl)
|
||||
b, e = os.ReadFile(tmpl)
|
||||
}
|
||||
if e != nil {
|
||||
return
|
||||
|
||||
5
vendor/github.com/webx-top/echo/middleware/session/default.go
generated
vendored
5
vendor/github.com/webx-top/echo/middleware/session/default.go
generated
vendored
@@ -2,7 +2,6 @@ package session
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
@@ -61,7 +60,7 @@ func registerSessionStore() error {
|
||||
}
|
||||
r := &cookieSecretKey{}
|
||||
cookieSecretFile := filepath.Join(tempDir, `cookiesecret`)
|
||||
b, err := ioutil.ReadFile(cookieSecretFile)
|
||||
b, err := os.ReadFile(cookieSecretFile)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
@@ -75,7 +74,7 @@ func registerSessionStore() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(cookieSecretFile, b, os.ModePerm)
|
||||
err = os.WriteFile(cookieSecretFile, b, os.ModePerm)
|
||||
}
|
||||
|
||||
//==================================
|
||||
|
||||
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@@ -564,7 +564,7 @@ github.com/chromedp/sysutil
|
||||
# github.com/coreos/go-oidc v2.2.1+incompatible
|
||||
## explicit
|
||||
github.com/coreos/go-oidc
|
||||
# github.com/coscms/forms v1.12.1
|
||||
# github.com/coscms/forms v1.12.2
|
||||
## explicit; go 1.16
|
||||
github.com/coscms/forms
|
||||
github.com/coscms/forms/common
|
||||
@@ -1490,7 +1490,7 @@ github.com/webx-top/db/lib/reflectx
|
||||
github.com/webx-top/db/lib/sqlbuilder
|
||||
github.com/webx-top/db/mysql
|
||||
github.com/webx-top/db/sqlite
|
||||
# github.com/webx-top/echo v2.38.4+incompatible
|
||||
# github.com/webx-top/echo v2.39.2+incompatible
|
||||
## explicit
|
||||
github.com/webx-top/echo
|
||||
github.com/webx-top/echo/code
|
||||
|
||||
Reference in New Issue
Block a user