penambahan login degnan Google

This commit is contained in:
baghizadizn 2025-11-27 09:23:00 +07:00
parent 979fa95f36
commit f18b7454a8
12 changed files with 1655 additions and 833 deletions

View File

@ -0,0 +1,160 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\DeviceIp;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Mail;
use Laravel\Socialite\Facades\Socialite;
use Exception;
class GoogleAuthController extends Controller
{
/**
* Redirect to Google OAuth
*/
public function redirect()
{
try {
return Socialite::driver('google')->redirect();
} catch (Exception $e) {
Session::flash('error', get_phrase('Google authentication is currently unavailable. Please try again later.'));
return redirect()->route('login');
}
}
/**
* Handle Google OAuth callback
*/
public function callback()
{
try {
$googleUser = Socialite::driver('google')->user();
// Validate required data
if (!$googleUser->getEmail()) {
Session::flash('error', get_phrase('Google account email is required. Please ensure your Google account has an email address.'));
return redirect()->route('login');
}
// Find existing user by email
$existingUser = User::where('email', $googleUser->getEmail())->first();
if ($existingUser) {
// Update existing user with Google data if missing
if (!$existingUser->google_id) {
$existingUser->update([
'google_id' => $googleUser->getId(),
'avatar' => $googleUser->getAvatar() ?? $existingUser->avatar,
]);
}
Auth::login($existingUser);
return $this->handlePostLogin($existingUser);
} else {
// Create new user with your existing field structure
$newUser = User::create([
'name' => $googleUser->getName() ?? $this->generateNameFromEmail($googleUser->getEmail()),
'email' => $googleUser->getEmail(),
'google_id' => $googleUser->getId(),
'password' => null, // No password for Google-authenticated users
'role' => 'student',
'status' => 1,
'photo' => $googleUser->getAvatar(),
]);
if (get_settings('student_email_verification') != 1) {
$user_data['email_verified_at'] = Carbon::now();
}
Auth::login($newUser);
Session::flash('success', get_phrase('Account created successfully! Welcome to our platform.'));
return $this->handlePostLogin($newUser);
}
} catch (Exception $e) {
Session::flash('error', get_phrase('Authentication failed. Please try again or use another method.'));
return redirect()->route('login');
}
}
/**
* Handle post-login logic (device tracking, etc.)
*/
private function handlePostLogin($user)
{
request()->session()->regenerate();
// Track device limitation (same as your existing login)
if (Auth::check() && $user->role != 'admin') {
$current_ip = request()->getClientIp();
$session_id = request()->session()->getId();
$current_user_agent = base64_encode($user->id . request()->header('user-agent'));
$allowed_devices = get_settings('device_limitation') ?? 1;
$logged_in_devices = DeviceIp::where('user_id', $user->id)->get();
if ($logged_in_devices->where('user_agent', '!=', $current_user_agent)->count() < $allowed_devices) {
if ($logged_in_devices->where('user_agent', $current_user_agent)->count() == 0) {
DeviceIp::insert([
'user_id' => $user->id,
'ip_address' => $current_ip,
'session_id' => $session_id,
'user_agent' => $current_user_agent,
'created_at' => now(),
'updated_at' => now(),
]);
} else {
DeviceIp::where('user_id', $user->id)
->where('user_agent', $current_user_agent)
->update([
'session_id' => $session_id,
'updated_at' => now(),
]);
}
} else {
$logged_in_oldest_row = DeviceIp::where('user_id', $user->id)->orderBy('id', 'desc')->first();
$data = [
'verification_link' => route('login', ['user_agent' => $logged_in_oldest_row->user_agent])
];
try {
Mail::send('email.new_device_login_verification', $data, function ($message) use($user) {
$message->to($user->email, $user->name)->subject('New login confirmation');
});
Auth::guard('web')->logout();
request()->session()->invalidate();
request()->session()->regenerateToken();
Session::flash('success', get_phrase('A confirmation email has been sent. Please check your inbox to confirm access to this account from this device.'));
return redirect(route('login'));
} catch (\Swift_TransportException $e) {
Session::flash('error', 'We could not send the email. Please try again later.');
} catch (Exception $e) {
Session::flash('error', 'Something went wrong. Please try again.');
}
Auth::guard('web')->logout();
request()->session()->invalidate();
request()->session()->regenerateToken();
return redirect(route('login'));
}
}
return redirect()->intended('/dashboard');
}
/**
* Generate a name from email if Google name is not available
*/
private function generateNameFromEmail($email)
{
$name = strstr($email, '@', true);
return ucfirst(str_replace(['.', '_'], ' ', $name));
}
}

View File

@ -26,6 +26,7 @@ class User extends Authenticatable implements MustVerifyEmail
'password',
'role',
'status',
'google_id',
'email_verified_at'
];

View File

@ -11,6 +11,7 @@
"intervention/image": "^2.7",
"laravel/framework": "^11.0",
"laravel/sanctum": "^4.0",
"laravel/socialite": "*",
"laravel/tinker": "^2.8",
"paytm/paytmchecksum": "^1.1",
"pbmedia/laravel-ffmpeg": "^8.6",

2282
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -30,5 +30,10 @@ return [
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
'google' => [
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_CLIENT_SECRET'),
'redirect' => env('GOOGLE_REDIRECT_URL'),
],
];

View File

@ -248,7 +248,6 @@ button:focus,
}
button {
border: none;
outline: none;
}

