2021-06-26 23:23:15 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace BookStack\Auth\Access;
|
2020-01-26 22:42:50 +08:00
|
|
|
|
2020-11-21 03:33:11 +08:00
|
|
|
use BookStack\Actions\ActivityType;
|
2020-01-26 22:42:50 +08:00
|
|
|
use BookStack\Auth\SocialAccount;
|
2020-02-03 01:31:00 +08:00
|
|
|
use BookStack\Auth\User;
|
2020-01-26 22:42:50 +08:00
|
|
|
use BookStack\Auth\UserRepo;
|
|
|
|
use BookStack\Exceptions\UserRegistrationException;
|
2020-11-21 03:33:11 +08:00
|
|
|
use BookStack\Facades\Activity;
|
2021-03-20 05:54:50 +08:00
|
|
|
use BookStack\Facades\Theme;
|
|
|
|
use BookStack\Theming\ThemeEvents;
|
2020-01-26 22:42:50 +08:00
|
|
|
use Exception;
|
|
|
|
|
|
|
|
class RegistrationService
|
|
|
|
{
|
|
|
|
protected $userRepo;
|
|
|
|
protected $emailConfirmationService;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* RegistrationService constructor.
|
|
|
|
*/
|
|
|
|
public function __construct(UserRepo $userRepo, EmailConfirmationService $emailConfirmationService)
|
|
|
|
{
|
|
|
|
$this->userRepo = $userRepo;
|
|
|
|
$this->emailConfirmationService = $emailConfirmationService;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check whether or not registrations are allowed in the app settings.
|
2021-06-26 23:23:15 +08:00
|
|
|
*
|
2020-01-26 22:42:50 +08:00
|
|
|
* @throws UserRegistrationException
|
|
|
|
*/
|
2020-02-03 01:31:00 +08:00
|
|
|
public function ensureRegistrationAllowed()
|
2020-01-26 22:42:50 +08:00
|
|
|
{
|
2020-02-03 01:31:00 +08:00
|
|
|
if (!$this->registrationAllowed()) {
|
2020-01-26 22:42:50 +08:00
|
|
|
throw new UserRegistrationException(trans('auth.registrations_disabled'), '/login');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-03 01:31:00 +08:00
|
|
|
/**
|
|
|
|
* 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'];
|
2021-06-26 23:23:15 +08:00
|
|
|
|
2020-02-03 01:31:00 +08:00
|
|
|
return in_array($authMethod, $authMethodsWithRegistration) && setting('registration-enabled');
|
|
|
|
}
|
|
|
|
|
2020-01-26 22:42:50 +08:00
|
|
|
/**
|
|
|
|
* The registrations flow for all users.
|
2021-06-26 23:23:15 +08:00
|
|
|
*
|
2020-01-26 22:42:50 +08:00
|
|
|
* @throws UserRegistrationException
|
|
|
|
*/
|
2020-02-03 01:31:00 +08:00
|
|
|
public function registerUser(array $userData, ?SocialAccount $socialAccount = null, bool $emailConfirmed = false): User
|
2020-01-26 22:42:50 +08:00
|
|
|
{
|
2020-02-03 01:31:00 +08:00
|
|
|
$userEmail = $userData['email'];
|
2020-01-26 22:42:50 +08:00
|
|
|
|
2020-02-03 01:31:00 +08:00
|
|
|
// Email restriction
|
|
|
|
$this->ensureEmailDomainAllowed($userEmail);
|
|
|
|
|
|
|
|
// Ensure user does not already exist
|
|
|
|
$alreadyUser = !is_null($this->userRepo->getByEmail($userEmail));
|
|
|
|
if ($alreadyUser) {
|
2020-09-26 23:43:06 +08:00
|
|
|
throw new UserRegistrationException(trans('errors.error_user_exists_different_creds', ['email' => $userEmail]), '/login');
|
2020-01-26 22:42:50 +08:00
|
|
|
}
|
|
|
|
|
2020-02-03 01:31:00 +08:00
|
|
|
// Create the user
|
|
|
|
$newUser = $this->userRepo->registerNew($userData, $emailConfirmed);
|
2020-01-26 22:42:50 +08:00
|
|
|
|
2020-02-03 01:31:00 +08:00
|
|
|
// Assign social account if given
|
2020-01-26 22:42:50 +08:00
|
|
|
if ($socialAccount) {
|
|
|
|
$newUser->socialAccounts()->save($socialAccount);
|
|
|
|
}
|
|
|
|
|
2020-11-21 03:33:11 +08:00
|
|
|
Activity::add(ActivityType::AUTH_REGISTER, $socialAccount ?? $newUser);
|
2021-03-20 05:54:50 +08:00
|
|
|
Theme::dispatch(ThemeEvents::AUTH_REGISTER, $socialAccount ? $socialAccount->driver : auth()->getDefaultDriver(), $newUser);
|
2020-11-21 03:33:11 +08:00
|
|
|
|
2020-02-03 01:31:00 +08:00
|
|
|
// Start email confirmation flow if required
|
|
|
|
if ($this->emailConfirmationService->confirmationRequired() && !$emailConfirmed) {
|
2020-01-26 22:42:50 +08:00
|
|
|
$newUser->save();
|
|
|
|
|
|
|
|
try {
|
|
|
|
$this->emailConfirmationService->sendConfirmation($newUser);
|
2020-09-06 00:26:48 +08:00
|
|
|
session()->flash('sent-email-confirmation', true);
|
2020-01-26 22:42:50 +08:00
|
|
|
} catch (Exception $e) {
|
|
|
|
$message = trans('auth.email_confirm_send_error');
|
2021-06-26 23:23:15 +08:00
|
|
|
|
2020-08-05 00:54:50 +08:00
|
|
|
throw new UserRegistrationException($message, '/register/confirm');
|
2020-01-26 22:42:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-03 01:31:00 +08:00
|
|
|
return $newUser;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
2021-06-26 23:23:15 +08:00
|
|
|
*
|
2020-02-03 01:31:00 +08:00
|
|
|
* @throws UserRegistrationException
|
|
|
|
*/
|
|
|
|
protected function ensureEmailDomainAllowed(string $userEmail): void
|
|
|
|
{
|
|
|
|
$registrationRestrict = setting('registration-restrict');
|
|
|
|
|
|
|
|
if (!$registrationRestrict) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$restrictedEmailDomains = explode(',', str_replace(' ', '', $registrationRestrict));
|
2021-06-26 23:23:15 +08:00
|
|
|
$userEmailDomain = $domain = mb_substr(mb_strrchr($userEmail, '@'), 1);
|
2020-02-03 01:31:00 +08:00
|
|
|
if (!in_array($userEmailDomain, $restrictedEmailDomains)) {
|
|
|
|
$redirect = $this->registrationAllowed() ? '/register' : '/login';
|
2021-06-26 23:23:15 +08:00
|
|
|
|
2020-02-03 01:31:00 +08:00
|
|
|
throw new UserRegistrationException(trans('auth.registration_email_domain_invalid'), $redirect);
|
|
|
|
}
|
|
|
|
}
|
2021-03-08 06:24:05 +08:00
|
|
|
}
|