diff --git a/src/controller/account.go b/src/controller/account.go index 523d866..625b03c 100644 --- a/src/controller/account.go +++ b/src/controller/account.go @@ -5,6 +5,7 @@ import ( "log" "net/http" + "github.com/gorilla/mux" "github.com/switcherapi/switcher-gitops/src/model" "github.com/switcherapi/switcher-gitops/src/repository" "github.com/switcherapi/switcher-gitops/src/utils" @@ -26,6 +27,17 @@ func NewAccountController(repo repository.AccountRepository) *AccountController } } +func (controller *AccountController) RegisterRoutes(r *mux.Router) http.Handler { + const routesDomainVar = "/{domainId}" + + r.HandleFunc(controller.RouteAccountPath, controller.CreateAccountHandler).Methods(http.MethodPost) + r.HandleFunc(controller.RouteAccountPath+routesDomainVar, controller.FetchAccountHandler).Methods(http.MethodGet) + r.HandleFunc(controller.RouteAccountPath+routesDomainVar, controller.UpdateAccountHandler).Methods(http.MethodPut) + r.HandleFunc(controller.RouteAccountPath+routesDomainVar, controller.DeleteAccountHandler).Methods(http.MethodDelete) + + return r +} + func (controller *AccountController) CreateAccountHandler(w http.ResponseWriter, r *http.Request) { var accountRequest model.Account err := json.NewDecoder(r.Body).Decode(&accountRequest) @@ -74,3 +86,15 @@ func (controller *AccountController) UpdateAccountHandler(w http.ResponseWriter, utils.ResponseJSON(w, accountUpdated, http.StatusOK) } + +func (controller *AccountController) DeleteAccountHandler(w http.ResponseWriter, r *http.Request) { + domainId := r.URL.Path[len(controller.RouteAccountPath+"/"):] + err := controller.AccountRepository.DeleteByDomainId(domainId) + if err != nil { + log.Println(err) + utils.ResponseJSON(w, ErrorResponse{Error: "Error deleting account: " + err.Error()}, http.StatusInternalServerError) + return + } + + utils.ResponseJSON(w, nil, http.StatusNoContent) +} diff --git a/src/controller/account_test.go b/src/controller/account_test.go index 024aa6a..52e2ac1 100644 --- a/src/controller/account_test.go +++ b/src/controller/account_test.go @@ -31,7 +31,7 @@ func TestCreateAccountHandler(t *testing.T) { func TestCreateAccountHandlerInvalidRequest(t *testing.T) { // Create a request and response recorder w := httptest.NewRecorder() - r := httptest.NewRequest("POST", accountController.RouteAccountPath, nil) + r := httptest.NewRequest(http.MethodPost, accountController.RouteAccountPath, nil) // Test accountController.CreateAccountHandler(w, r) @@ -47,7 +47,7 @@ func TestFetchAccountHandlerByDomainId(t *testing.T) { // Create a request and response recorder w := httptest.NewRecorder() - r := httptest.NewRequest("GET", accountController.RouteAccountPath+"/123", nil) + r := httptest.NewRequest(http.MethodGet, accountController.RouteAccountPath+"/123", nil) // Test accountController.FetchAccountHandler(w, r) @@ -64,7 +64,7 @@ func TestFetchAccountHandlerByDomainId(t *testing.T) { func TestFetchAccountHandlerByDomainIdNotFound(t *testing.T) { // Create a request and response recorder w := httptest.NewRecorder() - r := httptest.NewRequest("GET", accountController.RouteAccountPath+"/111", nil) + r := httptest.NewRequest(http.MethodGet, accountController.RouteAccountPath+"/111", nil) // Test accountController.FetchAccountHandler(w, r) @@ -96,7 +96,7 @@ func TestUpdateAccountHandler(t *testing.T) { func TestUpdateAccountHandlerInvalidRequest(t *testing.T) { // Create a request and response recorder w := httptest.NewRecorder() - r := httptest.NewRequest("PUT", accountController.RouteAccountPath, nil) + r := httptest.NewRequest(http.MethodPut, accountController.RouteAccountPath, nil) // Test accountController.UpdateAccountHandler(w, r) @@ -106,6 +106,34 @@ func TestUpdateAccountHandlerInvalidRequest(t *testing.T) { assert.Equal(t, "{\"error\":\"Invalid request\"}", w.Body.String()) } +func TestDeleteAccountHandler(t *testing.T) { + // Create an account + accountController.CreateAccountHandler(givenAccountRequest(accountV1)) + + // Create a request and response recorder + w := httptest.NewRecorder() + r := httptest.NewRequest(http.MethodDelete, accountController.RouteAccountPath+"/123", nil) + + // Test + accountController.DeleteAccountHandler(w, r) + + // Assert + assert.Equal(t, http.StatusNoContent, w.Code) +} + +func TestDeleteAccountHandlerNotFound(t *testing.T) { + // Create a request and response recorder + w := httptest.NewRecorder() + r := httptest.NewRequest(http.MethodDelete, accountController.RouteAccountPath+"/111", nil) + + // Test + accountController.DeleteAccountHandler(w, r) + + // Assert + assert.Equal(t, http.StatusInternalServerError, w.Code) + assert.Equal(t, "{\"error\":\"Error deleting account: Account not found for domain.id: 111\"}", w.Body.String()) +} + // Helpers func givenAccountRequest(data model.Account) (*httptest.ResponseRecorder, *http.Request) { diff --git a/src/controller/api.go b/src/controller/api.go index f2050ae..85ed3c8 100644 --- a/src/controller/api.go +++ b/src/controller/api.go @@ -3,6 +3,7 @@ package controller import ( "net/http" + "github.com/gorilla/mux" "github.com/switcherapi/switcher-gitops/src/utils" ) @@ -20,6 +21,12 @@ func NewApiController() *ApiController { } } +func (controller *ApiController) RegisterRoutes(r *mux.Router) http.Handler { + r.HandleFunc(controller.RouteCheckApiPath, controller.CheckApiHandler).Methods(http.MethodGet) + + return r +} + func (controller *ApiController) CheckApiHandler(w http.ResponseWriter, r *http.Request) { utils.ResponseJSON(w, ApiCheckResponse{Message: "API is working"}, http.StatusOK) } diff --git a/src/repository/account.go b/src/repository/account.go index 9b148bc..ae3ba68 100644 --- a/src/repository/account.go +++ b/src/repository/account.go @@ -13,12 +13,23 @@ type AccountRepository interface { Create(account *model.Account) (*model.Account, error) FetchByDomainId(domainId string) (*model.Account, error) Update(account *model.Account) (*model.Account, error) + DeleteByDomainId(domainId string) error } type AccountRepositoryMongo struct { Db *mongo.Database } +type ErrAccountNotFound struct { + DomainId string +} + +func (err ErrAccountNotFound) Error() string { + return "Account not found for domain.id: " + err.DomainId +} + +const domainIdFilter = "domain.id" + func (repo *AccountRepositoryMongo) Create(account *model.Account) (*model.Account, error) { collection, ctx, cancel := getDbContext(repo) defer cancel() @@ -37,7 +48,7 @@ func (repo *AccountRepositoryMongo) FetchByDomainId(domainId string) (*model.Acc defer cancel() var account model.Account - filter := primitive.M{"domain.id": domainId} + filter := primitive.M{domainIdFilter: domainId} err := collection.FindOne(ctx, filter).Decode(&account) if err != nil { return nil, err @@ -50,7 +61,7 @@ func (repo *AccountRepositoryMongo) Update(account *model.Account) (*model.Accou collection, ctx, cancel := getDbContext(repo) defer cancel() - filter := primitive.M{"domain.id": account.Domain.ID} + filter := primitive.M{domainIdFilter: account.Domain.ID} update := primitive.M{ "$set": account, } @@ -63,6 +74,20 @@ func (repo *AccountRepositoryMongo) Update(account *model.Account) (*model.Accou return account, nil } +func (repo *AccountRepositoryMongo) DeleteByDomainId(domainId string) error { + collection, ctx, cancel := getDbContext(repo) + defer cancel() + + filter := primitive.M{domainIdFilter: domainId} + result, err := collection.DeleteOne(ctx, filter) + + if result.DeletedCount == 0 { + return ErrAccountNotFound{DomainId: domainId} + } + + return err +} + func getDbContext(repo *AccountRepositoryMongo) (*mongo.Collection, context.Context, context.CancelFunc) { collection := repo.Db.Collection(model.CollectionName) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) diff --git a/src/server/app.go b/src/server/app.go index 9670e84..238c8fc 100644 --- a/src/server/app.go +++ b/src/server/app.go @@ -62,10 +62,8 @@ func initRoutes(db *mongo.Database) *mux.Router { accountController := controller.NewAccountController(&repository.AccountRepositoryMongo{Db: db}) r := mux.NewRouter() - r.HandleFunc(apiController.RouteCheckApiPath, apiController.CheckApiHandler).Methods("GET") - r.HandleFunc(accountController.RouteAccountPath, accountController.CreateAccountHandler).Methods("POST") - r.HandleFunc(accountController.RouteAccountPath+"/{domainId}", accountController.FetchAccountHandler).Methods("GET") - r.HandleFunc(accountController.RouteAccountPath+"/{domainId}", accountController.UpdateAccountHandler).Methods("PUT") + apiController.RegisterRoutes(r) + accountController.RegisterRoutes(r) return r }