From e61036632abc77d9679f178aafc9d12a19eb67bb Mon Sep 17 00:00:00 2001 From: Roberto Guido Date: Fri, 27 Oct 2023 15:31:26 +0200 Subject: [PATCH] prima implementazione social login --- code/app/Helpers/Paths.php | 12 ++- .../Auth/ForgotPasswordController.php | 2 +- .../Http/Controllers/Auth/LoginController.php | 82 +++++++++++++++++- .../Controllers/Auth/RegisterController.php | 86 +++++++++++-------- code/app/Http/Controllers/GasController.php | 11 +++ code/app/Parameters/Config/SocialLogin.php | 23 +++++ code/app/Providers/EventServiceProvider.php | 5 ++ code/composer.json | 2 + code/config/services.php | 12 +++ code/resources/views/auth/login.blade.php | 4 +- code/resources/views/auth/register.blade.php | 65 +++++++++++--- .../views/auth/socialbuttons.blade.php | 27 ++++++ code/resources/views/gas/users.blade.php | 5 ++ code/routes/web.php | 2 + 14 files changed, 284 insertions(+), 54 deletions(-) create mode 100644 code/app/Parameters/Config/SocialLogin.php create mode 100644 code/resources/views/auth/socialbuttons.blade.php diff --git a/code/app/Helpers/Paths.php b/code/app/Helpers/Paths.php index 99c94520d..b44a46a91 100644 --- a/code/app/Helpers/Paths.php +++ b/code/app/Helpers/Paths.php @@ -27,10 +27,20 @@ function gas_storage_path($path = null, $folder = false) return $ret; } +function current_instance() +{ + if (global_multi_installation() && isset($_SERVER['HTTP_HOST'])) { + return substr($_SERVER['HTTP_HOST'], 0, strpos($_SERVER['HTTP_HOST'], '.')); + } + else { + return null; + } +} + function env_file() { if (global_multi_installation() && isset($_SERVER['HTTP_HOST'])) { - $instance = substr($_SERVER['HTTP_HOST'], 0, strpos($_SERVER['HTTP_HOST'], '.')); + $instance = current_instance(); return ('.env.' . $instance); } else { diff --git a/code/app/Http/Controllers/Auth/ForgotPasswordController.php b/code/app/Http/Controllers/Auth/ForgotPasswordController.php index e796a657f..d48efb038 100644 --- a/code/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/code/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -33,7 +33,7 @@ public function sendResetLinkEmail(Request $request) $identifier = $request->input('username'); $user = User::where('username', $identifier)->orWhereHas('contacts', function($query) use ($identifier) { - $query->where('type', 'email')->where('value', $identifier); + $query->whereIn('type', ['email', 'skip_email'])->where('value', $identifier); })->first(); if (is_null($user)) { diff --git a/code/app/Http/Controllers/Auth/LoginController.php b/code/app/Http/Controllers/Auth/LoginController.php index 6825c8a66..f9c8f93f3 100644 --- a/code/app/Http/Controllers/Auth/LoginController.php +++ b/code/app/Http/Controllers/Auth/LoginController.php @@ -10,6 +10,7 @@ use Auth; use Log; +use Laravel\Socialite\Facades\Socialite; use LaravelGettext; use App\User; @@ -56,6 +57,13 @@ private function postLogin($request, $user) } } + private function failedLogin($message) + { + Session::flash('message', $message); + Session::flash('message_type', 'danger'); + return redirect()->route('login'); + } + public function login(Request $request) { $username = trim($request->input('username')); @@ -73,10 +81,8 @@ public function login(Request $request) })->first(); if (is_null($user)) { - Session::flash('message', _i('Username non valido')); - Session::flash('message_type', 'danger'); Log::debug('Username non trovato: ' . $username); - return redirect(url('login')); + return $this->failedLogin(_i('Username non valido')); } else { $request->offsetSet('username', $user->username); @@ -104,4 +110,74 @@ public function autologin(Request $request, $token) Auth::loginUsingId($user->id); return redirect()->route('dashboard'); } + + public function social($driver) + { + $client_id = config('service.' . $driver . '.client_id'); + $client_secret = config('service.' . $driver . '.client_secret'); + + if (env('GASDOTTO_NET')) { + /* + Per le istanze gasdotto.net c'è un unico URL valido per i + redirect OAuth, da cui poi si viene smistati sulla rotta + login.social.back dell'istanza giusta + */ + $redirect_url = sprintf('https://gasdotto.net/social/%s?instance=%s', $driver, current_instance()); + } + else { + $redirect_url = route('login.social.back', $driver); + } + + $config = new \SocialiteProviders\Manager\Config($client_id, $client_secret, $redirect_url); + return Socialite::driver($driver)->setConfig($config)->redirect(); + } + + private function retrieveSocialUser($user, $driver) + { + $identifier = $user->id; + $driver_contact_type = sprintf('%s_id', $driver); + + $u = User::whereHas('contacts', function($query) use ($identifier, $driver_contact_type) { + $query->where('type', $driver_contact_type)->where('value', $identifier); + })->first(); + + if (is_null($u)) { + $email = $user->email; + if (filled($email)) { + $u = User::whereHas('contacts', function($query) use ($email) { + $query->whereIn('type', ['email', 'skip_email'])->where('value', $email); + })->first(); + } + } + + return $u; + } + + public function socialCallback(Request $request, $driver) + { + $user = Socialite::driver($driver)->user(); + + if ($user) { + $u = $this->retrieveSocialUser($user, $driver); + if ($u) { + Auth::loginUsingId($u->id); + return redirect()->route('dashboard'); + } + + $gas = currentAbsoluteGas(); + + if ($gas->hasFeature('public_registrations')) { + $social_identifier = sprintf('%s_id::%s', $driver, $user->id); + Session::put('from_social', $social_identifier); + Session::put('from_social_email', $user->email); + return redirect()->route('register'); + } + else { + return $this->failedLogin(_i('Utente non riconosciuto. Per accedere è necessario farsi prima creare un account da un amministratore.')); + } + } + else { + return $this->failedLogin(_i('Errore nella fase di autenticazione')); + } + } } diff --git a/code/app/Http/Controllers/Auth/RegisterController.php b/code/app/Http/Controllers/Auth/RegisterController.php index 8f7b5a047..211594b4e 100644 --- a/code/app/Http/Controllers/Auth/RegisterController.php +++ b/code/app/Http/Controllers/Auth/RegisterController.php @@ -4,19 +4,18 @@ use Illuminate\Http\Request; use App\Http\Controllers\Controller; -use Illuminate\Support\Facades\Validator; use Illuminate\Foundation\Auth\RegistersUsers; +use Illuminate\Support\Str; +use Illuminate\Support\Facades\Validator; +use Illuminate\Support\Facades\Mail; +use Illuminate\Support\Facades\Session; +use Illuminate\Support\Facades\Hash; use App\Rules\Captcha; use App\Rules\EMail; use App\Notifications\WelcomeMessage; use App\Notifications\NewUserNotification; -use Mail; -use Session; -use Hash; -use Log; - use App\Gas; use App\User; use App\Contact; @@ -56,15 +55,27 @@ public function __construct() public function showRegistrationForm() { $gas = currentAbsoluteGas(); + if($gas->hasFeature('public_registrations') == false) { return redirect()->route('login'); } else { - $first = rand(1, 20); - $second = rand(1, 20); - $captcha = sprintf('%s + %s =', $first, $second); - Session::put('captcha_solution', $first + $second); - return view('auth.register', ['captcha' => $captcha]); + $social = Session::get('from_social'); + $email = Session::get('from_social_email'); + + if ($social) { + return view('auth.register', [ + 'social' => $social, + 'email' => $email, + ]); + } + else { + $first = rand(1, 20); + $second = rand(1, 20); + $captcha = sprintf('%s + %s =', $first, $second); + Session::put('captcha_solution', $first + $second); + return view('auth.register', ['captcha' => $captcha]); + } } } @@ -81,11 +92,15 @@ protected function validator(array $data) throw new \Exception('No GAS selected', 1); } - $options = [ - 'username' => 'required|string|max:255|unique:users', - 'password' => 'required|string|min:6|confirmed', - 'verify' => [new Captcha()] - ]; + $social = $data['social'] ?? null; + + if (is_null($social)) { + $options = [ + 'username' => 'required|string|max:255|unique:users', + 'password' => 'required|string|min:6|confirmed', + 'verify' => [new Captcha()] + ]; + } $mandatory = $gas->public_registrations['mandatory_fields']; @@ -116,13 +131,19 @@ protected function validator(array $data) */ protected function create(array $data) { + $gas = Gas::find($data['gas_id']); + $user = new User(); $user->gas_id = $data['gas_id']; $user->member_since = date('Y-m-d', time()); - $user->username = $data['username']; $user->firstname = $data['firstname']; $user->lastname = $data['lastname']; - $user->password = Hash::make($data['password']); + + $username = $data['username'] ?? ($data['email'] ?? Str::random(30)); + $user->username = $username; + + $password = $data['password'] ?? Str::random(30); + $user->password = Hash::make($password); $manual = $gas->public_registrations['manual']; if ($manual) { @@ -131,22 +152,17 @@ protected function create(array $data) $user->save(); - if (!empty($data['email'])) { - $contact = new Contact(); - $contact->target_id = $user->id; - $contact->target_type = get_class($user); - $contact->type = 'email'; - $contact->value = $data['email']; - $contact->save(); + if (isset($data['email']) && empty($data['email']) == false) { + $user->addContact('email', $data['email']); + } + + if (isset($data['phone']) && empty($data['phone']) == false) { + $user->addContact('phone', $data['phone']); } - if (!empty($data['phone'])) { - $contact = new Contact(); - $contact->target_id = $user->id; - $contact->target_type = get_class($user); - $contact->type = 'phone'; - $contact->value = $data['phone']; - $contact->save(); + if (isset($data['social']) && empty($data['social']) == false) { + list($identifier, $value) = explode('::', $data['social']); + $user->addContact($identifier, $value); } return $user; @@ -155,12 +171,14 @@ protected function create(array $data) protected function registered(Request $request, $user) { Session::forget('captcha_solution'); + Session::forget('from_social'); + Session::forget('from_social_email'); try { $user->notify(new WelcomeMessage()); } catch(\Exception $e) { - Log::error('Impossibile inviare mail di verifica a nuovo utente: ' . $e->getMessage()); + \Log::error('Impossibile inviare mail di verifica a nuovo utente: ' . $e->getMessage()); } $admins = everybodyCan('users.admin', $user->gas); @@ -169,7 +187,7 @@ protected function registered(Request $request, $user) $ad->notify(new NewUserNotification($user)); } catch(\Exception $e) { - Log::error('Impossibile inviare notifica registrazione nuovo utente: ' . $e->getMessage()); + \Log::error('Impossibile inviare notifica registrazione nuovo utente: ' . $e->getMessage()); } } diff --git a/code/app/Http/Controllers/GasController.php b/code/app/Http/Controllers/GasController.php index 451e2ffbf..73a395325 100644 --- a/code/app/Http/Controllers/GasController.php +++ b/code/app/Http/Controllers/GasController.php @@ -173,7 +173,18 @@ private function configUsers($gas, $request) ]; } + $socials = []; + + if ($request->has('enable_login_google')) { + $socials[] = 'google'; + } + + if ($request->has('enable_login_facebook')) { + $socials[] = 'facebook'; + } + $gas->setConfig('public_registrations', $registrations_info); + $gas->setConfig('social_login', $socials); } private function configOrders($gas, $request) diff --git a/code/app/Parameters/Config/SocialLogin.php b/code/app/Parameters/Config/SocialLogin.php new file mode 100644 index 000000000..3c10e8a98 --- /dev/null +++ b/code/app/Parameters/Config/SocialLogin.php @@ -0,0 +1,23 @@ + [] + ]; + } +} diff --git a/code/app/Providers/EventServiceProvider.php b/code/app/Providers/EventServiceProvider.php index 592d2d466..bafcedc67 100644 --- a/code/app/Providers/EventServiceProvider.php +++ b/code/app/Providers/EventServiceProvider.php @@ -52,6 +52,11 @@ class EventServiceProvider extends ServiceProvider 'Illuminate\Mail\Events\MessageSending' => [ 'App\Listeners\CustomMailTag', ], + + \SocialiteProviders\Manager\SocialiteWasCalled::class => [ + \SocialiteProviders\Google\GoogleExtendSocialite::class.'@handle', + \SocialiteProviders\Facebook\FacebookExtendSocialite::class.'@handle', + ], ]; public function boot() diff --git a/code/composer.json b/code/composer.json index ba208661f..65c6b3908 100644 --- a/code/composer.json +++ b/code/composer.json @@ -23,6 +23,8 @@ "madbob/laravel-log2rss": "0.5.0", "madbob/laravel-queue-loopback": "0.5.0", "satispay/online-api-php-sdk": "^1.6", + "socialiteproviders/facebook": "^4.1", + "socialiteproviders/google": "^4.1", "spatie/db-dumper": "^3.0", "symfony/http-client": "^6.2", "symfony/psr-http-message-bridge": "^2.1", diff --git a/code/config/services.php b/code/config/services.php index 2230d9a9a..e6d3c346b 100644 --- a/code/config/services.php +++ b/code/config/services.php @@ -43,4 +43,16 @@ 'secret' => env('STRIPE_SECRET'), ], + 'google' => [ + 'client_id' => env('GOOGLE_CLIENT_ID'), + 'client_secret' => env('GOOGLE_CLIENT_SECRET'), + 'redirect' => '', + ], + + 'facebook' => [ + 'client_id' => env('FACEBOOK_CLIENT_ID'), + 'client_secret' => env('FACEBOOK_CLIENT_SECRET'), + 'redirect' => '', + ], + ]; diff --git a/code/resources/views/auth/login.blade.php b/code/resources/views/auth/login.blade.php index 253172294..3f96cc463 100644 --- a/code/resources/views/auth/login.blade.php +++ b/code/resources/views/auth/login.blade.php @@ -2,7 +2,7 @@ @section('content') -
+
@if($gas->message != '')
{!! nl2br($gas->message) !!} @@ -37,6 +37,8 @@ + + @include('auth.socialbuttons')
diff --git a/code/resources/views/auth/register.blade.php b/code/resources/views/auth/register.blade.php index c1334f6ff..1e3dc79f2 100644 --- a/code/resources/views/auth/register.blade.php +++ b/code/resources/views/auth/register.blade.php @@ -2,33 +2,70 @@ @section('content') -
+@php + +if (isset($social) == false) { + $social = null; +} + +if (isset($email) == false) { + $email = ''; +} + +if (isset($captcha) == false) { + $captcha = null; +} + +$gas = currentAbsoluteGas(); +$mandatory_fields = $gas->public_registrations['mandatory_fields']; + +@endphp + +
- - - - - - - - + @if($social) + + +
+ {{ _i('Completa la tua registrazione con qualche informazione in più.') }} +
+ @endif + + + + + + + @if(is_null($social)) + + + + @endif + + @if($captcha) + + @endif @if(App\Gas::count() > 1) @else - + @endif - @if (!empty(currentAbsoluteGas()->public_registrations['privacy_link'])) - Informativa sulla Privacy.", [currentAbsoluteGas()->public_registrations['privacy_link']]) ?> + @if (!empty($gas->public_registrations['privacy_link'])) + Informativa sulla Privacy.", [$gas->public_registrations['privacy_link']]) ?> @endif - @if (!empty(currentAbsoluteGas()->public_registrations['terms_link'])) - Condizioni d'Uso.", [currentAbsoluteGas()->public_registrations['terms_link']]) ?> + @if (!empty($gas->public_registrations['terms_link'])) + Condizioni d'Uso.", [$gas->public_registrations['terms_link']]) ?> @endif
+ + @if(is_null($social)) + @include('auth.socialbuttons') + @endif
diff --git a/code/resources/views/auth/socialbuttons.blade.php b/code/resources/views/auth/socialbuttons.blade.php new file mode 100644 index 000000000..a4a4aa5f8 --- /dev/null +++ b/code/resources/views/auth/socialbuttons.blade.php @@ -0,0 +1,27 @@ +@php + +$enabled = []; + +foreach(App\Gas::all() as $gas) { + $enabled = array_merge($enabled, $gas->social_login); +} + +$enabled = array_unique($enabled); + +@endphp + +@if(empty($enabled) == false) +
+
+ @foreach($enabled as $social) + + @endforeach +
+@endif diff --git a/code/resources/views/gas/users.blade.php b/code/resources/views/gas/users.blade.php index e7a261358..85d8b36fa 100644 --- a/code/resources/views/gas/users.blade.php +++ b/code/resources/views/gas/users.blade.php @@ -4,6 +4,11 @@
+ + + +
+ diff --git a/code/routes/web.php b/code/routes/web.php index 5f60a9d38..ec0390a5f 100644 --- a/code/routes/web.php +++ b/code/routes/web.php @@ -1,6 +1,8 @@ name('login.social'); +Route::get('login/social/{driver}/callback', 'Auth\LoginController@socialCallback')->name('login.social.back'); Route::get('autologin/{token}', 'Auth\LoginController@autologin')->name('autologin'); Route::get('ordini.xml', 'OrdersController@rss')->name('rss');