diff --git a/api/account.go b/api/account.go index 46be565..17de652 100644 --- a/api/account.go +++ b/api/account.go @@ -107,3 +107,79 @@ func (server *Server) listAccounts(ctx *gin.Context) { ctx.JSON(http.StatusOK, accounts) } + +type updateAccountRequest struct { + ID int64 `binding:"required" json:"ID"` + Changer string `binding:"required" json:"changer"` + Passwordhash string `json:"passwordhash"` + Firstname string `json:"firstname"` + Lastname string `json:"lastname"` + Birthday time.Time `json:"birthday"` + Email string `json:"email"` + Phone string `json:"phone"` + City string `json:"city"` + Zip string `json:"zip"` + Street string `json:"street"` + Country string `json:"country"` +} + +func (server *Server) updateAccount(ctx *gin.Context) { + var req updateAccountRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + ctx.JSON(http.StatusBadRequest, errorResponse(err)) + return + } + + arg := db.UpdateAccountParams{ + ID: req.ID, + Changer: req.Changer, + Passwordhash: sql.NullString{ + String: req.Passwordhash, + Valid: req.Passwordhash != "", + }, + Firstname: sql.NullString{ + String: req.Firstname, + Valid: req.Firstname != "", + }, + Lastname: sql.NullString{ + String: req.Lastname, + Valid: req.Lastname != "", + }, + Birthday: sql.NullTime{ + Time: req.Birthday, + Valid: req.Birthday != time.Time{}, + }, + Email: sql.NullString{ + String: req.Email, + Valid: req.Email != "", + }, + City: sql.NullString{ + String: req.City, + Valid: req.City != "", + }, + Zip: sql.NullString{ + String: req.Zip, + Valid: req.Zip != "", + }, + Street: sql.NullString{ + String: req.Street, + Valid: req.Street != "", + }, + Country: sql.NullString{ + String: req.Country, + Valid: req.Country != "", + }, + Phone: sql.NullString{ + String: req.Phone, + Valid: req.Phone != "", + }, + } + + account, err := server.store.UpdateAccount(ctx, arg) + if err != nil { + ctx.JSON(http.StatusInternalServerError, errorResponse(err)) + return + } + + ctx.JSON(http.StatusOK, account) +} diff --git a/api/account_test.go b/api/account_test.go index a6fe385..e2cf6d7 100644 --- a/api/account_test.go +++ b/api/account_test.go @@ -140,6 +140,144 @@ func TestCreateAccountAPI(t *testing.T) { } } +func TestUpdateAccountAPI(t *testing.T) { + account := randomAccount() + changer := util.RandomName() + newPassword := util.RandomString(30) + newEmail := util.RandomEmail() + testCases := []struct { + name string + body gin.H + accountID string + buildStubs func(store *mockdb.MockStore) + checkResponse func(recoder *httptest.ResponseRecorder) + }{ + { + name: "OK_PasswordHash", + body: gin.H{ + "id": account.ID, + "passwordhash": newPassword, + "changer": changer, + }, + buildStubs: func(store *mockdb.MockStore) { + arg := db.UpdateAccountParams{ + ID: account.ID, + Passwordhash: sql.NullString{ + Valid: true, + String: newPassword, + }, + Changer: changer, + } + + store.EXPECT(). + UpdateAccount(gomock.Any(), gomock.Eq(arg)). + Times(1). + Return(account, nil) + }, + checkResponse: func(recorder *httptest.ResponseRecorder) { + require.Equal(t, http.StatusOK, recorder.Code) + requireBodyMatchAccount(t, recorder.Body, account) + }, + }, + { + name: "OK_Email", + body: gin.H{ + "id": account.ID, + "email": newEmail, + "changer": changer, + }, + buildStubs: func(store *mockdb.MockStore) { + arg := db.UpdateAccountParams{ + ID: account.ID, + Email: sql.NullString{ + Valid: true, + String: newEmail, + }, + Changer: changer, + } + + store.EXPECT(). + UpdateAccount(gomock.Any(), gomock.Eq(arg)). + Times(1). + Return(account, nil) + }, + checkResponse: func(recorder *httptest.ResponseRecorder) { + require.Equal(t, http.StatusOK, recorder.Code) + requireBodyMatchAccount(t, recorder.Body, account) + }, + }, + // { + // name: "NoAuthorization", + // body: gin.H{ + // "currency": account.Currency, + // }, + // buildStubs: func(store *mockdb.MockStore) { + // store.EXPECT(). + // CreateAccount(gomock.Any(), gomock.Any()). + // Times(0) + // }, + // checkResponse: func(recorder *httptest.ResponseRecorder) { + // require.Equal(t, http.StatusUnauthorized, recorder.Code) + // }, + // }, + { + name: "BadRequest", + body: gin.H{ + "email": account.Email, + }, + buildStubs: func(store *mockdb.MockStore) { + store.EXPECT(). + CreateAccount(gomock.Any(), gomock.Any()). + Times(0). + Return(db.Account{}, sql.ErrConnDone) + }, + checkResponse: func(recorder *httptest.ResponseRecorder) { + require.Equal(t, http.StatusBadRequest, recorder.Code) + }, + }, + /* { + name: "InvalidCurrency", + body: gin.H{ + "currency": "invalid", + }, + buildStubs: func(store *mockdb.MockStore) { + store.EXPECT(). + CreateAccount(gomock.Any(), gomock.Any()). + Times(0) + }, + checkResponse: func(recorder *httptest.ResponseRecorder) { + require.Equal(t, http.StatusBadRequest, recorder.Code) + }, + }, */ + } + + for i := range testCases { + tc := testCases[i] + + t.Run(tc.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + store := mockdb.NewMockStore(ctrl) + tc.buildStubs(store) + + server := NewServer(config, store) + recorder := httptest.NewRecorder() + + // Marshal body data to JSON + data, err := json.Marshal(tc.body) + require.NoError(t, err) + + url := "/accounts" + request, err := http.NewRequest(http.MethodPut, url, bytes.NewReader(data)) + require.NoError(t, err) + + server.router.ServeHTTP(recorder, request) + tc.checkResponse(recorder) + }) + } +} + // func TestGetAccountAPI(t *testing.T) { // account := randomAccount() diff --git a/api/server.go b/api/server.go index 4f09c5c..8fb94ec 100644 --- a/api/server.go +++ b/api/server.go @@ -46,6 +46,7 @@ func NewServer(config util.Config, store db.Store) *Server { router.Use(Logger()) router.POST("/accounts", server.createAccount) + router.PUT("/accounts", server.updateAccount) router.GET("/accounts/:id", server.getAccount) router.GET("/accounts", server.listAccounts)