OAuthController.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Models\User;
  4. use App\Models\UserOauth;
  5. use App\Utils\Helpers;
  6. use App\Utils\IP;
  7. use Illuminate\Http\RedirectResponse;
  8. use Laravel\Socialite\Facades\Socialite;
  9. use Str;
  10. class OAuthController extends Controller
  11. {
  12. public function unbind(string $provider): RedirectResponse
  13. {
  14. $user = auth()->user();
  15. if ($user && $user->userAuths()->whereType($provider)->delete()) {
  16. return redirect()->back()->with('successMsg', trans('common.success_item', ['attribute' => trans('user.oauth.unbind')]));
  17. }
  18. return redirect()->back()->withErrors(trans('common.failed_item', ['attribute' => trans('user.oauth.unbind')]));
  19. }
  20. public function bind(string $provider): RedirectResponse
  21. {
  22. config(["services.$provider.redirect" => route('oauth.bind', ['provider' => $provider])]);
  23. $authInfo = Socialite::driver($provider)->stateless()->user();
  24. if (! $authInfo) {
  25. return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed'));
  26. }
  27. $user = auth()->user();
  28. if (! $user) {
  29. return redirect()->back()->withErrors(trans('common.failed_item', ['attribute' => trans('user.oauth.bind')]));
  30. }
  31. return $this->bindLogic($provider, $user, $authInfo);
  32. }
  33. private function bindLogic(string $provider, User $user, \Laravel\Socialite\Contracts\User $authInfo): RedirectResponse
  34. {
  35. $data = [
  36. 'type' => $provider,
  37. 'identifier' => $authInfo->getId(),
  38. 'credential' => $authInfo->token,
  39. ];
  40. $auth = $user->userAuths()->whereType($provider)->first();
  41. if ($auth) {
  42. $user->userAuths()->whereType($provider)->update($data);
  43. $message = trans('common.success_item', ['attribute' => trans('user.oauth.rebind')]);
  44. } else {
  45. $user->userAuths()->create($data);
  46. $message = trans('common.success_item', ['attribute' => trans('user.oauth.bind')]);
  47. }
  48. return redirect()->back()->with('successMsg', $message);
  49. }
  50. public function register(string $provider): RedirectResponse
  51. {
  52. config(["services.$provider.redirect" => route('oauth.register', ['provider' => $provider])]);
  53. if (! sysConfig('is_register')) {
  54. return redirect()->route('register')->withErrors(trans('auth.register.error.disable'));
  55. }
  56. if ((int) sysConfig('is_invite_register') === 2) {
  57. return redirect()->route('register')->withErrors(trans('validation.required', ['attribute' => trans('user.invite.attribute')]));
  58. }
  59. $registerInfo = Socialite::driver($provider)->stateless()->user();
  60. if (! $registerInfo) {
  61. return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed'));
  62. }
  63. $user = User::whereUsername($registerInfo->getEmail())->first();
  64. if (! $user) { // 邮箱未被注册
  65. $userAuth = UserOauth::whereType($provider)->whereIdentifier($registerInfo->getId())->first();
  66. if (! $userAuth) { // 第三方账号未被绑定
  67. $user = Helpers::addUser($registerInfo->getEmail(), Str::random(), MiB * sysConfig('default_traffic'), (int) sysConfig('default_days'), $registerInfo->getNickname(), 1);
  68. $user->userAuths()->create([
  69. 'type' => $provider,
  70. 'identifier' => $registerInfo->getId(),
  71. 'credential' => $registerInfo->token,
  72. ]);
  73. return $this->handleLogin($user);
  74. }
  75. }
  76. return redirect()->route('login')->withErrors(trans('auth.oauth.registered'));
  77. }
  78. private function handleLogin(User $user): RedirectResponse
  79. {
  80. auth()->login($user);
  81. Helpers::userLoginAction($user, IP::getClientIp());
  82. return redirect()->route('login');
  83. }
  84. public function login(string $provider): RedirectResponse
  85. {
  86. config(["services.$provider.redirect" => route('oauth.login', ['provider' => $provider])]);
  87. $authInfo = Socialite::driver($provider)->stateless()->user();
  88. if ($authInfo) {
  89. $auth = UserOauth::whereType($provider)->whereIdentifier($authInfo->getId())->first();
  90. if ($auth && ($user = $auth->user)) { // 如果第三方登录有记录,直接登录用户
  91. return $this->handleLogin($user);
  92. }
  93. $user = User::whereUsername($authInfo->getEmail())->first();
  94. if ($user) { // 如果用户存在,执行绑定逻辑并登录用户
  95. $this->bindLogic($provider, $user, $authInfo);
  96. return $this->handleLogin($user);
  97. }
  98. // 如果用户不存在,则返回错误消息
  99. return redirect()->route('login')->withErrors(trans('auth.error.not_found_user'));
  100. }
  101. return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed'));
  102. }
  103. public function redirect(string $provider, string $operation = 'login'): RedirectResponse
  104. {
  105. $redirectRoutes = [
  106. 'bind' => 'oauth.bind',
  107. 'register' => 'oauth.register',
  108. 'login' => 'oauth.login',
  109. ];
  110. $key = "services.$provider.redirect";
  111. config([$key => route($redirectRoutes[$operation], ['provider' => $provider])]);
  112. return Socialite::driver($provider)->stateless()->redirect();
  113. }
  114. }