set('email', 'nieznany@firma.pl') ->set('subject', 'Temat') ->set('body', 'Treść') ->call('submit') ->assertHasErrors(['email']) ->assertSee('Nie znaleziono użytkownika o podanym adresie e-mail.'); expect(Ticket::query()->count())->toBe(0); }); test('restricting guest tickets to LDAP still allows a submission from an e-mail that exists in LDAP', function () { DirectoryEmulator::setup(); seedStatusesAndPriorities(); Settings::set('restrict_tickets_to_ldap', '1'); LldapUser::create([ 'uid' => 'znany.gosc', 'cn' => 'Znany Gość', 'mail' => 'znany.gosc@firma.pl', 'entryuuid' => (string) Str::uuid(), ]); Livewire::test(Landing::class) ->set('email', 'znany.gosc@firma.pl') ->set('subject', 'Temat') ->set('body', 'Treść') ->call('submit') ->assertHasNoErrors(); expect(Ticket::query()->where('email', 'znany.gosc@firma.pl')->exists())->toBeTrue(); }); test('restricting guest tickets to LDAP still allows an already-known local account even if LDAP lookup fails', function () { DirectoryEmulator::setup(); seedStatusesAndPriorities(); Settings::set('restrict_tickets_to_ldap', '1'); User::query()->create(['name' => 'Istniejący Klient', 'email' => 'istniejacy@firma.pl', 'roles' => ['client']]); Livewire::test(Landing::class) ->set('email', 'istniejacy@firma.pl') ->set('subject', 'Temat') ->set('body', 'Treść') ->call('submit') ->assertHasNoErrors(); expect(Ticket::query()->where('email', 'istniejacy@firma.pl')->exists())->toBeTrue(); }); test('leaving the restriction off (the default) allows any guest e-mail to file a ticket', function () { DirectoryEmulator::setup(); seedStatusesAndPriorities(); Livewire::test(Landing::class) ->set('email', 'ktokolwiek@example.com') ->set('subject', 'Temat') ->set('body', 'Treść') ->call('submit') ->assertHasNoErrors(); expect(Ticket::query()->where('email', 'ktokolwiek@example.com')->exists())->toBeTrue(); }); test('admin can create a local user with a password who can then log in without an LDAP entry', function () { DirectoryEmulator::setup(); $admin = adminUser(); Livewire::actingAs($admin)->test(Panel::class) ->call('openUserForm') ->set('userForm.name', 'Konto Lokalne') ->set('userForm.email', 'lokalny@firma.pl') ->set('userForm.password', 'sekretne-haslo') ->set('userForm.password_confirmation', 'sekretne-haslo') ->call('submitUser') ->assertOk(); $user = User::query()->where('email', 'lokalny@firma.pl')->firstOrFail(); expect($user->password)->not->toBeNull(); $ok = Auth::attempt([ 'uid' => 'lokalny@firma.pl', 'password' => 'sekretne-haslo', 'fallback' => ['email' => 'lokalny@firma.pl'], ]); expect($ok)->toBeTrue() ->and(Auth::id())->toBe($user->id); }); test('a mismatched password confirmation is rejected when creating a local user', function () { $admin = adminUser(); Livewire::actingAs($admin)->test(Panel::class) ->call('openUserForm') ->set('userForm.name', 'Konto Lokalne') ->set('userForm.email', 'zle-haslo@firma.pl') ->set('userForm.password', 'sekretne-haslo') ->set('userForm.password_confirmation', 'inne-haslo') ->call('submitUser') ->assertHasErrors(['userForm.password']); expect(User::query()->where('email', 'zle-haslo@firma.pl')->exists())->toBeFalse(); }); test('leaving the password blank keeps a user LDAP-only, as before', function () { $admin = adminUser(); Livewire::actingAs($admin)->test(Panel::class) ->call('openUserForm') ->set('userForm.name', 'Tylko LDAP') ->set('userForm.email', 'tylko-ldap@firma.pl') ->call('submitUser') ->assertOk(); $user = User::query()->where('email', 'tylko-ldap@firma.pl')->firstOrFail(); expect($user->password)->toBeNull(); }); /** * Exercises Login::safeRedirectTarget() directly via reflection rather than * through a full ->call('submit') — Livewire's test harness disables the * middleware stack (see RequestBroker::temporarilyDisableExceptionHandlingAndMiddleware), * so no session is ever bound to the request during a component test, and * submit() unconditionally touches the session to regenerate it. The * open-redirect guard itself has no such dependency, so it's tested in isolation. */ function safeRedirectTargetFor(?string $redirect): ?string { $login = new Login; $ref = new ReflectionClass($login); $prop = $ref->getProperty('redirect'); $prop->setAccessible(true); $prop->setValue($login, $redirect); $method = $ref->getMethod('safeRedirectTarget'); $method->setAccessible(true); return $method->invoke($login); } test('a same-app ?redirect= path is honored', function () { expect(safeRedirectTargetFor('/client/tickets/42'))->toBe('/client/tickets/42'); }); test('an external ?redirect= target is rejected to prevent an open redirect', function () { expect(safeRedirectTargetFor('https://evil.example.com/'))->toBeNull() ->and(safeRedirectTargetFor('//evil.example.com/'))->toBeNull() ->and(safeRedirectTargetFor(null))->toBeNull(); });