orgA = Organisation::factory()->create(); $this->orgB = Organisation::factory()->create(); $this->eventA = Event::factory()->for($this->orgA)->create(); $this->eventB = Event::factory()->for($this->orgB)->create(); } private function withOrgRoute(Organisation $org): void { $route = new Route(['GET'], '/_test', static fn () => null); $route->bind(request()); $route->setParameter('organisation', $org); request()->setRouteResolver(static fn () => $route); } public function test_artist_scope_blocks_cross_org(): void { Artist::factory()->create(['organisation_id' => $this->orgA->id]); Artist::factory()->create(['organisation_id' => $this->orgB->id]); $this->withOrgRoute($this->orgA); $this->assertSame(1, Artist::query()->count()); $this->assertSame(2, Artist::withoutGlobalScope(OrganisationScope::class)->count()); } public function test_genre_scope_blocks_cross_org(): void { Genre::factory()->create(['organisation_id' => $this->orgA->id]); Genre::factory()->create(['organisation_id' => $this->orgB->id]); $this->withOrgRoute($this->orgB); $genres = Genre::query()->get(); $this->assertCount(1, $genres); $this->assertSame($this->orgB->id, $genres->first()->organisation_id); } public function test_artist_engagement_scope_blocks_cross_org(): void { $artistA = Artist::factory()->create(['organisation_id' => $this->orgA->id]); $artistB = Artist::factory()->create(['organisation_id' => $this->orgB->id]); ArtistEngagement::create([ 'artist_id' => $artistA->id, 'event_id' => $this->eventA->id, 'booking_status' => ArtistEngagementStatus::Draft->value, ]); ArtistEngagement::create([ 'artist_id' => $artistB->id, 'event_id' => $this->eventB->id, 'booking_status' => ArtistEngagementStatus::Draft->value, ]); $this->withOrgRoute($this->orgA); $this->assertSame(1, ArtistEngagement::query()->count()); } public function test_stage_fk_chain_scope_blocks_cross_org(): void { Stage::factory()->for($this->eventA)->create(); Stage::factory()->for($this->eventA)->create(); Stage::factory()->for($this->eventB)->create(); $this->withOrgRoute($this->orgA); $this->assertSame(2, Stage::query()->count()); $this->assertSame(3, Stage::withoutGlobalScope(OrganisationScope::class)->count()); } public function test_performance_fk_chain_scope_blocks_cross_org(): void { $artistA = Artist::factory()->create(['organisation_id' => $this->orgA->id]); $artistB = Artist::factory()->create(['organisation_id' => $this->orgB->id]); $engA = ArtistEngagement::create([ 'artist_id' => $artistA->id, 'event_id' => $this->eventA->id, 'booking_status' => ArtistEngagementStatus::Draft->value, ]); $engB = ArtistEngagement::create([ 'artist_id' => $artistB->id, 'event_id' => $this->eventB->id, 'booking_status' => ArtistEngagementStatus::Draft->value, ]); $stageA = Stage::factory()->for($this->eventA)->create(); $stageB = Stage::factory()->for($this->eventB)->create(); $start = CarbonImmutable::now(); Performance::create([ 'engagement_id' => $engA->id, 'event_id' => $this->eventA->id, 'stage_id' => $stageA->id, 'start_at' => $start, 'end_at' => $start->addHour(), ]); Performance::create([ 'engagement_id' => $engB->id, 'event_id' => $this->eventB->id, 'stage_id' => $stageB->id, 'start_at' => $start, 'end_at' => $start->addHour(), ]); $this->withOrgRoute($this->orgB); $this->assertSame(1, Performance::query()->count()); $this->assertSame(2, Performance::withoutGlobalScope(OrganisationScope::class)->count()); } }