feat(auth): implement authorization checks for application management
This commit is contained in:
@@ -3,11 +3,14 @@
|
|||||||
namespace App\Livewire\Project\Application;
|
namespace App\Livewire\Project\Application;
|
||||||
|
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Attributes\Validate;
|
use Livewire\Attributes\Validate;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Advanced extends Component
|
class Advanced extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public Application $application;
|
public Application $application;
|
||||||
|
|
||||||
#[Validate(['boolean'])]
|
#[Validate(['boolean'])]
|
||||||
@@ -142,6 +145,7 @@ class Advanced extends Component
|
|||||||
public function instantSave()
|
public function instantSave()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
$reset = false;
|
$reset = false;
|
||||||
if ($this->isLogDrainEnabled) {
|
if ($this->isLogDrainEnabled) {
|
||||||
if (! $this->application->destination->server->isLogDrainEnabled()) {
|
if (! $this->application->destination->server->isLogDrainEnabled()) {
|
||||||
@@ -180,6 +184,7 @@ class Advanced extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
if ($this->gpuCount && $this->gpuDeviceIds) {
|
if ($this->gpuCount && $this->gpuDeviceIds) {
|
||||||
$this->dispatch('error', 'You cannot set both GPU count and GPU device IDs.');
|
$this->dispatch('error', 'You cannot set both GPU count and GPU device IDs.');
|
||||||
$this->gpuCount = null;
|
$this->gpuCount = null;
|
||||||
@@ -197,6 +202,9 @@ class Advanced extends Component
|
|||||||
|
|
||||||
public function saveCustomName()
|
public function saveCustomName()
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
|
|
||||||
if (str($this->customInternalName)->isNotEmpty()) {
|
if (str($this->customInternalName)->isNotEmpty()) {
|
||||||
$this->customInternalName = str($this->customInternalName)->slug()->value();
|
$this->customInternalName = str($this->customInternalName)->slug()->value();
|
||||||
} else {
|
} else {
|
||||||
@@ -224,6 +232,9 @@ class Advanced extends Component
|
|||||||
}
|
}
|
||||||
$this->syncData(true);
|
$this->syncData(true);
|
||||||
$this->dispatch('success', 'Custom name saved.');
|
$this->dispatch('success', 'Custom name saved.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
|
@@ -5,6 +5,7 @@ namespace App\Livewire\Project\Application;
|
|||||||
use App\Actions\Application\GenerateConfig;
|
use App\Actions\Application\GenerateConfig;
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Support\ValidationPatterns;
|
use App\Support\ValidationPatterns;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Spatie\Url\Url;
|
use Spatie\Url\Url;
|
||||||
@@ -12,6 +13,8 @@ use Visus\Cuid2\Cuid2;
|
|||||||
|
|
||||||
class General extends Component
|
class General extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public string $applicationId;
|
public string $applicationId;
|
||||||
|
|
||||||
public Application $application;
|
public Application $application;
|
||||||
@@ -224,6 +227,9 @@ class General extends Component
|
|||||||
|
|
||||||
public function instantSave()
|
public function instantSave()
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
|
|
||||||
if ($this->application->settings->isDirty('is_spa')) {
|
if ($this->application->settings->isDirty('is_spa')) {
|
||||||
$this->generateNginxConfiguration($this->application->settings->is_spa ? 'spa' : 'static');
|
$this->generateNginxConfiguration($this->application->settings->is_spa ? 'spa' : 'static');
|
||||||
}
|
}
|
||||||
@@ -249,12 +255,16 @@ class General extends Component
|
|||||||
if ($this->application->settings->is_container_label_readonly_enabled) {
|
if ($this->application->settings->is_container_label_readonly_enabled) {
|
||||||
$this->resetDefaultLabels(false);
|
$this->resetDefaultLabels(false);
|
||||||
}
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadComposeFile($isInit = false, $showToast = true)
|
public function loadComposeFile($isInit = false, $showToast = true)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
|
|
||||||
if ($isInit && $this->application->docker_compose_raw) {
|
if ($isInit && $this->application->docker_compose_raw) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -293,6 +303,9 @@ class General extends Component
|
|||||||
|
|
||||||
public function generateDomain(string $serviceName)
|
public function generateDomain(string $serviceName)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
|
|
||||||
$uuid = new Cuid2;
|
$uuid = new Cuid2;
|
||||||
$domain = generateUrl(server: $this->application->destination->server, random: $uuid);
|
$domain = generateUrl(server: $this->application->destination->server, random: $uuid);
|
||||||
$sanitizedKey = str($serviceName)->slug('_')->toString();
|
$sanitizedKey = str($serviceName)->slug('_')->toString();
|
||||||
@@ -322,6 +335,9 @@ class General extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $domain;
|
return $domain;
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updatedApplicationBaseDirectory()
|
public function updatedApplicationBaseDirectory()
|
||||||
@@ -374,6 +390,9 @@ class General extends Component
|
|||||||
|
|
||||||
public function getWildcardDomain()
|
public function getWildcardDomain()
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
|
|
||||||
$server = data_get($this->application, 'destination.server');
|
$server = data_get($this->application, 'destination.server');
|
||||||
if ($server) {
|
if ($server) {
|
||||||
$fqdn = generateFqdn(server: $server, random: $this->application->uuid, parserVersion: $this->application->compose_parsing_version);
|
$fqdn = generateFqdn(server: $server, random: $this->application->uuid, parserVersion: $this->application->compose_parsing_version);
|
||||||
@@ -382,13 +401,22 @@ class General extends Component
|
|||||||
$this->resetDefaultLabels();
|
$this->resetDefaultLabels();
|
||||||
$this->dispatch('success', 'Wildcard domain generated.');
|
$this->dispatch('success', 'Wildcard domain generated.');
|
||||||
}
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateNginxConfiguration($type = 'static')
|
public function generateNginxConfiguration($type = 'static')
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
|
|
||||||
$this->application->custom_nginx_configuration = defaultNginxConfiguration($type);
|
$this->application->custom_nginx_configuration = defaultNginxConfiguration($type);
|
||||||
$this->application->save();
|
$this->application->save();
|
||||||
$this->dispatch('success', 'Nginx configuration generated.');
|
$this->dispatch('success', 'Nginx configuration generated.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resetDefaultLabels($manualReset = false)
|
public function resetDefaultLabels($manualReset = false)
|
||||||
@@ -430,6 +458,8 @@ class General extends Component
|
|||||||
|
|
||||||
public function setRedirect()
|
public function setRedirect()
|
||||||
{
|
{
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$has_www = collect($this->application->fqdns)->filter(fn ($fqdn) => str($fqdn)->contains('www.'))->count();
|
$has_www = collect($this->application->fqdns)->filter(fn ($fqdn) => str($fqdn)->contains('www.'))->count();
|
||||||
if ($has_www === 0 && $this->application->redirect === 'www') {
|
if ($has_www === 0 && $this->application->redirect === 'www') {
|
||||||
@@ -448,6 +478,7 @@ class General extends Component
|
|||||||
public function submit($showToaster = true)
|
public function submit($showToaster = true)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
$this->application->fqdn = str($this->application->fqdn)->replaceEnd(',', '')->trim();
|
$this->application->fqdn = str($this->application->fqdn)->replaceEnd(',', '')->trim();
|
||||||
$this->application->fqdn = str($this->application->fqdn)->replaceStart(',', '')->trim();
|
$this->application->fqdn = str($this->application->fqdn)->replaceStart(',', '')->trim();
|
||||||
$this->application->fqdn = str($this->application->fqdn)->trim()->explode(',')->map(function ($domain) {
|
$this->application->fqdn = str($this->application->fqdn)->trim()->explode(',')->map(function ($domain) {
|
||||||
|
@@ -5,11 +5,14 @@ namespace App\Livewire\Project\Application;
|
|||||||
use App\Actions\Application\StopApplication;
|
use App\Actions\Application\StopApplication;
|
||||||
use App\Actions\Docker\GetContainersStatus;
|
use App\Actions\Docker\GetContainersStatus;
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
class Heading extends Component
|
class Heading extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public Application $application;
|
public Application $application;
|
||||||
|
|
||||||
public ?string $lastDeploymentInfo = null;
|
public ?string $lastDeploymentInfo = null;
|
||||||
@@ -57,11 +60,15 @@ class Heading extends Component
|
|||||||
|
|
||||||
public function force_deploy_without_cache()
|
public function force_deploy_without_cache()
|
||||||
{
|
{
|
||||||
|
$this->authorize('deploy', $this->application);
|
||||||
|
|
||||||
$this->deploy(force_rebuild: true);
|
$this->deploy(force_rebuild: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deploy(bool $force_rebuild = false)
|
public function deploy(bool $force_rebuild = false)
|
||||||
{
|
{
|
||||||
|
$this->authorize('deploy', $this->application);
|
||||||
|
|
||||||
if ($this->application->build_pack === 'dockercompose' && is_null($this->application->docker_compose_raw)) {
|
if ($this->application->build_pack === 'dockercompose' && is_null($this->application->docker_compose_raw)) {
|
||||||
$this->dispatch('error', 'Failed to deploy', 'Please load a Compose file first.');
|
$this->dispatch('error', 'Failed to deploy', 'Please load a Compose file first.');
|
||||||
|
|
||||||
@@ -110,12 +117,16 @@ class Heading extends Component
|
|||||||
|
|
||||||
public function stop()
|
public function stop()
|
||||||
{
|
{
|
||||||
|
$this->authorize('deploy', $this->application);
|
||||||
|
|
||||||
$this->dispatch('info', 'Gracefully stopping application.<br/>It could take a while depending on the application.');
|
$this->dispatch('info', 'Gracefully stopping application.<br/>It could take a while depending on the application.');
|
||||||
StopApplication::dispatch($this->application, false, $this->docker_cleanup);
|
StopApplication::dispatch($this->application, false, $this->docker_cleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function restart()
|
public function restart()
|
||||||
{
|
{
|
||||||
|
$this->authorize('deploy', $this->application);
|
||||||
|
|
||||||
if ($this->application->additional_servers->count() > 0 && str($this->application->docker_registry_image_name)->isEmpty()) {
|
if ($this->application->additional_servers->count() > 0 && str($this->application->docker_registry_image_name)->isEmpty()) {
|
||||||
$this->dispatch('error', 'Failed to deploy', 'Before deploying to multiple servers, you must first set a Docker image in the General tab.<br>More information here: <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/multiple-servers">documentation</a>');
|
$this->dispatch('error', 'Failed to deploy', 'Before deploying to multiple servers, you must first set a Docker image in the General tab.<br>More information here: <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/multiple-servers">documentation</a>');
|
||||||
|
|
||||||
|
@@ -6,12 +6,15 @@ use App\Actions\Docker\GetContainersStatus;
|
|||||||
use App\Jobs\DeleteResourceJob;
|
use App\Jobs\DeleteResourceJob;
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Models\ApplicationPreview;
|
use App\Models\ApplicationPreview;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
class Previews extends Component
|
class Previews extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public Application $application;
|
public Application $application;
|
||||||
|
|
||||||
public string $deployment_uuid;
|
public string $deployment_uuid;
|
||||||
@@ -48,6 +51,7 @@ class Previews extends Component
|
|||||||
public function save_preview($preview_id)
|
public function save_preview($preview_id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
$success = true;
|
$success = true;
|
||||||
$preview = $this->application->previews->find($preview_id);
|
$preview = $this->application->previews->find($preview_id);
|
||||||
if (data_get_str($preview, 'fqdn')->isNotEmpty()) {
|
if (data_get_str($preview, 'fqdn')->isNotEmpty()) {
|
||||||
@@ -73,6 +77,9 @@ class Previews extends Component
|
|||||||
|
|
||||||
public function generate_preview($preview_id)
|
public function generate_preview($preview_id)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
|
|
||||||
$preview = $this->application->previews->find($preview_id);
|
$preview = $this->application->previews->find($preview_id);
|
||||||
if (! $preview) {
|
if (! $preview) {
|
||||||
$this->dispatch('error', 'Preview not found.');
|
$this->dispatch('error', 'Preview not found.');
|
||||||
@@ -91,11 +98,15 @@ class Previews extends Component
|
|||||||
$this->application->refresh();
|
$this->application->refresh();
|
||||||
$this->dispatch('update_links');
|
$this->dispatch('update_links');
|
||||||
$this->dispatch('success', 'Domain generated.');
|
$this->dispatch('success', 'Domain generated.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function add(int $pull_request_id, ?string $pull_request_html_url = null)
|
public function add(int $pull_request_id, ?string $pull_request_html_url = null)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
if ($this->application->build_pack === 'dockercompose') {
|
if ($this->application->build_pack === 'dockercompose') {
|
||||||
$this->setDeploymentUuid();
|
$this->setDeploymentUuid();
|
||||||
$found = ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first();
|
$found = ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first();
|
||||||
@@ -131,17 +142,23 @@ class Previews extends Component
|
|||||||
|
|
||||||
public function force_deploy_without_cache(int $pull_request_id, ?string $pull_request_html_url = null)
|
public function force_deploy_without_cache(int $pull_request_id, ?string $pull_request_html_url = null)
|
||||||
{
|
{
|
||||||
|
$this->authorize('deploy', $this->application);
|
||||||
|
|
||||||
$this->deploy($pull_request_id, $pull_request_html_url, force_rebuild: true);
|
$this->deploy($pull_request_id, $pull_request_html_url, force_rebuild: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function add_and_deploy(int $pull_request_id, ?string $pull_request_html_url = null)
|
public function add_and_deploy(int $pull_request_id, ?string $pull_request_html_url = null)
|
||||||
{
|
{
|
||||||
|
$this->authorize('deploy', $this->application);
|
||||||
|
|
||||||
$this->add($pull_request_id, $pull_request_html_url);
|
$this->add($pull_request_id, $pull_request_html_url);
|
||||||
$this->deploy($pull_request_id, $pull_request_html_url);
|
$this->deploy($pull_request_id, $pull_request_html_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deploy(int $pull_request_id, ?string $pull_request_html_url = null, bool $force_rebuild = false)
|
public function deploy(int $pull_request_id, ?string $pull_request_html_url = null, bool $force_rebuild = false)
|
||||||
{
|
{
|
||||||
|
$this->authorize('deploy', $this->application);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->setDeploymentUuid();
|
$this->setDeploymentUuid();
|
||||||
$found = ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first();
|
$found = ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first();
|
||||||
@@ -184,6 +201,8 @@ class Previews extends Component
|
|||||||
|
|
||||||
public function stop(int $pull_request_id)
|
public function stop(int $pull_request_id)
|
||||||
{
|
{
|
||||||
|
$this->authorize('deploy', $this->application);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$server = $this->application->destination->server;
|
$server = $this->application->destination->server;
|
||||||
|
|
||||||
@@ -206,6 +225,7 @@ class Previews extends Component
|
|||||||
public function delete(int $pull_request_id)
|
public function delete(int $pull_request_id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('delete', $this->application);
|
||||||
$preview = ApplicationPreview::where('application_id', $this->application->id)
|
$preview = ApplicationPreview::where('application_id', $this->application->id)
|
||||||
->where('pull_request_id', $pull_request_id)
|
->where('pull_request_id', $pull_request_id)
|
||||||
->first();
|
->first();
|
||||||
|
@@ -3,12 +3,15 @@
|
|||||||
namespace App\Livewire\Project\Application;
|
namespace App\Livewire\Project\Application;
|
||||||
|
|
||||||
use App\Models\ApplicationPreview;
|
use App\Models\ApplicationPreview;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Spatie\Url\Url;
|
use Spatie\Url\Url;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
class PreviewsCompose extends Component
|
class PreviewsCompose extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $service;
|
public $service;
|
||||||
|
|
||||||
public $serviceName;
|
public $serviceName;
|
||||||
@@ -22,6 +25,9 @@ class PreviewsCompose extends Component
|
|||||||
|
|
||||||
public function save()
|
public function save()
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
$this->authorize('update', $this->preview->application);
|
||||||
|
|
||||||
$domain = data_get($this->service, 'domain');
|
$domain = data_get($this->service, 'domain');
|
||||||
$docker_compose_domains = data_get($this->preview, 'docker_compose_domains');
|
$docker_compose_domains = data_get($this->preview, 'docker_compose_domains');
|
||||||
$docker_compose_domains = json_decode($docker_compose_domains, true);
|
$docker_compose_domains = json_decode($docker_compose_domains, true);
|
||||||
@@ -30,10 +36,16 @@ class PreviewsCompose extends Component
|
|||||||
$this->preview->save();
|
$this->preview->save();
|
||||||
$this->dispatch('update_links');
|
$this->dispatch('update_links');
|
||||||
$this->dispatch('success', 'Domain saved.');
|
$this->dispatch('success', 'Domain saved.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generate()
|
public function generate()
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
$this->authorize('update', $this->preview->application);
|
||||||
|
|
||||||
$domains = collect(json_decode($this->preview->application->docker_compose_domains)) ?? collect();
|
$domains = collect(json_decode($this->preview->application->docker_compose_domains)) ?? collect();
|
||||||
$domain = $domains->first(function ($_, $key) {
|
$domain = $domains->first(function ($_, $key) {
|
||||||
return $key === $this->serviceName;
|
return $key === $this->serviceName;
|
||||||
@@ -76,5 +88,8 @@ class PreviewsCompose extends Component
|
|||||||
|
|
||||||
$this->dispatch('update_links');
|
$this->dispatch('update_links');
|
||||||
$this->dispatch('success', 'Domain generated.');
|
$this->dispatch('success', 'Domain generated.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,11 +3,14 @@
|
|||||||
namespace App\Livewire\Project\Application;
|
namespace App\Livewire\Project\Application;
|
||||||
|
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
class Rollback extends Component
|
class Rollback extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public Application $application;
|
public Application $application;
|
||||||
|
|
||||||
public $images = [];
|
public $images = [];
|
||||||
@@ -23,6 +26,8 @@ class Rollback extends Component
|
|||||||
|
|
||||||
public function rollbackImage($commit)
|
public function rollbackImage($commit)
|
||||||
{
|
{
|
||||||
|
$this->authorize('deploy', $this->application);
|
||||||
|
|
||||||
$deployment_uuid = new Cuid2;
|
$deployment_uuid = new Cuid2;
|
||||||
|
|
||||||
queue_application_deployment(
|
queue_application_deployment(
|
||||||
@@ -43,6 +48,8 @@ class Rollback extends Component
|
|||||||
|
|
||||||
public function loadImages($showToast = false)
|
public function loadImages($showToast = false)
|
||||||
{
|
{
|
||||||
|
$this->authorize('view', $this->application);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$image = $this->application->docker_registry_image_name ?? $this->application->uuid;
|
$image = $this->application->docker_registry_image_name ?? $this->application->uuid;
|
||||||
if ($this->application->destination->server->isFunctional()) {
|
if ($this->application->destination->server->isFunctional()) {
|
||||||
|
@@ -4,12 +4,15 @@ namespace App\Livewire\Project\Application;
|
|||||||
|
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Models\PrivateKey;
|
use App\Models\PrivateKey;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Attributes\Locked;
|
use Livewire\Attributes\Locked;
|
||||||
use Livewire\Attributes\Validate;
|
use Livewire\Attributes\Validate;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Source extends Component
|
class Source extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public Application $application;
|
public Application $application;
|
||||||
|
|
||||||
#[Locked]
|
#[Locked]
|
||||||
@@ -81,6 +84,7 @@ class Source extends Component
|
|||||||
public function setPrivateKey(int $privateKeyId)
|
public function setPrivateKey(int $privateKeyId)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
$this->privateKeyId = $privateKeyId;
|
$this->privateKeyId = $privateKeyId;
|
||||||
$this->syncData(true);
|
$this->syncData(true);
|
||||||
$this->getPrivateKeys();
|
$this->getPrivateKeys();
|
||||||
@@ -94,7 +98,9 @@ class Source extends Component
|
|||||||
|
|
||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
if (str($this->gitCommitSha)->isEmpty()) {
|
if (str($this->gitCommitSha)->isEmpty()) {
|
||||||
$this->gitCommitSha = 'HEAD';
|
$this->gitCommitSha = 'HEAD';
|
||||||
}
|
}
|
||||||
@@ -107,7 +113,9 @@ class Source extends Component
|
|||||||
|
|
||||||
public function changeSource($sourceId, $sourceType)
|
public function changeSource($sourceId, $sourceType)
|
||||||
{
|
{
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
$this->application->update([
|
$this->application->update([
|
||||||
'source_id' => $sourceId,
|
'source_id' => $sourceId,
|
||||||
'source_type' => $sourceType,
|
'source_type' => $sourceType,
|
||||||
|
@@ -7,6 +7,7 @@ use App\Models\InstanceSettings;
|
|||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
use App\Models\ServiceApplication;
|
use App\Models\ServiceApplication;
|
||||||
use App\Models\ServiceDatabase;
|
use App\Models\ServiceDatabase;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@@ -14,6 +15,8 @@ use Visus\Cuid2\Cuid2;
|
|||||||
|
|
||||||
class Danger extends Component
|
class Danger extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $resource;
|
public $resource;
|
||||||
|
|
||||||
public $resourceName;
|
public $resourceName;
|
||||||
@@ -96,6 +99,7 @@ class Danger extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('delete', $this->resource);
|
||||||
$this->resource->delete();
|
$this->resource->delete();
|
||||||
DeleteResourceJob::dispatch(
|
DeleteResourceJob::dispatch(
|
||||||
$this->resource,
|
$this->resource,
|
||||||
|
@@ -4,11 +4,12 @@ namespace App\Livewire\Project\Shared\EnvironmentVariable;
|
|||||||
|
|
||||||
use App\Models\EnvironmentVariable;
|
use App\Models\EnvironmentVariable;
|
||||||
use App\Traits\EnvironmentVariableProtection;
|
use App\Traits\EnvironmentVariableProtection;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class All extends Component
|
class All extends Component
|
||||||
{
|
{
|
||||||
use EnvironmentVariableProtection;
|
use AuthorizesRequests, EnvironmentVariableProtection;
|
||||||
|
|
||||||
public $resource;
|
public $resource;
|
||||||
|
|
||||||
@@ -44,6 +45,8 @@ class All extends Component
|
|||||||
|
|
||||||
public function instantSave()
|
public function instantSave()
|
||||||
{
|
{
|
||||||
|
$this->authorize('manageEnvironment', $this->resource);
|
||||||
|
|
||||||
$this->resource->settings->is_env_sorting_enabled = $this->is_env_sorting_enabled;
|
$this->resource->settings->is_env_sorting_enabled = $this->is_env_sorting_enabled;
|
||||||
$this->resource->settings->save();
|
$this->resource->settings->save();
|
||||||
$this->sortEnvironmentVariables();
|
$this->sortEnvironmentVariables();
|
||||||
@@ -95,6 +98,8 @@ class All extends Component
|
|||||||
|
|
||||||
public function submit($data = null)
|
public function submit($data = null)
|
||||||
{
|
{
|
||||||
|
$this->authorize('manageEnvironment', $this->resource);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($data === null) {
|
if ($data === null) {
|
||||||
$this->handleBulkSubmit();
|
$this->handleBulkSubmit();
|
||||||
|
@@ -12,11 +12,14 @@ use App\Models\Environment;
|
|||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\StandaloneDocker;
|
use App\Models\StandaloneDocker;
|
||||||
use App\Models\SwarmDocker;
|
use App\Models\SwarmDocker;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
class ResourceOperations extends Component
|
class ResourceOperations extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $resource;
|
public $resource;
|
||||||
|
|
||||||
public $projectUuid;
|
public $projectUuid;
|
||||||
@@ -45,6 +48,8 @@ class ResourceOperations extends Component
|
|||||||
|
|
||||||
public function cloneTo($destination_id)
|
public function cloneTo($destination_id)
|
||||||
{
|
{
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
$new_destination = StandaloneDocker::find($destination_id);
|
$new_destination = StandaloneDocker::find($destination_id);
|
||||||
if (! $new_destination) {
|
if (! $new_destination) {
|
||||||
$new_destination = SwarmDocker::find($destination_id);
|
$new_destination = SwarmDocker::find($destination_id);
|
||||||
@@ -485,6 +490,7 @@ class ResourceOperations extends Component
|
|||||||
public function moveTo($environment_id)
|
public function moveTo($environment_id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
$new_environment = Environment::findOrFail($environment_id);
|
$new_environment = Environment::findOrFail($environment_id);
|
||||||
$this->resource->update([
|
$this->resource->update([
|
||||||
'environment_id' => $environment_id,
|
'environment_id' => $environment_id,
|
||||||
|
@@ -4,6 +4,7 @@ namespace App\Policies;
|
|||||||
|
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use Illuminate\Auth\Access\Response;
|
||||||
|
|
||||||
class ApplicationPolicy
|
class ApplicationPolicy
|
||||||
{
|
{
|
||||||
@@ -28,15 +29,23 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
|
if ($user->isAdmin()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether the user can update the model.
|
* Determine whether the user can update the model.
|
||||||
*/
|
*/
|
||||||
public function update(User $user, Application $application): bool
|
public function update(User $user, Application $application): Response
|
||||||
{
|
{
|
||||||
return true;
|
if ($user->isAdmin()) {
|
||||||
|
return Response::allow();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response::deny('As a member, you cannot update this application.<br/><br/>You need at least admin or owner permissions.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,6 +73,30 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function forceDelete(User $user, Application $application): bool
|
public function forceDelete(User $user, Application $application): bool
|
||||||
{
|
{
|
||||||
return true;
|
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can deploy the application.
|
||||||
|
*/
|
||||||
|
public function deploy(User $user, Application $application): bool
|
||||||
|
{
|
||||||
|
return $user->teams()->get()->firstWhere('id', $application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can manage deployments.
|
||||||
|
*/
|
||||||
|
public function manageDeployments(User $user, Application $application): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can manage environment variables.
|
||||||
|
*/
|
||||||
|
public function manageEnvironment(User $user, Application $application): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $application->team()->first()->id) !== null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
86
app/Policies/ApplicationPreviewPolicy.php
Normal file
86
app/Policies/ApplicationPreviewPolicy.php
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\ApplicationPreview;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Auth\Access\Response;
|
||||||
|
|
||||||
|
class ApplicationPreviewPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any models.
|
||||||
|
*/
|
||||||
|
public function viewAny(User $user): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*/
|
||||||
|
public function view(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
|
{
|
||||||
|
return $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create models.
|
||||||
|
*/
|
||||||
|
public function create(User $user): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*/
|
||||||
|
public function update(User $user, ApplicationPreview $applicationPreview): Response
|
||||||
|
{
|
||||||
|
if ($user->isAdmin()) {
|
||||||
|
return Response::allow();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response::deny('As a member, you cannot update this preview.<br/><br/>You need at least admin or owner permissions.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*/
|
||||||
|
public function delete(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can restore the model.
|
||||||
|
*/
|
||||||
|
public function restore(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can permanently delete the model.
|
||||||
|
*/
|
||||||
|
public function forceDelete(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can deploy the preview.
|
||||||
|
*/
|
||||||
|
public function deploy(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
|
{
|
||||||
|
return $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can manage preview deployments.
|
||||||
|
*/
|
||||||
|
public function manageDeployments(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
}
|
65
app/Policies/ApplicationSettingPolicy.php
Normal file
65
app/Policies/ApplicationSettingPolicy.php
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\ApplicationSetting;
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
class ApplicationSettingPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any models.
|
||||||
|
*/
|
||||||
|
public function viewAny(User $user): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*/
|
||||||
|
public function view(User $user, ApplicationSetting $applicationSetting): bool
|
||||||
|
{
|
||||||
|
return $user->teams()->get()->firstWhere('id', $applicationSetting->application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create models.
|
||||||
|
*/
|
||||||
|
public function create(User $user): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*/
|
||||||
|
public function update(User $user, ApplicationSetting $applicationSetting): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationSetting->application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*/
|
||||||
|
public function delete(User $user, ApplicationSetting $applicationSetting): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationSetting->application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can restore the model.
|
||||||
|
*/
|
||||||
|
public function restore(User $user, ApplicationSetting $applicationSetting): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationSetting->application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can permanently delete the model.
|
||||||
|
*/
|
||||||
|
public function forceDelete(User $user, ApplicationSetting $applicationSetting): bool
|
||||||
|
{
|
||||||
|
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationSetting->application->team()->first()->id) !== null;
|
||||||
|
}
|
||||||
|
}
|
@@ -17,6 +17,9 @@ class AuthServiceProvider extends ServiceProvider
|
|||||||
\App\Models\PrivateKey::class => \App\Policies\PrivateKeyPolicy::class,
|
\App\Models\PrivateKey::class => \App\Policies\PrivateKeyPolicy::class,
|
||||||
\App\Models\StandaloneDocker::class => \App\Policies\StandaloneDockerPolicy::class,
|
\App\Models\StandaloneDocker::class => \App\Policies\StandaloneDockerPolicy::class,
|
||||||
\App\Models\SwarmDocker::class => \App\Policies\SwarmDockerPolicy::class,
|
\App\Models\SwarmDocker::class => \App\Policies\SwarmDockerPolicy::class,
|
||||||
|
\App\Models\Application::class => \App\Policies\ApplicationPolicy::class,
|
||||||
|
\App\Models\ApplicationPreview::class => \App\Policies\ApplicationPreviewPolicy::class,
|
||||||
|
\App\Models\ApplicationSetting::class => \App\Policies\ApplicationSettingPolicy::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user