mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-04 10:42:23 +00:00
186 lines
6.2 KiB
PHP
186 lines
6.2 KiB
PHP
<?php
|
|
|
|
use App\Livewire\Security\ApiTokens;
|
|
use App\Models\InstanceSettings;
|
|
use App\Models\Team;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Livewire\Attributes\Locked;
|
|
use Livewire\Features\SupportLockedProperties\CannotUpdateLockedPropertyException;
|
|
use Livewire\Livewire;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
InstanceSettings::unguarded(fn () => InstanceSettings::query()->create([
|
|
'id' => 0,
|
|
'is_api_enabled' => true,
|
|
]));
|
|
|
|
$this->team = Team::factory()->create();
|
|
});
|
|
|
|
test('api token permission flags are locked', function (string $property) {
|
|
$property = new ReflectionProperty(ApiTokens::class, $property);
|
|
|
|
expect($property->getAttributes(Locked::class))->not->toBeEmpty();
|
|
})->with([
|
|
'root permission flag' => 'canUseRootPermissions',
|
|
'write permission flag' => 'canUseWritePermissions',
|
|
]);
|
|
|
|
test('member cannot tamper with root permission flag', function () {
|
|
$member = User::factory()->create();
|
|
$this->team->members()->attach($member->id, ['role' => 'member']);
|
|
|
|
$this->actingAs($member);
|
|
session(['currentTeam' => $this->team]);
|
|
|
|
Livewire::test(ApiTokens::class)
|
|
->set('canUseRootPermissions', true);
|
|
})->throws(CannotUpdateLockedPropertyException::class);
|
|
|
|
test('member cannot create root token through tampered permissions payload', function () {
|
|
$member = User::factory()->create();
|
|
$this->team->members()->attach($member->id, ['role' => 'member']);
|
|
|
|
$this->actingAs($member);
|
|
session(['currentTeam' => $this->team]);
|
|
|
|
Livewire::test(ApiTokens::class)
|
|
->set('form.description', 'pwned-root-token')
|
|
->set('form.expiresInDays', 30)
|
|
->set('form.permissions', ['root'])
|
|
->call('addNewToken');
|
|
|
|
expect($member->tokens()->count())->toBe(0);
|
|
});
|
|
|
|
test('member can still create read token', function () {
|
|
$member = User::factory()->create();
|
|
$this->team->members()->attach($member->id, ['role' => 'member']);
|
|
|
|
$this->actingAs($member);
|
|
session(['currentTeam' => $this->team]);
|
|
|
|
Livewire::test(ApiTokens::class)
|
|
->set('form.description', 'read-token')
|
|
->set('form.expiresInDays', 30)
|
|
->set('form.permissions', ['read'])
|
|
->call('addNewToken')
|
|
->assertHasNoErrors();
|
|
|
|
$token = $member->tokens()->latest()->first();
|
|
|
|
expect($token)->not->toBeNull()
|
|
->and($token->abilities)->toBe(['read']);
|
|
});
|
|
|
|
test('api token list only contains tokens for the current team', function () {
|
|
$user = User::factory()->create();
|
|
$otherTeam = Team::factory()->create();
|
|
$this->team->members()->attach($user->id, ['role' => 'admin']);
|
|
$otherTeam->members()->attach($user->id, ['role' => 'admin']);
|
|
|
|
session(['currentTeam' => $this->team]);
|
|
$currentTeamToken = $user->createToken('current-team-token', ['read'])->accessToken;
|
|
|
|
session(['currentTeam' => $otherTeam]);
|
|
$user->createToken('other-team-token', ['read']);
|
|
|
|
$this->actingAs($user);
|
|
session(['currentTeam' => $this->team]);
|
|
|
|
Livewire::test(ApiTokens::class)
|
|
->assertSet('tokens', fn ($tokens) => $tokens->pluck('id')->all() === [$currentTeamToken->id]);
|
|
});
|
|
|
|
test('user cannot revoke a token from another team through the current team', function () {
|
|
$user = User::factory()->create();
|
|
$otherTeam = Team::factory()->create();
|
|
$this->team->members()->attach($user->id, ['role' => 'admin']);
|
|
$otherTeam->members()->attach($user->id, ['role' => 'admin']);
|
|
|
|
session(['currentTeam' => $otherTeam]);
|
|
$otherTeamToken = $user->createToken('other-team-token', ['read'])->accessToken;
|
|
|
|
$this->actingAs($user);
|
|
session(['currentTeam' => $this->team]);
|
|
|
|
Livewire::test(ApiTokens::class)->call('revoke', $otherTeamToken->id);
|
|
|
|
expect($user->tokens()->whereKey($otherTeamToken->id)->exists())->toBeTrue();
|
|
});
|
|
|
|
test('owner can create root token', function () {
|
|
$owner = User::factory()->create();
|
|
$this->team->members()->attach($owner->id, ['role' => 'owner']);
|
|
|
|
$this->actingAs($owner);
|
|
session(['currentTeam' => $this->team]);
|
|
|
|
Livewire::test(ApiTokens::class)
|
|
->set('form.description', 'root-token')
|
|
->set('form.expiresInDays', 30)
|
|
->set('form.permissions', ['root'])
|
|
->call('addNewToken')
|
|
->assertHasNoErrors();
|
|
|
|
$token = $owner->tokens()->latest()->first();
|
|
|
|
expect($token)->not->toBeNull()
|
|
->and($token->abilities)->toBe(['root']);
|
|
});
|
|
|
|
test('owner can deselect root and falls back to read permission', function () {
|
|
$owner = User::factory()->create();
|
|
$this->team->members()->attach($owner->id, ['role' => 'owner']);
|
|
|
|
$this->actingAs($owner);
|
|
session(['currentTeam' => $this->team]);
|
|
|
|
Livewire::test(ApiTokens::class)
|
|
->set('form.permissions', ['root'])
|
|
->set('form.permissions', [])
|
|
->assertSet('form.permissions', ['read']);
|
|
});
|
|
|
|
test('deploy permission can be combined with write permission', function (array $steps) {
|
|
$owner = User::factory()->create();
|
|
$this->team->members()->attach($owner->id, ['role' => 'owner']);
|
|
|
|
$this->actingAs($owner);
|
|
session(['currentTeam' => $this->team]);
|
|
|
|
$component = Livewire::test(ApiTokens::class)->set('form.permissions', ['read']);
|
|
|
|
foreach ($steps as $permission) {
|
|
$component->set('form.permissions.'.count($component->get('form.permissions')), $permission);
|
|
}
|
|
|
|
$component->assertSet('form.permissions', ['deploy', 'read', 'write']);
|
|
})->with([
|
|
'write then deploy' => [['write', 'deploy']],
|
|
'deploy then write' => [['deploy', 'write']],
|
|
]);
|
|
|
|
test('owner can create token with read, write, and deploy permissions', function () {
|
|
$owner = User::factory()->create();
|
|
$this->team->members()->attach($owner->id, ['role' => 'owner']);
|
|
|
|
$this->actingAs($owner);
|
|
session(['currentTeam' => $this->team]);
|
|
|
|
Livewire::test(ApiTokens::class)
|
|
->set('form.description', 'deploy-write-token')
|
|
->set('form.expiresInDays', 30)
|
|
->set('form.permissions', ['read', 'write', 'deploy'])
|
|
->call('addNewToken')
|
|
->assertHasNoErrors();
|
|
|
|
$token = $owner->tokens()->latest()->first();
|
|
|
|
expect($token)->not->toBeNull()
|
|
->and($token->abilities)->toEqualCanonicalizing(['read', 'write', 'deploy']);
|
|
});
|