diff --git a/internal/api/api.go b/internal/api/api.go index bd09d40..5df5eff 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -12,7 +12,6 @@ import ( "github.com/hazemKrimi/crimson-vault/internal/lib" "github.com/hazemKrimi/crimson-vault/internal/models" - "github.com/hazemKrimi/crimson-vault/internal/types" ) type API struct { @@ -28,20 +27,6 @@ func (api *API) Initialize() { db := &models.DB{} ech := echo.New() - ech.Validator = &CustomValidator{validator: validator} - ech.HTTPErrorHandler = func(err error, context echo.Context) { - if context.Response().Committed { - return - } - - custom, ok := err.(types.Error) - - if ok { - context.JSONPretty(custom.Code, map[string][]string{"errors": custom.Messages}, " ") - } - - ech.DefaultHTTPErrorHandler(err, context) - } db.Connect(api.ConfigDirectory) db.MigrateClients() @@ -50,6 +35,9 @@ func (api *API) Initialize() { api.instance = ech api.db = db + api.instance.Validator = &CustomValidator{validator: validator} + api.instance.HTTPErrorHandler = api.CustomErrorHandler + api.instance.Use(api.LoggerMiddleware()) // TODO: Update with appropriate origins when finishing v1 api.instance.Use(middleware.CORSWithConfig(middleware.CORSConfig{ diff --git a/internal/api/auth.go b/internal/api/auth.go index 47946ce..a13ba84 100644 --- a/internal/api/auth.go +++ b/internal/api/auth.go @@ -1,8 +1,7 @@ package api import ( - "fmt" - "log" + "errors" "net/http" "github.com/labstack/echo-contrib/session" @@ -16,8 +15,7 @@ func (api *API) LoginHandler(context echo.Context) error { var body types.LoginRequestBody if err := context.Bind(&body); err != nil { - log.Println(fmt.Sprintf("Error logging User in: %v.", err)) - return context.String(http.StatusBadRequest, "Invalid JSON!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"Invalid JSON!"}} } if err := context.Validate(body); err != nil { @@ -27,31 +25,27 @@ func (api *API) LoginHandler(context echo.Context) error { var user types.User if err := api.db.GetUserByUsername(body.Username, &user); err != nil { - return context.String(http.StatusNotFound, "User not found!") + return types.Error{Code: http.StatusNotFound, Messages: []string{"User not found!"}} } if match := lib.CheckPasswordHash(body.Password, user.Password); !match { - return context.String(http.StatusBadRequest, "Invalid credentials!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"Invalid credentials!"}} } sess, err := session.Get("session", context) if err != nil { - log.Println(fmt.Sprintf("Error creating User session: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error creating User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error creating User session!"}} } if err := api.db.UpdateUserSessionID(&user); err != nil { - log.Println(fmt.Sprintf("Error creating User session: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error creating User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error creating User session!"}} } if err := lib.CreateSession(sess, context, &user); err != nil { - log.Println(fmt.Sprintf("Error creating User session: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error creating User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error creating User session!"}} } - log.Println(fmt.Sprintf("User with ID %s logged in.", user.ID)) return context.JSON(http.StatusOK, user) } @@ -59,28 +53,22 @@ func (api *API) LogoutHandler(context echo.Context) error { sessionId, ok := context.Get("sessionId").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error deleting User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error deleting User session!"}} } if err := api.db.DeleteUserSessionID(sessionId); err != nil { - log.Println(fmt.Sprintf("Error deleting User session: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error deleting User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error deleting User session!"}} } sess, err := session.Get("session", context) if err != nil { - log.Println(fmt.Sprintf("Error deleting User session: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error deleting User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error deleting User session!"}} } if err := lib.DeleteSession(sess, context); err != nil { - log.Println(fmt.Sprintf("Error deleting User session: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error deleting User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error deleting User session!"}} } - id := context.Get("id") - - log.Println(fmt.Sprintf("User with ID %s logged out.", id)) - return context.String(http.StatusOK, "Logged out successfully!") + return context.JSON(http.StatusOK, map[string]string{"message":"Logged out successfully!"}) } diff --git a/internal/api/client.go b/internal/api/client.go index 4d6ce40..448a58f 100644 --- a/internal/api/client.go +++ b/internal/api/client.go @@ -1,8 +1,7 @@ package api import ( - "fmt" - "log" + "errors" "net/http" "github.com/google/uuid" @@ -15,20 +14,19 @@ func (api *API) CreateClientHandler(context echo.Context) error { userId, ok := context.Get("id").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error getting User!"}} } id, err := uuid.Parse(userId) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error getting User!"}} } var body types.CreateClientRequestBody if err := context.Bind(&body); err != nil { - log.Println(fmt.Sprintf("Error creating Client: %v.", err)) - return context.String(http.StatusBadRequest, "Invalid JSON!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"Invalid JSON!"}} } if err := context.Validate(body); err != nil { @@ -37,7 +35,6 @@ func (api *API) CreateClientHandler(context echo.Context) error { client := api.db.CreateClient(id, body) - log.Println(fmt.Sprintf("Client created with ID %s.", client.ID)) return context.JSON(http.StatusOK, client) } @@ -45,22 +42,21 @@ func (api *API) GetAllClientsHandler(context echo.Context) error { userId, ok := context.Get("id").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error getting User!"}} } id, err := uuid.Parse(userId) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error getting User!"}} } clients, err := api.db.GetClients(id) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error getting Clients!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error getting Clients!"}} } - log.Println("Got all Clients.") return context.JSON(http.StatusOK, clients) } @@ -68,28 +64,27 @@ func (api *API) GetClientHandler(context echo.Context) error { userIdString, ok := context.Get("id").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error getting User!"}} } userId, err := uuid.Parse(userIdString) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error getting User!"}} } id, err := uuid.Parse(context.Param("id")) if err != nil { - return context.String(http.StatusBadRequest, "ID is required to get a Client!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"ID is required to get a Client!"}} } var client types.Client if err := api.db.GetClientById(userId, id, &client); err != nil { - return context.String(http.StatusNotFound, "Client not found!") + return types.Error{Code: http.StatusNotFound, Messages: []string{"Client not found!"}} } - log.Println(fmt.Sprintf("Got User with ID %s.", client.ID)) return context.JSON(http.StatusOK, client) } @@ -97,26 +92,31 @@ func (api *API) UpdateClientHandler(context echo.Context) error { userIdString, ok := context.Get("id").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error getting User!"}} } userId, err := uuid.Parse(userIdString) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error getting User!"}} } id, err := uuid.Parse(context.Param("id")) if err != nil { - return context.String(http.StatusBadRequest, "ID is required to update a Client!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"ID is required to update a Client!"}} } var body types.UpdateClientRequestBody if err := context.Bind(&body); err != nil { - log.Println(fmt.Sprintf("Error updating Client: %v.", err)) - return context.String(http.StatusBadRequest, "Invalid JSON!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"Invalid JSON!"}} + } + + empty := body == types.UpdateClientRequestBody{} + + if empty { + return types.Error{Code: http.StatusBadRequest, Messages: []string{"You must update at least one field!"}} } if err := context.Validate(body); err != nil { @@ -126,10 +126,9 @@ func (api *API) UpdateClientHandler(context echo.Context) error { var client types.Client if err := api.db.UpdateClient(userId, id, body, &client); err != nil { - return context.String(http.StatusNotFound, "Client not found!") + return types.Error{Code: http.StatusNotFound, Messages: []string{"Client not found!"}} } - log.Println(fmt.Sprintf("Updated Client with ID %s.", client.ID)) return context.JSON(http.StatusOK, client) } @@ -137,25 +136,24 @@ func (api *API) DeleteClientHandler(context echo.Context) error { userIdString, ok := context.Get("id").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error getting User!"}} } userId, err := uuid.Parse(userIdString) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error getting User!"}} } id, err := uuid.Parse(context.Param("id")) if err != nil { - return context.String(http.StatusBadRequest, "ID is required to delete a Client!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"ID is required to delete a Client!"}} } if err := api.db.DeleteClient(userId, id); err != nil { - return context.String(http.StatusNotFound, "Client not found!") + return types.Error{Code: http.StatusNotFound, Messages: []string{"Client not found!"}} } - log.Println(fmt.Sprintf("Deleted Client with ID %s.", id)) - return context.String(http.StatusOK, "Client deleted successfully!") + return context.JSON(http.StatusOK, map[string]string{"message": "Client deleted successfully!"}) } diff --git a/internal/api/error.go b/internal/api/error.go new file mode 100644 index 0000000..51145a3 --- /dev/null +++ b/internal/api/error.go @@ -0,0 +1,37 @@ +package api + +import ( + "github.com/labstack/echo/v4" + + "github.com/hazemKrimi/crimson-vault/internal/types" +) + +func (api *API) CustomErrorHandler(err error, context echo.Context) { + if context.Response().Committed { + return + } + + custom, ok := err.(types.Error) + + if ok { + cause, ok := custom.Cause.(error) + + if ok { + api.Logger.Error(cause.Error()) + } + + context.JSON(custom.Code, map[string][]string{"errors": custom.Messages}) + } + + herr, ok := err.(*echo.HTTPError) + + if ok { + message, ok := herr.Message.(string) + + if ok { + context.JSON(herr.Code, map[string][]string{"errors": {message}}) + } + } + + api.instance.DefaultHTTPErrorHandler(err, context) +} diff --git a/internal/api/middleware.go b/internal/api/middleware.go index 5304833..6272891 100644 --- a/internal/api/middleware.go +++ b/internal/api/middleware.go @@ -18,25 +18,25 @@ func (api *API) AuthSessionMiddleware(next echo.HandlerFunc) echo.HandlerFunc { sess, err := session.Get("session", context) if err != nil || sess.IsNew { - return context.String(http.StatusUnauthorized, "User not authenticated!") + return types.Error{Code: http.StatusUnauthorized, Messages: []string{"User not authenticated!"}} } id, ok := sess.Values["sessionId"].(string) if !ok || id == "" { - return context.String(http.StatusUnauthorized, "User not authenticated!") + return types.Error{Code: http.StatusUnauthorized, Messages: []string{"User not authenticated!"}} } sessionId, err := uuid.Parse(id) if err != nil { - return context.String(http.StatusUnauthorized, "User not authenticated!") + return types.Error{Code: http.StatusUnauthorized, Messages: []string{"User not authenticated!"}} } var user types.User if err := api.db.GetUserBySessionId(sessionId, &user); err != nil { - return context.String(http.StatusUnauthorized, "User not authenticated!") + return types.Error{Code: http.StatusUnauthorized, Messages: []string{"User not authenticated!"}} } context.Set("id", sess.Values["id"]) diff --git a/internal/api/user.go b/internal/api/user.go index 5b0abc3..d2675ba 100644 --- a/internal/api/user.go +++ b/internal/api/user.go @@ -1,9 +1,9 @@ package api import ( + "errors" "fmt" "io" - "log" "net/http" "os" "path/filepath" @@ -21,8 +21,7 @@ func (api *API) CreateUserHandler(context echo.Context) error { var body types.CreateUserRequestBody if err := context.Bind(&body); err != nil { - log.Println(fmt.Sprintf("Error creating User: %v.", err)) - return context.String(http.StatusBadRequest, "Invalid JSON!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"Invalid JSON!"}} } if err := context.Validate(body); err != nil { @@ -32,23 +31,19 @@ func (api *API) CreateUserHandler(context echo.Context) error { user, err := api.db.CreateUser(body) if err != nil { - log.Println(fmt.Sprintf("Error creating User: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error creating User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error creating User!"}} } sess, err := session.Get("session", context) if err != nil { - log.Println(fmt.Sprintf("Error creating User session: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error creating User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error creating User session!"}} } if err := lib.CreateSession(sess, context, &user); err != nil { - log.Println(fmt.Sprintf("Error creating User session: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error creating User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error creating User session!"}} } - log.Println(fmt.Sprintf("User created with ID %s.", user.ID)) return context.JSON(http.StatusOK, user) } @@ -56,10 +51,9 @@ func (api *API) GetAllUsersHandler(context echo.Context) error { users, err := api.db.GetUsers() if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error getting User!"}} } - log.Println("Got all Users.") return context.JSON(http.StatusOK, users) } @@ -67,22 +61,21 @@ func (api *API) GetUserHandler(context echo.Context) error { userId, ok := context.Get("id").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error getting User!"}} } id, err := uuid.Parse(userId) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error getting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error getting User!"}} } var user types.User if err := api.db.GetUserById(id, &user); err != nil { - return context.String(http.StatusNotFound, "User not found!") + return types.Error{Code: http.StatusNotFound, Messages: []string{"User not found!"}} } - log.Println(fmt.Sprintf("Got User with ID %s.", user.ID)) return context.JSON(http.StatusOK, user) } @@ -90,20 +83,25 @@ func (api *API) UpdateUserHandler(context echo.Context) error { userId, ok := context.Get("id").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error updating User!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error updating User!"}} } id, err := uuid.Parse(userId) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error updating User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error updating User!"}} } var body types.UpdateUserRequestBody if err := context.Bind(&body); err != nil { - log.Println(fmt.Sprintf("Error updating User: %v.", err)) - return context.String(http.StatusBadRequest, "Invalid JSON!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"Invalid JSON!"}} + } + + empty := body == types.UpdateUserRequestBody{} + + if empty { + return types.Error{Code: http.StatusBadRequest, Messages: []string{"You must update at least one field!"}} } if err := context.Validate(body); err != nil { @@ -113,10 +111,9 @@ func (api *API) UpdateUserHandler(context echo.Context) error { var user types.User if err := api.db.UpdateUser(id, body, &user); err != nil { - return context.String(http.StatusNotFound, "User not found!") + return types.Error{Code: http.StatusNotFound, Messages: []string{"User not found!"}} } - log.Println(fmt.Sprintf("Updated user with ID %s.", user.ID)) return context.JSON(http.StatusOK, user) } @@ -124,20 +121,19 @@ func (api *API) UpdateUserSecurityCredentialsHandler(context echo.Context) error userId, ok := context.Get("id").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error updating User security credentials!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error updating User security credentials!"}} } id, err := uuid.Parse(userId) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error updating User security credentials!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error updating User security credentials!"}} } var body types.UpdateUserSecurityCredentialsBody if err := context.Bind(&body); err != nil { - log.Println(fmt.Sprintf("Error creating security details for User: %v.", err)) - return context.String(http.StatusBadRequest, "Invalid JSON!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"Invalid JSON!"}} } if err := context.Validate(body); err != nil { @@ -147,10 +143,9 @@ func (api *API) UpdateUserSecurityCredentialsHandler(context echo.Context) error var user types.User if err := api.db.UpdateUserSecurityCredentials(id, body, &user); err != nil { - return context.String(http.StatusNotFound, "User not found!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"Invalid JSON!"}} } - log.Println(fmt.Sprintf("Updated security details of user with ID %s.", user.ID)) return context.JSON(http.StatusOK, user) } @@ -158,29 +153,29 @@ func (api *API) UpdateUserLogoHandler(context echo.Context) error { userId, ok := context.Get("id").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error updating User logo!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error updating User logo!"}} } id, err := uuid.Parse(userId) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error updating User logo!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error updating User logo!"}} } var user types.User if err := api.db.GetUserById(id, &user); err != nil { - return context.String(http.StatusNotFound, "User not found!") + return types.Error{Code: http.StatusNotFound, Messages: []string{"User not found!"}} } if user.Username == "" { - return context.String(http.StatusBadRequest, "You have to add a username first for this User!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"You have to add a username first for this User!"}} } file, err := context.FormFile("logo") if err != nil { - return types.Error{Code: http.StatusBadRequest, Messages: []string{"No image has been uploaded!"}} + return types.Error{Code: http.StatusUnsupportedMediaType, Messages: []string{"Image must be uploaded in form data!"}} } ext := strings.ToLower(filepath.Ext(file.Filename)) @@ -194,14 +189,13 @@ func (api *API) UpdateUserLogoHandler(context echo.Context) error { } if !allowedExtensions[ext] { - return context.String(http.StatusBadRequest, "Invalid file type, only image files are allowed!") + return types.Error{Code: http.StatusUnsupportedMediaType, Messages: []string{"Invalid file type, only image files are allowed!"}} } src, err := file.Open() if err != nil { - log.Println(fmt.Sprintf("Error updating logo for User: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error while updating logo for User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error updating logo User logo!"}} } defer src.Close() @@ -209,35 +203,31 @@ func (api *API) UpdateUserLogoHandler(context echo.Context) error { data, err := io.ReadAll(src) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error while updating logo for User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error updating logo User logo!"}} } filetype := http.DetectContentType(data) if !strings.HasPrefix(filetype, "image/") { - return context.String(http.StatusBadRequest, "Uploaded file is not a valid image!") + return types.Error{Code: http.StatusBadRequest, Messages: []string{"Uploaded file is not a valid image!"}} } if err := os.MkdirAll(filepath.Join(api.ConfigDirectory, user.Username), os.ModePerm); err != nil { - log.Println(fmt.Sprintf("Error updating logo for User: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error while updating logo for User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error updating User logo!"}} } path, err := filepath.Abs(filepath.Join(api.ConfigDirectory, user.Username, fmt.Sprintf("logo%s", ext))) if err != nil { - log.Println(fmt.Sprintf("Error updating logo for User: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error while updating logo for User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error updating User logo!"}} } if err := os.WriteFile(path, data, 0644); err != nil { - log.Println(fmt.Sprintf("Error updating logo for User: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error while updating logo for User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error updating User logo!"}} } if err := api.db.UpdateUserLogo(path, &user); err != nil { - log.Println(fmt.Sprintf("Error updating logo for User: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error while updating logo for User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error updating User logo!"}} } return context.JSON(http.StatusOK, user) @@ -247,49 +237,46 @@ func (api *API) DeleteUserHandler(context echo.Context) error { userId, ok := context.Get("id").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error deleting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error updating User logo!"}} } id, err := uuid.Parse(userId) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error deleting User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error deleting User!"}} } if err := api.db.DeleteUser(id); err != nil { - return context.String(http.StatusNotFound, "User not found!") + return types.Error{Code: http.StatusNotFound, Messages: []string{"User not found!"}} } - log.Println(fmt.Sprintf("Deleted User with ID %d.", id)) - return context.String(http.StatusOK, "User deleted successfully!") + return context.JSON(http.StatusOK, map[string]string{"message":"User deleted successfully!"}) } func (api *API) DeleteUserLogoHandler(context echo.Context) error { userId, ok := context.Get("id").(string) if !ok { - return context.String(http.StatusInternalServerError, "Unexpected error deleting User logo!") + return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Session ID not found after authorization."), Messages: []string{"Unexpected error deleting User logo!"}} } id, err := uuid.Parse(userId) if err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error deleting User logo!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error deleting User logo!"}} } var user types.User if err := api.db.GetUserById(id, &user); err != nil { - return context.String(http.StatusNotFound, "User not found!") + return types.Error{Code: http.StatusNotFound, Messages: []string{"User not found!"}} } os.Remove(user.Logo) if err := api.db.DeleteUserLogo(&user); err != nil { - log.Println(fmt.Sprintf("Error deleting logo of User: %v.", err)) - return context.String(http.StatusInternalServerError, "Unexpected error deleting logo of User!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error deleting User logo!"}} } - log.Println(fmt.Sprintf("Deleted logo of User with ID %s.", user.ID)) - return context.String(http.StatusOK, "User logo deleted successfully!") + return context.JSON(http.StatusOK, map[string]string{"message":"User logo deleted successfully!"}) } diff --git a/internal/api/validator.go b/internal/api/validator.go index 468d742..79856db 100644 --- a/internal/api/validator.go +++ b/internal/api/validator.go @@ -17,7 +17,7 @@ type CustomValidator struct { func (v *CustomValidator) Validate(i any) error { if err := v.validator.Struct(i); err != nil { if validationErrors, ok := err.(validator.ValidationErrors); ok { - errors := make([]string, 0, 10) + errs := make([]string, 0, 10) for _, ve := range validationErrors { field := ve.Field() @@ -42,9 +42,9 @@ func (v *CustomValidator) Validate(i any) error { msg = fmt.Sprintf("%s is not valid!", field) } - errors = append(errors, msg) + errs = append(errs, msg) } - return types.Error{Code: http.StatusBadRequest, Messages: errors} + return types.Error{Code: http.StatusBadRequest, Messages: errs} } } diff --git a/internal/lib/utils.go b/internal/lib/utils.go index 833b8fd..7a06430 100644 --- a/internal/lib/utils.go +++ b/internal/lib/utils.go @@ -27,7 +27,7 @@ func GetConfigDirectory() (string, error) { func SaveSession(session *sessions.Session, context echo.Context) error { if err := session.Save(context.Request(), context.Response()); err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error saving User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error saving User session!"}} } return nil @@ -35,7 +35,7 @@ func SaveSession(session *sessions.Session, context echo.Context) error { func CreateSession(session *sessions.Session, context echo.Context, user *types.User) error { if err := uuid.Validate(user.SessionID); err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error saving User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error saving User session!"}} } session.Options = &sessions.Options{ @@ -48,7 +48,7 @@ func CreateSession(session *sessions.Session, context echo.Context, user *types. session.Values["username"] = user.Username if err := SaveSession(session, context); err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error saving User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error saving User session!"}} } return nil @@ -58,7 +58,7 @@ func DeleteSession(session *sessions.Session, context echo.Context) error { session.Options.MaxAge = -1 if err := SaveSession(session, context); err != nil { - return context.String(http.StatusInternalServerError, "Unexpected error saving User session!") + return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error saving User session!"}} } return nil diff --git a/internal/types/error.go b/internal/types/error.go index ab02a70..fc4d163 100644 --- a/internal/types/error.go +++ b/internal/types/error.go @@ -1,13 +1,17 @@ package types -import "fmt" +import ( + "fmt" + "strings" +) type Error struct { Messages []string + Cause error Code int } func (err Error) Error() string { - return fmt.Sprintf("%v", - err.Messages) + return fmt.Sprintf("%s", + strings.Join(err.Messages, ", ")) }