package db import ( "fmt" "log" "time" "gorm.io/gorm" ) type jwtToken struct { ID int `gorm:"primaryKey;autoIncrement"` UserID int `gorm:"column:user_id;index"` UserType string `gorm:"column:user_type"` Token string `gorm:"column:token;uniqueIndex"` DateSave time.Time `gorm:"column:date_save;autoCreateTime"` DateFin time.Time `gorm:"column:date_fin"` } func (jwtToken) TableName() string { return "jwt_tokens" } var validTokenTypes = map[string]bool{ "client": true, "admin": true, "cabine": true, "livreur": true, } func (d *Database) SaveToken(userID int, userType string, token string, expiresAt time.Time) error { if !validTokenTypes[userType] { return fmt.Errorf("type d'utilisateur invalide: %s", userType) } t := jwtToken{UserID: userID, UserType: userType, Token: token, DateFin: expiresAt} if err := d.GDB.Create(&t).Error; err != nil { return fmt.Errorf("erreur lors de l'enregistrement du token: %w", err) } log.Printf("✅ Token enregistré pour %s ID: %d", userType, userID) return nil } func (d *Database) IsTokenValid(token string) (bool, error) { var count int64 err := d.GDB.Model(&jwtToken{}). Where("token = ? AND date_fin > ?", token, time.Now()). Count(&count).Error return count > 0, err } func (d *Database) RevokeToken(token string) error { result := d.GDB.Where("token = ?", token).Delete(&jwtToken{}) if result.Error != nil { return fmt.Errorf("erreur lors de la révocation du token: %w", result.Error) } if result.RowsAffected > 0 { log.Printf("✅ Token révoqué avec succès") } return nil } func (d *Database) RevokeAllUserTokens(userID int, userType string) error { result := d.GDB.Where("user_id = ? AND user_type = ?", userID, userType).Delete(&jwtToken{}) if result.Error != nil { return fmt.Errorf("erreur lors de la révocation des tokens: %w", result.Error) } log.Printf("✅ %d token(s) révoqué(s) pour %s ID: %d", result.RowsAffected, userType, userID) return nil } func (d *Database) GetUserActiveTokens(userID int, userType string) ([]map[string]any, error) { var tokens []jwtToken err := d.GDB.Where("user_id = ? AND user_type = ? AND date_fin > ?", userID, userType, time.Now()). Order("date_save DESC").Find(&tokens).Error if err != nil { return nil, fmt.Errorf("erreur lors de la récupération des tokens: %w", err) } result := make([]map[string]any, len(tokens)) for i, t := range tokens { truncated := t.Token if len(truncated) > 20 { truncated = truncated[:20] + "..." } result[i] = map[string]any{ "id": t.ID, "token": truncated, "date_save": t.DateSave, "date_fin": t.DateFin, "user_type": t.UserType, } } return result, nil } func (d *Database) GetTokenInfo(token string) (map[string]any, error) { var t jwtToken err := d.GDB.Where("token = ? AND date_fin > ?", token, time.Now()).First(&t).Error if err != nil { if err == gorm.ErrRecordNotFound { return nil, fmt.Errorf("token non trouvé ou expiré") } return nil, fmt.Errorf("erreur lors de la récupération des infos du token: %w", err) } return map[string]any{ "user_id": t.UserID, "user_type": t.UserType, "date_save": t.DateSave, "date_fin": t.DateFin, }, nil } func (d *Database) CountActiveTokensByType() (map[string]int, error) { type row struct { UserType string Count int } var rows []row err := d.GDB.Model(&jwtToken{}). Select("user_type, COUNT(*) as count"). Where("date_fin > ?", time.Now()). Group("user_type"). Scan(&rows).Error if err != nil { return nil, fmt.Errorf("erreur lors du comptage des tokens: %w", err) } counts := make(map[string]int, len(rows)) for _, r := range rows { counts[r.UserType] = r.Count } return counts, nil }