Browse Source

Add Telegram as OAuth option

兔姬桑 4 years ago
parent
commit
46a50b944d

+ 30 - 0
app/Components/Helpers.php

@@ -9,8 +9,10 @@ use App\Models\SsConfig;
 use App\Models\User;
 use App\Models\UserCreditLog;
 use App\Models\UserDataModifyLog;
+use App\Models\UserLoginLog;
 use App\Models\UserSubscribe;
 use DateTime;
+use Log;
 use Str;
 
 class Helpers
@@ -261,4 +263,32 @@ class Helpers
 
         return $marketing->save();
     }
+
+    /**
+     * 用户登录后操作.
+     *
+     * @param  User  $user  用户ID
+     * @param  string  $ip  IP地址
+     */
+    public static function userLoginAction(User $user, string $ip): void
+    {
+        $ipLocation = IP::getIPInfo($ip);
+
+        if (empty($ipLocation) || empty($ipLocation['country'])) {
+            Log::warning(trans('error.get_ip').':'.$ip);
+        }
+
+        $log = new UserLoginLog();
+        $log->user_id = $user->id;
+        $log->ip = $ip;
+        $log->country = $ipLocation['country'] ?? '';
+        $log->province = $ipLocation['province'] ?? '';
+        $log->city = $ipLocation['city'] ?? '';
+        $log->county = $ipLocation['county'] ?? '';
+        $log->isp = $ipLocation['isp'] ?? ($ipLocation['organization'] ?? '');
+        $log->area = $ipLocation['area'] ?? '';
+        $log->save();
+
+        $user->update(['last_login' => time()]); // 更新登录信息
+    }
 }

+ 1 - 31
app/Http/Controllers/AuthController.php

@@ -93,11 +93,7 @@ class AuthController extends Controller
                 '" target="_blank">👉【'.trans('common.active_item', ['attribute' => trans('common.account')]).'】👈</span></a><br>'.trans('auth.active.promotion.1'));
         }
 
-        // 写入登录日志
-        $this->addUserLoginLog($user->id, IP::getClientIp());
-
-        // 更新登录信息
-        $user->update(['last_login' => time()]);
+        Helpers::userLoginAction($user, IP::getClientIp()); // 用户登录后操作
 
         return redirect()->back();
     }
@@ -145,32 +141,6 @@ class AuthController extends Controller
         return false;
     }
 
-    /**
-     * 添加用户登录日志.
-     *
-     * @param  int  $userId  用户ID
-     * @param  string  $ip  IP地址
-     */
-    private function addUserLoginLog(int $userId, string $ip): void
-    {
-        $ipLocation = IP::getIPInfo($ip);
-
-        if (empty($ipLocation) || empty($ipLocation['country'])) {
-            Log::warning(trans('error.get_ip').':'.$ip);
-        }
-
-        $log = new UserLoginLog();
-        $log->user_id = $userId;
-        $log->ip = $ip;
-        $log->country = $ipLocation['country'] ?? '';
-        $log->province = $ipLocation['province'] ?? '';
-        $log->city = $ipLocation['city'] ?? '';
-        $log->county = $ipLocation['county'] ?? '';
-        $log->isp = $ipLocation['isp'] ?? ($ipLocation['organization'] ?? '');
-        $log->area = $ipLocation['area'] ?? '';
-        $log->save();
-    }
-
     // 退出
     public function logout(): RedirectResponse
     {

+ 49 - 54
app/Http/Controllers/OAuth/BaseController.php

@@ -6,12 +6,9 @@ use App\Components\Helpers;
 use App\Components\IP;
 use App\Http\Controllers\Controller;
 use App\Models\User;
-use App\Models\UserLoginLog;
 use App\Models\UserOauth;
 use Auth;
 use Laravel\Socialite\Facades\Socialite;
-use Log;
-use Redirect;
 use Str;
 
 class BaseController extends Controller
@@ -26,82 +23,80 @@ class BaseController extends Controller
             return Socialite::driver($type)->with(['redirect_uri' => route('oauth.register', ['type' => $type])])->redirect();
         }
 
