1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-08-07 23:03:00 +03:00

Got standard form-based registration working

This commit is contained in:
Dan Brown
2015-09-05 20:25:57 +01:00
parent 2c3fb557d6
commit dec0cbb1b2
17 changed files with 370 additions and 10 deletions

15
app/EmailConfirmation.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
namespace Oxbow;
use Illuminate\Database\Eloquent\Model;
class EmailConfirmation extends Model
{
protected $fillable = ['user_id', 'token'];
public function user()
{
return $this->belongsTo('Oxbow\User');
}
}

View File

@@ -0,0 +1,7 @@
<?php namespace Oxbow\Exceptions;
class ConfirmationEmailException extends NotifyException
{
}

View File

@@ -0,0 +1,7 @@
<?php namespace Oxbow\Exceptions;
class UserRegistrationException extends NotifyException
{
}

View File

@@ -2,7 +2,12 @@
namespace Oxbow\Http\Controllers\Auth;
use Illuminate\Http\Request;
use Oxbow\Exceptions\SocialSignInException;
use Oxbow\Exceptions\UserRegistrationException;
use Oxbow\Repos\UserRepo;
use Oxbow\Services\EmailConfirmationService;
use Oxbow\Services\Facades\Setting;
use Oxbow\Services\SocialAuthService;
use Oxbow\User;
use Validator;
@@ -30,15 +35,22 @@ class AuthController extends Controller
protected $redirectAfterLogout = '/login';
protected $socialAuthService;
protected $emailConfirmationService;
protected $userRepo;
/**
* Create a new authentication controller instance.
* @param SocialAuthService $socialAuthService
* @param SocialAuthService $socialAuthService
* @param EmailConfirmationService $emailConfirmationService
* @param UserRepo $userRepo
*/
public function __construct(SocialAuthService $socialAuthService)
public function __construct(SocialAuthService $socialAuthService, EmailConfirmationService $emailConfirmationService, UserRepo $userRepo)
{
$this->middleware('guest', ['only' => ['getLogin', 'postLogin', 'getRegister']]);
$this->socialAuthService = $socialAuthService;
$this->emailConfirmationService = $emailConfirmationService;
$this->userRepo = $userRepo;
parent::__construct();
}
/**
@@ -52,7 +64,7 @@ class AuthController extends Controller
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|confirmed|min:6',
'password' => 'required|min:6',
]);
}
@@ -71,6 +83,13 @@ class AuthController extends Controller
]);
}
protected function checkRegistrationAllowed()
{
if(!\Setting::get('registration-enabled')) {
throw new UserRegistrationException('Registrations are currently disabled.', '/login');
}
}
/**
* Show the application registration form.
*
@@ -78,10 +97,104 @@ class AuthController extends Controller
*/
public function getRegister()
{
$this->checkRegistrationAllowed();
$socialDrivers = $this->socialAuthService->getActiveDrivers();
return view('auth.register', ['socialDrivers' => $socialDrivers]);
}
/**
* Handle a registration request for the application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
* @throws UserRegistrationException
*/
public function postRegister(Request $request)
{
$this->checkRegistrationAllowed();
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
if(\Setting::get('registration-restrict')) {
$restrictedEmailDomains = explode(',', str_replace(' ', '', \Setting::get('registration-restrict')));
$userEmailDomain = $domain = substr(strrchr($request->get('email'), "@"), 1);
if(!in_array($userEmailDomain, $restrictedEmailDomains)) {
throw new UserRegistrationException('That email domain does not have access to this application', '/register');
}
}
$newUser = $this->create($request->all());
$newUser->attachRoleId(\Setting::get('registration-role'), 1);
if(\Setting::get('registration-confirmation') || \Setting::get('registration-restrict')) {
$newUser->email_confirmed = false;
$newUser->save();
$this->emailConfirmationService->sendConfirmation($newUser);
return redirect('/register/confirm');
}
auth()->login($newUser);
return redirect($this->redirectPath());
}
/**
* Show the page to tell the user to check thier email
* and confirm their address.
*/
public function getRegisterConfirmation()
{
return view('auth/register-confirm');
}
/**
* Confirms an email via a token and logs the user into the system.
* @param $token
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
* @throws UserRegistrationException
*/
public function confirmEmail($token)
{
$confirmation = $this->emailConfirmationService->getEmailConfirmationFromToken($token);
$user = $confirmation->user;
$user->email_confirmed = true;
$user->save();
auth()->login($confirmation->user);
session()->flash('success', 'Your email has been confirmed!');
$this->emailConfirmationService->deleteConfirmationsByUser($user);
return redirect($this->redirectPath);
}
/**
* Shows a notice that a user's email address has not been confirmed,
* Also has the option to re-send the confirmation email.
* @return \Illuminate\View\View
*/
public function showAwaitingConfirmation()
{
return view('auth/user-unconfirmed');
}
/**
* Resend the confirmation email
* @param Request $request
* @return \Illuminate\View\View
*/
public function resendConfirmation(Request $request)
{
$this->validate($request, [
'email' => 'required|email|exists:users,email'
]);
$user = $this->userRepo->getByEmail($request->get('email'));
$this->emailConfirmationService->sendConfirmation($user);
\Session::flash('success', 'Confirmation email resent, Please check your inbox.');
return redirect('/register/confirm');
}
/**
* Show the application login form.
*

View File

@@ -38,6 +38,7 @@ class SettingController extends Controller
$key = str_replace('setting-', '', trim($name));
Setting::put($key, $value);
}
session()->flash('success', 'Settings Saved');
return redirect('/settings');
}

View File

@@ -118,7 +118,6 @@ class UserController extends Controller
}
if ($request->has('password') && $request->get('password') != '') {
//dd('cat');
$password = $request->get('password');
$user->password = bcrypt($password);
}

View File

@@ -4,6 +4,7 @@ namespace Oxbow\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Oxbow\Exceptions\UserRegistrationException;
use Setting;
class Authenticate
@@ -34,6 +35,9 @@ class Authenticate
*/
public function handle($request, Closure $next)
{
if(auth()->check() && auth()->user()->email_confirmed == false) {
return redirect()->guest('/register/confirm/awaiting');
}
if ($this->auth->guest() && !Setting::get('app-public')) {
if ($request->ajax()) {
return response('Unauthorized.', 401);

View File

@@ -88,6 +88,11 @@ Route::get('/login', 'Auth\AuthController@getLogin');
Route::post('/login', 'Auth\AuthController@postLogin');
Route::get('/logout', 'Auth\AuthController@getLogout');
Route::get('/register', 'Auth\AuthController@getRegister');
Route::get('/register/confirm', 'Auth\AuthController@getRegisterConfirmation');
Route::get('/register/confirm/awaiting', 'Auth\AuthController@showAwaitingConfirmation');
Route::post('/register/confirm/resend', 'Auth\AuthController@resendConfirmation');
Route::get('/register/confirm/{token}', 'Auth\AuthController@confirmEmail');
Route::post('/register', 'Auth\AuthController@postRegister');
// Password reset link request routes...
Route::get('/password/email', 'Auth\PasswordController@getEmail');

View File

@@ -21,4 +21,9 @@ class UserRepo
public function getByEmail($email) {
return $this->user->where('email', '=', $email)->first();
}
public function getById($id)
{
return $this->user->findOrFail($id);
}
}

View File

@@ -0,0 +1,102 @@
<?php namespace Oxbow\Services;
use Carbon\Carbon;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Mail\Message;
use Oxbow\EmailConfirmation;
use Oxbow\Exceptions\ConfirmationEmailException;
use Oxbow\Exceptions\UserRegistrationException;
use Oxbow\Repos\UserRepo;
use Oxbow\Setting;
use Oxbow\User;
class EmailConfirmationService
{
protected $mailer;
protected $emailConfirmation;
/**
* EmailConfirmationService constructor.
* @param Mailer $mailer
* @param EmailConfirmation $emailConfirmation
*/
public function __construct(Mailer $mailer, EmailConfirmation $emailConfirmation)
{
$this->mailer = $mailer;
$this->emailConfirmation = $emailConfirmation;
}
/**
* Create new confirmation for a user,
* Also removes any existing old ones.
* @param User $user
* @throws ConfirmationEmailException
*/
public function sendConfirmation(User $user)
{
if($user->email_confirmed) {
throw new ConfirmationEmailException('Email has already been confirmed, Try logging in.', '/login');
}
$this->deleteConfirmationsByUser($user);
$token = $this->getToken();
$this->emailConfirmation->create([
'user_id' => $user->id,
'token' => $token,
]);
$this->mailer->send('emails/email-confirmation', ['token' => $token], function (Message $message) use ($user) {
$appName = \Setting::get('app-name', 'BookStack');
$message->to($user->email, $user->name)->subject('Confirm your email on ' . $appName . '.');
});
}
/**
* Gets an email confirmation by looking up the token,
* Ensures the token has not expired.
* @param string $token
* @return EmailConfirmation
* @throws UserRegistrationException
*/
public function getEmailConfirmationFromToken($token)
{
$emailConfirmation = $this->emailConfirmation->where('token', '=', $token)->first();
// If not found
if ($emailConfirmation === null) {
throw new UserRegistrationException('This confirmation token is not valid or has already been used, Please try registering again.', '/register');
}
// If more than a day old
if(Carbon::now()->subDay()->gt($emailConfirmation->created_at)) {
$this->sendConfirmation($emailConfirmation->user);
throw new UserRegistrationException('The confirmation token has expired, A new confirmation email has been sent.', '/register/confirm');
}
return $emailConfirmation;
}
/**
* Delete all email confirmations that belong to a user.
* @param User $user
* @return mixed
*/
public function deleteConfirmationsByUser(User $user)
{
return $this->emailConfirmation->where('user_id', '=', $user->id)->delete();
}
/**
* Creates a unique token within the email confirmation database.
* @return string
*/
protected function getToken()
{
$token = str_random(24);
while ($this->emailConfirmation->where('token', '=', $token)->exists()) {
$token = str_random(25);
}
return $token;
}
}