user_repository = $user_repository; $this->group_repository = $group_repository; $this->name_generator_service = $name_generator_service; $this->request_reset_password_repository = $request_reset_password_repository; $this->user_registration_request_repository = $user_registration_request_repository; $this->spam_estimator_feed_repository = $spam_estimator_feed_repository; $this->client_repository = $client_repository; } /** * @param array $payload * @throws ValidationException * @return User */ public function registerUser(array $payload): User { return $this->tx_service->transaction(function() use($payload){ $email = trim($payload['email']); $former_user = $this->user_repository->getByEmailOrName($email); if(!is_null($former_user)) throw new ValidationException(sprintf("email %s belongs to another user !!!", $email)); $default_groups = $this->group_repository->getDefaultOnes(); if(count($default_groups) > 0){ $payload['groups'] = $default_groups; } $user = UserFactory::build($payload); $this->user_repository->add($user); $formerRequest = $this->user_registration_request_repository->getByEmail($email); if(!is_null($formerRequest)){ if(!$formerRequest->isRedeem()){ $formerRequest->redeem(); } } return $user; }); } /** * @param string $token * @throws ValidationException * @throws EntityNotFoundException * @return User */ public function verifyEmail(string $token): User { return $this->tx_service->transaction(function() use($token){ $user = $this->user_repository->getByVerificationEmailToken($token); if(is_null($user)) throw new EntityNotFoundException(); $user->verifyEmail(); return $user; }); } /** * @param array $payload * @throws ValidationException * @throws EntityNotFoundException * @return User */ public function resendVerificationEmail(array $payload): User { return $this->tx_service->transaction(function() use($payload){ $email = trim($payload['email']); $user = $this->user_repository->getByEmailOrName($email); if(is_null($user)) throw new EntityNotFoundException(); return $this->sendVerificationEmail($user); }); } /** * @param User $user * @return string */ private function generateVerificationLink(User $user):string{ return $this->tx_service->transaction(function() use($user) { //generate unique token do { $token = $user->generateEmailVerificationToken(); $former_user = $this->user_repository->getByVerificationEmailToken($token); if (is_null($former_user)) break; } while (true); return URL::route("verification_verify", ["token" => $token]); }); } /** * @param User $user * @return string|null * @throws \Exception */ public function sendWelcomeEmail(User $user):?string { return $this->tx_service->transaction(function() use($user){ $verification_link = null; if(!$user->isEmailVerified()) $verification_link = $this->generateVerificationLink($user); Mail::queue(new WelcomeNewUserEmail($user, $verification_link)); return $verification_link; }); } /** * @param User $user * @param string|null $verification_link * @return User * @throws \Exception */ public function sendVerificationEmail(User $user, string $verification_link = null): User { return $this->tx_service->transaction(function() use($user, $verification_link){ if(empty($verification_link)) $verification_link = $this->generateVerificationLink($user); Mail::queue(new UserEmailVerificationRequest($user, $verification_link)); return $user; }); } /** * @param User $user * @return User * @throws \Exception */ public function generateIdentifier(User $user): User { return $this->tx_service->transaction(function() use($user) { $fragment_nbr = 1; $this->name_generator_service->generate($user); $identifier = $original_identifier = $user->getIdentifier(); do { $old_user = $this->user_repository->getByIdentifier($identifier); if(!is_null($old_user)) { $identifier = $original_identifier . IUserNameGeneratorService::USER_NAME_CHAR_CONNECTOR . $fragment_nbr; $fragment_nbr++; continue; } $user->setIdentifier($identifier); break; } while (1); return $user; }); } /** * @param array $payload * @throws ValidationException * @throws EntityNotFoundException * @return UserPasswordResetRequest */ public function requestPasswordReset(array $payload): UserPasswordResetRequest { return $this->tx_service->transaction(function() use($payload) { $user = $this->user_repository->getByEmailOrName(trim($payload['email'])); if(is_null($user) || !$user->isEmailVerified()) throw new EntityNotFoundException("User not found."); $request = new UserPasswordResetRequest(); $request->setOwner($user); do{ $token = $request->generateToken(); $former_request = $this->request_reset_password_repository->getByToken($token); if(is_null($former_request)) break; }while(1); $user->addPasswordResetRequest($request); $reset_link = URL::route("password.reset", ["token" => $token]); Mail::queue(new UserPasswordResetRequestMail($user, $reset_link)); return $request; }); } /** * @param string $token * @param string $new_password * @throws ValidationException * @throws EntityNotFoundException * @return User */ public function resetPassword(string $token, string $new_password): User { return $this->tx_service->transaction(function() use($token, $new_password) { $request = $this->request_reset_password_repository->getByToken($token); if(is_null($request)) throw new EntityNotFoundException("request not found"); if(!$request->isValid()) throw new ValidationException("request is void"); if($request->isRedeem()){ throw new ValidationException("request is already redeem"); } $user = $request->getOwner(); $user->setPassword($new_password); $request->redeem(); Event::dispatch(new UserPasswordResetSuccessful($user->getId())); return $user; }); } /** * @param string $client_id * @param array $payload * @return UserRegistrationRequest * @throws ValidationException * @throws EntityNotFoundException */ public function createRegistrationRequest(string $client_id, array $payload): UserRegistrationRequest { return $this->tx_service->transaction(function() use($client_id, $payload) { $client = $this->client_repository->getClientById($client_id); if(is_null($client)) throw new EntityNotFoundException("client not found!"); $email = $payload['email']; $former_user = $this->user_repository->getByEmailOrName($email); if(!is_null($former_user)) throw new ValidationException(sprintf("There is another user already with email %s.", $email)); $formerRequest = $this->user_registration_request_repository->getByEmail($email); if(!is_null($formerRequest)){ if($formerRequest->isRedeem()){ throw new ValidationException(sprintf("There is already a former registration request for email %s.", $email)); } return $formerRequest; } $request = UserRegistrationRequestFactory::build($payload); $generator = new RandomGenerator(); do{ $hash = md5( $request->getEmail(). $request->getFirstName(). $request->getLastName(). $generator->randomToken()); $former_registration_request = $this->user_registration_request_repository->getByHash($hash); $request->setHash($hash); if(is_null($former_registration_request)) break; } while(1); $request->setClient($client); $this->user_registration_request_repository->add($request); return $request; }); } /** * @param string $token * @param string $new_password * @return UserRegistrationRequest * @throws \Exception */ public function setPassword(string $token, string $new_password): UserRegistrationRequest { return $this->tx_service->transaction(function() use($token, $new_password) { $request = $this->user_registration_request_repository->getByHash($token); if(is_null($request)) { Log::warning(sprintf("UserService::setPassword registration request %s not found.", $token)); throw new EntityNotFoundException("Request not found."); } if($request->isRedeem()){ Log::warning(sprintf("UserService::setPassword registration request %s already redeem.", $token)); throw new ValidationException("Request is already redeem."); } $email = $request->getEmail(); $former_user = $this->user_repository->getByEmailOrName($email); if(!is_null($former_user)) throw new ValidationException(sprintf("User %s already exists!.", $email)); $user = UserFactory::build([ 'first_name' => $request->getFirstName(), 'last_name' => $request->getLastName(), 'email' => $email, 'password' => $new_password, 'active' => true, 'email_verified' => true, ]); $request->setOwner($user); $request->redeem(); $this->user_repository->add($user); Event::dispatch(new UserPasswordResetSuccessful($user->getId())); return $request; }); } /** * @inheritDoc */ public function recalculateUserSpamType(User $user): void { $this->tx_service->transaction(function() use($user) { $this->spam_estimator_feed_repository->deleteByEmail($user->getEmail()); switch($user->getSpamType()){ case User::SpamTypeSpam: $feed = SpamEstimatorFeed::buildFromUser($user, User::SpamTypeSpam); $this->spam_estimator_feed_repository->add($feed); break; case User::SpamTypeHam: $feed = SpamEstimatorFeed::buildFromUser($user, User::SpamTypeHam); $this->spam_estimator_feed_repository->add($feed); break; } }); } }