]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/Auth/AuthController.php
Added social sign in
[bookstack] / app / Http / Controllers / Auth / AuthController.php
1 <?php
2
3 namespace Oxbow\Http\Controllers\Auth;
4
5 use Oxbow\Exceptions\SocialDriverNotConfigured;
6 use Oxbow\Exceptions\UserNotFound;
7 use Oxbow\Repos\UserRepo;
8 use Oxbow\User;
9 use Validator;
10 use Oxbow\Http\Controllers\Controller;
11 use Illuminate\Foundation\Auth\ThrottlesLogins;
12 use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
13 use Laravel\Socialite\Contracts\Factory as Socialite;
14
15 class AuthController extends Controller
16 {
17     /*
18     |--------------------------------------------------------------------------
19     | Registration & Login Controller
20     |--------------------------------------------------------------------------
21     |
22     | This controller handles the registration of new users, as well as the
23     | authentication of existing users. By default, this controller uses
24     | a simple trait to add these behaviors. Why don't you explore it?
25     |
26     */
27
28     use AuthenticatesAndRegistersUsers, ThrottlesLogins;
29
30     protected $loginPath = '/login';
31     protected $redirectPath = '/';
32     protected $redirectAfterLogout = '/login';
33
34     protected $validSocialDrivers = ['google', 'github'];
35
36     protected $socialite;
37     protected $userRepo;
38
39     /**
40      * Create a new authentication controller instance.
41      * @param Socialite $socialite
42      * @param UserRepo  $userRepo
43      */
44     public function __construct(Socialite $socialite, UserRepo $userRepo)
45     {
46         $this->middleware('guest', ['except' => 'getLogout']);
47         $this->socialite = $socialite;
48         $this->userRepo = $userRepo;
49     }
50
51     /**
52      * Get a validator for an incoming registration request.
53      *
54      * @param  array $data
55      * @return \Illuminate\Contracts\Validation\Validator
56      */
57     protected function validator(array $data)
58     {
59         return Validator::make($data, [
60             'name'     => 'required|max:255',
61             'email'    => 'required|email|max:255|unique:users',
62             'password' => 'required|confirmed|min:6',
63         ]);
64     }
65
66     /**
67      * Create a new user instance after a valid registration.
68      *
69      * @param  array $data
70      * @return User
71      */
72     protected function create(array $data)
73     {
74         return User::create([
75             'name'     => $data['name'],
76             'email'    => $data['email'],
77             'password' => bcrypt($data['password']),
78         ]);
79     }
80
81     /**
82      * Show the application login form.
83      *
84      * @return \Illuminate\Http\Response
85      */
86     public function getLogin()
87     {
88
89         if (view()->exists('auth.authenticate')) {
90             return view('auth.authenticate');
91         }
92
93         $socialDrivers = $this->getActiveSocialDrivers();
94
95         return view('auth.login', ['socialDrivers' => $socialDrivers]);
96     }
97
98     /**
99      * Redirect to the relevant social site.
100      * @param $socialDriver
101      * @return \Symfony\Component\HttpFoundation\RedirectResponse
102      */
103     public function getSocialLogin($socialDriver)
104     {
105         $driver = $this->validateSocialDriver($socialDriver);
106         return $this->socialite->driver($driver)->redirect();
107     }
108
109     /**
110      * The callback for social login services.
111      *
112      * @param $socialDriver
113      * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
114      * @throws UserNotFound
115      */
116     public function socialCallback($socialDriver)
117     {
118         $driver = $this->validateSocialDriver($socialDriver);
119         // Get user details from social driver
120         $socialUser = $this->socialite->driver($driver)->user();
121         $user = $this->userRepo->getByEmail($socialUser->getEmail());
122
123         // Redirect if the email is not a current user.
124         if ($user === null) {
125             throw new UserNotFound('A user with the email ' . $socialUser->getEmail() . ' was not found.', '/login');
126         }
127
128         \Auth::login($user, true);
129         return redirect($this->redirectPath);
130     }
131
132     /**
133      * Ensure the social driver is correct and supported.
134      *
135      * @param $socialDriver
136      * @return string
137      * @throws SocialDriverNotConfigured
138      */
139     protected function validateSocialDriver($socialDriver)
140     {
141         $driver = trim(strtolower($socialDriver));
142
143         if (!in_array($driver, $this->validSocialDrivers)) abort(404, 'Social Driver Not Found');
144         if(!$this->checkSocialDriverConfigured($driver)) throw new SocialDriverNotConfigured;
145
146         return $driver;
147     }
148
149     /**
150      * Check a social driver has been configured correctly.
151      * @param $driver
152      * @return bool
153      */
154     protected function checkSocialDriverConfigured($driver)
155     {
156         $upperName = strtoupper($driver);
157         $config = [env($upperName . '_APP_ID', false), env($upperName . '_APP_SECRET', false), env('APP_URL', false)];
158         return (!in_array(false, $config) && !in_array(null, $config));
159     }
160
161     /**
162      * Gets the names of the active social drivers.
163      * @return array
164      */
165     protected function getActiveSocialDrivers()
166     {
167         $activeDrivers = [];
168         foreach($this->validSocialDrivers as $driverName) {
169             if($this->checkSocialDriverConfigured($driverName)) {
170                 $activeDrivers[$driverName] = true;
171             }
172         }
173         return $activeDrivers;
174     }
175 }