chore: update id order
This commit is contained in:
+53
-154
@@ -1,7 +1,6 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"gestion/models"
|
||||
"log"
|
||||
@@ -42,7 +41,6 @@ func validateProductID(productID int) error {
|
||||
// validateMediaType vérifie le type de média
|
||||
func validateMediaType(mediaType string) error {
|
||||
validTypes := []string{"image", "video"}
|
||||
|
||||
mediaType = strings.ToLower(strings.TrimSpace(mediaType))
|
||||
if slices.Contains(validTypes, mediaType) {
|
||||
return nil
|
||||
@@ -55,46 +53,29 @@ func validateMediaURL(url string) error {
|
||||
if len(url) == 0 {
|
||||
return fmt.Errorf("URL vide")
|
||||
}
|
||||
|
||||
if len(url) > 500 {
|
||||
return fmt.Errorf("URL trop longue (max 500 caractères)")
|
||||
}
|
||||
|
||||
// ✅ PROTECTION PATH TRAVERSAL
|
||||
if strings.Contains(url, "..") || strings.Contains(url, "...") || strings.Contains(url, "..//") {
|
||||
return fmt.Errorf("path traversal détecté dans l'URL")
|
||||
}
|
||||
|
||||
// ✅ VÉRIFIER QUE L'URL COMMENCE PAR /uploads/
|
||||
if !strings.HasPrefix(url, "/uploads/") {
|
||||
return fmt.Errorf("URL doit commencer par /uploads/")
|
||||
}
|
||||
|
||||
// ✅ VÉRIFIER QU'IL N'Y A PAS DE CARACTÈRES DANGEREUX
|
||||
dangerousChars := []string{
|
||||
"<", ">", "\"", "'", ";", "|", "&", "$", "`", "\\",
|
||||
}
|
||||
|
||||
dangerousChars := []string{"<", ">", "\"", "'", ";", "|", "&", "$", "`", "\\"}
|
||||
for _, char := range dangerousChars {
|
||||
if strings.Contains(url, char) {
|
||||
return fmt.Errorf("caractères interdits dans l'URL")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// CREATE MEDIA - VERSION SÉCURISÉE
|
||||
// ============================================
|
||||
|
||||
func (db *Database) CreateMedia(media any) error {
|
||||
func (d *Database) CreateMedia(media any) error {
|
||||
log.Printf("🔒 [CreateMedia] START - Type: %T", media)
|
||||
|
||||
// ✅ TYPE ASSERTION SÉCURISÉE
|
||||
m, ok := media.(MediaInterface)
|
||||
if !ok {
|
||||
// Vérifier si c'est un pointeur vers models.Media
|
||||
if mediaPtr, isPtr := media.(*models.Media); isPtr {
|
||||
m = mediaPtr
|
||||
ok = true
|
||||
@@ -116,29 +97,25 @@ func (db *Database) CreateMedia(media any) error {
|
||||
log.Printf("❌ [CreateMedia] %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := validateMediaType(mediaType); err != nil {
|
||||
log.Printf("❌ [CreateMedia] %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := validateMediaURL(mediaURL); err != nil {
|
||||
log.Printf("❌ [CreateMedia] %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.InsertMedia(m, productID, mediaURL, mediaType); err != nil {
|
||||
if err := d.InsertMedia(m, productID, mediaURL, mediaType); err != nil {
|
||||
log.Printf("❌ [InsertMedia] %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *Database) InsertMedia(m any, productID int, mediaURL any, mediaType string) error {
|
||||
func (d *Database) InsertMedia(m any, productID int, mediaURL any, mediaType string) error {
|
||||
var exists bool
|
||||
checkQuery := `SELECT EXISTS(SELECT 1 FROM products WHERE id = $1)`
|
||||
err := db.QueryRow(checkQuery, productID).Scan(&exists)
|
||||
if err != nil {
|
||||
if err := d.GDB.Raw(`SELECT EXISTS(SELECT 1 FROM products WHERE id = ?)`, productID).Scan(&exists).Error; err != nil {
|
||||
log.Printf("❌ [CreateMedia] Erreur vérification produit: %v", err)
|
||||
return fmt.Errorf("erreur vérification produit: %w", err)
|
||||
}
|
||||
@@ -147,178 +124,111 @@ func (db *Database) InsertMedia(m any, productID int, mediaURL any, mediaType st
|
||||
return fmt.Errorf("produit %d n'existe pas", productID)
|
||||
}
|
||||
|
||||
query := `INSERT INTO media (product_id, url, type, created_at)
|
||||
VALUES ($1, $2, $3, $4) RETURNING id`
|
||||
|
||||
var mediaID int
|
||||
now := time.Now()
|
||||
|
||||
err = db.QueryRow(query, productID, mediaURL, mediaType, now).Scan(&mediaID)
|
||||
var result struct {
|
||||
ID int `gorm:"column:id"`
|
||||
}
|
||||
err := d.GDB.Raw(`
|
||||
INSERT INTO media (product_id, url, type, created_at)
|
||||
VALUES (?, ?, ?, ?) RETURNING id`,
|
||||
productID, mediaURL, mediaType, time.Now(),
|
||||
).Scan(&result).Error
|
||||
if err != nil {
|
||||
log.Printf("❌ [CreateMedia] Erreur INSERT: %v", err)
|
||||
return fmt.Errorf("erreur création média: %w", err)
|
||||
}
|
||||
|
||||
if mi, ok := m.(MediaInterface); ok {
|
||||
mi.SetID(mediaID)
|
||||
mi.SetID(result.ID)
|
||||
}
|
||||
log.Printf("✅ [CreateMedia] Média créé: ID=%d, Type=%s", mediaID, mediaType)
|
||||
log.Printf("✅ [CreateMedia] Média créé: ID=%d, Type=%s", result.ID, mediaType)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// GET MEDIA BY ID - VERSION SÉCURISÉE
|
||||
// ============================================
|
||||
|
||||
func (db *Database) GetMediaByID(mediaID int) (*models.Media, error) {
|
||||
func (d *Database) GetMediaByID(mediaID int) (*models.Media, error) {
|
||||
log.Printf("🔍 [GetMediaByID] START - ID=%d", mediaID)
|
||||
|
||||
// ✅ VALIDATION
|
||||
if err := validateMediaID(mediaID); err != nil {
|
||||
log.Printf("❌ [GetMediaByID] %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var media models.Media
|
||||
|
||||
query := `SELECT id, product_id, url, type, created_at
|
||||
FROM media
|
||||
WHERE id = $1`
|
||||
|
||||
err := db.QueryRow(query, mediaID).Scan(
|
||||
&media.ID,
|
||||
&media.ProductID,
|
||||
&media.URL,
|
||||
&media.Type,
|
||||
&media.CreatedAt,
|
||||
)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
log.Printf("❌ [GetMediaByID] Média %d non trouvé", mediaID)
|
||||
return nil, fmt.Errorf("média non trouvé")
|
||||
}
|
||||
|
||||
err := d.GDB.Raw(`
|
||||
SELECT id, product_id, url, type, created_at
|
||||
FROM media WHERE id = ?`, mediaID).Scan(&media).Error
|
||||
if err != nil {
|
||||
log.Printf("❌ [GetMediaByID] Erreur query: %v", err)
|
||||
return nil, fmt.Errorf("erreur récupération média: %w", err)
|
||||
}
|
||||
if media.ID == 0 {
|
||||
log.Printf("❌ [GetMediaByID] Média %d non trouvé", mediaID)
|
||||
return nil, fmt.Errorf("média non trouvé")
|
||||
}
|
||||
|
||||
log.Printf("✅ [GetMediaByID] Média trouvé: Type=%s", media.Type)
|
||||
|
||||
return &media, nil
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// GET MEDIA BY PRODUCT ID - VERSION SÉCURISÉE
|
||||
// ============================================
|
||||
|
||||
func (db *Database) GetMediaByProductID(productID int) ([]models.Media, error) {
|
||||
func (d *Database) GetMediaByProductID(productID int) ([]models.Media, error) {
|
||||
log.Printf("🖼️ [GetMediaByProductID] START - ProductID=%d", productID)
|
||||
|
||||
// ✅ VALIDATION
|
||||
if err := validateProductID(productID); err != nil {
|
||||
log.Printf("❌ [GetMediaByProductID] %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := `SELECT id, product_id, url, type, created_at
|
||||
FROM media
|
||||
WHERE product_id = $1
|
||||
ORDER BY id ASC`
|
||||
|
||||
rows, err := db.Query(query, productID)
|
||||
var mediaList []models.Media
|
||||
err := d.GDB.Raw(`
|
||||
SELECT id, product_id, url, type, created_at
|
||||
FROM media WHERE product_id = ?
|
||||
ORDER BY id ASC`, productID).Scan(&mediaList).Error
|
||||
if err != nil {
|
||||
log.Printf("❌ [GetMediaByProductID] Erreur query: %v", err)
|
||||
return nil, fmt.Errorf("erreur récupération médias: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var mediaList []models.Media
|
||||
|
||||
for rows.Next() {
|
||||
var media models.Media
|
||||
|
||||
if err := rows.Scan(
|
||||
&media.ID,
|
||||
&media.ProductID,
|
||||
&media.URL,
|
||||
&media.Type,
|
||||
&media.CreatedAt,
|
||||
); err != nil {
|
||||
log.Printf("❌ [GetMediaByProductID] Erreur scan: %v", err)
|
||||
return nil, fmt.Errorf("erreur scan média: %w", err)
|
||||
}
|
||||
|
||||
log.Printf(" 🖼️ Media: ID=%d, Type=%s", media.ID, media.Type)
|
||||
mediaList = append(mediaList, media)
|
||||
}
|
||||
|
||||
if err = rows.Err(); err != nil {
|
||||
log.Printf("❌ [GetMediaByProductID] Erreur iteration: %v", err)
|
||||
return nil, fmt.Errorf("erreur itération médias: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("✅ [GetMediaByProductID] %d médias trouvés", len(mediaList))
|
||||
|
||||
return mediaList, nil
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// UPDATE MEDIA - VERSION SÉCURISÉE
|
||||
// ============================================
|
||||
|
||||
func (db *Database) UpdateMedia(media *models.Media) error {
|
||||
func (d *Database) UpdateMedia(media *models.Media) error {
|
||||
if media == nil {
|
||||
return fmt.Errorf("média nil")
|
||||
}
|
||||
|
||||
if err := validateMediaID(media.ID); err != nil {
|
||||
log.Printf("❌ [UpdateMedia] %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := validateMediaType(media.Type); err != nil {
|
||||
log.Printf("❌ [UpdateMedia] %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := validateMediaURL(media.URL); err != nil {
|
||||
log.Printf("❌ [UpdateMedia] %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// ✅ VÉRIFIER QUE LE MÉDIA EXISTE
|
||||
if err := db.CheckMediaExists(media); err != nil {
|
||||
if err := d.CheckMediaExists(media); err != nil {
|
||||
log.Printf("❌ [UpdateMedia] %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// ✅ UPDATE
|
||||
query := `UPDATE media
|
||||
SET url = $1, type = $2
|
||||
WHERE id = $3`
|
||||
|
||||
result, err := db.Exec(query, media.URL, media.Type, media.ID)
|
||||
if err != nil {
|
||||
log.Printf("❌ [UpdateMedia] Erreur UPDATE: %v", err)
|
||||
return fmt.Errorf("erreur mise à jour média: %w", err)
|
||||
result := d.GDB.Exec(`UPDATE media SET url = ?, type = ? WHERE id = ?`, media.URL, media.Type, media.ID)
|
||||
if result.Error != nil {
|
||||
log.Printf("❌ [UpdateMedia] Erreur UPDATE: %v", result.Error)
|
||||
return fmt.Errorf("erreur mise à jour média: %w", result.Error)
|
||||
}
|
||||
|
||||
rowsAffected, _ := result.RowsAffected()
|
||||
if rowsAffected == 0 {
|
||||
if result.RowsAffected == 0 {
|
||||
log.Printf("❌ [UpdateMedia] Aucune ligne affectée")
|
||||
return fmt.Errorf("média non trouvé")
|
||||
}
|
||||
|
||||
log.Printf("✅ [UpdateMedia] Média %d mis à jour", media.ID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *Database) CheckMediaExists(media *models.Media) error {
|
||||
func (d *Database) CheckMediaExists(media *models.Media) error {
|
||||
var exists bool
|
||||
checkQuery := `SELECT EXISTS(SELECT 1 FROM media WHERE id = $1)`
|
||||
err := db.QueryRow(checkQuery, media.ID).Scan(&exists)
|
||||
if err != nil {
|
||||
if err := d.GDB.Raw(`SELECT EXISTS(SELECT 1 FROM media WHERE id = ?)`, media.ID).Scan(&exists).Error; err != nil {
|
||||
log.Printf("❌ [UpdateMedia] Erreur vérification: %v", err)
|
||||
return fmt.Errorf("erreur vérification média: %w", err)
|
||||
}
|
||||
@@ -329,38 +239,33 @@ func (db *Database) CheckMediaExists(media *models.Media) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *Database) DeleteMedia(mediaID int) error {
|
||||
func (d *Database) DeleteMedia(mediaID int) error {
|
||||
if err := validateMediaID(mediaID); err != nil {
|
||||
log.Printf("❌ [DeleteMedia] %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
media := models.Media{ID: mediaID}
|
||||
if err := db.CheckMediaExists(&media); err != nil {
|
||||
if err := d.CheckMediaExists(&media); err != nil {
|
||||
log.Printf("❌ [DeleteMedia] %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
query := `DELETE FROM media WHERE id = $1`
|
||||
|
||||
result, err := db.Exec(query, mediaID)
|
||||
if err != nil {
|
||||
log.Printf("❌ [DeleteMedia] Erreur DELETE: %v", err)
|
||||
return fmt.Errorf("erreur suppression média: %w", err)
|
||||
result := d.GDB.Exec(`DELETE FROM media WHERE id = ?`, mediaID)
|
||||
if result.Error != nil {
|
||||
log.Printf("❌ [DeleteMedia] Erreur DELETE: %v", result.Error)
|
||||
return fmt.Errorf("erreur suppression média: %w", result.Error)
|
||||
}
|
||||
|
||||
rowsAffected, _ := result.RowsAffected()
|
||||
if rowsAffected == 0 {
|
||||
if result.RowsAffected == 0 {
|
||||
log.Printf("❌ [DeleteMedia] Aucune ligne affectée")
|
||||
return fmt.Errorf("média non trouvé")
|
||||
}
|
||||
|
||||
log.Printf("✅ [DeleteMedia] Média %d supprimé", mediaID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *Database) DeleteMediaByProductID(productID int) error {
|
||||
func (d *Database) DeleteMediaByProductID(productID int) error {
|
||||
log.Printf("🗑️ [DeleteMediaByProductID] START - ProductID=%d", productID)
|
||||
|
||||
if err := validateProductID(productID); err != nil {
|
||||
@@ -369,9 +274,7 @@ func (db *Database) DeleteMediaByProductID(productID int) error {
|
||||
}
|
||||
|
||||
var exists bool
|
||||
checkQuery := `SELECT EXISTS(SELECT 1 FROM products WHERE id = $1)`
|
||||
err := db.QueryRow(checkQuery, productID).Scan(&exists)
|
||||
if err != nil {
|
||||
if err := d.GDB.Raw(`SELECT EXISTS(SELECT 1 FROM products WHERE id = ?)`, productID).Scan(&exists).Error; err != nil {
|
||||
log.Printf("❌ [DeleteMediaByProductID] Erreur vérification: %v", err)
|
||||
return fmt.Errorf("erreur vérification produit: %w", err)
|
||||
}
|
||||
@@ -380,17 +283,13 @@ func (db *Database) DeleteMediaByProductID(productID int) error {
|
||||
return fmt.Errorf("produit %d non trouvé", productID)
|
||||
}
|
||||
|
||||
query := `DELETE FROM media WHERE product_id = $1`
|
||||
|
||||
result, err := db.Exec(query, productID)
|
||||
if err != nil {
|
||||
log.Printf("❌ [DeleteMediaByProductID] Erreur DELETE: %v", err)
|
||||
return fmt.Errorf("erreur suppression médias: %w", err)
|
||||
result := d.GDB.Exec(`DELETE FROM media WHERE product_id = ?`, productID)
|
||||
if result.Error != nil {
|
||||
log.Printf("❌ [DeleteMediaByProductID] Erreur DELETE: %v", result.Error)
|
||||
return fmt.Errorf("erreur suppression médias: %w", result.Error)
|
||||
}
|
||||
|
||||
rowsAffected, _ := result.RowsAffected()
|
||||
log.Printf("✅ [DeleteMediaByProductID] %d média(s) supprimé(s) pour produit %d",
|
||||
rowsAffected, productID)
|
||||
|
||||
result.RowsAffected, productID)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user