]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/Auth/RegisterController.php
Merge pull request #1573 from miles75/lang-hu
[bookstack] / app / Http / Controllers / Auth / RegisterController.php
1 <?php
2
3 namespace BookStack\Http\Controllers\Auth;
4
5 use BookStack\Auth\Access\EmailConfirmationService;
6 use BookStack\Auth\Access\SocialAuthService;
7 use BookStack\Auth\SocialAccount;
8 use BookStack\Auth\User;
9 use BookStack\Auth\UserRepo;
10 use BookStack\Exceptions\SocialDriverNotConfigured;
11 use BookStack\Exceptions\SocialSignInAccountNotUsed;
12 use BookStack\Exceptions\SocialSignInException;
13 use BookStack\Exceptions\UserRegistrationException;
14 use BookStack\Http\Controllers\Controller;
15 use Exception;
16 use Illuminate\Foundation\Auth\RegistersUsers;
17 use Illuminate\Http\RedirectResponse;
18 use Illuminate\Http\Request;
19 use Illuminate\Http\Response;
20 use Illuminate\Routing\Redirector;
21 use Laravel\Socialite\Contracts\User as SocialUser;
22 use Validator;
23
24 class RegisterController extends Controller
25 {
26     /*
27     |--------------------------------------------------------------------------
28     | Register Controller
29     |--------------------------------------------------------------------------
30     |
31     | This controller handles the registration of new users as well as their
32     | validation and creation. By default this controller uses a trait to
33     | provide this functionality without requiring any additional code.
34     |
35     */
36
37     use RegistersUsers;
38
39     protected $socialAuthService;
40     protected $emailConfirmationService;
41     protected $userRepo;
42
43     /**
44      * Where to redirect users after login / registration.
45      *
46      * @var string
47      */
48     protected $redirectTo = '/';
49     protected $redirectPath = '/';
50
51     /**
52      * Create a new controller instance.
53      *
54      * @param SocialAuthService $socialAuthService
55      * @param EmailConfirmationService $emailConfirmationService
56      * @param UserRepo $userRepo
57      */
58     public function __construct(SocialAuthService $socialAuthService, EmailConfirmationService $emailConfirmationService, UserRepo $userRepo)
59     {
60         $this->middleware('guest')->only(['getRegister', 'postRegister', 'socialRegister']);
61         $this->socialAuthService = $socialAuthService;
62         $this->emailConfirmationService = $emailConfirmationService;
63         $this->userRepo = $userRepo;
64         $this->redirectTo = url('/');
65         $this->redirectPath = url('/');
66         parent::__construct();
67     }
68
69     /**
70      * Get a validator for an incoming registration request.
71      *
72      * @param  array $data
73      * @return \Illuminate\Contracts\Validation\Validator
74      */
75     protected function validator(array $data)
76     {
77         return Validator::make($data, [
78             'name' => 'required|min:2|max:255',
79             'email' => 'required|email|max:255|unique:users',
80             'password' => 'required|min:6',
81         ]);
82     }
83
84     /**
85      * Check whether or not registrations are allowed in the app settings.
86      * @throws UserRegistrationException
87      */
88     protected function checkRegistrationAllowed()
89     {
90         if (!setting('registration-enabled')) {
91             throw new UserRegistrationException(trans('auth.registrations_disabled'), '/login');
92         }
93     }
94
95     /**
96      * Show the application registration form.
97      * @return Response
98      * @throws UserRegistrationException
99      */
100     public function getRegister()
101     {
102         $this->checkRegistrationAllowed();
103         $socialDrivers = $this->socialAuthService->getActiveDrivers();
104         return view('auth.register', ['socialDrivers' => $socialDrivers]);
105     }
106
107     /**
108      * Handle a registration request for the application.
109      * @param Request|Request $request
110      * @return RedirectResponse|Redirector
111      * @throws UserRegistrationException
112      */
113     public function postRegister(Request $request)
114     {
115         $this->checkRegistrationAllowed();
116         $this->validator($request->all())->validate();
117
118         $userData = $request->all();
119         return $this->registerUser($userData);
120     }
121
122     /**
123      * Create a new user instance after a valid registration.
124      * @param  array  $data
125      * @return User
126      */
127     protected function create(array $data)
128     {
129         return User::create([
130             'name' => $data['name'],
131             'email' => $data['email'],
132             'password' => bcrypt($data['password']),
133         ]);
134     }
135
136     /**
137      * The registrations flow for all users.
138      * @param array $userData
139      * @param bool|false|SocialAccount $socialAccount
140      * @param bool $emailVerified
141      * @return RedirectResponse|Redirector
142      * @throws UserRegistrationException
143      */
144     protected function registerUser(array $userData, $socialAccount = false, $emailVerified = false)
145     {
146         $registrationRestrict = setting('registration-restrict');
147
148         if ($registrationRestrict) {
149             $restrictedEmailDomains = explode(',', str_replace(' ', '', $registrationRestrict));
150             $userEmailDomain = $domain = mb_substr(mb_strrchr($userData['email'], "@"), 1);
151             if (!in_array($userEmailDomain, $restrictedEmailDomains)) {
152                 throw new UserRegistrationException(trans('auth.registration_email_domain_invalid'), '/register');
153             }
154         }
155
156         $newUser = $this->userRepo->registerNew($userData, $emailVerified);
157         if ($socialAccount) {
158             $newUser->socialAccounts()->save($socialAccount);
159         }
160
161         if ($this->emailConfirmationService->confirmationRequired() && !$emailVerified) {
162             $newUser->save();
163
164             try {
165                 $this->emailConfirmationService->sendConfirmation($newUser);
166             } catch (Exception $e) {
167                 session()->flash('error', trans('auth.email_confirm_send_error'));
168             }
169
170             return redirect('/register/confirm');
171         }
172
173         auth()->login($newUser);
174         session()->flash('success', trans('auth.register_success'));
175         return redirect($this->redirectPath());
176     }
177
178     /**
179      * Redirect to the social site for authentication intended to register.
180      * @param $socialDriver
181      * @return mixed
182      * @throws UserRegistrationException
183      * @throws SocialDriverNotConfigured
184      */
185     public function socialRegister($socialDriver)
186     {
187         $this->checkRegistrationAllowed();
188         session()->put('social-callback', 'register');
189         return $this->socialAuthService->startRegister($socialDriver);
190     }
191
192     /**
193      * The callback for social login services.
194      * @param $socialDriver
195      * @param Request $request
196      * @return RedirectResponse|Redirector
197      * @throws SocialSignInException
198      * @throws UserRegistrationException
199      * @throws SocialDriverNotConfigured
200      */
201     public function socialCallback($socialDriver, Request $request)
202     {
203         if (!session()->has('social-callback')) {
204             throw new SocialSignInException(trans('errors.social_no_action_defined'), '/login');
205         }
206
207         // Check request for error information
208         if ($request->has('error') && $request->has('error_description')) {
209             throw new SocialSignInException(trans('errors.social_login_bad_response', [
210                 'socialAccount' => $socialDriver,
211                 'error' => $request->get('error_description'),
212             ]), '/login');
213         }
214
215         $action = session()->pull('social-callback');
216
217         // Attempt login or fall-back to register if allowed.
218         $socialUser = $this->socialAuthService->getSocialUser($socialDriver);
219         if ($action == 'login') {
220             try {
221                 return $this->socialAuthService->handleLoginCallback($socialDriver, $socialUser);
222             } catch (SocialSignInAccountNotUsed $exception) {
223                 if ($this->socialAuthService->driverAutoRegisterEnabled($socialDriver)) {
224                     return $this->socialRegisterCallback($socialDriver, $socialUser);
225                 }
226                 throw $exception;
227             }
228         }
229
230         if ($action == 'register') {
231             return $this->socialRegisterCallback($socialDriver, $socialUser);
232         }
233
234         return redirect()->back();
235     }
236
237     /**
238      * Detach a social account from a user.
239      * @param $socialDriver
240      * @return RedirectResponse|Redirector
241      */
242     public function detachSocialAccount($socialDriver)
243     {
244         return $this->socialAuthService->detachSocialAccount($socialDriver);
245     }
246
247     /**
248      * Register a new user after a registration callback.
249      * @param string $socialDriver
250      * @param SocialUser $socialUser
251      * @return RedirectResponse|Redirector
252      * @throws UserRegistrationException
253      */
254     protected function socialRegisterCallback(string $socialDriver, SocialUser $socialUser)
255     {
256         $socialUser = $this->socialAuthService->handleRegistrationCallback($socialDriver, $socialUser);
257         $socialAccount = $this->socialAuthService->fillSocialAccount($socialDriver, $socialUser);
258         $emailVerified = $this->socialAuthService->driverAutoConfirmEmailEnabled($socialDriver);
259
260         // Create an array of the user data to create a new user instance
261         $userData = [
262             'name' => $socialUser->getName(),
263             'email' => $socialUser->getEmail(),
264             'password' => str_random(30)
265         ];
266         return $this->registerUser($userData, $socialAccount, $emailVerified);
267     }
268 }