X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/e743cd3f606fb8a2e432813f7c84fed1093f68c4..refs/pull/3210/head:/app/Auth/Access/RegistrationService.php diff --git a/app/Auth/Access/RegistrationService.php b/app/Auth/Access/RegistrationService.php index 74142301a..dcdb68bd5 100644 --- a/app/Auth/Access/RegistrationService.php +++ b/app/Auth/Access/RegistrationService.php @@ -1,13 +1,20 @@ -registrationAllowed()) { + throw new UserRegistrationException(trans('auth.registrations_disabled'), '/login'); + } + } + + /** + * Check if standard BookStack User registrations are currently allowed. + * Does not prevent external-auth based registration. + */ + protected function registrationAllowed(): bool { $authMethod = config('auth.method'); $authMethodsWithRegistration = ['standard']; - if (!setting('registration-enabled') || !in_array($authMethod, $authMethodsWithRegistration)) { - throw new UserRegistrationException(trans('auth.registrations_disabled'), '/login'); + + return in_array($authMethod, $authMethodsWithRegistration) && setting('registration-enabled'); + } + + /** + * Attempt to find a user in the system otherwise register them as a new + * user. For use with external auth systems since password is auto-generated. + * + * @throws UserRegistrationException + */ + public function findOrRegister(string $name, string $email, string $externalId): User + { + $user = User::query() + ->where('external_auth_id', '=', $externalId) + ->first(); + + if (is_null($user)) { + $userData = [ + 'name' => $name, + 'email' => $email, + 'password' => Str::random(32), + 'external_auth_id' => $externalId, + ]; + + $user = $this->registerUser($userData, null, false); } + + return $user; } /** * The registrations flow for all users. + * * @throws UserRegistrationException */ - public function registerUser(array $userData, ?SocialAccount $socialAccount = null, bool $emailVerified = false) + public function registerUser(array $userData, ?SocialAccount $socialAccount = null, bool $emailConfirmed = false): User { - $registrationRestrict = setting('registration-restrict'); + $userEmail = $userData['email']; - if ($registrationRestrict) { - $restrictedEmailDomains = explode(',', str_replace(' ', '', $registrationRestrict)); - $userEmailDomain = $domain = mb_substr(mb_strrchr($userData['email'], "@"), 1); - if (!in_array($userEmailDomain, $restrictedEmailDomains)) { - throw new UserRegistrationException(trans('auth.registration_email_domain_invalid'), '/register'); - } + // Email restriction + $this->ensureEmailDomainAllowed($userEmail); + + // Ensure user does not already exist + $alreadyUser = !is_null($this->userRepo->getByEmail($userEmail)); + if ($alreadyUser) { + throw new UserRegistrationException(trans('errors.error_user_exists_different_creds', ['email' => $userEmail]), '/login'); } - $newUser = $this->userRepo->registerNew($userData, $emailVerified); + // Create the user + $newUser = $this->userRepo->registerNew($userData, $emailConfirmed); + // Assign social account if given if ($socialAccount) { $newUser->socialAccounts()->save($socialAccount); } - if ($this->emailConfirmationService->confirmationRequired() && !$emailVerified) { + Activity::add(ActivityType::AUTH_REGISTER, $socialAccount ?? $newUser); + Theme::dispatch(ThemeEvents::AUTH_REGISTER, $socialAccount ? $socialAccount->driver : auth()->getDefaultDriver(), $newUser); + + // Start email confirmation flow if required + if ($this->emailConfirmationService->confirmationRequired() && !$emailConfirmed) { $newUser->save(); - $message = ''; try { $this->emailConfirmationService->sendConfirmation($newUser); + session()->flash('sent-email-confirmation', true); } catch (Exception $e) { $message = trans('auth.email_confirm_send_error'); - } - throw new UserRegistrationException($message, '/register/confirm'); + throw new UserRegistrationException($message, '/register/confirm'); + } } - auth()->login($newUser); + return $newUser; } -} \ No newline at end of file + /** + * Ensure that the given email meets any active email domain registration restrictions. + * Throws if restrictions are active and the email does not match an allowed domain. + * + * @throws UserRegistrationException + */ + protected function ensureEmailDomainAllowed(string $userEmail): void + { + $registrationRestrict = setting('registration-restrict'); + + if (!$registrationRestrict) { + return; + } + + $restrictedEmailDomains = explode(',', str_replace(' ', '', $registrationRestrict)); + $userEmailDomain = $domain = mb_substr(mb_strrchr($userEmail, '@'), 1); + if (!in_array($userEmailDomain, $restrictedEmailDomains)) { + $redirect = $this->registrationAllowed() ? '/register' : '/login'; + + throw new UserRegistrationException(trans('auth.registration_email_domain_invalid'), $redirect); + } + } +}