A community based topic aggregation platform built on atproto
1package users 2 3import ( 4 "fmt" 5 "strings" 6) 7 8type UserService struct { 9 userRepo UserRepository 10} 11 12func NewUserService(userRepo UserRepository) *UserService { 13 return &UserService{ 14 userRepo: userRepo, 15 } 16} 17 18func (s *UserService) CreateUser(req CreateUserRequest) (*User, error) { 19 if err := s.validateCreateRequest(req); err != nil { 20 return nil, err 21 } 22 23 req.Email = strings.TrimSpace(strings.ToLower(req.Email)) 24 req.Username = strings.TrimSpace(req.Username) 25 26 existingUser, _ := s.userRepo.GetByEmail(req.Email) 27 if existingUser != nil { 28 return nil, fmt.Errorf("service: email already exists") 29 } 30 31 existingUser, _ = s.userRepo.GetByUsername(req.Username) 32 if existingUser != nil { 33 return nil, fmt.Errorf("service: username already exists") 34 } 35 36 user := &User{ 37 Email: req.Email, 38 Username: req.Username, 39 } 40 41 return s.userRepo.Create(user) 42} 43 44func (s *UserService) GetUserByID(id int) (*User, error) { 45 if id <= 0 { 46 return nil, fmt.Errorf("service: invalid user ID") 47 } 48 49 user, err := s.userRepo.GetByID(id) 50 if err != nil { 51 if strings.Contains(err.Error(), "not found") { 52 return nil, fmt.Errorf("service: user not found") 53 } 54 return nil, fmt.Errorf("service: %w", err) 55 } 56 57 return user, nil 58} 59 60func (s *UserService) GetUserByEmail(email string) (*User, error) { 61 email = strings.TrimSpace(strings.ToLower(email)) 62 if email == "" { 63 return nil, fmt.Errorf("service: email is required") 64 } 65 66 user, err := s.userRepo.GetByEmail(email) 67 if err != nil { 68 if strings.Contains(err.Error(), "not found") { 69 return nil, fmt.Errorf("service: user not found") 70 } 71 return nil, fmt.Errorf("service: %w", err) 72 } 73 74 return user, nil 75} 76 77func (s *UserService) GetUserByUsername(username string) (*User, error) { 78 username = strings.TrimSpace(username) 79 if username == "" { 80 return nil, fmt.Errorf("service: username is required") 81 } 82 83 user, err := s.userRepo.GetByUsername(username) 84 if err != nil { 85 if strings.Contains(err.Error(), "not found") { 86 return nil, fmt.Errorf("service: user not found") 87 } 88 return nil, fmt.Errorf("service: %w", err) 89 } 90 91 return user, nil 92} 93 94func (s *UserService) UpdateUser(id int, req UpdateUserRequest) (*User, error) { 95 user, err := s.GetUserByID(id) 96 if err != nil { 97 return nil, err 98 } 99 100 if req.Email != "" { 101 req.Email = strings.TrimSpace(strings.ToLower(req.Email)) 102 if req.Email != user.Email { 103 existingUser, _ := s.userRepo.GetByEmail(req.Email) 104 if existingUser != nil && existingUser.ID != id { 105 return nil, fmt.Errorf("service: email already exists") 106 } 107 } 108 user.Email = req.Email 109 } 110 111 if req.Username != "" { 112 req.Username = strings.TrimSpace(req.Username) 113 if req.Username != user.Username { 114 existingUser, _ := s.userRepo.GetByUsername(req.Username) 115 if existingUser != nil && existingUser.ID != id { 116 return nil, fmt.Errorf("service: username already exists") 117 } 118 } 119 user.Username = req.Username 120 } 121 122 return s.userRepo.Update(user) 123} 124 125func (s *UserService) DeleteUser(id int) error { 126 if id <= 0 { 127 return fmt.Errorf("service: invalid user ID") 128 } 129 130 err := s.userRepo.Delete(id) 131 if err != nil { 132 if strings.Contains(err.Error(), "not found") { 133 return fmt.Errorf("service: user not found") 134 } 135 return fmt.Errorf("service: %w", err) 136 } 137 138 return nil 139} 140 141func (s *UserService) validateCreateRequest(req CreateUserRequest) error { 142 if strings.TrimSpace(req.Email) == "" { 143 return fmt.Errorf("service: email is required") 144 } 145 146 if strings.TrimSpace(req.Username) == "" { 147 return fmt.Errorf("service: username is required") 148 } 149 150 if !strings.Contains(req.Email, "@") { 151 return fmt.Errorf("service: invalid email format") 152 } 153 154 if len(req.Username) < 3 { 155 return fmt.Errorf("service: username must be at least 3 characters") 156 } 157 158 return nil 159} 160 161type UpdateUserRequest struct { 162 Email string `json:"email,omitempty"` 163 Username string `json:"username,omitempty"` 164}