package repository import ( "context" "errors" "sync" "veza-backend-api/internal/models" "github.com/google/uuid" ) // 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(_ context.Context, 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(_ context.Context, 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(_ context.Context, 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(_ context.Context, 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(_ context.Context, 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(_ context.Context, 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 }