Removed usage of laravel/ui dependency
Brings app auth controller handling aligned within the app, rather than having many overrides of the framwork packages causing confusion and messiness over time.
This commit is contained in:
parent
7165481075
commit
f4388d5e4a
|
@ -5,6 +5,7 @@ namespace BookStack\Auth\Access;
|
||||||
use BookStack\Actions\ActivityType;
|
use BookStack\Actions\ActivityType;
|
||||||
use BookStack\Auth\Access\Mfa\MfaSession;
|
use BookStack\Auth\Access\Mfa\MfaSession;
|
||||||
use BookStack\Auth\User;
|
use BookStack\Auth\User;
|
||||||
|
use BookStack\Exceptions\LoginAttemptException;
|
||||||
use BookStack\Exceptions\StoppedAuthenticationException;
|
use BookStack\Exceptions\StoppedAuthenticationException;
|
||||||
use BookStack\Facades\Activity;
|
use BookStack\Facades\Activity;
|
||||||
use BookStack\Facades\Theme;
|
use BookStack\Facades\Theme;
|
||||||
|
@ -149,6 +150,7 @@ class LoginService
|
||||||
* May interrupt the flow if extra authentication requirements are imposed.
|
* May interrupt the flow if extra authentication requirements are imposed.
|
||||||
*
|
*
|
||||||
* @throws StoppedAuthenticationException
|
* @throws StoppedAuthenticationException
|
||||||
|
* @throws LoginAttemptException
|
||||||
*/
|
*/
|
||||||
public function attempt(array $credentials, string $method, bool $remember = false): bool
|
public function attempt(array $credentials, string $method, bool $remember = false): bool
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,7 @@ use BookStack\Exceptions\UserUpdateException;
|
||||||
use BookStack\Facades\Activity;
|
use BookStack\Facades\Activity;
|
||||||
use BookStack\Uploads\UserAvatars;
|
use BookStack\Uploads\UserAvatars;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ class UserRepo
|
||||||
$user = new User();
|
$user = new User();
|
||||||
$user->name = $data['name'];
|
$user->name = $data['name'];
|
||||||
$user->email = $data['email'];
|
$user->email = $data['email'];
|
||||||
$user->password = bcrypt(empty($data['password']) ? Str::random(32) : $data['password']);
|
$user->password = Hash::make(empty($data['password']) ? Str::random(32) : $data['password']);
|
||||||
$user->email_confirmed = $emailConfirmed;
|
$user->email_confirmed = $emailConfirmed;
|
||||||
$user->external_auth_id = $data['external_auth_id'] ?? '';
|
$user->external_auth_id = $data['external_auth_id'] ?? '';
|
||||||
|
|
||||||
|
@ -126,7 +127,7 @@ class UserRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($data['password'])) {
|
if (!empty($data['password'])) {
|
||||||
$user->password = bcrypt($data['password']);
|
$user->password = Hash::make($data['password']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($data['language'])) {
|
if (!empty($data['language'])) {
|
||||||
|
|
|
@ -4,24 +4,11 @@ namespace BookStack\Http\Controllers\Auth;
|
||||||
|
|
||||||
use BookStack\Actions\ActivityType;
|
use BookStack\Actions\ActivityType;
|
||||||
use BookStack\Http\Controllers\Controller;
|
use BookStack\Http\Controllers\Controller;
|
||||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Password;
|
use Illuminate\Support\Facades\Password;
|
||||||
|
|
||||||
class ForgotPasswordController extends Controller
|
class ForgotPasswordController extends Controller
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Password Reset Controller
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This controller is responsible for handling password reset emails and
|
|
||||||
| includes a trait which assists in sending these notifications from
|
|
||||||
| your application to your users. Feel free to explore this trait.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
use SendsPasswordResetEmails;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new controller instance.
|
* Create a new controller instance.
|
||||||
*
|
*
|
||||||
|
@ -33,6 +20,14 @@ class ForgotPasswordController extends Controller
|
||||||
$this->middleware('guard:standard');
|
$this->middleware('guard:standard');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the form to request a password reset link.
|
||||||
|
*/
|
||||||
|
public function showLinkRequestForm()
|
||||||
|
{
|
||||||
|
return view('auth.passwords.email');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a reset link to the given user.
|
* Send a reset link to the given user.
|
||||||
*
|
*
|
||||||
|
@ -49,7 +44,7 @@ class ForgotPasswordController extends Controller
|
||||||
// We will send the password reset link to this user. Once we have attempted
|
// We will send the password reset link to this user. Once we have attempted
|
||||||
// to send the link, we will examine the response then see the message we
|
// to send the link, we will examine the response then see the message we
|
||||||
// need to show to the user. Finally, we'll send out a proper response.
|
// need to show to the user. Finally, we'll send out a proper response.
|
||||||
$response = $this->broker()->sendResetLink(
|
$response = Password::broker()->sendResetLink(
|
||||||
$request->only('email')
|
$request->only('email')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -8,31 +8,14 @@ use BookStack\Exceptions\LoginAttemptEmailNeededException;
|
||||||
use BookStack\Exceptions\LoginAttemptException;
|
use BookStack\Exceptions\LoginAttemptException;
|
||||||
use BookStack\Facades\Activity;
|
use BookStack\Facades\Activity;
|
||||||
use BookStack\Http\Controllers\Controller;
|
use BookStack\Http\Controllers\Controller;
|
||||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class LoginController extends Controller
|
class LoginController extends Controller
|
||||||
{
|
{
|
||||||
/*
|
use ThrottlesLogins;
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Login Controller
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This controller handles authenticating users for the application and
|
|
||||||
| redirecting them to your home screen. The controller uses a trait
|
|
||||||
| to conveniently provide its functionality to your applications.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
use AuthenticatesUsers {
|
|
||||||
logout as traitLogout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirection paths.
|
|
||||||
*/
|
|
||||||
protected string $redirectTo = '/';
|
|
||||||
protected string $redirectPath = '/';
|
|
||||||
|
|
||||||
protected SocialAuthService $socialAuthService;
|
protected SocialAuthService $socialAuthService;
|
||||||
protected LoginService $loginService;
|
protected LoginService $loginService;
|
||||||
|
@ -48,21 +31,6 @@ class LoginController extends Controller
|
||||||
|
|
||||||
$this->socialAuthService = $socialAuthService;
|
$this->socialAuthService = $socialAuthService;
|
||||||
$this->loginService = $loginService;
|
$this->loginService = $loginService;
|
||||||
|
|
||||||
$this->redirectPath = url('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function username()
|
|
||||||
{
|
|
||||||
return config('auth.method') === 'standard' ? 'email' : 'username';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the needed authorization credentials from the request.
|
|
||||||
*/
|
|
||||||
protected function credentials(Request $request)
|
|
||||||
{
|
|
||||||
return $request->only('username', 'email', 'password');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,29 +66,15 @@ class LoginController extends Controller
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a login request to the application.
|
* Handle a login request to the application.
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
*
|
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
|
|
||||||
*/
|
*/
|
||||||
public function login(Request $request)
|
public function login(Request $request)
|
||||||
{
|
{
|
||||||
$this->validateLogin($request);
|
$this->validateLogin($request);
|
||||||
$username = $request->get($this->username());
|
$username = $request->get($this->username());
|
||||||
|
|
||||||
// If the class is using the ThrottlesLogins trait, we can automatically throttle
|
// Check login throttling attempts to see if they've gone over the limit
|
||||||
// the login attempts for this application. We'll key this by the username and
|
if ($this->hasTooManyLoginAttempts($request)) {
|
||||||
// the IP address of the client making these requests into this application.
|
|
||||||
if (
|
|
||||||
method_exists($this, 'hasTooManyLoginAttempts') &&
|
|
||||||
$this->hasTooManyLoginAttempts($request)
|
|
||||||
) {
|
|
||||||
$this->fireLockoutEvent($request);
|
|
||||||
|
|
||||||
Activity::logFailedLogin($username);
|
Activity::logFailedLogin($username);
|
||||||
|
|
||||||
return $this->sendLockoutResponse($request);
|
return $this->sendLockoutResponse($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,24 +88,62 @@ class LoginController extends Controller
|
||||||
return $this->sendLoginAttemptExceptionResponse($exception, $request);
|
return $this->sendLoginAttemptExceptionResponse($exception, $request);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the login attempt was unsuccessful we will increment the number of attempts
|
// On unsuccessful login attempt, Increment login attempts for throttling and log failed login.
|
||||||
// to login and redirect the user back to the login form. Of course, when this
|
|
||||||
// user surpasses their maximum number of attempts they will get locked out.
|
|
||||||
$this->incrementLoginAttempts($request);
|
$this->incrementLoginAttempts($request);
|
||||||
|
|
||||||
Activity::logFailedLogin($username);
|
Activity::logFailedLogin($username);
|
||||||
|
|
||||||
return $this->sendFailedLoginResponse($request);
|
// Throw validation failure for failed login
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
$this->username() => [trans('auth.failed')],
|
||||||
|
])->redirectTo('/login');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logout user and perform subsequent redirect.
|
||||||
|
*/
|
||||||
|
public function logout(Request $request)
|
||||||
|
{
|
||||||
|
Auth::guard()->logout();
|
||||||
|
$request->session()->invalidate();
|
||||||
|
$request->session()->regenerateToken();
|
||||||
|
|
||||||
|
$redirectUri = $this->shouldAutoInitiate() ? '/login?prevent_auto_init=true' : '/';
|
||||||
|
|
||||||
|
return redirect($redirectUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the expected username input based upon the current auth method.
|
||||||
|
*/
|
||||||
|
protected function username(): string
|
||||||
|
{
|
||||||
|
return config('auth.method') === 'standard' ? 'email' : 'username';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the needed authorization credentials from the request.
|
||||||
|
*/
|
||||||
|
protected function credentials(Request $request): array
|
||||||
|
{
|
||||||
|
return $request->only('username', 'email', 'password');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the response after the user was authenticated.
|
||||||
|
* @return RedirectResponse
|
||||||
|
*/
|
||||||
|
protected function sendLoginResponse(Request $request)
|
||||||
|
{
|
||||||
|
$request->session()->regenerate();
|
||||||
|
$this->clearLoginAttempts($request);
|
||||||
|
|
||||||
|
return redirect()->intended('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to log the user into the application.
|
* Attempt to log the user into the application.
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
protected function attemptLogin(Request $request)
|
protected function attemptLogin(Request $request): bool
|
||||||
{
|
{
|
||||||
return $this->loginService->attempt(
|
return $this->loginService->attempt(
|
||||||
$this->credentials($request),
|
$this->credentials($request),
|
||||||
|
@ -160,29 +152,12 @@ class LoginController extends Controller
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The user has been authenticated.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @param mixed $user
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
protected function authenticated(Request $request, $user)
|
|
||||||
{
|
|
||||||
return redirect()->intended($this->redirectPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the user login request.
|
* Validate the user login request.
|
||||||
*
|
* @throws ValidationException
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
*
|
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
*/
|
||||||
protected function validateLogin(Request $request)
|
protected function validateLogin(Request $request): void
|
||||||
{
|
{
|
||||||
$rules = ['password' => ['required', 'string']];
|
$rules = ['password' => ['required', 'string']];
|
||||||
$authMethod = config('auth.method');
|
$authMethod = config('auth.method');
|
||||||
|
@ -216,22 +191,6 @@ class LoginController extends Controller
|
||||||
return redirect('/login');
|
return redirect('/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the failed login response instance.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
*
|
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
|
||||||
*
|
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
|
||||||
*/
|
|
||||||
protected function sendFailedLoginResponse(Request $request)
|
|
||||||
{
|
|
||||||
throw ValidationException::withMessages([
|
|
||||||
$this->username() => [trans('auth.failed')],
|
|
||||||
])->redirectTo('/login');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the intended URL location from their previous URL.
|
* Update the intended URL location from their previous URL.
|
||||||
* Ignores if not from the current app instance or if from certain
|
* Ignores if not from the current app instance or if from certain
|
||||||
|
@ -271,20 +230,4 @@ class LoginController extends Controller
|
||||||
|
|
||||||
return $autoRedirect && count($socialDrivers) === 0 && in_array($authMethod, ['oidc', 'saml2']);
|
return $autoRedirect && count($socialDrivers) === 0 && in_array($authMethod, ['oidc', 'saml2']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Logout user and perform subsequent redirect.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function logout(Request $request)
|
|
||||||
{
|
|
||||||
$this->traitLogout($request);
|
|
||||||
|
|
||||||
$redirectUri = $this->shouldAutoInitiate() ? '/login?prevent_auto_init=true' : '/';
|
|
||||||
|
|
||||||
return redirect($redirectUri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,40 +5,20 @@ namespace BookStack\Http\Controllers\Auth;
|
||||||
use BookStack\Auth\Access\LoginService;
|
use BookStack\Auth\Access\LoginService;
|
||||||
use BookStack\Auth\Access\RegistrationService;
|
use BookStack\Auth\Access\RegistrationService;
|
||||||
use BookStack\Auth\Access\SocialAuthService;
|
use BookStack\Auth\Access\SocialAuthService;
|
||||||
use BookStack\Auth\User;
|
|
||||||
use BookStack\Exceptions\StoppedAuthenticationException;
|
use BookStack\Exceptions\StoppedAuthenticationException;
|
||||||
use BookStack\Exceptions\UserRegistrationException;
|
use BookStack\Exceptions\UserRegistrationException;
|
||||||
use BookStack\Http\Controllers\Controller;
|
use BookStack\Http\Controllers\Controller;
|
||||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
use Illuminate\Contracts\Validation\Validator as ValidatorContract;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Hash;
|
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Validation\Rules\Password;
|
use Illuminate\Validation\Rules\Password;
|
||||||
|
|
||||||
class RegisterController extends Controller
|
class RegisterController extends Controller
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Register Controller
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This controller handles the registration of new users as well as their
|
|
||||||
| validation and creation. By default this controller uses a trait to
|
|
||||||
| provide this functionality without requiring any additional code.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
use RegistersUsers;
|
|
||||||
|
|
||||||
protected SocialAuthService $socialAuthService;
|
protected SocialAuthService $socialAuthService;
|
||||||
protected RegistrationService $registrationService;
|
protected RegistrationService $registrationService;
|
||||||
protected LoginService $loginService;
|
protected LoginService $loginService;
|
||||||
|
|
||||||
/**
|
|
||||||
* Where to redirect users after login / registration.
|
|
||||||
*/
|
|
||||||
protected string $redirectTo = '/';
|
|
||||||
protected string $redirectPath = '/';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new controller instance.
|
* Create a new controller instance.
|
||||||
*/
|
*/
|
||||||
|
@ -53,23 +33,6 @@ class RegisterController extends Controller
|
||||||
$this->socialAuthService = $socialAuthService;
|
$this->socialAuthService = $socialAuthService;
|
||||||
$this->registrationService = $registrationService;
|
$this->registrationService = $registrationService;
|
||||||
$this->loginService = $loginService;
|
$this->loginService = $loginService;
|
||||||
|
|
||||||
$this->redirectTo = url('/');
|
|
||||||
$this->redirectPath = url('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a validator for an incoming registration request.
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\Validation\Validator
|
|
||||||
*/
|
|
||||||
protected function validator(array $data)
|
|
||||||
{
|
|
||||||
return Validator::make($data, [
|
|
||||||
'name' => ['required', 'min:2', 'max:100'],
|
|
||||||
'email' => ['required', 'email', 'max:255', 'unique:users'],
|
|
||||||
'password' => ['required', Password::default()],
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,22 +75,18 @@ class RegisterController extends Controller
|
||||||
|
|
||||||
$this->showSuccessNotification(trans('auth.register_success'));
|
$this->showSuccessNotification(trans('auth.register_success'));
|
||||||
|
|
||||||
return redirect($this->redirectPath());
|
return redirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new user instance after a valid registration.
|
* Get a validator for an incoming registration request.
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return User
|
|
||||||
*/
|
*/
|
||||||
protected function create(array $data)
|
protected function validator(array $data): ValidatorContract
|
||||||
{
|
{
|
||||||
return User::create([
|
return Validator::make($data, [
|
||||||
'name' => $data['name'],
|
'name' => ['required', 'min:2', 'max:100'],
|
||||||
'email' => $data['email'],
|
'email' => ['required', 'email', 'max:255', 'unique:users'],
|
||||||
'password' => Hash::make($data['password']),
|
'password' => ['required', Password::default()],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,65 +3,87 @@
|
||||||
namespace BookStack\Http\Controllers\Auth;
|
namespace BookStack\Http\Controllers\Auth;
|
||||||
|
|
||||||
use BookStack\Actions\ActivityType;
|
use BookStack\Actions\ActivityType;
|
||||||
|
use BookStack\Auth\Access\LoginService;
|
||||||
|
use BookStack\Auth\User;
|
||||||
use BookStack\Http\Controllers\Controller;
|
use BookStack\Http\Controllers\Controller;
|
||||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Password;
|
use Illuminate\Support\Facades\Password;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Validation\Rules\Password as PasswordRule;
|
||||||
|
|
||||||
class ResetPasswordController extends Controller
|
class ResetPasswordController extends Controller
|
||||||
{
|
{
|
||||||
/*
|
protected LoginService $loginService;
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Password Reset Controller
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This controller is responsible for handling password reset requests
|
|
||||||
| and uses a simple trait to include this behavior. You're free to
|
|
||||||
| explore this trait and override any methods you wish to tweak.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
use ResetsPasswords;
|
|
||||||
|
|
||||||
protected $redirectTo = '/';
|
public function __construct(LoginService $loginService)
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new controller instance.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
{
|
||||||
$this->middleware('guest');
|
$this->middleware('guest');
|
||||||
$this->middleware('guard:standard');
|
$this->middleware('guard:standard');
|
||||||
|
|
||||||
|
$this->loginService = $loginService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the password reset view for the given token.
|
||||||
|
* If no token is present, display the link request form.
|
||||||
|
*/
|
||||||
|
public function showResetForm(Request $request)
|
||||||
|
{
|
||||||
|
$token = $request->route()->parameter('token');
|
||||||
|
|
||||||
|
return view('auth.passwords.reset')->with(
|
||||||
|
['token' => $token, 'email' => $request->email]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the given user's password.
|
||||||
|
*/
|
||||||
|
public function reset(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'token' => 'required',
|
||||||
|
'email' => 'required|email',
|
||||||
|
'password' => ['required', 'confirmed', PasswordRule::defaults()],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Here we will attempt to reset the user's password. If it is successful we
|
||||||
|
// will update the password on an actual user model and persist it to the
|
||||||
|
// database. Otherwise we will parse the error and return the response.
|
||||||
|
$credentials = $request->only('email', 'password', 'password_confirmation', 'token');
|
||||||
|
$response = Password::broker()->reset($credentials, function (User $user, string $password) {
|
||||||
|
$user->password = Hash::make($password);
|
||||||
|
$user->setRememberToken(Str::random(60));
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
$this->loginService->login($user, auth()->getDefaultDriver());
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the password was successfully reset, we will redirect the user back to
|
||||||
|
// the application's home authenticated view. If there is an error we can
|
||||||
|
// redirect them back to where they came from with their error message.
|
||||||
|
return $response === Password::PASSWORD_RESET
|
||||||
|
? $this->sendResetResponse()
|
||||||
|
: $this->sendResetFailedResponse($request, $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the response for a successful password reset.
|
* Get the response for a successful password reset.
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @param string $response
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\Response
|
|
||||||
*/
|
*/
|
||||||
protected function sendResetResponse(Request $request, $response)
|
protected function sendResetResponse(): RedirectResponse
|
||||||
{
|
{
|
||||||
$message = trans('auth.reset_password_success');
|
$this->showSuccessNotification(trans('auth.reset_password_success'));
|
||||||
$this->showSuccessNotification($message);
|
|
||||||
$this->logActivity(ActivityType::AUTH_PASSWORD_RESET_UPDATE, user());
|
$this->logActivity(ActivityType::AUTH_PASSWORD_RESET_UPDATE, user());
|
||||||
|
|
||||||
return redirect($this->redirectPath())
|
return redirect('/');
|
||||||
->with('status', trans($response));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the response for a failed password reset.
|
* Get the response for a failed password reset.
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @param string $response
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
|
|
||||||
*/
|
*/
|
||||||
protected function sendResetFailedResponse(Request $request, $response)
|
protected function sendResetFailedResponse(Request $request, string $response): RedirectResponse
|
||||||
{
|
{
|
||||||
// We show invalid users as invalid tokens as to not leak what
|
// We show invalid users as invalid tokens as to not leak what
|
||||||
// users may exist in the system.
|
// users may exist in the system.
|
||||||
|
|
|
@ -9,7 +9,7 @@ use Illuminate\Support\Str;
|
||||||
|
|
||||||
class Saml2Controller extends Controller
|
class Saml2Controller extends Controller
|
||||||
{
|
{
|
||||||
protected $samlService;
|
protected Saml2Service $samlService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saml2Controller constructor.
|
* Saml2Controller constructor.
|
||||||
|
|
|
@ -28,7 +28,7 @@ class SocialController extends Controller
|
||||||
RegistrationService $registrationService,
|
RegistrationService $registrationService,
|
||||||
LoginService $loginService
|
LoginService $loginService
|
||||||
) {
|
) {
|
||||||
$this->middleware('guest')->only(['getRegister', 'postRegister']);
|
$this->middleware('guest')->only(['register']);
|
||||||
$this->socialAuthService = $socialAuthService;
|
$this->socialAuthService = $socialAuthService;
|
||||||
$this->registrationService = $registrationService;
|
$this->registrationService = $registrationService;
|
||||||
$this->loginService = $loginService;
|
$this->loginService = $loginService;
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BookStack\Http\Controllers\Auth;
|
||||||
|
|
||||||
|
use Illuminate\Cache\RateLimiter;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
|
trait ThrottlesLogins
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user has too many failed login attempts.
|
||||||
|
*/
|
||||||
|
protected function hasTooManyLoginAttempts(Request $request): bool
|
||||||
|
{
|
||||||
|
return $this->limiter()->tooManyAttempts(
|
||||||
|
$this->throttleKey($request),
|
||||||
|
$this->maxAttempts()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment the login attempts for the user.
|
||||||
|
*/
|
||||||
|
protected function incrementLoginAttempts(Request $request): void
|
||||||
|
{
|
||||||
|
$this->limiter()->hit(
|
||||||
|
$this->throttleKey($request),
|
||||||
|
$this->decayMinutes() * 60
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect the user after determining they are locked out.
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
protected function sendLockoutResponse(Request $request): \Symfony\Component\HttpFoundation\Response
|
||||||
|
{
|
||||||
|
$seconds = $this->limiter()->availableIn(
|
||||||
|
$this->throttleKey($request)
|
||||||
|
);
|
||||||
|
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
$this->username() => [trans('auth.throttle', [
|
||||||
|
'seconds' => $seconds,
|
||||||
|
'minutes' => ceil($seconds / 60),
|
||||||
|
])],
|
||||||
|
])->status(Response::HTTP_TOO_MANY_REQUESTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the login locks for the given user credentials.
|
||||||
|
*/
|
||||||
|
protected function clearLoginAttempts(Request $request): void
|
||||||
|
{
|
||||||
|
$this->limiter()->clear($this->throttleKey($request));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the throttle key for the given request.
|
||||||
|
*/
|
||||||
|
protected function throttleKey(Request $request): string
|
||||||
|
{
|
||||||
|
return Str::transliterate(Str::lower($request->input($this->username())) . '|' . $request->ip());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the rate limiter instance.
|
||||||
|
*/
|
||||||
|
protected function limiter(): RateLimiter
|
||||||
|
{
|
||||||
|
return app(RateLimiter::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum number of attempts to allow.
|
||||||
|
*/
|
||||||
|
public function maxAttempts(): int
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of minutes to throttle for.
|
||||||
|
*/
|
||||||
|
public function decayMinutes(): int
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ use Exception;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Routing\Redirector;
|
use Illuminate\Routing\Redirector;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Validation\Rules\Password;
|
use Illuminate\Validation\Rules\Password;
|
||||||
|
|
||||||
class UserInviteController extends Controller
|
class UserInviteController extends Controller
|
||||||
|
@ -66,7 +67,7 @@ class UserInviteController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = $this->userRepo->getById($userId);
|
$user = $this->userRepo->getById($userId);
|
||||||
$user->password = bcrypt($request->get('password'));
|
$user->password = Hash::make($request->get('password'));
|
||||||
$user->email_confirmed = true;
|
$user->email_confirmed = true;
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
"laravel/framework": "^8.68",
|
"laravel/framework": "^8.68",
|
||||||
"laravel/socialite": "^5.2",
|
"laravel/socialite": "^5.2",
|
||||||
"laravel/tinker": "^2.6",
|
"laravel/tinker": "^2.6",
|
||||||
"laravel/ui": "^3.3",
|
|
||||||
"league/commonmark": "^1.6",
|
"league/commonmark": "^1.6",
|
||||||
"league/flysystem-aws-s3-v3": "^1.0.29",
|
"league/flysystem-aws-s3-v3": "^1.0.29",
|
||||||
"league/html-to-markdown": "^5.0.0",
|
"league/html-to-markdown": "^5.0.0",
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "1d3bd88b99d07b5410ee4b245bece28e",
|
"content-hash": "01795571047babf7ee6372b7f98843af",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aws/aws-crt-php",
|
"name": "aws/aws-crt-php",
|
||||||
|
@ -2160,67 +2160,6 @@
|
||||||
},
|
},
|
||||||
"time": "2022-03-23T12:38:24+00:00"
|
"time": "2022-03-23T12:38:24+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "laravel/ui",
|
|
||||||
"version": "v3.4.6",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/laravel/ui.git",
|
|
||||||
"reference": "65ec5c03f7fee2c8ecae785795b829a15be48c2c"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/laravel/ui/zipball/65ec5c03f7fee2c8ecae785795b829a15be48c2c",
|
|
||||||
"reference": "65ec5c03f7fee2c8ecae785795b829a15be48c2c",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"illuminate/console": "^8.42|^9.0",
|
|
||||||
"illuminate/filesystem": "^8.42|^9.0",
|
|
||||||
"illuminate/support": "^8.82|^9.0",
|
|
||||||
"illuminate/validation": "^8.42|^9.0",
|
|
||||||
"php": "^7.3|^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"orchestra/testbench": "^6.23|^7.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "3.x-dev"
|
|
||||||
},
|
|
||||||
"laravel": {
|
|
||||||
"providers": [
|
|
||||||
"Laravel\\Ui\\UiServiceProvider"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Laravel\\Ui\\": "src/",
|
|
||||||
"Illuminate\\Foundation\\Auth\\": "auth-backend/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Taylor Otwell",
|
|
||||||
"email": "taylor@laravel.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Laravel UI utilities and presets.",
|
|
||||||
"keywords": [
|
|
||||||
"laravel",
|
|
||||||
"ui"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/laravel/ui/tree/v3.4.6"
|
|
||||||
},
|
|
||||||
"time": "2022-05-20T13:38:08+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "league/commonmark",
|
"name": "league/commonmark",
|
||||||
"version": "1.6.7",
|
"version": "1.6.7",
|
||||||
|
|
Loading…
Reference in New Issue