Fixed OAuth not function and improve the code quality

This commit is contained in:
BrettonYe
2024-04-08 23:31:36 +08:00
parent 2ca6965074
commit 66d9f22f6e
5 changed files with 122 additions and 100 deletions

View File

@@ -13,118 +13,140 @@ use Str;
class OAuthController extends Controller
{
public function simple(string $type): RedirectResponse
{
$info = Socialite::driver($type)->stateless()->user();
if ($info) {
$user = Auth::user();
if ($user) {
return $this->binding($type, $user, $info);
}
return $this->logging($type, $info);
}
return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed'));
}
private function binding(string $type, User $user, \Laravel\Socialite\Contracts\User $OauthUser): RedirectResponse
{
$data = ['type' => $type, 'identifier' => $OauthUser->getId(), 'credential' => $OauthUser->token];
if ($user->userAuths()->whereType($type)->updateOrCreate($data)) {
return redirect()->route('profile')->with('successMsg', trans('auth.oauth.bind_success'));
}
return redirect()->route('profile')->withErrors(trans('auth.oauth.bind_failed'));
}
private function logging(string $type, \Laravel\Socialite\Contracts\User $OauthUser): RedirectResponse
{
$user = User::whereUsername($OauthUser->getEmail())->first();
if (! isset($user)) {
$auth = UserOauth::whereType($type)->whereIdentifier($OauthUser->getId())->first();
if (isset($auth)) {
$user = $auth->user;
}
}
if (isset($user)) {
Auth::login($user);
Helpers::userLoginAction($user, IP::getClientIp()); // 用户登录后操作
return redirect()->route('login');
}
return redirect()->route('login')->withErrors(trans('auth.error.not_found_user'));
}
public function login(string $type): RedirectResponse
{
$info = Socialite::driver($type)->stateless()->user();
if ($info) {
return $this->logging($type, $info);
}
return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed'));
}
public function unbind(string $type): RedirectResponse
public function unbind(string $provider): RedirectResponse
{
$user = Auth::user();
if ($user && $user->userAuths()->whereType($type)->delete()) {
if ($user && $user->userAuths()->whereType($provider)->delete()) {
return redirect()->route('profile')->with('successMsg', trans('auth.oauth.unbind_success'));
}
return redirect()->route('profile')->with('successMsg', trans('auth.oauth.unbind_failed'));
return redirect()->route('profile')->withErrors(trans('auth.oauth.unbind_failed'));
}
public function bind(string $type): RedirectResponse
public function bind(string $provider): RedirectResponse
{
$info = Socialite::driver($type)->stateless()->user();
config(["services.$provider.redirect" => route('oauth.bind', ['provider' => $provider])]);
$authInfo = Socialite::driver($provider)->stateless()->user();
if ($info) {
$user = Auth::user();
if ($user) {
return $this->binding($type, $user, $info);
}
if (! $authInfo) {
return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed'));
}
$user = Auth::user();
if (! $user) {
return redirect()->route('profile')->withErrors(trans('auth.oauth.bind_failed'));
}
return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed'));
return $this->bindLogic($provider, $user, $authInfo);
}
public function register(string $type): RedirectResponse
private function bindLogic(string $provider, User $user, \Laravel\Socialite\Contracts\User $authInfo): RedirectResponse
{
$data = [
'type' => $provider,
'identifier' => $authInfo->getId(),
'credential' => $authInfo->token,
];
$auth = $user->userAuths()->whereType($provider)->first();
if ($auth) {
$user->userAuths()->whereType($provider)->update($data);
$message = trans('auth.oauth.rebind_success');
} else {
$user->userAuths()->create($data);
$message = trans('auth.oauth.bind_success');
}
return redirect()->route('profile')->with('successMsg', $message);
}
public function register(string $provider): RedirectResponse
{
config(["services.$provider.redirect" => route('oauth.register', ['provider' => $provider])]);
if (! sysConfig('is_register')) {
return redirect()->route('register')->withErrors(trans('auth.register.error.disable'));
}
if ((int) sysConfig('is_invite_register') === 2) { // 必须使用邀请码
if ((int) sysConfig('is_invite_register') === 2) {
return redirect()->route('register')->withErrors(trans('validation.required', ['attribute' => trans('auth.invite.attribute')]));
}
$OauthUser = Socialite::driver($type)->stateless()->user();
$registerInfo = Socialite::driver($provider)->stateless()->user();
if ($OauthUser) {
if (User::whereUsername($OauthUser->getEmail())->doesntExist() && UserOauth::whereIdentifier($OauthUser->getId())->doesntExist()) { // 排除重复用户注册
$user = Helpers::addUser($OauthUser->getEmail(), Str::random(), MiB * sysConfig('default_traffic'), (int) sysConfig('default_days'), $OauthUser->getNickname());
if (! $registerInfo) {
return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed'));
}
$user = User::whereUsername($registerInfo->getEmail())->first();
if (! $user) { // 邮箱未被注册
$userAuth = UserOauth::whereType($provider)->whereIdentifier($registerInfo->getId())->first();
if (! $userAuth) { // 第三方账号未被绑定
$user = Helpers::addUser($registerInfo->getEmail(), Str::random(), MiB * sysConfig('default_traffic'), (int) sysConfig('default_days'), $registerInfo->getNickname());
$user->userAuths()->create([
'type' => $type,
'identifier' => $OauthUser->getId(),
'credential' => $OauthUser->token,
'type' => $provider,
'identifier' => $registerInfo->getId(),
'credential' => $registerInfo->token,
]);
Auth::login($user);
return $this->handleLogin($user);
}
}
return redirect()->route('login');
return redirect()->route('login')->withErrors(trans('auth.oauth.registered'));
}
private function handleLogin(User $user): RedirectResponse
{
Auth::login($user);
Helpers::userLoginAction($user, IP::getClientIp());
return redirect()->route('login');
}
public function login(string $provider): RedirectResponse
{
config(["services.$provider.redirect" => route('oauth.login', ['provider' => $provider])]);
$authInfo = Socialite::driver($provider)->stateless()->user();
if ($authInfo) {
$auth = UserOauth::whereType($provider)->whereIdentifier($authInfo->getId())->first();
if ($auth && ($user = $auth->user)) { // 如果第三方登录有记录,直接登录用户
return $this->handleLogin($user);
}
return redirect()->route('login')->withErrors(trans('auth.oauth.registered'));
$user = User::whereUsername($authInfo->getEmail())->first();
if ($user) { // 如果用户存在,执行绑定逻辑并登录用户
$this->bindLogic($provider, $user, $authInfo);
return $this->handleLogin($user);
}
// 如果用户不存在,则返回错误消息
return redirect()->route('login')->withErrors(trans('auth.error.not_found_user'));
}
return redirect()->route('login')->withErrors(trans('auth.oauth.login_failed'));
}
public function redirect(string $provider, string $operation = 'login'): RedirectResponse
{
$redirectRoutes = [
'bind' => 'oauth.bind',
'register' => 'oauth.register',
'login' => 'oauth.login',
];
$key = "services.$provider.redirect";
config([$key => route($redirectRoutes[$operation], ['provider' => $provider])]);
return Socialite::driver($provider)->stateless()->redirect();
}
}

View File

@@ -36,14 +36,14 @@
<div class="line">
<span> {{ trans('auth.one-click_login') }} </span>
</div>
@foreach (json_decode(sysConfig('oauth_path')) as $item)
@if ($item === 'telegram')
@foreach (json_decode(sysConfig('oauth_path')) as $provider)
@if ($provider === 'telegram')
<div>
{!! Socialite::driver('telegram')->getButton() !!}
</div>
@else
<a class="btn btn-icon btn-pure" href="{{route('oauth.login', ['type' => $item])}}">
<i class="fa-brands {{config('common.oauth.icon')[$item]}} fa-lg" aria-hidden="true"></i>
<a class="btn btn-icon btn-pure" href="{{route('oauth.route', ['provider' => $provider, 'operation' => 'login'])}}">
<i class="fa-brands {{config('common.oauth.icon')[$provider]}} fa-lg" aria-hidden="true"></i>
</a>
@endif
@endforeach

View File

@@ -106,10 +106,10 @@
<div class="line">
<span> {{trans('auth.oauth.register')}} </span>
</div>
@foreach (json_decode(sysConfig('oauth_path')) as $item)
@if ($item !== 'telegram')
<a class="btn btn-icon btn-pure" href="{{route('oauth.register', ['type' => $item])}}">
<i class="fa-brands {{config('common.oauth.icon')[$item]}} fa-lg" aria-hidden="true"></i>
@foreach (json_decode(sysConfig('oauth_path')) as $provider)
@if ($provider !== 'telegram')
<a class="btn btn-icon btn-pure" href="{{route('oauth.route', ['provider' => $provider, 'operation' => 'register'])}}">
<i class="fa-brands {{config('common.oauth.icon')[$provider]}} fa-lg" aria-hidden="true"></i>
</a>
@endif
@endforeach

View File

@@ -42,22 +42,22 @@
<span> {{trans('user.oauth.bind_title')}} </span>
</div>
<div class="user-socials list-group-gap list-group-full row m-0">
@foreach (json_decode(sysConfig('oauth_path')) as $item)
<a class="list-group-item justify-content-center @if(in_array($item, $auth, true)) col-10 @else col-12 @endif"
@if($item !== 'telegram') href="{{route('oauth.bind', ['type' => $item])}}" @endif>
<i class="fa-brands {{ config('common.oauth.icon')[$item] }} fa-lg mr-10" aria-hidden="true"></i> {{ ucfirst($item) }}
@foreach (json_decode(sysConfig('oauth_path')) as $provider)
<a class="list-group-item justify-content-center @if(in_array($provider, $auth, true)) col-10 @else col-12 @endif"
@if($provider !== 'telegram') href="{{route('oauth.route', ['provider' => $provider, 'operation' => 'bind'])}}" @endif>
<i class="fa-brands {{ config('common.oauth.icon')[$provider] }} fa-lg mr-10" aria-hidden="true"></i> {{ ucfirst($provider) }}
:
@if(in_array($item, $auth, true))
@if(in_array($provider, $auth, true))
<span class="red-600">{{trans('user.oauth.rebind')}}</span>
@else
<span class="grey-500">{{trans('user.oauth.not_bind')}}</span>
@endif
@if($item === 'telegram')
@if($provider === 'telegram')
{!! Socialite::driver('telegram')->getButton() !!}
@endif
</a>
@if(in_array($item, $auth, true))
<a class="col-2 btn btn-block btn-danger my-auto" href="{{route('oauth.unbind', ['type' => $item])}}">{{trans('user.oauth.unbind')}}</a>
@if(in_array($provider, $auth, true))
<a class="col-2 btn btn-block btn-danger my-auto" href="{{route('oauth.unbind', ['provider' => $provider])}}">{{trans('user.oauth.unbind')}}</a>
@endif
@endforeach
</div>

View File

@@ -22,11 +22,11 @@ Route::get('/message/{type}/{msg_id}/show', [MessageController::class, 'index'])
Route::middleware(['isForbidden', 'affiliate', 'isMaintenance'])->group(function () { // 登录相关
Route::prefix('oauth')->name('oauth.')->controller(OAuthController::class)->group(function () { // 用户第三方登录默认登录/转跳方式
Route::get('{type}/login', 'login')->name('login');
Route::get('{type}/register', 'register')->name('register');
Route::get('{type}/bind', 'bind')->name('bind');
Route::get('{type}/unbind', 'unbind')->name('unbind');
Route::get('{type}/redirect', 'simple')->name('simple');
Route::get('{provider}/redirect/{operation}', 'redirect')->whereIn('operation', ['bind', 'register', 'login'])->name('route'); // 转跳
Route::get('{provider}/unbind', 'unbind')->name('unbind'); // 解绑
Route::get('{provider}/login', 'login')->name('login'); // 登录 callback
Route::get('{provider}/register', 'register')->name('register'); // 注册 callback
Route::get('{provider}/bind', 'bind')->name('bind'); // 绑定 callback
});
Route::controller(AuthController::class)->group(function () {