]> BookStack Code Mirror - bookstack/commitdiff
Added facebook, slack & twitter sign in options.
authorDan Brown <redacted>
Sat, 4 Feb 2017 11:01:49 +0000 (11:01 +0000)
committerDan Brown <redacted>
Sat, 4 Feb 2017 11:01:49 +0000 (11:01 +0000)
Also added icon svg blade helper.
Closes #125. Starts #213.
Requires documentation.

19 files changed:
app/Providers/AppServiceProvider.php
app/Providers/EventServiceProvider.php
app/Providers/SocialiteServiceProvider.php [deleted file]
app/Services/SocialAuthService.php
app/helpers.php
composer.json
composer.lock
config/app.php
config/services.php
resources/assets/icons/facebook.svg [new file with mode: 0644]
resources/assets/icons/github.svg [new file with mode: 0644]
resources/assets/icons/google.svg [new file with mode: 0644]
resources/assets/icons/slack.svg [new file with mode: 0644]
resources/assets/icons/twitter.svg [new file with mode: 0644]
resources/assets/sass/_text.scss
resources/views/auth/login.blade.php
resources/views/auth/register.blade.php
resources/views/public.blade.php
resources/views/users/edit.blade.php

index 40a1eef3d81d5ecfdbbf1eb27f41d0b17ceb19b6..118271f51bfced69723353d61c31289c6ae91a4e 100644 (file)
@@ -17,6 +17,10 @@ class AppServiceProvider extends ServiceProvider
             $imageMimes = ['image/png', 'image/bmp', 'image/gif', 'image/jpeg', 'image/jpg', 'image/tiff', 'image/webp'];
             return in_array($value->getMimeType(), $imageMimes);
         });
