controller update

This commit is contained in:
2026-03-05 18:43:19 -06:00
parent 14588269d6
commit 020e473dc9
9 changed files with 196 additions and 42 deletions

View File

@@ -0,0 +1,71 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Socialite\Facades\Socialite;
use Throwable;
class EveLoginController extends Controller
{
public function showLogin()
{
return view('auth.eve');
}
public function redirectToProvider(): RedirectResponse
{
// "eveonline" driver registered via SocialiteProviders
return Socialite::driver('eveonline')->redirect();
}
public function handleProviderCallback(Request $request): RedirectResponse
{
try {
// Stateless can help in some deployments, but keep stateful by default.
// If you run into "Invalid state" issues behind proxies, switch to ->stateless()
$ssoUser = Socialite::driver('eveonline')->user();
// Socialite user basics
$characterId = (int) $ssoUser->getId();
$characterName = $ssoUser->getName() ?: ($ssoUser->getNickname() ?? 'Unknown');
// Provider-specific extra payload sometimes appears in user array / token response.
// Well defensively extract what we can.
$raw = $ssoUser->user ?? [];
$characterOwnerHash =
$raw['CharacterOwnerHash'] ?? $raw['character_owner_hash'] ?? $raw['owner_hash'] ?? '';
$token = $ssoUser->token;
$refreshToken = $ssoUser->refreshToken ?? null;
$expiresIn = $ssoUser->expiresIn ?? null;
$user = User::updateOrCreate(
['character_id' => $characterId],
[
'character_name' => $characterName,
'character_owner_hash' => $characterOwnerHash,
'token' => $token,
'refresh_token' => $refreshToken,
'expiresIn' => $expiresIn,
// "user" holds jwt - you can set it later when you add JWT issuance.
'user' => null,
]
);
Auth::login($user, true);
$request->session()->regenerate();
return redirect()->route('dashboard');
} catch (Throwable $e) {
// For now: fail back to login with a generic error.
// Later you can add logging/telemetry.
return redirect()->route('login')->with('error', 'SSO login failed. Please try again.');
}
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AuthEveLoginController extends Controller
{
//
}

View File

@@ -2,34 +2,33 @@
namespace App\Models\Auth;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
/** @use HasFactory<\Database\Factories\UserFactory> */
use HasFactory, Notifiable;
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var list<string>
*/
protected $fillable = [
'character_id',
'character_name',
'character_owner_hash',
'character_name',
'character_id',
'token',
'refresh_token',
'expiresIn',
'user', // holds jwt (per spec)
];
/**
* The attributes that should be hidden for serialization.
*
* @var list<string>
*/
protected $hidden = [
'token',
'refresh_token',
'remember_token',
];
protected function casts(): array
{
return [
'expiresIn' => 'integer',
];
}
}

View File

@@ -20,8 +20,8 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot(): void
{
Event::listen(function (\SocialiteProvider\Manager\SocialiteWasCalled $event) {
$event->extendSocialite('eveonline', \SocialiteProviders\Eveonline\Provider::class);
});
//Event::listen(function (\SocialiteProvider\Manager\SocialiteWasCalled $event) {
// $event->extendSocialite('eveonline', \SocialiteProviders\Eveonline\Provider::class);
//});
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use SocialiteProviders\Manager\SocialiteWasCalled;
class EventServiceProvider extends ServiceProvider {
protected $listen = [
SocialiteWasCalled::class => [
// registers Eve Online driver "eveonline"
\SocialiteProviders\EveOnline\EveOnlineExtendSocialite::class.'@handle';
];
];
}

View File

@@ -11,32 +11,28 @@ return new class extends Migration
*/
public function up(): void
{
if(!Schema::hasTable('users')) {
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('character_id');
$table->string('character_owner_hash')->index();
$table->string('character_name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('character_owner_hash');
$table->string('token');
$table->string('refresh_token');
$table->integer('expiresIn');
$table->string('user_jwt_token');
$table->unsignedBigInteger('character_id')->unique();
$table->text('token');
$table->text('refresh_token')->nullable();
$table->integer('expiresIn')->nullable();
// As requested: "user" holds jwt. (Note: naming a column "user" can be confusing later;
// consider "jwt" in future refactors, but this honors your spec.)
$table->text('user')->nullable();
$table->rememberToken();
$table->timestamps();
});
}
if(!Schema::hasTable('password_reset_tokens')) {
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
}
if(!Schema::hasTable('sessions')) {
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();

View File

@@ -0,0 +1,32 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>EVE SSO Login</title>
<style>
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 0; display:flex; min-height:100vh; align-items:center; justify-content:center; background:#0b0f14; color:#fff; }
.card { background:#121826; border:1px solid #1f2a3a; border-radius:12px; padding:28px; width:min(520px, 92vw); text-align:center; }
.btn-img { display:inline-block; border-radius:10px; overflow:hidden; border:1px solid #243349; }
.btn-img img { display:block; width:320px; max-width:72vw; height:auto; }
.hint { opacity:.8; margin-top:14px; font-size:14px; }
.error { background:#3a1414; border:1px solid #6d2020; padding:10px 12px; border-radius:10px; margin-bottom:16px; }
</style>
</head>
<body>
<div class="card">
@if (session('error'))
<div class="error">{{ session('error') }}</div>
@endif
<h1 style="margin:0 0 16px;">Sign in with EVE Online</h1>
<a class="btn-img" href="{{ route('login.eve') }}" aria-label="Login with EVE Online">
{{-- Put the official EVE SSO image in: public/images/eve-sso.png --}}
<img src="{{ asset('images/eve-sso.png') }}" alt="EVE Online Single Sign-On">
</a>
<div class="hint">Click the image to begin the EVE Online SSO flow.</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,22 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Dashboard</title>
</head>
<body style="font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;">
<div style="max-width: 900px; margin: 40px auto; padding: 0 16px;">
<div style="display:flex; justify-content:space-between; align-items:center;">
<h1>Hello World</h1>
<form method="POST" action="{{ route('logout') }}">
@csrf
<button type="submit">Logout</button>
</form>
</div>
<p>Logged in as: <strong>{{ auth()->user()->character_name }}</strong> ({{ auth()->user()->character_id }})</p>
</div>
</body>
</html>

View File

@@ -9,11 +9,20 @@ Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/', [EveLoginController::class, 'showLogin'])->name('login');
Route::get('/dashboard', [App\Http\Controllers\DashboardController::class, 'index'])->name('dashboard');
Route::get('/login/eve', [EveLoginController::class, 'redirectToProvider'])->name('login.eve');
Route::get('/login/eve/callback', [EveLoginController::class, 'handleProviderCallback'])->name('login.eve.callback');
Route::controller(LoginController::class)->group(function () {
Route::get('auth/eveonline', 'redirectToEve')->name('auth.eveonline');
Route::get('auth/eveonline/callback', 'handleEveonlineCallback');
});
Route::middleware('auth')->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
Route::post('/logout', function () {
auth()->logout();
request()->session()->invalidate();
request()->session()->regenerateToken();
return redirect()->route('login');
})->name('logout');
});