Dan Brown

Added social sign in

...@@ -22,8 +22,7 @@ class Handler extends ExceptionHandler ...@@ -22,8 +22,7 @@ class Handler extends ExceptionHandler
22 * 22 *
23 * This is a great spot to send exceptions to Sentry, Bugsnag, etc. 23 * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
24 * 24 *
25 - * @param \Exception $e 25 + * @param \Exception $e
26 - * @return void
27 */ 26 */
28 public function report(Exception $e) 27 public function report(Exception $e)
29 { 28 {
...@@ -39,6 +38,11 @@ class Handler extends ExceptionHandler ...@@ -39,6 +38,11 @@ class Handler extends ExceptionHandler
39 */ 38 */
40 public function render($request, Exception $e) 39 public function render($request, Exception $e)
41 { 40 {
41 + if($e instanceof NotifyException) {
42 + \Session::flash('error', $e->message);
43 + return response()->redirectTo($e->redirectLocation);
44 + }
45 +
42 return parent::render($request, $e); 46 return parent::render($request, $e);
43 } 47 }
44 } 48 }
......
1 +<?php namespace Oxbow\Exceptions;
2 +
3 +
4 +class NotifyException extends \Exception
5 +{
6 +
7 + public $message;
8 + public $redirectLocation;
9 +
10 + /**
11 + * NotifyException constructor.
12 + * @param string $message
13 + * @param string $redirectLocation
14 + */
15 + public function __construct($message, $redirectLocation)
16 + {
17 + $this->message = $message;
18 + $this->redirectLocation = $redirectLocation;
19 + parent::__construct();
20 + }
21 +}
...\ No newline at end of file ...\ No newline at end of file
1 +<?php namespace Oxbow\Exceptions;
2 +
3 +
4 +class SocialDriverNotConfigured extends \Exception
5 +{
6 +}
...\ No newline at end of file ...\ No newline at end of file
1 +<?php namespace Oxbow\Exceptions;
2 +
3 +
4 +class UserNotFound extends NotifyException
5 +{
6 +
7 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -2,11 +2,15 @@ ...@@ -2,11 +2,15 @@
2 2
3 namespace Oxbow\Http\Controllers\Auth; 3 namespace Oxbow\Http\Controllers\Auth;
4 4
5 +use Oxbow\Exceptions\SocialDriverNotConfigured;
6 +use Oxbow\Exceptions\UserNotFound;
7 +use Oxbow\Repos\UserRepo;
5 use Oxbow\User; 8 use Oxbow\User;
6 use Validator; 9 use Validator;
7 use Oxbow\Http\Controllers\Controller; 10 use Oxbow\Http\Controllers\Controller;
8 use Illuminate\Foundation\Auth\ThrottlesLogins; 11 use Illuminate\Foundation\Auth\ThrottlesLogins;
9 use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers; 12 use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
13 +use Laravel\Socialite\Contracts\Factory as Socialite;
10 14
11 class AuthController extends Controller 15 class AuthController extends Controller
12 { 16 {
...@@ -27,28 +31,34 @@ class AuthController extends Controller ...@@ -27,28 +31,34 @@ class AuthController extends Controller
27 protected $redirectPath = '/'; 31 protected $redirectPath = '/';
28 protected $redirectAfterLogout = '/login'; 32 protected $redirectAfterLogout = '/login';
29 33
34 + protected $validSocialDrivers = ['google', 'github'];
35 +
36 + protected $socialite;
37 + protected $userRepo;
30 38
31 /** 39 /**
32 * Create a new authentication controller instance. 40 * Create a new authentication controller instance.
33 - * 41 + * @param Socialite $socialite
34 - * @return void 42 + * @param UserRepo $userRepo
35 */ 43 */
36 - public function __construct() 44 + public function __construct(Socialite $socialite, UserRepo $userRepo)
37 { 45 {
38 $this->middleware('guest', ['except' => 'getLogout']); 46 $this->middleware('guest', ['except' => 'getLogout']);
47 + $this->socialite = $socialite;
48 + $this->userRepo = $userRepo;
39 } 49 }
40 50
41 /** 51 /**
42 * Get a validator for an incoming registration request. 52 * Get a validator for an incoming registration request.
43 * 53 *
44 - * @param array $data 54 + * @param array $data
45 * @return \Illuminate\Contracts\Validation\Validator 55 * @return \Illuminate\Contracts\Validation\Validator
46 */ 56 */
47 protected function validator(array $data) 57 protected function validator(array $data)
48 { 58 {
49 return Validator::make($data, [ 59 return Validator::make($data, [
50 - 'name' => 'required|max:255', 60 + 'name' => 'required|max:255',
51 - 'email' => 'required|email|max:255|unique:users', 61 + 'email' => 'required|email|max:255|unique:users',
52 'password' => 'required|confirmed|min:6', 62 'password' => 'required|confirmed|min:6',
53 ]); 63 ]);
54 } 64 }
...@@ -56,15 +66,110 @@ class AuthController extends Controller ...@@ -56,15 +66,110 @@ class AuthController extends Controller
56 /** 66 /**
57 * Create a new user instance after a valid registration. 67 * Create a new user instance after a valid registration.
58 * 68 *
59 - * @param array $data 69 + * @param array $data
60 * @return User 70 * @return User
61 */ 71 */
62 protected function create(array $data) 72 protected function create(array $data)
63 { 73 {
64 return User::create([ 74 return User::create([
65 - 'name' => $data['name'], 75 + 'name' => $data['name'],
66 - 'email' => $data['email'], 76 + 'email' => $data['email'],
67 'password' => bcrypt($data['password']), 77 'password' => bcrypt($data['password']),
68 ]); 78 ]);
69 } 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 + }
70 } 175 }
......
...@@ -82,6 +82,10 @@ Route::group(['middleware' => 'auth'], function () { ...@@ -82,6 +82,10 @@ Route::group(['middleware' => 'auth'], function () {
82 Route::get('/login', 'Auth\AuthController@getLogin'); 82 Route::get('/login', 'Auth\AuthController@getLogin');
83 Route::post('/login', 'Auth\AuthController@postLogin'); 83 Route::post('/login', 'Auth\AuthController@postLogin');
84 Route::get('/logout', 'Auth\AuthController@getLogout'); 84 Route::get('/logout', 'Auth\AuthController@getLogout');
85 +// Login using social authentication
86 +Route::get('/login/service/{socialService}', 'Auth\AuthController@getSocialLogin');
87 +Route::get('/login/service/{socialService}/callback', 'Auth\AuthController@socialCallback');
88 +
85 // Password reset link request routes... 89 // Password reset link request routes...
86 Route::get('/password/email', 'Auth\PasswordController@getEmail'); 90 Route::get('/password/email', 'Auth\PasswordController@getEmail');
87 Route::post('/password/email', 'Auth\PasswordController@postEmail'); 91 Route::post('/password/email', 'Auth\PasswordController@postEmail');
......
1 +<?php namespace Oxbow\Repos;
2 +
3 +
4 +use Oxbow\User;
5 +
6 +class UserRepo
7 +{
8 +
9 + protected $user;
10 +
11 + /**
12 + * UserRepo constructor.
13 + * @param $user
14 + */
15 + public function __construct(User $user)
16 + {
17 + $this->user = $user;
18 + }
19 +
20 +
21 + public function getByEmail($email) {
22 + return $this->user->where('email', '=', $email)->first();
23 + }
24 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
8 "php": ">=5.5.9", 8 "php": ">=5.5.9",
9 "laravel/framework": "5.1.*", 9 "laravel/framework": "5.1.*",
10 "intervention/image": "^2.3", 10 "intervention/image": "^2.3",
11 - "barryvdh/laravel-ide-helper": "^2.1" 11 + "barryvdh/laravel-ide-helper": "^2.1",
12 + "laravel/socialite": "^2.0"
12 }, 13 },
13 "require-dev": { 14 "require-dev": {
14 "fzaninotto/faker": "~1.4", 15 "fzaninotto/faker": "~1.4",
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
4 "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 4 "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 "This file is @generated automatically" 5 "This file is @generated automatically"
6 ], 6 ],
7 - "hash": "16de3a44150d9425a501c9873cb28eaf", 7 + "hash": "7d7e80e9f1c13417c35195f79e41c038",
8 "packages": [ 8 "packages": [
9 { 9 {
10 "name": "barryvdh/laravel-ide-helper", 10 "name": "barryvdh/laravel-ide-helper",
...@@ -280,6 +280,214 @@ ...@@ -280,6 +280,214 @@
280 "time": "2014-12-20 21:24:13" 280 "time": "2014-12-20 21:24:13"
281 }, 281 },
282 { 282 {
283 + "name": "guzzle/guzzle",
284 + "version": "v3.9.3",
285 + "source": {
286 + "type": "git",
287 + "url": "https://github.com/guzzle/guzzle3.git",
288 + "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9"
289 + },
290 + "dist": {
291 + "type": "zip",
292 + "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9",
293 + "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9",
294 + "shasum": ""
295 + },
296 + "require": {
297 + "ext-curl": "*",
298 + "php": ">=5.3.3",
299 + "symfony/event-dispatcher": "~2.1"
300 + },
301 + "replace": {
302 + "guzzle/batch": "self.version",
303 + "guzzle/cache": "self.version",
304 + "guzzle/common": "self.version",
305 + "guzzle/http": "self.version",
306 + "guzzle/inflection": "self.version",
307 + "guzzle/iterator": "self.version",
308 + "guzzle/log": "self.version",
309 + "guzzle/parser": "self.version",
310 + "guzzle/plugin": "self.version",
311 + "guzzle/plugin-async": "self.version",
312 + "guzzle/plugin-backoff": "self.version",
313 + "guzzle/plugin-cache": "self.version",
314 + "guzzle/plugin-cookie": "self.version",
315 + "guzzle/plugin-curlauth": "self.version",
316 + "guzzle/plugin-error-response": "self.version",
317 + "guzzle/plugin-history": "self.version",
318 + "guzzle/plugin-log": "self.version",
319 + "guzzle/plugin-md5": "self.version",
320 + "guzzle/plugin-mock": "self.version",
321 + "guzzle/plugin-oauth": "self.version",
322 + "guzzle/service": "self.version",
323 + "guzzle/stream": "self.version"
324 + },
325 + "require-dev": {
326 + "doctrine/cache": "~1.3",
327 + "monolog/monolog": "~1.0",
328 + "phpunit/phpunit": "3.7.*",
329 + "psr/log": "~1.0",
330 + "symfony/class-loader": "~2.1",
331 + "zendframework/zend-cache": "2.*,<2.3",
332 + "zendframework/zend-log": "2.*,<2.3"
333 + },
334 + "suggest": {
335 + "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated."
336 + },
337 + "type": "library",
338 + "extra": {
339 + "branch-alias": {
340 + "dev-master": "3.9-dev"
341 + }
342 + },
343 + "autoload": {
344 + "psr-0": {
345 + "Guzzle": "src/",
346 + "Guzzle\\Tests": "tests/"
347 + }
348 + },
349 + "notification-url": "https://packagist.org/downloads/",
350 + "license": [
351 + "MIT"
352 + ],
353 + "authors": [
354 + {
355 + "name": "Michael Dowling",
356 + "email": "mtdowling@gmail.com",
357 + "homepage": "https://github.com/mtdowling"
358 + },
359 + {
360 + "name": "Guzzle Community",
361 + "homepage": "https://github.com/guzzle/guzzle/contributors"
362 + }
363 + ],
364 + "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle",
365 + "homepage": "http://guzzlephp.org/",
366 + "keywords": [
367 + "client",
368 + "curl",
369 + "framework",
370 + "http",
371 + "http client",
372 + "rest",
373 + "web service"
374 + ],
375 + "time": "2015-03-18 18:23:50"
376 + },
377 + {
378 + "name": "guzzlehttp/guzzle",
379 + "version": "6.0.2",
380 + "source": {
381 + "type": "git",
382 + "url": "https://github.com/guzzle/guzzle.git",
383 + "reference": "a8dfeff00eb84616a17fea7a4d72af35e750410f"
384 + },
385 + "dist": {
386 + "type": "zip",
387 + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a8dfeff00eb84616a17fea7a4d72af35e750410f",
388 + "reference": "a8dfeff00eb84616a17fea7a4d72af35e750410f",
389 + "shasum": ""
390 + },
391 + "require": {
392 + "guzzlehttp/promises": "~1.0",
393 + "guzzlehttp/psr7": "~1.1",
394 + "php": ">=5.5.0"
395 + },
396 + "require-dev": {
397 + "ext-curl": "*",
398 + "phpunit/phpunit": "~4.0",
399 + "psr/log": "~1.0"
400 + },
401 + "type": "library",
402 + "extra": {
403 + "branch-alias": {
404 + "dev-master": "6.0-dev"
405 + }
406 + },
407 + "autoload": {
408 + "files": [
409 + "src/functions_include.php"
410 + ],
411 + "psr-4": {
412 + "GuzzleHttp\\": "src/"
413 + }
414 + },
415 + "notification-url": "https://packagist.org/downloads/",
416 + "license": [
417 + "MIT"
418 + ],
419 + "authors": [
420 + {
421 + "name": "Michael Dowling",
422 + "email": "mtdowling@gmail.com",
423 + "homepage": "https://github.com/mtdowling"
424 + }
425 + ],
426 + "description": "Guzzle is a PHP HTTP client library",
427 + "homepage": "http://guzzlephp.org/",
428 + "keywords": [
429 + "client",
430 + "curl",
431 + "framework",
432 + "http",
433 + "http client",
434 + "rest",
435 + "web service"
436 + ],
437 + "time": "2015-07-04 20:09:24"
438 + },
439 + {
440 + "name": "guzzlehttp/promises",
441 + "version": "1.0.2",
442 + "source": {
443 + "type": "git",
444 + "url": "https://github.com/guzzle/promises.git",
445 + "reference": "97fe7210def29451ec74923b27e552238defd75a"
446 + },
447 + "dist": {
448 + "type": "zip",
449 + "url": "https://api.github.com/repos/guzzle/promises/zipball/97fe7210def29451ec74923b27e552238defd75a",
450 + "reference": "97fe7210def29451ec74923b27e552238defd75a",
451 + "shasum": ""
452 + },
453 + "require": {
454 + "php": ">=5.5.0"
455 + },
456 + "require-dev": {
457 + "phpunit/phpunit": "~4.0"
458 + },
459 + "type": "library",
460 + "extra": {
461 + "branch-alias": {
462 + "dev-master": "1.0-dev"
463 + }
464 + },
465 + "autoload": {
466 + "psr-4": {
467 + "GuzzleHttp\\Promise\\": "src/"
468 + },
469 + "files": [
470 + "src/functions_include.php"
471 + ]
472 + },
473 + "notification-url": "https://packagist.org/downloads/",
474 + "license": [
475 + "MIT"
476 + ],
477 + "authors": [
478 + {
479 + "name": "Michael Dowling",
480 + "email": "mtdowling@gmail.com",
481 + "homepage": "https://github.com/mtdowling"
482 + }
483 + ],
484 + "description": "Guzzle promises library",
485 + "keywords": [
486 + "promise"
487 + ],
488 + "time": "2015-08-15 19:37:21"
489 + },
490 + {
283 "name": "guzzlehttp/psr7", 491 "name": "guzzlehttp/psr7",
284 "version": "1.2.0", 492 "version": "1.2.0",
285 "source": { 493 "source": {
...@@ -673,6 +881,60 @@ ...@@ -673,6 +881,60 @@
673 "time": "2015-08-12 18:16:08" 881 "time": "2015-08-12 18:16:08"
674 }, 882 },
675 { 883 {
884 + "name": "laravel/socialite",
885 + "version": "v2.0.12",
886 + "source": {
887 + "type": "git",
888 + "url": "https://github.com/laravel/socialite.git",
889 + "reference": "0bb08c8666f4c01e55e3b3b0e42f2b5075be6a6e"
890 + },
891 + "dist": {
892 + "type": "zip",
893 + "url": "https://api.github.com/repos/laravel/socialite/zipball/0bb08c8666f4c01e55e3b3b0e42f2b5075be6a6e",
894 + "reference": "0bb08c8666f4c01e55e3b3b0e42f2b5075be6a6e",
895 + "shasum": ""
896 + },
897 + "require": {
898 + "guzzlehttp/guzzle": "~5.0|~6.0",
899 + "illuminate/contracts": "~5.0",
900 + "illuminate/http": "~5.0",
901 + "illuminate/support": "~5.0",
902 + "league/oauth1-client": "~1.0",
903 + "php": ">=5.4.0"
904 + },
905 + "require-dev": {
906 + "mockery/mockery": "~0.9",
907 + "phpunit/phpunit": "~4.0"
908 + },
909 + "type": "library",
910 + "extra": {
911 + "branch-alias": {
912 + "dev-master": "3.0-dev"
913 + }
914 + },
915 + "autoload": {
916 + "psr-4": {
917 + "Laravel\\Socialite\\": "src/"
918 + }
919 + },
920 + "notification-url": "https://packagist.org/downloads/",
921 + "license": [
922 + "MIT"
923 + ],
924 + "authors": [
925 + {
926 + "name": "Taylor Otwell",
927 + "email": "taylorotwell@gmail.com"
928 + }
929 + ],
930 + "description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.",
931 + "keywords": [
932 + "laravel",
933 + "oauth"
934 + ],
935 + "time": "2015-08-30 01:12:56"
936 + },
937 + {
676 "name": "league/flysystem", 938 "name": "league/flysystem",
677 "version": "1.0.11", 939 "version": "1.0.11",
678 "source": { 940 "source": {
...@@ -754,6 +1016,69 @@ ...@@ -754,6 +1016,69 @@
754 "time": "2015-07-28 20:41:58" 1016 "time": "2015-07-28 20:41:58"
755 }, 1017 },
756 { 1018 {
1019 + "name": "league/oauth1-client",
1020 + "version": "1.6.0",
1021 + "source": {
1022 + "type": "git",
1023 + "url": "https://github.com/thephpleague/oauth1-client.git",
1024 + "reference": "4d4edd9b6014f882e319231a9b3351e3a1dfdc81"
1025 + },
1026 + "dist": {
1027 + "type": "zip",
1028 + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/4d4edd9b6014f882e319231a9b3351e3a1dfdc81",
1029 + "reference": "4d4edd9b6014f882e319231a9b3351e3a1dfdc81",
1030 + "shasum": ""
1031 + },
1032 + "require": {
1033 + "guzzle/guzzle": "3.*",
1034 + "php": ">=5.3.0"
1035 + },
1036 + "require-dev": {
1037 + "mockery/mockery": "~0.9",
1038 + "phpunit/phpunit": "~4.0",
1039 + "squizlabs/php_codesniffer": "~2.0"
1040 + },
1041 + "type": "library",
1042 + "extra": {
1043 + "branch-alias": {
1044 + "dev-master": "1.0-dev"
1045 + }
1046 + },
1047 + "autoload": {
1048 + "psr-4": {
1049 + "League\\OAuth1\\": "src/"
1050 + }
1051 + },
1052 + "notification-url": "https://packagist.org/downloads/",
1053 + "license": [
1054 + "MIT"
1055 + ],
1056 + "authors": [
1057 + {
1058 + "name": "Ben Corlett",
1059 + "email": "bencorlett@me.com",
1060 + "homepage": "http://www.webcomm.com.au",
1061 + "role": "Developer"
1062 + }
1063 + ],
1064 + "description": "OAuth 1.0 Client Library",
1065 + "keywords": [
1066 + "Authentication",
1067 + "SSO",
1068 + "authorization",
1069 + "bitbucket",
1070 + "identity",
1071 + "idp",
1072 + "oauth",
1073 + "oauth1",
1074 + "single sign on",
1075 + "trello",
1076 + "tumblr",
1077 + "twitter"
1078 + ],
1079 + "time": "2015-08-22 09:49:14"
1080 + },
1081 + {
757 "name": "monolog/monolog", 1082 "name": "monolog/monolog",
758 "version": "1.16.0", 1083 "version": "1.16.0",
759 "source": { 1084 "source": {
......
...@@ -26,7 +26,7 @@ return [ ...@@ -26,7 +26,7 @@ return [
26 | 26 |
27 */ 27 */
28 28
29 - 'url' => 'http://localhost', 29 + 'url' => env('APP_URL', 'http://localhost'),
30 30
31 /* 31 /*
32 |-------------------------------------------------------------------------- 32 |--------------------------------------------------------------------------
...@@ -136,6 +136,7 @@ return [ ...@@ -136,6 +136,7 @@ return [
136 Illuminate\Translation\TranslationServiceProvider::class, 136 Illuminate\Translation\TranslationServiceProvider::class,
137 Illuminate\Validation\ValidationServiceProvider::class, 137 Illuminate\Validation\ValidationServiceProvider::class,
138 Illuminate\View\ViewServiceProvider::class, 138 Illuminate\View\ViewServiceProvider::class,
139 + Laravel\Socialite\SocialiteServiceProvider::class,
139 140
140 /** 141 /**
141 * Third Party 142 * Third Party
...@@ -199,6 +200,7 @@ return [ ...@@ -199,6 +200,7 @@ return [
199 'URL' => Illuminate\Support\Facades\URL::class, 200 'URL' => Illuminate\Support\Facades\URL::class,
200 'Validator' => Illuminate\Support\Facades\Validator::class, 201 'Validator' => Illuminate\Support\Facades\Validator::class,
201 'View' => Illuminate\Support\Facades\View::class, 202 'View' => Illuminate\Support\Facades\View::class,
203 + 'Socialite' => Laravel\Socialite\Facades\Socialite::class,
202 204
203 /** 205 /**
204 * Third Party 206 * Third Party
......
...@@ -14,7 +14,7 @@ return [ ...@@ -14,7 +14,7 @@ return [
14 | 14 |
15 */ 15 */
16 16
17 - 'mailgun' => [ 17 + 'mailgun' => [
18 'domain' => '', 18 'domain' => '',
19 'secret' => '', 19 'secret' => '',
20 ], 20 ],
...@@ -23,16 +23,28 @@ return [ ...@@ -23,16 +23,28 @@ return [
23 'secret' => '', 23 'secret' => '',
24 ], 24 ],
25 25
26 - 'ses' => [ 26 + 'ses' => [
27 'key' => '', 27 'key' => '',
28 'secret' => '', 28 'secret' => '',
29 'region' => 'us-east-1', 29 'region' => 'us-east-1',
30 ], 30 ],
31 31
32 - 'stripe' => [ 32 + 'stripe' => [
33 'model' => Oxbow\User::class, 33 'model' => Oxbow\User::class,
34 'key' => '', 34 'key' => '',
35 'secret' => '', 35 'secret' => '',
36 ], 36 ],
37 37
38 + 'github' => [
39 + 'client_id' => env('GITHUB_APP_ID', false),
40 + 'client_secret' => env('GITHUB_APP_SECRET', false),
41 + 'redirect' => env('APP_URL') . '/login/service/github/callback',
42 + ],
43 +
44 + 'google' => [
45 + 'client_id' => env('GOOGLE_APP_ID', false),
46 + 'client_secret' => env('GOOGLE_APP_SECRET', false),
47 + 'redirect' => env('APP_URL') . '/login/service/google/callback',
48 + ],
49 +
38 ]; 50 ];
......
...@@ -3,6 +3,7 @@ $(function () { ...@@ -3,6 +3,7 @@ $(function () {
3 // Notification hiding 3 // Notification hiding
4 $('.notification').click(function () { 4 $('.notification').click(function () {
5 $(this).fadeOut(100); 5 $(this).fadeOut(100);
6 +
6 }); 7 });
7 8
8 // Dropdown toggles 9 // Dropdown toggles
......
...@@ -42,6 +42,9 @@ ...@@ -42,6 +42,9 @@
42 animation-duration: 3s; 42 animation-duration: 3s;
43 animation-timing-function: ease-in-out; 43 animation-timing-function: ease-in-out;
44 animation-fill-mode: forwards; 44 animation-fill-mode: forwards;
45 + &.stopped {
46 + animation-name: notificationStopped;
47 + }
45 } 48 }
46 49
47 @keyframes notification { 50 @keyframes notification {
...@@ -58,6 +61,17 @@ ...@@ -58,6 +61,17 @@
58 transform: translate3d(580px, 0, 0); 61 transform: translate3d(580px, 0, 0);
59 } 62 }
60 } 63 }
64 +@keyframes notificationStopped {
65 + 0% {
66 + transform: translate3d(580px, 0, 0);
67 + }
68 + 10% {
69 + transform: translate3d(0, 0, 0);
70 + }
71 + 100% {
72 + transform: translate3d(0, 0, 0);
73 + }
74 +}
61 75
62 @keyframes menuIn { 76 @keyframes menuIn {
63 from { 77 from {
......
...@@ -30,7 +30,6 @@ $button-border-radius: 2px; ...@@ -30,7 +30,6 @@ $button-border-radius: 2px;
30 border-radius: $button-border-radius; 30 border-radius: $button-border-radius;
31 cursor: pointer; 31 cursor: pointer;
32 transition: all ease-in-out 120ms; 32 transition: all ease-in-out 120ms;
33 - text-transform: uppercase;
34 box-shadow: 0 0.5px 1.5px 0 rgba(0, 0, 0, 0.21); 33 box-shadow: 0 0.5px 1.5px 0 rgba(0, 0, 0, 0.21);
35 @include generate-button-colors(#EEE, $primary); 34 @include generate-button-colors(#EEE, $primary);
36 } 35 }
......
1 @extends('public') 1 @extends('public')
2 2
3 -@section('sidebar') 3 +@section('content')
4 4
5 <div class="center-box"> 5 <div class="center-box">
6 <h1>Log In</h1> 6 <h1>Log In</h1>
...@@ -23,6 +23,16 @@ ...@@ -23,6 +23,16 @@
23 <button class="button block pos">Sign In</button> 23 <button class="button block pos">Sign In</button>
24 </div> 24 </div>
25 </form> 25 </form>
26 + @if(count($socialDrivers) > 0)
27 + <hr class="margin-top">
28 + <h3 class="text-muted">Social Login</h3>
29 + @if(isset($socialDrivers['google']))
30 + <a href="/login/service/google" style="color: #DC4E41;"><i class="zmdi zmdi-google-plus-box zmdi-hc-4x"></i></a>
31 + @endif
32 + @if(isset($socialDrivers['github']))
33 + <a href="/login/service/github" style="color:#000;"><i class="zmdi zmdi-github zmdi-hc-4x"></i></a>
34 + @endif
35 + @endif
26 </div> 36 </div>
27 37
28 @stop 38 @stop
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 2
3 @section('body-class', 'image-cover login') 3 @section('body-class', 'image-cover login')
4 4
5 -@section('sidebar') 5 +@section('content')
6 6
7 7
8 <div class="text-center"> 8 <div class="text-center">
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 2
3 @section('body-class', 'image-cover login') 3 @section('body-class', 'image-cover login')
4 4
5 -@section('sidebar') 5 +@section('content')
6 6
7 7
8 <div class="text-center"> 8 <div class="text-center">
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
31 @endif 31 @endif
32 32
33 @if(Session::has('error')) 33 @if(Session::has('error'))
34 - <div class="notification anim neg"> 34 + <div class="notification anim neg stopped">
35 <i class="zmdi zmdi-alert-circle"></i> <span>{{ Session::get('error') }}</span> 35 <i class="zmdi zmdi-alert-circle"></i> <span>{{ Session::get('error') }}</span>
36 </div> 36 </div>
37 @endif 37 @endif
......
...@@ -6,14 +6,25 @@ ...@@ -6,14 +6,25 @@
6 <link rel="stylesheet" href="/css/app.css"> 6 <link rel="stylesheet" href="/css/app.css">
7 <link href='//fonts.googleapis.com/css?family=Roboto:400,400italic,500,500italic,700,700italic,300italic,100,300' rel='stylesheet' type='text/css'> 7 <link href='//fonts.googleapis.com/css?family=Roboto:400,400italic,500,500italic,700,700italic,300italic,100,300' rel='stylesheet' type='text/css'>
8 <link rel="stylesheet" href="/bower/material-design-iconic-font/dist/css/material-design-iconic-font.min.css"> 8 <link rel="stylesheet" href="/bower/material-design-iconic-font/dist/css/material-design-iconic-font.min.css">
9 +
10 + <!-- Scripts -->
9 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> 11 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
12 + <script src="/js/common.js"></script>
10 13
11 </head> 14 </head>
12 <body class="@yield('body-class')"> 15 <body class="@yield('body-class')">
13 16
14 -<section id="sidebar"> 17 +@if(Session::has('success'))
15 - @yield('sidebar') 18 + <div class="notification anim pos">
16 -</section> 19 + <i class="zmdi zmdi-mood"></i> <span>{{ Session::get('success') }}</span>
20 + </div>
21 +@endif
22 +
23 +@if(Session::has('error'))
24 + <div class="notification anim neg stopped">
25 + <i class="zmdi zmdi-alert-circle"></i> <span>{{ Session::get('error') }}</span>
26 + </div>
27 +@endif
17 28
18 <section class="container"> 29 <section class="container">
19 @yield('content') 30 @yield('content')
......
...@@ -8,18 +8,18 @@ ...@@ -8,18 +8,18 @@
8 @include('form/text', ['name' => 'email']) 8 @include('form/text', ['name' => 'email'])
9 </div> 9 </div>
10 10
11 -@if(isset($model)) 11 +@if($currentUser->can('user-update'))
12 <div class="form-group"> 12 <div class="form-group">
13 - <span class="text-muted"> 13 + <label for="role">User Role</label>
14 - Only fill the below if you would like <br>to change your password: 14 + @include('form.role-select', ['name' => 'role', 'options' => \Oxbow\Role::all(), 'displayKey' => 'display_name'])
15 - </span>
16 </div> 15 </div>
17 @endif 16 @endif
18 17
19 -@if($currentUser->can('user-update')) 18 +@if(isset($model))
20 <div class="form-group"> 19 <div class="form-group">
21 - <label for="role">User Role</label> 20 + <span class="text-muted">
22 - @include('form.role-select', ['name' => 'role', 'options' => \Oxbow\Role::all(), 'displayKey' => 'display_name']) 21 + Only fill the below if you would like <br>to change your password:
22 + </span>
23 </div> 23 </div>
24 @endif 24 @endif
25 25
......