Update api docs

This commit is contained in:
2024-12-03 21:50:16 +01:00
parent c400d81c87
commit e413e955c5
17 changed files with 331 additions and 261 deletions

View File

@@ -32,15 +32,15 @@ type DeleteAccountRequest struct {
// @Produce json
// @Param body body UpdateProfileRequest true "Profile update request"
// @Success 200 {object} models.User
// @Failure 400 {string} string "Invalid request body"
// @Failure 400 {string} string "Current password is required to change password"
// @Failure 400 {string} string "New password must be at least 8 characters long"
// @Failure 400 {string} string "Current password is required to change email"
// @Failure 401 {string} string "Current password is incorrect"
// @Failure 404 {string} string "User not found"
// @Failure 409 {string} string "Email already in use"
// @Failure 500 {string} string "Failed to process new password"
// @Failure 500 {string} string "Failed to update profile"
// @Failure 400 {object} ErrorResponse "Invalid request body"
// @Failure 400 {object} ErrorResponse "Current password is required to change password"
// @Failure 400 {object} ErrorResponse "New password must be at least 8 characters long"
// @Failure 400 {object} ErrorResponse "Current password is required to change email"
// @Failure 401 {object} ErrorResponse "Current password is incorrect"
// @Failure 404 {object} ErrorResponse "User not found"
// @Failure 409 {object} ErrorResponse "Email already in use"
// @Failure 500 {object} ErrorResponse "Failed to process new password"
// @Failure 500 {object} ErrorResponse "Failed to update profile"
// @Router /profile [put]
func (h *Handler) UpdateProfile() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -51,14 +51,14 @@ func (h *Handler) UpdateProfile() http.HandlerFunc {
var req UpdateProfileRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
respondError(w, "Invalid request body", http.StatusBadRequest)
return
}
// Get current user
user, err := h.DB.GetUserByID(ctx.UserID)
if err != nil {
http.Error(w, "User not found", http.StatusNotFound)
respondError(w, "User not found", http.StatusNotFound)
return
}
@@ -66,26 +66,26 @@ func (h *Handler) UpdateProfile() http.HandlerFunc {
if req.NewPassword != "" {
// Current password must be provided to change password
if req.CurrentPassword == "" {
http.Error(w, "Current password is required to change password", http.StatusBadRequest)
respondError(w, "Current password is required to change password", http.StatusBadRequest)
return
}
// Verify current password
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.CurrentPassword)); err != nil {
http.Error(w, "Current password is incorrect", http.StatusUnauthorized)
respondError(w, "Current password is incorrect", http.StatusUnauthorized)
return
}
// Validate new password
if len(req.NewPassword) < 8 {
http.Error(w, "New password must be at least 8 characters long", http.StatusBadRequest)
respondError(w, "New password must be at least 8 characters long", http.StatusBadRequest)
return
}
// Hash new password
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
if err != nil {
http.Error(w, "Failed to process new password", http.StatusInternalServerError)
respondError(w, "Failed to process new password", http.StatusInternalServerError)
return
}
user.PasswordHash = string(hashedPassword)
@@ -95,14 +95,14 @@ func (h *Handler) UpdateProfile() http.HandlerFunc {
if req.Email != "" && req.Email != user.Email {
// Check if email change requires password verification
if req.CurrentPassword == "" {
http.Error(w, "Current password is required to change email", http.StatusBadRequest)
respondError(w, "Current password is required to change email", http.StatusBadRequest)
return
}
// Verify current password if not already verified for password change
if req.NewPassword == "" {
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.CurrentPassword)); err != nil {
http.Error(w, "Current password is incorrect", http.StatusUnauthorized)
respondError(w, "Current password is incorrect", http.StatusUnauthorized)
return
}
}
@@ -110,7 +110,7 @@ func (h *Handler) UpdateProfile() http.HandlerFunc {
// Check if new email is already in use
existingUser, err := h.DB.GetUserByEmail(req.Email)
if err == nil && existingUser.ID != user.ID {
http.Error(w, "Email already in use", http.StatusConflict)
respondError(w, "Email already in use", http.StatusConflict)
return
}
user.Email = req.Email
@@ -123,7 +123,7 @@ func (h *Handler) UpdateProfile() http.HandlerFunc {
// Update user in database
if err := h.DB.UpdateUser(user); err != nil {
http.Error(w, "Failed to update profile", http.StatusInternalServerError)
respondError(w, "Failed to update profile", http.StatusInternalServerError)
return
}
@@ -141,13 +141,13 @@ func (h *Handler) UpdateProfile() http.HandlerFunc {
// @Accept json
// @Produce json
// @Param body body DeleteAccountRequest true "Account deletion request"
// @Success 200 {object} map[string]string
// @Failure 400 {string} string "Invalid request body"
// @Failure 401 {string} string "Password is incorrect"
// @Failure 403 {string} string "Cannot delete the last admin account"
// @Failure 404 {string} string "User not found"
// @Failure 500 {string} string "Failed to verify admin status"
// @Failure 500 {string} string "Failed to delete account"
// @Success 204 "No Content - Account deleted successfully"
// @Failure 400 {object} ErrorResponse "Invalid request body"
// @Failure 401 {object} ErrorResponse "Password is incorrect"
// @Failure 403 {object} ErrorResponse "Cannot delete the last admin account"
// @Failure 404 {object} ErrorResponse "User not found"
// @Failure 500 {object} ErrorResponse "Failed to verify admin status"
// @Failure 500 {object} ErrorResponse "Failed to delete account"
// @Router /profile [delete]
func (h *Handler) DeleteAccount() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -158,20 +158,20 @@ func (h *Handler) DeleteAccount() http.HandlerFunc {
var req DeleteAccountRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
respondError(w, "Invalid request body", http.StatusBadRequest)
return
}
// Get current user
user, err := h.DB.GetUserByID(ctx.UserID)
if err != nil {
http.Error(w, "User not found", http.StatusNotFound)
respondError(w, "User not found", http.StatusNotFound)
return
}
// Verify password
if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password)); err != nil {
http.Error(w, "Password is incorrect", http.StatusUnauthorized)
respondError(w, "Password is incorrect", http.StatusUnauthorized)
return
}
@@ -180,11 +180,11 @@ func (h *Handler) DeleteAccount() http.HandlerFunc {
// Count number of admin users
adminCount, err := h.DB.CountAdminUsers()
if err != nil {
http.Error(w, "Failed to verify admin status", http.StatusInternalServerError)
respondError(w, "Failed to verify admin status", http.StatusInternalServerError)
return
}
if adminCount <= 1 {
http.Error(w, "Cannot delete the last admin account", http.StatusForbidden)
respondError(w, "Cannot delete the last admin account", http.StatusForbidden)
return
}
}
@@ -192,24 +192,24 @@ func (h *Handler) DeleteAccount() http.HandlerFunc {
// Get user's workspaces for cleanup
workspaces, err := h.DB.GetWorkspacesByUserID(ctx.UserID)
if err != nil {
http.Error(w, "Failed to get user workspaces", http.StatusInternalServerError)
respondError(w, "Failed to get user workspaces", http.StatusInternalServerError)
return
}
// Delete workspace directories
for _, workspace := range workspaces {
if err := h.Storage.DeleteUserWorkspace(ctx.UserID, workspace.ID); err != nil {
http.Error(w, "Failed to delete workspace files", http.StatusInternalServerError)
respondError(w, "Failed to delete workspace files", http.StatusInternalServerError)
return
}
}
// Delete user from database (this will cascade delete workspaces and sessions)
if err := h.DB.DeleteUser(ctx.UserID); err != nil {
http.Error(w, "Failed to delete account", http.StatusInternalServerError)
respondError(w, "Failed to delete account", http.StatusInternalServerError)
return
}
respondJSON(w, map[string]string{"message": "Account deleted successfully"})
w.WriteHeader(http.StatusNoContent)
}
}