diff --git a/app/Constants.php b/app/Constants.php index d6e88a1750..397527a076 100644 --- a/app/Constants.php +++ b/app/Constants.php @@ -22,8 +22,13 @@ if (! defined('APP_NAME')) { define('TEST_CLIENTNAME', env('TEST_CLIENTNAME', 'client@example.com')); define('TEST_PASSWORD', 'password'); - - define('BANK_LIBRARY_OFX', 1); define('MULTI_DBS', serialize(['db-ninja-1', 'db-ninja-2'])); + + define('SOCIAL_GOOGLE', 'Google'); + define('SOCIAL_FACEBOOK', 'Facebook'); + define('SOCIAL_GITHUB', 'GitHub'); + define('SOCIAL_LINKEDIN', 'LinkedIn'); + define('SOCIAL_TWITTER', 'Twitter'); + define('SOCIAL_BITBUCKET', 'Bitbucket'); } \ No newline at end of file diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index e99476a058..e29bc2076c 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; +use Laravel\Socialite\Facades\Socialite; class LoginController extends Controller { @@ -36,4 +37,16 @@ class LoginController extends Controller { $this->middleware('guest:user')->except('logout'); } + + public function redirectToProvider($provider) + { + return Socialite::driver($provider)->redirect(); + } + + public function handleProviderCallback($provider) + { + $user = Socialite::driver('github')->user(); + + dd($user); + } } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 42fecc65c6..7afb0c4a03 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -2,8 +2,6 @@ namespace App\Http\Controllers; -use App\Http\Requests\SignupRequest; - class HomeController extends Controller { /** @@ -33,14 +31,5 @@ class HomeController extends Controller return view('dashboard.index'); } - public function signup() - { - return view('signup.index'); - } - - public function processSignup(SignupRequest $request) - { - dd($request->validated()); - } } diff --git a/app/Http/Controllers/SignupController.php b/app/Http/Controllers/SignupController.php new file mode 100644 index 0000000000..56c29d8d86 --- /dev/null +++ b/app/Http/Controllers/SignupController.php @@ -0,0 +1,38 @@ +middleware('guest'); + } + + /** + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + */ + public function signup() + { + return view('signup.index'); + } + + /** + * @param SignupRequest $request + */ + public function processSignup(SignupRequest $request) + { + dd($request->validated()); + } + +} \ No newline at end of file diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 0e5dff868b..acb9b25f22 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -41,6 +41,9 @@ class Kernel extends HttpKernel 'throttle:60,1', 'bindings', ], + 'db' => [ + + ], ]; /** diff --git a/app/Http/Middleware/setDb.php b/app/Http/Middleware/setDb.php new file mode 100644 index 0000000000..ea643206c5 --- /dev/null +++ b/app/Http/Middleware/setDb.php @@ -0,0 +1,26 @@ +user()->) + } + + return $next($request); + } +} diff --git a/app/Http/ValidationRules/UniqueUserRule.php b/app/Http/ValidationRules/UniqueUserRule.php index 0c6be04c2a..8046b52e55 100644 --- a/app/Http/ValidationRules/UniqueUserRule.php +++ b/app/Http/ValidationRules/UniqueUserRule.php @@ -2,6 +2,7 @@ namespace App\Http\ValidationRules; +use App\Libraries\MultiDB; use App\Models\User; use Illuminate\Contracts\Validation\Rule; @@ -10,7 +11,7 @@ class UniqueUserRule implements Rule public function passes($attribute, $value) { - return $this->checkIfEmailExists($value); + return ! $this->checkIfEmailExists($value); //if it exists, return false! } public function message() @@ -20,23 +21,7 @@ class UniqueUserRule implements Rule private function checkIfEmailExists($email) : bool { - if (config('auth.providers.users.driver') == 'eloquent') //default eloquent = single DB - { - return User::where(['email' => $email])->get()->count() == 0 ?? false; // true -> 0 emails found / false -> >=1 emails found - } - - //multi-db active - foreach (unserialize(MULTI_DBS) as $db) - { - if(User::on($db)->where(['email' => $email])->get()->count() >=1) // if user already exists, validation will fail - return false; - - } - return true; - - - - + return MultiDB::checkUserEmailExists($email); } } diff --git a/app/Libraries/MultiDB.php b/app/Libraries/MultiDB.php new file mode 100644 index 0000000000..b3ba60fbc5 --- /dev/null +++ b/app/Libraries/MultiDB.php @@ -0,0 +1,71 @@ + $email])->get()->count() >= 1 ?? false; // true >= 1 emails found / false -> == emails found + } + + //multi-db active + foreach (unserialize(MULTI_DBS) as $db) + { + if(User::on($db)->where(['email' => $email])->get()->count() >=1) // if user already exists, validation will fail + return true; + } + + return false; + + } + + /** + * @param array $data + * @return bool + */ + public static function getUser(array $data) + { + if (config('auth.providers.users.driver') == 'eloquent') //default eloquent = single DB + { + return User::where($data)->first(); + } + + foreach (unserialize(MULTI_DBS) as $db) + { + self::setDB($db); + + $user = User::where($data)->first(); + + if($user) + return $user; + } + + return false; + } + + + /** + * @param $database + */ + public static function setDB($database) : void + { + /* This will set the default configuration for the request */ + config(['database.default' => $database]); + app('db')->connection(config('database.connections.database.'.$database)); + } + +} \ No newline at end of file diff --git a/app/Libraries/OAuth.php b/app/Libraries/OAuth.php new file mode 100644 index 0000000000..83bed7fbc8 --- /dev/null +++ b/app/Libraries/OAuth.php @@ -0,0 +1,35 @@ +getEmail())) //if email is in the system this is an existing user -> check they are arriving on the correct provider + { + + } + } +} \ No newline at end of file diff --git a/app/Providers/MultiDatabaseUserProvider.php b/app/Providers/MultiDatabaseUserProvider.php index fbcb060a08..7a45fa0b8a 100644 --- a/app/Providers/MultiDatabaseUserProvider.php +++ b/app/Providers/MultiDatabaseUserProvider.php @@ -208,7 +208,7 @@ class MultiDatabaseUserProvider implements UserProvider private function setDefaultDatabase($id = false, $email = false, $token = false) : void { - $databases = ['db-ninja-1', 'db-ninja-2']; + $databases = unserialize(MULTI_DBS); foreach ($databases as $database) { $this->setDB($database); diff --git a/composer.json b/composer.json index ab24b7aa92..e57a946f9a 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ "davejamesmiller/laravel-breadcrumbs": "5.x", "fideloper/proxy": "^4.0", "laravel/framework": "5.7.*", + "laravel/socialite": "^3.1", "laravel/tinker": "^1.0", "spatie/laravel-html": "^2.19", "webpatser/laravel-countries": "dev-master#75992ad" diff --git a/composer.lock b/composer.lock index 61b26e10b1..1a53cb7052 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c9e2e008fc8ade0315e2c39e1934152d", + "content-hash": "0a3a5aeaabd9e3362e0da55be647367c", "packages": [ { "name": "asgrim/ofxparser", @@ -481,6 +481,187 @@ ], "time": "2018-02-07T20:20:57+00:00" }, + { + "name": "guzzlehttp/guzzle", + "version": "6.3.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.3-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2018-04-22T15:46:56+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2017-03-20T17:10:46+00:00" + }, { "name": "jakub-onderka/php-console-color", "version": "v0.2", @@ -709,6 +890,69 @@ ], "time": "2018-10-09T13:28:28+00:00" }, + { + "name": "laravel/socialite", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/socialite.git", + "reference": "65f771ff4f266ebae23de1a3f18efd80a1da2f8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/socialite/zipball/65f771ff4f266ebae23de1a3f18efd80a1da2f8d", + "reference": "65f771ff4f266ebae23de1a3f18efd80a1da2f8d", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~6.0", + "illuminate/contracts": "~5.4", + "illuminate/http": "~5.4", + "illuminate/support": "~5.4", + "league/oauth1-client": "~1.0", + "php": ">=5.6.4" + }, + "require-dev": { + "mockery/mockery": "~0.9", + "phpunit/phpunit": "~4.0|~5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Socialite\\SocialiteServiceProvider" + ], + "aliases": { + "Socialite": "Laravel\\Socialite\\Facades\\Socialite" + } + } + }, + "autoload": { + "psr-4": { + "Laravel\\Socialite\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.", + "homepage": "https://laravel.com", + "keywords": [ + "laravel", + "oauth" + ], + "time": "2018-08-16T12:51:21+00:00" + }, { "name": "laravel/tinker", "version": "v1.0.8", @@ -856,6 +1100,69 @@ ], "time": "2018-10-15T13:53:10+00:00" }, + { + "name": "league/oauth1-client", + "version": "1.7.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth1-client.git", + "reference": "fca5f160650cb74d23fc11aa570dd61f86dcf647" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/fca5f160650cb74d23fc11aa570dd61f86dcf647", + "reference": "fca5f160650cb74d23fc11aa570dd61f86dcf647", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5.0" + }, + "require-dev": { + "mockery/mockery": "^0.9", + "phpunit/phpunit": "^4.0", + "squizlabs/php_codesniffer": "^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth1\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Corlett", + "email": "bencorlett@me.com", + "homepage": "http://www.webcomm.com.au", + "role": "Developer" + } + ], + "description": "OAuth 1.0 Client Library", + "keywords": [ + "Authentication", + "SSO", + "authorization", + "bitbucket", + "identity", + "idp", + "oauth", + "oauth1", + "single sign on", + "trello", + "tumblr", + "twitter" + ], + "time": "2016-08-17T00:36:58+00:00" + }, { "name": "monolog/monolog", "version": "1.23.0", @@ -1195,6 +1502,56 @@ ], "time": "2017-02-14T16:28:37+00:00" }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, { "name": "psr/log", "version": "1.0.2", diff --git a/config/services.php b/config/services.php index 201e3ef7cd..2a985b84f6 100644 --- a/config/services.php +++ b/config/services.php @@ -39,5 +39,38 @@ return [ 'key' => env('STRIPE_KEY'), 'secret' => env('STRIPE_SECRET'), ], - + 'stripe' => [ + 'model' => 'User', + 'secret' => '', + ], + 'github' => [ + 'client_id' => env('GITHUB_CLIENT_ID'), + 'client_secret' => env('GITHUB_CLIENT_SECRET'), + 'redirect' => env('GITHUB_OAUTH_REDIRECT'), + ], + 'google' => [ + 'client_id' => env('GOOGLE_CLIENT_ID'), + 'client_secret' => env('GOOGLE_CLIENT_SECRET'), + 'redirect' => env('GOOGLE_OAUTH_REDIRECT'), + ], + 'facebook' => [ + 'client_id' => env('FACEBOOK_CLIENT_ID'), + 'client_secret' => env('FACEBOOK_CLIENT_SECRET'), + 'redirect' => env('FACEBOOK_OAUTH_REDIRECT'), + ], + 'linkedin' => [ + 'client_id' => env('LINKEDIN_CLIENT_ID'), + 'client_secret' => env('LINKEDIN_CLIENT_SECRET'), + 'redirect' => env('LINKEDIN_OAUTH_REDIRECT'), + ], + 'twitter' => [ + 'client_id' => env('TWITTER_CLIENT_ID'), + 'client_secret' => env('TWITTER_CLIENT_SECRET'), + 'redirect' => env('TWITTER_OAUTH_REDIRECT'), + ], + 'bitbucket' => [ + 'client_id' => env('BITBUCKET_CLIENT_ID'), + 'client_secret' => env('BITBUCKET_CLIENT_SECRET'), + 'redirect' => env('BITBUCKET_OAUTH_REDIRECT'), + ], ]; \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index ef1a4a6bbb..e8a1954a9b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -17,6 +17,11 @@ Route::get('login', 'Auth\LoginController@showLoginForm')->name('login'); Route::post('login', 'Auth\LoginController@login'); Route::post('logout', 'Auth\LoginController@logout')->name('logout'); +// Social authentication + +Route::get('auth/{provider}', 'Auth\LoginController@redirectToProvider'); +Route::get('auth/{provider}/callback', 'Auth\LoginController@handleProviderCallback'); + // Password Reset Routes... Route::get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request'); Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email'); @@ -30,8 +35,8 @@ Open Routes Route::redirect('/', '/login', 301); -Route::get('/signup', 'HomeController@signup')->name('signup'); -Route::post('/process_signup', 'HomeController@processSignup')->name('signup.submit'); +Route::get('/signup', 'SignupController@signup')->name('signup'); +Route::post('/process_signup', 'SignupController@processSignup')->name('signup.submit'); Route::get('/contact/login', 'Auth\ContactLoginController@showLoginForm')->name('contact.login'); Route::post('/contact/login', 'Auth\ContactLoginController@login')->name('contact.login.submit'); @@ -40,7 +45,7 @@ Route::post('/contact/login', 'Auth\ContactLoginController@login')->name('contac /* Authenticated User Routes */ -Route::group(['middleware' => ['auth:user']], function () { +Route::group(['middleware' => ['auth:user', 'db']], function () { Route::get('/dashboard', 'HomeController@user')->name('user.dashboard'); Route::get('/logout', 'Auth\LoginController@logout')->name('user.logout'); diff --git a/tests/Integration/MultiDBUserTest.php b/tests/Integration/MultiDBUserTest.php new file mode 100644 index 0000000000..a68ffd7670 --- /dev/null +++ b/tests/Integration/MultiDBUserTest.php @@ -0,0 +1,82 @@ +markTestSkipped('Multi DB not enabled - skipping'); + + User::unguard(); + + $user = [ + 'first_name' => 'user_db_1', + 'last_name' => 'user_db_1-s', + 'phone' => '55555', + 'email_verified_at' => now(), + 'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret + 'remember_token' => str_random(10), + 'email' => 'db1@example.com', + 'oauth_user_id' => '123' + ]; + + + $user2 = [ + 'first_name' => 'user_db_2', + 'last_name' => 'user_db_2-s', + 'phone' => '55555', + 'email_verified_at' => now(), + 'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret + 'remember_token' => str_random(10), + 'email' => 'db2@example.com', + 'oauth_user_id' => 'abc' + ]; + + User::on('db-ninja-1')->create($user); + User::on('db-ninja-2')->create($user2); + } + + public function test_oauth_user_db2_exists() + { + $user = MultiDB::getUser(['email' => 'db2@example.com', 'oauth_user_id' => 'abc']); + + $this->assertEquals($user->email, 'db2@example.com'); + + } + + public function test_oauth_user_db1_exists() + { + $user = MultiDB::getUser(['email' => 'db1@example.com', 'oauth_user_id' => '123']); + + $this->assertEquals($user->email, 'db1@example.com'); + + } + + public function tearDown() + { + DB::connection('db-ninja-1')->table('users')->delete(); + DB::connection('db-ninja-2')->table('users')->delete(); + } +} diff --git a/tests/Integration/UniqueEmailTest.php b/tests/Integration/UniqueEmailTest.php index 7c49bc3367..90d5fd8de3 100644 --- a/tests/Integration/UniqueEmailTest.php +++ b/tests/Integration/UniqueEmailTest.php @@ -5,6 +5,7 @@ namespace Tests\Unit; use App\Http\ValidationRules\UniqueUserRule; use App\Models\User; use Illuminate\Foundation\Testing\Concerns\InteractsWithDatabase; +use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Hash; use Tests\TestCase; @@ -15,7 +16,8 @@ use Tests\TestCase; */ class UniqueEmailTest extends TestCase { - use InteractsWithDatabase; + //use InteractsWithDatabase; + //use DatabaseMigrations; protected $rule; @@ -58,8 +60,8 @@ class UniqueEmailTest extends TestCase public function tearDown() { - // DB::connection('db-ninja-1')->table('users')->delete(); - // DB::connection('db-ninja-2')->table('users')->delete(); + DB::connection('db-ninja-1')->table('users')->delete(); + DB::connection('db-ninja-2')->table('users')->delete(); } } \ No newline at end of file