View File

@ -406,7 +406,7 @@ img {
.google-login-btn:hover {
background: linear-gradient(45deg, #f8f9fa 0%, #e9ecef 100%);
border-color: var(--color-1);
transform: translateY(-2px);
transform: translateY(-1px);
color: #333;
text-decoration: none;
box-shadow: 0 4px 15px rgba(66, 133, 244, 0.2);
@ -428,6 +428,7 @@ img {
}
.eBtn {
border: none;
padding: 12px 30px;
border-radius: 10px;
color: #fff;
@ -443,9 +444,11 @@ img {
}
.eBtn:hover {
border: 1px solid;
background-position: right center;
border-color: #0330c4 !important;
transform: translateY(-1px);
border-color: var(--color-1);
transform: translateY(-2px);
color: #333 !important;
box-shadow: 0 6px 20px rgba(2, 25, 110, 0.25);
}
@ -460,7 +463,7 @@ img {
.gradient:hover {
background-position: right center;
color: #001151;
color: #001151 !important;
text-decoration: none;
}
@ -2903,7 +2906,6 @@ html .ui-button.ui-state-disabled:active {
}
.global-form button {
border: none;
padding: 12px 30px;
}
@ -7790,3 +7792,5 @@ textarea.lms-form-control {
/* ===================================================================
Tutor Details CSS End
====================================================================*/
px

View File

@ -75,7 +75,7 @@
</div>
</div>
<a href="#" class="list text-18px d-inline-flex" data-bs-toggle="offcanvas" data-bs-target="#offcanvasRight" aria-controls="offcanvasRight">
{{-- <a href="#" class="list text-18px d-inline-flex" data-bs-toggle="offcanvas" data-bs-target="#offcanvasRight" aria-controls="offcanvasRight">
<span class="d-block h-100 w-100" data-bs-toggle="tooltip" data-bs-placement="bottom" title="{{ get_phrase('AI Assistant') }}">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="22" height="22" x="0" y="0" viewBox="0 0 64 64" style="enable-background:new 0 0 512 512" xml:space="preserve" class="">
<g>
@ -85,7 +85,7 @@
</g>
</svg>
</span>
</a>
</a> --}}
<div class="dropdown ol-icon-dropdown ol-icon-dropdown-transparent" data-bs-toggle="tooltip" data-bs-placement="bottom" title="{{ get_phrase('Help Center') }}">
<button class="btn ol-btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">

View File

@ -68,7 +68,7 @@
</div>
{{-- Google Login Button --}}
<a href="javascript:void(0)" onclick="error('{{ get_phrase("Feature still in development 🚧") }}')" class="google-login-btn w-100">
<a href="{{ route('google.redirect') }}" class="google-login-btn w-100">
<img src="{{ asset('assets/frontend/default/image/Google.png') }}" alt="Google Logo">
{{ get_phrase('Login with Google') }}
</a>

View File

@ -104,7 +104,7 @@
</div>
{{-- Google Login Button --}}
<a href="javascript:void(0)" onclick="error('{{ get_phrase("Feature still in development 🚧") }}')" class="google-login-btn w-100">
<a href="{{ route('google.redirect') }}" class="google-login-btn w-100">
<img src="{{ asset('assets/frontend/default/image/Google.png') }}" alt="Google Logo">
{{ get_phrase('Sign Up with Google') }}
</a>

View File

@ -41,7 +41,7 @@
</a>
</li>
<li class="@if ($current_route == 'my_bookings' || $current_route == 'booking_invoice') active @endif">
{{-- <li class="@if ($current_route == 'my_bookings' || $current_route == 'booking_invoice') active @endif">
<a href="{{ route('my_bookings', ['tab' => 'live-upcoming']) }}" class="bootcamp-sidebar-icon text-capitalize">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" class="m-0">
<path d="M1.67188 7.5V6.66667C1.67188 4.16667 3.33854 2.5 5.83854 2.5H14.1719C16.6719 2.5 18.3385 4.16667 18.3385 6.66667V13.3333C18.3385 15.8333 16.6719 17.5 14.1719 17.5H13.3385" stroke="#6B7385" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" />
@ -51,7 +51,7 @@
</svg>
{{ get_phrase('My Bookings') }}
</a>
</li>
</li> --}}
<li class="@if ($current_route == 'my.team.packages' || $current_route == 'my.team.packages.details' || $current_route == 'team.package.invoice') active @endif">
<a href="{{ route('my.team.packages') }}">

View File

@ -4,6 +4,7 @@ use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\Auth\ConfirmablePasswordController;
use App\Http\Controllers\Auth\EmailVerificationNotificationController;
use App\Http\Controllers\Auth\EmailVerificationPromptController;
use App\Http\Controllers\Auth\GoogleAuthController;
use App\Http\Controllers\Auth\NewPasswordController;
use App\Http\Controllers\Auth\PasswordController;
use App\Http\Controllers\Auth\PasswordResetLinkController;
@ -34,6 +35,11 @@ Route::middleware('guest')->group(function () {
Route::post('reset-password', [NewPasswordController::class, 'store'])
->name('password.store');
// Google OAuth Routes
Route::get('/auth/google/redirect', [GoogleAuthController::class, 'redirect'])->name('google.redirect');
Route::get('/auth/google/callback', [GoogleAuthController::class, 'callback'])->name('google.callback');
});
Route::middleware('auth')->group(function () {