mirror of
				https://github.com/BookStackApp/BookStack.git
				synced 2025-10-31 03:50:27 +03:00 
			
		
		
		
	Was done for convenience but could potentially be exploited by an attacker using signing up via one of these routes, then forwarding an email confirmation to another user so they unknowingly utilise an account someone else controls. Tweaks the flow of confirming email, and the user invite flow. For #3050
		
			
				
	
	
		
			109 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace BookStack\Http\Controllers\Auth;
 | |
| 
 | |
| use BookStack\Auth\Access\EmailConfirmationService;
 | |
| use BookStack\Auth\Access\LoginService;
 | |
| use BookStack\Auth\UserRepo;
 | |
| use BookStack\Exceptions\ConfirmationEmailException;
 | |
| use BookStack\Exceptions\UserTokenExpiredException;
 | |
| use BookStack\Exceptions\UserTokenNotFoundException;
 | |
| use BookStack\Http\Controllers\Controller;
 | |
| use Exception;
 | |
| use Illuminate\Http\Request;
 | |
| 
 | |
| class ConfirmEmailController extends Controller
 | |
| {
 | |
|     protected $emailConfirmationService;
 | |
|     protected $loginService;
 | |
|     protected $userRepo;
 | |
| 
 | |
|     /**
 | |
|      * Create a new controller instance.
 | |
|      */
 | |
|     public function __construct(
 | |
|         EmailConfirmationService $emailConfirmationService,
 | |
|         LoginService $loginService,
 | |
|         UserRepo $userRepo
 | |
|     ) {
 | |
|         $this->emailConfirmationService = $emailConfirmationService;
 | |
|         $this->loginService = $loginService;
 | |
|         $this->userRepo = $userRepo;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Show the page to tell the user to check their email
 | |
|      * and confirm their address.
 | |
|      */
 | |
|     public function show()
 | |
|     {
 | |
|         return view('auth.register-confirm');
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Shows a notice that a user's email address has not been confirmed,
 | |
|      * Also has the option to re-send the confirmation email.
 | |
|      */
 | |
|     public function showAwaiting()
 | |
|     {
 | |
|         $user = $this->loginService->getLastLoginAttemptUser();
 | |
| 
 | |
|         return view('auth.user-unconfirmed', ['user' => $user]);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Confirms an email via a token and logs the user into the system.
 | |
|      *
 | |
|      * @throws ConfirmationEmailException
 | |
|      * @throws Exception
 | |
|      */
 | |
|     public function confirm(string $token)
 | |
|     {
 | |
|         try {
 | |
|             $userId = $this->emailConfirmationService->checkTokenAndGetUserId($token);
 | |
|         } catch (UserTokenNotFoundException $exception) {
 | |
|             $this->showErrorNotification(trans('errors.email_confirmation_invalid'));
 | |
| 
 | |
|             return redirect('/register');
 | |
|         } catch (UserTokenExpiredException $exception) {
 | |
|             $user = $this->userRepo->getById($exception->userId);
 | |
|             $this->emailConfirmationService->sendConfirmation($user);
 | |
|             $this->showErrorNotification(trans('errors.email_confirmation_expired'));
 | |
| 
 | |
|             return redirect('/register/confirm');
 | |
|         }
 | |
| 
 | |
|         $user = $this->userRepo->getById($userId);
 | |
|         $user->email_confirmed = true;
 | |
|         $user->save();
 | |
| 
 | |
|         $this->emailConfirmationService->deleteByUser($user);
 | |
|         $this->showSuccessNotification(trans('auth.email_confirm_success'));
 | |
| 
 | |
|         return redirect('/login');
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Resend the confirmation email.
 | |
|      */
 | |
|     public function resend(Request $request)
 | |
|     {
 | |
|         $this->validate($request, [
 | |
|             'email' => ['required', 'email', 'exists:users,email'],
 | |
|         ]);
 | |
|         $user = $this->userRepo->getByEmail($request->get('email'));
 | |
| 
 | |
|         try {
 | |
|             $this->emailConfirmationService->sendConfirmation($user);
 | |
|         } catch (Exception $e) {
 | |
|             $this->showErrorNotification(trans('auth.email_confirm_send_error'));
 | |
| 
 | |
|             return redirect('/register/confirm');
 | |
|         }
 | |
| 
 | |
|         $this->showSuccessNotification(trans('auth.email_confirm_resent'));
 | |
| 
 | |
|         return redirect('/register/confirm');
 | |
|     }
 | |
| }
 |