feat: add City10 platform with Laravel 13, AI agents, 3D viewer, and LGPD compliance
Initial commit of the complete City10 virtual city simulation platform. Backend (Laravel 13): - REST API with Sanctum tokens and session-based web authentication - Role-based access control (admin/user) with middleware protection - AI agent CRUD with OpenRouter.ai integration restricted to free models - Store management with 3D coordinates and AI shopkeeper assignment - Versioned legal documents (Terms, Privacy, Cookies) with LGPD audit trail - Math CAPTCHA on public forms and multi-language support (pt_BR, en, es) Frontend: - Responsive Blade templates with Tailwind CSS v4 - Three.js 3D city viewer with SSE chat streaming to AI agents - Admin panel for store and user administration Infrastructure: - MariaDB/MySQL database with comprehensive migrations - Database seeders for demo content and test accounts - PHPUnit test suite and Laravel Pint code styling - Vite build configuration with hot reload
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\LoginRequest;
|
||||
use App\Http\Requests\RegisterRequest;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
* Web authentication controllers (session based).
|
||||
*
|
||||
* Complements the token-based API with a traditional server-rendered
|
||||
* login and registration flow including a math CAPTCHA.
|
||||
*/
|
||||
class AuthController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show the login form.
|
||||
*/
|
||||
public function showLogin(): View
|
||||
{
|
||||
return view('auth.login', [
|
||||
'captcha' => self::makeCaptcha(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the login form submission.
|
||||
*/
|
||||
public function login(LoginRequest $request): RedirectResponse
|
||||
{
|
||||
$credentials = $request->only('email', 'password');
|
||||
$remember = $request->boolean('remember');
|
||||
|
||||
if (! Auth::attempt($credentials, $remember)) {
|
||||
return back()->withErrors([
|
||||
'email' => __('auth.failed'),
|
||||
])->onlyInput('email');
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
if (! $user->is_active) {
|
||||
Auth::logout();
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return redirect()->route('login')->withErrors([
|
||||
'email' => __('auth.disabled'),
|
||||
]);
|
||||
}
|
||||
|
||||
$user->forceFill(['last_login_at' => now()])->save();
|
||||
$request->session()->regenerate();
|
||||
|
||||
// Seed the session locale from the user's stored preference so the
|
||||
// SetLocale middleware renders the UI in their chosen language.
|
||||
if (in_array($user->locale, ['pt_BR', 'en', 'es'], true)) {
|
||||
$request->session()->put('locale', $user->locale);
|
||||
}
|
||||
|
||||
return redirect()->intended(route('dashboard'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the registration form.
|
||||
*/
|
||||
public function showRegister(): View
|
||||
{
|
||||
return view('auth.register', [
|
||||
'captcha' => self::makeCaptcha(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the registration form submission.
|
||||
*/
|
||||
public function register(RegisterRequest $request): RedirectResponse
|
||||
{
|
||||
$data = $request->validated();
|
||||
|
||||
$user = User::create([
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'password' => $data['password'],
|
||||
'role' => User::ROLE_USER,
|
||||
'locale' => $data['locale'] ?? 'pt_BR',
|
||||
'is_active' => true,
|
||||
]);
|
||||
|
||||
Auth::login($user);
|
||||
$request->session()->regenerate();
|
||||
|
||||
return redirect()->route('terms.accept');
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the user out of the web session.
|
||||
*/
|
||||
public function logout(Request $request): RedirectResponse
|
||||
{
|
||||
Auth::logout();
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return redirect()->route('login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a fresh math CAPTCHA challenge.
|
||||
*
|
||||
* @return array{a: int, b: int, question: string}
|
||||
*/
|
||||
private static function makeCaptcha(): array
|
||||
{
|
||||
$a = random_int(1, 9);
|
||||
$b = random_int(1, 9);
|
||||
|
||||
session()->put('captcha_result', $a + $b);
|
||||
session()->put('captcha_expires_at', now()->addMinutes(10)->getTimestamp());
|
||||
|
||||
return [
|
||||
'a' => $a,
|
||||
'b' => $b,
|
||||
'question' => sprintf('%d + %d = ?', $a, $b),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user