diff --git a/app/Http/Controllers/Auth/ProviderController.php b/app/Http/Controllers/Auth/ProviderController.php index e1ee2a4..223020e 100644 --- a/app/Http/Controllers/Auth/ProviderController.php +++ b/app/Http/Controllers/Auth/ProviderController.php @@ -3,9 +3,85 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; +use App\Models\User; +use App\Models\Provider; use Illuminate\Http\Request; +use Illuminate\Support\Str; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Hash; +use Laravel\Socialite\Facades\Socialite; +use Inertia\Inertia; class ProviderController extends Controller { - // + /** + * Redirect to the provider for authentication. + * + * @return \Illuminate\Http\RedirectResponse + */ + public function redirectToProvider(Request $request) + { + $providerValue = $request->provider; + + // Validate the provider to ensure it's supported + if (!in_array($providerValue, ['google', 'linkedin', 'github'])) { + return redirect()->route('home')->with('error', 'Unsupported provider.'); + } + + // Store the previous URL to redirect back after login + session()->put('previous_url', url()->previous()); + + return Inertia::location(Socialite::driver($providerValue)->redirect()->getTargetUrl()); + } + + /** + * Handle the provider callback after authentication. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\RedirectResponse + */ + public function handleProviderCallback(Request $request) + { + $providerValue = $request->provider; + + // Validate the provider to ensure it's supported + if (!in_array($providerValue, ['google', 'linkedin', 'github'])) { + return redirect()->route('home')->with('error', 'Unsupported provider.'); + } + + $previousUrl = $request->session()->pull('previous_url', route('welcome')); // Use a named route as default + $providerUser = Socialite::driver($providerValue)->user(); + + // Find or create the user + $user = User::firstOrCreate( + ['email' => $providerUser->getEmail()], + [ + 'name' => $providerUser->getName(), + 'first_name' => $providerUser->user['given_name'] ?? null, + 'last_name' => $providerUser->user['family_name'] ?? null, + 'password' => Hash::make(Str::random(24)), // Generate a random password + 'email_verified_at' => now(), + 'avatar' => $providerUser->getAvatar(), + ] + ); + + // Update or create the provider + Provider::updateOrCreate( + [ + 'provider' => $providerValue, + 'provider_id' => $providerUser->getId(), + ], + [ + 'user_id' => $user->id, + 'provider_token' => $providerUser->token, + ] + ); + + // Log the user in + Auth::login($user); + + return redirect($previousUrl)->with('success', 'Logged in successfully.'); + + + } } diff --git a/app/Http/Resources/UserResource.php b/app/Http/Resources/UserResource.php index f0d5c99..e499411 100644 --- a/app/Http/Resources/UserResource.php +++ b/app/Http/Resources/UserResource.php @@ -14,9 +14,9 @@ class UserResource extends JsonResource */ public function toArray(Request $request): array { - $avatarUrl = $this->getFirstMediaUrl('avatar'); + $avatarUrl = $this->avatar ?? $this->getFirstMediaUrl('avatar') ?? null; $avatar = $avatarUrl ? $avatarUrl : 'https://ui-avatars.com/api/?name=' . urlencode($this->name) . '&color=7F9CF5&background=EBF4FF'; - + return [ 'id' => $this->id, 'name' => $this->name, diff --git a/app/Models/Provider.php b/app/Models/Provider.php index 6aeaf39..5e06bf8 100644 --- a/app/Models/Provider.php +++ b/app/Models/Provider.php @@ -9,4 +9,51 @@ class Provider extends Model { /** @use HasFactory<\Database\Factories\ProviderFactory> */ use HasFactory; + + /** + * The attributes that are mass assignable. + * + * @var string[] + */ + protected $fillable = [ + 'user_id', + 'provider', + 'provider_id', + 'provider_token', + ]; + + /** + * Get the user that owns the provider. + */ + public function user() + { + return $this->belongsTo(User::class); + } + + + /** + * Find a provider by the given provider and provider ID. + * + * @param string $provider + * @param string $providerId + * @return static|null + */ + public static function findByProvider($provider, $providerId) + { + return static::where('provider', $provider) + ->where('provider_id', $providerId) + ->first(); + } + + /** + * Find a provider by the given user ID. + * + * @param int $userId + * @return static|null + */ + public static function findByUserId($userId) + { + return static::where('user_id', $userId) + ->first(); + } } diff --git a/app/Models/User.php b/app/Models/User.php index 77a1815..2aed7cb 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -27,6 +27,10 @@ class User extends Authenticatable implements HasMedia, FilamentUser 'name', 'email', 'password', + 'first_name', + 'last_name', + 'email_verified_at', + 'avatar', ]; /** diff --git a/resources/js/Components/Layout/Header.vue b/resources/js/Components/Layout/Header.vue index d399025..887f2fe 100644 --- a/resources/js/Components/Layout/Header.vue +++ b/resources/js/Components/Layout/Header.vue @@ -71,8 +71,9 @@ const headerClass = computed(() => {