Adding support for UPDATE.
This commit is contained in:
parent
e436c2d528
commit
5e15ae95fc
|
@ -8,6 +8,7 @@ type IController interface {
|
|||
POST(w http.ResponseWriter, r *http.Request)
|
||||
GET(w http.ResponseWriter, r *http.Request)
|
||||
DELETE(w http.ResponseWriter, r *http.Request)
|
||||
PUT(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
type Controller struct {
|
||||
IController IController
|
||||
|
@ -20,13 +21,21 @@ func GenerateController(controller IController) Controller {
|
|||
func (self Controller) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "POST" {
|
||||
self.POST(w, r)
|
||||
return
|
||||
}
|
||||
if r.Method == "GET" {
|
||||
self.GET(w, r)
|
||||
return
|
||||
}
|
||||
if r.Method == "DELETE" {
|
||||
self.DELETE(w, r)
|
||||
return
|
||||
}
|
||||
if r.Method == "PUT" {
|
||||
self.PUT(w, r)
|
||||
return
|
||||
}
|
||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||
}
|
||||
|
||||
func (self Controller) POST(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -40,3 +49,7 @@ func (self Controller) GET(w http.ResponseWriter, r *http.Request) {
|
|||
func (self Controller) DELETE(w http.ResponseWriter, r *http.Request) {
|
||||
self.IController.DELETE(w, r)
|
||||
}
|
||||
|
||||
func (self Controller) PUT(w http.ResponseWriter, r *http.Request) {
|
||||
self.IController.PUT(w, r)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package usercontroller
|
|||
import (
|
||||
d "WWWShop/wwwshop/dao/database"
|
||||
u "WWWShop/wwwshop/dao/usermanager"
|
||||
"WWWShop/wwwshop/model/user"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -65,16 +66,52 @@ func (self UserController) SetupInputForFilter(w http.ResponseWriter, r *http.Re
|
|||
return ids_int, usernames, &page, nil
|
||||
}
|
||||
|
||||
func (self UserController) PUT(w http.ResponseWriter, r *http.Request) {
|
||||
var decoded_user_struct user.User
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&decoded_user_struct)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError("Failed to decode json user on update."))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
if decoded_user_struct.Id == nil && decoded_user_struct.Username == nil {
|
||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError("Failed to get username or id needed to update users."))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
if decoded_user_struct.Password == nil {
|
||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError("Failed to get some field to update in the user."))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
user_manager := u.New(d.DB())
|
||||
user, err := user_manager.Update(decoded_user_struct)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError(strings.Join([]string{"Failed to update user with the given data, may be our fault: ", err.Error()}, "")))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
json_response, _ := EncodeJSONResponse(user)
|
||||
fmt.Fprintf(w, json_response)
|
||||
}
|
||||
|
||||
func (self UserController) GET(w http.ResponseWriter, r *http.Request) {
|
||||
user_manager := u.New(d.DB())
|
||||
ids, usernames, page, err := self.SetupInputForFilter(w, r)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError(err.Error()))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
}
|
||||
users, err := user_manager.Retrieve(*page, ids, usernames)
|
||||
if err != nil {
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
json_response, _ := EncodeJSONResponse(NewResponseError(strings.Join([]string{"Unable to retrieve users ", err.Error()}, "")))
|
||||
fmt.Fprintf(w, json_response)
|
||||
return
|
||||
|
|
|
@ -3,10 +3,10 @@ package usermanager
|
|||
import (
|
||||
"WWWShop/wwwshop/model/user"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"strings"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type UserManager struct {
|
||||
|
@ -30,55 +30,100 @@ func (self UserManager) Add(username string, password_hash string) (*user.User,
|
|||
}
|
||||
|
||||
func (self UserManager) AddWithPlainPassword(username string, password string) (*user.User, error) {
|
||||
password_hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
password_hash, err := self.EncryptPassword(password);
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user, err := self.Add(username, string(password_hash))
|
||||
user, err := self.Add(username, password_hash)
|
||||
return user, err
|
||||
}
|
||||
|
||||
func (self UserManager) EncryptPassword(password string) (string, error) {
|
||||
password_hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
return string(password_hash), nil
|
||||
}
|
||||
}
|
||||
|
||||
type QueryParameter interface{}
|
||||
|
||||
func (self UserManager) GenerateWhere(cur_key *int64, ids []int64, usernames []string) string {
|
||||
where_string := "WHERE true "
|
||||
if usernames != nil && len(usernames) > 0 {
|
||||
where_string = strings.Join([]string{where_string, "AND ( false"}, "")
|
||||
for range usernames {
|
||||
where_string = strings.Join([]string{where_string, fmt.Sprintf(" OR username = $%d", *cur_key)}, "")
|
||||
(*cur_key)++
|
||||
}
|
||||
where_string = strings.Join([]string{where_string, " ) "}, "")
|
||||
where_string := "WHERE false "
|
||||
if usernames != nil && len(usernames) > 0 {
|
||||
where_string = strings.Join([]string{where_string, "OR ( false"}, "")
|
||||
for range usernames {
|
||||
where_string = strings.Join([]string{where_string, fmt.Sprintf(" OR username = $%d", *cur_key)}, "")
|
||||
(*cur_key)++
|
||||
}
|
||||
where_string = strings.Join([]string{where_string, " ) "}, "")
|
||||
}
|
||||
if ids != nil && len(ids) > 0 {
|
||||
where_string = strings.Join([]string{where_string, "OR ( false"}, "")
|
||||
for range ids {
|
||||
where_string = strings.Join([]string{where_string, fmt.Sprintf(" OR id = $%d", *cur_key)}, "")
|
||||
(*cur_key)++
|
||||
}
|
||||
where_string = strings.Join([]string{where_string, " ) "}, "")
|
||||
}
|
||||
return where_string
|
||||
}
|
||||
|
||||
func (self UserManager) Update(user user.User) (*user.User, error) {
|
||||
if user.Id == nil && user.Username == nil {
|
||||
return nil, errors.New("Both Id and Username cannot be null on the same time on UPDATE.")
|
||||
}
|
||||
if user.Password == nil {
|
||||
return nil, errors.New("Should be at least a field for update .")
|
||||
}
|
||||
query := "UPDATE users SET password = $1 WHERE true "
|
||||
parameters := make([]interface{}, 0)
|
||||
password_hash, err := self.EncryptPassword(*(user.Password));
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ids != nil && len(ids) > 0 {
|
||||
where_string = strings.Join([]string{where_string, "AND ( false"}, "")
|
||||
for range ids {
|
||||
where_string = strings.Join([]string{where_string, fmt.Sprintf(" OR id = $%d", *cur_key)}, "")
|
||||
(*cur_key)++
|
||||
}
|
||||
where_string = strings.Join([]string{where_string, " ) "}, "")
|
||||
parameters = append(parameters, password_hash)
|
||||
if user.Id != nil {
|
||||
query = strings.Join([]string{query, "AND id = $2 "}, "")
|
||||
parameters = append(parameters, *(user.Id))
|
||||
} else {
|
||||
query = strings.Join([]string{query, "AND username = $2 "}, "")
|
||||
parameters = append(parameters, *(user.Password))
|
||||
}
|
||||
query = strings.Join([]string{query, " RETURNING id"}, "")
|
||||
var id int64
|
||||
result := self.db.QueryRow(query, parameters...)
|
||||
err = result.Scan(&id);
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return where_string
|
||||
users, err := self.Retrieve(0, []int64{id}, nil)
|
||||
user = users[0]
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (self UserManager) Delete(ids []int64, usernames []string) ([]string, error) {
|
||||
var where bool
|
||||
var cur_key int64
|
||||
var where_string string
|
||||
cur_key = 1
|
||||
var where bool
|
||||
var cur_key int64
|
||||
var where_string string
|
||||
cur_key = 1
|
||||
|
||||
if ids != nil && len(ids) > 0 {
|
||||
where = true
|
||||
}
|
||||
if usernames != nil && len(usernames) > 0 {
|
||||
where = true
|
||||
}
|
||||
if ids != nil && len(ids) > 0 {
|
||||
where = true
|
||||
}
|
||||
if usernames != nil && len(usernames) > 0 {
|
||||
where = true
|
||||
}
|
||||
|
||||
if where {
|
||||
where_string = self.GenerateWhere(&cur_key, ids, usernames)
|
||||
} else {
|
||||
return nil, errors.New("Cannot delete without a clause")
|
||||
}
|
||||
if where {
|
||||
where_string = self.GenerateWhere(&cur_key, ids, usernames)
|
||||
} else {
|
||||
return nil, errors.New("Cannot delete without a clause")
|
||||
}
|
||||
|
||||
query_parameters := make([]interface{}, 0)
|
||||
for _, username := range usernames {
|
||||
|
@ -87,33 +132,33 @@ func (self UserManager) Delete(ids []int64, usernames []string) ([]string, error
|
|||
for _, id := range ids {
|
||||
query_parameters = append(query_parameters, id)
|
||||
}
|
||||
query_string := fmt.Sprintf("DELETE FROM users %s RETURNING username", where_string)
|
||||
query_string := fmt.Sprintf("DELETE FROM users %s RETURNING username", where_string)
|
||||
result, err := self.db.Query(
|
||||
query_string,
|
||||
query_parameters...,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer result.Close()
|
||||
var deleted_users []string
|
||||
for result.Next() {
|
||||
var username string
|
||||
err := result.Scan(&username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deleted_users = append(deleted_users, username)
|
||||
}
|
||||
if deleted_users == nil {
|
||||
deleted_users = make([]string, 0)
|
||||
}
|
||||
return deleted_users, nil
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer result.Close()
|
||||
var deleted_users []string
|
||||
for result.Next() {
|
||||
var username string
|
||||
err := result.Scan(&username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
deleted_users = append(deleted_users, username)
|
||||
}
|
||||
if deleted_users == nil {
|
||||
deleted_users = make([]string, 0)
|
||||
}
|
||||
return deleted_users, nil
|
||||
}
|
||||
|
||||
func (self UserManager) Retrieve(page int64, ids []int64, usernames []string) ([]user.User, error) {
|
||||
var where bool
|
||||
var cur_key int64
|
||||
var cur_key int64
|
||||
|
||||
if ids != nil && len(ids) > 0 {
|
||||
where = true
|
||||
|
@ -124,9 +169,9 @@ func (self UserManager) Retrieve(page int64, ids []int64, usernames []string) ([
|
|||
cur_key = 1
|
||||
where_string := ""
|
||||
if where {
|
||||
where_string = self.GenerateWhere(&cur_key, ids, usernames)
|
||||
where_string = self.GenerateWhere(&cur_key, ids, usernames)
|
||||
}
|
||||
page = (10 * page)
|
||||
page = (10 * page)
|
||||
page_string := fmt.Sprintf("LIMIT 10 OFFSET %d", page)
|
||||
query_parameters := make([]interface{}, 0)
|
||||
for _, username := range usernames {
|
||||
|
@ -158,8 +203,8 @@ func (self UserManager) Retrieve(page int64, ids []int64, usernames []string) ([
|
|||
u := user.New(id_user, username_user, password_user)
|
||||
users = append(users, u)
|
||||
}
|
||||
if users == nil {
|
||||
users = make([]user.User, 0)
|
||||
}
|
||||
if users == nil {
|
||||
users = make([]user.User, 0)
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
|
|
@ -5,16 +5,21 @@ import (
|
|||
)
|
||||
|
||||
type User struct {
|
||||
Id int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
Id *int64 `json:"id"`
|
||||
Username *string `json:"username"`
|
||||
PasswordHash *string `json:"password_hash"`
|
||||
Password *string `json:"password"` // Only used in update.
|
||||
}
|
||||
|
||||
func New(id int64, username string, password_hash string) User {
|
||||
return User{id, username, password_hash}
|
||||
return User{
|
||||
Id: &id,
|
||||
Username: &username,
|
||||
PasswordHash: &password_hash,
|
||||
}
|
||||
}
|
||||
|
||||
func (self User) CheckPassword(password string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(self.PasswordHash), []byte(password))
|
||||
err := bcrypt.CompareHashAndPassword([]byte(*(self.PasswordHash)), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue