chore:simplify connected account verifications
This commit is contained in:
@@ -8,8 +8,8 @@ use App\Models\ConnectedAccount;
|
|||||||
use Illuminate\Support\MessageBag;
|
use Illuminate\Support\MessageBag;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Blade;
|
||||||
use Laravel\Socialite\Facades\Socialite;
|
use Laravel\Socialite\Facades\Socialite;
|
||||||
use App\Models\ConnectedAccountVerification;
|
|
||||||
use App\Notifications\VerifyConnectedAccountNotification;
|
use App\Notifications\VerifyConnectedAccountNotification;
|
||||||
|
|
||||||
class ConnectedAccountController extends Controller
|
class ConnectedAccountController extends Controller
|
||||||
@@ -52,11 +52,16 @@ class ConnectedAccountController extends Controller
|
|||||||
'token' => $providerUser->token,
|
'token' => $providerUser->token,
|
||||||
'secret' => $providerUser->tokenSecret,
|
'secret' => $providerUser->tokenSecret,
|
||||||
'refresh_token' => $providerUser->refreshToken,
|
'refresh_token' => $providerUser->refreshToken,
|
||||||
'expires_at' => $providerUser->expiresIn
|
'expires_at' => $providerUser->expiresIn,
|
||||||
|
'verified_at' => false
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// already linked, let's go login
|
// already linked and verified, let's go login!
|
||||||
if ($connected_account->exists) {
|
if (
|
||||||
|
$connected_account->exists
|
||||||
|
&& !is_null($connected_account->verified_at)
|
||||||
|
) {
|
||||||
|
|
||||||
Auth::login($connected_account->user, true);
|
Auth::login($connected_account->user, true);
|
||||||
|
|
||||||
return redirect(route('dashboard'));
|
return redirect(route('dashboard'));
|
||||||
@@ -72,6 +77,7 @@ class ConnectedAccountController extends Controller
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$connected_account->user_id = $user->id;
|
$connected_account->user_id = $user->id;
|
||||||
|
$connected_account->verified_at = now();
|
||||||
$connected_account->save();
|
$connected_account->save();
|
||||||
|
|
||||||
Auth::login($user, true);
|
Auth::login($user, true);
|
||||||
@@ -80,16 +86,10 @@ class ConnectedAccountController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// email exists already, send verification link
|
// email exists already, send verification link
|
||||||
$verification = ConnectedAccountVerification::updateOrCreate([
|
$connected_account->user_id = $user->id;
|
||||||
'email' => $providerUser->email,
|
$connected_account->save();
|
||||||
'provider' => $provider,
|
|
||||||
'verified_at' => null
|
|
||||||
], [
|
|
||||||
'provider_id' => $providerUser->id,
|
|
||||||
'connected_account' => $connected_account
|
|
||||||
]);
|
|
||||||
|
|
||||||
$user->notify(new VerifyConnectedAccountNotification($verification->id));
|
$user->notify(new VerifyConnectedAccountNotification($connected_account->id));
|
||||||
|
|
||||||
return redirect(route('login'))
|
return redirect(route('login'))
|
||||||
->with('status', __(
|
->with('status', __(
|
||||||
@@ -106,34 +106,30 @@ class ConnectedAccountController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function verify(string $verification_id)
|
public function verify(ConnectedAccount $connected_account)
|
||||||
{
|
{
|
||||||
|
if (!$connected_account->verified_at) {
|
||||||
$verification = ConnectedAccountVerification::findOrFail($verification_id);
|
|
||||||
|
|
||||||
if (!$verification->verified_at) {
|
|
||||||
|
|
||||||
// mark request as verified
|
// mark request as verified
|
||||||
$verification->verified_at = now();
|
$connected_account->verified_at = now();
|
||||||
$verification->save();
|
$connected_account->save();
|
||||||
|
|
||||||
// mark user as verified
|
// mark user as verified
|
||||||
$user = User::where('email', $verification->email)->firstOrFail();
|
$connected_account->user->email_verified_at = now();
|
||||||
$user->email_verified_at = now();
|
$connected_account->user->save();
|
||||||
$user->save();
|
|
||||||
|
|
||||||
// add connected account
|
Auth::login($connected_account->user, true);
|
||||||
$user->connectedAccounts()->create([
|
}
|
||||||
...$verification->connected_account,
|
|
||||||
...[
|
return redirect(route('dashboard'))->with('toast', json_encode([
|
||||||
'provider' => $verification->provider,
|
'toast' => [
|
||||||
'provider_id' => $verification->provider_id,
|
'title' => __('Your :provider account has been connected.', ['provider' => config("services.{$connected_account->provider}.name")]),
|
||||||
|
'description' => null,
|
||||||
|
'css' => 'alert-success',
|
||||||
|
'icon' => Blade::render("<x-mary-icon class='w-7 h-7' name='o-check-circle' />"),
|
||||||
|
'position' => 'toast-top toast-end',
|
||||||
|
'timeout' => '5000'
|
||||||
]
|
]
|
||||||
]);
|
]));
|
||||||
|
|
||||||
Auth::login($user, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect(route('dashboard'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,11 +24,6 @@ class HoldingController extends Controller
|
|||||||
->portfolio($portfolio->id)
|
->portfolio($portfolio->id)
|
||||||
->firstOrFail();
|
->firstOrFail();
|
||||||
|
|
||||||
// if ($holding->quantity <= 0) {
|
|
||||||
|
|
||||||
// return redirect(route('portfolio.show', ['portfolio' => $portfolio->id]));
|
|
||||||
// }
|
|
||||||
|
|
||||||
return view('holding.show', compact(['portfolio', 'holding']));
|
return view('holding.show', compact(['portfolio', 'holding']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class ConnectedAccountVerification extends Model
|
|
||||||
{
|
|
||||||
|
|
||||||
use HasUuids;
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
'provider',
|
|
||||||
'provider_id',
|
|
||||||
'email',
|
|
||||||
'connected_account'
|
|
||||||
];
|
|
||||||
|
|
||||||
protected function casts(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'created_at' => 'datetime',
|
|
||||||
'updated_at' => 'datetime',
|
|
||||||
'verified_at' => 'datetime',
|
|
||||||
'connected_account' => 'json'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Notifications;
|
namespace App\Notifications;
|
||||||
|
|
||||||
use App\Models\ConnectedAccountVerification;
|
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
|
use App\Models\ConnectedAccount;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Notifications\Messages\MailMessage;
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
use Illuminate\Notifications\Notification;
|
|
||||||
|
|
||||||
class VerifyConnectedAccountNotification extends Notification implements ShouldQueue
|
class VerifyConnectedAccountNotification extends Notification implements ShouldQueue
|
||||||
{
|
{
|
||||||
@@ -16,7 +16,7 @@ class VerifyConnectedAccountNotification extends Notification implements ShouldQ
|
|||||||
* Create a new notification instance.
|
* Create a new notification instance.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public string $verification_id
|
public string $connected_account_id
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,10 +34,10 @@ class VerifyConnectedAccountNotification extends Notification implements ShouldQ
|
|||||||
*/
|
*/
|
||||||
public function toMail(object $notifiable): MailMessage
|
public function toMail(object $notifiable): MailMessage
|
||||||
{
|
{
|
||||||
$verification = ConnectedAccountVerification::find($this->verification_id);
|
$connected_account = ConnectedAccount::find($this->connected_account_id);
|
||||||
$provider = config("services.$verification->provider.name");
|
$provider = config("services.$connected_account->provider.name");
|
||||||
|
|
||||||
$url = url()->signedRoute('oauth.verify_connected_account', ['verification_id' => $this->verification_id], now()->days($days = 7));
|
$url = url()->signedRoute('oauth.verify_connected_account', ['connected_account' => $this->connected_account_id], now()->days($days = 7));
|
||||||
|
|
||||||
return (new MailMessage)
|
return (new MailMessage)
|
||||||
->greeting('Welcome back!')
|
->greeting('Welcome back!')
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class AppLayout extends Component
|
|||||||
<x-slot:body class="min-h-screen font-sans antialiased bg-base-200/50 dark:bg-base-200" x-data>
|
<x-slot:body class="min-h-screen font-sans antialiased bg-base-200/50 dark:bg-base-200" x-data>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
<x-partials.nav-bar />
|
<x-partials.nav-bar />
|
||||||
|
|
||||||
<x-main with-nav full-width>
|
<x-main with-nav full-width>
|
||||||
@@ -27,11 +28,19 @@ class AppLayout extends Component
|
|||||||
</x-slot:sidebar>
|
</x-slot:sidebar>
|
||||||
|
|
||||||
<x-slot:content>
|
<x-slot:content>
|
||||||
|
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
</x-slot:content>
|
</x-slot:content>
|
||||||
|
|
||||||
</x-main>
|
</x-main>
|
||||||
|
|
||||||
|
@if(session('toast'))
|
||||||
|
<script lang="text/javascript">
|
||||||
|
window.addEventListener('DOMContentLoaded', function () {
|
||||||
|
window.toast(JSON.parse(@json(session('toast'))))
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endif
|
||||||
<x-toast />
|
<x-toast />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -25,21 +25,12 @@ return new class extends Migration
|
|||||||
$table->string('secret')->nullable(); // OAuth1
|
$table->string('secret')->nullable(); // OAuth1
|
||||||
$table->string('refresh_token', 1000)->nullable(); // OAuth2
|
$table->string('refresh_token', 1000)->nullable(); // OAuth2
|
||||||
$table->dateTime('expires_at')->nullable(); // OAuth2
|
$table->dateTime('expires_at')->nullable(); // OAuth2
|
||||||
|
$table->dateTime('verified_at')->nullable(); // OAuth2
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
$table->index(['user_id', 'id']);
|
$table->index(['user_id', 'id']);
|
||||||
$table->index(['provider', 'provider_id']);
|
$table->index(['provider', 'provider_id']);
|
||||||
});
|
});
|
||||||
|
|
||||||
Schema::create('connected_account_verifications', function (Blueprint $table) {
|
|
||||||
$table->uuid('id')->primary();
|
|
||||||
$table->string('email');
|
|
||||||
$table->string('provider');
|
|
||||||
$table->string('provider_id');
|
|
||||||
$table->json('connected_account');
|
|
||||||
$table->timestamps();
|
|
||||||
$table->timestamp('verified_at')->nullable();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,8 +39,6 @@ return new class extends Migration
|
|||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
|
|
||||||
Schema::dropIfExists('connected_account_verifications');
|
|
||||||
|
|
||||||
Schema::dropIfExists('connected_accounts');
|
Schema::dropIfExists('connected_accounts');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
"Token Name": "Token Name",
|
"Token Name": "Token Name",
|
||||||
"Permissions": "Permissions",
|
"Permissions": "Permissions",
|
||||||
"Profile Information": "Profile Information",
|
"Profile Information": "Profile Information",
|
||||||
|
"Your :provider account has been connected.": "Your :provider account has been connected.",
|
||||||
"Account already exists. Check your email to connect your :provider account.": "Account already exists. Check your email to connect your :provider account.",
|
"Account already exists. Check your email to connect your :provider account.": "Account already exists. Check your email to connect your :provider account.",
|
||||||
"Could not login using :provider. Try again later.": "Could not login using :provider. Try again later.",
|
"Could not login using :provider. Try again later.": "Could not login using :provider. Try again later.",
|
||||||
"Update your account\\'s profile information and email address.": "Update your account\\'s profile information and email address.",
|
"Update your account\\'s profile information and email address.": "Update your account\\'s profile information and email address.",
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
"Token Name": "Nombre del Token",
|
"Token Name": "Nombre del Token",
|
||||||
"Permissions": "Permisos",
|
"Permissions": "Permisos",
|
||||||
"Profile Information": "Información del Perfil",
|
"Profile Information": "Información del Perfil",
|
||||||
|
"Your :provider account has been connected.": "Su cuenta :provider ha sido conectada.",
|
||||||
"Account already exists. Check your email to connect your :provider account.": "La cuenta ya existe. Revisa tu correo electrónico para conectar tu cuenta :provider.",
|
"Account already exists. Check your email to connect your :provider account.": "La cuenta ya existe. Revisa tu correo electrónico para conectar tu cuenta :provider.",
|
||||||
"Could not login using :provider. Try again later.": "No se pudo iniciar sesión con :provider. Inténtalo nuevamente más tarde.",
|
"Could not login using :provider. Try again later.": "No se pudo iniciar sesión con :provider. Inténtalo nuevamente más tarde.",
|
||||||
"Update your account's profile information and email address.": "Actualiza la información de perfil y la dirección de correo electrónico de tu cuenta.",
|
"Update your account's profile information and email address.": "Actualiza la información de perfil y la dirección de correo electrónico de tu cuenta.",
|
||||||
|
|||||||
+1
-1
@@ -44,7 +44,7 @@ Route::get('/terms', [TermsOfServiceController::class, 'show'])->name('terms.sho
|
|||||||
Route::get('/privacy', [PrivacyPolicyController::class, 'show'])->name('policy.show');
|
Route::get('/privacy', [PrivacyPolicyController::class, 'show'])->name('policy.show');
|
||||||
|
|
||||||
// social login routes
|
// social login routes
|
||||||
Route::get('auth/verify/{verification_id}', [ConnectedAccountController::class, 'verify'])->name('oauth.verify_connected_account');
|
Route::get('auth/verify/{connected_account}', [ConnectedAccountController::class, 'verify'])->name('oauth.verify_connected_account');
|
||||||
|
|
||||||
Route::get('auth/{provider}', [ConnectedAccountController::class, 'redirectToProvider'])->name('oauth.redirect');
|
Route::get('auth/{provider}', [ConnectedAccountController::class, 'redirectToProvider'])->name('oauth.redirect');
|
||||||
Route::get('auth/{provider}/callback', [ConnectedAccountController::class, 'handleProviderCallback']);
|
Route::get('auth/{provider}/callback', [ConnectedAccountController::class, 'handleProviderCallback']);
|
||||||
|
|||||||
Reference in New Issue
Block a user