+
+        \Blade::directive('icon', function($expression) {
+            return "<?php echo icon($expression); ?>";
+        });
     }
 
     /**
index 3802f20c0de0ba7c4c9697c8736b4598feed3538..d82a560f99987fef423adb6db969b01cc5314f49 100644 (file)
@@ -4,6 +4,7 @@ namespace BookStack\Providers;
 
 use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
 use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
+use SocialiteProviders\Manager\SocialiteWasCalled;
 
 class EventServiceProvider extends ServiceProvider
 {
@@ -13,8 +14,8 @@ class EventServiceProvider extends ServiceProvider
      * @var array
      */
     protected $listen = [
-        'BookStack\Events\SomeEvent' => [
-            'BookStack\Listeners\EventListener',
+        SocialiteWasCalled::class => [
+            'SocialiteProviders\Slack\SlackExtendSocialite@handle',
         ],
     ];
 
diff --git a/app/Providers/SocialiteServiceProvider.php b/app/Providers/SocialiteServiceProvider.php
deleted file mode 100644 (file)
index f7fb30f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php namespace BookStack\Providers;
-
-
-use Illuminate\Support\ServiceProvider;
-
-class SocialiteServiceProvider extends ServiceProvider
-{
-    /**
-     * Indicates if loading of the provider is deferred.
-     *
-     * @var bool
-     */
-    protected $defer = true;
-
-    /**
-     * Register the service provider.
-     *
-     * @return void
-     */
-    public function register()
-    {
-        $this->app->bindShared('Laravel\Socialite\Contracts\Factory', function ($app) {
-            return new SocialiteManager($app);
-        });
-    }
-
-    /**
-     * Get the services provided by the provider.
-     *
-     * @return array
-     */
-    public function provides()
-    {
-        return ['Laravel\Socialite\Contracts\Factory'];
-    }
-}
\ No newline at end of file
index 5edd4cad76a9c361a1a88a17971069551c049780..710f956963f56885d35d21a56536d618e78c9327 100644 (file)
@@ -14,7 +14,7 @@ class SocialAuthService
     protected $socialite;
     protected $socialAccount;
 
-    protected $validSocialDrivers = ['google', 'github'];
+    protected $validSocialDrivers = ['google', 'github', 'facebook', 'slack', 'twitter'];
 
     /**
      * SocialAuthService constructor.
@@ -211,7 +211,6 @@ class SocialAuthService
      */
     public function detachSocialAccount($socialDriver)
     {
-        session();
         user()->socialAccounts()->where('driver', '=', $socialDriver)->delete();
         session()->flash('success', trans('settings.users_social_disconnected', ['socialAccount' => title_case($socialDriver)]));
         return redirect(user()->getEditUrl());
index 6decb08e96517233086eb9fe2e76ad002ce892fa..8103ad1ff9e72033e49abbeff643a27db67e610b 100644 (file)
@@ -117,6 +117,16 @@ function redirect($to = null, $status = 302, $headers = [], $secure = null)
     return app('redirect')->to($to, $status, $headers, $secure);
 }
 
+function icon($name, $attrs = []) {
+    $iconPath = resource_path('assets/icons/' . $name . '.svg');
+    $attrString = ' ';
+    foreach ($attrs as $attrName => $attr) {
+        $attrString .=  $attrName . '="' . $attr . '" ';
+    }
+    $fileContents = file_get_contents($iconPath);
+    return  str_replace('<svg', '<svg' . $attrString, $fileContents);
+}
+
 /**
  * Generate a url with multiple parameters for sorting purposes.
  * Works out the logic to set the correct sorting direction
@@ -147,4 +157,4 @@ function sortUrl($path, $data, $overrideData = [])
     if (count($queryStringSections) === 0) return $path;
 
     return baseUrl($path . '?' . implode('&', $queryStringSections));
-}
+}
\ No newline at end of file
index f0cf9c4ae03b9b81a514e101c43fff3ee79a7f97..959bdbdc2930bc256682a0dae944a51a96f58c7b 100644 (file)
@@ -17,7 +17,8 @@
         "predis/predis": "^1.1",
         "gathercontent/htmldiff": "^0.2.1",
         "barryvdh/laravel-snappy": "^0.3.1",
-        "laravel/browser-kit-testing": "^1.0"
+        "laravel/browser-kit-testing": "^1.0",
+        "socialiteproviders/slack": "^3.0"
     },
     "require-dev": {
         "fzaninotto/faker": "~1.4",
index e0699361192abe004265595aff7d61ca4f7cd5f2..586213e57853a7655471c8e380c2aea5ea5a641f 100644 (file)
@@ -4,8 +4,8 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "c0bb098e9430247688c61ebd66d3d51c",
-    "content-hash": "3bb8bb2f252327c32aa40c686d1327cc",
+    "hash": "27dd30e92f700ea9a8c2a0a2327d4f9f",
+    "content-hash": "e851e9fd06efac8362604c39b0a17542",
     "packages": [
         {
             "name": "aws/aws-sdk-php",
             ],
             "time": "2016-11-22 19:21:44"
         },
+        {
+            "name": "socialiteproviders/manager",
+            "version": "v3.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/SocialiteProviders/Manager.git",
+                "reference": "3bf2b405b6bfd4bec66f706f5390323f51033eb1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/3bf2b405b6bfd4bec66f706f5390323f51033eb1",
+                "reference": "3bf2b405b6bfd4bec66f706f5390323f51033eb1",
+                "shasum": ""
+            },
+            "require": {
+                "laravel/socialite": "~3.0",
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "mockery/mockery": "^0.9.4",
+                "phpunit/phpunit": "^5.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "SocialiteProviders\\Manager\\": "src/",
+                    "SocialiteProviders\\Manager\\Test\\": "tests/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Andy Wendt",
+                    "email": "[email protected]"
+                }
+            ],
+            "description": "Easily add new or override built-in providers in Laravel Socialite.",
+            "time": "2017-01-27 08:35:03"
+        },
+        {
+            "name": "socialiteproviders/slack",
+            "version": "v3.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/SocialiteProviders/Slack.git",
+                "reference": "a0d676a07bb8293547df6678f1da0258ac40bfec"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/SocialiteProviders/Slack/zipball/a0d676a07bb8293547df6678f1da0258ac40bfec",
+                "reference": "a0d676a07bb8293547df6678f1da0258ac40bfec",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0",
+                "socialiteproviders/manager": "~3.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "SocialiteProviders\\Slack\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Brian Faust",
+                    "email": "[email protected]"
+                }
+            ],
+            "description": "Slack OAuth2 Provider for Laravel Socialite",
+            "time": "2017-01-25 09:48:29"
+        },
         {
             "name": "swiftmailer/swiftmailer",
             "version": "v5.4.5",
index 0c3e1e71c5360ebb63e58587fd0a7c9197ec296c..bf4f84fc78c362651f32842945948d62db201e3b 100644 (file)
@@ -139,7 +139,7 @@ return [
         Illuminate\Validation\ValidationServiceProvider::class,
         Illuminate\View\ViewServiceProvider::class,
         Illuminate\Notifications\NotificationServiceProvider::class,
-        Laravel\Socialite\SocialiteServiceProvider::class,
+        SocialiteProviders\Manager\ServiceProvider::class,
 
         /**
          * Third Party
index d71ff4a26d27a8987f11835e4472dc82c96865df..8c17897e49e96d40fd83a145d479345006002785 100644 (file)
@@ -49,6 +49,24 @@ return [
         'redirect'      => env('APP_URL') . '/login/service/google/callback',
     ],
 
+    'slack'   => [
+        'client_id'     => env('SLACK_APP_ID', false),
+        'client_secret' => env('SLACK_APP_SECRET', false),
+        'redirect'      => env('APP_URL') . '/login/service/slack/callback',
+    ],
+
+    'facebook'   => [
+        'client_id'     => env('FACEBOOK_APP_ID', false),
+        'client_secret' => env('FACEBOOK_APP_SECRET', false),
+        'redirect'      => env('APP_URL') . '/login/service/facebook/callback',
+    ],
+
+    'twitter'   => [
+        'client_id'     => env('TWITTER_APP_ID', false),
+        'client_secret' => env('TWITTER_APP_SECRET', false),
+        'redirect'      => env('APP_URL') . '/login/service/twitter/callback',
+    ],
+
     'ldap' => [
         'server' => env('LDAP_SERVER', false),
         'dn' => env('LDAP_DN', false),
diff --git a/resources/assets/icons/facebook.svg b/resources/assets/icons/facebook.svg
new file mode 100644 (file)
index 0000000..7bfafd2
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 266.893 266.895"><path fill="#3C5A99" d="M248.082 262.307c7.854 0 14.223-6.37 14.223-14.225V18.812c0-7.857-6.368-14.224-14.223-14.224H18.812c-7.857 0-14.224 6.367-14.224 14.224v229.27c0 7.855 6.366 14.225 14.224 14.225h229.27z"/><path fill="#FFF" d="M182.41 262.307v-99.803h33.498l5.016-38.895H182.41V98.775c0-11.26 3.126-18.935 19.274-18.935l20.596-.01V45.047c-3.562-.474-15.788-1.533-30.012-1.533-29.695 0-50.025 18.126-50.025 51.413v28.684h-33.585v38.894h33.585v99.803h40.166z"/></svg>
\ No newline at end of file
diff --git a/resources/assets/icons/github.svg b/resources/assets/icons/github.svg
new file mode 100644 (file)
index 0000000..ae6dc6f
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path fill="#333333" fill-rule="evenodd" d="M31.9.693c-17.672 0-32 14.327-32 32 0 14.14 9.17 26.132 21.886 30.365 1.6.293 2.184-.695 2.184-1.544 0-.758-.028-2.77-.043-5.44-8.9 1.932-10.78-4.292-10.78-4.292-1.455-3.695-3.553-4.68-3.553-4.68-2.905-1.985.22-1.946.22-1.946 3.212.228 4.9 3.3 4.9 3.3 2.856 4.888 7.492 3.476 9.315 2.66.29-2.07 1.11-3.48 2.03-4.28-7.11-.807-14.58-3.554-14.58-15.816 0-3.493 1.243-6.35 3.29-8.586-.33-.81-1.428-4.063.313-8.47 0 0 2.687-.86 8.8 3.28 2.552-.708 5.29-1.063 8.01-1.075 2.718.01 5.457.36 8.01 1.07 6.11-4.14 8.793-3.28 8.793-3.28 1.747 4.403.65 7.66.32 8.47 2.05 2.233 3.29 5.09 3.29 8.582 0 12.293-7.483 15-14.61 15.79 1.15.99 2.17 2.94 2.17 5.926 0 4.277-.04 7.73-.04 8.777 0 .857.578 1.853 2.2 1.54 12.71-4.235 21.87-16.22 21.87-30.355 0-17.674-14.326-32-32-32"/></svg>
\ No newline at end of file
diff --git a/resources/assets/icons/google.svg b/resources/assets/icons/google.svg
new file mode 100644 (file)
index 0000000..34ed160
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><g fill="none" fill-rule="evenodd"><path fill="#4285f4" d="M62.735 32.712c0-2.27-.204-4.45-.582-6.545H32.015v12.378h17.222c-.742 4-2.997 7.39-6.386 9.658v8.03h10.344c6.05-5.57 9.542-13.775 9.542-23.52z"/><path fill="#34a853" d="M32.015 63.985c8.64 0 15.883-2.865 21.178-7.753l-10.342-8.03c-2.863 1.92-6.53 3.056-10.834 3.056-8.335 0-15.39-5.63-17.906-13.193H3.417v8.29c5.266 10.46 16.088 17.63 28.597 17.63z"/><path fill="#fbbc05" d="M14.11 38.065c-.64-1.92-1.004-3.97-1.004-6.08s.363-4.16 1.003-6.08v-8.29H3.416C1.25 21.935.015 26.82.015 31.985c0 5.163 1.236 10.05 3.403 14.37l10.69-8.29z"/><path fill="#ea4335" d="M32.015 12.712c4.698 0 8.916 1.615 12.233 4.786l9.178-9.178C47.884 3.156 40.64-.015 32.016-.015c-12.51 0-23.332 7.17-28.598 17.63l10.69 8.29c2.518-7.563 9.572-13.193 17.907-13.193z"/><path d="M.015-.015h64v64h-64v-64z"/></g></svg>
\ No newline at end of file
diff --git a/resources/assets/icons/slack.svg b/resources/assets/icons/slack.svg
new file mode 100644 (file)
index 0000000..5280f97
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" viewBox="0 0 64 64"><style id="style3">.st0{fill:#ECB32D;} .st1{fill:#63C1A0;} .st2{fill:#E01A59;} .st3{fill:#331433;} .st4{fill:#D62027;} .st5{fill:#89D3DF;} .st6{fill:#258B74;} .st7{fill:#819C3C;}</style><g id="g5"><g id="g7"><path id="path9" fill="#ecb32d" d="M41.478 3.945C40.48.95 37.28-.677 34.288.27c-2.992.997-4.62 4.2-3.674 7.195l14.748 45.383c.997 2.784 4.042 4.36 6.928 3.52 3.044-.893 4.88-4.098 3.884-7.04 0-.104-14.696-45.383-14.696-45.383z" class="st0"/><path id="path11" fill="#63c1a0" d="M18.648 11.352c-.997-2.994-4.2-4.623-7.19-3.677-2.992.998-4.62 4.202-3.674 7.196l14.748 45.39c.997 2.784 4.04 4.36 6.928 3.52 3.044-.894 4.88-4.098 3.883-7.04 0-.105-14.695-45.383-14.695-45.383z" class="st1"/><path id="path13" fill="#e01a59" d="M60.058 41.502c2.99-.998 4.618-4.202 3.674-7.196-.997-2.994-4.2-4.622-7.19-3.677L11.14 45.44c-2.78.998-4.356 4.045-3.516 6.934.892 3.046 4.094 4.885 7.033 3.887.104 0 45.398-14.76 45.398-14.76z" class="st2"/><path id="path15" fill="#331433" d="M20.59 54.372c2.94-.946 6.77-2.207 10.864-3.52-.945-2.94-2.204-6.776-3.516-10.873l-10.865 3.514L20.59 54.37z" class="st3"/><path id="path17" fill="#d62027" d="M43.473 46.913c4.094-1.313 7.925-2.574 10.864-3.52-.945-2.94-2.204-6.776-3.516-10.873l-10.86 3.52 3.518 10.873z" class="st4"/><path id="path19" fill="#89d3df" d="M52.605 18.653c2.992-.998 4.62-4.202 3.674-7.196-1-2.994-4.2-4.623-7.19-3.677L3.74 22.54c-2.78.998-4.356 4.045-3.516 6.934.892 3.046 4.094 4.885 7.033 3.887.104 0 45.345-14.703 45.345-14.703z" class="st5"/><path id="path21" fill="#258b74" d="M13.19 31.47c2.94-.946 6.77-2.206 10.864-3.52-1.312-4.097-2.572-7.93-3.517-10.873l-10.864 3.52L13.19 31.47z" class="st6"/><path id="path23" fill="#819c3c" d="M36.02 24.063c4.094-1.313 7.925-2.573 10.864-3.52-1.312-4.096-2.57-7.93-3.516-10.872l-10.864 3.52 3.516 10.877z" class="st7"/></g></g></svg>
\ No newline at end of file
diff --git a/resources/assets/icons/twitter.svg b/resources/assets/icons/twitter.svg
new file mode 100644 (file)
index 0000000..fa4d59e
--- /dev/null
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path fill="#00aced" d="M64 12.145c-2.355 1.045-4.886 1.75-7.54 2.068 2.71-1.625 4.79-4.198 5.772-7.265-2.538 1.505-5.347 2.598-8.338 3.187-2.395-2.552-5.808-4.147-9.584-4.147-7.252 0-13.13 5.88-13.13 13.13 0 1.03.115 2.032.34 2.993-10.914-.543-20.59-5.77-27.065-13.714-1.13 1.94-1.777 4.195-1.777 6.6 0 4.556 2.317 8.575 5.84 10.93-2.15-.068-4.176-.66-5.946-1.642v.166c0 6.36 4.525 11.667 10.53 12.874-1.1.3-2.26.46-3.458.46-.846 0-1.67-.08-2.47-.234 1.67 5.215 6.52 9.012 12.265 9.117-4.498 3.522-10.16 5.62-16.31 5.62-1.06 0-2.107-.06-3.13-.183C5.81 55.827 12.71 58 20.124 58c24.15 0 37.358-20.008 37.358-37.36 0-.568-.013-1.134-.038-1.698 2.566-1.85 4.792-4.163 6.552-6.797"/></svg>
\ No newline at end of file
index aac4298ea96384d2367616f86309e2c6b8b929a7..79d3c3a922c334d7ca0fcf345c87238335d05043 100644 (file)
@@ -16,7 +16,7 @@ h2 {
 }
 h3 {
   font-size: 2.333em;
-  line-height: 1.571428572em;
+  line-height: 1.221428572em;
   margin-top: 0.78571429em;
   margin-bottom: 0.43137255em;
 }
@@ -71,6 +71,13 @@ a, .link {
     padding-right: 0;
     padding-left: $-s;
   }
+  &.icon {
+    display: inline-block;
+  }
+  svg {
+    position: relative;
+    display: inline-block;
+  }
 }
 
 /*
@@ -84,7 +91,6 @@ p, ul, ol, pre, table, blockquote {
 hr {
   border: 0;
   height: 1px;
-  border: 0;
   background: #EAEAEA;
   margin-bottom: $-l;
   &.faded {
index 928565156e4dc78f5f1ceabd93dc8704de00f6f3..6c8b1720cbd37461b982eb67a16e0b61c73ab6f7 100644 (file)
             @if(count($socialDrivers) > 0)
                 <hr class="margin-top">
                 <h3 class="text-muted">{{ trans('auth.social_login') }}</h3>
-                @if(isset($socialDrivers['google']))
-                    <a id="social-login-google" href="{{ baseUrl("/login/service/google") }}" style="color: #DC4E41;"><i class="zmdi zmdi-google-plus-box zmdi-hc-4x"></i></a>
-                @endif
-                @if(isset($socialDrivers['github']))
-                    <a id="social-login-github" href="{{ baseUrl("/login/service/github") }}" style="color:#444;"><i class="zmdi zmdi-github zmdi-hc-4x"></i></a>
-                @endif
+                @foreach($socialDrivers as $driver => $enabled)
+                    <a id="social-login-{{$driver}}" href="{{ baseUrl("/login/service/" . $driver) }}">@icon($driver, ['width' => 56])</a>
+                        &nbsp;
+                @endforeach
             @endif
         </div>
     </div>
index 7a119ddba880f8ee8f14af1e2999babf6c9aed8d..860508df04830f2c5e998ea0d1f4a560c18f2215 100644 (file)
                 <hr class="margin-top">
                 <h3 class="text-muted">{{ trans('auth.social_registration') }}</h3>
                 <p class="text-small">{{ trans('auth.social_registration_text') }}</p>
-                @if(isset($socialDrivers['google']))
-                    <a href="{{ baseUrl("/register/service/google") }}" style="color: #DC4E41;"><i class="zmdi zmdi-google-plus-box zmdi-hc-4x"></i></a>
-                @endif
-                @if(isset($socialDrivers['github']))
-                    <a href="{{ baseUrl("/register/service/github") }}" style="color:#444;"><i class="zmdi zmdi-github zmdi-hc-4x"></i></a>
-                @endif
+                @foreach($socialDrivers as $driver => $enabled)
+                    <a href="{{ baseUrl("/register/service/" . $driver) }}">@icon($driver, ['width' => 56])</a>
+                    &nbsp;
+                @endforeach
             @endif
         </div>
     </div>
index 05cf043fd69a4a9855d21e32b53b3fb645849b73..ea2069b866162abdc345528295ead45234eda09c 100644 (file)
@@ -30,7 +30,7 @@
 <header id="header">
     <div class="container">
         <div class="row">
-            <div class="col-md-6">
+            <div class="col-sm-6">
 
                 <a href="{{ baseUrl('/') }}" class="logo">
                     @if(setting('app-logo', '') !== 'none')
@@ -41,7 +41,7 @@
                     @endif
                 </a>
             </div>
-            <div class="col-md-6">
+            <div class="col-sm-6">
                 <div class="float right">
                     <div class="links text-center">
                         @yield('header-buttons')
index c5d512725ba7ab82a952172f85aa791285afb0ab..bf10b829d0620de193e43711833fa6787d548db5 100644 (file)
             <h3>{{ trans('settings.users_social_accounts') }}</h3>
             <p class="text-muted">{{ trans('settings.users_social_accounts_info') }}</p>
             <div class="row">
-                @if(isset($activeSocialDrivers['google']))
+                @foreach($activeSocialDrivers as $driver => $enabled)
                     <div class="col-md-3 text-center">
-                        <div><i class="zmdi zmdi-google-plus-box zmdi-hc-4x" style="color: #DC4E41;"></i></div>
+                        <div>@icon($driver, ['width' => 56])</div>
                         <div>
-                            @if($user->hasSocialAccount('google'))
-                                <a href="{{ baseUrl("/login/service/google/detach") }}" class="button neg">{{ trans('settings.users_social_disconnect') }}</a>
+                            @if($user->hasSocialAccount($driver))
+                                <a href="{{ baseUrl("/login/service/{$driver}/detach") }}" class="button neg">{{ trans('settings.users_social_disconnect') }}</a>
                             @else
-                                <a href="{{ baseUrl("/login/service/google") }}" class="button pos">{{ trans('settings.users_social_connect') }}</a>
+                                <a href="{{ baseUrl("/login/service/{$driver}") }}" class="button pos">{{ trans('settings.users_social_connect') }}</a>
                             @endif
                         </div>
                     </div>
-                @endif
-                @if(isset($activeSocialDrivers['github']))
-                    <div class="col-md-3 text-center">
-                        <div><i class="zmdi zmdi-github zmdi-hc-4x" style="color: #444;"></i></div>
-                        <div>
-                            @if($user->hasSocialAccount('github'))
-                                <a href="{{ baseUrl("/login/service/github/detach") }}" class="button neg">{{ trans('settings.users_social_disconnect') }}</a>
-                            @else
-                                <a href="{{ baseUrl("/login/service/github") }}" class="button pos">{{ trans('settings.users_social_connect') }}</a>
-                            @endif
-                        </div>
-                    </div>
-                @endif
+                @endforeach
             </div>
         @endif