email === null || $request->email === '') { throw new BadRequestException('email is required'); } if ($request->displayName === null || $request->displayName === '') { throw new BadRequestException('displayName is required'); } if ( preg_match( self::DISPLAY_NAME_PATTERN, $request->displayName, ) !== 1 ) { throw new BadRequestException( 'displayName must be 3-30 chars of [a-z0-9_-]' ); } try { $email = new EmailAddress($request->email); } catch (InvalidArgumentException $exception) { throw new BadRequestException($exception->getMessage()); } if ($this->userRepo->findByEmail($email) !== null) { throw new DomainException('email already registered'); } if ($this->userRepo->findByDisplayName($request->displayName) !== null) { throw new DomainException('displayName already taken'); } $user = $this->userRepo->create(new CreateUserDto( email: $email, displayName: $request->displayName, passwordHash: '', isAdmin: false, emailConfirmedAt: null, )); $token = $this->tokenRepo->create(new CreateEmailConfirmationTokenDto( user: $user, availableTo: $this->clock->now()->modify(self::TOKEN_LIFETIME), )); $this->emailer->send( $this->fromAddress, $user->getEmail()->value(), $this->emailFactory->makeConfirmationEmail($token->getToken()), ); return $user; } }