seed(RolesAndPermissionsSeeder::class); }); function editorActor(): User { $editor = User::factory()->create(); $editor->assignRole('editor'); return $editor; } test('editor is blocked from admin-only management pages', function () { /** @var TestCase $this */ $this->actingAs(editorActor()); foreach ([ 'admin/categories', 'admin/categories/create', 'admin/footer-codes', 'admin/footer-codes/create', 'admin/payments', 'admin/coupons', 'admin/invoices', 'admin/legal-requests', 'admin/contact-messages', ] as $path) { $this->get("https://pressekonto.test/{$path}")->assertForbidden(); } }); test('editor keeps access to content and read-only CRM pages', function () { /** @var TestCase $this */ $this->actingAs(editorActor()); $this->get('https://pressekonto.test/admin/press-releases')->assertSuccessful(); $this->get('https://pressekonto.test/admin/companies')->assertSuccessful(); $this->get('https://pressekonto.test/admin/contacts')->assertSuccessful(); }); test('editor cannot open company write forms', function () { /** @var TestCase $this */ $company = Company::factory()->presseecho()->create(); $this->actingAs(editorActor()); $this->get('https://pressekonto.test/admin/companies/create')->assertForbidden(); $this->get("https://pressekonto.test/admin/companies/{$company->id}/edit")->assertForbidden(); }); test('editor cannot delete a contact from the index', function () { /** @var TestCase $this */ $company = Company::factory()->presseecho()->create(); $contact = Contact::factory()->for($company)->create(); $this->actingAs(editorActor()); Livewire::test('admin.contacts.index') ->call('deleteContactFromIndex', $contact->id) ->assertForbidden(); expect(Contact::query()->whereKey($contact->id)->exists())->toBeTrue(); }); test('editor cannot invoke admin-only livewire actions directly', function () { /** @var TestCase $this */ $this->actingAs(editorActor()); Livewire::test('admin.categories.create') ->call('save') ->assertForbidden(); Livewire::test('admin.footer-codes.create') ->call('save') ->assertForbidden(); Livewire::test('admin.payments.index') ->call('cancelBundle', 999_999) ->assertForbidden(); Livewire::test('admin.legal-requests.index') ->call('resolveWithdrawal', 999_999) ->assertForbidden(); Livewire::test('admin.press-releases.index') ->set('legacyApiAiReview', true) ->assertForbidden(); expect(AppSetting::getBool(LegacyPressReleaseController::SETTING_AI_REVIEW))->toBeFalse(); }); test('admin retains access to all restricted management pages', function () { /** @var TestCase $this */ $admin = User::factory()->create(); $admin->assignRole('admin'); $this->actingAs($admin); foreach ([ 'admin/categories', 'admin/footer-codes', 'admin/invoices', 'admin/legal-requests', 'admin/contact-messages', ] as $path) { $this->get("https://pressekonto.test/{$path}")->assertSuccessful(); } }); /* * Sicherheitsaudit 07.10.2026, S-02: Die Firmenanzeige ist für Editoren * lesbar, das Umhängen eines Kontakts aber eine Schreibaktion. */ test('editor cannot attach an existing contact to another company', function () { /** @var TestCase $this */ $source = Company::factory()->presseecho()->create(); $target = Company::factory()->presseecho()->create(); $contact = Contact::factory()->for($source)->create(); $this->actingAs(editorActor()); Livewire::test('admin.companies.show', ['id' => $target->id]) ->set('selectedExistingContactId', $contact->id) ->assertForbidden(); Livewire::test('admin.companies.show', ['id' => $target->id]) ->call('attachExistingContact') ->assertForbidden(); expect($contact->fresh()->company_id)->toBe($source->id); }); test('the company id of the company page cannot be changed by the client', function () { /** @var TestCase $this */ $company = Company::factory()->presseecho()->create(); $admin = User::factory()->create(); $admin->assignRole('admin'); $this->actingAs($admin); expect(fn () => Livewire::test('admin.companies.show', ['id' => $company->id])->set('id', $company->id + 1)) ->toThrow(CannotUpdateLockedPropertyException::class); }); test('admin can still attach an existing contact to a company', function () { /** @var TestCase $this */ $source = Company::factory()->presseecho()->create(); $target = Company::factory()->presseecho()->create(); $contact = Contact::factory()->for($source)->create(); $admin = User::factory()->create(); $admin->assignRole('admin'); $this->actingAs($admin); Livewire::test('admin.companies.show', ['id' => $target->id]) ->set('selectedExistingContactId', $contact->id) ->assertHasNoErrors(); expect($contact->fresh()->company_id)->toBe($target->id); });