2025-12-03 19:29:37 +00:00
|
|
|
package repository
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
|
|
"veza-backend-api/internal/models"
|
2026-03-05 22:03:43 +00:00
|
|
|
|
|
|
|
|
"github.com/google/uuid"
|
2025-12-03 19:29:37 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// UserRepositoryImpl implémentation en mémoire du repository des utilisateurs
|
|
|
|
|
type UserRepositoryImpl struct {
|
|
|
|
|
users map[string]*models.User
|
|
|
|
|
emails map[string]string
|
|
|
|
|
usernames map[string]string // username -> userID mapping
|
|
|
|
|
mutex sync.RWMutex
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewUserRepository crée une nouvelle instance du repository
|
|
|
|
|
func NewUserRepository() *UserRepositoryImpl {
|
|
|
|
|
return &UserRepositoryImpl{
|
|
|
|
|
users: make(map[string]*models.User),
|
|
|
|
|
emails: make(map[string]string),
|
|
|
|
|
usernames: make(map[string]string),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetByID récupère un utilisateur par son ID
|
|
|
|
|
func (r *UserRepositoryImpl) GetByID(id string) (*models.User, error) {
|
|
|
|
|
r.mutex.RLock()
|
|
|
|
|
defer r.mutex.RUnlock()
|
|
|
|
|
|
|
|
|
|
user, exists := r.users[id]
|
|
|
|
|
if !exists {
|
|
|
|
|
return nil, errors.New("user not found")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Retourner une copie pour éviter les modifications accidentelles
|
|
|
|
|
userCopy := *user
|
|
|
|
|
return &userCopy, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetByEmail récupère un utilisateur par son email
|
|
|
|
|
func (r *UserRepositoryImpl) GetByEmail(email string) (*models.User, error) {
|
|
|
|
|
r.mutex.RLock()
|
|
|
|
|
defer r.mutex.RUnlock()
|
|
|
|
|
|
|
|
|
|
userID, exists := r.emails[email]
|
|
|
|
|
if !exists {
|
|
|
|
|
return nil, errors.New("user not found")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
user, exists := r.users[userID]
|
|
|
|
|
if !exists {
|
|
|
|
|
return nil, errors.New("user not found")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Retourner une copie pour éviter les modifications accidentelles
|
|
|
|
|
userCopy := *user
|
|
|
|
|
return &userCopy, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetByUsername récupère un utilisateur par son username
|
|
|
|
|
func (r *UserRepositoryImpl) GetByUsername(username string) (*models.User, error) {
|
|
|
|
|
r.mutex.RLock()
|
|
|
|
|
defer r.mutex.RUnlock()
|
|
|
|
|
|
|
|
|
|
userID, exists := r.usernames[username]
|
|
|
|
|
if !exists {
|
|
|
|
|
return nil, errors.New("user not found")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
user, exists := r.users[userID]
|
|
|
|
|
if !exists {
|
|
|
|
|
return nil, errors.New("user not found")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Retourner une copie pour éviter les modifications accidentelles
|
|
|
|
|
userCopy := *user
|
|
|
|
|
return &userCopy, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create crée un nouvel utilisateur
|
|
|
|
|
func (r *UserRepositoryImpl) Create(user *models.User) error {
|
|
|
|
|
r.mutex.Lock()
|
|
|
|
|
defer r.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
// Vérifier si l'email existe déjà
|
|
|
|
|
if _, exists := r.emails[user.Email]; exists {
|
|
|
|
|
return errors.New("email already exists")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Assigner un ID si vide
|
|
|
|
|
if user.ID == uuid.Nil {
|
|
|
|
|
user.ID = uuid.New()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Créer une copie pour éviter les modifications accidentelles
|
|
|
|
|
userCopy := *user
|
|
|
|
|
// Forcer les valeurs par défaut
|
|
|
|
|
userCopy.Role = "user"
|
|
|
|
|
userCopy.FirstName = user.FirstName
|
|
|
|
|
userCopy.LastName = user.LastName
|
|
|
|
|
userCopy.Avatar = user.Avatar
|
|
|
|
|
userCopy.Bio = user.Bio
|
|
|
|
|
userCopy.IsActive = true
|
|
|
|
|
userCopy.IsVerified = false
|
|
|
|
|
userCopy.IsAdmin = false
|
|
|
|
|
userIDStr := user.ID.String()
|
|
|
|
|
r.users[userIDStr] = &userCopy
|
|
|
|
|
r.emails[user.Email] = userIDStr
|
|
|
|
|
r.usernames[user.Username] = userIDStr
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update met à jour un utilisateur existant
|
|
|
|
|
func (r *UserRepositoryImpl) Update(user *models.User) error {
|
|
|
|
|
r.mutex.Lock()
|
|
|
|
|
defer r.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
userIDStr := user.ID.String()
|
|
|
|
|
// Vérifier si l'utilisateur existe
|
|
|
|
|
existingUser, exists := r.users[userIDStr]
|
|
|
|
|
if !exists {
|
|
|
|
|
return errors.New("user not found")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Si l'email a changé, vérifier qu'il n'existe pas déjà
|
|
|
|
|
if existingUser.Email != user.Email {
|
|
|
|
|
if _, emailExists := r.emails[user.Email]; emailExists {
|
|
|
|
|
return errors.New("email already exists")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Mettre à jour les mappings
|
|
|
|
|
delete(r.emails, existingUser.Email)
|
|
|
|
|
r.emails[user.Email] = userIDStr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Si le username a changé, mettre à jour le mapping
|
|
|
|
|
if existingUser.Username != user.Username {
|
|
|
|
|
// Vérifier que le nouveau username n'est pas déjà pris (par un autre utilisateur)
|
|
|
|
|
if existingUserID, usernameExists := r.usernames[user.Username]; usernameExists && existingUserID != userIDStr {
|
|
|
|
|
return errors.New("username already exists")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Mettre à jour les mappings
|
|
|
|
|
delete(r.usernames, existingUser.Username)
|
|
|
|
|
r.usernames[user.Username] = userIDStr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Créer une copie pour éviter les modifications accidentelles
|
|
|
|
|
userCopy := *user
|
|
|
|
|
r.users[userIDStr] = &userCopy
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delete supprime un utilisateur
|
|
|
|
|
func (r *UserRepositoryImpl) Delete(id string) error {
|
|
|
|
|
r.mutex.Lock()
|
|
|
|
|
defer r.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
user, exists := r.users[id]
|
|
|
|
|
if !exists {
|
|
|
|
|
return errors.New("user not found")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Supprimer les mappings
|
|
|
|
|
delete(r.users, id)
|
|
|
|
|
delete(r.emails, user.Email)
|
|
|
|
|
delete(r.usernames, user.Username)
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|