diff --git a/handlers.go b/handlers.go index 2d96b3c..49db55b 100644 --- a/handlers.go +++ b/handlers.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "errors" + "fmt" "io/ioutil" "net/http" "os" @@ -73,7 +74,9 @@ func Handler() http.Handler { // Auth routes m.Handle("/users", j.Secure(http.HandlerFunc(handleLister(UserService{})), verifyClaims)).Methods("GET") + m.Handle("/users", j.Secure(http.HandlerFunc(handleCreater(UserService{})), verifyClaims)).Methods("POST") m.Handle("/users/{Id:.+}", j.Secure(http.HandlerFunc(handleGetter(UserService{})), verifyClaims)).Methods("GET") + m.Handle("/users/{Id:.+}", j.Secure(http.HandlerFunc(handleUpdater(UserService{})), verifyClaims)).Methods("PUT") // Path-based pattern matching subrouter s := m.PathPrefix("/{genus}").Subrouter() @@ -108,6 +111,12 @@ func Handler() http.Handler { return corsHandler(m) } +func Error(w http.ResponseWriter, err string, code int) { + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + w.WriteHeader(code) + fmt.Fprintln(w, err) +} + func handleGetter(g getter) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, err := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0) @@ -209,7 +218,7 @@ func handleCreater(c creater) http.HandlerFunc { err = c.create(&e, claims) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + Error(w, err.Error(), http.StatusInternalServerError) return } diff --git a/users.go b/users.go index d57b0b6..d119171 100644 --- a/users.go +++ b/users.go @@ -32,6 +32,21 @@ type User struct { DeletedAt NullTime `db:"deleted_at" json:"deletedAt"` } +type UserValidation struct { + Email []string `json:"email,omitempty"` + Password []string `json:"password,omitempty"` + Name []string `json:"name,omitempty"` + Role []string `json:"role,omitempty"` +} + +func (uv UserValidation) Error() string { + errs, err := json.Marshal(uv) + if err != nil { + return err.Error() + } + return string(errs) +} + type Users []*User type UserJSON struct { @@ -56,6 +71,22 @@ func (u UserService) unmarshal(b []byte) (entity, error) { return uj.User, err } +func (u *User) validate() error { + var uv UserValidation + validationError := false + + if u.Name == "" { + uv.Name = append(uv.Name, "Must provide a value") + validationError = true + } + + if validationError { + errs, _ := json.Marshal(uv) + return errors.New(string(errs)) + } + return nil +} + func (u UserService) list(val *url.Values) (entity, error) { if val == nil { return nil, errors.New("must provide options") @@ -85,6 +116,41 @@ func (u UserService) get(id int64, genus string) (entity, error) { return &user, nil } +func (u UserService) update(id int64, e *entity, claims Claims) error { + user := (*e).(*User) + user.UpdatedAt = time.Now() + user.Id = id + + count, err := DBH.Update(user) + if err != nil { + return err + } + if count != 1 { + return ErrStrainNotUpdated + } + return nil +} + +func (u UserService) create(e *entity, claims Claims) error { + user := (*e).(*User) + if err := user.validate(); err != nil { + return err + } + ct := time.Now() + user.CreatedAt = ct + user.UpdatedAt = ct + hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), 10) + if err != nil { + return err + } + user.Password = string(hash) + + if err := DBH.Insert(user); err != nil { + return err + } + return nil +} + // for thermokarst/jwt: authentication callback func dbAuthenticate(email string, password string) error { var user User