package useCases import ( "RenewCMS/internal/domain/hash" "RenewCMS/internal/domain/invite" "RenewCMS/internal/domain/user" "errors" "strings" "time" ) type AcceptInviteUseCase struct { userRepository user.Repository inviteRepository invite.Repository hasher hash.Hasher } type AcceptInviteCommand struct { Code string Username string Password string } func NewAcceptInviteUseCase(userRepository user.Repository, inviteRepository invite.Repository, hasher hash.Hasher) *AcceptInviteUseCase { return &AcceptInviteUseCase{userRepository, inviteRepository, hasher} } func (a *AcceptInviteUseCase) AcceptInvite(command AcceptInviteCommand) (user.User, error) { now := time.Now() pending, err := findUsableInvite(a.inviteRepository, a.hasher, command.Code, now) if err != nil { return user.User{}, err } if a.emailHasAccount(pending.Email) { return user.User{}, invite.ErrEmailHasAccount } if err := a.ensureUsernameFree(command.Username); err != nil { return user.User{}, err } hashedPassword, err := a.hasher.Hash(command.Password) if err != nil { return user.User{}, err } createdUser, err := a.userRepository.Create(user.User{ Username: command.Username, Password: hashedPassword, Email: pending.Email, IsVerified: true, }) if err != nil { return user.User{}, err } if err := a.inviteRepository.MarkAccepted(pending.ID, now); err != nil { if deleteErr := a.userRepository.Delete(createdUser.ID); deleteErr != nil { return user.User{}, errors.Join(err, deleteErr) } return user.User{}, err } return createdUser, nil } func (a *AcceptInviteUseCase) emailHasAccount(email string) bool { for _, existingUser := range a.userRepository.GetAll() { if strings.EqualFold(existingUser.Email, email) { return true } } return false } func (a *AcceptInviteUseCase) ensureUsernameFree(username string) error { _, err := a.userRepository.GetByUsername(username) if err == nil { return user.ErrUsernameTaken } if errors.Is(err, user.ErrUserNotFound) { return nil } return err }