Merge remote-tracking branch 'origin/next' into harden-database-import-files

This commit is contained in:
Andras Bacsai committed 2026-06-29 10:35:35 +02:00
commit 7d65a4b496
550 files changed
+18078 -5008

No files matched your search

+1 -1
View File
@@ -182,7 +182,7 @@ test('escapeshellarg neutralizes command injection in mariadb password', functio
$escaped = escapeshellarg($maliciousPassword);
// Single quotes in the value get escaped as '\''
expect($escaped)->toBe("'pass'\\'''; whoami; echo '\\'''");
expect($escaped)->toBe("'pass'\\''; whoami; echo '\\'''");
$command = "docker exec container mariadb-dump -u root -p$escaped db";
// Verify the command doesn't contain an unescaped semicolon outside quotes
expect($command)->toContain("-p'pass'");
+87 -31
View File
@@ -4,11 +4,50 @@ use App\Models\Application;
use App\Models\ApplicationSetting;
use App\Models\GitlabApp;
use App\Models\PrivateKey;
use Illuminate\Support\Collection;
afterEach(function () {
Mockery::close();
});
function commandStrings(array|Collection|string $commands): Collection
{
if (is_string($commands)) {
return collect([$commands]);
}
return collect($commands)->map(fn ($command) => data_get($command, 'command') ?? $command[0] ?? $command);
}
function privateKeyMaterializationCommands(array|Collection|string $commands): Collection
{
if (is_string($commands)) {
$commands = [$commands];
}
return collect($commands)->filter(fn ($command) => str(commandStrings([$command])->first())->contains('base64 -d | tee /root/.ssh/id_rsa_coolify_'));
}
function expectCommandListToContain(array|Collection|string $commands, string $expected): void
{
expect(commandStrings($commands)->implode(' && '))->toContain($expected);
}
function expectCommandListNotToContain(array|Collection|string $commands, string $expected): void
{
expect(commandStrings($commands)->implode(' && '))->not->toContain($expected);
}
function expectPrivateKeyMaterializationCommandsSkipLogging(array|Collection|string $commands): void
{
$keyCommands = privateKeyMaterializationCommands($commands);
expect($keyCommands)->not->toBeEmpty();
$keyCommands->each(function ($command): void {
expect(data_get($command, 'skip_command_log'))->toBeTrue();
});
}
/**
* Git operations authenticate with the SSH key assigned in the UI. Coolify writes that key to a
* per-deployment path (/root/.ssh/id_rsa_coolify_<deployment_uuid>) instead of the shared
@@ -19,6 +58,24 @@ afterEach(function () {
*/
$keyPath = '/root/.ssh/id_rsa_coolify_test-deployment-uuid';
it('skips logging the docker deploy key materialization command before ls-remote', function () {
$source = file_get_contents(__DIR__.'/../../app/Jobs/ApplicationDeploymentJob.php');
$commandPosition = strpos($source, 'base64 -d | tee {$customSshKeyLocation}');
expect($commandPosition)->not->toBeFalse()
->and(substr($source, $commandPosition, 200))->toContain("'skip_command_log' => true");
});
it('supports skipping command log entries without adding a hidden command entry', function () {
$source = file_get_contents(__DIR__.'/../../app/Traits/ExecuteRemoteCommand.php');
expect($source)
->toContain('$skip_command_log = data_get($single_command, \'skip_command_log\', false);')
->toContain('if ($command_hidden && ! $skip_command_log && isset($this->application_deployment_queue))')
->toContain('use ($command, $hidden, $customType, $append, $command_hidden, $skip_command_log)')
->toContain('\'command\' => $skip_command_log || $command_hidden ? null : $this->redact_sensitive_info($command),');
});
it('writes a deploy key to a per-deployment path and cleans it up for ls-remote on the host', function () use ($keyPath) {
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->shouldReceive('getAttribute')->with('private_key')->andReturn('fake-private-key');
@@ -31,11 +88,11 @@ it('writes a deploy key to a per-deployment path and cleans it up for ls-remote
$result = $application->generateGitLsRemoteCommands('test-deployment-uuid', false);
expect($result['commands'])
->toContain("tee {$keyPath}")
->toContain("-i {$keyPath} -o IdentitiesOnly=yes")
->toContain("trap 'rm -f {$keyPath}' EXIT") // removed when the shell exits
->not->toContain('tee /root/.ssh/id_rsa >'); // never overwrites the host root's own key
expectCommandListToContain($result['commands'], "tee {$keyPath}");
expectCommandListToContain($result['commands'], "-i {$keyPath} -o IdentitiesOnly=yes");
expectCommandListToContain($result['commands'], "trap 'rm -f {$keyPath}' EXIT"); // removed when the shell exits
expectCommandListNotToContain($result['commands'], 'tee /root/.ssh/id_rsa >'); // never overwrites the host root's own key
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
});
it('writes a deploy key to a per-deployment path for ls-remote inside docker without a trap', function () use ($keyPath) {
@@ -50,11 +107,11 @@ it('writes a deploy key to a per-deployment path for ls-remote inside docker wit
$result = $application->generateGitLsRemoteCommands('test-deployment-uuid', true);
expect($result['commands'])
->toContain("tee {$keyPath}")
->toContain("-i {$keyPath} -o IdentitiesOnly=yes")
->not->toContain('trap ') // ephemeral container, no cleanup needed
->not->toContain('tee /root/.ssh/id_rsa >');
expectCommandListToContain($result['commands'], "tee {$keyPath}");
expectCommandListToContain($result['commands'], "-i {$keyPath} -o IdentitiesOnly=yes");
expectCommandListNotToContain($result['commands'], 'trap '); // ephemeral container, no cleanup needed
expectCommandListNotToContain($result['commands'], 'tee /root/.ssh/id_rsa >');
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
});
it('writes a GitLab source private key to a per-deployment path with cleanup on the host', function () use ($keyPath) {
@@ -77,11 +134,11 @@ it('writes a GitLab source private key to a per-deployment path with cleanup on
$result = $application->generateGitLsRemoteCommands('test-deployment-uuid', false);
expect($result['commands'])
->toContain("tee {$keyPath}")
->toContain("-i {$keyPath} -o IdentitiesOnly=yes")
->toContain("trap 'rm -f {$keyPath}' EXIT")
->not->toContain('tee /root/.ssh/id_rsa >');
expectCommandListToContain($result['commands'], "tee {$keyPath}");
expectCommandListToContain($result['commands'], "-i {$keyPath} -o IdentitiesOnly=yes");
expectCommandListToContain($result['commands'], "trap 'rm -f {$keyPath}' EXIT");
expectCommandListNotToContain($result['commands'], 'tee /root/.ssh/id_rsa >');
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
});
it('writes a deploy key to a per-deployment path and cleans it up when cloning on the host', function () use ($keyPath) {
@@ -104,11 +161,11 @@ it('writes a deploy key to a per-deployment path and cleans it up when cloning o
// exec_in_docker = false → the loadComposeFile / host clone path
$result = $application->generateGitImportCommands('test-deployment-uuid', 0, null, false);
expect($result['commands'])
->toContain("tee {$keyPath}")
->toContain("-i {$keyPath} -o IdentitiesOnly=yes")
->toContain("trap 'rm -f {$keyPath}' EXIT")
->not->toContain('tee /root/.ssh/id_rsa >');
expectCommandListToContain($result['commands'], "tee {$keyPath}");
expectCommandListToContain($result['commands'], "-i {$keyPath} -o IdentitiesOnly=yes");
expectCommandListToContain($result['commands'], "trap 'rm -f {$keyPath}' EXIT");
expectCommandListNotToContain($result['commands'], 'tee /root/.ssh/id_rsa >');
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
});
it('writes a GitLab source private key to a per-deployment path and cleans it up when cloning on the host', function () use ($keyPath) {
@@ -137,11 +194,11 @@ it('writes a GitLab source private key to a per-deployment path and cleans it up
$result = $application->generateGitImportCommands('test-deployment-uuid', 0, null, false);
expect($result['commands'])
->toContain("tee {$keyPath}")
->toContain("-i {$keyPath} -o IdentitiesOnly=yes")
->toContain("trap 'rm -f {$keyPath}' EXIT")
->not->toContain('tee /root/.ssh/id_rsa >');
expectCommandListToContain($result['commands'], "tee {$keyPath}");
expectCommandListToContain($result['commands'], "-i {$keyPath} -o IdentitiesOnly=yes");
expectCommandListToContain($result['commands'], "trap 'rm -f {$keyPath}' EXIT");
expectCommandListNotToContain($result['commands'], 'tee /root/.ssh/id_rsa >');
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
});
it('uses the per-deployment deploy key for pull request fetches', function () use ($keyPath) {
@@ -163,9 +220,9 @@ it('uses the per-deployment deploy key for pull request fetches', function () us
$result = $application->generateGitImportCommands('test-deployment-uuid', 123, 'github', false);
expect($result['commands'])
->toContain("GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i {$keyPath} -o IdentitiesOnly=yes\" git fetch origin pull/123/head:pr-123-coolify")
->not->toContain('GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa" git fetch origin pull/123/head:pr-123-coolify');
expectCommandListToContain($result['commands'], "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i {$keyPath} -o IdentitiesOnly=yes\" git fetch origin pull/123/head:pr-123-coolify");
expectCommandListNotToContain($result['commands'], 'GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa" git fetch origin pull/123/head:pr-123-coolify');
expectPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
});
it('does not force a missing per-deployment key for other repository pull request fetches', function () use ($keyPath) {
@@ -183,7 +240,6 @@ it('does not force a missing per-deployment key for other repository pull reques
$result = $application->generateGitImportCommands('test-deployment-uuid', 123, 'github', false);
expect($result['commands'])
->toContain('GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa" git fetch origin pull/123/head:pr-123-coolify')
->not->toContain($keyPath);
expectCommandListToContain($result['commands'], 'GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa" git fetch origin pull/123/head:pr-123-coolify');
expectCommandListNotToContain($result['commands'], $keyPath);
});
+47 -9
View File
@@ -3,11 +3,45 @@
use App\Models\Application;
use App\Models\GitlabApp;
use App\Models\PrivateKey;
use Illuminate\Support\Collection;
afterEach(function () {
Mockery::close();
});
function gitlabCommandStrings(array|Collection|string $commands): Collection
{
if (is_string($commands)) {
return collect([$commands]);
}
return collect($commands)->map(fn ($command) => data_get($command, 'command') ?? $command[0] ?? $command);
}
function expectGitlabCommandListToContain(array|Collection|string $commands, string $expected): void
{
expect(gitlabCommandStrings($commands)->implode(' && '))->toContain($expected);
}
function expectGitlabCommandListNotToContain(array|Collection|string $commands, string $expected): void
{
expect(gitlabCommandStrings($commands)->implode(' && '))->not->toContain($expected);
}
function expectGitlabPrivateKeyMaterializationCommandsSkipLogging(array|Collection|string $commands): void
{
if (is_string($commands)) {
$commands = [$commands];
}
$keyCommands = collect($commands)->filter(fn ($command) => str(data_get($command, 'command') ?? $command[0] ?? $command)->contains('base64 -d | tee /root/.ssh/id_rsa_coolify_'));
expect($keyCommands)->not->toBeEmpty();
$keyCommands->each(function ($command): void {
expect(data_get($command, 'skip_command_log'))->toBeTrue();
});
}
it('generates ls-remote commands for GitLab source with private key', function () {
$deploymentUuid = 'test-deployment-uuid';
@@ -15,7 +49,8 @@ it('generates ls-remote commands for GitLab source with private key', function (
$privateKey->shouldReceive('getAttribute')->with('private_key')->andReturn('fake-private-key');
$gitlabSource = Mockery::mock(GitlabApp::class)->makePartial();
$gitlabSource->shouldReceive('getMorphClass')->andReturn(\App\Models\GitlabApp::class);
$gitlabSource->shouldReceive('getMorphClass')->andReturn(GitlabApp::class);
$gitlabSource->shouldReceive('getAttribute')->with('html_url')->andReturn('https://gitlab.com');
$gitlabSource->shouldReceive('getAttribute')->with('privateKey')->andReturn($privateKey);
$gitlabSource->shouldReceive('getAttribute')->with('private_key_id')->andReturn(1);
$gitlabSource->shouldReceive('getAttribute')->with('custom_port')->andReturn(22);
@@ -34,16 +69,18 @@ it('generates ls-remote commands for GitLab source with private key', function (
expect($result)->toBeArray();
expect($result)->toHaveKey('commands');
expect($result['commands'])->toContain('git ls-remote');
expect($result['commands'])->toContain('id_rsa');
expect($result['commands'])->toContain('mkdir -p /root/.ssh');
expectGitlabCommandListToContain($result['commands'], 'git ls-remote');
expectGitlabCommandListToContain($result['commands'], 'id_rsa');
expectGitlabCommandListToContain($result['commands'], 'mkdir -p /root/.ssh');
expectGitlabPrivateKeyMaterializationCommandsSkipLogging($result['commands']);
});
it('generates ls-remote commands for GitLab source without private key', function () {
$deploymentUuid = 'test-deployment-uuid';
$gitlabSource = Mockery::mock(GitlabApp::class)->makePartial();
$gitlabSource->shouldReceive('getMorphClass')->andReturn(\App\Models\GitlabApp::class);
$gitlabSource->shouldReceive('getMorphClass')->andReturn(GitlabApp::class);
$gitlabSource->shouldReceive('getAttribute')->with('html_url')->andReturn('https://gitlab.com');
$gitlabSource->shouldReceive('getAttribute')->with('privateKey')->andReturn(null);
$gitlabSource->shouldReceive('getAttribute')->with('private_key_id')->andReturn(null);
@@ -61,17 +98,18 @@ it('generates ls-remote commands for GitLab source without private key', functio
expect($result)->toBeArray();
expect($result)->toHaveKey('commands');
expect($result['commands'])->toContain('git ls-remote');
expect($result['commands'])->toContain('https://gitlab.com/user/repo.git');
expectGitlabCommandListToContain($result['commands'], 'git ls-remote');
expectGitlabCommandListToContain($result['commands'], 'https://gitlab.com/user/repo.git');
// Should NOT contain SSH key setup
expect($result['commands'])->not->toContain('id_rsa');
expectGitlabCommandListNotToContain($result['commands'], 'id_rsa');
});
it('does not return null for GitLab source type', function () {
$deploymentUuid = 'test-deployment-uuid';
$gitlabSource = Mockery::mock(GitlabApp::class)->makePartial();
$gitlabSource->shouldReceive('getMorphClass')->andReturn(\App\Models\GitlabApp::class);
$gitlabSource->shouldReceive('getMorphClass')->andReturn(GitlabApp::class);
$gitlabSource->shouldReceive('getAttribute')->with('html_url')->andReturn('https://gitlab.com');
$gitlabSource->shouldReceive('getAttribute')->with('privateKey')->andReturn(null);
$gitlabSource->shouldReceive('getAttribute')->with('private_key_id')->andReturn(null);
@@ -25,12 +25,12 @@ it('ensures GlobalSearch clears search query when starting resource creation', f
->toContain('$this->searchQuery = \'\'');
});
it('ensures GlobalSearch uses Livewire redirect method', function () {
it('ensures GlobalSearch uses redirect route helper', function () {
$globalSearchFile = file_get_contents(__DIR__.'/../../app/Livewire/GlobalSearch.php');
// Check that completeResourceCreation uses $this->redirect()
// Check that completeResourceCreation uses the shared redirect route helper
expect($globalSearchFile)
->toContain('$this->redirect(route(\'project.resource.create\'');
->toContain('redirectRoute($this, \'project.resource.create\'');
});
it('ensures docker-image item has quickcommand with new image', function () {
@@ -42,3 +42,103 @@ it('ensures docker-image item has quickcommand with new image', function () {
->toContain("'quickcommand' => '(type: new image)'")
->toContain("'type' => 'docker-image'");
});
it('uses neutral hover styling for GlobalSearch quick action rows', function () {
$bladeFile = file_get_contents(__DIR__.'/../../resources/views/livewire/global-search.blade.php');
preg_match_all('/<button[^>]+(?:wire:click="navigateToResource|@click="\\$wire\\.navigateToResource)[^>]+>/s', $bladeFile, $quickActionButtons);
expect($quickActionButtons[0])->not->toBeEmpty();
foreach ($quickActionButtons[0] as $quickActionButton) {
expect($quickActionButton)
->toContain('hover:bg-neutral-100 dark:hover:bg-coolgray-200')
->toContain('focus:bg-neutral-100 dark:focus:bg-coolgray-200')
->toContain('focus-visible:ring-coollabs dark:focus-visible:ring-warning')
->not->toContain('hover:bg-warning-50')
->not->toContain('hover:border-warning-500');
}
});
it('uses product logos for GlobalSearch database quick actions', function () {
$globalSearchFile = file_get_contents(__DIR__.'/../../app/Livewire/GlobalSearch.php');
$bladeFile = file_get_contents(__DIR__.'/../../resources/views/livewire/global-search.blade.php');
expect($bladeFile)
->toContain('asset($item[\'logo\'])')
->toContain(":src=\"'/' + item.logo\"");
foreach ([
'postgresql' => 'svgs/postgresql.svg',
'mysql' => 'svgs/mysql.svg',
'mariadb' => 'svgs/mariadb.svg',
'redis' => 'svgs/redis.svg',
'keydb' => 'svgs/keydb.svg',
'dragonfly' => 'svgs/dragonfly.svg',
'mongodb' => 'svgs/mongodb.svg',
'clickhouse' => 'svgs/clickhouse-icon.svg',
] as $type => $logo) {
expect($globalSearchFile)
->toContain("'type' => '{$type}'")
->toContain("'logo' => '{$logo}'");
expect(file_exists(__DIR__.'/../../public/'.$logo))->toBeTrue();
}
});
it('uses neutral hover styling for GlobalSearch existing resource rows', function () {
$bladeFile = file_get_contents(__DIR__.'/../../resources/views/livewire/global-search.blade.php');
preg_match_all('/<a[^>]+(?:href="{{ \\$result\\[\'link\'\\]|:href="result\\.link)[^>]+>/s', $bladeFile, $existingResourceLinks);
expect($existingResourceLinks[0])->not->toBeEmpty();
foreach ($existingResourceLinks[0] as $existingResourceLink) {
expect($existingResourceLink)
->toContain('hover:bg-neutral-100 dark:hover:bg-coolgray-200')
->toContain('focus:bg-neutral-100 dark:focus:bg-coolgray-200')
->toContain('focus-visible:ring-coollabs dark:focus-visible:ring-warning')
->not->toContain('hover:bg-neutral-50')
->not->toContain('focus:bg-warning')
->not->toContain('hover:border-coollabs')
->not->toContain('focus:border-warning');
}
});
it('uses visible cropped SVG marks for wide database logos', function () {
$keydbLogo = file_get_contents(__DIR__.'/../../public/svgs/keydb.svg');
$dragonflyLogo = file_get_contents(__DIR__.'/../../public/svgs/dragonfly.svg');
$clickhouseLogo = file_get_contents(__DIR__.'/../../public/svgs/clickhouse-icon.svg');
expect($keydbLogo)
->toContain('viewBox="0 0 160 182"')
->toContain('svg{color:#d4d4d4}')
->not->toContain('prefers-color-scheme');
expect($dragonflyLogo)
->toContain('viewBox="0 0 88 88"')
->toContain('svg{color:#d4d4d4}')
->not->toContain('prefers-color-scheme');
expect($clickhouseLogo)
->toContain('viewBox="1.70837 1.875 22.25025 22.2493"')
->toContain('svg{color:#d4d4d4}')
->toContain('x="20.7087"')
->toContain('width="2.24992"')
->not->toContain('viewBox="0 0 100 43"')
->not->toContain('width="215"')
->not->toContain('height="90"');
});
it('uses cropped image assets instead of inline wide logos for GlobalSearch database icons', function () {
$globalSearchFile = file_get_contents(__DIR__.'/../../app/Livewire/GlobalSearch.php');
$bladeFile = file_get_contents(__DIR__.'/../../resources/views/livewire/global-search.blade.php');
expect($bladeFile)
->toContain('class="w-8 h-8 object-contain"')
->toContain('class="w-8 h-8 object-contain"')
->not->toContain('$item[\'logo_html\']')
->not->toContain('x-html="item.logo_html"');
expect($globalSearchFile)->not->toContain("'logo_html' =>");
});
+13
View File
@@ -0,0 +1,13 @@
<?php
test('expanded navbar theme item cycles themes without a right side selector', function () {
$navbar = file_get_contents(__DIR__.'/../../resources/views/components/navbar.blade.php');
expect(substr_count($navbar, '@click.stop="cycleTheme()"'))->toBe(2)
->and($navbar)->not->toContain('aria-label="Theme switcher"')
->and($navbar)->not->toContain('ml-auto flex items-center gap-0.5')
->and($navbar)->not->toContain('@click.stop="setTheme(\'light\')"')
->and($navbar)->not->toContain('@click.stop="setTheme(\'system\')"')
->and($navbar)->not->toContain('@click.stop="setTheme(\'dark\')"')
->and($navbar)->toContain('<span class="text-left menu-item-label">Theme</span>');
});
+193
View File
@@ -0,0 +1,193 @@
<?php
use App\Models\User;
use App\Policies\ApiTokenPolicy;
use Laravel\Sanctum\PersonalAccessToken;
it('allows any user to view any api tokens', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new ApiTokenPolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows any user to create api tokens', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new ApiTokenPolicy;
expect($policy->create($user))->toBeTrue();
});
it('allows any user to manage api tokens', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new ApiTokenPolicy;
expect($policy->manage($user))->toBeTrue();
});
it('allows owner to view their own api token', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->id = 1;
$token = Mockery::mock(PersonalAccessToken::class)->makePartial();
$token->tokenable_id = 1;
$token->tokenable_type = User::class;
$policy = new ApiTokenPolicy;
expect($policy->view($user, $token))->toBeTrue();
});
it('denies non-owner from viewing api token', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->id = 2;
$token = Mockery::mock(PersonalAccessToken::class)->makePartial();
$token->tokenable_id = 1;
$token->tokenable_type = User::class;
$policy = new ApiTokenPolicy;
expect($policy->view($user, $token))->toBeFalse();
});
it('allows owner to update their own api token', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->id = 1;
$token = Mockery::mock(PersonalAccessToken::class)->makePartial();
$token->tokenable_id = 1;
$token->tokenable_type = User::class;
$policy = new ApiTokenPolicy;
expect($policy->update($user, $token))->toBeTrue();
});
it('denies non-owner from updating api token', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->id = 2;
$token = Mockery::mock(PersonalAccessToken::class)->makePartial();
$token->tokenable_id = 1;
$token->tokenable_type = User::class;
$policy = new ApiTokenPolicy;
expect($policy->update($user, $token))->toBeFalse();
});
it('allows owner to delete their own api token', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->id = 1;
$token = Mockery::mock(PersonalAccessToken::class)->makePartial();
$token->tokenable_id = 1;
$token->tokenable_type = User::class;
$policy = new ApiTokenPolicy;
expect($policy->delete($user, $token))->toBeTrue();
});
it('denies non-owner from deleting api token', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->id = 2;
$token = Mockery::mock(PersonalAccessToken::class)->makePartial();
$token->tokenable_id = 1;
$token->tokenable_type = User::class;
$policy = new ApiTokenPolicy;
expect($policy->delete($user, $token))->toBeFalse();
});
it('allows admin to use root permissions', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ApiTokenPolicy;
expect($policy->useRootPermissions($user))->toBeTrue();
});
it('allows owner to use root permissions', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$user->shouldReceive('isOwner')->andReturn(true);
$policy = new ApiTokenPolicy;
expect($policy->useRootPermissions($user))->toBeTrue();
});
it('denies member from using root permissions', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$user->shouldReceive('isOwner')->andReturn(false);
$policy = new ApiTokenPolicy;
expect($policy->useRootPermissions($user))->toBeFalse();
});
it('allows admin to use write permissions', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ApiTokenPolicy;
expect($policy->useWritePermissions($user))->toBeTrue();
});
it('denies member from using write permissions', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$user->shouldReceive('isOwner')->andReturn(false);
$policy = new ApiTokenPolicy;
expect($policy->useWritePermissions($user))->toBeFalse();
});
it('allows admin to use deploy permissions', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ApiTokenPolicy;
expect($policy->useDeployPermissions($user))->toBeTrue();
});
it('allows owner to use deploy permissions', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$user->shouldReceive('isOwner')->andReturn(true);
$policy = new ApiTokenPolicy;
expect($policy->useDeployPermissions($user))->toBeTrue();
});
it('denies member from using deploy permissions', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$user->shouldReceive('isOwner')->andReturn(false);
$policy = new ApiTokenPolicy;
expect($policy->useDeployPermissions($user))->toBeFalse();
});
it('allows admin to use sensitive permissions', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ApiTokenPolicy;
expect($policy->useSensitivePermissions($user))->toBeTrue();
});
it('allows owner to use sensitive permissions', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$user->shouldReceive('isOwner')->andReturn(true);
$policy = new ApiTokenPolicy;
expect($policy->useSensitivePermissions($user))->toBeTrue();
});
it('denies member from using sensitive permissions', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$user->shouldReceive('isOwner')->andReturn(false);
$policy = new ApiTokenPolicy;
expect($policy->useSensitivePermissions($user))->toBeFalse();
});
@@ -0,0 +1,237 @@
<?php
use App\Models\Application;
use App\Models\User;
use App\Policies\ApplicationPolicy;
it('allows any user to view any applications', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new ApplicationPolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows team member to view their own team application', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ApplicationPolicy;
expect($policy->view($user, $application))->toBeTrue();
});
it('denies non-member to view another team application', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 2]);
$policy = new ApplicationPolicy;
expect($policy->view($user, $application))->toBeFalse();
});
it('denies view when application has no team', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn(null);
$policy = new ApplicationPolicy;
expect($policy->view($user, $application))->toBeFalse();
});
it('allows admin to create an application', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ApplicationPolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies member to create an application', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ApplicationPolicy;
expect($policy->create($user))->toBeFalse();
});
it('allows team admin to update their own team application', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ApplicationPolicy;
expect($policy->update($user, $application)->allowed())->toBeTrue();
});
it('denies team member to update their own team application', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ApplicationPolicy;
expect($policy->update($user, $application)->allowed())->toBeFalse();
});
it('denies update when application has no team', function () {
$user = Mockery::mock(User::class)->makePartial();
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn(null);
$policy = new ApplicationPolicy;
expect($policy->update($user, $application)->allowed())->toBeFalse();
});
it('allows team admin to delete their own team application', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ApplicationPolicy;
expect($policy->delete($user, $application))->toBeTrue();
});
it('denies team member to delete their own team application', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ApplicationPolicy;
expect($policy->delete($user, $application))->toBeFalse();
});
it('denies delete when application has no team', function () {
$user = Mockery::mock(User::class)->makePartial();
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn(null);
$policy = new ApplicationPolicy;
expect($policy->delete($user, $application))->toBeFalse();
});
it('allows team admin to deploy their own team application', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ApplicationPolicy;
expect($policy->deploy($user, $application))->toBeTrue();
});
it('denies team member to deploy their own team application', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ApplicationPolicy;
expect($policy->deploy($user, $application))->toBeFalse();
});
it('allows team admin to manage deployments', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ApplicationPolicy;
expect($policy->manageDeployments($user, $application))->toBeTrue();
});
it('denies team member to manage deployments', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ApplicationPolicy;
expect($policy->manageDeployments($user, $application))->toBeFalse();
});
it('allows team admin to manage environment variables', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ApplicationPolicy;
expect($policy->manageEnvironment($user, $application))->toBeTrue();
});
it('denies team member to manage environment variables', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ApplicationPolicy;
expect($policy->manageEnvironment($user, $application))->toBeFalse();
});
it('allows admin to cleanup deployment queue', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ApplicationPolicy;
expect($policy->cleanupDeploymentQueue($user))->toBeTrue();
});
it('denies member to cleanup deployment queue', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ApplicationPolicy;
expect($policy->cleanupDeploymentQueue($user))->toBeFalse();
});
it('denies restore for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$application = Mockery::mock(Application::class)->makePartial();
$policy = new ApplicationPolicy;
expect($policy->restore($user, $application))->toBeFalse();
});
it('denies force delete for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$application = Mockery::mock(Application::class)->makePartial();
$policy = new ApplicationPolicy;
expect($policy->forceDelete($user, $application))->toBeFalse();
});
@@ -0,0 +1,239 @@
<?php
use App\Models\Application;
use App\Models\ApplicationPreview;
use App\Models\User;
use App\Policies\ApplicationPreviewPolicy;
it('allows any user to view any application previews', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new ApplicationPreviewPolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows team member to view application preview', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'member']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationPreviewPolicy;
expect($policy->view($user, $preview))->toBeTrue();
});
it('denies non-team member from viewing application preview', function () {
$teams = collect([
(object) ['id' => 2, 'pivot' => (object) ['role' => 'member']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationPreviewPolicy;
expect($policy->view($user, $preview))->toBeFalse();
});
it('denies viewing application preview with null application', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'admin']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn(null);
$policy = new ApplicationPreviewPolicy;
expect($policy->view($user, $preview))->toBeFalse();
});
it('allows admin user to create application preview', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ApplicationPreviewPolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies non-admin user from creating application preview', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ApplicationPreviewPolicy;
expect($policy->create($user))->toBeFalse();
});
it('allows team admin to update application preview', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationPreviewPolicy;
expect($policy->update($user, $preview)->allowed())->toBeTrue();
});
it('denies team member from updating application preview', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationPreviewPolicy;
expect($policy->update($user, $preview)->allowed())->toBeFalse();
});
it('denies updating application preview with null application', function () {
$user = Mockery::mock(User::class)->makePartial();
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn(null);
$policy = new ApplicationPreviewPolicy;
$response = $policy->update($user, $preview);
expect($response->allowed())->toBeFalse();
});
it('allows team admin to delete application preview', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationPreviewPolicy;
expect($policy->delete($user, $preview))->toBeTrue();
});
it('denies team member from deleting application preview', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationPreviewPolicy;
expect($policy->delete($user, $preview))->toBeFalse();
});
it('denies deleting application preview with null application', function () {
$user = Mockery::mock(User::class)->makePartial();
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn(null);
$policy = new ApplicationPreviewPolicy;
expect($policy->delete($user, $preview))->toBeFalse();
});
it('allows team admin to deploy application preview', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationPreviewPolicy;
expect($policy->deploy($user, $preview))->toBeTrue();
});
it('denies team member from deploying application preview', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationPreviewPolicy;
expect($policy->deploy($user, $preview))->toBeFalse();
});
it('allows team admin to manage preview deployments', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationPreviewPolicy;
expect($policy->manageDeployments($user, $preview))->toBeTrue();
});
it('denies team member from managing preview deployments', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$preview->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationPreviewPolicy;
expect($policy->manageDeployments($user, $preview))->toBeFalse();
});
it('denies restoring application preview', function () {
$user = Mockery::mock(User::class)->makePartial();
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$policy = new ApplicationPreviewPolicy;
expect($policy->restore($user, $preview))->toBeFalse();
});
it('denies force deleting application preview', function () {
$user = Mockery::mock(User::class)->makePartial();
$preview = Mockery::mock(ApplicationPreview::class)->makePartial();
$policy = new ApplicationPreviewPolicy;
expect($policy->forceDelete($user, $preview))->toBeFalse();
});
@@ -0,0 +1,178 @@
<?php
use App\Models\Application;
use App\Models\ApplicationSetting;
use App\Models\User;
use App\Policies\ApplicationSettingPolicy;
it('allows any user to view any application settings', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new ApplicationSettingPolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows team member to view application setting', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'member']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$setting = Mockery::mock(ApplicationSetting::class)->makePartial();
$setting->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationSettingPolicy;
expect($policy->view($user, $setting))->toBeTrue();
});
it('denies non-team member from viewing application setting', function () {
$teams = collect([
(object) ['id' => 2, 'pivot' => (object) ['role' => 'member']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$setting = Mockery::mock(ApplicationSetting::class)->makePartial();
$setting->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationSettingPolicy;
expect($policy->view($user, $setting))->toBeFalse();
});
it('denies viewing application setting with null application', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'admin']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$setting = Mockery::mock(ApplicationSetting::class)->makePartial();
$setting->shouldReceive('getAttribute')->with('application')->andReturn(null);
$policy = new ApplicationSettingPolicy;
expect($policy->view($user, $setting))->toBeFalse();
});
it('allows admin user to create application setting', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ApplicationSettingPolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies non-admin user from creating application setting', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ApplicationSettingPolicy;
expect($policy->create($user))->toBeFalse();
});
it('allows team admin to update application setting', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$setting = Mockery::mock(ApplicationSetting::class)->makePartial();
$setting->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationSettingPolicy;
expect($policy->update($user, $setting))->toBeTrue();
});
it('denies team member from updating application setting', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$setting = Mockery::mock(ApplicationSetting::class)->makePartial();
$setting->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationSettingPolicy;
expect($policy->update($user, $setting))->toBeFalse();
});
it('denies updating application setting with null application', function () {
$user = Mockery::mock(User::class)->makePartial();
$setting = Mockery::mock(ApplicationSetting::class)->makePartial();
$setting->shouldReceive('getAttribute')->with('application')->andReturn(null);
$policy = new ApplicationSettingPolicy;
expect($policy->update($user, $setting))->toBeFalse();
});
it('allows team admin to delete application setting', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$setting = Mockery::mock(ApplicationSetting::class)->makePartial();
$setting->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationSettingPolicy;
expect($policy->delete($user, $setting))->toBeTrue();
});
it('denies team member from deleting application setting', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$team = (object) ['id' => 1];
$application = Mockery::mock(Application::class)->makePartial();
$application->shouldReceive('team')->andReturn($team);
$setting = Mockery::mock(ApplicationSetting::class)->makePartial();
$setting->shouldReceive('getAttribute')->with('application')->andReturn($application);
$policy = new ApplicationSettingPolicy;
expect($policy->delete($user, $setting))->toBeFalse();
});
it('denies deleting application setting with null application', function () {
$user = Mockery::mock(User::class)->makePartial();
$setting = Mockery::mock(ApplicationSetting::class)->makePartial();
$setting->shouldReceive('getAttribute')->with('application')->andReturn(null);
$policy = new ApplicationSettingPolicy;
expect($policy->delete($user, $setting))->toBeFalse();
});
it('denies restoring application setting', function () {
$user = Mockery::mock(User::class)->makePartial();
$setting = Mockery::mock(ApplicationSetting::class)->makePartial();
$policy = new ApplicationSettingPolicy;
expect($policy->restore($user, $setting))->toBeFalse();
});
it('denies force deleting application setting', function () {
$user = Mockery::mock(User::class)->makePartial();
$setting = Mockery::mock(ApplicationSetting::class)->makePartial();
$policy = new ApplicationSettingPolicy;
expect($policy->forceDelete($user, $setting))->toBeFalse();
});
+221
View File
@@ -0,0 +1,221 @@
<?php
use App\Models\StandalonePostgresql;
use App\Models\User;
use App\Policies\DatabasePolicy;
it('allows any user to view any databases', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new DatabasePolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows team member to view their own team database', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new DatabasePolicy;
expect($policy->view($user, $database))->toBeTrue();
});
it('denies non-member to view another team database', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 2]);
$policy = new DatabasePolicy;
expect($policy->view($user, $database))->toBeFalse();
});
it('denies view when database has no team', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn(null);
$policy = new DatabasePolicy;
expect($policy->view($user, $database))->toBeFalse();
});
it('allows admin to create a database', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new DatabasePolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies member to create a database', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new DatabasePolicy;
expect($policy->create($user))->toBeFalse();
});
it('allows team admin to update their own team database', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new DatabasePolicy;
expect($policy->update($user, $database)->allowed())->toBeTrue();
});
it('denies team member to update their own team database', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new DatabasePolicy;
expect($policy->update($user, $database)->allowed())->toBeFalse();
});
it('denies update when database has no team', function () {
$user = Mockery::mock(User::class)->makePartial();
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn(null);
$policy = new DatabasePolicy;
expect($policy->update($user, $database)->allowed())->toBeFalse();
});
it('allows team admin to delete their own team database', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new DatabasePolicy;
expect($policy->delete($user, $database))->toBeTrue();
});
it('denies team member to delete their own team database', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new DatabasePolicy;
expect($policy->delete($user, $database))->toBeFalse();
});
it('denies delete when database has no team', function () {
$user = Mockery::mock(User::class)->makePartial();
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn(null);
$policy = new DatabasePolicy;
expect($policy->delete($user, $database))->toBeFalse();
});
it('allows team admin to manage their own team database', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new DatabasePolicy;
expect($policy->manage($user, $database))->toBeTrue();
});
it('denies team member to manage their own team database', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new DatabasePolicy;
expect($policy->manage($user, $database))->toBeFalse();
});
it('allows team admin to manage backups', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new DatabasePolicy;
expect($policy->manageBackups($user, $database))->toBeTrue();
});
it('denies team member to manage backups', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new DatabasePolicy;
expect($policy->manageBackups($user, $database))->toBeFalse();
});
it('allows team admin to manage database environment variables', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new DatabasePolicy;
expect($policy->manageEnvironment($user, $database))->toBeTrue();
});
it('denies team member to manage database environment variables', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$database->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new DatabasePolicy;
expect($policy->manageEnvironment($user, $database))->toBeFalse();
});
it('denies restore for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$policy = new DatabasePolicy;
expect($policy->restore($user, $database))->toBeFalse();
});
it('denies force delete for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$database = Mockery::mock(StandalonePostgresql::class)->makePartial();
$policy = new DatabasePolicy;
expect($policy->forceDelete($user, $database))->toBeFalse();
});
@@ -0,0 +1,155 @@
<?php
use App\Models\Environment;
use App\Models\User;
use App\Policies\EnvironmentPolicy;
it('allows any user to view any environments', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new EnvironmentPolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows team member to view their own team environment', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$environment = Mockery::mock(Environment::class)->makePartial();
$environment->shouldReceive('getAttribute')->with('project')->andReturn((object) ['team_id' => 1]);
$policy = new EnvironmentPolicy;
expect($policy->view($user, $environment))->toBeTrue();
});
it('denies non-member to view another team environment', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$environment = Mockery::mock(Environment::class)->makePartial();
$environment->shouldReceive('getAttribute')->with('project')->andReturn((object) ['team_id' => 2]);
$policy = new EnvironmentPolicy;
expect($policy->view($user, $environment))->toBeFalse();
});
it('denies view when environment has no project', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$environment = Mockery::mock(Environment::class)->makePartial();
$environment->shouldReceive('getAttribute')->with('project')->andReturn(null);
$policy = new EnvironmentPolicy;
expect($policy->view($user, $environment))->toBeFalse();
});
it('allows admin to create an environment', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new EnvironmentPolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies member to create an environment', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new EnvironmentPolicy;
expect($policy->create($user))->toBeFalse();
});
it('allows team admin to update their own team environment', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$environment = Mockery::mock(Environment::class)->makePartial();
$environment->shouldReceive('getAttribute')->with('project')->andReturn((object) ['team_id' => 1]);
$policy = new EnvironmentPolicy;
expect($policy->update($user, $environment))->toBeTrue();
});
it('denies team member to update their own team environment', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$environment = Mockery::mock(Environment::class)->makePartial();
$environment->shouldReceive('getAttribute')->with('project')->andReturn((object) ['team_id' => 1]);
$policy = new EnvironmentPolicy;
expect($policy->update($user, $environment))->toBeFalse();
});
it('denies update when environment has no project', function () {
$user = Mockery::mock(User::class)->makePartial();
$environment = Mockery::mock(Environment::class)->makePartial();
$environment->shouldReceive('getAttribute')->with('project')->andReturn(null);
$policy = new EnvironmentPolicy;
expect($policy->update($user, $environment))->toBeFalse();
});
it('allows team admin to delete their own team environment', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$environment = Mockery::mock(Environment::class)->makePartial();
$environment->shouldReceive('getAttribute')->with('project')->andReturn((object) ['team_id' => 1]);
$policy = new EnvironmentPolicy;
expect($policy->delete($user, $environment))->toBeTrue();
});
it('denies team member to delete their own team environment', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$environment = Mockery::mock(Environment::class)->makePartial();
$environment->shouldReceive('getAttribute')->with('project')->andReturn((object) ['team_id' => 1]);
$policy = new EnvironmentPolicy;
expect($policy->delete($user, $environment))->toBeFalse();
});
it('denies delete when environment has no project', function () {
$user = Mockery::mock(User::class)->makePartial();
$environment = Mockery::mock(Environment::class)->makePartial();
$environment->shouldReceive('getAttribute')->with('project')->andReturn(null);
$policy = new EnvironmentPolicy;
expect($policy->delete($user, $environment))->toBeFalse();
});
it('denies restore for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$environment = Mockery::mock(Environment::class)->makePartial();
$policy = new EnvironmentPolicy;
expect($policy->restore($user, $environment))->toBeFalse();
});
it('denies force delete for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$environment = Mockery::mock(Environment::class)->makePartial();
$policy = new EnvironmentPolicy;
expect($policy->forceDelete($user, $environment))->toBeFalse();
});
@@ -0,0 +1,199 @@
<?php
use App\Models\Application;
use App\Models\EnvironmentVariable;
use App\Models\User;
use App\Policies\EnvironmentVariablePolicy;
use Illuminate\Support\Collection;
it('allows any user to view any environment variables', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new EnvironmentVariablePolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows team member to view environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->teams = new Collection([(object) ['id' => 1]]);
$resource = Mockery::mock(Application::class)->makePartial();
$resource->shouldReceive('team')->andReturn((object) ['id' => 1]);
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn($resource);
$policy = new EnvironmentVariablePolicy;
expect($policy->view($user, $envVar))->toBeTrue();
});
it('denies non-team member from viewing environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->teams = new Collection([(object) ['id' => 2]]);
$resource = Mockery::mock(Application::class)->makePartial();
$resource->shouldReceive('team')->andReturn((object) ['id' => 1]);
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn($resource);
$policy = new EnvironmentVariablePolicy;
expect($policy->view($user, $envVar))->toBeFalse();
});
it('denies view when resourceable is null', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->teams = new Collection([(object) ['id' => 1]]);
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn(null);
$policy = new EnvironmentVariablePolicy;
expect($policy->view($user, $envVar))->toBeFalse();
});
it('allows admin to create environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new EnvironmentVariablePolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies member from creating environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new EnvironmentVariablePolicy;
expect($policy->create($user))->toBeFalse();
});
it('allows team admin to update environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$resource = Mockery::mock(Application::class)->makePartial();
$resource->shouldReceive('team')->andReturn((object) ['id' => 1]);
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn($resource);
$policy = new EnvironmentVariablePolicy;
expect($policy->update($user, $envVar))->toBeTrue();
});
it('denies non-admin from updating environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$resource = Mockery::mock(Application::class)->makePartial();
$resource->shouldReceive('team')->andReturn((object) ['id' => 1]);
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn($resource);
$policy = new EnvironmentVariablePolicy;
expect($policy->update($user, $envVar))->toBeFalse();
});
it('denies update when resourceable is null', function () {
$user = Mockery::mock(User::class)->makePartial();
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn(null);
$policy = new EnvironmentVariablePolicy;
expect($policy->update($user, $envVar))->toBeFalse();
});
it('allows team admin to delete environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$resource = Mockery::mock(Application::class)->makePartial();
$resource->shouldReceive('team')->andReturn((object) ['id' => 1]);
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn($resource);
$policy = new EnvironmentVariablePolicy;
expect($policy->delete($user, $envVar))->toBeTrue();
});
it('denies non-admin from deleting environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$resource = Mockery::mock(Application::class)->makePartial();
$resource->shouldReceive('team')->andReturn((object) ['id' => 1]);
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn($resource);
$policy = new EnvironmentVariablePolicy;
expect($policy->delete($user, $envVar))->toBeFalse();
});
it('denies delete when resourceable is null', function () {
$user = Mockery::mock(User::class)->makePartial();
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn(null);
$policy = new EnvironmentVariablePolicy;
expect($policy->delete($user, $envVar))->toBeFalse();
});
it('denies restore for environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$policy = new EnvironmentVariablePolicy;
expect($policy->restore($user, $envVar))->toBeFalse();
});
it('denies force delete for environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$policy = new EnvironmentVariablePolicy;
expect($policy->forceDelete($user, $envVar))->toBeFalse();
});
it('allows team admin to manage environment', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$resource = Mockery::mock(Application::class)->makePartial();
$resource->shouldReceive('team')->andReturn((object) ['id' => 1]);
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn($resource);
$policy = new EnvironmentVariablePolicy;
expect($policy->manageEnvironment($user, $envVar))->toBeTrue();
});
it('denies non-admin from managing environment', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$resource = Mockery::mock(Application::class)->makePartial();
$resource->shouldReceive('team')->andReturn((object) ['id' => 1]);
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn($resource);
$policy = new EnvironmentVariablePolicy;
expect($policy->manageEnvironment($user, $envVar))->toBeFalse();
});
it('denies manage environment when resourceable is null', function () {
$user = Mockery::mock(User::class)->makePartial();
$envVar = Mockery::mock(EnvironmentVariable::class)->makePartial();
$envVar->shouldReceive('getAttribute')->with('resourceable')->andReturn(null);
$policy = new EnvironmentVariablePolicy;
expect($policy->manageEnvironment($user, $envVar))->toBeFalse();
});
+23 -78
View File
@@ -1,5 +1,6 @@
<?php
use App\Models\GithubApp;
use App\Models\User;
use App\Policies\GithubAppPolicy;
@@ -13,12 +14,7 @@ it('allows any user to view any github apps', function () {
it('allows any user to view system-wide github app', function () {
$user = Mockery::mock(User::class)->makePartial();
$model = new class
{
public $team_id = 1;
public $is_system_wide = true;
};
$model = mockGithubApp(teamId: 1, isSystemWide: true);
$policy = new GithubAppPolicy;
expect($policy->view($user, $model))->toBeTrue();
@@ -32,12 +28,7 @@ it('allows team member to view non-system-wide github app', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$model = new class
{
public $team_id = 1;
public $is_system_wide = false;
};
$model = mockGithubApp(teamId: 1, isSystemWide: false);
$policy = new GithubAppPolicy;
expect($policy->view($user, $model))->toBeTrue();
@@ -51,12 +42,7 @@ it('denies non-team member to view non-system-wide github app', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$model = new class
{
public $team_id = 1;
public $is_system_wide = false;
};
$model = mockGithubApp(teamId: 1, isSystemWide: false);
$policy = new GithubAppPolicy;
expect($policy->view($user, $model))->toBeFalse();
@@ -82,12 +68,7 @@ it('allows user with system access to update system-wide github app', function (
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('canAccessSystemResources')->andReturn(true);
$model = new class
{
public $team_id = 1;
public $is_system_wide = true;
};
$model = mockGithubApp(teamId: 1, isSystemWide: true);
$policy = new GithubAppPolicy;
expect($policy->update($user, $model))->toBeTrue();
@@ -97,12 +78,7 @@ it('denies user without system access to update system-wide github app', functio
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('canAccessSystemResources')->andReturn(false);
$model = new class
{
public $team_id = 1;
public $is_system_wide = true;
};
$model = mockGithubApp(teamId: 1, isSystemWide: true);
$policy = new GithubAppPolicy;
expect($policy->update($user, $model))->toBeFalse();
@@ -112,12 +88,7 @@ it('allows team admin to update non-system-wide github app', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$model = new class
{
public $team_id = 1;
public $is_system_wide = false;
};
$model = mockGithubApp(teamId: 1, isSystemWide: false);
$policy = new GithubAppPolicy;
expect($policy->update($user, $model))->toBeTrue();
@@ -127,12 +98,7 @@ it('denies team member to update non-system-wide github app', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$model = new class
{
public $team_id = 1;
public $is_system_wide = false;
};
$model = mockGithubApp(teamId: 1, isSystemWide: false);
$policy = new GithubAppPolicy;
expect($policy->update($user, $model))->toBeFalse();
@@ -142,12 +108,7 @@ it('allows user with system access to delete system-wide github app', function (
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('canAccessSystemResources')->andReturn(true);
$model = new class
{
public $team_id = 1;
public $is_system_wide = true;
};
$model = mockGithubApp(teamId: 1, isSystemWide: true);
$policy = new GithubAppPolicy;
expect($policy->delete($user, $model))->toBeTrue();
@@ -157,12 +118,7 @@ it('denies user without system access to delete system-wide github app', functio
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('canAccessSystemResources')->andReturn(false);
$model = new class
{
public $team_id = 1;
public $is_system_wide = true;
};
$model = mockGithubApp(teamId: 1, isSystemWide: true);
$policy = new GithubAppPolicy;
expect($policy->delete($user, $model))->toBeFalse();
@@ -172,12 +128,7 @@ it('allows team admin to delete non-system-wide github app', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$model = new class
{
public $team_id = 1;
public $is_system_wide = false;
};
$model = mockGithubApp(teamId: 1, isSystemWide: false);
$policy = new GithubAppPolicy;
expect($policy->delete($user, $model))->toBeTrue();
@@ -187,12 +138,7 @@ it('denies team member to delete non-system-wide github app', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$model = new class
{
public $team_id = 1;
public $is_system_wide = false;
};
$model = mockGithubApp(teamId: 1, isSystemWide: false);
$policy = new GithubAppPolicy;
expect($policy->delete($user, $model))->toBeFalse();
@@ -201,12 +147,7 @@ it('denies team member to delete non-system-wide github app', function () {
it('denies restore of github app', function () {
$user = Mockery::mock(User::class)->makePartial();
$model = new class
{
public $team_id = 1;
public $is_system_wide = false;
};
$model = mockGithubApp(teamId: 1, isSystemWide: false);
$policy = new GithubAppPolicy;
expect($policy->restore($user, $model))->toBeFalse();
@@ -215,13 +156,17 @@ it('denies restore of github app', function () {
it('denies force delete of github app', function () {
$user = Mockery::mock(User::class)->makePartial();
$model = new class
{
public $team_id = 1;
public $is_system_wide = false;
};
$model = mockGithubApp(teamId: 1, isSystemWide: false);
$policy = new GithubAppPolicy;
expect($policy->forceDelete($user, $model))->toBeFalse();
});
function mockGithubApp(int $teamId, bool $isSystemWide): GithubApp
{
$githubApp = Mockery::mock(GithubApp::class)->makePartial();
$githubApp->team_id = $teamId;
$githubApp->is_system_wide = $isSystemWide;
return $githubApp;
}
@@ -0,0 +1,175 @@
<?php
use App\Models\User;
use App\Policies\NotificationPolicy;
use Illuminate\Database\Eloquent\Model;
it('allows team member to view notification settings', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'member']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn((object) ['id' => 1]);
$policy = new NotificationPolicy;
expect($policy->view($user, $notification))->toBeTrue();
});
it('denies non-team member from viewing notification settings', function () {
$teams = collect([
(object) ['id' => 2, 'pivot' => (object) ['role' => 'member']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn((object) ['id' => 1]);
$policy = new NotificationPolicy;
expect($policy->view($user, $notification))->toBeFalse();
});
it('denies viewing notification settings with no team', function () {
$user = Mockery::mock(User::class)->makePartial();
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn(null);
$policy = new NotificationPolicy;
expect($policy->view($user, $notification))->toBeFalse();
});
it('allows team admin to update notification settings', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn((object) ['id' => 1]);
$policy = new NotificationPolicy;
expect($policy->update($user, $notification))->toBeTrue();
});
it('denies team member from updating notification settings', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn((object) ['id' => 1]);
$policy = new NotificationPolicy;
expect($policy->update($user, $notification))->toBeFalse();
});
it('denies updating notification settings with no team', function () {
$user = Mockery::mock(User::class)->makePartial();
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn(null);
$policy = new NotificationPolicy;
expect($policy->update($user, $notification))->toBeFalse();
});
it('allows team admin to manage notification settings', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn((object) ['id' => 1]);
$policy = new NotificationPolicy;
expect($policy->manage($user, $notification))->toBeTrue();
});
it('denies team member from managing notification settings', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn((object) ['id' => 1]);
$policy = new NotificationPolicy;
expect($policy->manage($user, $notification))->toBeFalse();
});
it('denies managing notification settings with no team', function () {
$user = Mockery::mock(User::class)->makePartial();
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn(null);
$policy = new NotificationPolicy;
expect($policy->manage($user, $notification))->toBeFalse();
});
it('allows team admin to send test notification', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn((object) ['id' => 1]);
$policy = new NotificationPolicy;
expect($policy->sendTest($user, $notification))->toBeTrue();
});
it('denies team member from sending test notification', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn((object) ['id' => 1]);
$policy = new NotificationPolicy;
expect($policy->sendTest($user, $notification))->toBeFalse();
});
it('denies sending test notification with no team', function () {
$user = Mockery::mock(User::class)->makePartial();
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn(null);
$policy = new NotificationPolicy;
expect($policy->sendTest($user, $notification))->toBeFalse();
});
it('allows team member to view but not update notification settings', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'member']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn((object) ['id' => 1]);
$policy = new NotificationPolicy;
expect($policy->view($user, $notification))->toBeTrue();
expect($policy->update($user, $notification))->toBeFalse();
});
it('allows team admin to view and update notification settings', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'admin']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$notification = Mockery::mock(Model::class)->makePartial();
$notification->shouldReceive('getAttribute')->with('team')->andReturn((object) ['id' => 1]);
$policy = new NotificationPolicy;
expect($policy->view($user, $notification))->toBeTrue();
expect($policy->update($user, $notification))->toBeTrue();
});
+25 -48
View File
@@ -1,5 +1,6 @@
<?php
use App\Models\PrivateKey;
use App\Models\User;
use App\Policies\PrivateKeyPolicy;
@@ -11,10 +12,8 @@ it('allows root team admin to view system private key', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 0;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 0;
$policy = new PrivateKeyPolicy;
expect($policy->view($user, $privateKey))->toBeTrue();
@@ -28,10 +27,8 @@ it('allows root team owner to view system private key', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 0;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 0;
$policy = new PrivateKeyPolicy;
expect($policy->view($user, $privateKey))->toBeTrue();
@@ -45,10 +42,8 @@ it('denies regular member of root team to view system private key', function ()
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 0;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 0;
$policy = new PrivateKeyPolicy;
expect($policy->view($user, $privateKey))->toBeFalse();
@@ -62,10 +57,8 @@ it('denies non-root team member to view system private key', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 0;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 0;
$policy = new PrivateKeyPolicy;
expect($policy->view($user, $privateKey))->toBeFalse();
@@ -79,10 +72,8 @@ it('allows team member to view their own team private key', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 1;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 1;
$policy = new PrivateKeyPolicy;
expect($policy->view($user, $privateKey))->toBeTrue();
@@ -96,10 +87,8 @@ it('denies team member to view another team private key', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 2;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 2;
$policy = new PrivateKeyPolicy;
expect($policy->view($user, $privateKey))->toBeFalse();
@@ -113,10 +102,8 @@ it('allows root team admin to update system private key', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 0;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 0;
$policy = new PrivateKeyPolicy;
expect($policy->update($user, $privateKey))->toBeTrue();
@@ -130,10 +117,8 @@ it('denies root team member to update system private key', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 0;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 0;
$policy = new PrivateKeyPolicy;
expect($policy->update($user, $privateKey))->toBeFalse();
@@ -147,10 +132,8 @@ it('allows team admin to update their own team private key', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 1;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 1;
$policy = new PrivateKeyPolicy;
expect($policy->update($user, $privateKey))->toBeTrue();
@@ -164,10 +147,8 @@ it('denies team member to update their own team private key', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 1;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 1;
$policy = new PrivateKeyPolicy;
expect($policy->update($user, $privateKey))->toBeFalse();
@@ -181,10 +162,8 @@ it('allows root team admin to delete system private key', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 0;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 0;
$policy = new PrivateKeyPolicy;
expect($policy->delete($user, $privateKey))->toBeTrue();
@@ -198,10 +177,8 @@ it('denies root team member to delete system private key', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$privateKey = new class
{
public $team_id = 0;
};
$privateKey = Mockery::mock(PrivateKey::class)->makePartial();
$privateKey->team_id = 0;
$policy = new PrivateKeyPolicy;
expect($policy->delete($user, $privateKey))->toBeFalse();
+122
View File
@@ -0,0 +1,122 @@
<?php
use App\Models\Project;
use App\Models\User;
use App\Policies\ProjectPolicy;
it('allows any user to view any projects', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new ProjectPolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows team member to view their own team project', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$project = Mockery::mock(Project::class)->makePartial();
$project->team_id = 1;
$policy = new ProjectPolicy;
expect($policy->view($user, $project))->toBeTrue();
});
it('denies non-member to view another team project', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$project = Mockery::mock(Project::class)->makePartial();
$project->team_id = 2;
$policy = new ProjectPolicy;
expect($policy->view($user, $project))->toBeFalse();
});
it('allows admin to create a project', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ProjectPolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies member to create a project', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ProjectPolicy;
expect($policy->create($user))->toBeFalse();
});
it('allows team admin to update their own team project', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$project = Mockery::mock(Project::class)->makePartial();
$project->team_id = 1;
$policy = new ProjectPolicy;
expect($policy->update($user, $project))->toBeTrue();
});
it('denies team member to update their own team project', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$project = Mockery::mock(Project::class)->makePartial();
$project->team_id = 1;
$policy = new ProjectPolicy;
expect($policy->update($user, $project))->toBeFalse();
});
it('allows team admin to delete their own team project', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$project = Mockery::mock(Project::class)->makePartial();
$project->team_id = 1;
$policy = new ProjectPolicy;
expect($policy->delete($user, $project))->toBeTrue();
});
it('denies team member to delete their own team project', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$project = Mockery::mock(Project::class)->makePartial();
$project->team_id = 1;
$policy = new ProjectPolicy;
expect($policy->delete($user, $project))->toBeFalse();
});
it('denies restore for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$project = Mockery::mock(Project::class)->makePartial();
$project->team_id = 1;
$policy = new ProjectPolicy;
expect($policy->restore($user, $project))->toBeFalse();
});
it('denies force delete for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$project = Mockery::mock(Project::class)->makePartial();
$project->team_id = 1;
$policy = new ProjectPolicy;
expect($policy->forceDelete($user, $project))->toBeFalse();
});
@@ -0,0 +1,61 @@
<?php
use App\Models\Application;
use App\Models\User;
use App\Policies\ResourceCreatePolicy;
it('allows admin to create any resource', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ResourceCreatePolicy;
expect($policy->createAny($user))->toBeTrue();
});
it('denies member from creating any resource', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ResourceCreatePolicy;
expect($policy->createAny($user))->toBeFalse();
});
it('allows admin to create a valid resource class', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ResourceCreatePolicy;
expect($policy->create($user, Application::class))->toBeTrue();
});
it('denies member from creating a valid resource class', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ResourceCreatePolicy;
expect($policy->create($user, Application::class))->toBeFalse();
});
it('denies admin from creating an invalid resource class', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ResourceCreatePolicy;
expect($policy->create($user, 'App\Models\NonExistent'))->toBeFalse();
});
it('allows admin to authorize all resource creation', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ResourceCreatePolicy;
expect($policy->authorizeAllResourceCreation($user))->toBeTrue();
});
it('denies member from authorizing all resource creation', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ResourceCreatePolicy;
expect($policy->authorizeAllResourceCreation($user))->toBeFalse();
});
+55 -7
View File
@@ -52,7 +52,23 @@ it('allows team admin to update S3 storage from their team', function () {
expect($policy->update($user, $storage))->toBeTrue();
});
it('denies team member to update S3 storage from another team', function () {
it('denies team member to update S3 storage from their team', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'member']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$storage = Mockery::mock(S3Storage::class)->makePartial();
$storage->shouldReceive('getAttribute')->with('team_id')->andReturn(1);
$storage->team_id = 1;
$policy = new S3StoragePolicy;
expect($policy->update($user, $storage))->toBeFalse();
});
it('denies team admin to update S3 storage from another team', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'admin']],
]);
@@ -68,9 +84,9 @@ it('denies team member to update S3 storage from another team', function () {
expect($policy->update($user, $storage))->toBeFalse();
});
it('allows team member to delete S3 storage from their team', function () {
it('allows team admin to delete S3 storage from their team', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'member']],
(object) ['id' => 1, 'pivot' => (object) ['role' => 'admin']],
]);
$user = Mockery::mock(User::class)->makePartial();
@@ -84,7 +100,23 @@ it('allows team member to delete S3 storage from their team', function () {
expect($policy->delete($user, $storage))->toBeTrue();
});
it('denies team member to delete S3 storage from another team', function () {
it('denies team member to delete S3 storage from their team', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'member']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$storage = Mockery::mock(S3Storage::class)->makePartial();
$storage->shouldReceive('getAttribute')->with('team_id')->andReturn(1);
$storage->team_id = 1;
$policy = new S3StoragePolicy;
expect($policy->delete($user, $storage))->toBeFalse();
});
it('denies team admin to delete S3 storage from another team', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'owner']],
]);
@@ -116,9 +148,9 @@ it('denies non-admin to create S3 storage', function () {
expect($policy->create($user))->toBeFalse();
});
it('allows team member to validate connection of S3 storage from their team', function () {
it('allows team admin to validate connection of S3 storage from their team', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'member']],
(object) ['id' => 1, 'pivot' => (object) ['role' => 'admin']],
]);
$user = Mockery::mock(User::class)->makePartial();
@@ -132,7 +164,23 @@ it('allows team member to validate connection of S3 storage from their team', fu
expect($policy->validateConnection($user, $storage))->toBeTrue();
});
it('denies team member to validate connection of S3 storage from another team', function () {
it('denies team member to validate connection of S3 storage from their team', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'member']],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$storage = Mockery::mock(S3Storage::class)->makePartial();
$storage->shouldReceive('getAttribute')->with('team_id')->andReturn(1);
$storage->team_id = 1;
$policy = new S3StoragePolicy;
expect($policy->validateConnection($user, $storage))->toBeFalse();
});
it('denies team admin to validate connection of S3 storage from another team', function () {
$teams = collect([
(object) ['id' => 1, 'pivot' => (object) ['role' => 'admin']],
]);
+169
View File
@@ -0,0 +1,169 @@
<?php
use App\Models\Server;
use App\Models\User;
use App\Policies\ServerPolicy;
it('allows any user to view any servers', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new ServerPolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows team member to view their own team server', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 1;
$policy = new ServerPolicy;
expect($policy->view($user, $server))->toBeTrue();
});
it('denies non-member to view another team server', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 2;
$policy = new ServerPolicy;
expect($policy->view($user, $server))->toBeFalse();
});
it('allows admin to create a server', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ServerPolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies member to create a server', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ServerPolicy;
expect($policy->create($user))->toBeFalse();
});
it('allows team admin to update their own team server', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 1;
$policy = new ServerPolicy;
expect($policy->update($user, $server))->toBeTrue();
});
it('denies team member to update their own team server', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 1;
$policy = new ServerPolicy;
expect($policy->update($user, $server))->toBeFalse();
});
it('allows team admin to delete their own team server', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 1;
$policy = new ServerPolicy;
expect($policy->delete($user, $server))->toBeTrue();
});
it('denies team member to delete their own team server', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 1;
$policy = new ServerPolicy;
expect($policy->delete($user, $server))->toBeFalse();
});
it('denies restore for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 1;
$policy = new ServerPolicy;
expect($policy->restore($user, $server))->toBeFalse();
});
it('denies force delete for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 1;
$policy = new ServerPolicy;
expect($policy->forceDelete($user, $server))->toBeFalse();
});
it('allows team admin to manage proxy', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 1;
$policy = new ServerPolicy;
expect($policy->manageProxy($user, $server))->toBeTrue();
});
it('denies team member to manage proxy', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 1;
$policy = new ServerPolicy;
expect($policy->manageProxy($user, $server))->toBeFalse();
});
it('allows team admin to manage sentinel, ca certificate, and view security', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 1;
$policy = new ServerPolicy;
expect($policy->manageSentinel($user, $server))->toBeTrue();
expect($policy->viewSentinel($user, $server))->toBeTrue();
expect($policy->manageCaCertificate($user, $server))->toBeTrue();
expect($policy->viewSecurity($user, $server))->toBeTrue();
});
it('denies team member to view sentinel', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$server = Mockery::mock(Server::class)->makePartial();
$server->team_id = 1;
$policy = new ServerPolicy;
expect($policy->viewSentinel($user, $server))->toBeFalse();
});
@@ -0,0 +1,37 @@
<?php
use App\Models\ServiceApplication;
use App\Models\User;
use App\Policies\ServiceApplicationPolicy;
it('allows admin to create service application', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ServiceApplicationPolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies member from creating service application', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ServiceApplicationPolicy;
expect($policy->create($user))->toBeFalse();
});
it('denies restore for service application', function () {
$user = Mockery::mock(User::class)->makePartial();
$serviceApp = Mockery::mock(ServiceApplication::class)->makePartial();
$policy = new ServiceApplicationPolicy;
expect($policy->restore($user, $serviceApp))->toBeFalse();
});
it('denies force delete for service application', function () {
$user = Mockery::mock(User::class)->makePartial();
$serviceApp = Mockery::mock(ServiceApplication::class)->makePartial();
$policy = new ServiceApplicationPolicy;
expect($policy->forceDelete($user, $serviceApp))->toBeFalse();
});
@@ -0,0 +1,37 @@
<?php
use App\Models\ServiceDatabase;
use App\Models\User;
use App\Policies\ServiceDatabasePolicy;
it('allows admin to create service database', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ServiceDatabasePolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies member from creating service database', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ServiceDatabasePolicy;
expect($policy->create($user))->toBeFalse();
});
it('denies restore for service database', function () {
$user = Mockery::mock(User::class)->makePartial();
$serviceDb = Mockery::mock(ServiceDatabase::class)->makePartial();
$policy = new ServiceDatabasePolicy;
expect($policy->restore($user, $serviceDb))->toBeFalse();
});
it('denies force delete for service database', function () {
$user = Mockery::mock(User::class)->makePartial();
$serviceDb = Mockery::mock(ServiceDatabase::class)->makePartial();
$policy = new ServiceDatabasePolicy;
expect($policy->forceDelete($user, $serviceDb))->toBeFalse();
});
+233
View File
@@ -0,0 +1,233 @@
<?php
use App\Models\Service;
use App\Models\User;
use App\Policies\ServicePolicy;
it('allows any user to view any services', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new ServicePolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows team member to view their own team service', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->view($user, $service))->toBeTrue();
});
it('denies non-member to view another team service', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 2]);
$policy = new ServicePolicy;
expect($policy->view($user, $service))->toBeFalse();
});
it('denies view when service has no team', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn(null);
$policy = new ServicePolicy;
expect($policy->view($user, $service))->toBeFalse();
});
it('allows admin to create a service', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new ServicePolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies member to create a service', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new ServicePolicy;
expect($policy->create($user))->toBeFalse();
});
it('allows team admin to update their own team service', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->update($user, $service))->toBeTrue();
});
it('denies team member to update their own team service', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->update($user, $service))->toBeFalse();
});
it('allows team admin to delete their own team service', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->delete($user, $service))->toBeTrue();
});
it('denies team member to delete their own team service', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->delete($user, $service))->toBeFalse();
});
it('denies delete when service has no team', function () {
$user = Mockery::mock(User::class)->makePartial();
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn(null);
$policy = new ServicePolicy;
expect($policy->delete($user, $service))->toBeFalse();
});
it('allows team admin to deploy their own team service', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->deploy($user, $service))->toBeTrue();
});
it('denies team member to deploy their own team service', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->deploy($user, $service))->toBeFalse();
});
it('allows team admin to stop their own team service', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->stop($user, $service))->toBeTrue();
});
it('denies team member to stop their own team service', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->stop($user, $service))->toBeFalse();
});
it('allows team admin to manage service environment variables', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->manageEnvironment($user, $service))->toBeTrue();
});
it('denies team member to manage service environment variables', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->manageEnvironment($user, $service))->toBeFalse();
});
it('allows team admin to access terminal', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->accessTerminal($user, $service))->toBeTrue();
});
it('denies team member to access terminal', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$service = Mockery::mock(Service::class)->makePartial();
$service->shouldReceive('team')->andReturn((object) ['id' => 1]);
$policy = new ServicePolicy;
expect($policy->accessTerminal($user, $service))->toBeFalse();
});
it('denies restore for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$service = Mockery::mock(Service::class)->makePartial();
$policy = new ServicePolicy;
expect($policy->restore($user, $service))->toBeFalse();
});
it('denies force delete for any user', function () {
$user = Mockery::mock(User::class)->makePartial();
$service = Mockery::mock(Service::class)->makePartial();
$policy = new ServicePolicy;
expect($policy->forceDelete($user, $service))->toBeFalse();
});
@@ -1,5 +1,6 @@
<?php
use App\Models\SharedEnvironmentVariable;
use App\Models\User;
use App\Policies\SharedEnvironmentVariablePolicy;
@@ -18,10 +19,7 @@ it('allows team member to view their team shared environment variable', function
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$model = new class
{
public $team_id = 1;
};
$model = mockSharedEnvironmentVariable(teamId: 1);
$policy = new SharedEnvironmentVariablePolicy;
expect($policy->view($user, $model))->toBeTrue();
@@ -35,10 +33,7 @@ it('denies non-team member to view shared environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$model = new class
{
public $team_id = 2;
};
$model = mockSharedEnvironmentVariable(teamId: 2);
$policy = new SharedEnvironmentVariablePolicy;
expect($policy->view($user, $model))->toBeFalse();
@@ -64,10 +59,7 @@ it('allows team admin to update shared environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$model = new class
{
public $team_id = 1;
};
$model = mockSharedEnvironmentVariable(teamId: 1);
$policy = new SharedEnvironmentVariablePolicy;
expect($policy->update($user, $model))->toBeTrue();
@@ -77,10 +69,7 @@ it('denies team member to update shared environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$model = new class
{
public $team_id = 1;
};
$model = mockSharedEnvironmentVariable(teamId: 1);
$policy = new SharedEnvironmentVariablePolicy;
expect($policy->update($user, $model))->toBeFalse();
@@ -90,10 +79,7 @@ it('allows team admin to delete shared environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$model = new class
{
public $team_id = 1;
};
$model = mockSharedEnvironmentVariable(teamId: 1);
$policy = new SharedEnvironmentVariablePolicy;
expect($policy->delete($user, $model))->toBeTrue();
@@ -103,10 +89,7 @@ it('denies team member to delete shared environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$model = new class
{
public $team_id = 1;
};
$model = mockSharedEnvironmentVariable(teamId: 1);
$policy = new SharedEnvironmentVariablePolicy;
expect($policy->delete($user, $model))->toBeFalse();
@@ -115,10 +98,7 @@ it('denies team member to delete shared environment variable', function () {
it('denies restore of shared environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$model = new class
{
public $team_id = 1;
};
$model = mockSharedEnvironmentVariable(teamId: 1);
$policy = new SharedEnvironmentVariablePolicy;
expect($policy->restore($user, $model))->toBeFalse();
@@ -127,10 +107,7 @@ it('denies restore of shared environment variable', function () {
it('denies force delete of shared environment variable', function () {
$user = Mockery::mock(User::class)->makePartial();
$model = new class
{
public $team_id = 1;
};
$model = mockSharedEnvironmentVariable(teamId: 1);
$policy = new SharedEnvironmentVariablePolicy;
expect($policy->forceDelete($user, $model))->toBeFalse();
@@ -140,10 +117,7 @@ it('allows team admin to manage environment', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$model = new class
{
public $team_id = 1;
};
$model = mockSharedEnvironmentVariable(teamId: 1);
$policy = new SharedEnvironmentVariablePolicy;
expect($policy->manageEnvironment($user, $model))->toBeTrue();
@@ -153,11 +127,16 @@ it('denies team member to manage environment', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$model = new class
{
public $team_id = 1;
};
$model = mockSharedEnvironmentVariable(teamId: 1);
$policy = new SharedEnvironmentVariablePolicy;
expect($policy->manageEnvironment($user, $model))->toBeFalse();
});
function mockSharedEnvironmentVariable(int $teamId): SharedEnvironmentVariable
{
$sharedEnvironmentVariable = Mockery::mock(SharedEnvironmentVariable::class)->makePartial();
$sharedEnvironmentVariable->team_id = $teamId;
return $sharedEnvironmentVariable;
}
@@ -0,0 +1,122 @@
<?php
use App\Models\StandaloneDocker;
use App\Models\User;
use App\Policies\StandaloneDockerPolicy;
it('allows any user to view any standalone docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new StandaloneDockerPolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows team member to view their team standalone docker', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$standaloneDocker = Mockery::mock(StandaloneDocker::class)->makePartial();
$standaloneDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new StandaloneDockerPolicy;
expect($policy->view($user, $standaloneDocker))->toBeTrue();
});
it('denies user from viewing another team standalone docker', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$standaloneDocker = Mockery::mock(StandaloneDocker::class)->makePartial();
$standaloneDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 2]);
$policy = new StandaloneDockerPolicy;
expect($policy->view($user, $standaloneDocker))->toBeFalse();
});
it('allows admin to create standalone docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new StandaloneDockerPolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies non-admin from creating standalone docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new StandaloneDockerPolicy;
expect($policy->create($user))->toBeFalse();
});
it('allows team admin to update standalone docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$standaloneDocker = Mockery::mock(StandaloneDocker::class)->makePartial();
$standaloneDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new StandaloneDockerPolicy;
expect($policy->update($user, $standaloneDocker))->toBeTrue();
});
it('denies non-admin from updating standalone docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$standaloneDocker = Mockery::mock(StandaloneDocker::class)->makePartial();
$standaloneDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new StandaloneDockerPolicy;
expect($policy->update($user, $standaloneDocker))->toBeFalse();
});
it('allows team admin to delete standalone docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$standaloneDocker = Mockery::mock(StandaloneDocker::class)->makePartial();
$standaloneDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new StandaloneDockerPolicy;
expect($policy->delete($user, $standaloneDocker))->toBeTrue();
});
it('denies non-admin from deleting standalone docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$standaloneDocker = Mockery::mock(StandaloneDocker::class)->makePartial();
$standaloneDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new StandaloneDockerPolicy;
expect($policy->delete($user, $standaloneDocker))->toBeFalse();
});
it('denies restore for standalone docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$standaloneDocker = Mockery::mock(StandaloneDocker::class)->makePartial();
$standaloneDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new StandaloneDockerPolicy;
expect($policy->restore($user, $standaloneDocker))->toBeFalse();
});
it('denies force delete for standalone docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$standaloneDocker = Mockery::mock(StandaloneDocker::class)->makePartial();
$standaloneDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new StandaloneDockerPolicy;
expect($policy->forceDelete($user, $standaloneDocker))->toBeFalse();
});
@@ -0,0 +1,122 @@
<?php
use App\Models\SwarmDocker;
use App\Models\User;
use App\Policies\SwarmDockerPolicy;
it('allows any user to view any swarm docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$policy = new SwarmDockerPolicy;
expect($policy->viewAny($user))->toBeTrue();
});
it('allows team member to view their team swarm docker', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$swarmDocker = Mockery::mock(SwarmDocker::class)->makePartial();
$swarmDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new SwarmDockerPolicy;
expect($policy->view($user, $swarmDocker))->toBeTrue();
});
it('denies user from viewing another team swarm docker', function () {
$teams = collect([
(object) ['id' => 1],
]);
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('getAttribute')->with('teams')->andReturn($teams);
$swarmDocker = Mockery::mock(SwarmDocker::class)->makePartial();
$swarmDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 2]);
$policy = new SwarmDockerPolicy;
expect($policy->view($user, $swarmDocker))->toBeFalse();
});
it('allows admin to create swarm docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(true);
$policy = new SwarmDockerPolicy;
expect($policy->create($user))->toBeTrue();
});
it('denies non-admin from creating swarm docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdmin')->andReturn(false);
$policy = new SwarmDockerPolicy;
expect($policy->create($user))->toBeFalse();
});
it('allows team admin to update swarm docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$swarmDocker = Mockery::mock(SwarmDocker::class)->makePartial();
$swarmDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new SwarmDockerPolicy;
expect($policy->update($user, $swarmDocker))->toBeTrue();
});
it('denies non-admin from updating swarm docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$swarmDocker = Mockery::mock(SwarmDocker::class)->makePartial();
$swarmDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new SwarmDockerPolicy;
expect($policy->update($user, $swarmDocker))->toBeFalse();
});
it('allows team admin to delete swarm docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(true);
$swarmDocker = Mockery::mock(SwarmDocker::class)->makePartial();
$swarmDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new SwarmDockerPolicy;
expect($policy->delete($user, $swarmDocker))->toBeTrue();
});
it('denies non-admin from deleting swarm docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$user->shouldReceive('isAdminOfTeam')->with(1)->andReturn(false);
$swarmDocker = Mockery::mock(SwarmDocker::class)->makePartial();
$swarmDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new SwarmDockerPolicy;
expect($policy->delete($user, $swarmDocker))->toBeFalse();
});
it('denies restore for swarm docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$swarmDocker = Mockery::mock(SwarmDocker::class)->makePartial();
$swarmDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new SwarmDockerPolicy;
expect($policy->restore($user, $swarmDocker))->toBeFalse();
});
it('denies force delete for swarm docker', function () {
$user = Mockery::mock(User::class)->makePartial();
$swarmDocker = Mockery::mock(SwarmDocker::class)->makePartial();
$swarmDocker->shouldReceive('getAttribute')->with('server')->andReturn((object) ['team_id' => 1]);
$policy = new SwarmDockerPolicy;
expect($policy->forceDelete($user, $swarmDocker))->toBeFalse();
});
+19
View File
@@ -0,0 +1,19 @@
<?php
it('generates lowercase URL-safe public ids without Cuid2', function () {
$ids = collect(range(1, 100))->map(fn () => new_public_id());
expect($ids)->each
->toBeString()
->toHaveLength(24)
->toMatch('/^[a-z0-9]+$/');
expect($ids->unique())->toHaveCount(100);
});
it('honors custom public id lengths', function () {
expect(new_public_id(32))
->toBeString()
->toHaveLength(32)
->toMatch('/^[a-z0-9]+$/');
});
+15 -8
View File
@@ -132,24 +132,31 @@ it('generates nullable dockerNetworkRules when not required', function () {
->not->toContain('required');
});
it('accepts Docker-compatible environment variable keys', function (string $key) {
it('accepts shell-safe environment variable keys', function (string $key) {
expect(ValidationPatterns::isValidEnvironmentVariableKey($key))->toBeTrue();
})->with([
'letters' => 'APP_ENV',
'leading underscore' => '_TOKEN',
'railpack control variable' => 'RAILPACK_NODE_VERSION',
'digits after first character' => 'NODE_VERSION_20',
'starts with digit' => '1BAD',
'hyphen' => 'BAD-KEY',
'dot' => 'node.name',
'lowercase' => 'node_version',
'dot notation' => 'node.name',
'uppercase dots' => 'XPACK.SECURITY.ENABLED',
'semicolon' => 'BAD;KEY',
'space' => 'BAD KEY',
]);
it('rejects environment variable keys Docker cannot represent', function (string $key) {
it('rejects invalid environment variable keys', function (string $key) {
expect(ValidationPatterns::isValidEnvironmentVariableKey($key))->toBeFalse();
})->with([
'starts with digit' => '1BAD',
'hyphen' => 'BAD-KEY',
'semicolon' => 'BAD;KEY',
'space' => 'BAD KEY',
'command substitution' => 'BAD$(id)',
'backticks' => 'BAD`id`',
'pipe' => 'BAD|id',
'ampersand' => 'BAD&id',
'newline' => 'BAD
KEY',
'equals' => 'BAD=KEY',
'empty' => '',
]);
@@ -164,7 +171,7 @@ it('generates environment variable key rules with correct defaults', function ()
});
it('normalizes environment variable keys by trimming surrounding whitespace', function () {
expect(ValidationPatterns::normalizeEnvironmentVariableKey(' node.name '))->toBe('node.name');
expect(ValidationPatterns::normalizeEnvironmentVariableKey(' APP_ENV '))->toBe('APP_ENV');
});
it('normalizes environment variable keys before model validation', function () {