diff --git a/trading_assistant_api/common/types/response.go b/trading_assistant_api/common/types/response.go new file mode 100644 index 0000000..29ab357 --- /dev/null +++ b/trading_assistant_api/common/types/response.go @@ -0,0 +1,6 @@ +package types + +type Response struct { + Status bool `json:"status"` + Message string `json:"message"` +} diff --git a/trading_assistant_api/services/user/main.go b/trading_assistant_api/services/user/main.go index 968eaab..e8e8ac7 100644 --- a/trading_assistant_api/services/user/main.go +++ b/trading_assistant_api/services/user/main.go @@ -17,6 +17,7 @@ import ( "common/db" "common/logger" "common/utils" + "common/types" "golang.org/x/crypto/bcrypt" "github.com/jackc/pgconn" ) @@ -95,28 +96,26 @@ type loginResp struct { func registerHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { - w.WriteHeader(http.StatusMethodNotAllowed) + writeJSON(w, http.StatusMethodNotAllowed, false, "method not allowed") return } var req registerReq if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("invalid json")) + writeJSON(w, http.StatusBadRequest, false, "invalid json") return } if !validAccount(req.Account) || !validPassword(req.Password) { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("invalid account or password")) + writeJSON(w, http.StatusBadRequest, false, "invalid account or password") return } hashed, err := bcrypt.GenerateFromPassword([]byte(req.Password), 12) if err != nil { - w.WriteHeader(http.StatusInternalServerError) + writeJSON(w, http.StatusInternalServerError, false, "internal error") return } tx, err := pg.Begin() if err != nil { - w.WriteHeader(http.StatusInternalServerError) + writeJSON(w, http.StatusInternalServerError, false, "internal error") return } defer func() { @@ -124,63 +123,57 @@ func registerHandler(w http.ResponseWriter, r *http.Request) { }() var userID string if err := tx.QueryRow(`INSERT INTO users DEFAULT VALUES RETURNING user_id`).Scan(&userID); err != nil { - w.WriteHeader(http.StatusInternalServerError) + writeJSON(w, http.StatusInternalServerError, false, "internal error") return } if _, err := tx.Exec(`INSERT INTO user_login_accounts (user_id, value, deleted) VALUES ($1, $2, false)`, userID, req.Account); err != nil { if isUniqueViolation(err) { - w.WriteHeader(http.StatusConflict) - w.Write([]byte("account exists")) + writeJSON(w, http.StatusConflict, false, "account exists") return } - w.WriteHeader(http.StatusInternalServerError) + writeJSON(w, http.StatusInternalServerError, false, "internal error") return } if _, err := tx.Exec(`INSERT INTO user_login_passwords (user_id, value, deleted) VALUES ($1, $2, false)`, userID, string(hashed)); err != nil { - w.WriteHeader(http.StatusInternalServerError) + writeJSON(w, http.StatusInternalServerError, false, "internal error") return } if err := tx.Commit(); err != nil { - w.WriteHeader(http.StatusInternalServerError) + writeJSON(w, http.StatusInternalServerError, false, "internal error") return } - w.WriteHeader(http.StatusCreated) - io.WriteString(w, userID) + writeJSON(w, http.StatusCreated, true, userID) } func loginHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { - w.WriteHeader(http.StatusMethodNotAllowed) + writeJSON(w, http.StatusMethodNotAllowed, false, "method not allowed") return } var req loginReq if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("invalid json")) + writeJSON(w, http.StatusBadRequest, false, "invalid json") return } if !validAccount(req.Account) || !validPassword(req.Password) { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("invalid account or password")) + writeJSON(w, http.StatusBadRequest, false, "invalid account or password") return } var userID string if err := pg.QueryRow(`SELECT user_id FROM user_login_accounts WHERE value = $1 AND deleted = false`, req.Account).Scan(&userID); err != nil { - w.WriteHeader(http.StatusUnauthorized) + writeJSON(w, http.StatusUnauthorized, false, "unauthorized") return } var hashed string if err := pg.QueryRow(`SELECT value FROM user_login_passwords WHERE user_id = $1 AND deleted = false`, userID).Scan(&hashed); err != nil { - w.WriteHeader(http.StatusUnauthorized) + writeJSON(w, http.StatusUnauthorized, false, "unauthorized") return } if bcrypt.CompareHashAndPassword([]byte(hashed), []byte(req.Password)) != nil { - w.WriteHeader(http.StatusUnauthorized) + writeJSON(w, http.StatusUnauthorized, false, "unauthorized") return } - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode(loginResp{UserID: userID}) + writeJSON(w, http.StatusOK, true, userID) } func validAccount(a string) bool { @@ -211,3 +204,9 @@ func applySchema(path string) error { _, err = pg.Exec(string(b)) return err } + +func writeJSON(w http.ResponseWriter, code int, status bool, msg string) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(code) + json.NewEncoder(w).Encode(types.Response{Status: status, Message: msg}) +}