mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-12 20:15:36 +00:00
chore(tests): reorganize feature suites and expand team auth coverage
This commit is contained in:
1 parent
34d8499a0c
commit
347af07a79
70 files changed
+125
-294
No files matched your search
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+4
-4
@@ -25,7 +25,7 @@ beforeEach(function () {
|
||||
$this->environment = Environment::factory()->create(['project_id' => $this->project->id]);
|
||||
});
|
||||
|
||||
function authHeaders(): array
|
||||
function domainApiAuthHeaders(): array
|
||||
{
|
||||
return [
|
||||
'Authorization' => 'Bearer '.test()->bearerToken,
|
||||
@@ -40,7 +40,7 @@ test('returns domains for own team application via uuid query param', function (
|
||||
'destination_type' => $this->destination->getMorphClass(),
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders())
|
||||
$response = $this->withHeaders(domainApiAuthHeaders())
|
||||
->getJson("/api/v1/servers/{$this->server->uuid}/domains?uuid={$application->uuid}");
|
||||
|
||||
$response->assertOk();
|
||||
@@ -64,7 +64,7 @@ test('returns 404 when application uuid belongs to another team', function () {
|
||||
'destination_type' => $otherDestination->getMorphClass(),
|
||||
]);
|
||||
|
||||
$response = $this->withHeaders(authHeaders())
|
||||
$response = $this->withHeaders(domainApiAuthHeaders())
|
||||
->getJson("/api/v1/servers/{$this->server->uuid}/domains?uuid={$otherApplication->uuid}");
|
||||
|
||||
$response->assertNotFound();
|
||||
@@ -72,7 +72,7 @@ test('returns 404 when application uuid belongs to another team', function () {
|
||||
});
|
||||
|
||||
test('returns 404 for nonexistent application uuid', function () {
|
||||
$response = $this->withHeaders(authHeaders())
|
||||
$response = $this->withHeaders(domainApiAuthHeaders())
|
||||
->getJson("/api/v1/servers/{$this->server->uuid}/domains?uuid=nonexistent-uuid");
|
||||
|
||||
$response->assertNotFound();
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+120
@@ -205,3 +205,123 @@ test('user from different team cannot manage members', function () {
|
||||
|
||||
expect(auth()->user()->can('manageMembers', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
// --- Team Policy: view ---
|
||||
|
||||
test('owner can view team', function () {
|
||||
$this->actingAs($this->owner);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect(auth()->user()->can('view', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('admin can view team', function () {
|
||||
$this->actingAs($this->admin);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect(auth()->user()->can('view', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('member can view team', function () {
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect(auth()->user()->can('view', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('non-team member cannot view team', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect($outsider->can('view', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
// --- Team Policy: viewAdmin ---
|
||||
|
||||
test('owner can view admin panel', function () {
|
||||
$this->actingAs($this->owner);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect(auth()->user()->can('viewAdmin', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('admin can view admin panel', function () {
|
||||
$this->actingAs($this->admin);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect(auth()->user()->can('viewAdmin', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('member cannot view admin panel', function () {
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect(auth()->user()->can('viewAdmin', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
test('non-team member cannot view admin panel', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect($outsider->can('viewAdmin', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
// --- Non-team member isolation ---
|
||||
|
||||
test('non-team member cannot update team', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect($outsider->can('update', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
test('non-team member cannot delete team', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect($outsider->can('delete', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
test('non-team member cannot manage members', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect($outsider->can('manageMembers', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
test('non-team member cannot manage invitations', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect($outsider->can('manageInvitations', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
// --- Team creation and model-level protection ---
|
||||
|
||||
test('member can create a new independent team', function () {
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
$newTeam = Team::create([
|
||||
'name' => 'New Team',
|
||||
'description' => 'Created by member',
|
||||
'personal_team' => false,
|
||||
]);
|
||||
|
||||
expect($newTeam)->toBeInstanceOf(Team::class)
|
||||
->and($newTeam->name)->toBe('New Team');
|
||||
});
|
||||
|
||||
test('member cannot update an existing team at model level', function () {
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect(fn () => $this->team->update(['name' => 'Hacked']))
|
||||
->toThrow(\Exception::class, 'You are not allowed to update this team.');
|
||||
});
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\Server;
|
||||
use App\Models\User;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use Tests\TestCase;
|
||||
use Tests\Traits\HandlesTestDatabase;
|
||||
|
||||
class ExecuteContainerCommandTest extends TestCase
|
||||
{
|
||||
use HandlesTestDatabase;
|
||||
|
||||
private $user;
|
||||
|
||||
private $team;
|
||||
|
||||
private $server;
|
||||
|
||||
private $application;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// Only set up database for tests that need it
|
||||
if ($this->shouldSetUpDatabase()) {
|
||||
$this->setUpTestDatabase();
|
||||
}
|
||||
// Create test data
|
||||
$this->user = User::factory()->create();
|
||||
$this->team = $this->user->teams()->first();
|
||||
$this->server = Server::factory()->create(['team_id' => $this->team->id]);
|
||||
$this->application = Application::factory()->create();
|
||||
|
||||
// Login the user
|
||||
$this->actingAs($this->user);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
if ($this->shouldSetUpDatabase()) {
|
||||
$this->tearDownTestDatabase();
|
||||
}
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
private function shouldSetUpDatabase(): bool
|
||||
{
|
||||
return in_array($this->name(), [
|
||||
'it_allows_valid_container_access',
|
||||
'it_prevents_cross_server_container_access',
|
||||
]);
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
namespace Tests\Feature\Helpers;
|
||||
|
||||
use Tests\TestCase;
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,232 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
// Create a team with owner, admin, and member
|
||||
$this->team = Team::factory()->create();
|
||||
|
||||
$this->owner = User::factory()->create();
|
||||
$this->admin = User::factory()->create();
|
||||
$this->member = User::factory()->create();
|
||||
|
||||
$this->team->members()->attach($this->owner->id, ['role' => 'owner']);
|
||||
$this->team->members()->attach($this->admin->id, ['role' => 'admin']);
|
||||
$this->team->members()->attach($this->member->id, ['role' => 'member']);
|
||||
});
|
||||
|
||||
describe('update permission', function () {
|
||||
test('owner can update team', function () {
|
||||
$this->actingAs($this->owner);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->owner->can('update', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('admin can update team', function () {
|
||||
$this->actingAs($this->admin);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->admin->can('update', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('member cannot update team', function () {
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->member->can('update', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
test('non-team member cannot update team', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($outsider->can('update', $this->team))->toBeFalse();
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete permission', function () {
|
||||
test('owner can delete team', function () {
|
||||
$this->actingAs($this->owner);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->owner->can('delete', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('admin can delete team', function () {
|
||||
$this->actingAs($this->admin);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->admin->can('delete', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('member cannot delete team', function () {
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->member->can('delete', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
test('non-team member cannot delete team', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($outsider->can('delete', $this->team))->toBeFalse();
|
||||
});
|
||||
});
|
||||
|
||||
describe('manageMembers permission', function () {
|
||||
test('owner can manage members', function () {
|
||||
$this->actingAs($this->owner);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->owner->can('manageMembers', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('admin can manage members', function () {
|
||||
$this->actingAs($this->admin);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->admin->can('manageMembers', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('member cannot manage members', function () {
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->member->can('manageMembers', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
test('non-team member cannot manage members', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($outsider->can('manageMembers', $this->team))->toBeFalse();
|
||||
});
|
||||
});
|
||||
|
||||
describe('viewAdmin permission', function () {
|
||||
test('owner can view admin panel', function () {
|
||||
$this->actingAs($this->owner);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->owner->can('viewAdmin', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('admin can view admin panel', function () {
|
||||
$this->actingAs($this->admin);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->admin->can('viewAdmin', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('member cannot view admin panel', function () {
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->member->can('viewAdmin', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
test('non-team member cannot view admin panel', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($outsider->can('viewAdmin', $this->team))->toBeFalse();
|
||||
});
|
||||
});
|
||||
|
||||
describe('manageInvitations permission (privilege escalation fix)', function () {
|
||||
test('owner can manage invitations', function () {
|
||||
$this->actingAs($this->owner);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->owner->can('manageInvitations', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('admin can manage invitations', function () {
|
||||
$this->actingAs($this->admin);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->admin->can('manageInvitations', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('member cannot manage invitations (SECURITY FIX)', function () {
|
||||
// This test verifies the privilege escalation vulnerability is fixed
|
||||
// Previously, members could see and manage admin invitations
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->member->can('manageInvitations', $this->team))->toBeFalse();
|
||||
});
|
||||
|
||||
test('non-team member cannot manage invitations', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($outsider->can('manageInvitations', $this->team))->toBeFalse();
|
||||
});
|
||||
});
|
||||
|
||||
describe('create team', function () {
|
||||
test('member can create a new independent team', function () {
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
$newTeam = Team::create([
|
||||
'name' => 'New Team',
|
||||
'description' => 'Created by member',
|
||||
'personal_team' => false,
|
||||
]);
|
||||
|
||||
expect($newTeam)->toBeInstanceOf(Team::class)
|
||||
->and($newTeam->name)->toBe('New Team');
|
||||
});
|
||||
|
||||
test('member cannot update an existing team', function () {
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
expect(fn () => $this->team->update(['name' => 'Hacked']))
|
||||
->toThrow(\Exception::class, 'You are not allowed to update this team.');
|
||||
});
|
||||
|
||||
test('owner can create a new team', function () {
|
||||
$this->actingAs($this->owner);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
$newTeam = Team::create([
|
||||
'name' => 'Owner New Team',
|
||||
'personal_team' => false,
|
||||
]);
|
||||
|
||||
expect($newTeam)->toBeInstanceOf(Team::class);
|
||||
});
|
||||
|
||||
test('admin can create a new team', function () {
|
||||
$this->actingAs($this->admin);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
$newTeam = Team::create([
|
||||
'name' => 'Admin New Team',
|
||||
'personal_team' => false,
|
||||
]);
|
||||
|
||||
expect($newTeam)->toBeInstanceOf(Team::class);
|
||||
});
|
||||
});
|
||||
|
||||
describe('view permission', function () {
|
||||
test('owner can view team', function () {
|
||||
$this->actingAs($this->owner);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->owner->can('view', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('admin can view team', function () {
|
||||
$this->actingAs($this->admin);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->admin->can('view', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('member can view team', function () {
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($this->member->can('view', $this->team))->toBeTrue();
|
||||
});
|
||||
|
||||
test('non-team member cannot view team', function () {
|
||||
$outsider = User::factory()->create();
|
||||
$this->actingAs($outsider);
|
||||
session(['currentTeam' => $this->team]);
|
||||
expect($outsider->can('view', $this->team))->toBeFalse();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user