veza/veza-backend-api/internal/repository/user_repository.go
senke 01378a06a5 fix(v0.12.6.1): update in-memory UserRepositoryImpl to accept context.Context
Aligns the in-memory implementation with the updated services.UserRepository
interface for consistency (HIGH-003 context propagation).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 05:47:47 +01:00

177 lines
4.5 KiB
Go

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
}