diff --git a/go.mod b/go.mod index 8e041a8..92c61f4 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module WWWShop go 1.15 require ( + github.com/go-delve/delve v1.6.0 // indirect github.com/go-pg/pg/v10 v10.7.4 // indirect github.com/golang-migrate/migrate/v4 v4.14.1 github.com/howeyc/fsnotify v0.9.0 // indirect diff --git a/wwwshop/controller/controller.go b/wwwshop/controller/controller.go index 02c0bf3..584fd29 100644 --- a/wwwshop/controller/controller.go +++ b/wwwshop/controller/controller.go @@ -7,6 +7,7 @@ import ( type IController interface { POST(w http.ResponseWriter, r *http.Request) GET(w http.ResponseWriter, r *http.Request) + DELETE(w http.ResponseWriter, r *http.Request) } type Controller struct { IController IController @@ -23,6 +24,9 @@ func (self Controller) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { self.GET(w, r) } + if r.Method == "DELETE" { + self.DELETE(w, r) + } } func (self Controller) POST(w http.ResponseWriter, r *http.Request) { @@ -32,3 +36,7 @@ func (self Controller) POST(w http.ResponseWriter, r *http.Request) { func (self Controller) GET(w http.ResponseWriter, r *http.Request) { self.IController.GET(w, r) } + +func (self Controller) DELETE(w http.ResponseWriter, r *http.Request) { + self.IController.DELETE(w, r) +} diff --git a/wwwshop/controller/usercontroller/usercontroller.go b/wwwshop/controller/usercontroller/usercontroller.go index cfdf0b0..6ae1396 100644 --- a/wwwshop/controller/usercontroller/usercontroller.go +++ b/wwwshop/controller/usercontroller/usercontroller.go @@ -9,6 +9,7 @@ import ( "net/http" "strconv" "strings" + "errors" ) type UserController struct{} @@ -17,7 +18,28 @@ func New() UserController { return UserController{} } -func (self UserController) GET(w http.ResponseWriter, r *http.Request) { +func (self UserController) DELETE(w http.ResponseWriter, r *http.Request) { + ids, usernames, _, err := self.SetupInputForFilter(w, r) + user_manager := u.New(d.DB()) + + if err != nil { + if err != nil { + json_response,_ := EncodeJSONResponse(NewResponseError(err.Error())) + fmt.Fprintf(w, json_response) + return + } + } + deleted_users, err := user_manager.Delete(ids, usernames) + if err != nil { + json_response, _ := EncodeJSONResponse(NewResponseError(err.Error())) + fmt.Fprintf(w, json_response) + return + } + deleted_users_json, _ := EncodeJSONResponse(deleted_users) + fmt.Fprintf(w, deleted_users_json) +} + +func (self UserController) SetupInputForFilter(w http.ResponseWriter, r *http.Request) ([]int64, []string, *int64, error) { query := r.URL.Query() usernames, _ := query["username"] ids, _ := query["id"] @@ -29,23 +51,29 @@ func (self UserController) GET(w http.ResponseWriter, r *http.Request) { var err error page, err = strconv.ParseInt(pages[0], 0, 64) if err != nil { - json_response, _ := EncodeJSONResponse(NewResponseError("Unable to parse int page.")) - fmt.Fprintf(w, json_response) - return + return nil, nil, nil, errors.New("Unable to parse int page.") } } - user_manager := u.New(d.DB()) ids_int := make([]int64, 0) for _, id := range ids { id_int, err := strconv.ParseInt(id, 0, 64) if err != nil { - json_response, _ := EncodeJSONResponse(NewResponseError("Unable to parse int id.")) - fmt.Fprintf(w, json_response) - return + return nil, nil, nil, errors.New("Unable to parse int id.") } ids_int = append(ids_int, id_int) } - users, err := user_manager.Retrieve(page, &ids_int, &usernames) + return ids_int, usernames, &page, nil +} + +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 { + json_response, _ := EncodeJSONResponse(NewResponseError(err.Error())) + fmt.Fprintf(w, json_response) + return + } + users, err := user_manager.Retrieve(*page, ids, usernames) if err != nil { json_response, _ := EncodeJSONResponse(NewResponseError(strings.Join([]string{"Unable to retrieve users ", err.Error()}, ""))) fmt.Fprintf(w, json_response) diff --git a/wwwshop/dao/usermanager/usermanager.go b/wwwshop/dao/usermanager/usermanager.go index 432eb7c..81ca8eb 100644 --- a/wwwshop/dao/usermanager/usermanager.go +++ b/wwwshop/dao/usermanager/usermanager.go @@ -6,6 +6,7 @@ import ( "fmt" "golang.org/x/crypto/bcrypt" "strings" + "errors" ) type UserManager struct { @@ -39,49 +40,102 @@ func (self UserManager) AddWithPlainPassword(username string, password string) ( type QueryParameter interface{} -func (self UserManager) Retrieve(page int64, ids *[]int64, usernames *[]string) (*[]user.User, error) { +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, " ) "}, "") + } + 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, " ) "}, "") + } + return where_string +} + +func (self UserManager) Delete(ids []int64, usernames []string) ([]string, error) { + 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 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 { + query_parameters = append(query_parameters, username) + } + for _, id := range ids { + query_parameters = append(query_parameters, id) + } + 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 +} + +func (self UserManager) Retrieve(page int64, ids []int64, usernames []string) ([]user.User, error) { var where bool - if ids != nil && len(*ids) > 0 { + var cur_key int64 + + if ids != nil && len(ids) > 0 { where = true } - if usernames != nil && len(*usernames) > 0 { + if usernames != nil && len(usernames) > 0 { where = true } - cur_key := 1 + cur_key = 1 where_string := "" if where { - 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, " ) "}, "") - } - 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, " ) "}, "") - } + where_string = self.GenerateWhere(&cur_key, ids, usernames) } page = (10 * page) page_string := fmt.Sprintf("LIMIT 10 OFFSET %d", page) - cur_key++ query_parameters := make([]interface{}, 0) - for _, username := range *usernames { + for _, username := range usernames { query_parameters = append(query_parameters, username) } - for _, id := range *ids { + for _, id := range ids { query_parameters = append(query_parameters, id) } query_string := fmt.Sprintf("SELECT id, username, password from users %s %s;", where_string, page_string) - fmt.Println(query_string) - fmt.Println(query_string) - fmt.Printf("%#v", query_parameters) result, err := self.db.Query( query_string, query_parameters..., @@ -104,5 +158,8 @@ func (self UserManager) Retrieve(page int64, ids *[]int64, usernames *[]string) u := user.New(id_user, username_user, password_user) users = append(users, u) } - return &users, nil + if users == nil { + users = make([]user.User, 0) + } + return users, nil } diff --git a/wwwshop/wwwshop.go b/wwwshop/wwwshop.go index e752fbb..7ec322f 100644 --- a/wwwshop/wwwshop.go +++ b/wwwshop/wwwshop.go @@ -17,5 +17,6 @@ func New() WWWShop { func (self WWWShop) Init() { user_controller := c.GenerateController(u.New()) http.Handle("/user", user_controller) + http.Handle("/user/", user_controller) http.ListenAndServe(":8080", nil) }