]> BookStack Code Mirror - bookstack/blobdiff - app/Http/Controllers/Auth/AuthController.php
Added social sign in
[bookstack] / app / Http / Controllers / Auth / AuthController.php
index 11f68fb983ba4b945bdcc2bd90adaf01a36cfe2e..eacbe2bb906d7c092ae327f1b6844d3810dd9904 100644 (file)
@@ -2,11 +2,15 @@
 
 namespace Oxbow\Http\Controllers\Auth;
 
+use Oxbow\Exceptions\SocialDriverNotConfigured;
+use Oxbow\Exceptions\UserNotFound;
+use Oxbow\Repos\UserRepo;
 use Oxbow\User;
 use Validator;
 use Oxbow\Http\Controllers\Controller;
 use Illuminate\Foundation\Auth\ThrottlesLogins;
 use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
+use Laravel\Socialite\Contracts\Factory as Socialite;
 
 class AuthController extends Controller
 {
@@ -27,28 +31,34 @@ class AuthController extends Controller
     protected $redirectPath = '/';
     protected $redirectAfterLogout = '/login';
 
+    protected $validSocialDrivers = ['google', 'github'];
+
+    protected $socialite;
+    protected $userRepo;
 
     /**
      * Create a new authentication controller instance.
-     *
-     * @return void
+     * @param Socialite $socialite
+     * @param UserRepo  $userRepo
      */
-    public function __construct()
+    public function __construct(Socialite $socialite, UserRepo $userRepo)
     {
         $this->middleware('guest', ['except' => 'getLogout']);
+        $this->socialite = $socialite;
+        $this->userRepo = $userRepo;
     }
 
     /**
      * Get a validator for an incoming registration request.
      *
-     * @param  array  $data
+     * @param  array $data
      * @return \Illuminate\Contracts\Validation\Validator
      */
     protected function validator(array $data)
     {
         return Validator::make($data, [
-            'name' => 'required|max:255',
-            'email' => 'required|email|max:255|unique:users',
+            'name'     => 'required|max:255',
+            'email'    => 'required|email|max:255|unique:users',
             'password' => 'required|confirmed|min:6',
         ]);
     }
@@ -56,15 +66,110 @@ class AuthController extends Controller
     /**
      * Create a new user instance after a valid registration.
      *
-     * @param  array  $data
+     * @param  array $data
      * @return User
      */
     protected function create(array $data)
     {
         return User::create([
-            'name' => $data['name'],
-            'email' => $data['email'],
+            'name'     => $data['name'],
+            'email'    => $data['email'],
             'password' => bcrypt($data['password']),
         ]);
     }
+
+    /**
+     * Show the application login form.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function getLogin()
+    {
+
+        if (view()->exists('auth.authenticate')) {
+            return view('auth.authenticate');
+        }
+
+        $socialDrivers = $this->getActiveSocialDrivers();
+
+        return view('auth.login', ['socialDrivers' => $socialDrivers]);
+    }
+
+    /**
+     * Redirect to the relevant social site.
+     * @param $socialDriver
+     * @return \Symfony\Component\HttpFoundation\RedirectResponse
+     */
+    public function getSocialLogin($socialDriver)
+    {
+        $driver = $this->validateSocialDriver($socialDriver);
+        return $this->socialite->driver($driver)->redirect();
+    }
+
+    /**
+     * The callback for social login services.
+     *
+     * @param $socialDriver
+     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
+     * @throws UserNotFound
+     */
+    public function socialCallback($socialDriver)
+    {
+        $driver = $this->validateSocialDriver($socialDriver);
+        // Get user details from social driver
+        $socialUser = $this->socialite->driver($driver)->user();
+        $user = $this->userRepo->getByEmail($socialUser->getEmail());
+
+        // Redirect if the email is not a current user.
+        if ($user === null) {
+            throw new UserNotFound('A user with the email ' . $socialUser->getEmail() . ' was not found.', '/login');
+        }
+
+        \Auth::login($user, true);
+        return redirect($this->redirectPath);
+    }
+
+    /**
+     * Ensure the social driver is correct and supported.
+     *
+     * @param $socialDriver
+     * @return string
+     * @throws SocialDriverNotConfigured
+     */
+    protected function validateSocialDriver($socialDriver)
+    {
+        $driver = trim(strtolower($socialDriver));
+
+        if (!in_array($driver, $this->validSocialDrivers)) abort(404, 'Social Driver Not Found');
+        if(!$this->checkSocialDriverConfigured($driver)) throw new SocialDriverNotConfigured;
+
+        return $driver;
+    }
+
+    /**
+     * Check a social driver has been configured correctly.
+     * @param $driver
+     * @return bool
+     */
+    protected function checkSocialDriverConfigured($driver)
+    {
+        $upperName = strtoupper($driver);
+        $config = [env($upperName . '_APP_ID', false), env($upperName . '_APP_SECRET', false), env('APP_URL', false)];
+        return (!in_array(false, $config) && !in_array(null, $config));
+    }
+
+    /**
+     * Gets the names of the active social drivers.
+     * @return array
+     */
+    protected function getActiveSocialDrivers()
+    {
+        $activeDrivers = [];
+        foreach($this->validSocialDrivers as $driverName) {
+            if($this->checkSocialDriverConfigured($driverName)) {
+                $activeDrivers[$driverName] = true;
+            }
+        }
+        return $activeDrivers;
+    }
 }