mirror of
https://github.com/R0m1k3/noteflow.git
synced 2026-10-11 17:29:37 +02:00
Merge pull request #109 from R0m1k3/claude/fix-note-overwrite-bug-01Rx2KMQBoF8XiWUyEHb4c1K
Fix: Correction du bug d'écrasement de notes lors de la création
This commit is contained in:
7 files changed
+68
-15
No files matched your search
@@ -256,8 +256,20 @@ async function runQuery(sql, params = []) {
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
const result = await client.query(sql, params);
|
||||
|
||||
// Si c'est un INSERT/UPDATE avec RETURNING, retourner la ligne complète
|
||||
if (result.rows && result.rows.length > 0) {
|
||||
logger.info(`[runQuery] Requête avec RETURNING - ID: ${result.rows[0].id}, rowCount: ${result.rowCount}`);
|
||||
return {
|
||||
...result.rows[0], // Retourne toutes les colonnes de la première ligne
|
||||
changes: result.rowCount
|
||||
};
|
||||
}
|
||||
|
||||
// Sinon, retourner juste le nombre de lignes affectées
|
||||
logger.info(`[runQuery] Requête sans RETURNING - rowCount: ${result.rowCount}`);
|
||||
return {
|
||||
id: result.rows[0]?.id || result.rowCount,
|
||||
id: result.rowCount,
|
||||
changes: result.rowCount
|
||||
};
|
||||
} catch (error) {
|
||||
|
||||
@@ -190,10 +190,12 @@ router.get('/oauth-callback', async (req, res) => {
|
||||
userId
|
||||
]);
|
||||
} else {
|
||||
logger.info(`[CREATE OAUTH TOKEN] Ajout nouveau token OAuth - user_id: ${userId}`);
|
||||
await runQuery(`
|
||||
INSERT INTO google_oauth_tokens
|
||||
(user_id, access_token, refresh_token, token_type, expiry_date, scope)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING *
|
||||
`, [
|
||||
userId,
|
||||
tokens.access_token,
|
||||
@@ -202,6 +204,7 @@ router.get('/oauth-callback', async (req, res) => {
|
||||
tokens.expiry_date || null,
|
||||
tokens.scope || SCOPES.join(' ')
|
||||
]);
|
||||
logger.info(`[CREATE OAUTH TOKEN] Token OAuth créé avec succès pour user_id: ${userId}`);
|
||||
}
|
||||
|
||||
logger.info(`Tokens OAuth sauvegardés pour l'utilisateur ${userId}`);
|
||||
@@ -562,10 +565,12 @@ router.post('/sync', authenticateToken, async (req, res) => {
|
||||
]);
|
||||
} else {
|
||||
// Créer un nouvel événement
|
||||
logger.info(`[CREATE CALENDAR EVENT] Ajout événement - event_id: "${event.id}", title: "${event.summary || 'Sans titre'}"`);
|
||||
await runQuery(`
|
||||
INSERT INTO calendar_events
|
||||
(google_event_id, user_id, title, description, start_time, end_time, location, html_link, all_day)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
RETURNING *
|
||||
`, [
|
||||
event.id,
|
||||
req.user.id,
|
||||
@@ -577,6 +582,7 @@ router.post('/sync', authenticateToken, async (req, res) => {
|
||||
event.htmlLink || '',
|
||||
isAllDay
|
||||
]);
|
||||
logger.info(`[CREATE CALENDAR EVENT] Événement créé avec succès - event_id: "${event.id}"`);
|
||||
}
|
||||
syncedCount++;
|
||||
}
|
||||
@@ -707,6 +713,7 @@ router.post('/events', authenticateToken, async (req, res) => {
|
||||
const itemEndUTC = itemIsAllDay ? itemEndRaw : new Date(itemEndRaw).toISOString();
|
||||
|
||||
// PostgreSQL : INSERT ... ON CONFLICT DO UPDATE (pas INSERT OR REPLACE)
|
||||
logger.info(`[SYNC CALENDAR EVENT] Sync événement - event_id: "${item.id}"`);
|
||||
await runQuery(`
|
||||
INSERT INTO calendar_events
|
||||
(google_event_id, user_id, title, description, start_time, end_time, location, html_link, all_day, synced_at)
|
||||
@@ -720,6 +727,7 @@ router.post('/events', authenticateToken, async (req, res) => {
|
||||
html_link = EXCLUDED.html_link,
|
||||
all_day = EXCLUDED.all_day,
|
||||
synced_at = CURRENT_TIMESTAMP
|
||||
RETURNING *
|
||||
`, [
|
||||
item.id,
|
||||
req.user.id,
|
||||
|
||||
+23
-4
@@ -172,12 +172,15 @@ router.post('/',
|
||||
|
||||
const { title, content } = req.body;
|
||||
|
||||
logger.info(`[CREATE NOTE] Début création - user_id: ${req.user.id}, title: "${title}"`);
|
||||
|
||||
const result = await runQuery(`
|
||||
INSERT INTO notes (user_id, title, content)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING *
|
||||
`, [req.user.id, title, content || '']);
|
||||
|
||||
logger.info(`Note créée: ${title} (ID: ${result.id}) par ${req.user.username}`);
|
||||
logger.info(`[CREATE NOTE] Note créée avec succès - ID: ${result.id}, title: "${title}", user: ${req.user.username}`);
|
||||
|
||||
res.status(201).json({
|
||||
id: result.id,
|
||||
@@ -395,11 +398,16 @@ router.post('/:id/todos',
|
||||
|
||||
const { text } = req.body;
|
||||
|
||||
logger.info(`[CREATE TODO] Ajout todo à note ${req.params.id}: "${text}"`);
|
||||
|
||||
const result = await runQuery(`
|
||||
INSERT INTO note_todos (note_id, text, position)
|
||||
VALUES ($1, $2, (SELECT COALESCE(MAX(position), FALSE) + 1 FROM note_todos WHERE note_id = $3))
|
||||
RETURNING *
|
||||
`, [req.params.id, text, req.params.id]);
|
||||
|
||||
logger.info(`[CREATE TODO] Todo créé - ID: ${result.id}, note_id: ${req.params.id}`);
|
||||
|
||||
await runQuery('UPDATE notes SET updated_at = CURRENT_TIMESTAMP WHERE id = $1', [req.params.id]);
|
||||
|
||||
res.status(201).json({
|
||||
@@ -582,15 +590,18 @@ router.post('/:id/images', imageUpload.single('image'), async (req, res) => {
|
||||
}
|
||||
|
||||
// Enregistrer l'image dans la base de données
|
||||
logger.info(`[CREATE IMAGE] Ajout image à note ${req.params.id}: ${req.file.originalname}`);
|
||||
|
||||
const result = await runQuery(`
|
||||
INSERT INTO note_images (note_id, filename, original_name)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING *
|
||||
`, [req.params.id, req.file.filename, req.file.originalname]);
|
||||
|
||||
// Mettre à jour la date de modification de la note
|
||||
await runQuery('UPDATE notes SET updated_at = CURRENT_TIMESTAMP WHERE id = $1', [req.params.id]);
|
||||
|
||||
logger.info(`Image ajoutée à la note ${req.params.id}: ${req.file.filename}`);
|
||||
logger.info(`[CREATE IMAGE] Image créée - ID: ${result.id}, filename: ${req.file.filename}, note_id: ${req.params.id}`);
|
||||
|
||||
res.json({
|
||||
message: 'Image ajoutée avec succès',
|
||||
@@ -716,15 +727,18 @@ router.post('/:id/files', fileUpload.single('file'), async (req, res) => {
|
||||
}
|
||||
|
||||
// Enregistrer le fichier dans la base de données
|
||||
logger.info(`[CREATE FILE] Ajout fichier à note ${req.params.id}: ${req.file.originalname}`);
|
||||
|
||||
const result = await runQuery(`
|
||||
INSERT INTO note_files (note_id, filename, original_name, file_size, mime_type)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING *
|
||||
`, [req.params.id, req.file.filename, req.file.originalname, req.file.size, req.file.mimetype]);
|
||||
|
||||
// Mettre à jour la date de modification de la note
|
||||
await runQuery('UPDATE notes SET updated_at = CURRENT_TIMESTAMP WHERE id = $1', [req.params.id]);
|
||||
|
||||
logger.info(`Fichier ajouté à la note ${req.params.id}: ${req.file.originalname}`);
|
||||
logger.info(`[CREATE FILE] Fichier créé - ID: ${result.id}, filename: ${req.file.filename}, note_id: ${req.params.id}`);
|
||||
|
||||
res.json({
|
||||
message: 'Fichier ajouté avec succès',
|
||||
@@ -877,7 +891,12 @@ router.post('/:id/tags', async (req, res) => {
|
||||
return res.status(404).json({ error: 'Note non trouvée' });
|
||||
}
|
||||
|
||||
const result = await runQuery('INSERT INTO note_tags (note_id, tag) VALUES ($1, $2)', [req.params.id, tag.trim().toLowerCase()]);
|
||||
logger.info(`[CREATE TAG] Ajout tag à note ${req.params.id}: "${tag.trim().toLowerCase()}"`);
|
||||
|
||||
const result = await runQuery('INSERT INTO note_tags (note_id, tag) VALUES ($1, $2) RETURNING *', [req.params.id, tag.trim().toLowerCase()]);
|
||||
|
||||
logger.info(`[CREATE TAG] Tag créé - ID: ${result.id}, tag: "${result.tag}", note_id: ${req.params.id}`);
|
||||
|
||||
res.json({ id: result.id, tag: tag.trim().toLowerCase() });
|
||||
} catch (error) {
|
||||
if (error.message && error.message.includes('UNIQUE constraint')) {
|
||||
|
||||
@@ -47,13 +47,15 @@ router.post('/feeds', requireAdmin, async (req, res) => {
|
||||
try {
|
||||
const feed = await parser.parseURL(url);
|
||||
|
||||
logger.info(`[CREATE RSS FEED] Ajout flux - url: "${url}", title: "${feed.title || url}"`);
|
||||
|
||||
// Ajouter le flux
|
||||
const result = await runQuery(
|
||||
'INSERT INTO rss_feeds (url, title, description, enabled) VALUES ($1, $2, $3, TRUE)',
|
||||
'INSERT INTO rss_feeds (url, title, description, enabled) VALUES ($1, $2, $3, TRUE) RETURNING *',
|
||||
[url, feed.title || url, feed.description || '']
|
||||
);
|
||||
|
||||
logger.info(`✅ Flux ajouté: ${feed.title}`);
|
||||
logger.info(`[CREATE RSS FEED] Flux créé avec succès - ID: ${result.id}, title: "${feed.title}"`);
|
||||
|
||||
// Déclencher un fetch immédiat
|
||||
setTimeout(() => {
|
||||
@@ -250,11 +252,15 @@ Résumé (100 mots max):`;
|
||||
|
||||
const summary = response.data.choices[0].message.content;
|
||||
|
||||
logger.info(`[CREATE RSS SUMMARY] Ajout résumé - article: "${article.title}", model: "${selectedModel}"`);
|
||||
|
||||
await runQuery(
|
||||
'INSERT INTO rss_summaries (summary, model, articles_count, feed_title, created_at) VALUES (?, ?, ?, ?, datetime("now"))',
|
||||
'INSERT INTO rss_summaries (summary, model, articles_count, feed_title, created_at) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP) RETURNING *',
|
||||
[`**${article.title}**\n\n${summary}\n\n🔗 [Lire l'article](${article.link})`, selectedModel, 1, article.feed_title]
|
||||
);
|
||||
|
||||
logger.info(`[CREATE RSS SUMMARY] Résumé créé avec succès`);
|
||||
|
||||
return {
|
||||
article_id: article.id,
|
||||
title: article.title,
|
||||
|
||||
@@ -52,10 +52,12 @@ router.put('/', async (req, res) => {
|
||||
[value, key]
|
||||
);
|
||||
} else {
|
||||
logger.info(`[CREATE SETTING] Ajout nouveau paramètre - key: "${key}"`);
|
||||
await runQuery(
|
||||
'INSERT INTO settings (key, value) VALUES ($1, $2)',
|
||||
'INSERT INTO settings (key, value) VALUES ($1, $2) RETURNING *',
|
||||
[key, value]
|
||||
);
|
||||
logger.info(`[CREATE SETTING] Paramètre créé avec succès - key: "${key}"`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,14 +104,15 @@ router.put('/:key', async (req, res) => {
|
||||
'UPDATE settings SET value = $1, updated_at = CURRENT_TIMESTAMP WHERE key = $2',
|
||||
[value, req.params.key]
|
||||
);
|
||||
logger.info(`Paramètre mis à jour: ${req.params.key}`);
|
||||
} else {
|
||||
logger.info(`[CREATE SETTING] Ajout nouveau paramètre - key: "${req.params.key}"`);
|
||||
await runQuery(
|
||||
'INSERT INTO settings (key, value) VALUES ($1, $2)',
|
||||
'INSERT INTO settings (key, value) VALUES ($1, $2) RETURNING *',
|
||||
[req.params.key, value]
|
||||
);
|
||||
logger.info(`[CREATE SETTING] Paramètre créé avec succès - key: "${req.params.key}"`);
|
||||
}
|
||||
|
||||
logger.info(`Paramètre mis à jour: ${req.params.key}`);
|
||||
res.json({ key: req.params.key, value });
|
||||
} catch (error) {
|
||||
logger.error('Erreur lors de la mise à jour du paramètre:', error);
|
||||
|
||||
@@ -45,12 +45,15 @@ router.post('/',
|
||||
|
||||
const { text } = req.body;
|
||||
|
||||
logger.info(`[CREATE GLOBAL TODO] Début création - user_id: ${req.user.id}, text: "${text}"`);
|
||||
|
||||
const result = await runQuery(`
|
||||
INSERT INTO global_todos (user_id, text)
|
||||
VALUES ($1, $2)
|
||||
RETURNING *
|
||||
`, [req.user.id, text]);
|
||||
|
||||
logger.info(`Todo global créé (ID: ${result.id}) par ${req.user.username}`);
|
||||
logger.info(`[CREATE GLOBAL TODO] Todo global créé avec succès - ID: ${result.id}, user: ${req.user.username}`);
|
||||
|
||||
res.status(201).json({
|
||||
id: result.id,
|
||||
|
||||
@@ -56,13 +56,15 @@ router.post('/',
|
||||
// Hasher le mot de passe
|
||||
const passwordHash = await bcrypt.hash(password, 12);
|
||||
|
||||
logger.info(`[CREATE USER] Début création - username: "${username}", is_admin: ${is_admin ? 1 : 0}`);
|
||||
|
||||
// Créer l'utilisateur
|
||||
const result = await runQuery(
|
||||
'INSERT INTO users (username, password_hash, is_admin) VALUES ($1, $2, $3)',
|
||||
'INSERT INTO users (username, password_hash, is_admin) VALUES ($1, $2, $3) RETURNING *',
|
||||
[username, passwordHash, is_admin ? 1 : 0]
|
||||
);
|
||||
|
||||
logger.info(`Utilisateur créé: ${username} (ID: ${result.id})`);
|
||||
logger.info(`[CREATE USER] Utilisateur créé avec succès - ID: ${result.id}, username: "${username}"`);
|
||||
|
||||
res.status(201).json({
|
||||
id: result.id,
|
||||
|
||||
Reference in new issue
Block a user