diff --git a/cmd/api/server/handlers/httpHandlersAdmin.go b/cmd/api/server/handlers/httpHandlersAdmin.go index 64e1d1df91c3f48502c8ff8a6d950f9816d67f49..237830397a8ec442b8b181abad5cb2fcd87bd0e4 100644 --- a/cmd/api/server/handlers/httpHandlersAdmin.go +++ b/cmd/api/server/handlers/httpHandlersAdmin.go @@ -10,6 +10,7 @@ import ( "github.com/go-chi/chi/v5" ) +// Type to cast for admin user type UserDataAsAdmin struct { ID string `gorm:"type:uuid;primary_key"` CreatedAt time.Time `json:"created_at"` diff --git a/cmd/api/server/handlers/httpHandlersUser.go b/cmd/api/server/handlers/httpHandlersUser.go index 2d8c04601c19076ade81e5bc25958a53a3c98877..e6481fcb44f73152863245a31aeff6aaea58c609 100644 --- a/cmd/api/server/handlers/httpHandlersUser.go +++ b/cmd/api/server/handlers/httpHandlersUser.go @@ -198,3 +198,37 @@ func Updateuser(app *application.Application) http.HandlerFunc { _ = utils.WriteJSON(w, http.StatusOK, response) } } + +func DeleteOwnUserData(app *application.Application) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + // Get the identity from jwt claims + _, claims, err := app.Auth.GetTokenFromHeaderAndVerify(w, r) + if err != nil { + w.WriteHeader(http.StatusUnauthorized) + return + } + + userID := claims.Subject + + // Get the user based on the user_id in the url params + userIdFromUrl := chi.URLParam(r, "user_id") + + if userID != userIdFromUrl { + utils.ErrorJSON(w, errors.New("the user id does not match with your identity")) + return + } + + // Delete the user (this will also delete the associated Mode due to cascading) + err = app.Repository.DeleteUserByID(userID) + if err != nil { + utils.ErrorJSON(w, err) + return + } + + resp := utils.JSONResponse{ + Data: "Successfully deleted the user and the associated mode", + } + + _ = utils.WriteJSON(w, http.StatusAccepted, resp) + } +} diff --git a/cmd/api/server/routes.go b/cmd/api/server/routes.go index 5e3edb5b2a2bab16e013c8ea5daff45c5c90e13a..c56ae071c8a91a973f38340550ee5096ab622924 100644 --- a/cmd/api/server/routes.go +++ b/cmd/api/server/routes.go @@ -66,6 +66,8 @@ func Routes(app *application.Application) http.Handler { // Profile image upload mux.Post("/upload/profile", handlers.UploadProfileImage(app)) // Upload user profile image + + mux.Delete("/user/{user_id}", handlers.DeleteOwnUserData(app)) }) mux.Route("/auth/api/admin", func(mux chi.Router) { diff --git a/internal/models/Users.go b/internal/models/Users.go index 70b862263f4820414e3d94fe86b1af8410c63066..2b32c79506249d26d7235cb2136ec57e6f585800 100644 --- a/internal/models/Users.go +++ b/internal/models/Users.go @@ -17,7 +17,7 @@ type User struct { LastName string `json:"last_name"` Email string `json:"email"` Password string `json:"password"` - Mode Mode `gorm:"foreignKey:UserID" json:"mode,omitempty"` + Mode Mode `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE;" json:"mode,omitempty"` } type Mode struct { diff --git a/internal/repositories/Mode.go b/internal/repositories/Mode.go index c0cd353a06f576b8a7c31df0b72e0a9af1dfa97e..cce9b1486cbce5a46ff5527bf97044569b7fc118 100644 --- a/internal/repositories/Mode.go +++ b/internal/repositories/Mode.go @@ -52,11 +52,23 @@ func (r *GORMRepo) DeleteModeByID(id int) error { } tx := r.DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + tx.SavePoint("beforeDeleteMode") + if err := tx.Delete(&mode, "id = ?", id).Error; err != nil { tx.RollbackTo("beforeDeleteMode") return err } + + if err := tx.Commit().Error; err != nil { + return err + } + return nil }