Added Form Validation
Display of error messages
Cette révision appartient à :
Parent
4814fff3dc
révision
4df2268094
7 fichiers modifiés avec 167 ajouts et 70 suppressions
20
db/gorm.go
20
db/gorm.go
|
@ -31,28 +31,12 @@ func GormInit(conf *config.Config) (*gorm.DB, error) {
|
|||
if config.Environment == "DEVELOPMENT" {
|
||||
db.LogMode(true)
|
||||
// db.DropTable(&model.User{}, "UserFollower")
|
||||
db.AutoMigrate(&model.Torrents{})
|
||||
// db.AutoMigrate(&model.User{}, &model.Role{}, &model.Connection{}, &model.Language{}, &model.Article{}, &model.Location{}, &model.Comment{}, &model.File{})
|
||||
db.AutoMigrate(&model.Torrents{}, &model.User{}, &model.Role{}, &model.Connection{}, &model.Language{})
|
||||
// db.AutoMigrate(&model.Article{}, &model.Location{}, &model.Comment{}, &model.File{})
|
||||
// db.Model(&model.User{}).AddIndex("idx_user_token", "token")
|
||||
|
||||
}
|
||||
log.CheckError(err)
|
||||
|
||||
// relation := gorm.Relationship{}
|
||||
// relation.Kind = "many2many"
|
||||
// relation.ForeignFieldNames = []string{"id"} //(M1 pkey)
|
||||
// relation.ForeignDBNames = []string{"user_id"} //(M1 fkey in m1m2join)
|
||||
// relation.AssociationForeignFieldNames = []string{"id"} //(M2 pkey)
|
||||
// // relation.AssociationForeignStructFieldNames = []string{"id", "ID"} //(m2 pkey name in m2 struct?)
|
||||
// relation.AssociationForeignDBNames = []string{"follower_id"} //(m2 fkey in m1m2join)
|
||||
// m1Type := reflect.TypeOf(model.User{})
|
||||
// m2Type := reflect.TypeOf(model.User{})
|
||||
// handler := gorm.JoinTableHandler{}
|
||||
// // ORDER BELOW MATTERS
|
||||
// // Install handler
|
||||
// db.SetJoinTableHandler(&model.User{}, "Likings", &handler)
|
||||
// // Configure handler to use the relation that we've defined
|
||||
// handler.Setup(&relation, "users_followers", m1Type, m2Type)
|
||||
|
||||
return db, err
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ type ViewTemplateVariables struct {
|
|||
|
||||
type UserRegisterTemplateVariables struct {
|
||||
RegistrationForm userForms.RegistrationForm
|
||||
FormErrors map[string][]string
|
||||
Search SearchForm
|
||||
Navigation Navigation
|
||||
URL *url.URL // For parsing Url in templates
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/ewhal/nyaa/service/user"
|
||||
"github.com/ewhal/nyaa/service/user/form"
|
||||
"github.com/ewhal/nyaa/util/languages"
|
||||
"github.com/ewhal/nyaa/util/log"
|
||||
"github.com/ewhal/nyaa/util/modelHelper"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
@ -20,7 +21,7 @@ func UserRegisterFormHandler(w http.ResponseWriter, r *http.Request) {
|
|||
modelHelper.BindValueForm(&b, r)
|
||||
b.CaptchaID = captcha.GetID()
|
||||
languages.SetTranslation("en-us", viewRegisterTemplate)
|
||||
htv := UserRegisterTemplateVariables{b, NewSearchForm(), Navigation{}, r.URL, mux.CurrentRoute(r)}
|
||||
htv := UserRegisterTemplateVariables{b, form.NewErrors(), NewSearchForm(), Navigation{}, r.URL, mux.CurrentRoute(r)}
|
||||
err := viewRegisterTemplate.ExecuteTemplate(w, "index.html", htv)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
|
@ -52,29 +53,43 @@ func UserProfileFormHandler(w http.ResponseWriter, r *http.Request) {
|
|||
// Post Registration controller, we do some check on the form here, the rest on user service
|
||||
func UserRegisterPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Check same Password
|
||||
b := form.RegistrationForm{}
|
||||
err := form.NewErrors()
|
||||
if !captcha.Authenticate(captcha.Extract(r)) {
|
||||
// TODO: Prettier passing of mistyoed captcha errors
|
||||
http.Error(w, captcha.ErrInvalidCaptcha.Error(), 403)
|
||||
return
|
||||
err["errors"] = append(err["errors"], "Wrong captcha!")
|
||||
}
|
||||
if (r.PostFormValue("password") == r.PostFormValue("password_confirm")) && (r.PostFormValue("password") != "") {
|
||||
if (form.EmailValidation(r.PostFormValue("email"))) && (form.ValidateUsername(r.PostFormValue("username"))) {
|
||||
_, err := userService.CreateUser(w, r)
|
||||
if err == nil {
|
||||
b := form.RegistrationForm{}
|
||||
htv := UserRegisterTemplateVariables{b, NewSearchForm(), Navigation{}, r.URL, mux.CurrentRoute(r)}
|
||||
err = viewRegisterSuccessTemplate.ExecuteTemplate(w, "index.html", htv)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
} else {
|
||||
UserRegisterFormHandler(w, r)
|
||||
}
|
||||
} else {
|
||||
UserRegisterFormHandler(w, r)
|
||||
if (len(err) == 0) {
|
||||
_, err = form.EmailValidation(r.PostFormValue("email"), err)
|
||||
_, err = form.ValidateUsername(r.PostFormValue("username"), err)
|
||||
log.Info("test lets see 3")
|
||||
if (len(err) == 0) {
|
||||
modelHelper.BindValueForm(&b, r)
|
||||
err = modelHelper.ValidateForm(&b, err)
|
||||
log.Info("test lets see 1")
|
||||
if (len(err) == 0) {
|
||||
_, errorUser := userService.CreateUser(w, r)
|
||||
err["errors"] = append(err["errors"], errorUser.Error())
|
||||
log.Info("test lets see 2")
|
||||
if (len(err) == 0) {
|
||||
b := form.RegistrationForm{}
|
||||
htv := UserRegisterTemplateVariables{b, err, NewSearchForm(), Navigation{}, r.URL, mux.CurrentRoute(r)}
|
||||
errorTmpl := viewRegisterSuccessTemplate.ExecuteTemplate(w, "index.html", htv)
|
||||
if errorTmpl != nil {
|
||||
http.Error(w, errorTmpl.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (len(err) > 0) {
|
||||
log.Info("test lets see 4")
|
||||
b.CaptchaID = captcha.GetID()
|
||||
languages.SetTranslation("en-us", viewRegisterTemplate)
|
||||
htv := UserRegisterTemplateVariables{b, err, NewSearchForm(), Navigation{}, r.URL, mux.CurrentRoute(r)}
|
||||
errorTmpl := viewRegisterTemplate.ExecuteTemplate(w, "index.html", htv)
|
||||
if errorTmpl != nil {
|
||||
http.Error(w, errorTmpl.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
} else {
|
||||
UserRegisterFormHandler(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ func SetCookieHandler(w http.ResponseWriter, email string, pass string) (int, er
|
|||
if email != "" && pass != "" {
|
||||
log.Debugf("User email : %s , password : %s", email, pass)
|
||||
var user model.User
|
||||
isValidEmail := formStruct.EmailValidation(email)
|
||||
isValidEmail, _ := formStruct.EmailValidation(email, formStruct.NewErrors())
|
||||
if isValidEmail {
|
||||
log.Debug("User entered valid email.")
|
||||
if db.ORM.Where("email = ?", email).First(&user).RecordNotFound() {
|
||||
|
|
|
@ -9,42 +9,44 @@ import (
|
|||
const EMAIL_REGEX = `(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})`
|
||||
const USERNAME_REGEX = `(\W)`
|
||||
|
||||
func EmailValidation(email string) bool {
|
||||
exp, err := regexp.Compile(EMAIL_REGEX)
|
||||
if regexpCompiled := log.CheckError(err); regexpCompiled {
|
||||
func EmailValidation(email string, err map[string][]string) (bool, map[string][]string) {
|
||||
exp, errorRegex := regexp.Compile(EMAIL_REGEX)
|
||||
if regexpCompiled := log.CheckError(errorRegex); regexpCompiled {
|
||||
if exp.MatchString(email) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
func ValidateUsername(username string) bool {
|
||||
exp, err := regexp.Compile(USERNAME_REGEX)
|
||||
|
||||
if username == "" {
|
||||
return false
|
||||
|
||||
}
|
||||
if (len(username) < 3) || (len(username) > 15) {
|
||||
return false
|
||||
|
||||
}
|
||||
if regexpCompiled := log.CheckError(err); regexpCompiled {
|
||||
if exp.MatchString(username) {
|
||||
return false
|
||||
err["email"] = append(err["email"], "Email Address is not valid")
|
||||
return true, err
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
return false, err
|
||||
}
|
||||
return true
|
||||
return false, err
|
||||
}
|
||||
func ValidateUsername(username string, err map[string][]string) (bool, map[string][]string) {
|
||||
exp, errorRegex := regexp.Compile(USERNAME_REGEX)
|
||||
if regexpCompiled := log.CheckError(errorRegex); regexpCompiled {
|
||||
if exp.MatchString(username) {
|
||||
err["username"] = append(err["username"], "Username contains illegal characters")
|
||||
return false, err
|
||||
}
|
||||
} else {
|
||||
return false, err
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
|
||||
func NewErrors() map[string][]string {
|
||||
err := make(map[string][]string)
|
||||
return err
|
||||
}
|
||||
|
||||
// RegistrationForm is used when creating a user.
|
||||
type RegistrationForm struct {
|
||||
Username string `form:"registrationUsername"`
|
||||
Email string `form:"registrationEmail"`
|
||||
Password string `form:"registrationPassword"`
|
||||
CaptchaID string `form:"captchaID" inmodel:"false"`
|
||||
Username string `form:"username" needed:"true" min_len:"3" max_len:"20"`
|
||||
Email string `form:"email" needed:"true"`
|
||||
Password string `form:"password" needed:"true" min_len:"6" max_len:"25"`
|
||||
Confirm_Password string `form:"password_confirmation" omit:"true" needed:"true"`
|
||||
CaptchaID string `form:"captchaID" omit:"true" needed:"true"`
|
||||
T_and_C bool `form:"t_and_c" omit:"true" needed:"true" equal:"true" hum_name:"Terms and Conditions"`
|
||||
}
|
||||
|
||||
// RegistrationForm is used when creating a user authentication.
|
||||
|
|
|
@ -8,21 +8,36 @@
|
|||
<form role="form" method="POST">
|
||||
<h2>{{T "signup_box_title" }}</h2>
|
||||
<hr class="colorgraph">
|
||||
{{ range (index $.FormErrors "errors")}}
|
||||
<div class="alert alert-danger">{{ . }}</div>
|
||||
{{end}}
|
||||
<div class="form-group">
|
||||
<input type="text" name="username" id="display_name" class="form-control input-lg" placeholder="{{T "username" }}" tabindex="1" value="{{ .Username }}">
|
||||
{{ range (index $.FormErrors "username")}}
|
||||
<p class="bg-danger">{{ . }}</p>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="email" name="email" id="email" class="form-control input-lg" placeholder="{{T "email_address" }}" tabindex="2" value="{{ .Email }}">
|
||||
{{ range (index $.FormErrors "email")}}
|
||||
<p class="bg-danger">{{ . }}</p>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<input type="password" name="password" id="password" class="form-control input-lg" placeholder="{{T "password" }}" tabindex="3" value="{{ .Password }}">
|
||||
</div>
|
||||
{{ range (index $.FormErrors "password")}}
|
||||
<p class="bg-danger">{{ . }}</p>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<input type="password" name="password_confirmation" id="password_confirmation" class="form-control input-lg" placeholder="{{T "confirm_password" }}" tabindex="4">
|
||||
{{ range (index $.FormErrors "password_confirmation")}}
|
||||
<p class="bg-danger">{{ . }}</p>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -31,6 +46,9 @@
|
|||
<span class="button-checkbox">
|
||||
<button type="button" class="btn hidden" data-color="info" tabindex="5">{{T "i_agree" }}</button>
|
||||
<input type="checkbox" name="t_and_c" id="t_and_c" value="1">
|
||||
{{ range (index $.FormErrors "t_and_c")}}
|
||||
<p class="bg-danger">{{ . }}</p>
|
||||
{{end}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-xs-8 col-sm-9 col-md-9">
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
"github.com/ewhal/nyaa/util/log"
|
||||
"strconv"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func IsZeroOfUnderlyingType(x interface{}) bool {
|
||||
|
@ -18,7 +19,7 @@ func AssignValue(model interface{}, form interface{}) {
|
|||
typeOfTForm := formElem.Type()
|
||||
for i := 0; i < formElem.NumField(); i++ {
|
||||
tag := typeOfTForm.Field(i).Tag
|
||||
if tag.Get("omit") != "false" {
|
||||
if tag.Get("omit") != "true" {
|
||||
modelField := modelIndirect.FieldByName(typeOfTForm.Field(i).Name)
|
||||
if modelField.IsValid() {
|
||||
formField := formElem.Field(i)
|
||||
|
@ -46,6 +47,82 @@ func BindValueForm(form interface{}, r *http.Request) {
|
|||
case "float" :
|
||||
nbr, _ := strconv.Atoi(r.PostFormValue(tag.Get("form")))
|
||||
formElem.Field(i).SetFloat(float64(nbr))
|
||||
case "bool" :
|
||||
nbr, _ := strconv.ParseBool(r.PostFormValue(tag.Get("form")))
|
||||
formElem.Field(i).SetBool(nbr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func ValidateForm(form interface{}, errorForm map[string][]string) (map[string][]string) {
|
||||
formElem := reflect.ValueOf(form).Elem()
|
||||
for i := 0; i < formElem.NumField(); i++ {
|
||||
typeField := formElem.Type().Field(i)
|
||||
tag := typeField.Tag
|
||||
inputName := typeField.Name
|
||||
if (tag.Get("hum_name") != "") { // For more human input name than gibberish
|
||||
inputName = tag.Get("hum_name")
|
||||
}
|
||||
if tag.Get("len_min") != "" { // Check minimum length
|
||||
lenMin, _ := strconv.Atoi(tag.Get("len_min"))
|
||||
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", lenMin, inputName))
|
||||
}
|
||||
}
|
||||
if tag.Get("len_max") != "" { // Check minimum length
|
||||
lenMax, _ := strconv.Atoi(tag.Get("len_max"))
|
||||
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", lenMax, inputName))
|
||||
}
|
||||
}
|
||||
if tag.Get("equalInput") != "" {
|
||||
otherInput := formElem.FieldByName(tag.Get("equalForm"))
|
||||
if formElem.Field(i).Interface() != otherInput.Interface() {
|
||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Wrong value for the input: %s", inputName))
|
||||
}
|
||||
}
|
||||
switch typeField.Type.Name() {
|
||||
case "string" :
|
||||
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))
|
||||
}
|
||||
if tag.Get("needed") != "" && formElem.Field(i).String() == "" {
|
||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Field needed: %s", inputName))
|
||||
}
|
||||
case "int" :
|
||||
if tag.Get("equal") != "" { // Check minimum length
|
||||
equal, _ := strconv.Atoi(tag.Get("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))
|
||||
}
|
||||
if tag.Get("needed") != "" && formElem.Field(i).Int() == 0 {
|
||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Field needed: %s", inputName))
|
||||
}
|
||||
}
|
||||
case "float" :
|
||||
if tag.Get("equal") != "" { // Check minimum length
|
||||
equal, _ := strconv.Atoi(tag.Get("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))
|
||||
}
|
||||
if tag.Get("needed") != "" && formElem.Field(i).Float() == 0 {
|
||||
errorForm[tag.Get("form")] = append(errorForm[tag.Get("form")], fmt.Sprintf("Field needed: %s", inputName))
|
||||
}
|
||||
}
|
||||
case "bool" :
|
||||
if tag.Get("equal") != "" { // Check minimum length
|
||||
equal, _ := strconv.ParseBool(tag.Get("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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len(errorForm) == 0) { // If no error, return nil
|
||||
return nil
|
||||
}
|
||||
return errorForm
|
||||
}
|
Référencer dans un nouveau ticket