v2.0.6: Fix addWords handler - add user_id and improve error handling
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 40s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 40s
- Added user_id to words insertion (was missing, causing 500 errors) - Fixed default dictionary query (removed incorrect id=0 condition) - Added dictionary ownership validation before inserting words - Added comprehensive logging for debugging addWords operations
This commit is contained in:
@@ -861,12 +861,16 @@ func (a *App) addWordsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req WordsRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
log.Printf("Error decoding addWords request: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("addWords: user_id=%d, words_count=%d", userID, len(req.Words))
|
||||
|
||||
tx, err := a.DB.Begin()
|
||||
if err != nil {
|
||||
log.Printf("Error beginning transaction: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@@ -875,52 +879,84 @@ func (a *App) addWordsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Create default dictionary for user if needed
|
||||
var defaultDictID int
|
||||
err = tx.QueryRow(`
|
||||
SELECT id FROM dictionaries WHERE user_id = $1 AND id = 0
|
||||
UNION ALL
|
||||
SELECT id FROM dictionaries WHERE user_id = $1 ORDER BY id LIMIT 1
|
||||
`, userID).Scan(&defaultDictID)
|
||||
if err == sql.ErrNoRows {
|
||||
// Create default dictionary for user
|
||||
log.Printf("Creating default dictionary for user_id=%d", userID)
|
||||
err = tx.QueryRow(`
|
||||
INSERT INTO dictionaries (name, user_id) VALUES ('Все слова', $1) RETURNING id
|
||||
`, userID).Scan(&defaultDictID)
|
||||
if err != nil {
|
||||
log.Printf("Error creating default dictionary: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
log.Printf("Created default dictionary id=%d for user_id=%d", defaultDictID, userID)
|
||||
} else if err != nil {
|
||||
log.Printf("Error finding default dictionary: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
} else {
|
||||
log.Printf("Using default dictionary id=%d for user_id=%d", defaultDictID, userID)
|
||||
}
|
||||
|
||||
stmt, err := tx.Prepare(`
|
||||
INSERT INTO words (name, translation, description, dictionary_id)
|
||||
VALUES ($1, $2, $3, COALESCE($4, $5))
|
||||
INSERT INTO words (name, translation, description, dictionary_id, user_id)
|
||||
VALUES ($1, $2, $3, COALESCE($4, $5), $6)
|
||||
RETURNING id
|
||||
`)
|
||||
if err != nil {
|
||||
log.Printf("Error preparing insert statement: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
var addedCount int
|
||||
for _, wordReq := range req.Words {
|
||||
for i, wordReq := range req.Words {
|
||||
var id int
|
||||
dictionaryID := defaultDictID
|
||||
if wordReq.DictionaryID != nil {
|
||||
dictionaryID = *wordReq.DictionaryID
|
||||
// Проверяем, что словарь принадлежит пользователю
|
||||
var dictUserID int
|
||||
err := tx.QueryRow(`
|
||||
SELECT user_id FROM dictionaries WHERE id = $1
|
||||
`, dictionaryID).Scan(&dictUserID)
|
||||
if err == sql.ErrNoRows {
|
||||
log.Printf("Dictionary %d not found for word %d", dictionaryID, i)
|
||||
sendErrorWithCORS(w, fmt.Sprintf("Dictionary %d not found", dictionaryID), http.StatusBadRequest)
|
||||
return
|
||||
} else if err != nil {
|
||||
log.Printf("Error checking dictionary ownership: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if dictUserID != userID {
|
||||
log.Printf("Dictionary %d belongs to user %d, but request from user %d", dictionaryID, dictUserID, userID)
|
||||
sendErrorWithCORS(w, fmt.Sprintf("Dictionary %d does not belong to user", dictionaryID), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
}
|
||||
err := stmt.QueryRow(wordReq.Name, wordReq.Translation, wordReq.Description, wordReq.DictionaryID, dictionaryID).Scan(&id)
|
||||
err := stmt.QueryRow(wordReq.Name, wordReq.Translation, wordReq.Description, wordReq.DictionaryID, dictionaryID, userID).Scan(&id)
|
||||
if err != nil {
|
||||
log.Printf("Error inserting word %d (name='%s', dict_id=%d, user_id=%d): %v", i, wordReq.Name, dictionaryID, userID, err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
addedCount++
|
||||
log.Printf("Successfully added word id=%d: name='%s', dict_id=%d", id, wordReq.Name, dictionaryID)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
log.Printf("Error committing transaction: %v", err)
|
||||
sendErrorWithCORS(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Successfully added %d words for user_id=%d", addedCount, userID)
|
||||
|
||||
setCORSHeaders(w)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
|
||||
Reference in New Issue
Block a user