mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-10-25 03:22:36 +00:00
Refs: https://codeberg.org/forgejo/forgejo/pulls/676 Author: Panagiotis "Ivory" Vasilopoulos <git@n0toose.net> Date: Mon Jun 12 13:57:01 2023 +0200 Co-authored-by: Gusted <postmaster@gusted.xyz> (cherry picked from commitfabdda5c6e) (cherry picked from commitd2c7f45621) (cherry picked from commitdfdbaba3d6) (cherry picked from commita3cda092b8) (cherry picked from commitf0fdb5905c) (cherry picked from commit9697e48c1f)
162 lines
4.5 KiB
Go
162 lines
4.5 KiB
Go
// Copyright 2014 The Gogs Authors. All rights reserved.
|
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package middleware
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
|
|
"code.gitea.io/gitea/modules/setting"
|
|
"code.gitea.io/gitea/modules/translation"
|
|
"code.gitea.io/gitea/modules/util"
|
|
"code.gitea.io/gitea/modules/validation"
|
|
|
|
"gitea.com/go-chi/binding"
|
|
)
|
|
|
|
// Form form binding interface
|
|
type Form interface {
|
|
binding.Validator
|
|
}
|
|
|
|
func init() {
|
|
binding.SetNameMapper(util.ToSnakeCase)
|
|
}
|
|
|
|
// AssignForm assign form values back to the template data.
|
|
func AssignForm(form any, data map[string]any) {
|
|
typ := reflect.TypeOf(form)
|
|
val := reflect.ValueOf(form)
|
|
|
|
for typ.Kind() == reflect.Ptr {
|
|
typ = typ.Elem()
|
|
val = val.Elem()
|
|
}
|
|
|
|
for i := 0; i < typ.NumField(); i++ {
|
|
field := typ.Field(i)
|
|
|
|
fieldName := field.Tag.Get("form")
|
|
// Allow ignored fields in the struct
|
|
if fieldName == "-" {
|
|
continue
|
|
} else if len(fieldName) == 0 {
|
|
fieldName = util.ToSnakeCase(field.Name)
|
|
}
|
|
|
|
data[fieldName] = val.Field(i).Interface()
|
|
}
|
|
}
|
|
|
|
func getRuleBody(field reflect.StructField, prefix string) string {
|
|
for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
|
|
if strings.HasPrefix(rule, prefix) {
|
|
return rule[len(prefix) : len(rule)-1]
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetSize get size int form tag
|
|
func GetSize(field reflect.StructField) string {
|
|
return getRuleBody(field, "Size(")
|
|
}
|
|
|
|
// GetMinSize get minimal size in form tag
|
|
func GetMinSize(field reflect.StructField) string {
|
|
return getRuleBody(field, "MinSize(")
|
|
}
|
|
|
|
// GetMaxSize get max size in form tag
|
|
func GetMaxSize(field reflect.StructField) string {
|
|
return getRuleBody(field, "MaxSize(")
|
|
}
|
|
|
|
// GetInclude get include in form tag
|
|
func GetInclude(field reflect.StructField) string {
|
|
return getRuleBody(field, "Include(")
|
|
}
|
|
|
|
// Validate validate TODO:
|
|
func Validate(errs binding.Errors, data map[string]any, f Form, l translation.Locale) binding.Errors {
|
|
if errs.Len() == 0 {
|
|
return errs
|
|
}
|
|
|
|
data["HasError"] = true
|
|
// If the field with name errs[0].FieldNames[0] is not found in form
|
|
// somehow, some code later on will panic on Data["ErrorMsg"].(string).
|
|
// So initialize it to some default.
|
|
data["ErrorMsg"] = l.Tr("form.unknown_error")
|
|
AssignForm(f, data)
|
|
|
|
typ := reflect.TypeOf(f)
|
|
|
|
if typ.Kind() == reflect.Ptr {
|
|
typ = typ.Elem()
|
|
}
|
|
|
|
if field, ok := typ.FieldByName(errs[0].FieldNames[0]); ok {
|
|
fieldName := field.Tag.Get("form")
|
|
if fieldName != "-" {
|
|
data["Err_"+field.Name] = true
|
|
|
|
trName := field.Tag.Get("locale")
|
|
if len(trName) == 0 {
|
|
trName = l.Tr("form." + field.Name)
|
|
} else {
|
|
trName = l.Tr(trName)
|
|
}
|
|
|
|
switch errs[0].Classification {
|
|
case binding.ERR_REQUIRED:
|
|
data["ErrorMsg"] = trName + l.Tr("form.require_error")
|
|
case binding.ERR_ALPHA_DASH:
|
|
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
|
|
case binding.ERR_ALPHA_DASH_DOT:
|
|
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
|
|
case validation.ErrGitRefName:
|
|
data["ErrorMsg"] = trName + l.Tr("form.git_ref_name_error")
|
|
case binding.ERR_SIZE:
|
|
data["ErrorMsg"] = trName + l.Tr("form.size_error", GetSize(field))
|
|
case binding.ERR_MIN_SIZE:
|
|
data["ErrorMsg"] = trName + l.Tr("form.min_size_error", GetMinSize(field))
|
|
case binding.ERR_MAX_SIZE:
|
|
data["ErrorMsg"] = trName + l.Tr("form.max_size_error", GetMaxSize(field))
|
|
case binding.ERR_EMAIL:
|
|
data["ErrorMsg"] = trName + l.Tr("form.email_error")
|
|
case binding.ERR_URL:
|
|
data["ErrorMsg"] = trName + l.Tr("form.url_error", errs[0].Message)
|
|
case binding.ERR_INCLUDE:
|
|
data["ErrorMsg"] = trName + l.Tr("form.include_error", GetInclude(field))
|
|
case validation.ErrGlobPattern:
|
|
data["ErrorMsg"] = trName + l.Tr("form.glob_pattern_error", errs[0].Message)
|
|
case validation.ErrRegexPattern:
|
|
data["ErrorMsg"] = trName + l.Tr("form.regex_pattern_error", errs[0].Message)
|
|
case validation.ErrUsername:
|
|
if setting.Service.AllowDotsInUsernames {
|
|
data["ErrorMsg"] = trName + l.Tr("form.username_error")
|
|
} else {
|
|
data["ErrorMsg"] = trName + l.Tr("form.username_error_no_dots")
|
|
}
|
|
case validation.ErrInvalidGroupTeamMap:
|
|
data["ErrorMsg"] = trName + l.Tr("form.invalid_group_team_map_error", errs[0].Message)
|
|
default:
|
|
msg := errs[0].Classification
|
|
if msg != "" && errs[0].Message != "" {
|
|
msg += ": "
|
|
}
|
|
|
|
msg += errs[0].Message
|
|
if msg == "" {
|
|
msg = l.Tr("form.unknown_error")
|
|
}
|
|
data["ErrorMsg"] = trName + ": " + msg
|
|
}
|
|
return errs
|
|
}
|
|
}
|
|
return errs
|
|
}
|