chore: update user create validator

This commit is contained in:
Steven 2022-08-20 21:03:15 +08:00
parent 734d5f3aed
commit 05a5c59a7e
6 changed files with 88 additions and 18 deletions

View file

@ -1,5 +1,11 @@
package api package api
import (
"fmt"
"github.com/usememos/memos/common"
)
// Role is the type of a role. // Role is the type of a role.
type Role string type Role string
@ -47,6 +53,20 @@ type UserCreate struct {
OpenID string OpenID string
} }
func (create UserCreate) Validate() error {
if !common.ValidateEmail(create.Email) {
return fmt.Errorf("invalid email format")
}
if len(create.Email) < 6 {
return fmt.Errorf("email is too short, minimum length is 6")
}
if len(create.Password) < 6 {
return fmt.Errorf("password is too short, minimum length is 6")
}
return nil
}
type UserPatch struct { type UserPatch struct {
ID int ID int

View file

@ -17,11 +17,6 @@ const (
NotFound Code = 4 NotFound Code = 4
Conflict Code = 5 Conflict Code = 5
NotImplemented Code = 6 NotImplemented Code = 6
// 101 ~ 199 db error
DbConnectionFailure Code = 101
DbStatementSyntaxError Code = 102
DbExecutionError Code = 103
) )
// Error represents an application-specific error. Application errors can be // Error represents an application-specific error. Application errors can be

View file

@ -1,6 +1,7 @@
package common package common
import ( import (
"net/mail"
"strings" "strings"
"github.com/google/uuid" "github.com/google/uuid"
@ -16,6 +17,14 @@ func HasPrefixes(src string, prefixes ...string) bool {
return false return false
} }
// ValidateEmail validates the email.
func ValidateEmail(email string) bool {
if _, err := mail.ParseAddress(email); err != nil {
return false
}
return true
}
func GenUUID() string { func GenUUID() string {
return uuid.New().String() return uuid.New().String()
} }

31
common/util_test.go Normal file
View file

@ -0,0 +1,31 @@
package common
import (
"testing"
)
func TestValidateEmail(t *testing.T) {
tests := []struct {
email string
want bool
}{
{
email: "t@gmail.com",
want: true,
},
{
email: "@qq.com",
want: false,
},
{
email: "1@gmail",
want: true,
},
}
for _, test := range tests {
result := ValidateEmail(test.email)
if result != test.want {
t.Errorf("Validate Email %s: got result %v, want %v.", test.email, result, test.want)
}
}
}

View file

@ -80,13 +80,15 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted signup request").SetInternal(err) return echo.NewHTTPError(http.StatusBadRequest, "Malformatted signup request").SetInternal(err)
} }
// Validate signup form. userCreate := &api.UserCreate{
// We can do stricter checks later. Email: signup.Email,
if len(signup.Email) < 6 { Role: api.Role(signup.Role),
return echo.NewHTTPError(http.StatusBadRequest, "Email is too short, minimum length is 6.") Name: signup.Name,
Password: signup.Password,
OpenID: common.GenUUID(),
} }
if len(signup.Password) < 6 { if err := userCreate.Validate(); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Password is too short, minimum length is 6.") return echo.NewHTTPError(http.StatusBadRequest, "Invalid user create format.").SetInternal(err)
} }
passwordHash, err := bcrypt.GenerateFromPassword([]byte(signup.Password), bcrypt.DefaultCost) passwordHash, err := bcrypt.GenerateFromPassword([]byte(signup.Password), bcrypt.DefaultCost)
@ -94,13 +96,8 @@ func (s *Server) registerAuthRoutes(g *echo.Group) {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to generate password hash").SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, "Failed to generate password hash").SetInternal(err)
} }
userCreate := &api.UserCreate{ userCreate.PasswordHash = string(passwordHash)
Email: signup.Email,
Role: api.Role(signup.Role),
Name: signup.Name,
PasswordHash: string(passwordHash),
OpenID: common.GenUUID(),
}
user, err := s.Store.CreateUser(ctx, userCreate) user, err := s.Store.CreateUser(ctx, userCreate)
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create user").SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create user").SetInternal(err)

View file

@ -16,11 +16,29 @@ import (
func (s *Server) registerUserRoutes(g *echo.Group) { func (s *Server) registerUserRoutes(g *echo.Group) {
g.POST("/user", func(c echo.Context) error { g.POST("/user", func(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
userID, ok := c.Get(getUserIDContextKey()).(int)
if !ok {
return echo.NewHTTPError(http.StatusUnauthorized, "Missing auth session")
}
currentUser, err := s.Store.FindUser(ctx, &api.UserFind{
ID: &userID,
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user by id").SetInternal(err)
}
if currentUser.Role != api.Host {
return echo.NewHTTPError(http.StatusUnauthorized, "Only Host user can create member.")
}
userCreate := &api.UserCreate{} userCreate := &api.UserCreate{}
if err := json.NewDecoder(c.Request().Body).Decode(userCreate); err != nil { if err := json.NewDecoder(c.Request().Body).Decode(userCreate); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post user request").SetInternal(err) return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post user request").SetInternal(err)
} }
if err := userCreate.Validate(); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Invalid user create format.").SetInternal(err)
}
passwordHash, err := bcrypt.GenerateFromPassword([]byte(userCreate.Password), bcrypt.DefaultCost) passwordHash, err := bcrypt.GenerateFromPassword([]byte(userCreate.Password), bcrypt.DefaultCost)
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to generate password hash").SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, "Failed to generate password hash").SetInternal(err)