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