]> BookStack Code Mirror - bookstack/blobdiff - app/Http/Controllers/Auth/LoginController.php
Update settings.php
[bookstack] / app / Http / Controllers / Auth / LoginController.php
index 08b1bce679a433191148ac6db1abf878480f9279..4660c16d5e9b47899595d47cf35b48cc51cabc47 100644 (file)
@@ -2,13 +2,11 @@
 
 namespace BookStack\Http\Controllers\Auth;
 
-use BookStack\Exceptions\AuthException;
+use BookStack\Auth\Access\SocialAuthService;
+use BookStack\Exceptions\LoginAttemptEmailNeededException;
+use BookStack\Exceptions\LoginAttemptException;
+use BookStack\Exceptions\UserRegistrationException;
 use BookStack\Http\Controllers\Controller;
-use BookStack\Repos\UserRepo;
-use BookStack\Repos\LdapRepo;
-use BookStack\Services\LdapService;
-use BookStack\Services\SocialAuthService;
-use Illuminate\Contracts\Auth\Authenticatable;
 use Illuminate\Foundation\Auth\AuthenticatesUsers;
 use Illuminate\Http\Request;
 
@@ -28,31 +26,25 @@ class LoginController extends Controller
     use AuthenticatesUsers;
 
     /**
-     * Where to redirect users after login.
-     *
-     * @var string
+     * Redirection paths
      */
     protected $redirectTo = '/';
-
     protected $redirectPath = '/';
     protected $redirectAfterLogout = '/login';
 
     protected $socialAuthService;
-    protected $userRepo;
 
     /**
      * Create a new controller instance.
-     *
-     * @param SocialAuthService $socialAuthService
-     * @param UserRepo $userRepo
      */
-    public function __construct(SocialAuthService $socialAuthService, UserRepo $userRepo)
+    public function __construct(SocialAuthService $socialAuthService)
     {
-        $this->middleware('guest', ['only' => ['getLogin', 'postLogin']]);
+        $this->middleware('guest', ['only' => ['getLogin', 'login']]);
+        $this->middleware('guard:standard,ldap', ['only' => ['login', 'logout']]);
+
         $this->socialAuthService = $socialAuthService;
-        $this->userRepo = $userRepo;
-        $this->redirectPath = baseUrl('/');
-        $this->redirectAfterLogout = baseUrl('/login');
+        $this->redirectPath = url('/');
+        $this->redirectAfterLogout = url('/login');
         parent::__construct();
     }
 
@@ -62,82 +54,117 @@ class LoginController extends Controller
     }
 
     /**
-     * Overrides the action when a user is authenticated.
-     * If the user authenticated but does not exist in the user table we create them.
-     * @param Request $request
-     * @param Authenticatable $user
-     * @return \Illuminate\Http\RedirectResponse
-     * @throws AuthException
+     * Get the needed authorization credentials from the request.
      */
-    protected function authenticated(Request $request, Authenticatable $user)
+    protected function credentials(Request $request)
     {
-        // Explicitly log them out for now if they do no exist.
-        if (!$user->exists) {
-            auth()->logout($user);
-        }
+        return $request->only('username', 'email', 'password');
+    }
 
