4.24.0: Удаление и сброс прогресса слов
This commit is contained in:
@@ -1543,6 +1543,129 @@ func (a *App) addWordsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) deleteWordHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "OPTIONS" {
|
||||
setCORSHeaders(w)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
userID, ok := getUserIDFromContext(r)
|
||||
if !ok {
|
||||
sendErrorWithCORS(w, "Unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
wordID, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
sendErrorWithCORS(w, "Invalid word ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Verify ownership - check that word belongs to user
|
||||
var ownerID int
|
||||
err = a.DB.QueryRow("SELECT user_id FROM words WHERE id = $1", wordID).Scan(&ownerID)
|
||||
if err == sql.ErrNoRows {
|
||||
sendErrorWithCORS(w, "Word not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("Error checking word ownership: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if ownerID != userID {
|
||||
sendErrorWithCORS(w, "Word not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete the word (progress will be deleted automatically due to CASCADE)
|
||||
result, err := a.DB.Exec("DELETE FROM words WHERE id = $1", wordID)
|
||||
if err != nil {
|
||||
log.Printf("Error deleting word: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
log.Printf("Error getting rows affected: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if rowsAffected == 0 {
|
||||
sendErrorWithCORS(w, "Word not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
setCORSHeaders(w)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"message": "Word deleted successfully",
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) resetWordProgressHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "OPTIONS" {
|
||||
setCORSHeaders(w)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
userID, ok := getUserIDFromContext(r)
|
||||
if !ok {
|
||||
sendErrorWithCORS(w, "Unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
wordID, err := strconv.Atoi(vars["id"])
|
||||
if err != nil {
|
||||
sendErrorWithCORS(w, "Invalid word ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Verify ownership - check that word belongs to user
|
||||
var ownerID int
|
||||
err = a.DB.QueryRow("SELECT user_id FROM words WHERE id = $1", wordID).Scan(&ownerID)
|
||||
if err == sql.ErrNoRows {
|
||||
sendErrorWithCORS(w, "Word not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("Error checking word ownership: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if ownerID != userID {
|
||||
sendErrorWithCORS(w, "Word not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Reset progress for this word and user
|
||||
_, err = a.DB.Exec(`
|
||||
UPDATE progress
|
||||
SET success = 0,
|
||||
failure = 0,
|
||||
last_success_at = NULL,
|
||||
last_failure_at = NULL
|
||||
WHERE word_id = $1 AND user_id = $2
|
||||
`, wordID, userID)
|
||||
if err != nil {
|
||||
log.Printf("Error resetting word progress: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
setCORSHeaders(w)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"message": "Word progress reset successfully",
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) getTestWordsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("getTestWordsHandler called: %s %s", r.Method, r.URL.Path)
|
||||
setCORSHeaders(w)
|
||||
@@ -4007,6 +4130,8 @@ func main() {
|
||||
// Words & dictionaries
|
||||
protected.HandleFunc("/api/words", app.getWordsHandler).Methods("GET", "OPTIONS")
|
||||
protected.HandleFunc("/api/words", app.addWordsHandler).Methods("POST", "OPTIONS")
|
||||
protected.HandleFunc("/api/words/{id}", app.deleteWordHandler).Methods("DELETE", "OPTIONS")
|
||||
protected.HandleFunc("/api/words/{id}/reset-progress", app.resetWordProgressHandler).Methods("POST", "OPTIONS")
|
||||
protected.HandleFunc("/api/test/words", app.getTestWordsHandler).Methods("GET", "OPTIONS")
|
||||
protected.HandleFunc("/api/test/progress", app.updateTestProgressHandler).Methods("POST", "OPTIONS")
|
||||
protected.HandleFunc("/api/dictionaries", app.getDictionariesHandler).Methods("GET", "OPTIONS")
|
||||
|
||||
Reference in New Issue
Block a user