package memory import ( "context" "sync" "git.threesix.ai/jordan/slack-auth-1770277926/services/auth-api/internal/domain" "git.threesix.ai/jordan/slack-auth-1770277926/services/auth-api/internal/port" ) // Compile-time verification that UserRepository implements port.UserRepository. var _ port.UserRepository = (*UserRepository)(nil) // UserRepository is a thread-safe in-memory implementation of port.UserRepository. type UserRepository struct { mu sync.RWMutex users map[domain.UserID]*domain.User } // NewUserRepository creates a new in-memory user repository. func NewUserRepository() *UserRepository { return &UserRepository{ users: make(map[domain.UserID]*domain.User), } } // Get returns a user by ID. // Returns domain.ErrUserNotFound if not found. func (r *UserRepository) Get(ctx context.Context, id domain.UserID) (*domain.User, error) { r.mu.RLock() defer r.mu.RUnlock() u, ok := r.users[id] if !ok { return nil, domain.ErrUserNotFound } // Return a copy to prevent external mutation cpy := *u return &cpy, nil } // GetByEmail returns a user by email address. // Returns domain.ErrUserNotFound if not found. func (r *UserRepository) GetByEmail(ctx context.Context, email string) (*domain.User, error) { r.mu.RLock() defer r.mu.RUnlock() for _, u := range r.users { if u.Email == email { // Return a copy to prevent external mutation cpy := *u return &cpy, nil } } return nil, domain.ErrUserNotFound } // Create stores a new user. func (r *UserRepository) Create(ctx context.Context, user *domain.User) error { r.mu.Lock() defer r.mu.Unlock() // Store a copy to prevent external mutation cpy := *user r.users[user.ID] = &cpy return nil } // ExistsByEmail checks if a user with the given email exists. func (r *UserRepository) ExistsByEmail(ctx context.Context, email string) (bool, error) { r.mu.RLock() defer r.mu.RUnlock() for _, u := range r.users { if u.Email == email { return true, nil } } return false, nil }