-        if (!$user->exists && $user->email === null && !$request->filled('email')) {
-            $request->flash();
-            session()->flash('request-email', true);
-            return redirect('/login');
+    /**
+     * Show the application login form.
+     */
+    public function getLogin(Request $request)
+    {
+        $socialDrivers = $this->socialAuthService->getActiveDrivers();
+        $authMethod = config('auth.method');
+
+        if ($request->has('email')) {
+            session()->flashInput([
+                'email' => $request->get('email'),
+                'password' => (config('app.env') === 'demo') ? $request->get('password', '') : ''
+            ]);
         }
 
-        if (!$user->exists && $user->email === null && $request->filled('email')) {
-            $user->email = $request->get('email');
+        $previous = url()->previous('');
+        if (setting('app-public') && $previous && $previous !== url('/login')) {
+            redirect()->setIntendedUrl($previous);
         }
 
-        if (!$user->exists) {
-            // Check for users with same email already
-            $alreadyUser = $user->newQuery()->where('email', '=', $user->email)->count() > 0;
-            if ($alreadyUser) {
-                throw new AuthException(trans('errors.error_user_exists_different_creds', ['email' => $user->email]));
-            }
+        return view('auth.login', [
+          'socialDrivers' => $socialDrivers,
+          'authMethod' => $authMethod,
+        ]);
+    }
+
+    /**
+     * Handle a login request to the application.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
+     *
+     * @throws \Illuminate\Validation\ValidationException
+     */
+    public function login(Request $request)
+    {
+        $this->validateLogin($request);
 
-            $user->save();
-            $this->userRepo->attachDefaultRole($user);
-            auth()->login($user);
+        // If the class is using the ThrottlesLogins trait, we can automatically throttle
+        // the login attempts for this application. We'll key this by the username and
+        // the IP address of the client making these requests into this application.
+        if (method_exists($this, 'hasTooManyLoginAttempts') &&
+            $this->hasTooManyLoginAttempts($request)) {
+            $this->fireLockoutEvent($request);
+
+            return $this->sendLockoutResponse($request);
         }
 
-        // ldap groups refresh
-        if (config('services.ldap.user_to_groups') !== false && $request->filled('username')) {
-            $ldapRepo = new LdapRepo($this->userRepo, app(LdapService::class));
-            $ldapRepo->syncGroups($user, $request->input('username'));
+        try {
+            if ($this->attemptLogin($request)) {
+                return $this->sendLoginResponse($request);
+            }
+        } catch (LoginAttemptException $exception) {
+            return $this->sendLoginAttemptExceptionResponse($exception, $request);
         }
 
+        // If the login attempt was unsuccessful we will increment the number of attempts
+        // 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);
 
-        $path = session()->pull('url.intended', '/');
-        $path = baseUrl($path, true);
-        return redirect($path);
+        return $this->sendFailedLoginResponse($request);
     }
 
     /**
-     * Show the application login form.
-     * @param Request $request
-     * @return \Illuminate\Http\Response
+     * Validate the user login request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return void
+     *
+     * @throws \Illuminate\Validation\ValidationException
      */
-    public function getLogin(Request $request)
+    protected function validateLogin(Request $request)
     {
-        $socialDrivers = $this->socialAuthService->getActiveDrivers();
+        $rules = ['password' => 'required|string'];
         $authMethod = config('auth.method');
 
-        if ($request->has('email')) {
-            session()->flashInput([
-                'email' => $request->get('email'),
-                'password' => (config('app.env') === 'demo') ? $request->get('password', '') : ''
-            ]);
+        if ($authMethod === 'standard') {
+            $rules['email'] = 'required|email';
         }
 
-        return view('auth/login', ['socialDrivers' => $socialDrivers, 'authMethod' => $authMethod]);
+        if ($authMethod === 'ldap') {
+            $rules['username'] = 'required|string';
+            $rules['email'] = 'email';
+        }
+
+        $request->validate($rules);
     }
 
     /**
-     * Redirect to the relevant social site.
-     * @param $socialDriver
-     * @return \Symfony\Component\HttpFoundation\RedirectResponse
+     * Send a response when a login attempt exception occurs.
      */
-    public function getSocialLogin($socialDriver)
+    protected function sendLoginAttemptExceptionResponse(LoginAttemptException $exception, Request $request)
     {
-        session()->put('social-callback', 'login');
-        return $this->socialAuthService->startLogIn($socialDriver);
+        if ($exception instanceof LoginAttemptEmailNeededException) {
+            $request->flash();
+            session()->flash('request-email', true);
+        }
+
+        if ($message = $exception->getMessage()) {
+            $this->showWarningNotification($message);
+        }
+
+        return redirect('/login');
     }
+
 }