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