slack-auth-1770277926/services/auth-api/internal/adapter/memory/user.go
rdev-worker fd9bf961bb
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
build: /implement-feature auth-system --requirements 'User model with email/...
2026-02-05 07:59:55 +00:00

81 lines
2.0 KiB
Go

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
}