chore: fix updates
This commit is contained in:
@@ -327,17 +327,63 @@ func LoginClient(c *gin.Context) {
|
||||
TokenType: "Bearer",
|
||||
ExpiresIn: int(clientTokenDuration.Seconds()),
|
||||
User: gin.H{
|
||||
"id": client.ID,
|
||||
"username": client.Username,
|
||||
"nom": client.Nom,
|
||||
"prenom": client.Prenom,
|
||||
"telephone": client.Telephone,
|
||||
"role": "client",
|
||||
"session_id": sessionID,
|
||||
"id": client.ID,
|
||||
"username": client.Username,
|
||||
"nom": client.Nom,
|
||||
"prenom": client.Prenom,
|
||||
"telephone": client.Telephone,
|
||||
"role": "client",
|
||||
"session_id": sessionID,
|
||||
"must_change_password": client.MustChangePassword,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// ChangePassword permet à un client de changer son mot de passe
|
||||
// PUT /api/v1/auth/change-password
|
||||
func ChangePassword(c *gin.Context) {
|
||||
var req struct {
|
||||
CurrentPassword string `json:"current_password" binding:"required"`
|
||||
NewPassword string `json:"new_password" binding:"required,min=8"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Données invalides", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
clientID := c.GetInt("client_id")
|
||||
database := c.MustGet("database").(*db.Database)
|
||||
|
||||
client, err := database.GetClientByID(clientID)
|
||||
if err != nil {
|
||||
log.Printf("❌ [CHANGE_PASSWORD] Client non trouvé: ID=%d", clientID)
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Client non trouvé"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(client.Password), []byte(req.CurrentPassword)); err != nil {
|
||||
log.Printf("❌ [CHANGE_PASSWORD] Mot de passe actuel invalide: ID=%d", clientID)
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Mot de passe actuel incorrect"})
|
||||
return
|
||||
}
|
||||
|
||||
hashed, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
log.Printf("❌ [CHANGE_PASSWORD] Erreur bcrypt: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur traitement mot de passe"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := database.UpdateClientPasswordAndClearFlag(clientID, string(hashed)); err != nil {
|
||||
log.Printf("❌ [CHANGE_PASSWORD] Erreur update: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur mise à jour mot de passe"})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("✅ [CHANGE_PASSWORD] Mot de passe changé: ID=%d", clientID)
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": "Mot de passe mis à jour avec succès"})
|
||||
}
|
||||
|
||||
// LogoutClient déconnecte un client
|
||||
// POST /api/v1/auth/logout
|
||||
func LogoutClient(c *gin.Context) {
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"gestion/db"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GetClientNotifications retourne les notifications du client connecté
|
||||
// GET /api/v1/notifications
|
||||
func GetClientNotifications(c *gin.Context) {
|
||||
username := c.GetString("username")
|
||||
if username == "" {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
||||
return
|
||||
}
|
||||
|
||||
notifKey := "notifications:" + username
|
||||
|
||||
// Récupérer toutes les notifications (max 50)
|
||||
results, err := db.Redis.LRange(db.RedisCtx, notifKey, 0, 49).Result()
|
||||
if err != nil {
|
||||
log.Printf("❌ [GET_NOTIFICATIONS] Erreur Redis: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur récupération notifications"})
|
||||
return
|
||||
}
|
||||
|
||||
type Notification struct {
|
||||
CommandID int `json:"command_id"`
|
||||
Type string `json:"type"`
|
||||
Message string `json:"message"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
Read bool `json:"read"`
|
||||
}
|
||||
|
||||
notifications := make([]Notification, 0, len(results))
|
||||
unreadCount := 0
|
||||
|
||||
for _, raw := range results {
|
||||
var n Notification
|
||||
if err := json.Unmarshal([]byte(raw), &n); err != nil {
|
||||
continue
|
||||
}
|
||||
notifications = append(notifications, n)
|
||||
if !n.Read {
|
||||
unreadCount++
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("✅ [GET_NOTIFICATIONS] %d notifications pour %s (%d non lues)", len(notifications), username, unreadCount)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"notifications": notifications,
|
||||
"unread_count": unreadCount,
|
||||
"total": len(notifications),
|
||||
})
|
||||
}
|
||||
|
||||
// MarkNotificationsRead marque toutes les notifications comme lues
|
||||
// POST /api/v1/notifications/read
|
||||
func MarkNotificationsRead(c *gin.Context) {
|
||||
username := c.GetString("username")
|
||||
if username == "" {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Non authentifié"})
|
||||
return
|
||||
}
|
||||
|
||||
notifKey := "notifications:" + username
|
||||
|
||||
// Récupérer toutes les notifications
|
||||
results, err := db.Redis.LRange(db.RedisCtx, notifKey, 0, -1).Result()
|
||||
if err != nil {
|
||||
log.Printf("❌ [MARK_NOTIFICATIONS_READ] Erreur Redis LRange: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur lecture notifications"})
|
||||
return
|
||||
}
|
||||
|
||||
// Réécrire chaque notification avec read=true
|
||||
markedCount := 0
|
||||
for i, raw := range results {
|
||||
var n map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(raw), &n); err != nil {
|
||||
continue
|
||||
}
|
||||
if read, ok := n["read"].(bool); ok && read {
|
||||
continue
|
||||
}
|
||||
n["read"] = true
|
||||
updated, _ := json.Marshal(n)
|
||||
db.Redis.LSet(db.RedisCtx, notifKey, int64(i), string(updated))
|
||||
markedCount++
|
||||
}
|
||||
|
||||
log.Printf("✅ [MARK_NOTIFICATIONS_READ] %d notifications marquées lues pour %s", markedCount, username)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"marked_count": markedCount,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user