-        return Socialite::driver($type)->with(['redirect_uri' => route('oauth.redirect', ['type' => $type])])->redirect();
+        return Socialite::driver($type)->with(['redirect_uri' => route('oauth.login', ['type' => $type])])->redirect();
     }
 
-    public function redirect($type)
+    public function simple(string $type)
     {
         $info = Socialite::driver($type)->user();
         if ($info) {
-            $user = User::whereUsername($info->getEmail())->first();
-            if (! $user) {
-                $user = UserOauth::whereIdentifier($info->getId())->first();
-                if ($user) {
-                    $user = $user->user;
-                }
+            $user = Auth::user();
+
+            if ($user) {
+                return $this->bind($type, $user, $info);
             }
-        }
 
-        if (isset($user)) {
-            Auth::login($user);
-            // 写入登录日志
-            $this->addUserLoginLog($user->id, IP::getClientIp());
+            return $this->login($type, $info);
+        }
 
-            // 更新登录信息
-            $user->update(['last_login' => time()]);
+        return redirect()->route('login')->withErrors('第三方登录失败!');
+    }
 
-            return Redirect::route('login');
-        }
+    private function bind(string $type, $user, $info)
+    {
+        $user->userAuths()->create([
+            'type'       => $type,
+            'identifier' => $info->getId(),
+            'credential' => $info->token,
+        ]);
 
-        return Redirect::route('login')->withErrors(trans('auth.error.not_found_user'));
+        return redirect()->route('profile')->with('successMsg', '绑定成功');
     }
 
-    /**
-     * 添加用户登录日志.
-     *
-     * @param  int  $userId  用户ID
-     * @param  string  $ip  IP地址
-     */
-    private function addUserLoginLog(int $userId, string $ip): void
+    private function login(string $type, $info)
     {
-        $ipLocation = IP::getIPInfo($ip);
+        $user = User::whereUsername($info->getEmail())->first();
+        if (! isset($user)) {
+            $auth = UserOauth::whereType($type)->whereIdentifier($info->getId())->first();
+            if (isset($auth)) {
+                $user = $auth->user;
+            }
+        }
+
+        if (isset($user)) {
+            Auth::login($user);
+            Helpers::userLoginAction($user, IP::getClientIp()); // 用户登录后操作
 
-        if (empty($ipLocation) || empty($ipLocation['country'])) {
-            Log::warning(trans('error.get_ip').':'.$ip);
+            return redirect()->route('login');
         }
 
-        $log = new UserLoginLog();
-        $log->user_id = $userId;
-        $log->ip = $ip;
-        $log->country = $ipLocation['country'] ?? '';
-        $log->province = $ipLocation['province'] ?? '';
-        $log->city = $ipLocation['city'] ?? '';
-        $log->county = $ipLocation['county'] ?? '';
-        $log->isp = $ipLocation['isp'] ?? ($ipLocation['organization'] ?? '');
-        $log->area = $ipLocation['area'] ?? '';
-        $log->save();
+        return redirect()->route('login')->withErrors(trans('auth.error.not_found_user'));
     }
 
-    public function bind($type)
+    public function binding($type)
     {
-        $user = Auth::user();
         $info = Socialite::driver($type)->stateless()->user();
 
-        if ($user) {
-            if ($info) {
-                $user->userAuths()->create([
-                    'type'       => $type,
-                    'identifier' => $info->getId(),
-                    'credential' => $info->token,
-                ]);
-
-                return redirect()->route('profile')->with('successMsg', '绑定成功');
+        if ($info) {
+            $user = Auth::user();
+            if ($user) {
+                return $this->bind($type, $user, $info);
             }
 
             return redirect()->route('profile')->withErrors('绑定失败');
         }
 
-        return redirect()->route('profile')->withErrors('无用户');
+        return redirect()->route('login')->withErrors('第三方登录失败!');
+    }
+
+    public function logining($type)
+    {
+        $info = Socialite::driver($type)->user();
+        if ($info) {
+            return $this->login($type, $info);
+        }
+
+        return redirect()->route('login')->withErrors('第三方登录失败!');
     }
 
     public function register($type)
@@ -135,6 +130,6 @@ class BaseController extends Controller
             return redirect()->route('login')->withErrors('已注册,请直接登录');
         }
 
-        return redirect()->route('register')->withErrors('绑定失败');
+        return redirect()->route('login')->withErrors('第三方登录失败!');
     }
 }

