feat(acl): Change views/backend code to able to use proper ACL's later on. Currently it is not enabled.
This commit is contained in:
@@ -5,12 +5,15 @@ namespace App\Livewire\Destination;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use App\Models\SwarmDocker;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
#[Locked]
|
||||
public $destination;
|
||||
|
||||
@@ -63,6 +66,8 @@ class Show extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->destination);
|
||||
|
||||
$this->syncData(true);
|
||||
$this->dispatch('success', 'Destination saved.');
|
||||
} catch (\Throwable $e) {
|
||||
@@ -73,6 +78,8 @@ class Show extends Component
|
||||
public function delete()
|
||||
{
|
||||
try {
|
||||
$this->authorize('delete', $this->destination);
|
||||
|
||||
if ($this->destination->getMorphClass() === \App\Models\StandaloneDocker::class) {
|
||||
if ($this->destination->attachedTo()) {
|
||||
return $this->dispatch('error', 'You must delete all resources before deleting this destination.');
|
||||
|
@@ -5,11 +5,14 @@ namespace App\Livewire\Notifications;
|
||||
use App\Models\DiscordNotificationSettings;
|
||||
use App\Models\Team;
|
||||
use App\Notifications\Test;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
class Discord extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public Team $team;
|
||||
|
||||
public DiscordNotificationSettings $settings;
|
||||
@@ -67,6 +70,7 @@ class Discord extends Component
|
||||
try {
|
||||
$this->team = auth()->user()->currentTeam();
|
||||
$this->settings = $this->team->discordNotificationSettings;
|
||||
$this->authorize('view', $this->settings);
|
||||
$this->syncData();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
@@ -77,6 +81,7 @@ class Discord extends Component
|
||||
{
|
||||
if ($toModel) {
|
||||
$this->validate();
|
||||
$this->authorize('update', $this->settings);
|
||||
$this->settings->discord_enabled = $this->discordEnabled;
|
||||
$this->settings->discord_webhook_url = $this->discordWebhookUrl;
|
||||
|
||||
@@ -182,6 +187,7 @@ class Discord extends Component
|
||||
public function sendTestNotification()
|
||||
{
|
||||
try {
|
||||
$this->authorize('sendTest', $this->settings);
|
||||
$this->team->notify(new Test(channel: 'discord'));
|
||||
$this->dispatch('success', 'Test notification sent.');
|
||||
} catch (\Throwable $e) {
|
||||
|
@@ -5,6 +5,7 @@ namespace App\Livewire\Notifications;
|
||||
use App\Models\EmailNotificationSettings;
|
||||
use App\Models\Team;
|
||||
use App\Notifications\Test;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Attributes\Validate;
|
||||
@@ -12,6 +13,8 @@ use Livewire\Component;
|
||||
|
||||
class Email extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
protected $listeners = ['refresh' => '$refresh'];
|
||||
|
||||
#[Locked]
|
||||
@@ -110,6 +113,7 @@ class Email extends Component
|
||||
$this->team = auth()->user()->currentTeam();
|
||||
$this->emails = auth()->user()->email;
|
||||
$this->settings = $this->team->emailNotificationSettings;
|
||||
$this->authorize('view', $this->settings);
|
||||
$this->syncData();
|
||||
$this->testEmailAddress = auth()->user()->email;
|
||||
} catch (\Throwable $e) {
|
||||
@@ -121,6 +125,7 @@ class Email extends Component
|
||||
{
|
||||
if ($toModel) {
|
||||
$this->validate();
|
||||
$this->authorize('update', $this->settings);
|
||||
$this->settings->smtp_enabled = $this->smtpEnabled;
|
||||
$this->settings->smtp_from_address = $this->smtpFromAddress;
|
||||
$this->settings->smtp_from_name = $this->smtpFromName;
|
||||
@@ -311,6 +316,7 @@ class Email extends Component
|
||||
public function sendTestEmail()
|
||||
{
|
||||
try {
|
||||
$this->authorize('sendTest', $this->settings);
|
||||
$this->validate([
|
||||
'testEmailAddress' => 'required|email',
|
||||
], [
|
||||
@@ -338,6 +344,7 @@ class Email extends Component
|
||||
|
||||
public function copyFromInstanceSettings()
|
||||
{
|
||||
$this->authorize('update', $this->settings);
|
||||
$settings = instanceSettings();
|
||||
$this->smtpFromAddress = $settings->smtp_from_address;
|
||||
$this->smtpFromName = $settings->smtp_from_name;
|
||||
|
@@ -5,12 +5,15 @@ namespace App\Livewire\Notifications;
|
||||
use App\Models\PushoverNotificationSettings;
|
||||
use App\Models\Team;
|
||||
use App\Notifications\Test;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
class Pushover extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
protected $listeners = ['refresh' => '$refresh'];
|
||||
|
||||
#[Locked]
|
||||
@@ -72,6 +75,7 @@ class Pushover extends Component
|
||||
try {
|
||||
$this->team = auth()->user()->currentTeam();
|
||||
$this->settings = $this->team->pushoverNotificationSettings;
|
||||
$this->authorize('view', $this->settings);
|
||||
$this->syncData();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
@@ -82,6 +86,7 @@ class Pushover extends Component
|
||||
{
|
||||
if ($toModel) {
|
||||
$this->validate();
|
||||
$this->authorize('update', $this->settings);
|
||||
$this->settings->pushover_enabled = $this->pushoverEnabled;
|
||||
$this->settings->pushover_user_key = $this->pushoverUserKey;
|
||||
$this->settings->pushover_api_token = $this->pushoverApiToken;
|
||||
@@ -175,6 +180,7 @@ class Pushover extends Component
|
||||
public function sendTestNotification()
|
||||
{
|
||||
try {
|
||||
$this->authorize('sendTest', $this->settings);
|
||||
$this->team->notify(new Test(channel: 'pushover'));
|
||||
$this->dispatch('success', 'Test notification sent.');
|
||||
} catch (\Throwable $e) {
|
||||
|
@@ -5,12 +5,15 @@ namespace App\Livewire\Notifications;
|
||||
use App\Models\SlackNotificationSettings;
|
||||
use App\Models\Team;
|
||||
use App\Notifications\Test;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
class Slack extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
protected $listeners = ['refresh' => '$refresh'];
|
||||
|
||||
#[Locked]
|
||||
@@ -69,6 +72,7 @@ class Slack extends Component
|
||||
try {
|
||||
$this->team = auth()->user()->currentTeam();
|
||||
$this->settings = $this->team->slackNotificationSettings;
|
||||
$this->authorize('view', $this->settings);
|
||||
$this->syncData();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
@@ -79,6 +83,7 @@ class Slack extends Component
|
||||
{
|
||||
if ($toModel) {
|
||||
$this->validate();
|
||||
$this->authorize('update', $this->settings);
|
||||
$this->settings->slack_enabled = $this->slackEnabled;
|
||||
$this->settings->slack_webhook_url = $this->slackWebhookUrl;
|
||||
|
||||
@@ -168,6 +173,7 @@ class Slack extends Component
|
||||
public function sendTestNotification()
|
||||
{
|
||||
try {
|
||||
$this->authorize('sendTest', $this->settings);
|
||||
$this->team->notify(new Test(channel: 'slack'));
|
||||
$this->dispatch('success', 'Test notification sent.');
|
||||
} catch (\Throwable $e) {
|
||||
|
@@ -5,12 +5,15 @@ namespace App\Livewire\Notifications;
|
||||
use App\Models\Team;
|
||||
use App\Models\TelegramNotificationSettings;
|
||||
use App\Notifications\Test;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
class Telegram extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
protected $listeners = ['refresh' => '$refresh'];
|
||||
|
||||
#[Locked]
|
||||
@@ -111,6 +114,7 @@ class Telegram extends Component
|
||||
try {
|
||||
$this->team = auth()->user()->currentTeam();
|
||||
$this->settings = $this->team->telegramNotificationSettings;
|
||||
$this->authorize('view', $this->settings);
|
||||
$this->syncData();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
@@ -121,6 +125,7 @@ class Telegram extends Component
|
||||
{
|
||||
if ($toModel) {
|
||||
$this->validate();
|
||||
$this->authorize('update', $this->settings);
|
||||
$this->settings->telegram_enabled = $this->telegramEnabled;
|
||||
$this->settings->telegram_token = $this->telegramToken;
|
||||
$this->settings->telegram_chat_id = $this->telegramChatId;
|
||||
@@ -241,6 +246,7 @@ class Telegram extends Component
|
||||
public function sendTestNotification()
|
||||
{
|
||||
try {
|
||||
$this->authorize('sendTest', $this->settings);
|
||||
$this->team->notify(new Test(channel: 'telegram'));
|
||||
$this->dispatch('success', 'Test notification sent.');
|
||||
} catch (\Throwable $e) {
|
||||
|
@@ -3,12 +3,15 @@
|
||||
namespace App\Livewire\Project\Application\Preview;
|
||||
|
||||
use App\Models\Application;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
use Spatie\Url\Url;
|
||||
|
||||
class Form extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public Application $application;
|
||||
|
||||
#[Validate('required')]
|
||||
@@ -27,6 +30,7 @@ class Form extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->application);
|
||||
$this->resetErrorBag();
|
||||
$this->validate();
|
||||
$this->application->preview_url_template = str_replace(' ', '', $this->previewUrlTemplate);
|
||||
@@ -41,6 +45,7 @@ class Form extends Component
|
||||
public function resetToDefault()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->application);
|
||||
$this->application->preview_url_template = '{{pr_id}}.{{domain}}';
|
||||
$this->previewUrlTemplate = $this->application->preview_url_template;
|
||||
$this->application->save();
|
||||
|
@@ -38,6 +38,7 @@ class Previews extends Component
|
||||
public function load_prs()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->application);
|
||||
['rate_limit_remaining' => $rate_limit_remaining, 'data' => $data] = githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/pulls");
|
||||
$this->rate_limit_remaining = $rate_limit_remaining;
|
||||
$this->pull_requests = $data->sortBy('number')->values();
|
||||
|
@@ -176,6 +176,7 @@ EOD;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$this->importRunning = true;
|
||||
$this->importCommands = [];
|
||||
if (filled($this->customLocation)) {
|
||||
$backupFileName = '/tmp/restore_'.$this->resource->uuid;
|
||||
|
@@ -20,6 +20,7 @@ class Index extends Component
|
||||
$this->private_keys = PrivateKey::ownedByCurrentTeam()->get();
|
||||
$this->projects = Project::ownedByCurrentTeam()->get()->map(function ($project) {
|
||||
$project->settingsRoute = route('project.edit', ['project_uuid' => $project->uuid]);
|
||||
$project->canUpdate = auth()->user()->can('update', $project);
|
||||
|
||||
return $project;
|
||||
});
|
||||
|
@@ -3,11 +3,14 @@
|
||||
namespace App\Livewire\Project\Service;
|
||||
|
||||
use App\Models\Service;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Livewire\Component;
|
||||
|
||||
class Configuration extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $currentRoute;
|
||||
|
||||
public $project;
|
||||
@@ -40,24 +43,30 @@ class Configuration extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->currentRoute = request()->route()->getName();
|
||||
$this->query = request()->query();
|
||||
$project = currentTeam()
|
||||
->projects()
|
||||
->select('id', 'uuid', 'team_id')
|
||||
->where('uuid', request()->route('project_uuid'))
|
||||
->firstOrFail();
|
||||
$environment = $project->environments()
|
||||
->select('id', 'uuid', 'name', 'project_id')
|
||||
->where('uuid', request()->route('environment_uuid'))
|
||||
->firstOrFail();
|
||||
$this->service = $environment->services()->whereUuid(request()->route('service_uuid'))->firstOrFail();
|
||||
try {
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->currentRoute = request()->route()->getName();
|
||||
$this->query = request()->query();
|
||||
$project = currentTeam()
|
||||
->projects()
|
||||
->select('id', 'uuid', 'team_id')
|
||||
->where('uuid', request()->route('project_uuid'))
|
||||
->firstOrFail();
|
||||
$environment = $project->environments()
|
||||
->select('id', 'uuid', 'name', 'project_id')
|
||||
->where('uuid', request()->route('environment_uuid'))
|
||||
->firstOrFail();
|
||||
$this->service = $environment->services()->whereUuid(request()->route('service_uuid'))->firstOrFail();
|
||||
|
||||
$this->project = $project;
|
||||
$this->environment = $environment;
|
||||
$this->applications = $this->service->applications->sort();
|
||||
$this->databases = $this->service->databases->sort();
|
||||
$this->authorize('view', $this->service);
|
||||
|
||||
$this->project = $project;
|
||||
$this->environment = $environment;
|
||||
$this->applications = $this->service->applications->sort();
|
||||
$this->databases = $this->service->databases->sort();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function refreshServices()
|
||||
@@ -70,6 +79,7 @@ class Configuration extends Component
|
||||
public function restartApplication($id)
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->service);
|
||||
$application = $this->service->applications->find($id);
|
||||
if ($application) {
|
||||
$application->restart();
|
||||
@@ -83,6 +93,7 @@ class Configuration extends Component
|
||||
public function restartDatabase($id)
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->service);
|
||||
$database = $this->service->databases->find($id);
|
||||
if ($database) {
|
||||
$database->restart();
|
||||
|
@@ -6,6 +6,7 @@ use App\Actions\Database\StartDatabaseProxy;
|
||||
use App\Actions\Database\StopDatabaseProxy;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\ServiceDatabase;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
@@ -13,6 +14,8 @@ use Livewire\Component;
|
||||
|
||||
class Database extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public ServiceDatabase $database;
|
||||
|
||||
public ?string $db_url_public = null;
|
||||
@@ -40,24 +43,31 @@ class Database extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
if ($this->database->is_public) {
|
||||
$this->db_url_public = $this->database->getServiceDatabaseUrl();
|
||||
try {
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->authorize('view', $this->database);
|
||||
if ($this->database->is_public) {
|
||||
$this->db_url_public = $this->database->getServiceDatabaseUrl();
|
||||
}
|
||||
$this->refreshFileStorages();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
$this->refreshFileStorages();
|
||||
}
|
||||
|
||||
public function delete($password)
|
||||
{
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$this->authorize('delete', $this->database);
|
||||
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->database->delete();
|
||||
$this->dispatch('success', 'Database deleted.');
|
||||
|
||||
@@ -69,24 +79,35 @@ class Database extends Component
|
||||
|
||||
public function instantSaveExclude()
|
||||
{
|
||||
$this->submit();
|
||||
try {
|
||||
$this->authorize('update', $this->database);
|
||||
$this->submit();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function instantSaveLogDrain()
|
||||
{
|
||||
if (! $this->database->service->destination->server->isLogDrainEnabled()) {
|
||||
$this->database->is_log_drain_enabled = false;
|
||||
$this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.');
|
||||
try {
|
||||
$this->authorize('update', $this->database);
|
||||
if (! $this->database->service->destination->server->isLogDrainEnabled()) {
|
||||
$this->database->is_log_drain_enabled = false;
|
||||
$this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.');
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
$this->submit();
|
||||
$this->dispatch('success', 'You need to restart the service for the changes to take effect.');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
$this->submit();
|
||||
$this->dispatch('success', 'You need to restart the service for the changes to take effect.');
|
||||
}
|
||||
|
||||
public function convertToApplication()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->database);
|
||||
$service = $this->database->service;
|
||||
$serviceDatabase = $this->database;
|
||||
|
||||
@@ -122,28 +143,33 @@ class Database extends Component
|
||||
|
||||
public function instantSave()
|
||||
{
|
||||
if ($this->database->is_public && ! $this->database->public_port) {
|
||||
$this->dispatch('error', 'Public port is required.');
|
||||
$this->database->is_public = false;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($this->database->is_public) {
|
||||
if (! str($this->database->status)->startsWith('running')) {
|
||||
$this->dispatch('error', 'Database must be started to be publicly accessible.');
|
||||
try {
|
||||
$this->authorize('update', $this->database);
|
||||
if ($this->database->is_public && ! $this->database->public_port) {
|
||||
$this->dispatch('error', 'Public port is required.');
|
||||
$this->database->is_public = false;
|
||||
|
||||
return;
|
||||
}
|
||||
StartDatabaseProxy::run($this->database);
|
||||
$this->db_url_public = $this->database->getServiceDatabaseUrl();
|
||||
$this->dispatch('success', 'Database is now publicly accessible.');
|
||||
} else {
|
||||
StopDatabaseProxy::run($this->database);
|
||||
$this->db_url_public = null;
|
||||
$this->dispatch('success', 'Database is no longer publicly accessible.');
|
||||
if ($this->database->is_public) {
|
||||
if (! str($this->database->status)->startsWith('running')) {
|
||||
$this->dispatch('error', 'Database must be started to be publicly accessible.');
|
||||
$this->database->is_public = false;
|
||||
|
||||
return;
|
||||
}
|
||||
StartDatabaseProxy::run($this->database);
|
||||
$this->db_url_public = $this->database->getServiceDatabaseUrl();
|
||||
$this->dispatch('success', 'Database is now publicly accessible.');
|
||||
} else {
|
||||
StopDatabaseProxy::run($this->database);
|
||||
$this->db_url_public = null;
|
||||
$this->dispatch('success', 'Database is no longer publicly accessible.');
|
||||
}
|
||||
$this->submit();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
$this->submit();
|
||||
}
|
||||
|
||||
public function refreshFileStorages()
|
||||
@@ -154,11 +180,13 @@ class Database extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->database);
|
||||
$this->validate();
|
||||
$this->database->save();
|
||||
updateCompose($this->database);
|
||||
$this->dispatch('success', 'Database saved.');
|
||||
} catch (\Throwable) {
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
} finally {
|
||||
$this->dispatch('generateDockerCompose');
|
||||
}
|
||||
|
@@ -15,12 +15,15 @@ use App\Models\StandaloneMongodb;
|
||||
use App\Models\StandaloneMysql;
|
||||
use App\Models\StandalonePostgresql;
|
||||
use App\Models\StandaloneRedis;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Component;
|
||||
|
||||
class FileStorage extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public LocalFileVolume $fileStorage;
|
||||
|
||||
public ServiceApplication|StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse|ServiceDatabase|Application $resource;
|
||||
@@ -54,6 +57,8 @@ class FileStorage extends Component
|
||||
public function convertToDirectory()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
$this->fileStorage->deleteStorageOnServer();
|
||||
$this->fileStorage->is_directory = true;
|
||||
$this->fileStorage->content = null;
|
||||
@@ -70,6 +75,8 @@ class FileStorage extends Component
|
||||
public function loadStorageOnServer()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
$this->fileStorage->loadStorageOnServer();
|
||||
$this->dispatch('success', 'File storage loaded from server.');
|
||||
} catch (\Throwable $e) {
|
||||
@@ -82,6 +89,8 @@ class FileStorage extends Component
|
||||
public function convertToFile()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
$this->fileStorage->deleteStorageOnServer();
|
||||
$this->fileStorage->is_directory = false;
|
||||
$this->fileStorage->content = null;
|
||||
@@ -99,6 +108,8 @@ class FileStorage extends Component
|
||||
|
||||
public function delete($password)
|
||||
{
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
@@ -127,6 +138,8 @@ class FileStorage extends Component
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
$original = $this->fileStorage->getOriginal();
|
||||
try {
|
||||
$this->validate();
|
||||
|
@@ -5,11 +5,14 @@ namespace App\Livewire\Project\Service;
|
||||
use App\Models\Service;
|
||||
use App\Models\ServiceApplication;
|
||||
use App\Models\ServiceDatabase;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public ?Service $service = null;
|
||||
|
||||
public ?ServiceApplication $serviceApplication = null;
|
||||
@@ -36,6 +39,7 @@ class Index extends Component
|
||||
if (! $this->service) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$this->authorize('view', $this->service);
|
||||
$service = $this->service->applications()->whereUuid($this->parameters['stack_service_uuid'])->first();
|
||||
if ($service) {
|
||||
$this->serviceApplication = $service;
|
||||
@@ -52,7 +56,12 @@ class Index extends Component
|
||||
|
||||
public function generateDockerCompose()
|
||||
{
|
||||
$this->service->parse();
|
||||
try {
|
||||
$this->authorize('update', $this->service);
|
||||
$this->service->parse();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
@@ -4,6 +4,7 @@ namespace App\Livewire\Project\Service;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\ServiceApplication;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
@@ -12,6 +13,8 @@ use Spatie\Url\Url;
|
||||
|
||||
class ServiceApplicationView extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public ServiceApplication $application;
|
||||
|
||||
public $parameters;
|
||||
@@ -34,32 +37,44 @@ class ServiceApplicationView extends Component
|
||||
|
||||
public function instantSave()
|
||||
{
|
||||
$this->submit();
|
||||
try {
|
||||
$this->authorize('update', $this->application);
|
||||
$this->submit();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function instantSaveAdvanced()
|
||||
{
|
||||
if (! $this->application->service->destination->server->isLogDrainEnabled()) {
|
||||
$this->application->is_log_drain_enabled = false;
|
||||
$this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.');
|
||||
try {
|
||||
$this->authorize('update', $this->application);
|
||||
if (! $this->application->service->destination->server->isLogDrainEnabled()) {
|
||||
$this->application->is_log_drain_enabled = false;
|
||||
$this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.');
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
$this->application->save();
|
||||
$this->dispatch('success', 'You need to restart the service for the changes to take effect.');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
$this->application->save();
|
||||
$this->dispatch('success', 'You need to restart the service for the changes to take effect.');
|
||||
}
|
||||
|
||||
public function delete($password)
|
||||
{
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$this->authorize('delete', $this->application);
|
||||
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->application->delete();
|
||||
$this->dispatch('success', 'Application deleted.');
|
||||
|
||||
@@ -71,12 +86,18 @@ class ServiceApplicationView extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
try {
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->authorize('view', $this->application);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function convertToDatabase()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->application);
|
||||
$service = $this->application->service;
|
||||
$serviceApplication = $this->application;
|
||||
|
||||
@@ -111,6 +132,7 @@ class ServiceApplicationView extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->application);
|
||||
$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)->trim()->explode(',')->map(function ($domain) {
|
||||
|
@@ -3,10 +3,13 @@
|
||||
namespace App\Livewire\Project\Service;
|
||||
|
||||
use App\Models\LocalPersistentVolume;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Storage extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $resource;
|
||||
|
||||
public $fileStorage;
|
||||
@@ -42,6 +45,8 @@ class Storage extends Component
|
||||
public function addNewVolume($data)
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
LocalPersistentVolume::create([
|
||||
'name' => $data['name'],
|
||||
'mount_path' => $data['mount_path'],
|
||||
|
@@ -2,10 +2,13 @@
|
||||
|
||||
namespace App\Livewire\Project\Shared\EnvironmentVariable;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Add extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $parameters;
|
||||
|
||||
public bool $shared = false;
|
||||
|
@@ -5,11 +5,12 @@ namespace App\Livewire\Project\Shared\EnvironmentVariable;
|
||||
use App\Models\EnvironmentVariable as ModelsEnvironmentVariable;
|
||||
use App\Models\SharedEnvironmentVariable;
|
||||
use App\Traits\EnvironmentVariableProtection;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
use EnvironmentVariableProtection;
|
||||
use AuthorizesRequests, EnvironmentVariableProtection;
|
||||
|
||||
public $parameters;
|
||||
|
||||
@@ -75,6 +76,11 @@ class Show extends Component
|
||||
}
|
||||
}
|
||||
|
||||
public function getResourceProperty()
|
||||
{
|
||||
return $this->env->resourceable ?? $this->env;
|
||||
}
|
||||
|
||||
public function refresh()
|
||||
{
|
||||
$this->syncData();
|
||||
@@ -140,6 +146,8 @@ class Show extends Component
|
||||
|
||||
public function lock()
|
||||
{
|
||||
$this->authorize('update', $this->env);
|
||||
|
||||
$this->env->is_shown_once = true;
|
||||
if ($this->isSharedVariable) {
|
||||
unset($this->env->is_required);
|
||||
@@ -158,6 +166,8 @@ class Show extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->env);
|
||||
|
||||
if (! $this->isSharedVariable && $this->is_required && str($this->value)->isEmpty()) {
|
||||
$oldValue = $this->env->getOriginal('value');
|
||||
$this->value = $oldValue;
|
||||
@@ -179,9 +189,11 @@ class Show extends Component
|
||||
public function delete()
|
||||
{
|
||||
try {
|
||||
$this->authorize('delete', $this->env);
|
||||
|
||||
// Check if the variable is used in Docker Compose
|
||||
if ($this->type === 'service' || $this->type === 'application' && $this->env->resource()?->docker_compose) {
|
||||
[$isUsed, $reason] = $this->isEnvironmentVariableUsedInDockerCompose($this->env->key, $this->env->resource()?->docker_compose);
|
||||
if ($this->type === 'service' || $this->type === 'application' && $this->env->resourceable?->docker_compose) {
|
||||
[$isUsed, $reason] = $this->isEnvironmentVariableUsedInDockerCompose($this->env->key, $this->env->resourceable?->docker_compose);
|
||||
|
||||
if ($isUsed) {
|
||||
$this->dispatch('error', "Cannot delete environment variable '{$this->env->key}' <br><br>Please remove it from the Docker Compose file first.");
|
||||
|
@@ -2,10 +2,13 @@
|
||||
|
||||
namespace App\Livewire\Project\Shared;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class HealthChecks extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $resource;
|
||||
|
||||
protected $rules = [
|
||||
@@ -27,6 +30,7 @@ class HealthChecks extends Component
|
||||
|
||||
public function instantSave()
|
||||
{
|
||||
$this->authorize('update', $this->resource);
|
||||
$this->resource->save();
|
||||
$this->dispatch('success', 'Health check updated.');
|
||||
}
|
||||
@@ -34,6 +38,7 @@ class HealthChecks extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
$this->validate();
|
||||
$this->resource->save();
|
||||
$this->dispatch('success', 'Health check updated.');
|
||||
|
@@ -2,10 +2,13 @@
|
||||
|
||||
namespace App\Livewire\Project\Shared;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class ResourceLimits extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $resource;
|
||||
|
||||
protected $rules = [
|
||||
@@ -31,6 +34,7 @@ class ResourceLimits extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
if (! $this->resource->limits_memory) {
|
||||
$this->resource->limits_memory = '0';
|
||||
}
|
||||
|
@@ -3,12 +3,15 @@
|
||||
namespace App\Livewire\Project\Shared\ScheduledTask;
|
||||
|
||||
use App\Models\ScheduledTask;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Component;
|
||||
|
||||
class Add extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $parameters;
|
||||
|
||||
#[Locked]
|
||||
@@ -20,6 +23,9 @@ class Add extends Component
|
||||
#[Locked]
|
||||
public Collection $containerNames;
|
||||
|
||||
#[Locked]
|
||||
public $resource;
|
||||
|
||||
public string $name;
|
||||
|
||||
public string $command;
|
||||
@@ -45,6 +51,22 @@ class Add extends Component
|
||||
public function mount()
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
|
||||
// Get the resource based on type and id
|
||||
switch ($this->type) {
|
||||
case 'application':
|
||||
$this->resource = \App\Models\Application::findOrFail($this->id);
|
||||
break;
|
||||
case 'service':
|
||||
$this->resource = \App\Models\Service::findOrFail($this->id);
|
||||
break;
|
||||
case 'standalone-postgresql':
|
||||
$this->resource = \App\Models\StandalonePostgresql::findOrFail($this->id);
|
||||
break;
|
||||
default:
|
||||
throw new \Exception('Invalid resource type');
|
||||
}
|
||||
|
||||
if ($this->containerNames->count() > 0) {
|
||||
$this->container = $this->containerNames->first();
|
||||
}
|
||||
@@ -53,6 +75,7 @@ class Add extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
$this->validate();
|
||||
$isValid = validate_cron_expression($this->frequency);
|
||||
if (! $isValid) {
|
||||
|
@@ -6,12 +6,15 @@ use App\Jobs\ScheduledTaskJob;
|
||||
use App\Models\Application;
|
||||
use App\Models\ScheduledTask;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public Application|Service $resource;
|
||||
|
||||
public ScheduledTask $task;
|
||||
@@ -109,6 +112,7 @@ class Show extends Component
|
||||
public function instantSave()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
$this->syncData(true);
|
||||
$this->dispatch('success', 'Scheduled task updated.');
|
||||
$this->refreshTasks();
|
||||
@@ -120,6 +124,7 @@ class Show extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
$this->syncData(true);
|
||||
$this->dispatch('success', 'Scheduled task updated.');
|
||||
} catch (\Exception $e) {
|
||||
@@ -139,6 +144,7 @@ class Show extends Component
|
||||
public function delete()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
$this->task->delete();
|
||||
|
||||
if ($this->type === 'application') {
|
||||
@@ -154,6 +160,7 @@ class Show extends Component
|
||||
public function executeNow()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
ScheduledTaskJob::dispatch($this->task);
|
||||
$this->dispatch('success', 'Scheduled task executed.');
|
||||
} catch (\Exception $e) {
|
||||
|
@@ -4,10 +4,13 @@ namespace App\Livewire\Project\Shared\Storages;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\LocalFileVolume;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Add extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $resource;
|
||||
|
||||
public $uuid;
|
||||
@@ -77,6 +80,8 @@ class Add extends Component
|
||||
public function submitFileStorage()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
$this->validate([
|
||||
'file_storage_path' => 'string',
|
||||
'file_storage_content' => 'nullable|string',
|
||||
@@ -112,6 +117,8 @@ class Add extends Component
|
||||
public function submitFileStorageDirectory()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
$this->validate([
|
||||
'file_storage_directory_source' => 'string',
|
||||
'file_storage_directory_destination' => 'string',
|
||||
@@ -140,6 +147,8 @@ class Add extends Component
|
||||
public function submitPersistentVolume()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
$this->validate([
|
||||
'name' => 'required|string',
|
||||
'mount_path' => 'required|string',
|
||||
|
@@ -4,14 +4,19 @@ namespace App\Livewire\Project\Shared\Storages;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\LocalPersistentVolume;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public LocalPersistentVolume $storage;
|
||||
|
||||
public $resource;
|
||||
|
||||
public bool $isReadOnly = false;
|
||||
|
||||
public bool $isFirst = true;
|
||||
@@ -34,6 +39,8 @@ class Show extends Component
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
$this->validate();
|
||||
$this->storage->save();
|
||||
$this->dispatch('success', 'Storage updated successfully');
|
||||
@@ -41,6 +48,8 @@ class Show extends Component
|
||||
|
||||
public function delete($password)
|
||||
{
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
@@ -3,12 +3,15 @@
|
||||
namespace App\Livewire\Project\Shared;
|
||||
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
// Refactored ✅
|
||||
class Tags extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $resource = null;
|
||||
|
||||
#[Validate('required|string|min:2')]
|
||||
@@ -34,6 +37,7 @@ class Tags extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
$this->validate();
|
||||
$tags = str($this->newTags)->trim()->explode(' ');
|
||||
foreach ($tags as $tag) {
|
||||
@@ -66,6 +70,7 @@ class Tags extends Component
|
||||
public function addTag(string $id, string $name)
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
$name = strip_tags($name);
|
||||
if ($this->resource->tags()->where('id', $id)->exists()) {
|
||||
$this->dispatch('error', 'Duplicate tags.', "Tag <span class='dark:text-warning'>$name</span> already added.");
|
||||
@@ -83,6 +88,7 @@ class Tags extends Component
|
||||
public function deleteTag(string $id)
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
$this->resource->tags()->detach($id);
|
||||
$found_more_tags = Tag::ownedByCurrentTeam()->find($id);
|
||||
if ($found_more_tags && $found_more_tags->applications()->count() == 0 && $found_more_tags->services()->count() == 0) {
|
||||
|
@@ -2,11 +2,14 @@
|
||||
|
||||
namespace App\Livewire\Project\Shared;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
// Refactored ✅
|
||||
class Webhooks extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $resource;
|
||||
|
||||
public ?string $deploywebhook;
|
||||
|
@@ -3,10 +3,14 @@
|
||||
namespace App\Livewire\Security;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Laravel\Sanctum\PersonalAccessToken;
|
||||
use Livewire\Component;
|
||||
|
||||
class ApiTokens extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public ?string $description = null;
|
||||
|
||||
public $tokens = [];
|
||||
@@ -15,6 +19,10 @@ class ApiTokens extends Component
|
||||
|
||||
public $isApiEnabled;
|
||||
|
||||
public bool $canUseRootPermissions = false;
|
||||
|
||||
public bool $canUseWritePermissions = false;
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.security.api-tokens');
|
||||
@@ -23,6 +31,8 @@ class ApiTokens extends Component
|
||||
public function mount()
|
||||
{
|
||||
$this->isApiEnabled = InstanceSettings::get()->is_api_enabled;
|
||||
$this->canUseRootPermissions = auth()->user()->can('useRootPermissions', PersonalAccessToken::class);
|
||||
$this->canUseWritePermissions = auth()->user()->can('useWritePermissions', PersonalAccessToken::class);
|
||||
$this->getTokens();
|
||||
}
|
||||
|
||||
@@ -33,6 +43,23 @@ class ApiTokens extends Component
|
||||
|
||||
public function updatedPermissions($permissionToUpdate)
|
||||
{
|
||||
// Check if user is trying to use restricted permissions
|
||||
if ($permissionToUpdate == 'root' && ! $this->canUseRootPermissions) {
|
||||
$this->dispatch('error', 'You do not have permission to use root permissions.');
|
||||
// Remove root from permissions if it was somehow added
|
||||
$this->permissions = array_diff($this->permissions, ['root']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($permissionToUpdate, ['write', 'write:sensitive']) && ! $this->canUseWritePermissions) {
|
||||
$this->dispatch('error', 'You do not have permission to use write permissions.');
|
||||
// Remove write permissions if they were somehow added
|
||||
$this->permissions = array_diff($this->permissions, ['write', 'write:sensitive']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($permissionToUpdate == 'root') {
|
||||
$this->permissions = ['root'];
|
||||
} elseif ($permissionToUpdate == 'read:sensitive' && ! in_array('read', $this->permissions)) {
|
||||
@@ -50,6 +77,17 @@ class ApiTokens extends Component
|
||||
public function addNewToken()
|
||||
{
|
||||
try {
|
||||
$this->authorize('create', PersonalAccessToken::class);
|
||||
|
||||
// Validate permissions based on user role
|
||||
if (in_array('root', $this->permissions) && ! $this->canUseRootPermissions) {
|
||||
throw new \Exception('You do not have permission to create tokens with root permissions.');
|
||||
}
|
||||
|
||||
if (array_intersect(['write', 'write:sensitive'], $this->permissions) && ! $this->canUseWritePermissions) {
|
||||
throw new \Exception('You do not have permission to create tokens with write permissions.');
|
||||
}
|
||||
|
||||
$this->validate([
|
||||
'description' => 'required|min:3|max:255',
|
||||
]);
|
||||
@@ -65,6 +103,7 @@ class ApiTokens extends Component
|
||||
{
|
||||
try {
|
||||
$token = auth()->user()->tokens()->where('id', $id)->firstOrFail();
|
||||
$this->authorize('delete', $token);
|
||||
$token->delete();
|
||||
$this->getTokens();
|
||||
} catch (\Exception $e) {
|
||||
|
@@ -3,10 +3,13 @@
|
||||
namespace App\Livewire\Security\PrivateKey;
|
||||
|
||||
use App\Models\PrivateKey;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public function render()
|
||||
{
|
||||
$privateKeys = PrivateKey::ownedByCurrentTeam(['name', 'uuid', 'is_git_related', 'description'])->get();
|
||||
@@ -18,6 +21,7 @@ class Index extends Component
|
||||
|
||||
public function cleanupUnusedKeys()
|
||||
{
|
||||
$this->authorize('create', PrivateKey::class);
|
||||
PrivateKey::cleanupUnusedKeys();
|
||||
$this->dispatch('success', 'Unused keys have been cleaned up.');
|
||||
}
|
||||
|
@@ -3,12 +3,17 @@
|
||||
namespace App\Livewire\Server\Proxy;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class DynamicConfigurationNavbar extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $server_id;
|
||||
|
||||
public Server $server;
|
||||
|
||||
public $fileName = '';
|
||||
|
||||
public $value = '';
|
||||
@@ -17,18 +22,18 @@ class DynamicConfigurationNavbar extends Component
|
||||
|
||||
public function delete(string $fileName)
|
||||
{
|
||||
$server = Server::ownedByCurrentTeam()->whereId($this->server_id)->first();
|
||||
$proxy_path = $server->proxyPath();
|
||||
$proxy_type = $server->proxyType();
|
||||
$this->authorize('update', $this->server);
|
||||
$proxy_path = $this->server->proxyPath();
|
||||
$proxy_type = $this->server->proxyType();
|
||||
$file = str_replace('|', '.', $fileName);
|
||||
if ($proxy_type === 'CADDY' && $file === 'Caddyfile') {
|
||||
$this->dispatch('error', 'Cannot delete Caddyfile.');
|
||||
|
||||
return;
|
||||
}
|
||||
instant_remote_process(["rm -f {$proxy_path}/dynamic/{$file}"], $server);
|
||||
instant_remote_process(["rm -f {$proxy_path}/dynamic/{$file}"], $this->server);
|
||||
if ($proxy_type === 'CADDY') {
|
||||
$server->reloadCaddy();
|
||||
$this->server->reloadCaddy();
|
||||
}
|
||||
$this->dispatch('success', 'File deleted.');
|
||||
$this->dispatch('loadDynamicConfigurations');
|
||||
|
@@ -4,10 +4,13 @@ namespace App\Livewire\SharedVariables\Environment;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\Project;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public Project $project;
|
||||
|
||||
public Application $application;
|
||||
@@ -21,6 +24,8 @@ class Show extends Component
|
||||
public function saveKey($data)
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->environment);
|
||||
|
||||
$found = $this->environment->environment_variables()->where('key', $data['key'])->first();
|
||||
if ($found) {
|
||||
throw new \Exception('Variable already exists.');
|
||||
|
@@ -3,10 +3,13 @@
|
||||
namespace App\Livewire\SharedVariables\Project;
|
||||
|
||||
use App\Models\Project;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public Project $project;
|
||||
|
||||
protected $listeners = ['refreshEnvs' => '$refresh', 'saveKey' => 'saveKey', 'environmentVariableDeleted' => '$refresh'];
|
||||
@@ -14,6 +17,8 @@ class Show extends Component
|
||||
public function saveKey($data)
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->project);
|
||||
|
||||
$found = $this->project->environment_variables()->where('key', $data['key'])->first();
|
||||
if ($found) {
|
||||
throw new \Exception('Variable already exists.');
|
||||
|
@@ -3,10 +3,13 @@
|
||||
namespace App\Livewire\SharedVariables\Team;
|
||||
|
||||
use App\Models\Team;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public Team $team;
|
||||
|
||||
protected $listeners = ['refreshEnvs' => '$refresh', 'saveKey' => 'saveKey', 'environmentVariableDeleted' => '$refresh'];
|
||||
@@ -14,6 +17,8 @@ class Index extends Component
|
||||
public function saveKey($data)
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->team);
|
||||
|
||||
$found = $this->team->environment_variables()->where('key', $data['key'])->first();
|
||||
if ($found) {
|
||||
throw new \Exception('Variable already exists.');
|
||||
|
@@ -5,6 +5,7 @@ namespace App\Livewire\Source\Github;
|
||||
use App\Jobs\GithubAppPermissionJob;
|
||||
use App\Models\GithubApp;
|
||||
use App\Models\PrivateKey;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Lcobucci\JWT\Configuration;
|
||||
use Lcobucci\JWT\Signer\Key\InMemory;
|
||||
@@ -13,7 +14,9 @@ use Livewire\Component;
|
||||
|
||||
class Change extends Component
|
||||
{
|
||||
public string $webhook_endpoint;
|
||||
use AuthorizesRequests;
|
||||
|
||||
public string $webhook_endpoint = '';
|
||||
|
||||
public ?string $ipv4 = null;
|
||||
|
||||
@@ -69,6 +72,8 @@ class Change extends Component
|
||||
public function checkPermissions()
|
||||
{
|
||||
try {
|
||||
$this->authorize('view', $this->github_app);
|
||||
|
||||
GithubAppPermissionJob::dispatchSync($this->github_app);
|
||||
$this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||
$this->dispatch('success', 'Github App permissions updated.');
|
||||
@@ -155,7 +160,7 @@ class Change extends Component
|
||||
if (isCloud() && ! isDev()) {
|
||||
$this->webhook_endpoint = config('app.url');
|
||||
} else {
|
||||
$this->webhook_endpoint = $this->ipv4;
|
||||
$this->webhook_endpoint = $this->ipv4 ?? '';
|
||||
$this->is_system_wide = $this->github_app->is_system_wide;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
@@ -195,6 +200,8 @@ class Change extends Component
|
||||
public function updateGithubAppName()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->github_app);
|
||||
|
||||
$privateKey = PrivateKey::ownedByCurrentTeam()->find($this->github_app->private_key_id);
|
||||
|
||||
if (! $privateKey) {
|
||||
@@ -237,6 +244,8 @@ class Change extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->github_app);
|
||||
|
||||
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||
$this->validate([
|
||||
'github_app.name' => 'required|string',
|
||||
@@ -262,6 +271,8 @@ class Change extends Component
|
||||
|
||||
public function createGithubAppManually()
|
||||
{
|
||||
$this->authorize('update', $this->github_app);
|
||||
|
||||
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||
$this->github_app->app_id = '1234567890';
|
||||
$this->github_app->installation_id = '1234567890';
|
||||
@@ -272,6 +283,8 @@ class Change extends Component
|
||||
public function instantSave()
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->github_app);
|
||||
|
||||
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||
$this->github_app->save();
|
||||
$this->dispatch('success', 'Github App updated.');
|
||||
@@ -283,6 +296,8 @@ class Change extends Component
|
||||
public function delete()
|
||||
{
|
||||
try {
|
||||
$this->authorize('delete', $this->github_app);
|
||||
|
||||
if ($this->github_app->applications->isNotEmpty()) {
|
||||
$this->dispatch('error', 'This source is being used by an application. Please delete all applications first.');
|
||||
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||
|
@@ -3,10 +3,13 @@
|
||||
namespace App\Livewire\Source\Github;
|
||||
|
||||
use App\Models\GithubApp;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Create extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public string $name;
|
||||
|
||||
public ?string $organization = null;
|
||||
@@ -29,6 +32,8 @@ class Create extends Component
|
||||
public function createGitHubApp()
|
||||
{
|
||||
try {
|
||||
$this->authorize('createAnyResource');
|
||||
|
||||
$this->validate([
|
||||
'name' => 'required|string',
|
||||
'organization' => 'nullable|string',
|
||||
|
@@ -4,11 +4,14 @@ namespace App\Livewire\Storage;
|
||||
|
||||
use App\Models\S3Storage;
|
||||
use App\Support\ValidationPatterns;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Uri;
|
||||
use Livewire\Component;
|
||||
|
||||
class Create extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public string $name;
|
||||
|
||||
public string $description;
|
||||
@@ -94,6 +97,8 @@ class Create extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->authorize('create', S3Storage::class);
|
||||
|
||||
$this->validate();
|
||||
$this->storage = new S3Storage;
|
||||
$this->storage->name = $this->name;
|
||||
|
@@ -4,10 +4,13 @@ namespace App\Livewire\Storage;
|
||||
|
||||
use App\Models\S3Storage;
|
||||
use App\Support\ValidationPatterns;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Form extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public S3Storage $storage;
|
||||
|
||||
protected function rules(): array
|
||||
@@ -60,6 +63,8 @@ class Form extends Component
|
||||
public function testConnection()
|
||||
{
|
||||
try {
|
||||
$this->authorize('validateConnection', $this->storage);
|
||||
|
||||
$this->storage->testConnection(shouldSave: true);
|
||||
|
||||
return $this->dispatch('success', 'Connection is working.', 'Tested with "ListObjectsV2" action.');
|
||||
@@ -83,8 +88,10 @@ class Form extends Component
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
try {
|
||||
$this->authorize('update', $this->storage);
|
||||
|
||||
$this->validate();
|
||||
$this->testConnection();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
|
@@ -5,12 +5,15 @@ namespace App\Livewire\Team;
|
||||
use App\Models\Team;
|
||||
use App\Models\TeamInvitation;
|
||||
use App\Support\ValidationPatterns;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $invitations = [];
|
||||
|
||||
public Team $team;
|
||||
@@ -58,6 +61,7 @@ class Index extends Component
|
||||
{
|
||||
$this->validate();
|
||||
try {
|
||||
$this->authorize('update', $this->team);
|
||||
$this->team->save();
|
||||
refreshSession();
|
||||
$this->dispatch('success', 'Team updated.');
|
||||
@@ -69,6 +73,7 @@ class Index extends Component
|
||||
public function delete()
|
||||
{
|
||||
$currentTeam = currentTeam();
|
||||
$this->authorize('delete', $currentTeam);
|
||||
$currentTeam->delete();
|
||||
|
||||
$currentTeam->members->each(function ($user) use ($currentTeam) {
|
||||
|
@@ -4,10 +4,13 @@ namespace App\Livewire\Team;
|
||||
|
||||
use App\Models\TeamInvitation;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Invitations extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $invitations;
|
||||
|
||||
protected $listeners = ['refreshInvitations'];
|
||||
@@ -15,6 +18,8 @@ class Invitations extends Component
|
||||
public function deleteInvitation(int $invitation_id)
|
||||
{
|
||||
try {
|
||||
$this->authorize('manageInvitations', currentTeam());
|
||||
|
||||
$invitation = TeamInvitation::ownedByCurrentTeam()->findOrFail($invitation_id);
|
||||
$user = User::whereEmail($invitation->email)->first();
|
||||
if (filled($user)) {
|
||||
|
@@ -4,6 +4,7 @@ namespace App\Livewire\Team;
|
||||
|
||||
use App\Models\TeamInvitation;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
@@ -13,6 +14,8 @@ use Visus\Cuid2\Cuid2;
|
||||
|
||||
class InviteLink extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public string $email;
|
||||
|
||||
public string $role = 'member';
|
||||
@@ -40,6 +43,7 @@ class InviteLink extends Component
|
||||
private function generateInviteLink(bool $sendEmail = false)
|
||||
{
|
||||
try {
|
||||
$this->authorize('manageInvitations', currentTeam());
|
||||
$this->validate();
|
||||
if (auth()->user()->role() === 'admin' && $this->role === 'owner') {
|
||||
throw new \Exception('Admins cannot invite owners.');
|
||||
|
@@ -4,16 +4,21 @@ namespace App\Livewire\Team;
|
||||
|
||||
use App\Enums\Role;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Livewire\Component;
|
||||
|
||||
class Member extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public User $member;
|
||||
|
||||
public function makeAdmin()
|
||||
{
|
||||
try {
|
||||
$this->authorize('manageMembers', currentTeam());
|
||||
|
||||
if (Role::from(auth()->user()->role())->lt(Role::ADMIN)
|
||||
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
||||
throw new \Exception('You are not authorized to perform this action.');
|
||||
@@ -28,6 +33,8 @@ class Member extends Component
|
||||
public function makeOwner()
|
||||
{
|
||||
try {
|
||||
$this->authorize('manageMembers', currentTeam());
|
||||
|
||||
if (Role::from(auth()->user()->role())->lt(Role::OWNER)
|
||||
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
||||
throw new \Exception('You are not authorized to perform this action.');
|
||||
@@ -42,6 +49,8 @@ class Member extends Component
|
||||
public function makeReadonly()
|
||||
{
|
||||
try {
|
||||
$this->authorize('manageMembers', currentTeam());
|
||||
|
||||
if (Role::from(auth()->user()->role())->lt(Role::ADMIN)
|
||||
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
||||
throw new \Exception('You are not authorized to perform this action.');
|
||||
@@ -56,6 +65,8 @@ class Member extends Component
|
||||
public function remove()
|
||||
{
|
||||
try {
|
||||
$this->authorize('manageMembers', currentTeam());
|
||||
|
||||
if (Role::from(auth()->user()->role())->lt(Role::ADMIN)
|
||||
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
||||
throw new \Exception('You are not authorized to perform this action.');
|
||||
|
@@ -3,15 +3,19 @@
|
||||
namespace App\Livewire\Team\Member;
|
||||
|
||||
use App\Models\TeamInvitation;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Component;
|
||||
|
||||
class Index extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $invitations = [];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (auth()->user()->isAdminFromSession()) {
|
||||
// Only load invitations for users who can manage them
|
||||
if (auth()->user()->can('manageInvitations', currentTeam())) {
|
||||
$this->invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get();
|
||||
}
|
||||
}
|
||||
|
@@ -18,7 +18,6 @@ class Index extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->authorize('useTerminal', Server::class);
|
||||
$this->servers = Server::isReachable()->get()->filter(function ($server) {
|
||||
return $server->isTerminalEnabled();
|
||||
});
|
||||
|
Reference in New Issue
Block a user