Fill in user validation
This commit is contained in:
parent
b87a05c39e
commit
e6733b2c2e
2 changed files with 53 additions and 4 deletions
22
helpers.go
22
helpers.go
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/lib/pq"
|
"github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
@ -13,6 +14,7 @@ var (
|
||||||
ErrMustProvideOptions = errors.New("Must provide necessary options")
|
ErrMustProvideOptions = errors.New("Must provide necessary options")
|
||||||
ErrMustProvideOptionsJSON = newJSONError(ErrMustProvideOptions, http.StatusBadRequest)
|
ErrMustProvideOptionsJSON = newJSONError(ErrMustProvideOptions, http.StatusBadRequest)
|
||||||
StatusUnprocessableEntity = 422
|
StatusUnprocessableEntity = 422
|
||||||
|
MustProvideAValue = "Must provide a value"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListOptions specifies general pagination options for fetching a list of results
|
// ListOptions specifies general pagination options for fetching a list of results
|
||||||
|
@ -67,3 +69,23 @@ func currentTime() NullTime {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://stackoverflow.com/a/25840157/313548
|
||||||
|
func verifyPassword(s string) (sevenOrMore, number, upper bool) {
|
||||||
|
letters := 0
|
||||||
|
for _, s := range s {
|
||||||
|
switch {
|
||||||
|
case unicode.IsNumber(s):
|
||||||
|
number = true
|
||||||
|
case unicode.IsUpper(s):
|
||||||
|
upper = true
|
||||||
|
letters++
|
||||||
|
case unicode.IsLetter(s) || s == ' ':
|
||||||
|
letters++
|
||||||
|
default:
|
||||||
|
// returns false, false, false, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sevenOrMore = letters >= 7
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
35
users.go
35
users.go
|
@ -6,6 +6,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
@ -27,7 +28,7 @@ type UserService struct{}
|
||||||
type User struct {
|
type User struct {
|
||||||
Id int64 `json:"id,omitempty"`
|
Id int64 `json:"id,omitempty"`
|
||||||
Email string `db:"email" json:"email"`
|
Email string `db:"email" json:"email"`
|
||||||
Password string `db:"password" json:"-"`
|
Password string `db:"password" json:"password,omitempty"`
|
||||||
Name string `db:"name" json:"name"`
|
Name string `db:"name" json:"name"`
|
||||||
Role string `db:"role" json:"role"`
|
Role string `db:"role" json:"role"`
|
||||||
CreatedAt NullTime `db:"created_at" json:"createdAt"`
|
CreatedAt NullTime `db:"created_at" json:"createdAt"`
|
||||||
|
@ -81,10 +82,33 @@ func (u *User) validate() error {
|
||||||
validationError := false
|
validationError := false
|
||||||
|
|
||||||
if u.Name == "" {
|
if u.Name == "" {
|
||||||
uv.Name = append(uv.Name, "Must provide a value")
|
uv.Name = append(uv.Name, MustProvideAValue)
|
||||||
validationError = true
|
validationError = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if u.Email == "" {
|
||||||
|
uv.Email = append(uv.Email, MustProvideAValue)
|
||||||
|
validationError = true
|
||||||
|
}
|
||||||
|
|
||||||
|
regex, _ := regexp.Compile(`(\w[-._\w]*\w@\w[-._\w]*\w\.\w{2,3})`)
|
||||||
|
if u.Email != "" && !regex.MatchString(u.Email) {
|
||||||
|
uv.Email = append(uv.Email, "Must provide a valid email address")
|
||||||
|
validationError = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Password == "" {
|
||||||
|
uv.Password = append(uv.Password, MustProvideAValue)
|
||||||
|
validationError = true
|
||||||
|
} else {
|
||||||
|
sevenOrMore, number, upper := verifyPassword(u.Password)
|
||||||
|
if !sevenOrMore || !number || !upper {
|
||||||
|
uv.Password = append(uv.Password, "Password must be at least 8 characters"+
|
||||||
|
" long, and have at least one number and one uppercase letter")
|
||||||
|
validationError = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if validationError {
|
if validationError {
|
||||||
return uv
|
return uv
|
||||||
}
|
}
|
||||||
|
@ -101,7 +125,8 @@ func (u UserService) list(val *url.Values) (entity, *appError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
users := make(Users, 0)
|
users := make(Users, 0)
|
||||||
sql := `SELECT * FROM users;`
|
sql := `SELECT id, email, 'password' AS password, name, role,
|
||||||
|
created_at, updated_at, deleted_at FROM users;`
|
||||||
if err := DBH.Select(&users, sql); err != nil {
|
if err := DBH.Select(&users, sql); err != nil {
|
||||||
return nil, newJSONError(err, http.StatusInternalServerError)
|
return nil, newJSONError(err, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
@ -110,7 +135,8 @@ func (u UserService) list(val *url.Values) (entity, *appError) {
|
||||||
|
|
||||||
func (u UserService) get(id int64, genus string) (entity, *appError) {
|
func (u UserService) get(id int64, genus string) (entity, *appError) {
|
||||||
var user User
|
var user User
|
||||||
q := `SELECT * FROM users WHERE id=$1;`
|
q := `SELECT id, email, 'password' AS password, name, role,
|
||||||
|
created_at, updated_at, deleted_at FROM users WHERE id=$1;`
|
||||||
if err := DBH.SelectOne(&user, q, id); err != nil {
|
if err := DBH.SelectOne(&user, q, id); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, ErrUserNotFoundJSON
|
return nil, ErrUserNotFoundJSON
|
||||||
|
@ -148,6 +174,7 @@ func (u UserService) create(e *entity, claims Claims) *appError {
|
||||||
return newJSONError(err, http.StatusInternalServerError)
|
return newJSONError(err, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
user.Password = string(hash)
|
user.Password = string(hash)
|
||||||
|
user.Role = "R"
|
||||||
|
|
||||||
if err := DBH.Insert(user); err != nil {
|
if err := DBH.Insert(user); err != nil {
|
||||||
return newJSONError(err, http.StatusInternalServerError)
|
return newJSONError(err, http.StatusInternalServerError)
|
||||||
|
|
Reference in a new issue