From 4dc4ce1517ea065578e11fe69cfec7978b2d0074 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Wed, 29 Apr 2020 22:19:21 +0100 Subject: [PATCH] Switched the socialite login providers to the new external services configuration #152 --- app/ExternalService.php | 28 ++-- app/Helpers/ConfigHelper.php | 9 +- .../Controllers/Admin/DefaultController.php | 30 +++- .../Controllers/Admin/ServiceController.php | 40 ++++- app/Http/Controllers/Auth/LoginController.php | 121 ++++++++++++-- resources/js/external_services.js | 22 ++- resources/lang/en/admin.php | 6 +- resources/lang/en/forms.php | 9 +- resources/sass/admin.scss | 4 - resources/sass/global.scss | 4 + .../base/admin/create_service.blade.php | 20 ++- .../themes/base/admin/edit_service.blade.php | 10 +- .../themes/base/admin/settings.blade.php | 155 +++++++++--------- .../admin_services_dropbox_options.blade.php | 31 ---- .../admin_services_oauth_options.blade.php | 9 +- .../partials/social_login_providers.blade.php | 6 +- 16 files changed, 323 insertions(+), 181 deletions(-) delete mode 100644 resources/views/themes/base/partials/admin_services_dropbox_options.blade.php diff --git a/app/ExternalService.php b/app/ExternalService.php index aaf14c9..d4a1a93 100644 --- a/app/ExternalService.php +++ b/app/ExternalService.php @@ -28,19 +28,27 @@ class ExternalService extends Model return ExternalService::where('service_type', $serviceType)->get(); } - public function hasOAuthStandardOptions() - { - // This logic must be mirrored in external_services.js - return in_array($this->service_type, [ - self::FACEBOOK, - self::GOOGLE, - self::TWITTER - ]); - } - public function isDropbox() { // This logic must be mirrored in external_services.js return $this->service_type == self::DROPBOX; } + + public function isFacebook() + { + // This logic must be mirrored in external_services.js + return $this->service_type == self::FACEBOOK; + } + + public function isGoogle() + { + // This logic must be mirrored in external_services.js + return $this->service_type == self::GOOGLE; + } + + public function isTwitter() + { + // This logic must be mirrored in external_services.js + return $this->service_type == self::TWITTER; + } } \ No newline at end of file diff --git a/app/Helpers/ConfigHelper.php b/app/Helpers/ConfigHelper.php index 27c2f20..eb53d1b 100644 --- a/app/Helpers/ConfigHelper.php +++ b/app/Helpers/ConfigHelper.php @@ -113,10 +113,8 @@ class ConfigHelper 'date_format' => $this->allowedDateFormats()[0], 'default_album_view' => $this->allowedAlbumViews()[0], 'enable_visitor_hits' => false, - 'facebook_app_id' => '', - 'facebook_app_secret' => '', - 'google_app_id' => '', - 'google_app_secret' => '', + 'facebook_external_service_id' => null, + 'google_external_service_id' => null, 'hotlink_protection' => false, 'items_per_page' => 12, 'items_per_page_admin' => 10, @@ -151,8 +149,7 @@ class ConfigHelper 'social_user_feeds' => false, 'social_user_profiles' => false, 'theme' => 'default', - 'twitter_app_id' => '', - 'twitter_app_secret' => '', + 'twitter_external_service_id' => null ); } diff --git a/app/Http/Controllers/Admin/DefaultController.php b/app/Http/Controllers/Admin/DefaultController.php index 83932f8..33809d2 100644 --- a/app/Http/Controllers/Admin/DefaultController.php +++ b/app/Http/Controllers/Admin/DefaultController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Admin; use App\Album; +use App\ExternalService; use App\Facade\Theme; use App\Facade\UserConfig; use App\Group; @@ -260,10 +261,8 @@ class DefaultController extends Controller 'analysis_queue_storage_location', 'app_name', 'date_format', - 'facebook_app_id', - 'facebook_app_secret', - 'google_app_id', - 'google_app_secret', + 'facebook_external_service_id', + 'google_external_service_id', 'photo_comments_allowed_html', 'photo_comments_thread_depth', 'rabbitmq_server', @@ -279,8 +278,7 @@ class DefaultController extends Controller 'smtp_username', 'smtp_password', 'theme', - 'twitter_app_id', - 'twitter_app_secret', + 'twitter_external_service_id', 'recaptcha_site_key', 'recaptcha_secret_key', 'analytics_code' @@ -374,12 +372,30 @@ class DefaultController extends Controller // Storage sources for the Image Processing tab $storageSources = AnalysisQueueHelper::getCompatibleStorages(); + // External services + $externalServices = ExternalService::all(); + $facebookServices = $externalServices->filter(function (ExternalService $item) + { + return $item->service_type == ExternalService::FACEBOOK; + }); + $googleServices = $externalServices->filter(function (ExternalService $item) + { + return $item->service_type == ExternalService::GOOGLE; + }); + $twitterServices = $externalServices->filter(function (ExternalService $item) + { + return $item->service_type == ExternalService::TWITTER; + }); + return Theme::render('admin.settings', [ 'config' => $config, 'date_formats' => $dateFormatsLookup, + 'facebookServices' => $facebookServices, + 'googleServices' => $googleServices, 'storage_sources' => $storageSources, 'success' => $request->session()->get('success'), - 'theme_names' => $themeNamesLookup + 'theme_names' => $themeNamesLookup, + 'twitterServices' => $twitterServices ]); } diff --git a/app/Http/Controllers/Admin/ServiceController.php b/app/Http/Controllers/Admin/ServiceController.php index 691aed4..464878c 100644 --- a/app/Http/Controllers/Admin/ServiceController.php +++ b/app/Http/Controllers/Admin/ServiceController.php @@ -90,14 +90,30 @@ class ServiceController extends Controller * * @return \Illuminate\Http\Response */ - public function create() + public function create(Request $request) { $this->authorizeAccessToAdminPanel('admin:manage-services'); + $serviceTypes = $this->serviceTypeList(); + $selectedServiceType = old('service_type', $request->get('service_type')); + + if (!array_key_exists($selectedServiceType, $serviceTypes)) + { + $selectedServiceType = ''; + } + + $returnTo = old('return_to', $request->get('return_to')); + if (!array_key_exists($returnTo, $this->validReturnLocations())) + { + $returnTo = ''; + } + return Theme::render('admin.create_service', [ 'callbackUrls' => $this->callbackList(), + 'returnTo' => $returnTo, + 'selectedServiceType' => $selectedServiceType, 'service' => new ExternalService(), - 'serviceTypes' => $this->serviceTypeList() + 'serviceTypes' => $serviceTypes ]); } @@ -236,6 +252,14 @@ class ServiceController extends Controller $service->save(); + $returnToLocations = $this->validReturnLocations(); + $returnTo = $request->get('return_to'); + + if (array_key_exists($returnTo, $returnToLocations)) + { + return redirect($returnToLocations[$returnTo]); + } + return redirect(route('services.index')); } @@ -278,7 +302,10 @@ class ServiceController extends Controller $dropboxService = new DropboxService(); return [ - ExternalService::DROPBOX => $dropboxService->callbackUrl() + ExternalService::DROPBOX => $dropboxService->callbackUrl(), + ExternalService::FACEBOOK => route('login_callback.facebook'), + ExternalService::GOOGLE => route('login_callback.google'), + ExternalService::TWITTER => route('login_callback.twitter') ]; } @@ -297,4 +324,11 @@ class ServiceController extends Controller ExternalService::TWITTER => trans(sprintf('services.%s', ExternalService::TWITTER)) ]; } + + private function validReturnLocations() + { + return [ + 'settings' => route('admin.settings') + ]; + } } \ No newline at end of file diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index f123724..46b3486 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Auth; +use App\ExternalService; use App\Facade\Theme; use App\Facade\UserConfig; use App\Helpers\MiscHelper; @@ -152,7 +153,12 @@ class LoginController extends Controller */ public function redirectToFacebook() { - $socialite = $this->setSocialiteConfigs(); + $socialite = $this->setSocialiteConfigForFacebook(); + if (is_null($socialite)) + { + return redirect(route('login')); + } + return $socialite->driver('facebook')->redirect(); } @@ -163,7 +169,12 @@ class LoginController extends Controller */ public function redirectToGoogle() { - $socialite = $this->setSocialiteConfigs(); + $socialite = $this->setSocialiteConfigForGoogle(); + if (is_null($socialite)) + { + return redirect(route('login')); + } + return $socialite->driver('google')->redirect(); } @@ -174,7 +185,12 @@ class LoginController extends Controller */ public function redirectToTwitter() { - $socialite = $this->setSocialiteConfigs(); + $socialite = $this->setSocialiteConfigForTwitter(); + if (is_null($socialite)) + { + return redirect(route('login')); + } + return $socialite->driver('twitter')->redirect(); } @@ -185,7 +201,12 @@ class LoginController extends Controller */ public function handleFacebookCallback(Request $request) { - $socialite = $this->setSocialiteConfigs(); + $socialite = $this->setSocialiteConfigForFacebook(); + if (is_null($socialite)) + { + return redirect(route('login')); + } + $facebookUser = $socialite->driver('facebook')->user(); return $this->processSocialMediaLogin($request, 'facebook_id', $facebookUser); @@ -198,7 +219,12 @@ class LoginController extends Controller */ public function handleGoogleCallback(Request $request) { - $socialite = $this->setSocialiteConfigs(); + $socialite = $this->setSocialiteConfigForGoogle(); + if (is_null($socialite)) + { + return redirect(route('login')); + } + $googleUser = $socialite->driver('google')->user(); return $this->processSocialMediaLogin($request, 'google_id', $googleUser); @@ -211,12 +237,30 @@ class LoginController extends Controller */ public function handleTwitterCallback(Request $request) { - $socialite = $this->setSocialiteConfigs(); + $socialite = $this->setSocialiteConfigForTwitter(); + if (is_null($socialite)) + { + return redirect(route('login')); + } + $twitterUser = $socialite->driver('twitter')->user(); return $this->processSocialMediaLogin($request, 'twitter_id', $twitterUser); } + private function getSocialMediaConfig($socialMediaEnabledField, $socialMediaExternalServiceIdField) + { + if (boolval(UserConfig::get($socialMediaEnabledField))) + { + $externalServiceID = intval(UserConfig::get($socialMediaExternalServiceIdField)); + $externalService = ExternalService::where('id', $externalServiceID)->first(); + + return $externalService; + } + + return null; + } + private function processSocialMediaLogin(Request $request, $socialMediaIdField, $socialMediaUser) { $userBySocialMediaId = User::where($socialMediaIdField, $socialMediaUser->getId())->first(); @@ -260,38 +304,81 @@ class LoginController extends Controller return redirect(route('auth.register_sso')); } - private function setSocialiteConfigs() + private function setSocialiteConfigForFacebook() { - // Force Socialite to use our config from the database instead of hard-coded in config/services.php + $facebookConfig = $this->getSocialMediaConfig( + 'social_facebook_login', + 'facebook_external_service_id' + ); + + if (is_null($facebookConfig)) + { + return null; + } + $socialite = app()->make(\Laravel\Socialite\Contracts\Factory::class); $socialite->extend( 'facebook', - function ($app) use ($socialite) { + function ($app) use ($socialite, $facebookConfig) { $config = [ - 'client_id' => trim(UserConfig::get('facebook_app_id')), - 'client_secret' => trim(decrypt(UserConfig::get('facebook_app_secret'))), + 'client_id' => trim(decrypt($facebookConfig->app_id)), + 'client_secret' => trim(decrypt($facebookConfig->app_secret)), 'redirect' => route('login_callback.facebook') ]; return $socialite->buildProvider(FacebookProvider::class, $config); } ); + + return $socialite; + } + + private function setSocialiteConfigForGoogle() + { + $googleConfig = $this->getSocialMediaConfig( + 'social_google_login', + 'google_external_service_id' + ); + + if (is_null($googleConfig)) + { + return null; + } + + $socialite = app()->make(\Laravel\Socialite\Contracts\Factory::class); $socialite->extend( 'google', - function ($app) use ($socialite) { + function ($app) use ($socialite, $googleConfig) { $config = [ - 'client_id' => trim(UserConfig::get('google_app_id')), - 'client_secret' => trim(decrypt(UserConfig::get('google_app_secret'))), + 'client_id' => trim(decrypt($googleConfig->app_id)), + 'client_secret' => trim(decrypt($googleConfig->app_secret)), 'redirect' => route('login_callback.google') ]; return $socialite->buildProvider(GoogleProvider::class, $config); } ); + + return $socialite; + } + + private function setSocialiteConfigForTwitter() + { + $twitterConfig = $this->getSocialMediaConfig( + 'social_twitter_login', + 'twitter_external_service_id' + ); + + if (is_null($twitterConfig)) + { + return null; + } + + $socialite = app()->make(\Laravel\Socialite\Contracts\Factory::class); $socialite->extend( 'twitter', - function ($app) use ($socialite) { + function ($app) use ($socialite, $twitterConfig) { $config = [ - 'identifier' => trim(UserConfig::get('twitter_app_id')), - 'secret' => trim(decrypt(UserConfig::get('twitter_app_secret'))), + 'identifier' => trim(decrypt($twitterConfig->app_id)), + 'secret' => trim(decrypt($twitterConfig->app_secret)), 'callback_uri' => route('login_callback.twitter') ]; return new TwitterProvider($app['request'], new TwitterServer($config)); diff --git a/resources/js/external_services.js b/resources/js/external_services.js index b6b6440..2daf11c 100644 --- a/resources/js/external_services.js +++ b/resources/js/external_services.js @@ -5,17 +5,25 @@ function ExternalServiceViewModel() service_type: '' }; this.computed = { - hasOAuthStandardOptions: function() - { - // This logic must be mirrored in App\ExternalService - return this.service_type === 'facebook' || - this.service_type === 'google' || - this.service_type === 'twitter'; - }, isDropbox: function() { // This logic must be mirrored in App\ExternalService return this.service_type === 'dropbox'; + }, + isFacebook: function() + { + // This logic must be mirrored in App\ExternalService + return this.service_type === 'facebook'; + }, + isGoogle: function() + { + // This logic must be mirrored in App\ExternalService + return this.service_type === 'google'; + }, + isTwitter: function() + { + // This logic must be mirrored in App\ExternalService + return this.service_type === 'twitter'; } } } \ No newline at end of file diff --git a/resources/lang/en/admin.php b/resources/lang/en/admin.php index b6b9cc6..65a714a 100644 --- a/resources/lang/en/admin.php +++ b/resources/lang/en/admin.php @@ -314,10 +314,14 @@ return [ 'rebuild_permissions_cache_succeeded' => 'The permissions cache rebuild completed successfully.', 'security_allow_self_registration' => 'Allow self-registration', 'security_allow_self_registration_description' => 'With this option enabled, users can sign up for their own accounts. You can grant permissions to accounts to allow users to upload their own photos or manage yours.', + 'social_add_external_services_link' => 'Add a new service', 'social_facebook' => 'Facebook', + 'social_facebook_no_services' => 'You haven\'t defined any services for Facebook. Add a new service with your Facebook app ID and secret.', 'social_google' => 'Google', + 'social_google_no_services' => 'You haven\'t defined any services for Google. Add a new service with your Google app ID and secret.', 'social_tab' => 'Social', - 'social_twitter' => 'Twitter' + 'social_twitter' => 'Twitter', + 'social_twitter_no_services' => 'You haven\'t defined any services for Twitter. Add a new service with your Twitter app API key and secret.', ], 'settings_email_tab' => 'E-mail', 'settings_general_tab' => 'General', diff --git a/resources/lang/en/forms.php b/resources/lang/en/forms.php index 5ecaa43..994b770 100644 --- a/resources/lang/en/forms.php +++ b/resources/lang/en/forms.php @@ -82,16 +82,13 @@ return [ 'settings_moderate_known_users_help' => 'If this option is enabled, comments posted by logged-in users must be moderated before being displayed.', 'settings_restrict_originals_download' => 'Restrict access to original images', 'settings_restrict_originals_download_help' => 'With this option enabled, only the photo\'s owner can download the original high-resolution images.', - 'settings_social_facebook_app_id' => 'Facebook App ID:', - 'settings_social_facebook_app_secret' => 'Facebook App Secret:', + 'settings_social_facebook_external_service' => 'Facebook service:', 'settings_social_facebook_login' => 'Allow login/registration with a Facebook account.', 'settings_social_facebook_login_help' => 'With this option enabled, users can register (if enabled) and login with their Facebook account.', - 'settings_social_google_app_id' => 'Google App ID:', - 'settings_social_google_app_secret' => 'Google App Secret:', + 'settings_social_google_external_service' => 'Google service:', 'settings_social_google_login' => 'Allow login/registration with a Google account.', 'settings_social_google_login_help' => 'With this option enabled, users can register (if enabled) and login with their Google account.', - 'settings_social_twitter_app_id' => 'Twitter App ID:', - 'settings_social_twitter_app_secret' => 'Twitter App Secret:', + 'settings_social_twitter_external_service' => 'Twitter service:', 'settings_social_twitter_login' => 'Allow login/registration with a Twitter account', 'settings_social_twitter_login_help' => 'With this option enabled, users can register (if enabled) and login with their Twitter account.', 'settings_social_user_feeds' => 'Enable user feeds and following', diff --git a/resources/sass/admin.scss b/resources/sass/admin.scss index 955bd37..c87012b 100644 --- a/resources/sass/admin.scss +++ b/resources/sass/admin.scss @@ -31,8 +31,4 @@ .text-red { color: #ff0000; -} - -[v-cloak] { - display: none; } \ No newline at end of file diff --git a/resources/sass/global.scss b/resources/sass/global.scss index 82b31d0..bf92941 100644 --- a/resources/sass/global.scss +++ b/resources/sass/global.scss @@ -27,4 +27,8 @@ textarea { border: solid 1px rgb(221, 221, 221); border-top: 0; padding: 20px; +} + +[v-cloak] { + display: none; } \ No newline at end of file diff --git a/resources/views/themes/base/admin/create_service.blade.php b/resources/views/themes/base/admin/create_service.blade.php index 9d221a2..704f6b1 100644 --- a/resources/views/themes/base/admin/create_service.blade.php +++ b/resources/views/themes/base/admin/create_service.blade.php @@ -19,6 +19,8 @@
{{ csrf_field() }} + +
- -
+ @if (count($facebookServices) == 0) +
+

@lang('admin.settings.social_facebook_no_services')

+

@lang('admin.settings.social_add_external_services_link')

+
+ @else +
+ + +
-
- - +
+ + - @if ($errors->has('facebook_app_id')) -
- {{ $errors->first('facebook_app_id') }} -
- @endif -
- -
- - - - @if ($errors->has('facebook_app_secret')) -
- {{ $errors->first('facebook_app_secret') }} -
- @endif -
+ @if ($errors->has('facebook_external_service_id')) +
+ {{ $errors->first('facebook_external_service_id') }} +
+ @endif +
+ @endif @@ -546,35 +547,36 @@ @lang('admin.settings.social_twitter') -
- - -
+ @if (count($twitterServices) == 0) +
+

@lang('admin.settings.social_twitter_no_services')

+

@lang('admin.settings.social_add_external_services_link')

+
+ @else +
+ + +
-
- - +
+ + - @if ($errors->has('twitter_app_id')) -
- {{ $errors->first('twitter_app_id') }} -
- @endif -
- -
- - - - @if ($errors->has('twitter_app_secret')) -
- {{ $errors->first('twitter_app_secret') }} -
- @endif -
+ @if ($errors->has('twitter_external_service_id')) +
+ {{ $errors->first('twitter_external_service_id') }} +
+ @endif +
+ @endif @@ -593,32 +595,33 @@ @lang('admin.settings.social_google') -
- - -
+ @if (count($googleServices) == 0) +
+

@lang('admin.settings.social_google_no_services')

+

@lang('admin.settings.social_add_external_services_link')

+
+ @else +
+ + +
+ @endif
- - + + - @if ($errors->has('google_app_id')) + @if ($errors->has('google_external_service_id'))
- {{ $errors->first('google_app_id') }} -
- @endif -
- -
- - - - @if ($errors->has('google_app_secret')) -
- {{ $errors->first('google_app_secret') }} + {{ $errors->first('google_external_service_id') }}
@endif
diff --git a/resources/views/themes/base/partials/admin_services_dropbox_options.blade.php b/resources/views/themes/base/partials/admin_services_dropbox_options.blade.php deleted file mode 100644 index b48c00f..0000000 --- a/resources/views/themes/base/partials/admin_services_dropbox_options.blade.php +++ /dev/null @@ -1,31 +0,0 @@ -
-
-
- - - - @if ($errors->has('app_id')) -
- {{ $errors->first('app_id') }} -
- @endif -
-
-
-
- - - - @if ($errors->has('app_secret')) -
- {{ $errors->first('app_secret') }} -
- @endif -
-
-
- -
-

@lang('admin.service_callback_intro', ['name' => trans(sprintf('services.%s', \App\ExternalService::DROPBOX))])

-

{{ $callbackUrls[\App\ExternalService::DROPBOX] }}

-
\ No newline at end of file diff --git a/resources/views/themes/base/partials/admin_services_oauth_options.blade.php b/resources/views/themes/base/partials/admin_services_oauth_options.blade.php index ac2db65..e5b76cc 100644 --- a/resources/views/themes/base/partials/admin_services_oauth_options.blade.php +++ b/resources/views/themes/base/partials/admin_services_oauth_options.blade.php @@ -23,4 +23,11 @@ @endif - \ No newline at end of file + + +@if (isset($callbackUrls[$oauthService])) +
+

@lang('admin.service_callback_intro', ['name' => trans(sprintf('services.%s', $oauthService))])

+

{{ $callbackUrls[$oauthService] }}

+
+@endif \ No newline at end of file diff --git a/resources/views/themes/base/partials/social_login_providers.blade.php b/resources/views/themes/base/partials/social_login_providers.blade.php index 13b9377..f327bae 100644 --- a/resources/views/themes/base/partials/social_login_providers.blade.php +++ b/resources/views/themes/base/partials/social_login_providers.blade.php @@ -1,11 +1,11 @@

@if (UserConfig::get('social_facebook_login')) - + @endif @if (UserConfig::get('social_twitter_login')) - + @endif @if (UserConfig::get('social_google_login')) - + @endif

\ No newline at end of file