create([ 'email' => 'valid@example.com', 'password' => bcrypt('password'), 'email_verified_at' => now(), ]); $response = $this->post(route('login.store'), [ 'login' => 'valid@example.com', 'password' => 'password', ]); $this->assertAuthenticated(); // User without specific role (null/default) redirects to packages for package selection $response->assertRedirect('/packages'); $this->assertEquals('valid@example.com', Auth::user()->email); } public function test_successful_login_with_username() { $user = User::factory()->create([ 'username' => 'validuser', 'password' => bcrypt('password'), 'email_verified_at' => now(), ]); $response = $this->post(route('login.store'), [ 'login' => 'validuser', 'password' => 'password', ]); $this->assertAuthenticated(); // User without specific role (null/default) redirects to packages for package selection $response->assertRedirect('/packages'); $this->assertEquals('validuser', Auth::user()->username); } public function test_login_fails_with_invalid_credentials() { User::factory()->create([ 'email' => 'invalid@example.com', 'password' => bcrypt('password'), ]); $response = $this->post(route('login.store'), [ 'login' => 'invalid@example.com', 'password' => 'wrongpassword', ]); $this->assertGuest(); $response->assertStatus(302); $response->assertRedirect(route('login', absolute: false)); $response->assertSessionHasErrors(['login' => 'Diese Anmeldedaten wurden nicht gefunden.']); $response->assertSessionHas('error', 'Diese Anmeldedaten wurden nicht gefunden.'); } public function test_login_success_shows_success_flash() { $user = User::factory()->create([ 'email' => 'success@example.com', 'role' => 'user', // Regular user 'password' => bcrypt('password'), 'email_verified_at' => now(), ]); $response = $this->post(route('login.store'), [ 'login' => 'success@example.com', 'password' => 'password', ]); $this->assertAuthenticated(); // Regular users now redirect to /packages for package selection $response->assertRedirect('/packages'); $response->assertSessionHas('success', 'Sie sind nun eingeloggt.'); } public function test_login_honors_return_to_parameter() { $user = User::factory()->create([ 'email' => 'return@example.com', 'role' => 'user', // Regular user 'password' => bcrypt('password'), 'email_verified_at' => now(), ]); // Test that return_to parameter is honored - set it to a specific dashboard path $target = '/marketing/profile'; $encoded = rtrim(strtr(base64_encode($target), '+/', '-_'), '='); $response = $this->post(route('login.store'), [ 'login' => 'return@example.com', 'password' => 'password', 'return_to' => $encoded, ]); $this->assertAuthenticated(); $response->assertRedirect($target); } public function test_login_prefers_intended_url_over_return_to_parameter() { $user = User::factory()->create([ 'email' => 'tenant@example.com', 'role' => 'tenant_admin', 'password' => bcrypt('password'), 'email_verified_at' => now(), ]); $intended = 'http://localhost/event-admin/dashboard?from=intended-test'; $returnTarget = '/event-admin/dashboard'; $encodedReturn = rtrim(strtr(base64_encode($returnTarget), '+/', '-_'), '='); $response = $this ->withSession(['url.intended' => $intended]) ->post(route('login.store'), [ 'login' => 'tenant@example.com', 'password' => 'password', 'return_to' => $encodedReturn, ]); $this->assertAuthenticated(); $this->assertSame($user->id, Auth::id()); $response->assertRedirect($intended); } public function test_tenant_admin_login_with_absolute_intended_redirects_to_event_admin_dashboard(): void { $user = User::factory()->create([ 'email' => 'absolute@example.com', 'role' => 'tenant_admin', 'password' => bcrypt('password'), 'email_verified_at' => now(), ]); $intended = url('/event-admin/dashboard?from=oauth'); $response = $this ->withSession(['url.intended' => $intended]) ->post(route('login.store'), [ 'login' => 'absolute@example.com', 'password' => 'password', ]); $this->assertAuthenticatedAs($user); $response->assertRedirect($intended); $dashboardResponse = $this->get('/dashboard'); $dashboardResponse->assertRedirect('/event-admin/dashboard?from=oauth'); } public function test_tenant_admin_login_ignores_non_admin_return_path() { $user = User::factory()->create([ 'email' => 'admin@example.com', 'role' => 'tenant_admin', 'password' => bcrypt('password'), 'email_verified_at' => now(), ]); $encodedReturn = rtrim(strtr(base64_encode('/dashboard'), '+/', '-_'), '='); $response = $this->post(route('login.store'), [ 'login' => 'admin@example.com', 'password' => 'password', 'return_to' => $encodedReturn, ]); $this->assertAuthenticatedAs($user); $response->assertRedirect('/event-admin/dashboard'); } public function test_tenant_admin_can_access_login_with_admin_return_path_when_authenticated() { $user = User::factory()->create([ 'email' => 'already@logged.in', 'role' => 'tenant_admin', 'password' => bcrypt('password'), 'email_verified_at' => now(), ]); $this->actingAs($user); $adminStart = '/event-admin/start?return_to='.rtrim(strtr(base64_encode('/event-admin/dashboard'), '+/', '-_'), '='); $encoded = rtrim(strtr(base64_encode($adminStart), '+/', '-_'), '='); $response = $this->get('/de/login?return_to='.$encoded); $response->assertRedirect('/dashboard'); $eventAdminResponse = $this->get('/event-admin/dashboard'); $eventAdminResponse->assertOk(); } public function test_login_redirects_unverified_user_to_verification_notice() { $user = User::factory()->create([ 'email' => 'unverified@example.com', 'password' => bcrypt('password'), 'email_verified_at' => null, ]); $response = $this->post(route('login.store'), [ 'login' => 'unverified@example.com', 'password' => 'password', ]); $this->assertAuthenticated(); $response->assertRedirect(route('verification.notice', absolute: false)); } public function test_rate_limiting_on_failed_logins() { $user = User::factory()->create([ 'email' => 'ratelimit@example.com', 'password' => bcrypt('password'), ]); // Simulate 5 failed attempts for ($i = 0; $i < 5; $i++) { $response = $this->post(route('login.store'), [ 'login' => 'ratelimit@example.com', 'password' => 'wrongpassword', ]); $response->assertStatus(302); $response->assertSessionHasErrors(['login' => 'Diese Anmeldedaten wurden nicht gefunden.']); } $response = $this->post(route('login.store'), [ 'login' => 'ratelimit@example.com', 'password' => 'wrongpassword', ]); $this->assertGuest(); $response->assertStatus(302); $response->assertSessionHasErrors(['login']); $this->assertStringContainsString( 'Zu viele Login-Versuche.', collect(session('errors')->get('login'))->first() ); } }