]> BookStack Code Mirror - bookstack/blob - app/Auth/Access/RegistrationService.php
68b17771d628552fe57a1d40fe7301774d43adb9
[bookstack] / app / Auth / Access / RegistrationService.php
1 <?php namespace BookStack\Auth\Access;
2
3 use BookStack\Actions\ActivityType;
4 use BookStack\Auth\SocialAccount;
5 use BookStack\Auth\User;
6 use BookStack\Auth\UserRepo;
7 use BookStack\Exceptions\UserRegistrationException;
8 use BookStack\Facades\Activity;
9 use BookStack\Facades\Theme;
10 use BookStack\Theming\ThemeEvents;
11 use Exception;
12
13 class RegistrationService
14 {
15
16     protected $userRepo;
17     protected $emailConfirmationService;
18
19     /**
20      * RegistrationService constructor.
21      */
22     public function __construct(UserRepo $userRepo, EmailConfirmationService $emailConfirmationService)
23     {
24         $this->userRepo = $userRepo;
25         $this->emailConfirmationService = $emailConfirmationService;
26     }
27
28     /**
29      * Check whether or not registrations are allowed in the app settings.
30      * @throws UserRegistrationException
31      */
32     public function ensureRegistrationAllowed()
33     {
34         if (!$this->registrationAllowed()) {
35             throw new UserRegistrationException(trans('auth.registrations_disabled'), '/login');
36         }
37     }
38
39     /**
40      * Check if standard BookStack User registrations are currently allowed.
41      * Does not prevent external-auth based registration.
42      */
43     protected function registrationAllowed(): bool
44     {
45         $authMethod = config('auth.method');
46         $authMethodsWithRegistration = ['standard'];
47         return in_array($authMethod, $authMethodsWithRegistration) && setting('registration-enabled');
48     }
49
50     /**
51      * The registrations flow for all users.
52      * @throws UserRegistrationException
53      */
54     public function registerUser(array $userData, ?SocialAccount $socialAccount = null, bool $emailConfirmed = false): User
55     {
56         $userEmail = $userData['email'];
57
58         // Email restriction
59         $this->ensureEmailDomainAllowed($userEmail);
60
61         // Ensure user does not already exist
62         $alreadyUser = !is_null($this->userRepo->getByEmail($userEmail));
63         if ($alreadyUser) {
64             throw new UserRegistrationException(trans('errors.error_user_exists_different_creds', ['email' => $userEmail]), '/login');
65         }
66
67         // Create the user
68         $newUser = $this->userRepo->registerNew($userData, $emailConfirmed);
69
70         // Assign social account if given
71         if ($socialAccount) {
72             $newUser->socialAccounts()->save($socialAccount);
73         }
74
75         Activity::add(ActivityType::AUTH_REGISTER, $socialAccount ?? $newUser);
76         Theme::dispatch(ThemeEvents::AUTH_REGISTER, $socialAccount ? $socialAccount->driver : auth()->getDefaultDriver(), $newUser);
77
78         // Start email confirmation flow if required
79         if ($this->emailConfirmationService->confirmationRequired() && !$emailConfirmed) {
80             $newUser->save();
81
82             try {
83                 $this->emailConfirmationService->sendConfirmation($newUser);
84                 session()->flash('sent-email-confirmation', true);
85             } catch (Exception $e) {
86                 $message = trans('auth.email_confirm_send_error');
87                 throw new UserRegistrationException($message, '/register/confirm');
88             }
89         }
90
91         return $newUser;
92     }
93
94     /**
95      * Ensure that the given email meets any active email domain registration restrictions.
96      * Throws if restrictions are active and the email does not match an allowed domain.
97      * @throws UserRegistrationException
98      */
99     protected function ensureEmailDomainAllowed(string $userEmail): void
100     {
101         $registrationRestrict = setting('registration-restrict');
102
103         if (!$registrationRestrict) {
104             return;
105         }
106
107         $restrictedEmailDomains = explode(',', str_replace(' ', '', $registrationRestrict));
108         $userEmailDomain = $domain = mb_substr(mb_strrchr($userEmail, "@"), 1);
109         if (!in_array($userEmailDomain, $restrictedEmailDomains)) {
110             $redirect = $this->registrationAllowed() ? '/register' : '/login';
111             throw new UserRegistrationException(trans('auth.registration_email_domain_invalid'), $redirect);
112         }
113     }
114 }