From f1ab9956e8a151ae36a48de7d53f8c313ef42e64 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 24 Oct 2026 18:14:46 +0200 Subject: [PATCH] fix(sources): only list the current team's applications on a source Co-Authored-By: Claude Opus 5.5 --- app/Livewire/Source/Gitea/Change.php | 2 +- app/Livewire/Source/Github/Change.php | 2 +- app/Livewire/Source/Gitlab/Change.php | 2 +- .../SystemWideGitSourceResourcesScopeTest.php | 101 ++++++++++++++++++ 4 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 tests/Feature/SystemWideGitSourceResourcesScopeTest.php diff --git a/app/Livewire/Source/Gitea/Change.php b/app/Livewire/Source/Gitea/Change.php index b09487e716..5980ed3fbf 100644 --- a/app/Livewire/Source/Gitea/Change.php +++ b/app/Livewire/Source/Gitea/Change.php @@ -143,7 +143,7 @@ class Change extends Component })->whereUuid($gitea_app_uuid)->firstOrFail(); $this->privateKeys = PrivateKey::ownedByCurrentTeamCached(); - $this->applications = $this->gitea_app->applications; + $this->applications = $this->gitea_app->applications()->whereRelation('environment.project.team', 'id', currentTeam()->id)->get(); $settings = instanceSettings(); diff --git a/app/Livewire/Source/Github/Change.php b/app/Livewire/Source/Github/Change.php index ca59577ccb..5ec577f2e4 100644 --- a/app/Livewire/Source/Github/Change.php +++ b/app/Livewire/Source/Github/Change.php @@ -305,7 +305,7 @@ class Change extends Component $this->authorize('view', $this->github_app); $this->privateKeys = PrivateKey::ownedByCurrentTeamCached(); - $this->applications = $this->github_app->applications; + $this->applications = $this->github_app->applications()->whereRelation('environment.project.team', 'id', currentTeam()->id)->get(); $settings = instanceSettings(); // Sync data from model to properties diff --git a/app/Livewire/Source/Gitlab/Change.php b/app/Livewire/Source/Gitlab/Change.php index 67bcea322b..a7ff5b47e8 100644 --- a/app/Livewire/Source/Gitlab/Change.php +++ b/app/Livewire/Source/Gitlab/Change.php @@ -143,7 +143,7 @@ class Change extends Component })->whereUuid($gitlab_app_uuid)->firstOrFail(); $this->privateKeys = PrivateKey::ownedByCurrentTeamCached(); - $this->applications = $this->gitlab_app->applications; + $this->applications = $this->gitlab_app->applications()->whereRelation('environment.project.team', 'id', currentTeam()->id)->get(); $settings = instanceSettings(); diff --git a/tests/Feature/SystemWideGitSourceResourcesScopeTest.php b/tests/Feature/SystemWideGitSourceResourcesScopeTest.php new file mode 100644 index 0000000000..1e339a0de6 --- /dev/null +++ b/tests/Feature/SystemWideGitSourceResourcesScopeTest.php @@ -0,0 +1,101 @@ +set('app.maintenance.driver', 'file'); + config()->set('cache.default', 'array'); + + InstanceSettings::forceCreate(['id' => 0]); + + $this->teamA = Team::factory()->create(); + $this->teamB = Team::factory()->create(); + $this->userB = User::factory()->create(); + $this->teamB->members()->attach($this->userB->id, ['role' => 'owner']); + + $this->actingAs($this->userB); + session(['currentTeam' => $this->teamB]); +}); + +function attachSourceApplication(Team $team, string $name, object $source): Application +{ + $project = Project::factory()->create(['team_id' => $team->id]); + $environment = Environment::factory()->create(['project_id' => $project->id]); + + return Application::factory()->create([ + 'name' => $name, + 'environment_id' => $environment->id, + 'source_id' => $source->id, + 'source_type' => $source::class, + ]); +} + +function systemWideGitSource(string $type, Team $owner): object +{ + $attributes = [ + 'name' => "System wide {$type}", + 'custom_user' => 'git', + 'custom_port' => 22, + 'team_id' => $owner->id, + 'is_system_wide' => true, + 'is_public' => false, + ]; + + return match ($type) { + 'github' => GithubApp::create([ + ...$attributes, + 'api_url' => 'https://api.github.com', + 'html_url' => 'https://github.com', + 'private_key_id' => PrivateKey::withoutEvents(fn () => PrivateKey::forceCreate([ + 'uuid' => 'resources-scope-key', + 'name' => 'Key', + 'private_key' => "-----BEGIN OPENSSH PRIVATE KEY-----\nKEY\n-----END OPENSSH PRIVATE KEY-----", + 'fingerprint' => 'resources-scope-fingerprint', + 'team_id' => $owner->id, + ]))->id, + ]), + 'gitlab' => GitlabApp::create([ + ...$attributes, + 'api_url' => 'https://gitlab.com/api/v4', + 'html_url' => 'https://gitlab.com', + ]), + 'gitea' => GiteaApp::create([ + ...$attributes, + 'api_url' => 'https://gitea.com/api/v1', + 'html_url' => 'https://gitea.com', + ]), + }; +} + +test('a system wide source lists only the applications of the current team', function (string $type, string $component, string $queryParameter) { + $source = systemWideGitSource($type, $this->teamA); + $foreignApplication = attachSourceApplication($this->teamA, 'team-a-secret-app', $source); + $ownApplication = attachSourceApplication($this->teamB, 'team-b-own-app', $source); + + $applications = Livewire::withQueryParams([$queryParameter => $source->uuid]) + ->test($component) + ->assertOk() + ->get('applications'); + + expect($applications->pluck('id')->all())->toBe([$ownApplication->id]); +})->with([ + 'github' => ['github', GithubChange::class, 'github_app_uuid'], + 'gitlab' => ['gitlab', GitlabChange::class, 'gitlab_app_uuid'], + 'gitea' => ['gitea', GiteaChange::class, 'gitea_app_uuid'], +]);