OAuthController.php 5.2 KB

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