+ 4 - 0
app/Providers/EventServiceProvider.php

@@ -4,6 +4,7 @@ namespace App\Providers;
 
 use Illuminate\Auth\Events\Registered;
 use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
+use SocialiteProviders\Manager\SocialiteWasCalled;
 
 class EventServiceProvider extends ServiceProvider
 {
@@ -14,6 +15,9 @@ class EventServiceProvider extends ServiceProvider
      */
     protected $listen = [
         Registered::class => [],
+        SocialiteWasCalled::class => [
+            'SocialiteProviders\\Telegram\\TelegramExtendSocialite@handle',
+        ],
     ];
 
     /**

+ 1 - 0
composer.json

@@ -33,6 +33,7 @@
     "phpoffice/phpspreadsheet": "^1.16",
     "rap2hpoutre/laravel-log-viewer": "^1.7",
     "riverslei/payment": "^5.1",
+    "socialiteproviders/telegram": "^4.1",
     "spatie/laravel-permission": "^4.0",
     "srmklive/paypal": "^1.8",
     "stripe/stripe-php": "^7.69",

+ 127 - 1
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": "b06a0feb668efb92a381963f52f0b265",
+    "content-hash": "d2b1ca543427ed7f9993d7350c36a649",
     "packages": [
         {
             "name": "asm89/stack-cors",
@@ -5130,6 +5130,132 @@
             },
             "time": "2020-05-04T03:07:17+00:00"
         },
+        {
+            "name": "socialiteproviders/manager",
+            "version": "4.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/SocialiteProviders/Manager.git",
+                "reference": "0f5e82af0404df0080bdc5c105cef936c1711524"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/0f5e82af0404df0080bdc5c105cef936c1711524",
+                "reference": "0f5e82af0404df0080bdc5c105cef936c1711524",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "illuminate/support": "^6.0|^7.0|^8.0",
+                "laravel/socialite": "~4.0|~5.0",
+                "php": "^7.2 || ^8.0"
+            },
+            "require-dev": {
+                "mockery/mockery": "^1.2",
+                "phpunit/phpunit": "^9.0"
+            },
+            "type": "library",
+            "extra": {
+                "laravel": {
+                    "providers": [
+                        "SocialiteProviders\\Manager\\ServiceProvider"
+                    ]
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "SocialiteProviders\\Manager\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Andy Wendt",
+                    "email": "[email protected]"
+                },
+                {
+                    "name": "Anton Komarev",
+                    "email": "[email protected]"
+                },
+                {
+                    "name": "Miguel Piedrafita",
+                    "email": "[email protected]"
+                },
+                {
+                    "name": "atymic",
+                    "email": "[email protected]",
+                    "homepage": "https://atymic.dev"
+                }
+            ],
+            "description": "Easily add new or override built-in providers in Laravel Socialite.",
+            "homepage": "https://socialiteproviders.com/",
+            "support": {
+                "issues": "https://github.com/SocialiteProviders/Manager/issues",
+                "source": "https://github.com/SocialiteProviders/Manager/tree/4.0.1"
+            },
+            "time": "2020-12-01T23:09:06+00:00"
+        },
+        {
+            "name": "socialiteproviders/telegram",
+            "version": "4.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/SocialiteProviders/Telegram.git",
+                "reference": "9d917894c7706494c147d0a0076e6c56efbefec2"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/SocialiteProviders/Telegram/zipball/9d917894c7706494c147d0a0076e6c56efbefec2",
+                "reference": "9d917894c7706494c147d0a0076e6c56efbefec2",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": "^7.2 || ^8.0",
+                "socialiteproviders/manager": "~4.0"
+            },
+            "type": "library",
+            "extra": {
+                "laravel": {
+                    "aliases": {
+                        "Socialite": "Laravel\\Socialite\\Facades\\Socialite"
+                    }
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "SocialiteProviders\\Telegram\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Adnan RIHAN",
+                    "email": "[email protected]"
+                }
+            ],
+            "description": "Telegram Authentication Provider for Laravel Socialite",
+            "support": {
+                "source": "https://github.com/SocialiteProviders/Telegram/tree/4.1.1"
+            },
+            "time": "2021-01-11T22:24:42+00:00"
+        },
         {
             "name": "spatie/laravel-permission",
             "version": "4.2.0",

+ 2 - 0
config/common.php

@@ -35,6 +35,7 @@ return [
             'github'    => 'GitHub',
             'gitlab'    => 'GitLab',
             'bitbucket' => 'Bitbucket',
+            'telegram'  => 'Telegram',
         ],
         'icon'   => [
             'facebook'  => 'fa-facebook',
@@ -44,6 +45,7 @@ return [
             'github'    => 'fa-github',
             'gitlab'    => 'fa-gitlab',
             'bitbucket' => 'fa-bitbucket',
+            'telegram'  => 'fa-telegram',
         ],
     ],
 ];

+ 7 - 0
config/services.php

@@ -71,4 +71,11 @@ return [
         'client_secret' => env('BITBUCKET_CLIENT_SECRET'),
         'redirect'      => '',
     ],
+
+    'telegram' => [
+        'bot' => env('TELEGRAM_BOT_NAME'),  // The bot's username
+        'client_id' => null,
+        'client_secret' => env('TELEGRAM_TOKEN'),
+        'redirect' => '/oauth/telegram/redirect',
+    ],
 ];

+ 9 - 3
resources/views/auth/login.blade.php

@@ -37,9 +37,15 @@
                 <span> 一键登录 </span>
             </div>
             @foreach (json_decode(sysConfig('oauth_path')) as $item)
-                <a class="btn btn-icon btn-pure" href="{{route('oauth.route', ['type' => $item, 'action' => 'login'])}}">
-                    <i class="fab {{config('common.oauth.icon')[$item]}} fa-lg" aria-hidden="true"></i>
-                </a>
+                @if ($item === 'telegram')
+                    <div>
+                        {!! Socialite::driver('telegram')->getButton() !!}
+                    </div>
+                @else
+                    <a class="btn btn-icon btn-pure" href="{{route('oauth.route', ['type' => $item, 'action' => 'login'])}}">
+                        <i class="fab {{config('common.oauth.icon')[$item]}} fa-lg" aria-hidden="true"></i>
+                    </a>
+                @endif
             @endforeach
         </div>
     @endif

+ 3 - 2
routes/web.php

@@ -17,9 +17,10 @@ Route::middleware(['isForbidden', 'affiliate', 'isMaintenance'])->group(function
     Route::get('login', 'AuthController@showLoginForm')->middleware('isSecurity')->name('login'); // 登录页面
 
     Route::namespace('OAuth')->prefix('oauth/')->name('oauth.')->group(function () { // 用户第三方登录默认登录/转跳方式
-        Route::get('{type}/redirect', 'BaseController@redirect')->name('redirect');
-        Route::get('{type}/bind', 'BaseController@bind')->name('bind');
+        Route::get('{type}/login', 'BaseController@logining')->name('login');
+        Route::get('{type}/bind', 'BaseController@binding')->name('bind');
         Route::get('{type}/register', 'BaseController@register')->name('register');
+        Route::get('{type}/redirect', 'BaseController@simple')->name('simple');
         Route::get('{type}/{action}', 'BaseController@route')->name('route');
     });