User Settings Notification (WIP)
Cette révision appartient à :
Parent
8081e0b639
révision
32c51a57cb
6 fichiers modifiés avec 105 ajouts et 40 suppressions
13
config/notifications.go
Fichier normal
13
config/notifications.go
Fichier normal
|
@ -0,0 +1,13 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we config the notifications options
|
||||||
|
*/
|
||||||
|
var EnableNotifications = map[string]bool {
|
||||||
|
"new_torrent": true,
|
||||||
|
"new_comment_owner": true,
|
||||||
|
"new_comment_all": true,
|
||||||
|
"new_follower": false,
|
||||||
|
"followed": false,
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ type User struct {
|
||||||
ApiToken string `gorm:"column:api_token"`
|
ApiToken string `gorm:"column:api_token"`
|
||||||
ApiTokenExpiry time.Time `gorm:"column:api_token_expiry"`
|
ApiTokenExpiry time.Time `gorm:"column:api_token_expiry"`
|
||||||
Language string `gorm:"column:language"`
|
Language string `gorm:"column:language"`
|
||||||
|
UserSettings string `gorm:"column:settings"`
|
||||||
|
|
||||||
// TODO: move this to PublicUser
|
// TODO: move this to PublicUser
|
||||||
Likings []User // Don't work `gorm:"foreignkey:user_id;associationforeignkey:follower_id;many2many:user_follows"`
|
Likings []User // Don't work `gorm:"foreignkey:user_id;associationforeignkey:follower_id;many2many:user_follows"`
|
||||||
|
@ -31,9 +32,10 @@ type User struct {
|
||||||
|
|
||||||
MD5 string `json:"md5" gorm:"column:md5"` // Hash of email address, used for Gravatar
|
MD5 string `json:"md5" gorm:"column:md5"` // Hash of email address, used for Gravatar
|
||||||
Torrents []Torrent `gorm:"ForeignKey:UploaderID"`
|
Torrents []Torrent `gorm:"ForeignKey:UploaderID"`
|
||||||
|
Notifications []Notification `gorm:"ForeignKey:UserID"`
|
||||||
|
|
||||||
UnreadNotifications int `gorm:"-"` // We don't want to loop every notifications when accessing user unread notif
|
UnreadNotifications int `gorm:"-"` // We don't want to loop every notifications when accessing user unread notif
|
||||||
Notifications []Notification `gorm:"ForeignKey:UserID"`
|
Settings *UserSettings `gorm:"-"` // We don't want to loop every notifications when accessing user unread notif
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserJSON struct {
|
type UserJSON struct {
|
||||||
|
@ -99,6 +101,10 @@ type UserUploadsOld struct {
|
||||||
TorrentId uint `gorm:"column:torrent_id"`
|
TorrentId uint `gorm:"column:torrent_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserSettings struct {
|
||||||
|
settings map[string]interface{} `json:"settings"`
|
||||||
|
}
|
||||||
|
|
||||||
func (c UserUploadsOld) TableName() string {
|
func (c UserUploadsOld) TableName() string {
|
||||||
// is this needed here?
|
// is this needed here?
|
||||||
return config.UploadsOldTableName
|
return config.UploadsOldTableName
|
||||||
|
@ -115,3 +121,26 @@ func (u *User) ToJSON() UserJSON {
|
||||||
}
|
}
|
||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* User Settings */
|
||||||
|
|
||||||
|
func(s *UserSettings) Get(key string) interface{} {
|
||||||
|
return s.settings[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *UserSettings) Set(key string, val interface{}) {
|
||||||
|
s.settings[key] = val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *UserSettings) GetSettings() {
|
||||||
|
return s.settings
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) SaveSettings() {
|
||||||
|
u.UserSettings , _ = json.Marshal(u.Settings.GetSettings())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *User) ParseSettings() {
|
||||||
|
if len(u.Settings.GetSettings()) == 0
|
||||||
|
json.Unmarshal([]byte(u.UserSettings), u.Settings)
|
||||||
|
}
|
|
@ -79,14 +79,16 @@ func UploadPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
url, err := Router.Get("view_torrent").URL("id", strconv.FormatUint(uint64(torrent.ID), 10))
|
url, err := Router.Get("view_torrent").URL("id", strconv.FormatUint(uint64(torrent.ID), 10))
|
||||||
|
|
||||||
if (user.ID > 0) { // If we are a member
|
if (user.ID > 0 && config.EnableNotifications["new_torrent"]) { // If we are a member and notifications for new torrents are enabled
|
||||||
userService.GetLikings(user) // We populate the liked field for users
|
userService.GetLikings(user) // We populate the liked field for users
|
||||||
if len(user.Likings) > 0 { // If we are followed by at least someone
|
if len(user.Likings) > 0 { // If we are followed by at least someone
|
||||||
for _, follower := range user.Likings {
|
for _, follower := range user.Likings {
|
||||||
T, _, _ := languages.TfuncAndLanguageWithFallback(user.Language, user.Language) // We need to send the notification to every user in their language
|
follower.ParseSettings() // We need to call it before checking settings
|
||||||
|
if follower.Settings.Get("notifications.new_torrent"] {
|
||||||
|
T, _, _ := languages.TfuncAndLanguageWithFallback(user.Language, user.Language) // We need to send the notification to every user in their language
|
||||||
|
|
||||||
notifierService.NotifyUser(&follower, torrent.Identifier(), fmt.Sprintf(T("new_torrent_uploaded"), torrent.Name, user.Username), url.String())
|
notifierService.NotifyUser(&follower, torrent.Identifier(), fmt.Sprintf(T("new_torrent_uploaded"), torrent.Name, user.Username), url.String())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,40 +137,42 @@ func UserProfileFormHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
NotFoundHandler(w, r)
|
NotFoundHandler(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
messages := msg.GetMessages(r)
|
||||||
userForm := form.UserForm{}
|
userForm := form.UserForm{}
|
||||||
err := form.NewErrors()
|
userSettingsForm := form.UserSettingsForm{}
|
||||||
infos := form.NewInfos()
|
|
||||||
|
|
||||||
T := languages.GetTfuncFromRequest(r)
|
T := languages.GetTfuncFromRequest(r)
|
||||||
if len(r.PostFormValue("email")) > 0 {
|
if len(r.PostFormValue("email")) > 0 {
|
||||||
_, err = form.EmailValidation(r.PostFormValue("email"), err)
|
form.EmailValidation(r.PostFormValue("email"), &messages)
|
||||||
}
|
}
|
||||||
if len(r.PostFormValue("username")) > 0 {
|
if len(r.PostFormValue("username")) > 0 {
|
||||||
_, err = form.ValidateUsername(r.PostFormValue("username"), err)
|
form.ValidateUsername(r.PostFormValue("username"), &messages)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(err) == 0 {
|
if !messages.HasErrors() {
|
||||||
modelHelper.BindValueForm(&userForm, r)
|
modelHelper.BindValueForm(&userForm, r)
|
||||||
|
modelHelper.BindValueForm(&userSettingsForm, r)
|
||||||
if !userPermission.HasAdmin(currentUser) {
|
if !userPermission.HasAdmin(currentUser) {
|
||||||
userForm.Username = userProfile.Username
|
userForm.Username = userProfile.Username
|
||||||
userForm.Status = userProfile.Status
|
userForm.Status = userProfile.Status
|
||||||
} else {
|
} else {
|
||||||
if userProfile.Status != userForm.Status && userForm.Status == 2 {
|
if userProfile.Status != userForm.Status && userForm.Status == 2 {
|
||||||
err["errors"] = append(err["errors"], "Elevating status to moderator is prohibited")
|
messages.AddError("errors", "Elevating status to moderator is prohibited")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = modelHelper.ValidateForm(&userForm, err)
|
modelHelper.ValidateForm(&userForm, &messages)
|
||||||
if len(err) == 0 {
|
if !messages.HasErrors() {
|
||||||
if userForm.Email != userProfile.Email {
|
if userForm.Email != userProfile.Email {
|
||||||
userService.SendVerificationToUser(*currentUser, userForm.Email)
|
userService.SendVerificationToUser(*currentUser, userForm.Email)
|
||||||
infos["infos"] = append(infos["infos"], fmt.Sprintf(string(T("email_changed")), userForm.Email))
|
messages.AddInfof("infos", string(T("email_changed")), userForm.Email)
|
||||||
userForm.Email = userProfile.Email // reset, it will be set when user clicks verification
|
userForm.Email = userProfile.Email // reset, it will be set when user clicks verification
|
||||||
}
|
}
|
||||||
userProfile, _, errorUser = userService.UpdateUser(w, &userForm, currentUser, id)
|
userProfile, _, errorUser = userService.UpdateUser(w, &userForm, currentUser, id)
|
||||||
if errorUser != nil {
|
if errorUser != nil {
|
||||||
err["errors"] = append(err["errors"], errorUser.Error())
|
messages.ImportFromError("errors", errorUser)
|
||||||
} else {
|
} else {
|
||||||
infos["infos"] = append(infos["infos"], string(T("profile_updated")))
|
messages.AddInfo("infos", string(T("profile_updated")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,8 +181,8 @@ func UserProfileFormHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
CommonTemplateVariables: NewCommonVariables(r),
|
CommonTemplateVariables: NewCommonVariables(r),
|
||||||
UserProfile: &userProfile,
|
UserProfile: &userProfile,
|
||||||
UserForm: userForm,
|
UserForm: userForm,
|
||||||
FormErrors: err,
|
FormErrors: messages.GetAllErrors(),
|
||||||
FormInfos: infos,
|
FormInfos: messages.GetAllInfos(),
|
||||||
Languages: availableLanguages,
|
Languages: availableLanguages,
|
||||||
}
|
}
|
||||||
errorTmpl := viewProfileEditTemplate.ExecuteTemplate(w, "index.html", upev)
|
errorTmpl := viewProfileEditTemplate.ExecuteTemplate(w, "index.html", upev)
|
||||||
|
|
|
@ -4,33 +4,34 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/NyaaPantsu/nyaa/util/log"
|
"github.com/NyaaPantsu/nyaa/util/log"
|
||||||
|
msg "github.com/NyaaPantsu/nyaa/util/messages"
|
||||||
)
|
)
|
||||||
|
|
||||||
const EMAIL_REGEX = `(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})`
|
const EMAIL_REGEX = `(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})`
|
||||||
const USERNAME_REGEX = `(\W)`
|
const USERNAME_REGEX = `(\W)`
|
||||||
|
|
||||||
func EmailValidation(email string, err map[string][]string) (bool, map[string][]string) {
|
func EmailValidation(email string, mes *msg.Messages) bool {
|
||||||
exp, errorRegex := regexp.Compile(EMAIL_REGEX)
|
exp, errorRegex := regexp.Compile(EMAIL_REGEX)
|
||||||
if regexpCompiled := log.CheckError(errorRegex); regexpCompiled {
|
if regexpCompiled := log.CheckError(errorRegex); regexpCompiled {
|
||||||
if exp.MatchString(email) {
|
if exp.MatchString(email) {
|
||||||
return true, err
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err["email"] = append(err["email"], "Email Address is not valid")
|
mes.AddError("email", "Email Address is not valid")
|
||||||
return false, err
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateUsername(username string, err map[string][]string) (bool, map[string][]string) {
|
func ValidateUsername(username string, mes *msg.Messages) bool {
|
||||||
exp, errorRegex := regexp.Compile(USERNAME_REGEX)
|
exp, errorRegex := regexp.Compile(USERNAME_REGEX)
|
||||||
if regexpCompiled := log.CheckError(errorRegex); regexpCompiled {
|
if regexpCompiled := log.CheckError(errorRegex); regexpCompiled {
|
||||||
if exp.MatchString(username) {
|
if exp.MatchString(username) {
|
||||||
err["username"] = append(err["username"], "Username contains illegal characters")
|
mes.AddError("username", "Username contains illegal characters")
|
||||||
return false, err
|
return false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false, err
|
return false
|
||||||
}
|
}
|
||||||
return true, err
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewErrors() map[string][]string {
|
func NewErrors() map[string][]string {
|
||||||
|
@ -73,6 +74,20 @@ type UserForm struct {
|
||||||
Status int `form:"status" default:"0"`
|
Status int `form:"status" default:"0"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserSettingsForm is used when updating a user.
|
||||||
|
type UserSettingsForm struct {
|
||||||
|
NewTorrent bool `form:"new_torrent" default:"true"`
|
||||||
|
NewTorrentEmail bool `form:"new_torrent_email" default:"true"`
|
||||||
|
NewComment bool `form:"new_comment" default:"true"`
|
||||||
|
NewCommentEmail bool `form:"new_comment_email" default:"false"`
|
||||||
|
NewResponses bool `form:"new_responses" default:"true"`
|
||||||
|
NewResponsesEmail bool `form:"new_responses_email" default:"false"`
|
||||||
|
NewFollower bool `form:"new_follower" default:"true"`
|
||||||
|
NewFollowerEmail bool `form:"new_follower_email" default:"true"`
|
||||||
|
Followed bool `form:"followed" default:"false"`
|
||||||
|
FollowedEmail bool `form:"followed_email" default:"false"`
|
||||||
|
}
|
||||||
|
|
||||||
// PasswordForm is used when updating a user password.
|
// PasswordForm is used when updating a user password.
|
||||||
type PasswordForm struct {
|
type PasswordForm struct {
|
||||||
CurrentPassword string `form:"currentPassword"`
|
CurrentPassword string `form:"currentPassword"`
|
||||||
|
|
|
@ -3,6 +3,7 @@ package modelHelper
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/NyaaPantsu/nyaa/util/log"
|
"github.com/NyaaPantsu/nyaa/util/log"
|
||||||
|
msg "github.com/NyaaPantsu/nyaa/util/messages"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -57,7 +58,7 @@ func BindValueForm(form interface{}, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateForm(form interface{}, errorForm map[string][]string) map[string][]string {
|
func ValidateForm(form interface{}, mes *msg.Messages) {
|
||||||
formElem := reflect.ValueOf(form).Elem()
|
formElem := reflect.ValueOf(form).Elem()
|
||||||
for i := 0; i < formElem.NumField(); i++ {
|
for i := 0; i < formElem.NumField(); i++ {
|
||||||
typeField := formElem.Type().Field(i)
|
typeField := formElem.Type().Field(i)
|
||||||
|
@ -69,28 +70,28 @@ func ValidateForm(form interface{}, errorForm map[string][]string) map[string][]
|
||||||
if tag.Get("len_min") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) { // Check minimum length
|
if tag.Get("len_min") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) { // Check minimum length
|
||||||
lenMin, _ := strconv.Atoi(tag.Get("len_min"))
|
lenMin, _ := strconv.Atoi(tag.Get("len_min"))
|
||||||
if formElem.Field(i).Len() < lenMin {
|
if formElem.Field(i).Len() < lenMin {
|
||||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Minimal length of %s required for the input: %s", strconv.Itoa(lenMin), inputName))
|
mes.AddErrorf(tag.Get("form"), "Minimal length of %s required for the input: %s", strconv.Itoa(lenMin), inputName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tag.Get("len_max") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) { // Check maximum length
|
if tag.Get("len_max") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) { // Check maximum length
|
||||||
lenMax, _ := strconv.Atoi(tag.Get("len_max"))
|
lenMax, _ := strconv.Atoi(tag.Get("len_max"))
|
||||||
if formElem.Field(i).Len() > lenMax {
|
if formElem.Field(i).Len() > lenMax {
|
||||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Maximal length of %s required for the input: %s", strconv.Itoa(lenMax), inputName))
|
mes.AddErrorf(tag.Get("form"), "Maximal length of %s required for the input: %s", strconv.Itoa(lenMax), inputName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tag.Get("equalInput") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) {
|
if tag.Get("equalInput") != "" && (tag.Get("needed") != "" || formElem.Field(i).Len() > 0) {
|
||||||
otherInput := formElem.FieldByName(tag.Get("equalInput"))
|
otherInput := formElem.FieldByName(tag.Get("equalInput"))
|
||||||
if formElem.Field(i).Interface() != otherInput.Interface() {
|
if formElem.Field(i).Interface() != otherInput.Interface() {
|
||||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Must be same %s", inputName))
|
mes.AddErrorf(tag.Get("form"), "Must be same %s", inputName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch typeField.Type.Name() {
|
switch typeField.Type.Name() {
|
||||||
case "string":
|
case "string":
|
||||||
if tag.Get("equal") != "" && formElem.Field(i).String() != tag.Get("equal") {
|
if tag.Get("equal") != "" && formElem.Field(i).String() != tag.Get("equal") {
|
||||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Wrong value for the input: %s", inputName))
|
mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName)
|
||||||
}
|
}
|
||||||
if tag.Get("needed") != "" && formElem.Field(i).String() == "" {
|
if tag.Get("needed") != "" && formElem.Field(i).String() == "" {
|
||||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Field needed: %s", inputName))
|
mes.AddErrorf(tag.Get("form"), "Field needed: %s", inputName)
|
||||||
}
|
}
|
||||||
if formElem.Field(i).String() == "" && tag.Get("default") != "" {
|
if formElem.Field(i).String() == "" && tag.Get("default") != "" {
|
||||||
formElem.Field(i).SetString(tag.Get("default"))
|
formElem.Field(i).SetString(tag.Get("default"))
|
||||||
|
@ -99,11 +100,11 @@ func ValidateForm(form interface{}, errorForm map[string][]string) map[string][]
|
||||||
if tag.Get("equal") != "" { // Check minimum length
|
if tag.Get("equal") != "" { // Check minimum length
|
||||||
equal, _ := strconv.Atoi(tag.Get("equal"))
|
equal, _ := strconv.Atoi(tag.Get("equal"))
|
||||||
if formElem.Field(i).Int() > int64(equal) {
|
if formElem.Field(i).Int() > int64(equal) {
|
||||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Wrong value for the input: %s", inputName))
|
mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tag.Get("needed") != "" && formElem.Field(i).Int() == 0 {
|
if tag.Get("needed") != "" && formElem.Field(i).Int() == 0 {
|
||||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Field needed: %s", inputName))
|
mes.AddErrorf(tag.Get("form"), "Field needed: %s", inputName)
|
||||||
}
|
}
|
||||||
if formElem.Field(i).Interface == nil && tag.Get("default") != "" {
|
if formElem.Field(i).Interface == nil && tag.Get("default") != "" {
|
||||||
defaultValue, _ := strconv.Atoi(tag.Get("default"))
|
defaultValue, _ := strconv.Atoi(tag.Get("default"))
|
||||||
|
@ -113,11 +114,11 @@ func ValidateForm(form interface{}, errorForm map[string][]string) map[string][]
|
||||||
if tag.Get("equal") != "" { // Check minimum length
|
if tag.Get("equal") != "" { // Check minimum length
|
||||||
equal, _ := strconv.Atoi(tag.Get("equal"))
|
equal, _ := strconv.Atoi(tag.Get("equal"))
|
||||||
if formElem.Field(i).Float() != float64(equal) {
|
if formElem.Field(i).Float() != float64(equal) {
|
||||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Wrong value for the input: %s", inputName))
|
mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if tag.Get("needed") != "" && formElem.Field(i).Float() == 0 {
|
if tag.Get("needed") != "" && formElem.Field(i).Float() == 0 {
|
||||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Field needed: %s", inputName))
|
mes.AddErrorf(tag.Get("form"), "Field needed: %s", inputName)
|
||||||
}
|
}
|
||||||
if formElem.Field(i).Interface == nil && tag.Get("default") != "" {
|
if formElem.Field(i).Interface == nil && tag.Get("default") != "" {
|
||||||
defaultValue, _ := strconv.Atoi(tag.Get("default"))
|
defaultValue, _ := strconv.Atoi(tag.Get("default"))
|
||||||
|
@ -127,10 +128,13 @@ func ValidateForm(form interface{}, errorForm map[string][]string) map[string][]
|
||||||
if tag.Get("equal") != "" { // Check minimum length
|
if tag.Get("equal") != "" { // Check minimum length
|
||||||
equal, _ := strconv.ParseBool(tag.Get("equal"))
|
equal, _ := strconv.ParseBool(tag.Get("equal"))
|
||||||
if formElem.Field(i).Bool() != equal {
|
if formElem.Field(i).Bool() != equal {
|
||||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Wrong value for the input: %s", inputName))
|
mes.AddErrorf(tag.Get("form"), "Wrong value for the input: %s", inputName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if formElem.Field(i).Interface == nil && tag.Get("default") != "" {
|
||||||
|
defaultValue, _ := strconv.ParseBool(tag.Get("default"))
|
||||||
|
formElem.Field(i).SetBool(defaultValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return errorForm
|
|
||||||
}
|
}
|
||||||
|
|
Référencer dans un nouveau ticket