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:
@@ -72,5 +72,7 @@ class Kernel extends HttpKernel
|
|||||||
'api.ability' => \App\Http\Middleware\ApiAbility::class,
|
'api.ability' => \App\Http\Middleware\ApiAbility::class,
|
||||||
'api.sensitive' => \App\Http\Middleware\ApiSensitiveData::class,
|
'api.sensitive' => \App\Http\Middleware\ApiSensitiveData::class,
|
||||||
'can.create.resources' => \App\Http\Middleware\CanCreateResources::class,
|
'can.create.resources' => \App\Http\Middleware\CanCreateResources::class,
|
||||||
|
'can.update.resource' => \App\Http\Middleware\CanUpdateResource::class,
|
||||||
|
'can.access.terminal' => \App\Http\Middleware\CanAccessTerminal::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
31
app/Http/Middleware/CanAccessTerminal.php
Normal file
31
app/Http/Middleware/CanAccessTerminal.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class CanAccessTerminal
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||||
|
*/
|
||||||
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
{
|
||||||
|
return $next($request);
|
||||||
|
|
||||||
|
// if (! auth()->check()) {
|
||||||
|
// abort(401, 'Authentication required');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Only admins/owners can access terminal functionality
|
||||||
|
// if (! auth()->user()->can('canAccessTerminal')) {
|
||||||
|
// abort(403, 'Access to terminal functionality is restricted to team administrators');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return $next($request);
|
||||||
|
}
|
||||||
|
}
|
@@ -16,10 +16,11 @@ class CanCreateResources
|
|||||||
*/
|
*/
|
||||||
public function handle(Request $request, Closure $next): Response
|
public function handle(Request $request, Closure $next): Response
|
||||||
{
|
{
|
||||||
if (! Gate::allows('createAnyResource')) {
|
|
||||||
abort(403, 'You do not have permission to create resources.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
|
// if (! Gate::allows('createAnyResource')) {
|
||||||
|
// abort(403, 'You do not have permission to create resources.');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return $next($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
75
app/Http/Middleware/CanUpdateResource.php
Normal file
75
app/Http/Middleware/CanUpdateResource.php
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Models\Application;
|
||||||
|
use App\Models\Environment;
|
||||||
|
use App\Models\Project;
|
||||||
|
use App\Models\Service;
|
||||||
|
use App\Models\ServiceApplication;
|
||||||
|
use App\Models\ServiceDatabase;
|
||||||
|
use App\Models\StandaloneClickhouse;
|
||||||
|
use App\Models\StandaloneDragonfly;
|
||||||
|
use App\Models\StandaloneKeydb;
|
||||||
|
use App\Models\StandaloneMariadb;
|
||||||
|
use App\Models\StandaloneMongodb;
|
||||||
|
use App\Models\StandaloneMysql;
|
||||||
|
use App\Models\StandalonePostgresql;
|
||||||
|
use App\Models\StandaloneRedis;
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class CanUpdateResource
|
||||||
|
{
|
||||||
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
{
|
||||||
|
return $next($request);
|
||||||
|
|
||||||
|
// Get resource from route parameters
|
||||||
|
// $resource = null;
|
||||||
|
// if ($request->route('application_uuid')) {
|
||||||
|
// $resource = Application::where('uuid', $request->route('application_uuid'))->first();
|
||||||
|
// } elseif ($request->route('service_uuid')) {
|
||||||
|
// $resource = Service::where('uuid', $request->route('service_uuid'))->first();
|
||||||
|
// } elseif ($request->route('stack_service_uuid')) {
|
||||||
|
// // Handle ServiceApplication or ServiceDatabase
|
||||||
|
// $stack_service_uuid = $request->route('stack_service_uuid');
|
||||||
|
// $resource = ServiceApplication::where('uuid', $stack_service_uuid)->first() ??
|
||||||
|
// ServiceDatabase::where('uuid', $stack_service_uuid)->first();
|
||||||
|
// } elseif ($request->route('database_uuid')) {
|
||||||
|
// // Try different database types
|
||||||
|
// $database_uuid = $request->route('database_uuid');
|
||||||
|
// $resource = StandalonePostgresql::where('uuid', $database_uuid)->first() ??
|
||||||
|
// StandaloneMysql::where('uuid', $database_uuid)->first() ??
|
||||||
|
// StandaloneMariadb::where('uuid', $database_uuid)->first() ??
|
||||||
|
// StandaloneRedis::where('uuid', $database_uuid)->first() ??
|
||||||
|
// StandaloneKeydb::where('uuid', $database_uuid)->first() ??
|
||||||
|
// StandaloneDragonfly::where('uuid', $database_uuid)->first() ??
|
||||||
|
// StandaloneClickhouse::where('uuid', $database_uuid)->first() ??
|
||||||
|
// StandaloneMongodb::where('uuid', $database_uuid)->first();
|
||||||
|
// } elseif ($request->route('server_uuid')) {
|
||||||
|
// // For server routes, check if user can manage servers
|
||||||
|
// if (! auth()->user()->isAdmin()) {
|
||||||
|
// abort(403, 'You do not have permission to access this resource.');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return $next($request);
|
||||||
|
// } elseif ($request->route('environment_uuid')) {
|
||||||
|
// $resource = Environment::where('uuid', $request->route('environment_uuid'))->first();
|
||||||
|
// } elseif ($request->route('project_uuid')) {
|
||||||
|
// $resource = Project::ownedByCurrentTeam()->where('uuid', $request->route('project_uuid'))->first();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (! $resource) {
|
||||||
|
// abort(404, 'Resource not found.');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (! Gate::allows('update', $resource)) {
|
||||||
|
// abort(403, 'You do not have permission to update this resource.');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return $next($request);
|
||||||
|
}
|
||||||
|
}
|
@@ -5,12 +5,15 @@ namespace App\Livewire\Destination;
|
|||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\StandaloneDocker;
|
use App\Models\StandaloneDocker;
|
||||||
use App\Models\SwarmDocker;
|
use App\Models\SwarmDocker;
|
||||||
|
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 Show extends Component
|
class Show extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
#[Locked]
|
#[Locked]
|
||||||
public $destination;
|
public $destination;
|
||||||
|
|
||||||
@@ -63,6 +66,8 @@ class Show extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->destination);
|
||||||
|
|
||||||
$this->syncData(true);
|
$this->syncData(true);
|
||||||
$this->dispatch('success', 'Destination saved.');
|
$this->dispatch('success', 'Destination saved.');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
@@ -73,6 +78,8 @@ class Show extends Component
|
|||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('delete', $this->destination);
|
||||||
|
|
||||||
if ($this->destination->getMorphClass() === \App\Models\StandaloneDocker::class) {
|
if ($this->destination->getMorphClass() === \App\Models\StandaloneDocker::class) {
|
||||||
if ($this->destination->attachedTo()) {
|
if ($this->destination->attachedTo()) {
|
||||||
return $this->dispatch('error', 'You must delete all resources before deleting this destination.');
|
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\DiscordNotificationSettings;
|
||||||
use App\Models\Team;
|
use App\Models\Team;
|
||||||
use App\Notifications\Test;
|
use App\Notifications\Test;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Attributes\Validate;
|
use Livewire\Attributes\Validate;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Discord extends Component
|
class Discord extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public Team $team;
|
public Team $team;
|
||||||
|
|
||||||
public DiscordNotificationSettings $settings;
|
public DiscordNotificationSettings $settings;
|
||||||
@@ -67,6 +70,7 @@ class Discord extends Component
|
|||||||
try {
|
try {
|
||||||
$this->team = auth()->user()->currentTeam();
|
$this->team = auth()->user()->currentTeam();
|
||||||
$this->settings = $this->team->discordNotificationSettings;
|
$this->settings = $this->team->discordNotificationSettings;
|
||||||
|
$this->authorize('view', $this->settings);
|
||||||
$this->syncData();
|
$this->syncData();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
@@ -77,6 +81,7 @@ class Discord extends Component
|
|||||||
{
|
{
|
||||||
if ($toModel) {
|
if ($toModel) {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
$this->authorize('update', $this->settings);
|
||||||
$this->settings->discord_enabled = $this->discordEnabled;
|
$this->settings->discord_enabled = $this->discordEnabled;
|
||||||
$this->settings->discord_webhook_url = $this->discordWebhookUrl;
|
$this->settings->discord_webhook_url = $this->discordWebhookUrl;
|
||||||
|
|
||||||
@@ -182,6 +187,7 @@ class Discord extends Component
|
|||||||
public function sendTestNotification()
|
public function sendTestNotification()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('sendTest', $this->settings);
|
||||||
$this->team->notify(new Test(channel: 'discord'));
|
$this->team->notify(new Test(channel: 'discord'));
|
||||||
$this->dispatch('success', 'Test notification sent.');
|
$this->dispatch('success', 'Test notification sent.');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
|
@@ -5,6 +5,7 @@ namespace App\Livewire\Notifications;
|
|||||||
use App\Models\EmailNotificationSettings;
|
use App\Models\EmailNotificationSettings;
|
||||||
use App\Models\Team;
|
use App\Models\Team;
|
||||||
use App\Notifications\Test;
|
use App\Notifications\Test;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Facades\RateLimiter;
|
use Illuminate\Support\Facades\RateLimiter;
|
||||||
use Livewire\Attributes\Locked;
|
use Livewire\Attributes\Locked;
|
||||||
use Livewire\Attributes\Validate;
|
use Livewire\Attributes\Validate;
|
||||||
@@ -12,6 +13,8 @@ use Livewire\Component;
|
|||||||
|
|
||||||
class Email extends Component
|
class Email extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
protected $listeners = ['refresh' => '$refresh'];
|
protected $listeners = ['refresh' => '$refresh'];
|
||||||
|
|
||||||
#[Locked]
|
#[Locked]
|
||||||
@@ -110,6 +113,7 @@ class Email extends Component
|
|||||||
$this->team = auth()->user()->currentTeam();
|
$this->team = auth()->user()->currentTeam();
|
||||||
$this->emails = auth()->user()->email;
|
$this->emails = auth()->user()->email;
|
||||||
$this->settings = $this->team->emailNotificationSettings;
|
$this->settings = $this->team->emailNotificationSettings;
|
||||||
|
$this->authorize('view', $this->settings);
|
||||||
$this->syncData();
|
$this->syncData();
|
||||||
$this->testEmailAddress = auth()->user()->email;
|
$this->testEmailAddress = auth()->user()->email;
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
@@ -121,6 +125,7 @@ class Email extends Component
|
|||||||
{
|
{
|
||||||
if ($toModel) {
|
if ($toModel) {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
$this->authorize('update', $this->settings);
|
||||||
$this->settings->smtp_enabled = $this->smtpEnabled;
|
$this->settings->smtp_enabled = $this->smtpEnabled;
|
||||||
$this->settings->smtp_from_address = $this->smtpFromAddress;
|
$this->settings->smtp_from_address = $this->smtpFromAddress;
|
||||||
$this->settings->smtp_from_name = $this->smtpFromName;
|
$this->settings->smtp_from_name = $this->smtpFromName;
|
||||||
@@ -311,6 +316,7 @@ class Email extends Component
|
|||||||
public function sendTestEmail()
|
public function sendTestEmail()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('sendTest', $this->settings);
|
||||||
$this->validate([
|
$this->validate([
|
||||||
'testEmailAddress' => 'required|email',
|
'testEmailAddress' => 'required|email',
|
||||||
], [
|
], [
|
||||||
@@ -338,6 +344,7 @@ class Email extends Component
|
|||||||
|
|
||||||
public function copyFromInstanceSettings()
|
public function copyFromInstanceSettings()
|
||||||
{
|
{
|
||||||
|
$this->authorize('update', $this->settings);
|
||||||
$settings = instanceSettings();
|
$settings = instanceSettings();
|
||||||
$this->smtpFromAddress = $settings->smtp_from_address;
|
$this->smtpFromAddress = $settings->smtp_from_address;
|
||||||
$this->smtpFromName = $settings->smtp_from_name;
|
$this->smtpFromName = $settings->smtp_from_name;
|
||||||
|
@@ -5,12 +5,15 @@ namespace App\Livewire\Notifications;
|
|||||||
use App\Models\PushoverNotificationSettings;
|
use App\Models\PushoverNotificationSettings;
|
||||||
use App\Models\Team;
|
use App\Models\Team;
|
||||||
use App\Notifications\Test;
|
use App\Notifications\Test;
|
||||||
|
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 Pushover extends Component
|
class Pushover extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
protected $listeners = ['refresh' => '$refresh'];
|
protected $listeners = ['refresh' => '$refresh'];
|
||||||
|
|
||||||
#[Locked]
|
#[Locked]
|
||||||
@@ -72,6 +75,7 @@ class Pushover extends Component
|
|||||||
try {
|
try {
|
||||||
$this->team = auth()->user()->currentTeam();
|
$this->team = auth()->user()->currentTeam();
|
||||||
$this->settings = $this->team->pushoverNotificationSettings;
|
$this->settings = $this->team->pushoverNotificationSettings;
|
||||||
|
$this->authorize('view', $this->settings);
|
||||||
$this->syncData();
|
$this->syncData();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
@@ -82,6 +86,7 @@ class Pushover extends Component
|
|||||||
{
|
{
|
||||||
if ($toModel) {
|
if ($toModel) {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
$this->authorize('update', $this->settings);
|
||||||
$this->settings->pushover_enabled = $this->pushoverEnabled;
|
$this->settings->pushover_enabled = $this->pushoverEnabled;
|
||||||
$this->settings->pushover_user_key = $this->pushoverUserKey;
|
$this->settings->pushover_user_key = $this->pushoverUserKey;
|
||||||
$this->settings->pushover_api_token = $this->pushoverApiToken;
|
$this->settings->pushover_api_token = $this->pushoverApiToken;
|
||||||
@@ -175,6 +180,7 @@ class Pushover extends Component
|
|||||||
public function sendTestNotification()
|
public function sendTestNotification()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('sendTest', $this->settings);
|
||||||
$this->team->notify(new Test(channel: 'pushover'));
|
$this->team->notify(new Test(channel: 'pushover'));
|
||||||
$this->dispatch('success', 'Test notification sent.');
|
$this->dispatch('success', 'Test notification sent.');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
|
@@ -5,12 +5,15 @@ namespace App\Livewire\Notifications;
|
|||||||
use App\Models\SlackNotificationSettings;
|
use App\Models\SlackNotificationSettings;
|
||||||
use App\Models\Team;
|
use App\Models\Team;
|
||||||
use App\Notifications\Test;
|
use App\Notifications\Test;
|
||||||
|
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 Slack extends Component
|
class Slack extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
protected $listeners = ['refresh' => '$refresh'];
|
protected $listeners = ['refresh' => '$refresh'];
|
||||||
|
|
||||||
#[Locked]
|
#[Locked]
|
||||||
@@ -69,6 +72,7 @@ class Slack extends Component
|
|||||||
try {
|
try {
|
||||||
$this->team = auth()->user()->currentTeam();
|
$this->team = auth()->user()->currentTeam();
|
||||||
$this->settings = $this->team->slackNotificationSettings;
|
$this->settings = $this->team->slackNotificationSettings;
|
||||||
|
$this->authorize('view', $this->settings);
|
||||||
$this->syncData();
|
$this->syncData();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
@@ -79,6 +83,7 @@ class Slack extends Component
|
|||||||
{
|
{
|
||||||
if ($toModel) {
|
if ($toModel) {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
$this->authorize('update', $this->settings);
|
||||||
$this->settings->slack_enabled = $this->slackEnabled;
|
$this->settings->slack_enabled = $this->slackEnabled;
|
||||||
$this->settings->slack_webhook_url = $this->slackWebhookUrl;
|
$this->settings->slack_webhook_url = $this->slackWebhookUrl;
|
||||||
|
|
||||||
@@ -168,6 +173,7 @@ class Slack extends Component
|
|||||||
public function sendTestNotification()
|
public function sendTestNotification()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('sendTest', $this->settings);
|
||||||
$this->team->notify(new Test(channel: 'slack'));
|
$this->team->notify(new Test(channel: 'slack'));
|
||||||
$this->dispatch('success', 'Test notification sent.');
|
$this->dispatch('success', 'Test notification sent.');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
|
@@ -5,12 +5,15 @@ namespace App\Livewire\Notifications;
|
|||||||
use App\Models\Team;
|
use App\Models\Team;
|
||||||
use App\Models\TelegramNotificationSettings;
|
use App\Models\TelegramNotificationSettings;
|
||||||
use App\Notifications\Test;
|
use App\Notifications\Test;
|
||||||
|
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 Telegram extends Component
|
class Telegram extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
protected $listeners = ['refresh' => '$refresh'];
|
protected $listeners = ['refresh' => '$refresh'];
|
||||||
|
|
||||||
#[Locked]
|
#[Locked]
|
||||||
@@ -111,6 +114,7 @@ class Telegram extends Component
|
|||||||
try {
|
try {
|
||||||
$this->team = auth()->user()->currentTeam();
|
$this->team = auth()->user()->currentTeam();
|
||||||
$this->settings = $this->team->telegramNotificationSettings;
|
$this->settings = $this->team->telegramNotificationSettings;
|
||||||
|
$this->authorize('view', $this->settings);
|
||||||
$this->syncData();
|
$this->syncData();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
@@ -121,6 +125,7 @@ class Telegram extends Component
|
|||||||
{
|
{
|
||||||
if ($toModel) {
|
if ($toModel) {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
$this->authorize('update', $this->settings);
|
||||||
$this->settings->telegram_enabled = $this->telegramEnabled;
|
$this->settings->telegram_enabled = $this->telegramEnabled;
|
||||||
$this->settings->telegram_token = $this->telegramToken;
|
$this->settings->telegram_token = $this->telegramToken;
|
||||||
$this->settings->telegram_chat_id = $this->telegramChatId;
|
$this->settings->telegram_chat_id = $this->telegramChatId;
|
||||||
@@ -241,6 +246,7 @@ class Telegram extends Component
|
|||||||
public function sendTestNotification()
|
public function sendTestNotification()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('sendTest', $this->settings);
|
||||||
$this->team->notify(new Test(channel: 'telegram'));
|
$this->team->notify(new Test(channel: 'telegram'));
|
||||||
$this->dispatch('success', 'Test notification sent.');
|
$this->dispatch('success', 'Test notification sent.');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
|
@@ -3,12 +3,15 @@
|
|||||||
namespace App\Livewire\Project\Application\Preview;
|
namespace App\Livewire\Project\Application\Preview;
|
||||||
|
|
||||||
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;
|
||||||
use Spatie\Url\Url;
|
use Spatie\Url\Url;
|
||||||
|
|
||||||
class Form extends Component
|
class Form extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public Application $application;
|
public Application $application;
|
||||||
|
|
||||||
#[Validate('required')]
|
#[Validate('required')]
|
||||||
@@ -27,6 +30,7 @@ class Form extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
$this->resetErrorBag();
|
$this->resetErrorBag();
|
||||||
$this->validate();
|
$this->validate();
|
||||||
$this->application->preview_url_template = str_replace(' ', '', $this->previewUrlTemplate);
|
$this->application->preview_url_template = str_replace(' ', '', $this->previewUrlTemplate);
|
||||||
@@ -41,6 +45,7 @@ class Form extends Component
|
|||||||
public function resetToDefault()
|
public function resetToDefault()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
$this->application->preview_url_template = '{{pr_id}}.{{domain}}';
|
$this->application->preview_url_template = '{{pr_id}}.{{domain}}';
|
||||||
$this->previewUrlTemplate = $this->application->preview_url_template;
|
$this->previewUrlTemplate = $this->application->preview_url_template;
|
||||||
$this->application->save();
|
$this->application->save();
|
||||||
|
@@ -38,6 +38,7 @@ class Previews extends Component
|
|||||||
public function load_prs()
|
public function load_prs()
|
||||||
{
|
{
|
||||||
try {
|
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");
|
['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->rate_limit_remaining = $rate_limit_remaining;
|
||||||
$this->pull_requests = $data->sortBy('number')->values();
|
$this->pull_requests = $data->sortBy('number')->values();
|
||||||
|
@@ -176,6 +176,7 @@ EOD;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
$this->importRunning = true;
|
||||||
$this->importCommands = [];
|
$this->importCommands = [];
|
||||||
if (filled($this->customLocation)) {
|
if (filled($this->customLocation)) {
|
||||||
$backupFileName = '/tmp/restore_'.$this->resource->uuid;
|
$backupFileName = '/tmp/restore_'.$this->resource->uuid;
|
||||||
|
@@ -20,6 +20,7 @@ class Index extends Component
|
|||||||
$this->private_keys = PrivateKey::ownedByCurrentTeam()->get();
|
$this->private_keys = PrivateKey::ownedByCurrentTeam()->get();
|
||||||
$this->projects = Project::ownedByCurrentTeam()->get()->map(function ($project) {
|
$this->projects = Project::ownedByCurrentTeam()->get()->map(function ($project) {
|
||||||
$project->settingsRoute = route('project.edit', ['project_uuid' => $project->uuid]);
|
$project->settingsRoute = route('project.edit', ['project_uuid' => $project->uuid]);
|
||||||
|
$project->canUpdate = auth()->user()->can('update', $project);
|
||||||
|
|
||||||
return $project;
|
return $project;
|
||||||
});
|
});
|
||||||
|
@@ -3,11 +3,14 @@
|
|||||||
namespace App\Livewire\Project\Service;
|
namespace App\Livewire\Project\Service;
|
||||||
|
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Configuration extends Component
|
class Configuration extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $currentRoute;
|
public $currentRoute;
|
||||||
|
|
||||||
public $project;
|
public $project;
|
||||||
@@ -40,24 +43,30 @@ class Configuration extends Component
|
|||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
$this->parameters = get_route_parameters();
|
try {
|
||||||
$this->currentRoute = request()->route()->getName();
|
$this->parameters = get_route_parameters();
|
||||||
$this->query = request()->query();
|
$this->currentRoute = request()->route()->getName();
|
||||||
$project = currentTeam()
|
$this->query = request()->query();
|
||||||
->projects()
|
$project = currentTeam()
|
||||||
->select('id', 'uuid', 'team_id')
|
->projects()
|
||||||
->where('uuid', request()->route('project_uuid'))
|
->select('id', 'uuid', 'team_id')
|
||||||
->firstOrFail();
|
->where('uuid', request()->route('project_uuid'))
|
||||||
$environment = $project->environments()
|
->firstOrFail();
|
||||||
->select('id', 'uuid', 'name', 'project_id')
|
$environment = $project->environments()
|
||||||
->where('uuid', request()->route('environment_uuid'))
|
->select('id', 'uuid', 'name', 'project_id')
|
||||||
->firstOrFail();
|
->where('uuid', request()->route('environment_uuid'))
|
||||||
$this->service = $environment->services()->whereUuid(request()->route('service_uuid'))->firstOrFail();
|
->firstOrFail();
|
||||||
|
$this->service = $environment->services()->whereUuid(request()->route('service_uuid'))->firstOrFail();
|
||||||
|
|
||||||
$this->project = $project;
|
$this->authorize('view', $this->service);
|
||||||
$this->environment = $environment;
|
|
||||||
$this->applications = $this->service->applications->sort();
|
$this->project = $project;
|
||||||
$this->databases = $this->service->databases->sort();
|
$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()
|
public function refreshServices()
|
||||||
@@ -70,6 +79,7 @@ class Configuration extends Component
|
|||||||
public function restartApplication($id)
|
public function restartApplication($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->service);
|
||||||
$application = $this->service->applications->find($id);
|
$application = $this->service->applications->find($id);
|
||||||
if ($application) {
|
if ($application) {
|
||||||
$application->restart();
|
$application->restart();
|
||||||
@@ -83,6 +93,7 @@ class Configuration extends Component
|
|||||||
public function restartDatabase($id)
|
public function restartDatabase($id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->service);
|
||||||
$database = $this->service->databases->find($id);
|
$database = $this->service->databases->find($id);
|
||||||
if ($database) {
|
if ($database) {
|
||||||
$database->restart();
|
$database->restart();
|
||||||
|
@@ -6,6 +6,7 @@ use App\Actions\Database\StartDatabaseProxy;
|
|||||||
use App\Actions\Database\StopDatabaseProxy;
|
use App\Actions\Database\StopDatabaseProxy;
|
||||||
use App\Models\InstanceSettings;
|
use App\Models\InstanceSettings;
|
||||||
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\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
@@ -13,6 +14,8 @@ use Livewire\Component;
|
|||||||
|
|
||||||
class Database extends Component
|
class Database extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public ServiceDatabase $database;
|
public ServiceDatabase $database;
|
||||||
|
|
||||||
public ?string $db_url_public = null;
|
public ?string $db_url_public = null;
|
||||||
@@ -40,24 +43,31 @@ class Database extends Component
|
|||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
$this->parameters = get_route_parameters();
|
try {
|
||||||
if ($this->database->is_public) {
|
$this->parameters = get_route_parameters();
|
||||||
$this->db_url_public = $this->database->getServiceDatabaseUrl();
|
$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)
|
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 {
|
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->database->delete();
|
||||||
$this->dispatch('success', 'Database deleted.');
|
$this->dispatch('success', 'Database deleted.');
|
||||||
|
|
||||||
@@ -69,24 +79,35 @@ class Database extends Component
|
|||||||
|
|
||||||
public function instantSaveExclude()
|
public function instantSaveExclude()
|
||||||
{
|
{
|
||||||
$this->submit();
|
try {
|
||||||
|
$this->authorize('update', $this->database);
|
||||||
|
$this->submit();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function instantSaveLogDrain()
|
public function instantSaveLogDrain()
|
||||||
{
|
{
|
||||||
if (! $this->database->service->destination->server->isLogDrainEnabled()) {
|
try {
|
||||||
$this->database->is_log_drain_enabled = false;
|
$this->authorize('update', $this->database);
|
||||||
$this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.');
|
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()
|
public function convertToApplication()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->database);
|
||||||
$service = $this->database->service;
|
$service = $this->database->service;
|
||||||
$serviceDatabase = $this->database;
|
$serviceDatabase = $this->database;
|
||||||
|
|
||||||
@@ -122,28 +143,33 @@ class Database extends Component
|
|||||||
|
|
||||||
public function instantSave()
|
public function instantSave()
|
||||||
{
|
{
|
||||||
if ($this->database->is_public && ! $this->database->public_port) {
|
try {
|
||||||
$this->dispatch('error', 'Public port is required.');
|
$this->authorize('update', $this->database);
|
||||||
$this->database->is_public = false;
|
if ($this->database->is_public && ! $this->database->public_port) {
|
||||||
|
$this->dispatch('error', 'Public port is required.');
|
||||||
return;
|
|
||||||
}
|
|
||||||
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;
|
$this->database->is_public = false;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
StartDatabaseProxy::run($this->database);
|
if ($this->database->is_public) {
|
||||||
$this->db_url_public = $this->database->getServiceDatabaseUrl();
|
if (! str($this->database->status)->startsWith('running')) {
|
||||||
$this->dispatch('success', 'Database is now publicly accessible.');
|
$this->dispatch('error', 'Database must be started to be publicly accessible.');
|
||||||
} else {
|
$this->database->is_public = false;
|
||||||
StopDatabaseProxy::run($this->database);
|
|
||||||
$this->db_url_public = null;
|
return;
|
||||||
$this->dispatch('success', 'Database is no longer publicly accessible.');
|
}
|
||||||
|
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()
|
public function refreshFileStorages()
|
||||||
@@ -154,11 +180,13 @@ class Database extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->database);
|
||||||
$this->validate();
|
$this->validate();
|
||||||
$this->database->save();
|
$this->database->save();
|
||||||
updateCompose($this->database);
|
updateCompose($this->database);
|
||||||
$this->dispatch('success', 'Database saved.');
|
$this->dispatch('success', 'Database saved.');
|
||||||
} catch (\Throwable) {
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
} finally {
|
} finally {
|
||||||
$this->dispatch('generateDockerCompose');
|
$this->dispatch('generateDockerCompose');
|
||||||
}
|
}
|
||||||
|
@@ -15,12 +15,15 @@ use App\Models\StandaloneMongodb;
|
|||||||
use App\Models\StandaloneMysql;
|
use App\Models\StandaloneMysql;
|
||||||
use App\Models\StandalonePostgresql;
|
use App\Models\StandalonePostgresql;
|
||||||
use App\Models\StandaloneRedis;
|
use App\Models\StandaloneRedis;
|
||||||
|
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;
|
||||||
|
|
||||||
class FileStorage extends Component
|
class FileStorage extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public LocalFileVolume $fileStorage;
|
public LocalFileVolume $fileStorage;
|
||||||
|
|
||||||
public ServiceApplication|StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse|ServiceDatabase|Application $resource;
|
public ServiceApplication|StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse|ServiceDatabase|Application $resource;
|
||||||
@@ -54,6 +57,8 @@ class FileStorage extends Component
|
|||||||
public function convertToDirectory()
|
public function convertToDirectory()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
$this->fileStorage->deleteStorageOnServer();
|
$this->fileStorage->deleteStorageOnServer();
|
||||||
$this->fileStorage->is_directory = true;
|
$this->fileStorage->is_directory = true;
|
||||||
$this->fileStorage->content = null;
|
$this->fileStorage->content = null;
|
||||||
@@ -70,6 +75,8 @@ class FileStorage extends Component
|
|||||||
public function loadStorageOnServer()
|
public function loadStorageOnServer()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
$this->fileStorage->loadStorageOnServer();
|
$this->fileStorage->loadStorageOnServer();
|
||||||
$this->dispatch('success', 'File storage loaded from server.');
|
$this->dispatch('success', 'File storage loaded from server.');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
@@ -82,6 +89,8 @@ class FileStorage extends Component
|
|||||||
public function convertToFile()
|
public function convertToFile()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
$this->fileStorage->deleteStorageOnServer();
|
$this->fileStorage->deleteStorageOnServer();
|
||||||
$this->fileStorage->is_directory = false;
|
$this->fileStorage->is_directory = false;
|
||||||
$this->fileStorage->content = null;
|
$this->fileStorage->content = null;
|
||||||
@@ -99,6 +108,8 @@ class FileStorage extends Component
|
|||||||
|
|
||||||
public function delete($password)
|
public function delete($password)
|
||||||
{
|
{
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||||
if (! Hash::check($password, Auth::user()->password)) {
|
if (! Hash::check($password, Auth::user()->password)) {
|
||||||
$this->addError('password', 'The provided password is incorrect.');
|
$this->addError('password', 'The provided password is incorrect.');
|
||||||
@@ -127,6 +138,8 @@ class FileStorage extends Component
|
|||||||
|
|
||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
$original = $this->fileStorage->getOriginal();
|
$original = $this->fileStorage->getOriginal();
|
||||||
try {
|
try {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
@@ -5,11 +5,14 @@ namespace App\Livewire\Project\Service;
|
|||||||
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\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Index extends Component
|
class Index extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public ?Service $service = null;
|
public ?Service $service = null;
|
||||||
|
|
||||||
public ?ServiceApplication $serviceApplication = null;
|
public ?ServiceApplication $serviceApplication = null;
|
||||||
@@ -36,6 +39,7 @@ class Index extends Component
|
|||||||
if (! $this->service) {
|
if (! $this->service) {
|
||||||
return redirect()->route('dashboard');
|
return redirect()->route('dashboard');
|
||||||
}
|
}
|
||||||
|
$this->authorize('view', $this->service);
|
||||||
$service = $this->service->applications()->whereUuid($this->parameters['stack_service_uuid'])->first();
|
$service = $this->service->applications()->whereUuid($this->parameters['stack_service_uuid'])->first();
|
||||||
if ($service) {
|
if ($service) {
|
||||||
$this->serviceApplication = $service;
|
$this->serviceApplication = $service;
|
||||||
@@ -52,7 +56,12 @@ class Index extends Component
|
|||||||
|
|
||||||
public function generateDockerCompose()
|
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()
|
public function render()
|
||||||
|
@@ -4,6 +4,7 @@ namespace App\Livewire\Project\Service;
|
|||||||
|
|
||||||
use App\Models\InstanceSettings;
|
use App\Models\InstanceSettings;
|
||||||
use App\Models\ServiceApplication;
|
use App\Models\ServiceApplication;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
@@ -12,6 +13,8 @@ use Spatie\Url\Url;
|
|||||||
|
|
||||||
class ServiceApplicationView extends Component
|
class ServiceApplicationView extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public ServiceApplication $application;
|
public ServiceApplication $application;
|
||||||
|
|
||||||
public $parameters;
|
public $parameters;
|
||||||
@@ -34,32 +37,44 @@ class ServiceApplicationView extends Component
|
|||||||
|
|
||||||
public function instantSave()
|
public function instantSave()
|
||||||
{
|
{
|
||||||
$this->submit();
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
|
$this->submit();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function instantSaveAdvanced()
|
public function instantSaveAdvanced()
|
||||||
{
|
{
|
||||||
if (! $this->application->service->destination->server->isLogDrainEnabled()) {
|
try {
|
||||||
$this->application->is_log_drain_enabled = false;
|
$this->authorize('update', $this->application);
|
||||||
$this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.');
|
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)
|
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 {
|
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->application->delete();
|
||||||
$this->dispatch('success', 'Application deleted.');
|
$this->dispatch('success', 'Application deleted.');
|
||||||
|
|
||||||
@@ -71,12 +86,18 @@ class ServiceApplicationView extends Component
|
|||||||
|
|
||||||
public function mount()
|
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()
|
public function convertToDatabase()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->application);
|
||||||
$service = $this->application->service;
|
$service = $this->application->service;
|
||||||
$serviceApplication = $this->application;
|
$serviceApplication = $this->application;
|
||||||
|
|
||||||
@@ -111,6 +132,7 @@ class ServiceApplicationView extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
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) {
|
||||||
|
@@ -3,10 +3,13 @@
|
|||||||
namespace App\Livewire\Project\Service;
|
namespace App\Livewire\Project\Service;
|
||||||
|
|
||||||
use App\Models\LocalPersistentVolume;
|
use App\Models\LocalPersistentVolume;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Storage extends Component
|
class Storage extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $resource;
|
public $resource;
|
||||||
|
|
||||||
public $fileStorage;
|
public $fileStorage;
|
||||||
@@ -42,6 +45,8 @@ class Storage extends Component
|
|||||||
public function addNewVolume($data)
|
public function addNewVolume($data)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
LocalPersistentVolume::create([
|
LocalPersistentVolume::create([
|
||||||
'name' => $data['name'],
|
'name' => $data['name'],
|
||||||
'mount_path' => $data['mount_path'],
|
'mount_path' => $data['mount_path'],
|
||||||
|
@@ -2,10 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Livewire\Project\Shared\EnvironmentVariable;
|
namespace App\Livewire\Project\Shared\EnvironmentVariable;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Add extends Component
|
class Add extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $parameters;
|
public $parameters;
|
||||||
|
|
||||||
public bool $shared = false;
|
public bool $shared = false;
|
||||||
|
@@ -5,11 +5,12 @@ namespace App\Livewire\Project\Shared\EnvironmentVariable;
|
|||||||
use App\Models\EnvironmentVariable as ModelsEnvironmentVariable;
|
use App\Models\EnvironmentVariable as ModelsEnvironmentVariable;
|
||||||
use App\Models\SharedEnvironmentVariable;
|
use App\Models\SharedEnvironmentVariable;
|
||||||
use App\Traits\EnvironmentVariableProtection;
|
use App\Traits\EnvironmentVariableProtection;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Show extends Component
|
class Show extends Component
|
||||||
{
|
{
|
||||||
use EnvironmentVariableProtection;
|
use AuthorizesRequests, EnvironmentVariableProtection;
|
||||||
|
|
||||||
public $parameters;
|
public $parameters;
|
||||||
|
|
||||||
@@ -75,6 +76,11 @@ class Show extends Component
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getResourceProperty()
|
||||||
|
{
|
||||||
|
return $this->env->resourceable ?? $this->env;
|
||||||
|
}
|
||||||
|
|
||||||
public function refresh()
|
public function refresh()
|
||||||
{
|
{
|
||||||
$this->syncData();
|
$this->syncData();
|
||||||
@@ -140,6 +146,8 @@ class Show extends Component
|
|||||||
|
|
||||||
public function lock()
|
public function lock()
|
||||||
{
|
{
|
||||||
|
$this->authorize('update', $this->env);
|
||||||
|
|
||||||
$this->env->is_shown_once = true;
|
$this->env->is_shown_once = true;
|
||||||
if ($this->isSharedVariable) {
|
if ($this->isSharedVariable) {
|
||||||
unset($this->env->is_required);
|
unset($this->env->is_required);
|
||||||
@@ -158,6 +166,8 @@ class Show extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->env);
|
||||||
|
|
||||||
if (! $this->isSharedVariable && $this->is_required && str($this->value)->isEmpty()) {
|
if (! $this->isSharedVariable && $this->is_required && str($this->value)->isEmpty()) {
|
||||||
$oldValue = $this->env->getOriginal('value');
|
$oldValue = $this->env->getOriginal('value');
|
||||||
$this->value = $oldValue;
|
$this->value = $oldValue;
|
||||||
@@ -179,9 +189,11 @@ class Show extends Component
|
|||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('delete', $this->env);
|
||||||
|
|
||||||
// Check if the variable is used in Docker Compose
|
// Check if the variable is used in Docker Compose
|
||||||
if ($this->type === 'service' || $this->type === 'application' && $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->resource()?->docker_compose);
|
[$isUsed, $reason] = $this->isEnvironmentVariableUsedInDockerCompose($this->env->key, $this->env->resourceable?->docker_compose);
|
||||||
|
|
||||||
if ($isUsed) {
|
if ($isUsed) {
|
||||||
$this->dispatch('error', "Cannot delete environment variable '{$this->env->key}' <br><br>Please remove it from the Docker Compose file first.");
|
$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;
|
namespace App\Livewire\Project\Shared;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class HealthChecks extends Component
|
class HealthChecks extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $resource;
|
public $resource;
|
||||||
|
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
@@ -27,6 +30,7 @@ class HealthChecks extends Component
|
|||||||
|
|
||||||
public function instantSave()
|
public function instantSave()
|
||||||
{
|
{
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
$this->resource->save();
|
$this->resource->save();
|
||||||
$this->dispatch('success', 'Health check updated.');
|
$this->dispatch('success', 'Health check updated.');
|
||||||
}
|
}
|
||||||
@@ -34,6 +38,7 @@ class HealthChecks extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
$this->validate();
|
$this->validate();
|
||||||
$this->resource->save();
|
$this->resource->save();
|
||||||
$this->dispatch('success', 'Health check updated.');
|
$this->dispatch('success', 'Health check updated.');
|
||||||
|
@@ -2,10 +2,13 @@
|
|||||||
|
|
||||||
namespace App\Livewire\Project\Shared;
|
namespace App\Livewire\Project\Shared;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class ResourceLimits extends Component
|
class ResourceLimits extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $resource;
|
public $resource;
|
||||||
|
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
@@ -31,6 +34,7 @@ class ResourceLimits extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
if (! $this->resource->limits_memory) {
|
if (! $this->resource->limits_memory) {
|
||||||
$this->resource->limits_memory = '0';
|
$this->resource->limits_memory = '0';
|
||||||
}
|
}
|
||||||
|
@@ -3,12 +3,15 @@
|
|||||||
namespace App\Livewire\Project\Shared\ScheduledTask;
|
namespace App\Livewire\Project\Shared\ScheduledTask;
|
||||||
|
|
||||||
use App\Models\ScheduledTask;
|
use App\Models\ScheduledTask;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Livewire\Attributes\Locked;
|
use Livewire\Attributes\Locked;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Add extends Component
|
class Add extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $parameters;
|
public $parameters;
|
||||||
|
|
||||||
#[Locked]
|
#[Locked]
|
||||||
@@ -20,6 +23,9 @@ class Add extends Component
|
|||||||
#[Locked]
|
#[Locked]
|
||||||
public Collection $containerNames;
|
public Collection $containerNames;
|
||||||
|
|
||||||
|
#[Locked]
|
||||||
|
public $resource;
|
||||||
|
|
||||||
public string $name;
|
public string $name;
|
||||||
|
|
||||||
public string $command;
|
public string $command;
|
||||||
@@ -45,6 +51,22 @@ class Add extends Component
|
|||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
$this->parameters = get_route_parameters();
|
$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) {
|
if ($this->containerNames->count() > 0) {
|
||||||
$this->container = $this->containerNames->first();
|
$this->container = $this->containerNames->first();
|
||||||
}
|
}
|
||||||
@@ -53,6 +75,7 @@ class Add extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
$this->validate();
|
$this->validate();
|
||||||
$isValid = validate_cron_expression($this->frequency);
|
$isValid = validate_cron_expression($this->frequency);
|
||||||
if (! $isValid) {
|
if (! $isValid) {
|
||||||
|
@@ -6,12 +6,15 @@ use App\Jobs\ScheduledTaskJob;
|
|||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Models\ScheduledTask;
|
use App\Models\ScheduledTask;
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
|
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 Show extends Component
|
class Show extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public Application|Service $resource;
|
public Application|Service $resource;
|
||||||
|
|
||||||
public ScheduledTask $task;
|
public ScheduledTask $task;
|
||||||
@@ -109,6 +112,7 @@ class Show extends Component
|
|||||||
public function instantSave()
|
public function instantSave()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
$this->syncData(true);
|
$this->syncData(true);
|
||||||
$this->dispatch('success', 'Scheduled task updated.');
|
$this->dispatch('success', 'Scheduled task updated.');
|
||||||
$this->refreshTasks();
|
$this->refreshTasks();
|
||||||
@@ -120,6 +124,7 @@ class Show extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
$this->syncData(true);
|
$this->syncData(true);
|
||||||
$this->dispatch('success', 'Scheduled task updated.');
|
$this->dispatch('success', 'Scheduled task updated.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@@ -139,6 +144,7 @@ class Show extends Component
|
|||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
$this->task->delete();
|
$this->task->delete();
|
||||||
|
|
||||||
if ($this->type === 'application') {
|
if ($this->type === 'application') {
|
||||||
@@ -154,6 +160,7 @@ class Show extends Component
|
|||||||
public function executeNow()
|
public function executeNow()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
ScheduledTaskJob::dispatch($this->task);
|
ScheduledTaskJob::dispatch($this->task);
|
||||||
$this->dispatch('success', 'Scheduled task executed.');
|
$this->dispatch('success', 'Scheduled task executed.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
@@ -4,10 +4,13 @@ namespace App\Livewire\Project\Shared\Storages;
|
|||||||
|
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Models\LocalFileVolume;
|
use App\Models\LocalFileVolume;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Add extends Component
|
class Add extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $resource;
|
public $resource;
|
||||||
|
|
||||||
public $uuid;
|
public $uuid;
|
||||||
@@ -77,6 +80,8 @@ class Add extends Component
|
|||||||
public function submitFileStorage()
|
public function submitFileStorage()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
$this->validate([
|
$this->validate([
|
||||||
'file_storage_path' => 'string',
|
'file_storage_path' => 'string',
|
||||||
'file_storage_content' => 'nullable|string',
|
'file_storage_content' => 'nullable|string',
|
||||||
@@ -112,6 +117,8 @@ class Add extends Component
|
|||||||
public function submitFileStorageDirectory()
|
public function submitFileStorageDirectory()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
$this->validate([
|
$this->validate([
|
||||||
'file_storage_directory_source' => 'string',
|
'file_storage_directory_source' => 'string',
|
||||||
'file_storage_directory_destination' => 'string',
|
'file_storage_directory_destination' => 'string',
|
||||||
@@ -140,6 +147,8 @@ class Add extends Component
|
|||||||
public function submitPersistentVolume()
|
public function submitPersistentVolume()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
$this->validate([
|
$this->validate([
|
||||||
'name' => 'required|string',
|
'name' => 'required|string',
|
||||||
'mount_path' => 'required|string',
|
'mount_path' => 'required|string',
|
||||||
|
@@ -4,14 +4,19 @@ namespace App\Livewire\Project\Shared\Storages;
|
|||||||
|
|
||||||
use App\Models\InstanceSettings;
|
use App\Models\InstanceSettings;
|
||||||
use App\Models\LocalPersistentVolume;
|
use App\Models\LocalPersistentVolume;
|
||||||
|
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;
|
||||||
|
|
||||||
class Show extends Component
|
class Show extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public LocalPersistentVolume $storage;
|
public LocalPersistentVolume $storage;
|
||||||
|
|
||||||
|
public $resource;
|
||||||
|
|
||||||
public bool $isReadOnly = false;
|
public bool $isReadOnly = false;
|
||||||
|
|
||||||
public bool $isFirst = true;
|
public bool $isFirst = true;
|
||||||
@@ -34,6 +39,8 @@ class Show extends Component
|
|||||||
|
|
||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
$this->validate();
|
$this->validate();
|
||||||
$this->storage->save();
|
$this->storage->save();
|
||||||
$this->dispatch('success', 'Storage updated successfully');
|
$this->dispatch('success', 'Storage updated successfully');
|
||||||
@@ -41,6 +48,8 @@ class Show extends Component
|
|||||||
|
|
||||||
public function delete($password)
|
public function delete($password)
|
||||||
{
|
{
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
|
|
||||||
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) {
|
||||||
if (! Hash::check($password, Auth::user()->password)) {
|
if (! Hash::check($password, Auth::user()->password)) {
|
||||||
$this->addError('password', 'The provided password is incorrect.');
|
$this->addError('password', 'The provided password is incorrect.');
|
||||||
|
@@ -3,12 +3,15 @@
|
|||||||
namespace App\Livewire\Project\Shared;
|
namespace App\Livewire\Project\Shared;
|
||||||
|
|
||||||
use App\Models\Tag;
|
use App\Models\Tag;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Attributes\Validate;
|
use Livewire\Attributes\Validate;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
// Refactored ✅
|
// Refactored ✅
|
||||||
class Tags extends Component
|
class Tags extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $resource = null;
|
public $resource = null;
|
||||||
|
|
||||||
#[Validate('required|string|min:2')]
|
#[Validate('required|string|min:2')]
|
||||||
@@ -34,6 +37,7 @@ class Tags extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
$this->validate();
|
$this->validate();
|
||||||
$tags = str($this->newTags)->trim()->explode(' ');
|
$tags = str($this->newTags)->trim()->explode(' ');
|
||||||
foreach ($tags as $tag) {
|
foreach ($tags as $tag) {
|
||||||
@@ -66,6 +70,7 @@ class Tags extends Component
|
|||||||
public function addTag(string $id, string $name)
|
public function addTag(string $id, string $name)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
$name = strip_tags($name);
|
$name = strip_tags($name);
|
||||||
if ($this->resource->tags()->where('id', $id)->exists()) {
|
if ($this->resource->tags()->where('id', $id)->exists()) {
|
||||||
$this->dispatch('error', 'Duplicate tags.', "Tag <span class='dark:text-warning'>$name</span> already added.");
|
$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)
|
public function deleteTag(string $id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->resource);
|
||||||
$this->resource->tags()->detach($id);
|
$this->resource->tags()->detach($id);
|
||||||
$found_more_tags = Tag::ownedByCurrentTeam()->find($id);
|
$found_more_tags = Tag::ownedByCurrentTeam()->find($id);
|
||||||
if ($found_more_tags && $found_more_tags->applications()->count() == 0 && $found_more_tags->services()->count() == 0) {
|
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;
|
namespace App\Livewire\Project\Shared;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
// Refactored ✅
|
// Refactored ✅
|
||||||
class Webhooks extends Component
|
class Webhooks extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $resource;
|
public $resource;
|
||||||
|
|
||||||
public ?string $deploywebhook;
|
public ?string $deploywebhook;
|
||||||
|
@@ -3,10 +3,14 @@
|
|||||||
namespace App\Livewire\Security;
|
namespace App\Livewire\Security;
|
||||||
|
|
||||||
use App\Models\InstanceSettings;
|
use App\Models\InstanceSettings;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
|
use Laravel\Sanctum\PersonalAccessToken;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class ApiTokens extends Component
|
class ApiTokens extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public ?string $description = null;
|
public ?string $description = null;
|
||||||
|
|
||||||
public $tokens = [];
|
public $tokens = [];
|
||||||
@@ -15,6 +19,10 @@ class ApiTokens extends Component
|
|||||||
|
|
||||||
public $isApiEnabled;
|
public $isApiEnabled;
|
||||||
|
|
||||||
|
public bool $canUseRootPermissions = false;
|
||||||
|
|
||||||
|
public bool $canUseWritePermissions = false;
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
return view('livewire.security.api-tokens');
|
return view('livewire.security.api-tokens');
|
||||||
@@ -23,6 +31,8 @@ class ApiTokens extends Component
|
|||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
$this->isApiEnabled = InstanceSettings::get()->is_api_enabled;
|
$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();
|
$this->getTokens();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,6 +43,23 @@ class ApiTokens extends Component
|
|||||||
|
|
||||||
public function updatedPermissions($permissionToUpdate)
|
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') {
|
if ($permissionToUpdate == 'root') {
|
||||||
$this->permissions = ['root'];
|
$this->permissions = ['root'];
|
||||||
} elseif ($permissionToUpdate == 'read:sensitive' && ! in_array('read', $this->permissions)) {
|
} elseif ($permissionToUpdate == 'read:sensitive' && ! in_array('read', $this->permissions)) {
|
||||||
@@ -50,6 +77,17 @@ class ApiTokens extends Component
|
|||||||
public function addNewToken()
|
public function addNewToken()
|
||||||
{
|
{
|
||||||
try {
|
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([
|
$this->validate([
|
||||||
'description' => 'required|min:3|max:255',
|
'description' => 'required|min:3|max:255',
|
||||||
]);
|
]);
|
||||||
@@ -65,6 +103,7 @@ class ApiTokens extends Component
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$token = auth()->user()->tokens()->where('id', $id)->firstOrFail();
|
$token = auth()->user()->tokens()->where('id', $id)->firstOrFail();
|
||||||
|
$this->authorize('delete', $token);
|
||||||
$token->delete();
|
$token->delete();
|
||||||
$this->getTokens();
|
$this->getTokens();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
@@ -3,10 +3,13 @@
|
|||||||
namespace App\Livewire\Security\PrivateKey;
|
namespace App\Livewire\Security\PrivateKey;
|
||||||
|
|
||||||
use App\Models\PrivateKey;
|
use App\Models\PrivateKey;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Index extends Component
|
class Index extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
$privateKeys = PrivateKey::ownedByCurrentTeam(['name', 'uuid', 'is_git_related', 'description'])->get();
|
$privateKeys = PrivateKey::ownedByCurrentTeam(['name', 'uuid', 'is_git_related', 'description'])->get();
|
||||||
@@ -18,6 +21,7 @@ class Index extends Component
|
|||||||
|
|
||||||
public function cleanupUnusedKeys()
|
public function cleanupUnusedKeys()
|
||||||
{
|
{
|
||||||
|
$this->authorize('create', PrivateKey::class);
|
||||||
PrivateKey::cleanupUnusedKeys();
|
PrivateKey::cleanupUnusedKeys();
|
||||||
$this->dispatch('success', 'Unused keys have been cleaned up.');
|
$this->dispatch('success', 'Unused keys have been cleaned up.');
|
||||||
}
|
}
|
||||||
|
@@ -3,12 +3,17 @@
|
|||||||
namespace App\Livewire\Server\Proxy;
|
namespace App\Livewire\Server\Proxy;
|
||||||
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class DynamicConfigurationNavbar extends Component
|
class DynamicConfigurationNavbar extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $server_id;
|
public $server_id;
|
||||||
|
|
||||||
|
public Server $server;
|
||||||
|
|
||||||
public $fileName = '';
|
public $fileName = '';
|
||||||
|
|
||||||
public $value = '';
|
public $value = '';
|
||||||
@@ -17,18 +22,18 @@ class DynamicConfigurationNavbar extends Component
|
|||||||
|
|
||||||
public function delete(string $fileName)
|
public function delete(string $fileName)
|
||||||
{
|
{
|
||||||
$server = Server::ownedByCurrentTeam()->whereId($this->server_id)->first();
|
$this->authorize('update', $this->server);
|
||||||
$proxy_path = $server->proxyPath();
|
$proxy_path = $this->server->proxyPath();
|
||||||
$proxy_type = $server->proxyType();
|
$proxy_type = $this->server->proxyType();
|
||||||
$file = str_replace('|', '.', $fileName);
|
$file = str_replace('|', '.', $fileName);
|
||||||
if ($proxy_type === 'CADDY' && $file === 'Caddyfile') {
|
if ($proxy_type === 'CADDY' && $file === 'Caddyfile') {
|
||||||
$this->dispatch('error', 'Cannot delete Caddyfile.');
|
$this->dispatch('error', 'Cannot delete Caddyfile.');
|
||||||
|
|
||||||
return;
|
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') {
|
if ($proxy_type === 'CADDY') {
|
||||||
$server->reloadCaddy();
|
$this->server->reloadCaddy();
|
||||||
}
|
}
|
||||||
$this->dispatch('success', 'File deleted.');
|
$this->dispatch('success', 'File deleted.');
|
||||||
$this->dispatch('loadDynamicConfigurations');
|
$this->dispatch('loadDynamicConfigurations');
|
||||||
|
@@ -4,10 +4,13 @@ namespace App\Livewire\SharedVariables\Environment;
|
|||||||
|
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Show extends Component
|
class Show extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public Project $project;
|
public Project $project;
|
||||||
|
|
||||||
public Application $application;
|
public Application $application;
|
||||||
@@ -21,6 +24,8 @@ class Show extends Component
|
|||||||
public function saveKey($data)
|
public function saveKey($data)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->environment);
|
||||||
|
|
||||||
$found = $this->environment->environment_variables()->where('key', $data['key'])->first();
|
$found = $this->environment->environment_variables()->where('key', $data['key'])->first();
|
||||||
if ($found) {
|
if ($found) {
|
||||||
throw new \Exception('Variable already exists.');
|
throw new \Exception('Variable already exists.');
|
||||||
|
@@ -3,10 +3,13 @@
|
|||||||
namespace App\Livewire\SharedVariables\Project;
|
namespace App\Livewire\SharedVariables\Project;
|
||||||
|
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Show extends Component
|
class Show extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public Project $project;
|
public Project $project;
|
||||||
|
|
||||||
protected $listeners = ['refreshEnvs' => '$refresh', 'saveKey' => 'saveKey', 'environmentVariableDeleted' => '$refresh'];
|
protected $listeners = ['refreshEnvs' => '$refresh', 'saveKey' => 'saveKey', 'environmentVariableDeleted' => '$refresh'];
|
||||||
@@ -14,6 +17,8 @@ class Show extends Component
|
|||||||
public function saveKey($data)
|
public function saveKey($data)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->project);
|
||||||
|
|
||||||
$found = $this->project->environment_variables()->where('key', $data['key'])->first();
|
$found = $this->project->environment_variables()->where('key', $data['key'])->first();
|
||||||
if ($found) {
|
if ($found) {
|
||||||
throw new \Exception('Variable already exists.');
|
throw new \Exception('Variable already exists.');
|
||||||
|
@@ -3,10 +3,13 @@
|
|||||||
namespace App\Livewire\SharedVariables\Team;
|
namespace App\Livewire\SharedVariables\Team;
|
||||||
|
|
||||||
use App\Models\Team;
|
use App\Models\Team;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Index extends Component
|
class Index extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public Team $team;
|
public Team $team;
|
||||||
|
|
||||||
protected $listeners = ['refreshEnvs' => '$refresh', 'saveKey' => 'saveKey', 'environmentVariableDeleted' => '$refresh'];
|
protected $listeners = ['refreshEnvs' => '$refresh', 'saveKey' => 'saveKey', 'environmentVariableDeleted' => '$refresh'];
|
||||||
@@ -14,6 +17,8 @@ class Index extends Component
|
|||||||
public function saveKey($data)
|
public function saveKey($data)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->team);
|
||||||
|
|
||||||
$found = $this->team->environment_variables()->where('key', $data['key'])->first();
|
$found = $this->team->environment_variables()->where('key', $data['key'])->first();
|
||||||
if ($found) {
|
if ($found) {
|
||||||
throw new \Exception('Variable already exists.');
|
throw new \Exception('Variable already exists.');
|
||||||
|
@@ -5,6 +5,7 @@ namespace App\Livewire\Source\Github;
|
|||||||
use App\Jobs\GithubAppPermissionJob;
|
use App\Jobs\GithubAppPermissionJob;
|
||||||
use App\Models\GithubApp;
|
use App\Models\GithubApp;
|
||||||
use App\Models\PrivateKey;
|
use App\Models\PrivateKey;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Lcobucci\JWT\Configuration;
|
use Lcobucci\JWT\Configuration;
|
||||||
use Lcobucci\JWT\Signer\Key\InMemory;
|
use Lcobucci\JWT\Signer\Key\InMemory;
|
||||||
@@ -13,7 +14,9 @@ use Livewire\Component;
|
|||||||
|
|
||||||
class Change extends Component
|
class Change extends Component
|
||||||
{
|
{
|
||||||
public string $webhook_endpoint;
|
use AuthorizesRequests;
|
||||||
|
|
||||||
|
public string $webhook_endpoint = '';
|
||||||
|
|
||||||
public ?string $ipv4 = null;
|
public ?string $ipv4 = null;
|
||||||
|
|
||||||
@@ -69,6 +72,8 @@ class Change extends Component
|
|||||||
public function checkPermissions()
|
public function checkPermissions()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('view', $this->github_app);
|
||||||
|
|
||||||
GithubAppPermissionJob::dispatchSync($this->github_app);
|
GithubAppPermissionJob::dispatchSync($this->github_app);
|
||||||
$this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret');
|
$this->github_app->refresh()->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||||
$this->dispatch('success', 'Github App permissions updated.');
|
$this->dispatch('success', 'Github App permissions updated.');
|
||||||
@@ -155,7 +160,7 @@ class Change extends Component
|
|||||||
if (isCloud() && ! isDev()) {
|
if (isCloud() && ! isDev()) {
|
||||||
$this->webhook_endpoint = config('app.url');
|
$this->webhook_endpoint = config('app.url');
|
||||||
} else {
|
} else {
|
||||||
$this->webhook_endpoint = $this->ipv4;
|
$this->webhook_endpoint = $this->ipv4 ?? '';
|
||||||
$this->is_system_wide = $this->github_app->is_system_wide;
|
$this->is_system_wide = $this->github_app->is_system_wide;
|
||||||
}
|
}
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
@@ -195,6 +200,8 @@ class Change extends Component
|
|||||||
public function updateGithubAppName()
|
public function updateGithubAppName()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->github_app);
|
||||||
|
|
||||||
$privateKey = PrivateKey::ownedByCurrentTeam()->find($this->github_app->private_key_id);
|
$privateKey = PrivateKey::ownedByCurrentTeam()->find($this->github_app->private_key_id);
|
||||||
|
|
||||||
if (! $privateKey) {
|
if (! $privateKey) {
|
||||||
@@ -237,6 +244,8 @@ class Change extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->github_app);
|
||||||
|
|
||||||
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||||
$this->validate([
|
$this->validate([
|
||||||
'github_app.name' => 'required|string',
|
'github_app.name' => 'required|string',
|
||||||
@@ -262,6 +271,8 @@ class Change extends Component
|
|||||||
|
|
||||||
public function createGithubAppManually()
|
public function createGithubAppManually()
|
||||||
{
|
{
|
||||||
|
$this->authorize('update', $this->github_app);
|
||||||
|
|
||||||
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||||
$this->github_app->app_id = '1234567890';
|
$this->github_app->app_id = '1234567890';
|
||||||
$this->github_app->installation_id = '1234567890';
|
$this->github_app->installation_id = '1234567890';
|
||||||
@@ -272,6 +283,8 @@ class Change extends Component
|
|||||||
public function instantSave()
|
public function instantSave()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->github_app);
|
||||||
|
|
||||||
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||||
$this->github_app->save();
|
$this->github_app->save();
|
||||||
$this->dispatch('success', 'Github App updated.');
|
$this->dispatch('success', 'Github App updated.');
|
||||||
@@ -283,6 +296,8 @@ class Change extends Component
|
|||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('delete', $this->github_app);
|
||||||
|
|
||||||
if ($this->github_app->applications->isNotEmpty()) {
|
if ($this->github_app->applications->isNotEmpty()) {
|
||||||
$this->dispatch('error', 'This source is being used by an application. Please delete all applications first.');
|
$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');
|
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
|
||||||
|
@@ -3,10 +3,13 @@
|
|||||||
namespace App\Livewire\Source\Github;
|
namespace App\Livewire\Source\Github;
|
||||||
|
|
||||||
use App\Models\GithubApp;
|
use App\Models\GithubApp;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Create extends Component
|
class Create extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public string $name;
|
public string $name;
|
||||||
|
|
||||||
public ?string $organization = null;
|
public ?string $organization = null;
|
||||||
@@ -29,6 +32,8 @@ class Create extends Component
|
|||||||
public function createGitHubApp()
|
public function createGitHubApp()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('createAnyResource');
|
||||||
|
|
||||||
$this->validate([
|
$this->validate([
|
||||||
'name' => 'required|string',
|
'name' => 'required|string',
|
||||||
'organization' => 'nullable|string',
|
'organization' => 'nullable|string',
|
||||||
|
@@ -4,11 +4,14 @@ namespace App\Livewire\Storage;
|
|||||||
|
|
||||||
use App\Models\S3Storage;
|
use App\Models\S3Storage;
|
||||||
use App\Support\ValidationPatterns;
|
use App\Support\ValidationPatterns;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Uri;
|
use Illuminate\Support\Uri;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Create extends Component
|
class Create extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public string $name;
|
public string $name;
|
||||||
|
|
||||||
public string $description;
|
public string $description;
|
||||||
@@ -94,6 +97,8 @@ class Create extends Component
|
|||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('create', S3Storage::class);
|
||||||
|
|
||||||
$this->validate();
|
$this->validate();
|
||||||
$this->storage = new S3Storage;
|
$this->storage = new S3Storage;
|
||||||
$this->storage->name = $this->name;
|
$this->storage->name = $this->name;
|
||||||
|
@@ -4,10 +4,13 @@ namespace App\Livewire\Storage;
|
|||||||
|
|
||||||
use App\Models\S3Storage;
|
use App\Models\S3Storage;
|
||||||
use App\Support\ValidationPatterns;
|
use App\Support\ValidationPatterns;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Form extends Component
|
class Form extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public S3Storage $storage;
|
public S3Storage $storage;
|
||||||
|
|
||||||
protected function rules(): array
|
protected function rules(): array
|
||||||
@@ -60,6 +63,8 @@ class Form extends Component
|
|||||||
public function testConnection()
|
public function testConnection()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('validateConnection', $this->storage);
|
||||||
|
|
||||||
$this->storage->testConnection(shouldSave: true);
|
$this->storage->testConnection(shouldSave: true);
|
||||||
|
|
||||||
return $this->dispatch('success', 'Connection is working.', 'Tested with "ListObjectsV2" action.');
|
return $this->dispatch('success', 'Connection is working.', 'Tested with "ListObjectsV2" action.');
|
||||||
@@ -83,8 +88,10 @@ class Form extends Component
|
|||||||
|
|
||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
$this->validate();
|
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->storage);
|
||||||
|
|
||||||
|
$this->validate();
|
||||||
$this->testConnection();
|
$this->testConnection();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
|
@@ -5,12 +5,15 @@ namespace App\Livewire\Team;
|
|||||||
use App\Models\Team;
|
use App\Models\Team;
|
||||||
use App\Models\TeamInvitation;
|
use App\Models\TeamInvitation;
|
||||||
use App\Support\ValidationPatterns;
|
use App\Support\ValidationPatterns;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Index extends Component
|
class Index extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $invitations = [];
|
public $invitations = [];
|
||||||
|
|
||||||
public Team $team;
|
public Team $team;
|
||||||
@@ -58,6 +61,7 @@ class Index extends Component
|
|||||||
{
|
{
|
||||||
$this->validate();
|
$this->validate();
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('update', $this->team);
|
||||||
$this->team->save();
|
$this->team->save();
|
||||||
refreshSession();
|
refreshSession();
|
||||||
$this->dispatch('success', 'Team updated.');
|
$this->dispatch('success', 'Team updated.');
|
||||||
@@ -69,6 +73,7 @@ class Index extends Component
|
|||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
$currentTeam = currentTeam();
|
$currentTeam = currentTeam();
|
||||||
|
$this->authorize('delete', $currentTeam);
|
||||||
$currentTeam->delete();
|
$currentTeam->delete();
|
||||||
|
|
||||||
$currentTeam->members->each(function ($user) use ($currentTeam) {
|
$currentTeam->members->each(function ($user) use ($currentTeam) {
|
||||||
|
@@ -4,10 +4,13 @@ namespace App\Livewire\Team;
|
|||||||
|
|
||||||
use App\Models\TeamInvitation;
|
use App\Models\TeamInvitation;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Invitations extends Component
|
class Invitations extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $invitations;
|
public $invitations;
|
||||||
|
|
||||||
protected $listeners = ['refreshInvitations'];
|
protected $listeners = ['refreshInvitations'];
|
||||||
@@ -15,6 +18,8 @@ class Invitations extends Component
|
|||||||
public function deleteInvitation(int $invitation_id)
|
public function deleteInvitation(int $invitation_id)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('manageInvitations', currentTeam());
|
||||||
|
|
||||||
$invitation = TeamInvitation::ownedByCurrentTeam()->findOrFail($invitation_id);
|
$invitation = TeamInvitation::ownedByCurrentTeam()->findOrFail($invitation_id);
|
||||||
$user = User::whereEmail($invitation->email)->first();
|
$user = User::whereEmail($invitation->email)->first();
|
||||||
if (filled($user)) {
|
if (filled($user)) {
|
||||||
|
@@ -4,6 +4,7 @@ namespace App\Livewire\Team;
|
|||||||
|
|
||||||
use App\Models\TeamInvitation;
|
use App\Models\TeamInvitation;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Notifications\Messages\MailMessage;
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
use Illuminate\Support\Facades\Crypt;
|
use Illuminate\Support\Facades\Crypt;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
@@ -13,6 +14,8 @@ use Visus\Cuid2\Cuid2;
|
|||||||
|
|
||||||
class InviteLink extends Component
|
class InviteLink extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public string $email;
|
public string $email;
|
||||||
|
|
||||||
public string $role = 'member';
|
public string $role = 'member';
|
||||||
@@ -40,6 +43,7 @@ class InviteLink extends Component
|
|||||||
private function generateInviteLink(bool $sendEmail = false)
|
private function generateInviteLink(bool $sendEmail = false)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('manageInvitations', currentTeam());
|
||||||
$this->validate();
|
$this->validate();
|
||||||
if (auth()->user()->role() === 'admin' && $this->role === 'owner') {
|
if (auth()->user()->role() === 'admin' && $this->role === 'owner') {
|
||||||
throw new \Exception('Admins cannot invite owners.');
|
throw new \Exception('Admins cannot invite owners.');
|
||||||
|
@@ -4,16 +4,21 @@ namespace App\Livewire\Team;
|
|||||||
|
|
||||||
use App\Enums\Role;
|
use App\Enums\Role;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Member extends Component
|
class Member extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public User $member;
|
public User $member;
|
||||||
|
|
||||||
public function makeAdmin()
|
public function makeAdmin()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('manageMembers', currentTeam());
|
||||||
|
|
||||||
if (Role::from(auth()->user()->role())->lt(Role::ADMIN)
|
if (Role::from(auth()->user()->role())->lt(Role::ADMIN)
|
||||||
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
||||||
throw new \Exception('You are not authorized to perform this action.');
|
throw new \Exception('You are not authorized to perform this action.');
|
||||||
@@ -28,6 +33,8 @@ class Member extends Component
|
|||||||
public function makeOwner()
|
public function makeOwner()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('manageMembers', currentTeam());
|
||||||
|
|
||||||
if (Role::from(auth()->user()->role())->lt(Role::OWNER)
|
if (Role::from(auth()->user()->role())->lt(Role::OWNER)
|
||||||
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
||||||
throw new \Exception('You are not authorized to perform this action.');
|
throw new \Exception('You are not authorized to perform this action.');
|
||||||
@@ -42,6 +49,8 @@ class Member extends Component
|
|||||||
public function makeReadonly()
|
public function makeReadonly()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('manageMembers', currentTeam());
|
||||||
|
|
||||||
if (Role::from(auth()->user()->role())->lt(Role::ADMIN)
|
if (Role::from(auth()->user()->role())->lt(Role::ADMIN)
|
||||||
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
||||||
throw new \Exception('You are not authorized to perform this action.');
|
throw new \Exception('You are not authorized to perform this action.');
|
||||||
@@ -56,6 +65,8 @@ class Member extends Component
|
|||||||
public function remove()
|
public function remove()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
$this->authorize('manageMembers', currentTeam());
|
||||||
|
|
||||||
if (Role::from(auth()->user()->role())->lt(Role::ADMIN)
|
if (Role::from(auth()->user()->role())->lt(Role::ADMIN)
|
||||||
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
|| Role::from($this->getMemberRole())->gt(auth()->user()->role())) {
|
||||||
throw new \Exception('You are not authorized to perform this action.');
|
throw new \Exception('You are not authorized to perform this action.');
|
||||||
|
@@ -3,15 +3,19 @@
|
|||||||
namespace App\Livewire\Team\Member;
|
namespace App\Livewire\Team\Member;
|
||||||
|
|
||||||
use App\Models\TeamInvitation;
|
use App\Models\TeamInvitation;
|
||||||
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class Index extends Component
|
class Index extends Component
|
||||||
{
|
{
|
||||||
|
use AuthorizesRequests;
|
||||||
|
|
||||||
public $invitations = [];
|
public $invitations = [];
|
||||||
|
|
||||||
public function mount()
|
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();
|
$this->invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ class Index extends Component
|
|||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
$this->authorize('useTerminal', Server::class);
|
|
||||||
$this->servers = Server::isReachable()->get()->filter(function ($server) {
|
$this->servers = Server::isReachable()->get()->filter(function ($server) {
|
||||||
return $server->isTerminalEnabled();
|
return $server->isTerminalEnabled();
|
||||||
});
|
});
|
||||||
|
@@ -12,4 +12,19 @@ class SharedEnvironmentVariable extends Model
|
|||||||
'key' => 'string',
|
'key' => 'string',
|
||||||
'value' => 'encrypted',
|
'value' => 'encrypted',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function team()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Team::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function project()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Project::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function environment()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Environment::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
109
app/Policies/ApiTokenPolicy.php
Normal file
109
app/Policies/ApiTokenPolicy.php
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Laravel\Sanctum\PersonalAccessToken;
|
||||||
|
|
||||||
|
class ApiTokenPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any API tokens.
|
||||||
|
*/
|
||||||
|
public function viewAny(User $user): bool
|
||||||
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
// Users can view their own API tokens
|
||||||
|
return true;
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the API token.
|
||||||
|
*/
|
||||||
|
public function view(User $user, PersonalAccessToken $token): bool
|
||||||
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
// Users can only view their own tokens
|
||||||
|
return $user->id === $token->tokenable_id && $token->tokenable_type === User::class;
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create API tokens.
|
||||||
|
*/
|
||||||
|
public function create(User $user): bool
|
||||||
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
// All authenticated users can create their own API tokens
|
||||||
|
return true;
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the API token.
|
||||||
|
*/
|
||||||
|
public function update(User $user, PersonalAccessToken $token): bool
|
||||||
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
// Users can only update their own tokens
|
||||||
|
return $user->id === $token->tokenable_id && $token->tokenable_type === User::class;
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the API token.
|
||||||
|
*/
|
||||||
|
public function delete(User $user, PersonalAccessToken $token): bool
|
||||||
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
// Users can only delete their own tokens
|
||||||
|
return $user->id === $token->tokenable_id && $token->tokenable_type === User::class;
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can manage their own API tokens.
|
||||||
|
*/
|
||||||
|
public function manage(User $user): bool
|
||||||
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
// All authenticated users can manage their own API tokens
|
||||||
|
return true;
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can use root permissions for API tokens.
|
||||||
|
*/
|
||||||
|
public function useRootPermissions(User $user): bool
|
||||||
|
{
|
||||||
|
// Only admins and owners can use root permissions
|
||||||
|
return $user->isAdmin() || $user->isOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can use write permissions for API tokens.
|
||||||
|
*/
|
||||||
|
public function useWritePermissions(User $user): bool
|
||||||
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
// Only admins and owners can use write permissions
|
||||||
|
return $user->isAdmin() || $user->isOwner();
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -13,6 +13,10 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function viewAny(User $user): bool
|
public function viewAny(User $user): bool
|
||||||
{
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
return true;
|
||||||
|
*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +25,10 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function view(User $user, Application $application): bool
|
public function view(User $user, Application $application): bool
|
||||||
{
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
return true;
|
||||||
|
*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,11 +37,15 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
if ($user->isAdmin()) {
|
if ($user->isAdmin()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,11 +53,15 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function update(User $user, Application $application): Response
|
public function update(User $user, Application $application): Response
|
||||||
{
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
if ($user->isAdmin()) {
|
if ($user->isAdmin()) {
|
||||||
return Response::allow();
|
return Response::allow();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response::deny('As a member, you cannot update this application.<br/><br/>You need at least admin or owner permissions.');
|
return Response::deny('As a member, you cannot update this application.<br/><br/>You need at least admin or owner permissions.');
|
||||||
|
*/
|
||||||
|
return Response::allow();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,11 +69,15 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, Application $application): bool
|
public function delete(User $user, Application $application): bool
|
||||||
{
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
if ($user->isAdmin()) {
|
if ($user->isAdmin()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,6 +85,10 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function restore(User $user, Application $application): bool
|
public function restore(User $user, Application $application): bool
|
||||||
{
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
return true;
|
||||||
|
*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +97,11 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function forceDelete(User $user, Application $application): bool
|
public function forceDelete(User $user, Application $application): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $application->team()->first()->id) !== null;
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
return $user->isAdmin() && $user->teams->contains('id', $application->team()->first()->id);
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,7 +109,11 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function deploy(User $user, Application $application): bool
|
public function deploy(User $user, Application $application): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $application->team()->first()->id) !== null;
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
return $user->teams->contains('id', $application->team()->first()->id);
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,7 +121,11 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function manageDeployments(User $user, Application $application): bool
|
public function manageDeployments(User $user, Application $application): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $application->team()->first()->id) !== null;
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
return $user->isAdmin() && $user->teams->contains('id', $application->team()->first()->id);
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,7 +133,11 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function manageEnvironment(User $user, Application $application): bool
|
public function manageEnvironment(User $user, Application $application): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $application->team()->first()->id) !== null;
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
|
return $user->isAdmin() && $user->teams->contains('id', $application->team()->first()->id);
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,6 +145,10 @@ class ApplicationPolicy
|
|||||||
*/
|
*/
|
||||||
public function cleanupDeploymentQueue(User $user): bool
|
public function cleanupDeploymentQueue(User $user): bool
|
||||||
{
|
{
|
||||||
|
// Authorization temporarily disabled
|
||||||
|
/*
|
||||||
return $user->isAdmin();
|
return $user->isAdmin();
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,8 @@ class ApplicationPreviewPolicy
|
|||||||
*/
|
*/
|
||||||
public function view(User $user, ApplicationPreview $applicationPreview): bool
|
public function view(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
// return $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,7 +30,8 @@ class ApplicationPreviewPolicy
|
|||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin();
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,11 +39,12 @@ class ApplicationPreviewPolicy
|
|||||||
*/
|
*/
|
||||||
public function update(User $user, ApplicationPreview $applicationPreview): Response
|
public function update(User $user, ApplicationPreview $applicationPreview): Response
|
||||||
{
|
{
|
||||||
if ($user->isAdmin()) {
|
// if ($user->isAdmin()) {
|
||||||
return Response::allow();
|
// return Response::allow();
|
||||||
}
|
// }
|
||||||
|
|
||||||
return Response::deny('As a member, you cannot update this preview.<br/><br/>You need at least admin or owner permissions.');
|
// return Response::deny('As a member, you cannot update this preview.<br/><br/>You need at least admin or owner permissions.');
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,7 +52,8 @@ class ApplicationPreviewPolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, ApplicationPreview $applicationPreview): bool
|
public function delete(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,7 +61,8 @@ class ApplicationPreviewPolicy
|
|||||||
*/
|
*/
|
||||||
public function restore(User $user, ApplicationPreview $applicationPreview): bool
|
public function restore(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,7 +70,8 @@ class ApplicationPreviewPolicy
|
|||||||
*/
|
*/
|
||||||
public function forceDelete(User $user, ApplicationPreview $applicationPreview): bool
|
public function forceDelete(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,7 +79,8 @@ class ApplicationPreviewPolicy
|
|||||||
*/
|
*/
|
||||||
public function deploy(User $user, ApplicationPreview $applicationPreview): bool
|
public function deploy(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
// return $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,6 +88,7 @@ class ApplicationPreviewPolicy
|
|||||||
*/
|
*/
|
||||||
public function manageDeployments(User $user, ApplicationPreview $applicationPreview): bool
|
public function manageDeployments(User $user, ApplicationPreview $applicationPreview): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationPreview->application->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,8 @@ class ApplicationSettingPolicy
|
|||||||
*/
|
*/
|
||||||
public function view(User $user, ApplicationSetting $applicationSetting): bool
|
public function view(User $user, ApplicationSetting $applicationSetting): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $applicationSetting->application->team()->first()->id) !== null;
|
// return $user->teams->contains('id', $applicationSetting->application->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +29,8 @@ class ApplicationSettingPolicy
|
|||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin();
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +38,8 @@ class ApplicationSettingPolicy
|
|||||||
*/
|
*/
|
||||||
public function update(User $user, ApplicationSetting $applicationSetting): bool
|
public function update(User $user, ApplicationSetting $applicationSetting): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationSetting->application->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +47,8 @@ class ApplicationSettingPolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, ApplicationSetting $applicationSetting): bool
|
public function delete(User $user, ApplicationSetting $applicationSetting): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationSetting->application->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +56,8 @@ class ApplicationSettingPolicy
|
|||||||
*/
|
*/
|
||||||
public function restore(User $user, ApplicationSetting $applicationSetting): bool
|
public function restore(User $user, ApplicationSetting $applicationSetting): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationSetting->application->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,6 +65,7 @@ class ApplicationSettingPolicy
|
|||||||
*/
|
*/
|
||||||
public function forceDelete(User $user, ApplicationSetting $applicationSetting): bool
|
public function forceDelete(User $user, ApplicationSetting $applicationSetting): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $applicationSetting->application->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,8 @@ class DatabasePolicy
|
|||||||
*/
|
*/
|
||||||
public function view(User $user, $database): bool
|
public function view(User $user, $database): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null;
|
// return $user->teams->contains('id', $database->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +29,8 @@ class DatabasePolicy
|
|||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin();
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,11 +38,12 @@ class DatabasePolicy
|
|||||||
*/
|
*/
|
||||||
public function update(User $user, $database): Response
|
public function update(User $user, $database): Response
|
||||||
{
|
{
|
||||||
if ($user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null) {
|
// if ($user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id)) {
|
||||||
return Response::allow();
|
// return Response::allow();
|
||||||
}
|
// }
|
||||||
|
|
||||||
return Response::deny('As a member, you cannot update this database.<br/><br/>You need at least admin or owner permissions.');
|
// return Response::deny('As a member, you cannot update this database.<br/><br/>You need at least admin or owner permissions.');
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +51,8 @@ class DatabasePolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, $database): bool
|
public function delete(User $user, $database): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,7 +60,8 @@ class DatabasePolicy
|
|||||||
*/
|
*/
|
||||||
public function restore(User $user, $database): bool
|
public function restore(User $user, $database): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,7 +69,8 @@ class DatabasePolicy
|
|||||||
*/
|
*/
|
||||||
public function forceDelete(User $user, $database): bool
|
public function forceDelete(User $user, $database): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +78,8 @@ class DatabasePolicy
|
|||||||
*/
|
*/
|
||||||
public function manage(User $user, $database): bool
|
public function manage(User $user, $database): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,7 +87,8 @@ class DatabasePolicy
|
|||||||
*/
|
*/
|
||||||
public function manageBackups(User $user, $database): bool
|
public function manageBackups(User $user, $database): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,6 +96,7 @@ class DatabasePolicy
|
|||||||
*/
|
*/
|
||||||
public function manageEnvironment(User $user, $database): bool
|
public function manageEnvironment(User $user, $database): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,8 @@ class EnvironmentPolicy
|
|||||||
*/
|
*/
|
||||||
public function view(User $user, Environment $environment): bool
|
public function view(User $user, Environment $environment): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $environment->project->team_id) !== null;
|
// return $user->teams->contains('id', $environment->project->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +29,8 @@ class EnvironmentPolicy
|
|||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin();
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +38,8 @@ class EnvironmentPolicy
|
|||||||
*/
|
*/
|
||||||
public function update(User $user, Environment $environment): bool
|
public function update(User $user, Environment $environment): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $environment->project->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +47,8 @@ class EnvironmentPolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, Environment $environment): bool
|
public function delete(User $user, Environment $environment): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $environment->project->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +56,8 @@ class EnvironmentPolicy
|
|||||||
*/
|
*/
|
||||||
public function restore(User $user, Environment $environment): bool
|
public function restore(User $user, Environment $environment): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $environment->project->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,6 +65,7 @@ class EnvironmentPolicy
|
|||||||
*/
|
*/
|
||||||
public function forceDelete(User $user, Environment $environment): bool
|
public function forceDelete(User $user, Environment $environment): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $environment->project->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
79
app/Policies/GithubAppPolicy.php
Normal file
79
app/Policies/GithubAppPolicy.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\GithubApp;
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
class GithubAppPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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, GithubApp $githubApp): bool
|
||||||
|
{
|
||||||
|
// return $user->teams->contains('id', $githubApp->team_id) || $githubApp->is_system_wide;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create models.
|
||||||
|
*/
|
||||||
|
public function create(User $user): bool
|
||||||
|
{
|
||||||
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*/
|
||||||
|
public function update(User $user, GithubApp $githubApp): bool
|
||||||
|
{
|
||||||
|
if ($githubApp->is_system_wide) {
|
||||||
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->isAdmin() && $user->teams->contains('id', $githubApp->team_id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*/
|
||||||
|
public function delete(User $user, GithubApp $githubApp): bool
|
||||||
|
{
|
||||||
|
if ($githubApp->is_system_wide) {
|
||||||
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->isAdmin() && $user->teams->contains('id', $githubApp->team_id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can restore the model.
|
||||||
|
*/
|
||||||
|
public function restore(User $user, GithubApp $githubApp): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can permanently delete the model.
|
||||||
|
*/
|
||||||
|
public function forceDelete(User $user, GithubApp $githubApp): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
56
app/Policies/NotificationPolicy.php
Normal file
56
app/Policies/NotificationPolicy.php
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class NotificationPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the notification settings.
|
||||||
|
*/
|
||||||
|
public function view(User $user, Model $notificationSettings): bool
|
||||||
|
{
|
||||||
|
// Check if the notification settings belong to the user's current team
|
||||||
|
if (! $notificationSettings->team) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->teams()->where('teams.id', $notificationSettings->team->id)->exists();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the notification settings.
|
||||||
|
*/
|
||||||
|
public function update(User $user, Model $notificationSettings): bool
|
||||||
|
{
|
||||||
|
// Check if the notification settings belong to the user's current team
|
||||||
|
if (! $notificationSettings->team) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only owners and admins can update notification settings
|
||||||
|
// return $user->isAdmin() || $user->isOwner();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can manage (create, update, delete) notification settings.
|
||||||
|
*/
|
||||||
|
public function manage(User $user, Model $notificationSettings): bool
|
||||||
|
{
|
||||||
|
// return $this->update($user, $notificationSettings);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can send test notifications.
|
||||||
|
*/
|
||||||
|
public function sendTest(User $user, Model $notificationSettings): bool
|
||||||
|
{
|
||||||
|
// return $this->update($user, $notificationSettings);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -20,7 +20,8 @@ class PrivateKeyPolicy
|
|||||||
*/
|
*/
|
||||||
public function view(User $user, PrivateKey $privateKey): bool
|
public function view(User $user, PrivateKey $privateKey): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $privateKey->team_id) !== null;
|
// return $user->teams->contains('id', $privateKey->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +29,8 @@ class PrivateKeyPolicy
|
|||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin();
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +38,8 @@ class PrivateKeyPolicy
|
|||||||
*/
|
*/
|
||||||
public function update(User $user, PrivateKey $privateKey): bool
|
public function update(User $user, PrivateKey $privateKey): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $privateKey->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $privateKey->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +47,8 @@ class PrivateKeyPolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, PrivateKey $privateKey): bool
|
public function delete(User $user, PrivateKey $privateKey): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $privateKey->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $privateKey->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -20,7 +20,8 @@ class ProjectPolicy
|
|||||||
*/
|
*/
|
||||||
public function view(User $user, Project $project): bool
|
public function view(User $user, Project $project): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $project->team_id) !== null;
|
// return $user->teams->contains('id', $project->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +29,8 @@ class ProjectPolicy
|
|||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin();
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +38,8 @@ class ProjectPolicy
|
|||||||
*/
|
*/
|
||||||
public function update(User $user, Project $project): bool
|
public function update(User $user, Project $project): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $project->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $project->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +47,8 @@ class ProjectPolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, Project $project): bool
|
public function delete(User $user, Project $project): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $project->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $project->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +56,8 @@ class ProjectPolicy
|
|||||||
*/
|
*/
|
||||||
public function restore(User $user, Project $project): bool
|
public function restore(User $user, Project $project): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $project->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $project->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,6 +65,7 @@ class ProjectPolicy
|
|||||||
*/
|
*/
|
||||||
public function forceDelete(User $user, Project $project): bool
|
public function forceDelete(User $user, Project $project): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $project->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $project->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,6 +30,7 @@ class ResourceCreatePolicy
|
|||||||
StandaloneClickhouse::class,
|
StandaloneClickhouse::class,
|
||||||
Service::class,
|
Service::class,
|
||||||
Application::class,
|
Application::class,
|
||||||
|
GithubApp::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,7 +38,8 @@ class ResourceCreatePolicy
|
|||||||
*/
|
*/
|
||||||
public function createAny(User $user): bool
|
public function createAny(User $user): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin();
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,7 +51,8 @@ class ResourceCreatePolicy
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $user->isAdmin();
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
namespace App\Policies;
|
namespace App\Policies;
|
||||||
|
|
||||||
use App\Models\S3Storage;
|
use App\Models\S3Storage;
|
||||||
use App\Models\Server;
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
|
||||||
class S3StoragePolicy
|
class S3StoragePolicy
|
||||||
@@ -21,7 +20,7 @@ class S3StoragePolicy
|
|||||||
*/
|
*/
|
||||||
public function view(User $user, S3Storage $storage): bool
|
public function view(User $user, S3Storage $storage): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $storage->team_id)->exists();
|
return $user->teams->contains('id', $storage->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,9 +34,10 @@ class S3StoragePolicy
|
|||||||
/**
|
/**
|
||||||
* Determine whether the user can update the model.
|
* Determine whether the user can update the model.
|
||||||
*/
|
*/
|
||||||
public function update(User $user, Server $server): bool
|
public function update(User $user, S3Storage $storage): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $server->team_id)->exists() && $user->isAdmin();
|
// return $user->teams->contains('id', $storage->team_id) && $user->isAdmin();
|
||||||
|
return $user->teams->contains('id', $storage->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,7 +45,8 @@ class S3StoragePolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, S3Storage $storage): bool
|
public function delete(User $user, S3Storage $storage): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $storage->team_id)->exists() && $user->isAdmin();
|
// return $user->teams->contains('id', $storage->team_id) && $user->isAdmin();
|
||||||
|
return $user->teams->contains('id', $storage->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,4 +64,12 @@ class S3StoragePolicy
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can validate the connection of the model.
|
||||||
|
*/
|
||||||
|
public function validateConnection(User $user, S3Storage $storage): bool
|
||||||
|
{
|
||||||
|
return $user->teams->contains('id', $storage->team_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,7 @@ class ServerPolicy
|
|||||||
*/
|
*/
|
||||||
public function view(User $user, Server $server): bool
|
public function view(User $user, Server $server): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $server->team_id) !== null;
|
return $user->teams->contains('id', $server->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +36,7 @@ class ServerPolicy
|
|||||||
*/
|
*/
|
||||||
public function update(User $user, Server $server): bool
|
public function update(User $user, Server $server): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $server->team_id) !== null;
|
return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +44,7 @@ class ServerPolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, Server $server): bool
|
public function delete(User $user, Server $server): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $server->team_id) !== null;
|
return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,7 +68,7 @@ class ServerPolicy
|
|||||||
*/
|
*/
|
||||||
public function manageProxy(User $user, Server $server): bool
|
public function manageProxy(User $user, Server $server): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $server->team_id) !== null;
|
return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,7 +76,7 @@ class ServerPolicy
|
|||||||
*/
|
*/
|
||||||
public function manageSentinel(User $user, Server $server): bool
|
public function manageSentinel(User $user, Server $server): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $server->team_id) !== null;
|
return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,7 +84,7 @@ class ServerPolicy
|
|||||||
*/
|
*/
|
||||||
public function manageCaCertificate(User $user, Server $server): bool
|
public function manageCaCertificate(User $user, Server $server): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $server->team_id) !== null;
|
return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,7 +92,7 @@ class ServerPolicy
|
|||||||
*/
|
*/
|
||||||
public function viewTerminal(User $user, Server $server): bool
|
public function viewTerminal(User $user, Server $server): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $server->team_id) !== null;
|
return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,6 +100,6 @@ class ServerPolicy
|
|||||||
*/
|
*/
|
||||||
public function viewSecurity(User $user, Server $server): bool
|
public function viewSecurity(User $user, Server $server): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $server->team_id) !== null;
|
return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
63
app/Policies/ServiceApplicationPolicy.php
Normal file
63
app/Policies/ServiceApplicationPolicy.php
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\ServiceApplication;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
|
||||||
|
class ServiceApplicationPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*/
|
||||||
|
public function view(User $user, ServiceApplication $serviceApplication): bool
|
||||||
|
{
|
||||||
|
return Gate::allows('view', $serviceApplication->service);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create models.
|
||||||
|
*/
|
||||||
|
public function create(User $user): bool
|
||||||
|
{
|
||||||
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*/
|
||||||
|
public function update(User $user, ServiceApplication $serviceApplication): bool
|
||||||
|
{
|
||||||
|
// return Gate::allows('update', $serviceApplication->service);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*/
|
||||||
|
public function delete(User $user, ServiceApplication $serviceApplication): bool
|
||||||
|
{
|
||||||
|
// return Gate::allows('delete', $serviceApplication->service);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can restore the model.
|
||||||
|
*/
|
||||||
|
public function restore(User $user, ServiceApplication $serviceApplication): bool
|
||||||
|
{
|
||||||
|
// return Gate::allows('update', $serviceApplication->service);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can permanently delete the model.
|
||||||
|
*/
|
||||||
|
public function forceDelete(User $user, ServiceApplication $serviceApplication): bool
|
||||||
|
{
|
||||||
|
// return Gate::allows('delete', $serviceApplication->service);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
63
app/Policies/ServiceDatabasePolicy.php
Normal file
63
app/Policies/ServiceDatabasePolicy.php
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\ServiceDatabase;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
|
||||||
|
class ServiceDatabasePolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*/
|
||||||
|
public function view(User $user, ServiceDatabase $serviceDatabase): bool
|
||||||
|
{
|
||||||
|
return Gate::allows('view', $serviceDatabase->service);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create models.
|
||||||
|
*/
|
||||||
|
public function create(User $user): bool
|
||||||
|
{
|
||||||
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*/
|
||||||
|
public function update(User $user, ServiceDatabase $serviceDatabase): bool
|
||||||
|
{
|
||||||
|
// return Gate::allows('update', $serviceDatabase->service);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*/
|
||||||
|
public function delete(User $user, ServiceDatabase $serviceDatabase): bool
|
||||||
|
{
|
||||||
|
// return Gate::allows('delete', $serviceDatabase->service);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can restore the model.
|
||||||
|
*/
|
||||||
|
public function restore(User $user, ServiceDatabase $serviceDatabase): bool
|
||||||
|
{
|
||||||
|
// return Gate::allows('update', $serviceDatabase->service);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can permanently delete the model.
|
||||||
|
*/
|
||||||
|
public function forceDelete(User $user, ServiceDatabase $serviceDatabase): bool
|
||||||
|
{
|
||||||
|
// return Gate::allows('delete', $serviceDatabase->service);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -28,7 +28,8 @@ class ServicePolicy
|
|||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin();
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +37,13 @@ class ServicePolicy
|
|||||||
*/
|
*/
|
||||||
public function update(User $user, Service $service): bool
|
public function update(User $user, Service $service): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $service->team()->first()->id) !== null;
|
$team = $service->team();
|
||||||
|
if (! $team) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->isAdmin() && $user->teams->contains('id', $team->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,11 +51,12 @@ class ServicePolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, Service $service): bool
|
public function delete(User $user, Service $service): bool
|
||||||
{
|
{
|
||||||
if ($user->isAdmin()) {
|
// if ($user->isAdmin()) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return false;
|
// return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,6 +64,7 @@ class ServicePolicy
|
|||||||
*/
|
*/
|
||||||
public function restore(User $user, Service $service): bool
|
public function restore(User $user, Service $service): bool
|
||||||
{
|
{
|
||||||
|
// return true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,16 +73,23 @@ class ServicePolicy
|
|||||||
*/
|
*/
|
||||||
public function forceDelete(User $user, Service $service): bool
|
public function forceDelete(User $user, Service $service): bool
|
||||||
{
|
{
|
||||||
if ($user->isAdmin()) {
|
// if ($user->isAdmin()) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return false;
|
// return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function stop(User $user, Service $service): bool
|
public function stop(User $user, Service $service): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $service->team()->first()->id) !== null;
|
$team = $service->team();
|
||||||
|
if (! $team) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->teams->contains('id', $team->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,7 +97,13 @@ class ServicePolicy
|
|||||||
*/
|
*/
|
||||||
public function manageEnvironment(User $user, Service $service): bool
|
public function manageEnvironment(User $user, Service $service): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $service->team()->first()->id) !== null;
|
$team = $service->team();
|
||||||
|
if (! $team) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->isAdmin() && $user->teams->contains('id', $team->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,6 +111,18 @@ class ServicePolicy
|
|||||||
*/
|
*/
|
||||||
public function deploy(User $user, Service $service): bool
|
public function deploy(User $user, Service $service): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $service->team()->first()->id) !== null;
|
$team = $service->team();
|
||||||
|
if (! $team) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->teams->contains('id', $team->id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function accessTerminal(User $user, Service $service): bool
|
||||||
|
{
|
||||||
|
// return $user->isAdmin() || $user->teams->contains('id', $service->team()->id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
79
app/Policies/SharedEnvironmentVariablePolicy.php
Normal file
79
app/Policies/SharedEnvironmentVariablePolicy.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\SharedEnvironmentVariable;
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
class SharedEnvironmentVariablePolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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, SharedEnvironmentVariable $sharedEnvironmentVariable): bool
|
||||||
|
{
|
||||||
|
return $user->teams->contains('id', $sharedEnvironmentVariable->team_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create models.
|
||||||
|
*/
|
||||||
|
public function create(User $user): bool
|
||||||
|
{
|
||||||
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*/
|
||||||
|
public function update(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool
|
||||||
|
{
|
||||||
|
// return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*/
|
||||||
|
public function delete(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool
|
||||||
|
{
|
||||||
|
// return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can restore the model.
|
||||||
|
*/
|
||||||
|
public function restore(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool
|
||||||
|
{
|
||||||
|
// return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can permanently delete the model.
|
||||||
|
*/
|
||||||
|
public function forceDelete(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool
|
||||||
|
{
|
||||||
|
// return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can manage environment variables.
|
||||||
|
*/
|
||||||
|
public function manageEnvironment(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool
|
||||||
|
{
|
||||||
|
// return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -20,7 +20,7 @@ class StandaloneDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function view(User $user, StandaloneDocker $standaloneDocker): bool
|
public function view(User $user, StandaloneDocker $standaloneDocker): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $standaloneDocker->server->team_id) !== null;
|
return $user->teams->contains('id', $standaloneDocker->server->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +28,8 @@ class StandaloneDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin();
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +37,8 @@ class StandaloneDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function update(User $user, StandaloneDocker $standaloneDocker): bool
|
public function update(User $user, StandaloneDocker $standaloneDocker): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $standaloneDocker->server->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $standaloneDocker->server->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +46,8 @@ class StandaloneDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, StandaloneDocker $standaloneDocker): bool
|
public function delete(User $user, StandaloneDocker $standaloneDocker): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $standaloneDocker->server->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $standaloneDocker->server->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +55,8 @@ class StandaloneDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function restore(User $user, StandaloneDocker $standaloneDocker): bool
|
public function restore(User $user, StandaloneDocker $standaloneDocker): bool
|
||||||
{
|
{
|
||||||
return false;
|
// return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,6 +64,7 @@ class StandaloneDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function forceDelete(User $user, StandaloneDocker $standaloneDocker): bool
|
public function forceDelete(User $user, StandaloneDocker $standaloneDocker): bool
|
||||||
{
|
{
|
||||||
return false;
|
// return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,7 @@ class SwarmDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function view(User $user, SwarmDocker $swarmDocker): bool
|
public function view(User $user, SwarmDocker $swarmDocker): bool
|
||||||
{
|
{
|
||||||
return $user->teams()->get()->firstWhere('id', $swarmDocker->server->team_id) !== null;
|
return $user->teams->contains('id', $swarmDocker->server->team_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +28,8 @@ class SwarmDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function create(User $user): bool
|
public function create(User $user): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin();
|
// return $user->isAdmin();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +37,8 @@ class SwarmDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function update(User $user, SwarmDocker $swarmDocker): bool
|
public function update(User $user, SwarmDocker $swarmDocker): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $swarmDocker->server->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $swarmDocker->server->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +46,8 @@ class SwarmDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function delete(User $user, SwarmDocker $swarmDocker): bool
|
public function delete(User $user, SwarmDocker $swarmDocker): bool
|
||||||
{
|
{
|
||||||
return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $swarmDocker->server->team_id) !== null;
|
// return $user->isAdmin() && $user->teams->contains('id', $swarmDocker->server->team_id);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +55,8 @@ class SwarmDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function restore(User $user, SwarmDocker $swarmDocker): bool
|
public function restore(User $user, SwarmDocker $swarmDocker): bool
|
||||||
{
|
{
|
||||||
return false;
|
// return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,6 +64,7 @@ class SwarmDockerPolicy
|
|||||||
*/
|
*/
|
||||||
public function forceDelete(User $user, SwarmDocker $swarmDocker): bool
|
public function forceDelete(User $user, SwarmDocker $swarmDocker): bool
|
||||||
{
|
{
|
||||||
return false;
|
// return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
104
app/Policies/TeamPolicy.php
Normal file
104
app/Policies/TeamPolicy.php
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\Team;
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
class TeamPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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, Team $team): bool
|
||||||
|
{
|
||||||
|
return $user->teams->contains('id', $team->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create models.
|
||||||
|
*/
|
||||||
|
public function create(User $user): bool
|
||||||
|
{
|
||||||
|
// All authenticated users can create teams
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*/
|
||||||
|
public function update(User $user, Team $team): bool
|
||||||
|
{
|
||||||
|
// Only admins and owners can update team settings
|
||||||
|
if (! $user->teams->contains('id', $team->id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->isAdmin() || $user->isOwner();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*/
|
||||||
|
public function delete(User $user, Team $team): bool
|
||||||
|
{
|
||||||
|
// Only admins and owners can delete teams
|
||||||
|
if (! $user->teams->contains('id', $team->id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->isAdmin() || $user->isOwner();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can manage team members.
|
||||||
|
*/
|
||||||
|
public function manageMembers(User $user, Team $team): bool
|
||||||
|
{
|
||||||
|
// Only admins and owners can manage team members
|
||||||
|
if (! $user->teams->contains('id', $team->id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->isAdmin() || $user->isOwner();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view admin panel.
|
||||||
|
*/
|
||||||
|
public function viewAdmin(User $user, Team $team): bool
|
||||||
|
{
|
||||||
|
// Only admins and owners can view admin panel
|
||||||
|
if (! $user->teams->contains('id', $team->id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->isAdmin() || $user->isOwner();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can manage invitations.
|
||||||
|
*/
|
||||||
|
public function manageInvitations(User $user, Team $team): bool
|
||||||
|
{
|
||||||
|
// Only admins and owners can manage invitations
|
||||||
|
if (! $user->teams->contains('id', $team->id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return $user->isAdmin() || $user->isOwner();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -23,8 +23,11 @@ class AuthServiceProvider extends ServiceProvider
|
|||||||
\App\Models\ApplicationPreview::class => \App\Policies\ApplicationPreviewPolicy::class,
|
\App\Models\ApplicationPreview::class => \App\Policies\ApplicationPreviewPolicy::class,
|
||||||
\App\Models\ApplicationSetting::class => \App\Policies\ApplicationSettingPolicy::class,
|
\App\Models\ApplicationSetting::class => \App\Policies\ApplicationSettingPolicy::class,
|
||||||
\App\Models\Service::class => \App\Policies\ServicePolicy::class,
|
\App\Models\Service::class => \App\Policies\ServicePolicy::class,
|
||||||
|
\App\Models\ServiceApplication::class => \App\Policies\ServiceApplicationPolicy::class,
|
||||||
|
\App\Models\ServiceDatabase::class => \App\Policies\ServiceDatabasePolicy::class,
|
||||||
\App\Models\Project::class => \App\Policies\ProjectPolicy::class,
|
\App\Models\Project::class => \App\Policies\ProjectPolicy::class,
|
||||||
\App\Models\Environment::class => \App\Policies\EnvironmentPolicy::class,
|
\App\Models\Environment::class => \App\Policies\EnvironmentPolicy::class,
|
||||||
|
\App\Models\SharedEnvironmentVariable::class => \App\Policies\SharedEnvironmentVariablePolicy::class,
|
||||||
// Database policies - all use the shared DatabasePolicy
|
// Database policies - all use the shared DatabasePolicy
|
||||||
\App\Models\StandalonePostgresql::class => \App\Policies\DatabasePolicy::class,
|
\App\Models\StandalonePostgresql::class => \App\Policies\DatabasePolicy::class,
|
||||||
\App\Models\StandaloneMysql::class => \App\Policies\DatabasePolicy::class,
|
\App\Models\StandaloneMysql::class => \App\Policies\DatabasePolicy::class,
|
||||||
@@ -35,6 +38,22 @@ class AuthServiceProvider extends ServiceProvider
|
|||||||
\App\Models\StandaloneDragonfly::class => \App\Policies\DatabasePolicy::class,
|
\App\Models\StandaloneDragonfly::class => \App\Policies\DatabasePolicy::class,
|
||||||
\App\Models\StandaloneClickhouse::class => \App\Policies\DatabasePolicy::class,
|
\App\Models\StandaloneClickhouse::class => \App\Policies\DatabasePolicy::class,
|
||||||
|
|
||||||
|
// Notification policies - all use the shared NotificationPolicy
|
||||||
|
\App\Models\EmailNotificationSettings::class => \App\Policies\NotificationPolicy::class,
|
||||||
|
\App\Models\DiscordNotificationSettings::class => \App\Policies\NotificationPolicy::class,
|
||||||
|
\App\Models\TelegramNotificationSettings::class => \App\Policies\NotificationPolicy::class,
|
||||||
|
\App\Models\SlackNotificationSettings::class => \App\Policies\NotificationPolicy::class,
|
||||||
|
\App\Models\PushoverNotificationSettings::class => \App\Policies\NotificationPolicy::class,
|
||||||
|
|
||||||
|
// API Token policy
|
||||||
|
\Laravel\Sanctum\PersonalAccessToken::class => \App\Policies\ApiTokenPolicy::class,
|
||||||
|
|
||||||
|
// Team policy
|
||||||
|
\App\Models\Team::class => \App\Policies\TeamPolicy::class,
|
||||||
|
|
||||||
|
// Git source policies
|
||||||
|
\App\Models\GithubApp::class => \App\Policies\GithubAppPolicy::class,
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,5 +63,11 @@ class AuthServiceProvider extends ServiceProvider
|
|||||||
{
|
{
|
||||||
// Register gates for resource creation policy
|
// Register gates for resource creation policy
|
||||||
Gate::define('createAnyResource', [ResourceCreatePolicy::class, 'createAny']);
|
Gate::define('createAnyResource', [ResourceCreatePolicy::class, 'createAny']);
|
||||||
|
|
||||||
|
// Register gate for terminal access
|
||||||
|
Gate::define('canAccessTerminal', function ($user) {
|
||||||
|
// return $user->isAdmin() || $user->isOwner();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ namespace App\View\Components\Forms;
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
|
|
||||||
class Button extends Component
|
class Button extends Component
|
||||||
@@ -17,7 +18,19 @@ class Button extends Component
|
|||||||
public ?string $modalId = null,
|
public ?string $modalId = null,
|
||||||
public string $defaultClass = 'button',
|
public string $defaultClass = 'button',
|
||||||
public bool $showLoadingIndicator = true,
|
public bool $showLoadingIndicator = true,
|
||||||
|
public ?string $canGate = null,
|
||||||
|
public mixed $canResource = null,
|
||||||
|
public bool $autoDisable = true,
|
||||||
) {
|
) {
|
||||||
|
// Handle authorization-based disabling
|
||||||
|
if ($this->canGate && $this->canResource && $this->autoDisable) {
|
||||||
|
$hasPermission = Gate::allows($this->canGate, $this->canResource);
|
||||||
|
|
||||||
|
if (! $hasPermission) {
|
||||||
|
$this->disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->noStyle) {
|
if ($this->noStyle) {
|
||||||
$this->defaultClass = '';
|
$this->defaultClass = '';
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ namespace App\View\Components\Forms;
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
|
|
||||||
class Checkbox extends Component
|
class Checkbox extends Component
|
||||||
@@ -22,7 +23,20 @@ class Checkbox extends Component
|
|||||||
public string|bool $instantSave = false,
|
public string|bool $instantSave = false,
|
||||||
public bool $disabled = false,
|
public bool $disabled = false,
|
||||||
public string $defaultClass = 'dark:border-neutral-700 text-coolgray-400 focus:ring-warning dark:bg-coolgray-100 rounded-sm cursor-pointer dark:disabled:bg-base dark:disabled:cursor-not-allowed',
|
public string $defaultClass = 'dark:border-neutral-700 text-coolgray-400 focus:ring-warning dark:bg-coolgray-100 rounded-sm cursor-pointer dark:disabled:bg-base dark:disabled:cursor-not-allowed',
|
||||||
|
public ?string $canGate = null,
|
||||||
|
public mixed $canResource = null,
|
||||||
|
public bool $autoDisable = true,
|
||||||
) {
|
) {
|
||||||
|
// Handle authorization-based disabling
|
||||||
|
if ($this->canGate && $this->canResource && $this->autoDisable) {
|
||||||
|
$hasPermission = Gate::allows($this->canGate, $this->canResource);
|
||||||
|
|
||||||
|
if (! $hasPermission) {
|
||||||
|
$this->disabled = true;
|
||||||
|
$this->instantSave = false; // Disable instant save for unauthorized users
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->disabled) {
|
if ($this->disabled) {
|
||||||
$this->defaultClass .= ' opacity-40';
|
$this->defaultClass .= ' opacity-40';
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ namespace App\View\Components\Forms;
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
@@ -26,7 +27,19 @@ class Input extends Component
|
|||||||
public ?int $minlength = null,
|
public ?int $minlength = null,
|
||||||
public ?int $maxlength = null,
|
public ?int $maxlength = null,
|
||||||
public bool $autofocus = false,
|
public bool $autofocus = false,
|
||||||
) {}
|
public ?string $canGate = null,
|
||||||
|
public mixed $canResource = null,
|
||||||
|
public bool $autoDisable = true,
|
||||||
|
) {
|
||||||
|
// Handle authorization-based disabling
|
||||||
|
if ($this->canGate && $this->canResource && $this->autoDisable) {
|
||||||
|
$hasPermission = Gate::allows($this->canGate, $this->canResource);
|
||||||
|
|
||||||
|
if (! $hasPermission) {
|
||||||
|
$this->disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function render(): View|Closure|string
|
public function render(): View|Closure|string
|
||||||
{
|
{
|
||||||
|
@@ -4,6 +4,7 @@ namespace App\View\Components\Forms;
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
@@ -19,9 +20,19 @@ class Select extends Component
|
|||||||
public ?string $helper = null,
|
public ?string $helper = null,
|
||||||
public bool $required = false,
|
public bool $required = false,
|
||||||
public bool $disabled = false,
|
public bool $disabled = false,
|
||||||
public string $defaultClass = 'select w-full'
|
public string $defaultClass = 'select w-full',
|
||||||
|
public ?string $canGate = null,
|
||||||
|
public mixed $canResource = null,
|
||||||
|
public bool $autoDisable = true,
|
||||||
) {
|
) {
|
||||||
//
|
// Handle authorization-based disabling
|
||||||
|
if ($this->canGate && $this->canResource && $this->autoDisable) {
|
||||||
|
$hasPermission = Gate::allows($this->canGate, $this->canResource);
|
||||||
|
|
||||||
|
if (! $hasPermission) {
|
||||||
|
$this->disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -4,6 +4,7 @@ namespace App\View\Components\Forms;
|
|||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Contracts\View\View;
|
use Illuminate\Contracts\View\View;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
|
||||||
@@ -33,8 +34,18 @@ class Textarea extends Component
|
|||||||
public string $defaultClassInput = 'input',
|
public string $defaultClassInput = 'input',
|
||||||
public ?int $minlength = null,
|
public ?int $minlength = null,
|
||||||
public ?int $maxlength = null,
|
public ?int $maxlength = null,
|
||||||
|
public ?string $canGate = null,
|
||||||
|
public mixed $canResource = null,
|
||||||
|
public bool $autoDisable = true,
|
||||||
) {
|
) {
|
||||||
//
|
// Handle authorization-based disabling
|
||||||
|
if ($this->canGate && $this->canResource && $this->autoDisable) {
|
||||||
|
$hasPermission = Gate::allows($this->canGate, $this->canResource);
|
||||||
|
|
||||||
|
if (! $hasPermission) {
|
||||||
|
$this->disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -59,20 +59,20 @@
|
|||||||
if (this.zoom === '90') {
|
if (this.zoom === '90') {
|
||||||
const style = document.createElement('style');
|
const style = document.createElement('style');
|
||||||
style.textContent = `
|
style.textContent = `
|
||||||
html {
|
html {
|
||||||
font-size: 93.75%;
|
font-size: 93.75%;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--vh: 1vh;
|
--vh: 1vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
html {
|
html {
|
||||||
font-size: 87.5%;
|
font-size: 87.5%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,20 +229,22 @@
|
|||||||
Tags
|
Tags
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
@can('canAccessTerminal')
|
||||||
<a title="Terminal"
|
<li>
|
||||||
class="{{ request()->is('terminal*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
<a title="Terminal"
|
||||||
href="{{ route('terminal') }}">
|
class="{{ request()->is('terminal*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
|
href="{{ route('terminal') }}">
|
||||||
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
|
||||||
stroke-linejoin="round">
|
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
stroke-linejoin="round">
|
||||||
<path d="M5 7l5 5l-5 5" />
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
<path d="M12 19l7 0" />
|
<path d="M5 7l5 5l-5 5" />
|
||||||
</svg>
|
<path d="M12 19l7 0" />
|
||||||
Terminal
|
</svg>
|
||||||
</a>
|
Terminal
|
||||||
</li>
|
</a>
|
||||||
|
</li>
|
||||||
|
@endcan
|
||||||
<li>
|
<li>
|
||||||
<a title="Profile"
|
<a title="Profile"
|
||||||
class="{{ request()->is('profile*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
class="{{ request()->is('profile*') ? 'menu-item-active menu-item' : 'menu-item' }}"
|
||||||
|
@@ -5,9 +5,11 @@
|
|||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h1>Destinations</h1>
|
<h1>Destinations</h1>
|
||||||
@if ($servers->count() > 0)
|
@if ($servers->count() > 0)
|
||||||
<x-modal-input buttonTitle="+ Add" title="New Destination">
|
@can('createAnyResource')
|
||||||
<livewire:destination.new.docker />
|
<x-modal-input buttonTitle="+ Add" title="New Destination">
|
||||||
</x-modal-input>
|
<livewire:destination.new.docker />
|
||||||
|
</x-modal-input>
|
||||||
|
@endcan
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="subtitle">Network endpoints to deploy your resources.</div>
|
<div class="subtitle">Network endpoints to deploy your resources.</div>
|
||||||
|
@@ -1,18 +1,25 @@
|
|||||||
<div class="w-full ">
|
@can('createAnyResource')
|
||||||
<div class="subtitle">Destinations are used to segregate resources by network.</div>
|
<div class="w-full ">
|
||||||
<form class="flex flex-col gap-4" wire:submit='submit'>
|
<div class="subtitle">Destinations are used to segregate resources by network.</div>
|
||||||
<div class="flex gap-2">
|
<form class="flex flex-col gap-4" wire:submit='submit'>
|
||||||
<x-forms.input id="name" label="Name" required />
|
<div class="flex gap-2">
|
||||||
<x-forms.input id="network" label="Network" required />
|
<x-forms.input id="name" label="Name" required />
|
||||||
</div>
|
<x-forms.input id="network" label="Network" required />
|
||||||
<x-forms.select id="serverId" label="Select a server" required wire:change="generateName">
|
</div>
|
||||||
<option disabled>Select a server</option>
|
<x-forms.select id="serverId" label="Select a server" required wire:change="generateName">
|
||||||
@foreach ($servers as $server)
|
<option disabled>Select a server</option>
|
||||||
<option value="{{ $server->id }}">{{ $server->name }}</option>
|
@foreach ($servers as $server)
|
||||||
@endforeach
|
<option value="{{ $server->id }}">{{ $server->name }}</option>
|
||||||
</x-forms.select>
|
@endforeach
|
||||||
<x-forms.button type="submit">
|
</x-forms.select>
|
||||||
Continue
|
<x-forms.button type="submit">
|
||||||
</x-forms.button>
|
Continue
|
||||||
</form>
|
</x-forms.button>
|
||||||
</div>
|
</form>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="text-gray-500 p-4 text-center">
|
||||||
|
<p>You don't have permission to create new destinations.</p>
|
||||||
|
<p class="text-sm">Please contact your team administrator for access.</p>
|
||||||
|
</div>
|
||||||
|
@endcan
|
||||||
|
@@ -2,14 +2,14 @@
|
|||||||
<form class="flex flex-col">
|
<form class="flex flex-col">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h1>Destination</h1>
|
<h1>Destination</h1>
|
||||||
<x-forms.button wire:click.prevent='submit' type="submit">
|
<x-forms.button canGate="update" :canResource="$destination" wire:click.prevent='submit'
|
||||||
Save
|
type="submit">Save</x-forms.button>
|
||||||
</x-forms.button>
|
|
||||||
@if ($network !== 'coolify')
|
@if ($network !== 'coolify')
|
||||||
<x-modal-confirmation title="Confirm Destination Deletion?" buttonTitle="Delete Destination" isErrorButton
|
<x-modal-confirmation title="Confirm Destination Deletion?" buttonTitle="Delete Destination" isErrorButton
|
||||||
submitAction="delete" :actions="['This will delete the selected destination/network.']" confirmationText="{{ $destination->name }}"
|
submitAction="delete" :actions="['This will delete the selected destination/network.']" confirmationText="{{ $destination->name }}"
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Destination Name below"
|
confirmationLabel="Please confirm the execution of the actions by entering the Destination Name below"
|
||||||
shortConfirmationLabel="Destination Name" :confirmWithPassword="false" step2ButtonText="Permanently Delete" />
|
shortConfirmationLabel="Destination Name" :confirmWithPassword="false" step2ButtonText="Permanently Delete"
|
||||||
|
canGate="delete" :canResource="$destination" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<div class="subtitle ">A swarm Docker network. WIP</div>
|
<div class="subtitle ">A swarm Docker network. WIP</div>
|
||||||
@endif
|
@endif
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input id="name" label="Name" />
|
<x-forms.input canGate="update" :canResource="$destination" id="name" label="Name" />
|
||||||
<x-forms.input id="serverIp" label="Server IP" readonly />
|
<x-forms.input id="serverIp" label="Server IP" readonly />
|
||||||
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
|
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
|
||||||
<x-forms.input id="network" label="Docker Network" readonly />
|
<x-forms.input id="network" label="Docker Network" readonly />
|
||||||
|
@@ -6,27 +6,27 @@
|
|||||||
<form wire:submit='submit' class="flex flex-col gap-4 pb-4">
|
<form wire:submit='submit' class="flex flex-col gap-4 pb-4">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>Discord</h2>
|
<h2>Discord</h2>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button canGate="update" :canResource="$settings" type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@if ($discordEnabled)
|
@if ($discordEnabled)
|
||||||
<x-forms.button class="normal-case dark:text-white btn btn-xs no-animation btn-primary"
|
<x-forms.button canGate="sendTest" :canResource="$settings" class="normal-case dark:text-white btn btn-xs no-animation btn-primary"
|
||||||
wire:click="sendTestNotification">
|
wire:click="sendTestNotification">
|
||||||
Send Test Notification
|
Send Test Notification
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@else
|
@else
|
||||||
<x-forms.button disabled class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
|
<x-forms.button canGate="sendTest" :canResource="$settings" disabled class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
|
||||||
Send Test Notification
|
Send Test Notification
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="w-48">
|
<div class="w-48">
|
||||||
<x-forms.checkbox instantSave="instantSaveDiscordEnabled" id="discordEnabled" label="Enabled" />
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="instantSaveDiscordEnabled" id="discordEnabled" label="Enabled" />
|
||||||
<x-forms.checkbox instantSave="instantSaveDiscordPingEnabled" id="discordPingEnabled"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="instantSaveDiscordPingEnabled" id="discordPingEnabled"
|
||||||
helper="If enabled, a ping (@here) will be sent to the notification when a critical event happens."
|
helper="If enabled, a ping (@here) will be sent to the notification when a critical event happens."
|
||||||
label="Ping Enabled" />
|
label="Ping Enabled" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password"
|
<x-forms.input canGate="update" :canResource="$settings" type="password"
|
||||||
helper="Create a Discord Server and generate a Webhook URL. <br><a class='inline-block underline dark:text-white' href='https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks' target='_blank'>Webhook Documentation</a>"
|
helper="Create a Discord Server and generate a Webhook URL. <br><a class='inline-block underline dark:text-white' href='https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks' target='_blank'>Webhook Documentation</a>"
|
||||||
required id="discordWebhookUrl" label="Webhook" />
|
required id="discordWebhookUrl" label="Webhook" />
|
||||||
</form>
|
</form>
|
||||||
@@ -38,11 +38,11 @@
|
|||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Deployments</h3>
|
<h3 class="font-medium mb-3">Deployments</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="deploymentSuccessDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentSuccessDiscordNotifications"
|
||||||
label="Deployment Success" />
|
label="Deployment Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="deploymentFailureDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentFailureDiscordNotifications"
|
||||||
label="Deployment Failure" />
|
label="Deployment Failure" />
|
||||||
<x-forms.checkbox instantSave="saveModel"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel"
|
||||||
helper="Send a notification when a container status changes. It will notify for Stopped and Restarted events of a container."
|
helper="Send a notification when a container status changes. It will notify for Stopped and Restarted events of a container."
|
||||||
id="statusChangeDiscordNotifications" label="Container Status Changes" />
|
id="statusChangeDiscordNotifications" label="Container Status Changes" />
|
||||||
</div>
|
</div>
|
||||||
@@ -50,35 +50,35 @@
|
|||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Backups</h3>
|
<h3 class="font-medium mb-3">Backups</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="backupSuccessDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupSuccessDiscordNotifications"
|
||||||
label="Backup Success" />
|
label="Backup Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="backupFailureDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupFailureDiscordNotifications"
|
||||||
label="Backup Failure" />
|
label="Backup Failure" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Scheduled Tasks</h3>
|
<h3 class="font-medium mb-3">Scheduled Tasks</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="scheduledTaskSuccessDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskSuccessDiscordNotifications"
|
||||||
label="Scheduled Task Success" />
|
label="Scheduled Task Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="scheduledTaskFailureDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskFailureDiscordNotifications"
|
||||||
label="Scheduled Task Failure" />
|
label="Scheduled Task Failure" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Server</h3>
|
<h3 class="font-medium mb-3">Server</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="dockerCleanupSuccessDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupSuccessDiscordNotifications"
|
||||||
label="Docker Cleanup Success" />
|
label="Docker Cleanup Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="dockerCleanupFailureDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupFailureDiscordNotifications"
|
||||||
label="Docker Cleanup Failure" />
|
label="Docker Cleanup Failure" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverDiskUsageDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverDiskUsageDiscordNotifications"
|
||||||
label="Server Disk Usage" />
|
label="Server Disk Usage" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverReachableDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverReachableDiscordNotifications"
|
||||||
label="Server Reachable" />
|
label="Server Reachable" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverUnreachableDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverUnreachableDiscordNotifications"
|
||||||
label="Server Unreachable" />
|
label="Server Unreachable" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverPatchDiscordNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverPatchDiscordNotifications"
|
||||||
label="Server Patching" />
|
label="Server Patching" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -6,41 +6,43 @@
|
|||||||
<form wire:submit='submit' class="flex flex-col gap-4 pb-4">
|
<form wire:submit='submit' class="flex flex-col gap-4 pb-4">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>Email</h2>
|
<h2>Email</h2>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button canGate="update" :canResource="$settings" type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@if (auth()->user()->isAdminFromSession())
|
@if (auth()->user()->isAdminFromSession())
|
||||||
@if ($team->isNotificationEnabled('email'))
|
@can('sendTest', $settings)
|
||||||
<x-modal-input buttonTitle="Send Test Email" title="Send Test Email">
|
@if ($team->isNotificationEnabled('email'))
|
||||||
<form wire:submit.prevent="sendTestEmail" class="flex flex-col w-full gap-2">
|
<x-modal-input buttonTitle="Send Test Email" title="Send Test Email">
|
||||||
<x-forms.input wire:model="testEmailAddress" placeholder="test@example.com"
|
<form wire:submit.prevent="sendTestEmail" class="flex flex-col w-full gap-2">
|
||||||
id="testEmailAddress" label="Recipient" required />
|
<x-forms.input wire:model="testEmailAddress" placeholder="test@example.com"
|
||||||
<x-forms.button type="submit" @click="modalOpen=false">
|
id="testEmailAddress" label="Recipient" required />
|
||||||
Send Email
|
<x-forms.button type="submit" @click="modalOpen=false">
|
||||||
</x-forms.button>
|
Send Email
|
||||||
</form>
|
</x-forms.button>
|
||||||
</x-modal-input>
|
</form>
|
||||||
@else
|
</x-modal-input>
|
||||||
<x-forms.button disabled class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
|
@else
|
||||||
Send Test Email
|
<x-forms.button disabled class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
|
||||||
</x-forms.button>
|
Send Test Email
|
||||||
@endif
|
</x-forms.button>
|
||||||
|
@endif
|
||||||
|
@endcan
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@if (!isCloud())
|
@if (!isCloud())
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="instantSave()" id="useInstanceEmailSettings"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="instantSave()" id="useInstanceEmailSettings"
|
||||||
label="Use system wide (transactional) email settings" />
|
label="Use system wide (transactional) email settings" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@if (!$useInstanceEmailSettings)
|
@if (!$useInstanceEmailSettings)
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input required id="smtpFromName" helper="Name used in emails." label="From Name" />
|
<x-forms.input canGate="update" :canResource="$settings" required id="smtpFromName" helper="Name used in emails." label="From Name" />
|
||||||
<x-forms.input required id="smtpFromAddress" helper="Email address used in emails."
|
<x-forms.input canGate="update" :canResource="$settings" required id="smtpFromAddress" helper="Email address used in emails."
|
||||||
label="From Address" />
|
label="From Address" />
|
||||||
</div>
|
</div>
|
||||||
@if (isInstanceAdmin() && !$useInstanceEmailSettings)
|
@if (isInstanceAdmin() && !$useInstanceEmailSettings)
|
||||||
<x-forms.button wire:click='copyFromInstanceSettings'>
|
<x-forms.button canGate="update" :canResource="$settings" wire:click='copyFromInstanceSettings'>
|
||||||
Copy from Instance Settings
|
Copy from Instance Settings
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
@@ -48,7 +50,7 @@
|
|||||||
</form>
|
</form>
|
||||||
@if (isCloud())
|
@if (isCloud())
|
||||||
<div class="w-64 py-4">
|
<div class="w-64 py-4">
|
||||||
<x-forms.checkbox instantSave="instantSave()" id="useInstanceEmailSettings"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="instantSave()" id="useInstanceEmailSettings"
|
||||||
label="Use Hosted Email Service" />
|
label="Use Hosted Email Service" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@@ -58,29 +60,29 @@
|
|||||||
class="p-4 border dark:border-coolgray-300 border-neutral-200 flex flex-col gap-2">
|
class="p-4 border dark:border-coolgray-300 border-neutral-200 flex flex-col gap-2">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h3>SMTP Server</h3>
|
<h3>SMTP Server</h3>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button canGate="update" :canResource="$settings" type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-32">
|
<div class="w-32">
|
||||||
<x-forms.checkbox wire:model="smtpEnabled" instantSave="instantSave('SMTP')" id="smtpEnabled"
|
<x-forms.checkbox canGate="update" :canResource="$settings" wire:model="smtpEnabled" instantSave="instantSave('SMTP')" id="smtpEnabled"
|
||||||
label="Enabled" />
|
label="Enabled" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||||
<x-forms.input required id="smtpHost" placeholder="smtp.mailgun.org" label="Host" />
|
<x-forms.input canGate="update" :canResource="$settings" required id="smtpHost" placeholder="smtp.mailgun.org" label="Host" />
|
||||||
<x-forms.input required id="smtpPort" placeholder="587" label="Port" />
|
<x-forms.input canGate="update" :canResource="$settings" required id="smtpPort" placeholder="587" label="Port" />
|
||||||
<x-forms.select required id="smtpEncryption" label="Encryption">
|
<x-forms.select canGate="update" :canResource="$settings" required id="smtpEncryption" label="Encryption">
|
||||||
<option value="starttls">StartTLS</option>
|
<option value="starttls">StartTLS</option>
|
||||||
<option value="tls">TLS/SSL</option>
|
<option value="tls">TLS/SSL</option>
|
||||||
<option value="none">None</option>
|
<option value="none">None</option>
|
||||||
</x-forms.select>
|
</x-forms.select>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||||
<x-forms.input id="smtpUsername" label="SMTP Username" />
|
<x-forms.input canGate="update" :canResource="$settings" id="smtpUsername" label="SMTP Username" />
|
||||||
<x-forms.input id="smtpPassword" type="password" label="SMTP Password" />
|
<x-forms.input canGate="update" :canResource="$settings" id="smtpPassword" type="password" label="SMTP Password" />
|
||||||
<x-forms.input id="smtpTimeout" helper="Timeout value for sending emails."
|
<x-forms.input canGate="update" :canResource="$settings" id="smtpTimeout" helper="Timeout value for sending emails."
|
||||||
label="Timeout" />
|
label="Timeout" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -90,18 +92,18 @@
|
|||||||
class="p-4 border dark:border-coolgray-300 border-neutral-200 flex flex-col gap-2">
|
class="p-4 border dark:border-coolgray-300 border-neutral-200 flex flex-col gap-2">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h3>Resend</h3>
|
<h3>Resend</h3>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button canGate="update" :canResource="$settings" type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-32">
|
<div class="w-32">
|
||||||
<x-forms.checkbox wire:model="resendEnabled" instantSave="instantSave('Resend')" id="resendEnabled"
|
<x-forms.checkbox canGate="update" :canResource="$settings" wire:model="resendEnabled" instantSave="instantSave('Resend')" id="resendEnabled"
|
||||||
label="Enabled" />
|
label="Enabled" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
<div class="flex flex-col w-full gap-2 xl:flex-row">
|
||||||
<x-forms.input required type="password" id="resendApiKey" placeholder="API key"
|
<x-forms.input canGate="update" :canResource="$settings" required type="password" id="resendApiKey" placeholder="API key"
|
||||||
label="API Key" />
|
label="API Key" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -117,11 +119,11 @@
|
|||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Deployments</h3>
|
<h3 class="font-medium mb-3">Deployments</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="deploymentSuccessEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentSuccessEmailNotifications"
|
||||||
label="Deployment Success" />
|
label="Deployment Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="deploymentFailureEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentFailureEmailNotifications"
|
||||||
label="Deployment Failure" />
|
label="Deployment Failure" />
|
||||||
<x-forms.checkbox instantSave="saveModel"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel"
|
||||||
helper="Send an email when a container status changes. It will send and email for Stopped and Restarted events of a container."
|
helper="Send an email when a container status changes. It will send and email for Stopped and Restarted events of a container."
|
||||||
id="statusChangeEmailNotifications" label="Container Status Changes" />
|
id="statusChangeEmailNotifications" label="Container Status Changes" />
|
||||||
</div>
|
</div>
|
||||||
@@ -129,35 +131,35 @@
|
|||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Backups</h3>
|
<h3 class="font-medium mb-3">Backups</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="backupSuccessEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupSuccessEmailNotifications"
|
||||||
label="Backup Success" />
|
label="Backup Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="backupFailureEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupFailureEmailNotifications"
|
||||||
label="Backup Failure" />
|
label="Backup Failure" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Scheduled Tasks</h3>
|
<h3 class="font-medium mb-3">Scheduled Tasks</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="scheduledTaskSuccessEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskSuccessEmailNotifications"
|
||||||
label="Scheduled Task Success" />
|
label="Scheduled Task Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="scheduledTaskFailureEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskFailureEmailNotifications"
|
||||||
label="Scheduled Task Failure" />
|
label="Scheduled Task Failure" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Server</h3>
|
<h3 class="font-medium mb-3">Server</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="dockerCleanupSuccessEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupSuccessEmailNotifications"
|
||||||
label="Docker Cleanup Success" />
|
label="Docker Cleanup Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="dockerCleanupFailureEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupFailureEmailNotifications"
|
||||||
label="Docker Cleanup Failure" />
|
label="Docker Cleanup Failure" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverDiskUsageEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverDiskUsageEmailNotifications"
|
||||||
label="Server Disk Usage" />
|
label="Server Disk Usage" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverReachableEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverReachableEmailNotifications"
|
||||||
label="Server Reachable" />
|
label="Server Reachable" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverUnreachableEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverUnreachableEmailNotifications"
|
||||||
label="Server Unreachable" />
|
label="Server Unreachable" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverPatchEmailNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverPatchEmailNotifications"
|
||||||
label="Server Patching" />
|
label="Server Patching" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -6,28 +6,28 @@
|
|||||||
<form wire:submit='submit' class="flex flex-col gap-4 pb-4">
|
<form wire:submit='submit' class="flex flex-col gap-4 pb-4">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>Pushover</h2>
|
<h2>Pushover</h2>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button canGate="update" :canResource="$settings" type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@if ($pushoverEnabled)
|
@if ($pushoverEnabled)
|
||||||
<x-forms.button class="normal-case dark:text-white btn btn-xs no-animation btn-primary"
|
<x-forms.button canGate="sendTest" :canResource="$settings" class="normal-case dark:text-white btn btn-xs no-animation btn-primary"
|
||||||
wire:click="sendTestNotification">
|
wire:click="sendTestNotification">
|
||||||
Send Test Notification
|
Send Test Notification
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@else
|
@else
|
||||||
<x-forms.button disabled class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
|
<x-forms.button canGate="sendTest" :canResource="$settings" disabled class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
|
||||||
Send Test Notification
|
Send Test Notification
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="w-32">
|
<div class="w-32">
|
||||||
<x-forms.checkbox instantSave="instantSavePushoverEnabled" id="pushoverEnabled" label="Enabled" />
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="instantSavePushoverEnabled" id="pushoverEnabled" label="Enabled" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input type="password"
|
<x-forms.input canGate="update" :canResource="$settings" type="password"
|
||||||
helper="Get your User Key in Pushover. You need to be logged in to Pushover to see your user key in the top right corner. <br><a class='inline-block underline dark:text-white' href='https://pushover.net/' target='_blank'>Pushover Dashboard</a>"
|
helper="Get your User Key in Pushover. You need to be logged in to Pushover to see your user key in the top right corner. <br><a class='inline-block underline dark:text-white' href='https://pushover.net/' target='_blank'>Pushover Dashboard</a>"
|
||||||
required id="pushoverUserKey" label="User Key" />
|
required id="pushoverUserKey" label="User Key" />
|
||||||
<x-forms.input type="password"
|
<x-forms.input canGate="update" :canResource="$settings" type="password"
|
||||||
helper="Generate an API Token/Key in Pushover by creating a new application. <br><a class='inline-block underline dark:text-white' href='https://pushover.net/apps/build' target='_blank'>Create Pushover Application</a>"
|
helper="Generate an API Token/Key in Pushover by creating a new application. <br><a class='inline-block underline dark:text-white' href='https://pushover.net/apps/build' target='_blank'>Create Pushover Application</a>"
|
||||||
required id="pushoverApiToken" label="API Token" />
|
required id="pushoverApiToken" label="API Token" />
|
||||||
</div>
|
</div>
|
||||||
@@ -40,11 +40,11 @@
|
|||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Deployments</h3>
|
<h3 class="font-medium mb-3">Deployments</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="deploymentSuccessPushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentSuccessPushoverNotifications"
|
||||||
label="Deployment Success" />
|
label="Deployment Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="deploymentFailurePushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentFailurePushoverNotifications"
|
||||||
label="Deployment Failure" />
|
label="Deployment Failure" />
|
||||||
<x-forms.checkbox instantSave="saveModel"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel"
|
||||||
helper="Send a notification when a container status changes. It will notify for Stopped and Restarted events of a container."
|
helper="Send a notification when a container status changes. It will notify for Stopped and Restarted events of a container."
|
||||||
id="statusChangePushoverNotifications" label="Container Status Changes" />
|
id="statusChangePushoverNotifications" label="Container Status Changes" />
|
||||||
</div>
|
</div>
|
||||||
@@ -52,35 +52,35 @@
|
|||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Backups</h3>
|
<h3 class="font-medium mb-3">Backups</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="backupSuccessPushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupSuccessPushoverNotifications"
|
||||||
label="Backup Success" />
|
label="Backup Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="backupFailurePushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupFailurePushoverNotifications"
|
||||||
label="Backup Failure" />
|
label="Backup Failure" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Scheduled Tasks</h3>
|
<h3 class="font-medium mb-3">Scheduled Tasks</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="scheduledTaskSuccessPushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskSuccessPushoverNotifications"
|
||||||
label="Scheduled Task Success" />
|
label="Scheduled Task Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="scheduledTaskFailurePushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskFailurePushoverNotifications"
|
||||||
label="Scheduled Task Failure" />
|
label="Scheduled Task Failure" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Server</h3>
|
<h3 class="font-medium mb-3">Server</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="dockerCleanupSuccessPushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupSuccessPushoverNotifications"
|
||||||
label="Docker Cleanup Success" />
|
label="Docker Cleanup Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="dockerCleanupFailurePushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupFailurePushoverNotifications"
|
||||||
label="Docker Cleanup Failure" />
|
label="Docker Cleanup Failure" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverDiskUsagePushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverDiskUsagePushoverNotifications"
|
||||||
label="Server Disk Usage" />
|
label="Server Disk Usage" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverReachablePushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverReachablePushoverNotifications"
|
||||||
label="Server Reachable" />
|
label="Server Reachable" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverUnreachablePushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverUnreachablePushoverNotifications"
|
||||||
label="Server Unreachable" />
|
label="Server Unreachable" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverPatchPushoverNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverPatchPushoverNotifications"
|
||||||
label="Server Patching" />
|
label="Server Patching" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -6,24 +6,24 @@
|
|||||||
<form wire:submit='submit' class="flex flex-col gap-4 pb-4">
|
<form wire:submit='submit' class="flex flex-col gap-4 pb-4">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>Slack</h2>
|
<h2>Slack</h2>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button canGate="update" :canResource="$settings" type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@if ($slackEnabled)
|
@if ($slackEnabled)
|
||||||
<x-forms.button class="normal-case dark:text-white btn btn-xs no-animation btn-primary"
|
<x-forms.button canGate="sendTest" :canResource="$settings" class="normal-case dark:text-white btn btn-xs no-animation btn-primary"
|
||||||
wire:click="sendTestNotification">
|
wire:click="sendTestNotification">
|
||||||
Send Test Notification
|
Send Test Notification
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@else
|
@else
|
||||||
<x-forms.button disabled class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
|
<x-forms.button canGate="sendTest" :canResource="$settings" disabled class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
|
||||||
Send Test Notification
|
Send Test Notification
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="w-32">
|
<div class="w-32">
|
||||||
<x-forms.checkbox instantSave="instantSaveSlackEnabled" id="slackEnabled" label="Enabled" />
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="instantSaveSlackEnabled" id="slackEnabled" label="Enabled" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password"
|
<x-forms.input canGate="update" :canResource="$settings" type="password"
|
||||||
helper="Create a Slack APP and generate a Incoming Webhook URL. <br><a class='inline-block underline dark:text-white' href='https://api.slack.com/apps' target='_blank'>Create Slack APP</a>"
|
helper="Create a Slack APP and generate a Incoming Webhook URL. <br><a class='inline-block underline dark:text-white' href='https://api.slack.com/apps' target='_blank'>Create Slack APP</a>"
|
||||||
required id="slackWebhookUrl" label="Webhook" />
|
required id="slackWebhookUrl" label="Webhook" />
|
||||||
</form>
|
</form>
|
||||||
@@ -35,11 +35,11 @@
|
|||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Deployments</h3>
|
<h3 class="font-medium mb-3">Deployments</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="deploymentSuccessSlackNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentSuccessSlackNotifications"
|
||||||
label="Deployment Success" />
|
label="Deployment Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="deploymentFailureSlackNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentFailureSlackNotifications"
|
||||||
label="Deployment Failure" />
|
label="Deployment Failure" />
|
||||||
<x-forms.checkbox instantSave="saveModel"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel"
|
||||||
helper="Send a notification when a container status changes. It will notify for Stopped and Restarted events of a container."
|
helper="Send a notification when a container status changes. It will notify for Stopped and Restarted events of a container."
|
||||||
id="statusChangeSlackNotifications" label="Container Status Changes" />
|
id="statusChangeSlackNotifications" label="Container Status Changes" />
|
||||||
</div>
|
</div>
|
||||||
@@ -47,33 +47,33 @@
|
|||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Backups</h3>
|
<h3 class="font-medium mb-3">Backups</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="backupSuccessSlackNotifications" label="Backup Success" />
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupSuccessSlackNotifications" label="Backup Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="backupFailureSlackNotifications" label="Backup Failure" />
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupFailureSlackNotifications" label="Backup Failure" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Scheduled Tasks</h3>
|
<h3 class="font-medium mb-3">Scheduled Tasks</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="scheduledTaskSuccessSlackNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskSuccessSlackNotifications"
|
||||||
label="Scheduled Task Success" />
|
label="Scheduled Task Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="scheduledTaskFailureSlackNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskFailureSlackNotifications"
|
||||||
label="Scheduled Task Failure" />
|
label="Scheduled Task Failure" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
<div class="border dark:border-coolgray-300 border-neutral-200 p-4 rounded-lg">
|
||||||
<h3 class="font-medium mb-3">Server</h3>
|
<h3 class="font-medium mb-3">Server</h3>
|
||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="dockerCleanupSuccessSlackNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupSuccessSlackNotifications"
|
||||||
label="Docker Cleanup Success" />
|
label="Docker Cleanup Success" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="dockerCleanupFailureSlackNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupFailureSlackNotifications"
|
||||||
label="Docker Cleanup Failure" />
|
label="Docker Cleanup Failure" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverDiskUsageSlackNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverDiskUsageSlackNotifications"
|
||||||
label="Server Disk Usage" />
|
label="Server Disk Usage" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverReachableSlackNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverReachableSlackNotifications"
|
||||||
label="Server Reachable" />
|
label="Server Reachable" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverUnreachableSlackNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverUnreachableSlackNotifications"
|
||||||
label="Server Unreachable" />
|
label="Server Unreachable" />
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverPatchSlackNotifications" label="Server Patching" />
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverPatchSlackNotifications" label="Server Patching" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -6,28 +6,28 @@
|
|||||||
<form wire:submit='submit' class="flex flex-col gap-4 pb-4">
|
<form wire:submit='submit' class="flex flex-col gap-4 pb-4">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>Telegram</h2>
|
<h2>Telegram</h2>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button canGate="update" :canResource="$settings" type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@if ($telegramEnabled)
|
@if ($telegramEnabled)
|
||||||
<x-forms.button class="normal-case dark:text-white btn btn-xs no-animation btn-primary"
|
<x-forms.button canGate="sendTest" :canResource="$settings" class="normal-case dark:text-white btn btn-xs no-animation btn-primary"
|
||||||
wire:click="sendTestNotification">
|
wire:click="sendTestNotification">
|
||||||
Send Test Notification
|
Send Test Notification
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@else
|
@else
|
||||||
<x-forms.button disabled class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
|
<x-forms.button canGate="sendTest" :canResource="$settings" disabled class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
|
||||||
Send Test Notification
|
Send Test Notification
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="w-32">
|
<div class="w-32">
|
||||||
<x-forms.checkbox instantSave="instantSaveTelegramEnabled" id="telegramEnabled" label="Enabled" />
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="instantSaveTelegramEnabled" id="telegramEnabled" label="Enabled" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input type="password" autocomplete="new-password"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" autocomplete="new-password"
|
||||||
helper="Get it from the <a class='inline-block underline dark:text-white' href='https://t.me/botfather' target='_blank'>BotFather Bot</a> on Telegram."
|
helper="Get it from the <a class='inline-block underline dark:text-white' href='https://t.me/botfather' target='_blank'>BotFather Bot</a> on Telegram."
|
||||||
required id="telegramToken" label="Bot API Token" />
|
required id="telegramToken" label="Bot API Token" />
|
||||||
<x-forms.input type="password" autocomplete="new-password"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" autocomplete="new-password"
|
||||||
helper="Add your bot to a group chat and add its Chat ID here." required id="telegramChatId"
|
helper="Add your bot to a group chat and add its Chat ID here." required id="telegramChatId"
|
||||||
label="Chat ID" />
|
label="Chat ID" />
|
||||||
</div>
|
</div>
|
||||||
@@ -42,27 +42,27 @@
|
|||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="deploymentSuccessTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentSuccessTelegramNotifications"
|
||||||
label="Deployment Success" />
|
label="Deployment Success" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsDeploymentSuccessThreadId" />
|
id="telegramNotificationsDeploymentSuccessThreadId" />
|
||||||
</div>
|
</div>
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="deploymentFailureTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="deploymentFailureTelegramNotifications"
|
||||||
label="Deployment Failure" />
|
label="Deployment Failure" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsDeploymentFailureThreadId" />
|
id="telegramNotificationsDeploymentFailureThreadId" />
|
||||||
</div>
|
</div>
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="statusChangeTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="statusChangeTelegramNotifications"
|
||||||
label="Container Status Changes"
|
label="Container Status Changes"
|
||||||
helper="Send a notification when a container status changes. It will send a notification for Stopped and Restarted events of a container." />
|
helper="Send a notification when a container status changes. It will send a notification for Stopped and Restarted events of a container." />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" id="telegramNotificationsStatusChangeThreadId"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" id="telegramNotificationsStatusChangeThreadId"
|
||||||
placeholder="Custom Telegram Thread ID" />
|
placeholder="Custom Telegram Thread ID" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -72,19 +72,19 @@
|
|||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="backupSuccessTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupSuccessTelegramNotifications"
|
||||||
label="Backup Success" />
|
label="Backup Success" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsBackupSuccessThreadId" />
|
id="telegramNotificationsBackupSuccessThreadId" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="backupFailureTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="backupFailureTelegramNotifications"
|
||||||
label="Backup Failure" />
|
label="Backup Failure" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsBackupFailureThreadId" />
|
id="telegramNotificationsBackupFailureThreadId" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -95,19 +95,19 @@
|
|||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="scheduledTaskSuccessTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskSuccessTelegramNotifications"
|
||||||
label="Scheduled Task Success" />
|
label="Scheduled Task Success" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsScheduledTaskSuccessThreadId" />
|
id="telegramNotificationsScheduledTaskSuccessThreadId" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="scheduledTaskFailureTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="scheduledTaskFailureTelegramNotifications"
|
||||||
label="Scheduled Task Failure" />
|
label="Scheduled Task Failure" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsScheduledTaskFailureThreadId" />
|
id="telegramNotificationsScheduledTaskFailureThreadId" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -118,55 +118,55 @@
|
|||||||
<div class="flex flex-col gap-1.5 pl-1">
|
<div class="flex flex-col gap-1.5 pl-1">
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="dockerCleanupSuccessTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupSuccessTelegramNotifications"
|
||||||
label="Docker Cleanup Success" />
|
label="Docker Cleanup Success" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsDockerCleanupSuccessThreadId" />
|
id="telegramNotificationsDockerCleanupSuccessThreadId" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="dockerCleanupFailureTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="dockerCleanupFailureTelegramNotifications"
|
||||||
label="Docker Cleanup Failure" />
|
label="Docker Cleanup Failure" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsDockerCleanupFailureThreadId" />
|
id="telegramNotificationsDockerCleanupFailureThreadId" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverDiskUsageTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverDiskUsageTelegramNotifications"
|
||||||
label="Server Disk Usage" />
|
label="Server Disk Usage" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsServerDiskUsageThreadId" />
|
id="telegramNotificationsServerDiskUsageThreadId" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverReachableTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverReachableTelegramNotifications"
|
||||||
label="Server Reachable" />
|
label="Server Reachable" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsServerReachableThreadId" />
|
id="telegramNotificationsServerReachableThreadId" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverUnreachableTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverUnreachableTelegramNotifications"
|
||||||
label="Server Unreachable" />
|
label="Server Unreachable" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsServerUnreachableThreadId" />
|
id="telegramNotificationsServerUnreachableThreadId" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pl-1 flex gap-2">
|
<div class="pl-1 flex gap-2">
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox instantSave="saveModel" id="serverPatchTelegramNotifications"
|
<x-forms.checkbox canGate="update" :canResource="$settings" instantSave="saveModel" id="serverPatchTelegramNotifications"
|
||||||
label="Server Patching" />
|
label="Server Patching" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input type="password" placeholder="Custom Telegram Thread ID"
|
<x-forms.input canGate="update" :canResource="$settings" type="password" placeholder="Custom Telegram Thread ID"
|
||||||
id="telegramNotificationsServerPatchThreadId" />
|
id="telegramNotificationsServerPatchThreadId" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -8,76 +8,73 @@
|
|||||||
<h3>General</h3>
|
<h3>General</h3>
|
||||||
@if ($application->git_based())
|
@if ($application->git_based())
|
||||||
<x-forms.checkbox helper="Automatically deploy new commits based on Git webhooks." instantSave
|
<x-forms.checkbox helper="Automatically deploy new commits based on Git webhooks." instantSave
|
||||||
id="isAutoDeployEnabled" label="Auto Deploy" />
|
id="isAutoDeployEnabled" label="Auto Deploy" canGate="update" :canResource="$application" />
|
||||||
<x-forms.checkbox
|
<x-forms.checkbox
|
||||||
helper="Allow to automatically deploy Preview Deployments for all opened PR's.<br><br>Closing a PR will delete Preview Deployments."
|
helper="Allow to automatically deploy Preview Deployments for all opened PR's.<br><br>Closing a PR will delete Preview Deployments."
|
||||||
instantSave id="isPreviewDeploymentsEnabled" label="Preview Deployments" />
|
instantSave id="isPreviewDeploymentsEnabled" label="Preview Deployments" canGate="update"
|
||||||
|
:canResource="$application" />
|
||||||
@endif
|
@endif
|
||||||
<x-forms.checkbox helper="Disable Docker build cache on every deployment." instantSave id="disableBuildCache"
|
<x-forms.checkbox helper="Disable Docker build cache on every deployment." instantSave
|
||||||
label="Disable Build Cache" />
|
id="disableBuildCache" label="Disable Build Cache" canGate="update" :canResource="$application" />
|
||||||
|
|
||||||
@if ($application->settings->is_container_label_readonly_enabled)
|
@if ($application->settings->is_container_label_readonly_enabled)
|
||||||
<x-forms.checkbox
|
<x-forms.checkbox
|
||||||
helper="Your application will be available only on https if your domain starts with https://..."
|
helper="Your application will be available only on https if your domain starts with https://..."
|
||||||
instantSave id="isForceHttpsEnabled" label="Force Https" />
|
instantSave id="isForceHttpsEnabled" label="Force Https" canGate="update" :canResource="$application" />
|
||||||
<x-forms.checkbox label="Enable Gzip Compression"
|
<x-forms.checkbox label="Enable Gzip Compression"
|
||||||
helper="You can disable gzip compression if you want. Some services are compressing data by default. In this case, you do not need this."
|
helper="You can disable gzip compression if you want. Some services are compressing data by default. In this case, you do not need this."
|
||||||
instantSave id="isGzipEnabled" />
|
instantSave id="isGzipEnabled" canGate="update" :canResource="$application" />
|
||||||
<x-forms.checkbox helper="Strip Prefix is used to remove prefixes from paths. Like /api/ to /api."
|
<x-forms.checkbox helper="Strip Prefix is used to remove prefixes from paths. Like /api/ to /api."
|
||||||
instantSave id="isStripprefixEnabled" label="Strip Prefixes" />
|
instantSave id="isStripprefixEnabled" label="Strip Prefixes" canGate="update" :canResource="$application" />
|
||||||
@else
|
@else
|
||||||
<x-forms.checkbox disabled
|
<x-forms.checkbox disabled
|
||||||
helper="Readonly labels are disabled. You need to set the labels in the labels section." instantSave
|
helper="Readonly labels are disabled. You need to set the labels in the labels section." instantSave
|
||||||
id="isForceHttpsEnabled" label="Force Https" />
|
id="isForceHttpsEnabled" label="Force Https" canGate="update" :canResource="$application" />
|
||||||
<x-forms.checkbox label="Enable Gzip Compression" disabled
|
<x-forms.checkbox label="Enable Gzip Compression" disabled
|
||||||
helper="Readonly labels are disabled. You need to set the labels in the labels section." instantSave
|
helper="Readonly labels are disabled. You need to set the labels in the labels section." instantSave
|
||||||
id="isGzipEnabled" />
|
id="isGzipEnabled" canGate="update" :canResource="$application" />
|
||||||
<x-forms.checkbox
|
<x-forms.checkbox
|
||||||
helper="Readonly labels are disabled. You need to set the labels in the labels section." disabled
|
helper="Readonly labels are disabled. You need to set the labels in the labels section." disabled
|
||||||
instantSave id="isStripprefixEnabled" label="Strip Prefixes" />
|
instantSave id="isStripprefixEnabled" label="Strip Prefixes" canGate="update" :canResource="$application" />
|
||||||
@endif
|
@endif
|
||||||
@if ($application->build_pack === 'dockercompose')
|
@if ($application->build_pack === 'dockercompose')
|
||||||
<h3>Docker Compose</h3>
|
<h3>Docker Compose</h3>
|
||||||
<x-forms.checkbox instantSave id="isRawComposeDeploymentEnabled" label="Raw Compose Deployment"
|
<x-forms.checkbox instantSave id="isRawComposeDeploymentEnabled" label="Raw Compose Deployment"
|
||||||
helper="WARNING: Advanced use cases only. Your docker compose file will be deployed as-is. Nothing is modified by Coolify. You need to configure the proxy parts. More info in the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/compose#raw-docker-compose-deployment'>documentation.</a>" />
|
helper="WARNING: Advanced use cases only. Your docker compose file will be deployed as-is. Nothing is modified by Coolify. You need to configure the proxy parts. More info in the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/compose#raw-docker-compose-deployment'>documentation.</a>"
|
||||||
|
canGate="update" :canResource="$application" />
|
||||||
@endif
|
@endif
|
||||||
<h3 class="pt-4">Container Names</h3>
|
<h3 class="pt-4">Container Names</h3>
|
||||||
<x-forms.checkbox
|
<x-forms.checkbox
|
||||||
helper="The deployed container will have the same name ({{ $application->uuid }}). <span class='font-bold dark:text-warning'>You will lose the rolling update feature!</span>"
|
helper="The deployed container will have the same name ({{ $application->uuid }}). <span class='font-bold dark:text-warning'>You will lose the rolling update feature!</span>"
|
||||||
instantSave id="isConsistentContainerNameEnabled" label="Consistent Container Names" />
|
instantSave id="isConsistentContainerNameEnabled" label="Consistent Container Names" canGate="update"
|
||||||
|
:canResource="$application" />
|
||||||
@if ($isConsistentContainerNameEnabled === false)
|
@if ($isConsistentContainerNameEnabled === false)
|
||||||
<form class="flex items-end gap-2 " wire:submit.prevent='saveCustomName'>
|
<form class="flex items-end gap-2 " wire:submit.prevent='saveCustomName'>
|
||||||
<x-forms.input
|
<x-forms.input
|
||||||
helper="You can add a custom name for your container.<br><br>The name will be converted to slug format when you save it. <span class='font-bold dark:text-warning'>You will lose the rolling update feature!</span>"
|
helper="You can add a custom name for your container.<br><br>The name will be converted to slug format when you save it. <span class='font-bold dark:text-warning'>You will lose the rolling update feature!</span>"
|
||||||
instantSave id="customInternalName" label="Custom Container Name" />
|
instantSave id="customInternalName" label="Custom Container Name" canGate="update"
|
||||||
@can('update', $application)
|
:canResource="$application" />
|
||||||
<x-forms.button type="submit">
|
<x-forms.button canGate="update" :canResource="$application" type="submit">Save</x-forms.button>
|
||||||
Save
|
|
||||||
</x-forms.button>
|
|
||||||
@else
|
|
||||||
<x-forms.button type="submit" disabled
|
|
||||||
title="You don't have permission to update this application. Contact your team administrator for access.">
|
|
||||||
Save
|
|
||||||
</x-forms.button>
|
|
||||||
@endcan
|
|
||||||
</form>
|
</form>
|
||||||
@endif
|
@endif
|
||||||
@if ($application->build_pack === 'dockercompose')
|
@if ($application->build_pack === 'dockercompose')
|
||||||
<h3 class="pt-4">Network</h3>
|
<h3 class="pt-4">Network</h3>
|
||||||
<x-forms.checkbox instantSave id="isConnectToDockerNetworkEnabled" label="Connect To Predefined Network"
|
<x-forms.checkbox instantSave id="isConnectToDockerNetworkEnabled" label="Connect To Predefined Network"
|
||||||
helper="By default, you do not reach the Coolify defined networks.<br>Starting a docker compose based resource will have an internal network. <br>If you connect to a Coolify defined network, you maybe need to use different internal DNS names to connect to a resource.<br><br>For more information, check <a class='underline dark:text-white' target='_blank' href='https://coolify.io/docs/knowledge-base/docker/compose#connect-to-predefined-networks'>this</a>." />
|
helper="By default, you do not reach the Coolify defined networks.<br>Starting a docker compose based resource will have an internal network. <br>If you connect to a Coolify defined network, you maybe need to use different internal DNS names to connect to a resource.<br><br>For more information, check <a class='underline dark:text-white' target='_blank' href='https://coolify.io/docs/knowledge-base/docker/compose#connect-to-predefined-networks'>this</a>."
|
||||||
|
canGate="update" :canResource="$application" />
|
||||||
@endif
|
@endif
|
||||||
<h3 class="pt-4">Logs</h3>
|
<h3 class="pt-4">Logs</h3>
|
||||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||||
instantSave id="isLogDrainEnabled" label="Drain Logs" />
|
instantSave id="isLogDrainEnabled" label="Drain Logs" canGate="update" :canResource="$application" />
|
||||||
@if ($application->git_based())
|
@if ($application->git_based())
|
||||||
<h3>Git</h3>
|
<h3>Git</h3>
|
||||||
<x-forms.checkbox instantSave id="isGitSubmodulesEnabled" label="Submodules"
|
<x-forms.checkbox instantSave id="isGitSubmodulesEnabled" label="Submodules"
|
||||||
helper="Allow Git Submodules during build process." />
|
helper="Allow Git Submodules during build process." canGate="update" :canResource="$application" />
|
||||||
<x-forms.checkbox instantSave id="isGitLfsEnabled" label="LFS"
|
<x-forms.checkbox instantSave id="isGitLfsEnabled" label="LFS"
|
||||||
helper="Allow Git LFS during build process." />
|
helper="Allow Git LFS during build process." canGate="update" :canResource="$application" />
|
||||||
<x-forms.checkbox instantSave id="isGitShallowCloneEnabled" label="Shallow Clone"
|
<x-forms.checkbox instantSave id="isGitShallowCloneEnabled" label="Shallow Clone"
|
||||||
helper="Use shallow cloning (--depth=1) to speed up deployments by only fetching the latest commit history. This reduces clone time and resource usage, especially for large repositories." />
|
helper="Use shallow cloning (--depth=1) to speed up deployments by only fetching the latest commit history. This reduces clone time and resource usage, especially for large repositories."
|
||||||
|
canGate="update" :canResource="$application" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -87,16 +84,7 @@
|
|||||||
<div class="flex gap-2 items-end pt-4">
|
<div class="flex gap-2 items-end pt-4">
|
||||||
<h3>GPU</h3>
|
<h3>GPU</h3>
|
||||||
@if ($isGpuEnabled)
|
@if ($isGpuEnabled)
|
||||||
@can('update', $application)
|
<x-forms.button canGate="update" :canResource="$application" type="submit">Save</x-forms.button>
|
||||||
<x-forms.button type="submit">
|
|
||||||
Save
|
|
||||||
</x-forms.button>
|
|
||||||
@else
|
|
||||||
<x-forms.button type="submit" disabled
|
|
||||||
title="You don't have permission to update this application. Contact your team administrator for access.">
|
|
||||||
Save
|
|
||||||
</x-forms.button>
|
|
||||||
@endcan
|
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@@ -104,21 +92,23 @@
|
|||||||
<div class="md:w-96 pb-4">
|
<div class="md:w-96 pb-4">
|
||||||
<x-forms.checkbox
|
<x-forms.checkbox
|
||||||
helper="Enable GPU usage for this application. More info <a href='https://docs.docker.com/compose/gpu-support/' class='underline dark:text-white' target='_blank'>here</a>."
|
helper="Enable GPU usage for this application. More info <a href='https://docs.docker.com/compose/gpu-support/' class='underline dark:text-white' target='_blank'>here</a>."
|
||||||
instantSave id="isGpuEnabled" label="Enable GPU" />
|
instantSave id="isGpuEnabled" label="Enable GPU" canGate="update" :canResource="$application" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@if ($isGpuEnabled)
|
@if ($isGpuEnabled)
|
||||||
<div class="flex flex-col w-full gap-2 ">
|
<div class="flex flex-col w-full gap-2 ">
|
||||||
<div class="flex gap-2 items-end">
|
<div class="flex gap-2 items-end">
|
||||||
<x-forms.input label="GPU Driver" id="gpuDriver"> </x-forms.input>
|
<x-forms.input label="GPU Driver" id="gpuDriver" canGate="update" :canResource="$application">
|
||||||
<x-forms.input label="GPU Count" placeholder="empty means use all GPUs" id="gpuCount">
|
</x-forms.input>
|
||||||
|
<x-forms.input label="GPU Count" placeholder="empty means use all GPUs" id="gpuCount"
|
||||||
|
canGate="update" :canResource="$application">
|
||||||
</x-forms.input>
|
</x-forms.input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<x-forms.input label="GPU Device Ids" placeholder="0,2"
|
<x-forms.input label="GPU Device Ids" placeholder="0,2"
|
||||||
helper="Comma separated list of device ids. More info <a href='https://docs.docker.com/compose/gpu-support/#access-specific-devices' class='underline dark:text-white' target='_blank'>here</a>."
|
helper="Comma separated list of device ids. More info <a href='https://docs.docker.com/compose/gpu-support/#access-specific-devices' class='underline dark:text-white' target='_blank'>here</a>."
|
||||||
id="gpuDeviceIds"> </x-forms.input>
|
id="gpuDeviceIds" canGate="update" :canResource="$application"> </x-forms.input>
|
||||||
<x-forms.textarea rows="10" label="GPU Options" id="gpuOptions"> </x-forms.textarea>
|
<x-forms.textarea rows="10" label="GPU Options" id="gpuOptions" canGate="update"
|
||||||
|
:canResource="$application"> </x-forms.textarea>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</form>
|
</form>
|
||||||
|
@@ -1,56 +1,35 @@
|
|||||||
<div x-data="{ initLoadingCompose: $wire.entangle('initLoadingCompose') }">
|
<div x-data="{
|
||||||
|
initLoadingCompose: $wire.entangle('initLoadingCompose'),
|
||||||
|
canUpdate: @js(auth()->user()->can('update', $application)),
|
||||||
|
shouldDisable() {
|
||||||
|
return this.initLoadingCompose || !this.canUpdate;
|
||||||
|
}
|
||||||
|
}">
|
||||||
<form wire:submit='submit' class="flex flex-col pb-32">
|
<form wire:submit='submit' class="flex flex-col pb-32">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>General</h2>
|
<h2>General</h2>
|
||||||
@can('update', $application)
|
<x-forms.button canGate="update" :canResource="$application" type="submit">Save</x-forms.button>
|
||||||
<x-forms.button type="submit">
|
|
||||||
Save
|
|
||||||
</x-forms.button>
|
|
||||||
@else
|
|
||||||
<x-forms.button type="submit" disabled
|
|
||||||
title="You don't have permission to update this application. Contact your team administrator for access.">
|
|
||||||
Save
|
|
||||||
</x-forms.button>
|
|
||||||
@endcan
|
|
||||||
|
|
||||||
{{-- <x-forms.button wire:click="downloadConfig">
|
|
||||||
Download Config
|
|
||||||
</x-forms.button> --}}
|
|
||||||
{{-- <x-modal-input buttonTitle="Upload Config" title="Upload Config" :closeOutside="false">
|
|
||||||
<livewire:project.shared.upload-config :applicationId="$application->id" />
|
|
||||||
</x-modal-input> --}}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div>General configuration for your application.</div>
|
<div>General configuration for your application.</div>
|
||||||
<div class="flex flex-col gap-2 py-4">
|
<div class="flex flex-col gap-2 py-4">
|
||||||
<div class="flex flex-col items-end gap-2 xl:flex-row">
|
<div class="flex flex-col items-end gap-2 xl:flex-row">
|
||||||
<x-forms.input x-bind:disabled="initLoadingCompose" id="application.name" label="Name" required />
|
<x-forms.input x-bind:disabled="shouldDisable()" id="application.name" label="Name" required />
|
||||||
<x-forms.input x-bind:disabled="initLoadingCompose" id="application.description" label="Description" />
|
<x-forms.input x-bind:disabled="shouldDisable()" id="application.description" label="Description" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (!$application->dockerfile && $application->build_pack !== 'dockerimage')
|
@if (!$application->dockerfile && $application->build_pack !== 'dockerimage')
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
@can('update', $application)
|
<x-forms.select x-bind:disabled="shouldDisable()" wire:model.live="application.build_pack"
|
||||||
<x-forms.select x-bind:disabled="initLoadingCompose" wire:model.live="application.build_pack"
|
label="Build Pack" required>
|
||||||
label="Build Pack" required>
|
<option value="nixpacks">Nixpacks</option>
|
||||||
<option value="nixpacks">Nixpacks</option>
|
<option value="static">Static</option>
|
||||||
<option value="static">Static</option>
|
<option value="dockerfile">Dockerfile</option>
|
||||||
<option value="dockerfile">Dockerfile</option>
|
<option value="dockercompose">Docker Compose</option>
|
||||||
<option value="dockercompose">Docker Compose</option>
|
</x-forms.select>
|
||||||
</x-forms.select>
|
|
||||||
@else
|
|
||||||
<x-forms.select disabled label="Build Pack" required>
|
|
||||||
<option value="nixpacks" @if ($application->build_pack === 'nixpacks') selected @endif>Nixpacks</option>
|
|
||||||
<option value="static" @if ($application->build_pack === 'static') selected @endif>Static</option>
|
|
||||||
<option value="dockerfile" @if ($application->build_pack === 'dockerfile') selected @endif>Dockerfile
|
|
||||||
</option>
|
|
||||||
<option value="dockercompose" @if ($application->build_pack === 'dockercompose') selected @endif>Docker
|
|
||||||
Compose</option>
|
|
||||||
</x-forms.select>
|
|
||||||
@endcan
|
|
||||||
@if ($application->settings->is_static || $application->build_pack === 'static')
|
@if ($application->settings->is_static || $application->build_pack === 'static')
|
||||||
<x-forms.select id="application.static_image" label="Static Image" required>
|
<x-forms.select x-bind:disabled="!canUpdate" id="application.static_image"
|
||||||
|
label="Static Image" required>
|
||||||
<option value="nginx:alpine">nginx:alpine</option>
|
<option value="nginx:alpine">nginx:alpine</option>
|
||||||
<option disabled value="apache:alpine">apache:alpine</option>
|
<option disabled value="apache:alpine">apache:alpine</option>
|
||||||
</x-forms.select>
|
</x-forms.select>
|
||||||
@@ -69,7 +48,8 @@
|
|||||||
<x-forms.input
|
<x-forms.input
|
||||||
helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io,https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "
|
helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io,https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "
|
||||||
label="Domains for {{ str($serviceName)->headline() }}"
|
label="Domains for {{ str($serviceName)->headline() }}"
|
||||||
id="parsedServiceDomains.{{ str($serviceName)->slug('_') }}.domain"></x-forms.input>
|
id="parsedServiceDomains.{{ str($serviceName)->slug('_') }}.domain"
|
||||||
|
x-bind:disabled="shouldDisable()"></x-forms.input>
|
||||||
@can('update', $application)
|
@can('update', $application)
|
||||||
<x-forms.button wire:click="generateDomain('{{ $serviceName }}')">Generate
|
<x-forms.button wire:click="generateDomain('{{ $serviceName }}')">Generate
|
||||||
Domain</x-forms.button>
|
Domain</x-forms.button>
|
||||||
@@ -85,27 +65,23 @@
|
|||||||
@if ($application->settings->is_static || $application->build_pack === 'static')
|
@if ($application->settings->is_static || $application->build_pack === 'static')
|
||||||
<x-forms.textarea id="application.custom_nginx_configuration"
|
<x-forms.textarea id="application.custom_nginx_configuration"
|
||||||
placeholder="Empty means default configuration will be used." label="Custom Nginx Configuration"
|
placeholder="Empty means default configuration will be used." label="Custom Nginx Configuration"
|
||||||
helper="You can add custom Nginx configuration here." />
|
helper="You can add custom Nginx configuration here." x-bind:disabled="!canUpdate" />
|
||||||
@can('update', $application)
|
@can('update', $application)
|
||||||
<x-forms.button wire:click="generateNginxConfiguration">
|
<x-forms.button wire:click="generateNginxConfiguration">
|
||||||
Generate Default Nginx Configuration
|
Generate Default Nginx Configuration
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@else
|
|
||||||
<x-forms.button wire:click="generateNginxConfiguration" disabled
|
|
||||||
title="You don't have permission to update this application. Contact your team administrator for access.">
|
|
||||||
Generate Default Nginx Configuration
|
|
||||||
</x-forms.button>
|
|
||||||
@endcan
|
@endcan
|
||||||
@endif
|
@endif
|
||||||
<div class="w-96 pb-6">
|
<div class="w-96 pb-6">
|
||||||
@if ($application->could_set_build_commands())
|
@if ($application->could_set_build_commands())
|
||||||
<x-forms.checkbox instantSave id="application.settings.is_static" label="Is it a static site?"
|
<x-forms.checkbox instantSave id="application.settings.is_static" label="Is it a static site?"
|
||||||
helper="If your application is a static site or the final build assets should be served as a static site, enable this." />
|
helper="If your application is a static site or the final build assets should be served as a static site, enable this."
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@endif
|
@endif
|
||||||
@if ($application->settings->is_static && $application->build_pack !== 'static')
|
@if ($application->settings->is_static && $application->build_pack !== 'static')
|
||||||
<x-forms.checkbox label="Is it a SPA (Single Page Application)?"
|
<x-forms.checkbox label="Is it a SPA (Single Page Application)?"
|
||||||
helper="If your application is a SPA, enable this." id="application.settings.is_spa"
|
helper="If your application is a SPA, enable this." id="application.settings.is_spa" instantSave
|
||||||
instantSave></x-forms.checkbox>
|
x-bind:disabled="!canUpdate"></x-forms.checkbox>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@if ($application->build_pack !== 'dockercompose')
|
@if ($application->build_pack !== 'dockercompose')
|
||||||
@@ -113,11 +89,13 @@
|
|||||||
@if ($application->settings->is_container_label_readonly_enabled == false)
|
@if ($application->settings->is_container_label_readonly_enabled == false)
|
||||||
<x-forms.input placeholder="https://coolify.io" wire:model.blur-sm="application.fqdn"
|
<x-forms.input placeholder="https://coolify.io" wire:model.blur-sm="application.fqdn"
|
||||||
label="Domains" readonly
|
label="Domains" readonly
|
||||||
helper="Readonly labels are disabled. You can set the domains in the labels section." />
|
helper="Readonly labels are disabled. You can set the domains in the labels section."
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@else
|
@else
|
||||||
<x-forms.input placeholder="https://coolify.io" wire:model.blur-sm="application.fqdn"
|
<x-forms.input placeholder="https://coolify.io" wire:model.blur-sm="application.fqdn"
|
||||||
label="Domains"
|
label="Domains"
|
||||||
helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io,https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. " />
|
helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io,https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@can('update', $application)
|
@can('update', $application)
|
||||||
<x-forms.button wire:click="getWildcardDomain">Generate Domain
|
<x-forms.button wire:click="getWildcardDomain">Generate Domain
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
@@ -128,32 +106,38 @@
|
|||||||
@if ($application->settings->is_container_label_readonly_enabled == false)
|
@if ($application->settings->is_container_label_readonly_enabled == false)
|
||||||
@if ($application->redirect === 'both')
|
@if ($application->redirect === 'both')
|
||||||
<x-forms.input label="Direction" value="Allow www & non-www." readonly
|
<x-forms.input label="Direction" value="Allow www & non-www." readonly
|
||||||
helper="Readonly labels are disabled. You can set the direction in the labels section." />
|
helper="Readonly labels are disabled. You can set the direction in the labels section."
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@elseif ($application->redirect === 'www')
|
@elseif ($application->redirect === 'www')
|
||||||
<x-forms.input label="Direction" value="Redirect to www." readonly
|
<x-forms.input label="Direction" value="Redirect to www." readonly
|
||||||
helper="Readonly labels are disabled. You can set the direction in the labels section." />
|
helper="Readonly labels are disabled. You can set the direction in the labels section."
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@elseif ($application->redirect === 'non-www')
|
@elseif ($application->redirect === 'non-www')
|
||||||
<x-forms.input label="Direction" value="Redirect to non-www." readonly
|
<x-forms.input label="Direction" value="Redirect to non-www." readonly
|
||||||
helper="Readonly labels are disabled. You can set the direction in the labels section." />
|
helper="Readonly labels are disabled. You can set the direction in the labels section."
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@endif
|
@endif
|
||||||
@else
|
@else
|
||||||
<x-forms.select label="Direction" id="application.redirect" required
|
<x-forms.select label="Direction" id="application.redirect" required
|
||||||
helper="You must need to add www and non-www as an A DNS record. Make sure the www domain is added under Domains.">
|
helper="You must need to add www and non-www as an A DNS record. Make sure the www domain is added under Domains."
|
||||||
|
x-bind:disabled="!canUpdate">
|
||||||
<option value="both">Allow www & non-www.</option>
|
<option value="both">Allow www & non-www.</option>
|
||||||
<option value="www">Redirect to www.</option>
|
<option value="www">Redirect to www.</option>
|
||||||
<option value="non-www">Redirect to non-www.</option>
|
<option value="non-www">Redirect to non-www.</option>
|
||||||
</x-forms.select>
|
</x-forms.select>
|
||||||
@if ($application->settings->is_container_label_readonly_enabled)
|
@if ($application->settings->is_container_label_readonly_enabled)
|
||||||
<x-modal-confirmation title="Confirm Redirection Setting?" buttonTitle="Set Direction"
|
@can('update', $application)
|
||||||
submitAction="setRedirect" :actions="['All traffic will be redirected to the selected direction.']"
|
<x-modal-confirmation title="Confirm Redirection Setting?" buttonTitle="Set Direction"
|
||||||
confirmationText="{{ $application->fqdn . '/' }}"
|
submitAction="setRedirect" :actions="['All traffic will be redirected to the selected direction.']"
|
||||||
confirmationLabel="Please confirm the execution of the action by entering the Application URL below"
|
confirmationText="{{ $application->fqdn . '/' }}"
|
||||||
shortConfirmationLabel="Application URL" :confirmWithPassword="false"
|
confirmationLabel="Please confirm the execution of the action by entering the Application URL below"
|
||||||
step2ButtonText="Set Direction">
|
shortConfirmationLabel="Application URL" :confirmWithPassword="false"
|
||||||
<x-slot:customButton>
|
step2ButtonText="Set Direction">
|
||||||
<div class="w-[7.2rem]">Set Direction</div>
|
<x-slot:customButton>
|
||||||
</x-slot:customButton>
|
<div class="w-[7.2rem]">Set Direction</div>
|
||||||
</x-modal-confirmation>
|
</x-slot:customButton>
|
||||||
|
</x-modal-confirmation>
|
||||||
|
@endcan
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@@ -177,11 +161,15 @@
|
|||||||
<div class="flex flex-col gap-2 xl:flex-row">
|
<div class="flex flex-col gap-2 xl:flex-row">
|
||||||
@if ($application->build_pack === 'dockerimage')
|
@if ($application->build_pack === 'dockerimage')
|
||||||
@if ($application->destination->server->isSwarm())
|
@if ($application->destination->server->isSwarm())
|
||||||
<x-forms.input required id="application.docker_registry_image_name" label="Docker Image" />
|
<x-forms.input required id="application.docker_registry_image_name" label="Docker Image"
|
||||||
<x-forms.input id="application.docker_registry_image_tag" label="Docker Image Tag" />
|
x-bind:disabled="!canUpdate" />
|
||||||
|
<x-forms.input id="application.docker_registry_image_tag" label="Docker Image Tag"
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@else
|
@else
|
||||||
<x-forms.input id="application.docker_registry_image_name" label="Docker Image" />
|
<x-forms.input id="application.docker_registry_image_name" label="Docker Image"
|
||||||
<x-forms.input id="application.docker_registry_image_tag" label="Docker Image Tag" />
|
x-bind:disabled="!canUpdate" />
|
||||||
|
<x-forms.input id="application.docker_registry_image_tag" label="Docker Image Tag"
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@endif
|
@endif
|
||||||
@else
|
@else
|
||||||
@if (
|
@if (
|
||||||
@@ -189,19 +177,20 @@
|
|||||||
$application->additional_servers->count() > 0 ||
|
$application->additional_servers->count() > 0 ||
|
||||||
$application->settings->is_build_server_enabled)
|
$application->settings->is_build_server_enabled)
|
||||||
<x-forms.input id="application.docker_registry_image_name" required label="Docker Image"
|
<x-forms.input id="application.docker_registry_image_name" required label="Docker Image"
|
||||||
placeholder="Required!" />
|
placeholder="Required!" x-bind:disabled="!canUpdate" />
|
||||||
<x-forms.input id="application.docker_registry_image_tag"
|
<x-forms.input id="application.docker_registry_image_tag"
|
||||||
helper="If set, it will tag the built image with this tag too. <br><br>Example: If you set it to 'latest', it will push the image with the commit sha tag + with the latest tag."
|
helper="If set, it will tag the built image with this tag too. <br><br>Example: If you set it to 'latest', it will push the image with the commit sha tag + with the latest tag."
|
||||||
placeholder="Empty means latest will be used." label="Docker Image Tag" />
|
placeholder="Empty means latest will be used." label="Docker Image Tag"
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@else
|
@else
|
||||||
<x-forms.input id="application.docker_registry_image_name"
|
<x-forms.input id="application.docker_registry_image_name"
|
||||||
helper="Empty means it won't push the image to a docker registry."
|
helper="Empty means it won't push the image to a docker registry."
|
||||||
placeholder="Empty means it won't push the image to a docker registry."
|
placeholder="Empty means it won't push the image to a docker registry."
|
||||||
label="Docker Image" />
|
label="Docker Image" x-bind:disabled="!canUpdate" />
|
||||||
<x-forms.input id="application.docker_registry_image_tag"
|
<x-forms.input id="application.docker_registry_image_tag"
|
||||||
placeholder="Empty means only push commit sha tag."
|
placeholder="Empty means only push commit sha tag."
|
||||||
helper="If set, it will tag the built image with this tag too. <br><br>Example: If you set it to 'latest', it will push the image with the commit sha tag + with the latest tag."
|
helper="If set, it will tag the built image with this tag too. <br><br>Example: If you set it to 'latest', it will push the image with the commit sha tag + with the latest tag."
|
||||||
label="Docker Image Tag" />
|
label="Docker Image Tag" x-bind:disabled="!canUpdate" />
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@@ -212,17 +201,21 @@
|
|||||||
<x-forms.input
|
<x-forms.input
|
||||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
||||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k --hostname=myapp"
|
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k --hostname=myapp"
|
||||||
id="application.custom_docker_run_options" label="Custom Docker Options" />
|
id="application.custom_docker_run_options" label="Custom Docker Options"
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@else
|
@else
|
||||||
@if ($application->could_set_build_commands())
|
@if ($application->could_set_build_commands())
|
||||||
@if ($application->build_pack === 'nixpacks')
|
@if ($application->build_pack === 'nixpacks')
|
||||||
<div class="flex flex-col gap-2 xl:flex-row">
|
<div class="flex flex-col gap-2 xl:flex-row">
|
||||||
<x-forms.input helper="If you modify this, you probably need to have a nixpacks.toml"
|
<x-forms.input helper="If you modify this, you probably need to have a nixpacks.toml"
|
||||||
id="application.install_command" label="Install Command" />
|
id="application.install_command" label="Install Command"
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
<x-forms.input helper="If you modify this, you probably need to have a nixpacks.toml"
|
<x-forms.input helper="If you modify this, you probably need to have a nixpacks.toml"
|
||||||
id="application.build_command" label="Build Command" />
|
id="application.build_command" label="Build Command"
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
<x-forms.input helper="If you modify this, you probably need to have a nixpacks.toml"
|
<x-forms.input helper="If you modify this, you probably need to have a nixpacks.toml"
|
||||||
id="application.start_command" label="Start Command" />
|
id="application.start_command" label="Start Command"
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
</div>
|
</div>
|
||||||
<div class="pt-1 text-xs">Nixpacks will detect the required configuration
|
<div class="pt-1 text-xs">Nixpacks will detect the required configuration
|
||||||
automatically.
|
automatically.
|
||||||
@@ -240,10 +233,10 @@
|
|||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
@endcan
|
@endcan
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input x-bind:disabled="initLoadingCompose" placeholder="/"
|
<x-forms.input x-bind:disabled="shouldDisable()" placeholder="/"
|
||||||
id="application.base_directory" label="Base Directory"
|
id="application.base_directory" label="Base Directory"
|
||||||
helper="Directory to use as root. Useful for monorepos." />
|
helper="Directory to use as root. Useful for monorepos." />
|
||||||
<x-forms.input x-bind:disabled="initLoadingCompose"
|
<x-forms.input x-bind:disabled="shouldDisable()"
|
||||||
placeholder="/docker-compose.yaml"
|
placeholder="/docker-compose.yaml"
|
||||||
id="application.docker_compose_location" label="Docker Compose Location"
|
id="application.docker_compose_location" label="Docker Compose Location"
|
||||||
helper="It is calculated together with the Base Directory:<br><span class='dark:text-warning'>{{ Str::start($application->base_directory . $application->docker_compose_location, '/') }}</span>" />
|
helper="It is calculated together with the Base Directory:<br><span class='dark:text-warning'>{{ Str::start($application->base_directory . $application->docker_compose_location, '/') }}</span>" />
|
||||||
@@ -252,7 +245,8 @@
|
|||||||
<x-forms.checkbox instantSave
|
<x-forms.checkbox instantSave
|
||||||
id="application.settings.is_preserve_repository_enabled"
|
id="application.settings.is_preserve_repository_enabled"
|
||||||
label="Preserve Repository During Deployment"
|
label="Preserve Repository During Deployment"
|
||||||
helper="Git repository (based on the base directory settings) will be copied to the deployment directory." />
|
helper="Git repository (based on the base directory settings) will be copied to the deployment directory."
|
||||||
|
x-bind:disabled="shouldDisable()" />
|
||||||
</div>
|
</div>
|
||||||
<div class="pt-4">The following commands are for advanced use cases.
|
<div class="pt-4">The following commands are for advanced use cases.
|
||||||
Only
|
Only
|
||||||
@@ -260,13 +254,13 @@
|
|||||||
know what are
|
know what are
|
||||||
you doing.</div>
|
you doing.</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input placeholder="docker compose build"
|
<x-forms.input x-bind:disabled="shouldDisable()"
|
||||||
x-bind:disabled="initLoadingCompose"
|
placeholder="docker compose build"
|
||||||
id="application.docker_compose_custom_build_command"
|
id="application.docker_compose_custom_build_command"
|
||||||
helper="If you use this, you need to specify paths relatively and should use the same compose file in the custom command, otherwise the automatically configured labels / etc won't work.<br><br>So in your case, use: <span class='dark:text-warning'>docker compose -f .{{ Str::start($application->base_directory . $application->docker_compose_location, '/') }} build</span>"
|
helper="If you use this, you need to specify paths relatively and should use the same compose file in the custom command, otherwise the automatically configured labels / etc won't work.<br><br>So in your case, use: <span class='dark:text-warning'>docker compose -f .{{ Str::start($application->base_directory . $application->docker_compose_location, '/') }} build</span>"
|
||||||
label="Custom Build Command" />
|
label="Custom Build Command" />
|
||||||
<x-forms.input placeholder="docker compose up -d"
|
<x-forms.input x-bind:disabled="shouldDisable()"
|
||||||
x-bind:disabled="initLoadingCompose"
|
placeholder="docker compose up -d"
|
||||||
id="application.docker_compose_custom_start_command"
|
id="application.docker_compose_custom_start_command"
|
||||||
helper="If you use this, you need to specify paths relatively and should use the same compose file in the custom command, otherwise the automatically configured labels / etc won't work.<br><br>So in your case, use: <span class='dark:text-warning'>docker compose -f .{{ Str::start($application->base_directory . $application->docker_compose_location, '/') }} up -d</span>"
|
helper="If you use this, you need to specify paths relatively and should use the same compose file in the custom command, otherwise the automatically configured labels / etc won't work.<br><br>So in your case, use: <span class='dark:text-warning'>docker compose -f .{{ Str::start($application->base_directory . $application->docker_compose_location, '/') }} up -d</span>"
|
||||||
label="Custom Start Command" />
|
label="Custom Start Command" />
|
||||||
@@ -276,25 +270,28 @@
|
|||||||
<div class="flex flex-col gap-2 xl:flex-row">
|
<div class="flex flex-col gap-2 xl:flex-row">
|
||||||
<x-forms.input placeholder="/" id="application.base_directory"
|
<x-forms.input placeholder="/" id="application.base_directory"
|
||||||
label="Base Directory"
|
label="Base Directory"
|
||||||
helper="Directory to use as root. Useful for monorepos." />
|
helper="Directory to use as root. Useful for monorepos."
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@if ($application->build_pack === 'dockerfile' && !$application->dockerfile)
|
@if ($application->build_pack === 'dockerfile' && !$application->dockerfile)
|
||||||
<x-forms.input placeholder="/Dockerfile" id="application.dockerfile_location"
|
<x-forms.input placeholder="/Dockerfile" id="application.dockerfile_location"
|
||||||
label="Dockerfile Location"
|
label="Dockerfile Location"
|
||||||
helper="It is calculated together with the Base Directory:<br><span class='dark:text-warning'>{{ Str::start($application->base_directory . $application->dockerfile_location, '/') }}</span>" />
|
helper="It is calculated together with the Base Directory:<br><span class='dark:text-warning'>{{ Str::start($application->base_directory . $application->dockerfile_location, '/') }}</span>"
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if ($application->build_pack === 'dockerfile')
|
@if ($application->build_pack === 'dockerfile')
|
||||||
<x-forms.input id="application.dockerfile_target_build"
|
<x-forms.input id="application.dockerfile_target_build"
|
||||||
label="Docker Build Stage Target"
|
label="Docker Build Stage Target"
|
||||||
helper="Useful if you have multi-staged dockerfile." />
|
helper="Useful if you have multi-staged dockerfile."
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@endif
|
@endif
|
||||||
@if ($application->could_set_build_commands())
|
@if ($application->could_set_build_commands())
|
||||||
@if ($application->settings->is_static)
|
@if ($application->settings->is_static)
|
||||||
<x-forms.input placeholder="/dist" id="application.publish_directory"
|
<x-forms.input placeholder="/dist" id="application.publish_directory"
|
||||||
label="Publish Directory" required />
|
label="Publish Directory" required x-bind:disabled="!canUpdate" />
|
||||||
@else
|
@else
|
||||||
<x-forms.input placeholder="/" id="application.publish_directory"
|
<x-forms.input placeholder="/" id="application.publish_directory"
|
||||||
label="Publish Directory" />
|
label="Publish Directory" x-bind:disabled="!canUpdate" />
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@@ -304,20 +301,21 @@
|
|||||||
<x-forms.textarea
|
<x-forms.textarea
|
||||||
helper="Gitignore-style rules to filter Git based webhook deployments."
|
helper="Gitignore-style rules to filter Git based webhook deployments."
|
||||||
placeholder="src/pages/**" id="application.watch_paths"
|
placeholder="src/pages/**" id="application.watch_paths"
|
||||||
label="Watch Paths" />
|
label="Watch Paths" x-bind:disabled="!canUpdate" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<x-forms.input
|
<x-forms.input
|
||||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
||||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k --hostname=myapp"
|
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k --hostname=myapp"
|
||||||
id="application.custom_docker_run_options" label="Custom Docker Options" />
|
id="application.custom_docker_run_options" label="Custom Docker Options"
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
|
|
||||||
@if ($application->build_pack !== 'dockercompose')
|
@if ($application->build_pack !== 'dockercompose')
|
||||||
<div class="pt-2 w-96">
|
<div class="pt-2 w-96">
|
||||||
<x-forms.checkbox
|
<x-forms.checkbox
|
||||||
helper="Use a build server to build your application. You can configure your build server in the Server settings. For more info, check the <a href='https://coolify.io/docs/knowledge-base/server/build-server' class='underline' target='_blank'>documentation</a>."
|
helper="Use a build server to build your application. You can configure your build server in the Server settings. For more info, check the <a href='https://coolify.io/docs/knowledge-base/server/build-server' class='underline' target='_blank'>documentation</a>."
|
||||||
instantSave id="application.settings.is_build_server_enabled"
|
instantSave id="application.settings.is_build_server_enabled"
|
||||||
label="Use a Build Server?" />
|
label="Use a Build Server?" x-bind:disabled="!canUpdate" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
@@ -327,8 +325,10 @@
|
|||||||
@if ($application->build_pack === 'dockercompose')
|
@if ($application->build_pack === 'dockercompose')
|
||||||
<div class="flex items-center gap-2 pb-4">
|
<div class="flex items-center gap-2 pb-4">
|
||||||
<h3>Docker Compose</h3>
|
<h3>Docker Compose</h3>
|
||||||
<x-forms.button wire:target='initLoadingCompose'
|
@can('update', $application)
|
||||||
x-on:click="$wire.dispatch('loadCompose', false)">Reload Compose File</x-forms.button>
|
<x-forms.button wire:target='initLoadingCompose'
|
||||||
|
x-on:click="$wire.dispatch('loadCompose', false)">Reload Compose File</x-forms.button>
|
||||||
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
@if ($application->settings->is_raw_compose_deployment_enabled)
|
@if ($application->settings->is_raw_compose_deployment_enabled)
|
||||||
<x-forms.textarea rows="10" readonly id="application.docker_compose_raw"
|
<x-forms.textarea rows="10" readonly id="application.docker_compose_raw"
|
||||||
@@ -350,7 +350,8 @@
|
|||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox label="Escape special characters in labels?"
|
<x-forms.checkbox label="Escape special characters in labels?"
|
||||||
helper="By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$.<br><br>If you want to use env variables inside the labels, turn this off."
|
helper="By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$.<br><br>If you want to use env variables inside the labels, turn this off."
|
||||||
id="application.settings.is_container_label_escape_enabled" instantSave></x-forms.checkbox>
|
id="application.settings.is_container_label_escape_enabled" instantSave
|
||||||
|
x-bind:disabled="!canUpdate"></x-forms.checkbox>
|
||||||
{{-- <x-forms.checkbox label="Readonly labels"
|
{{-- <x-forms.checkbox label="Readonly labels"
|
||||||
helper="Labels are readonly by default. Readonly means that edits you do to the labels could be lost and Coolify will autogenerate the labels for you. If you want to edit the labels directly, disable this option. <br><br>Be careful, it could break the proxy configuration after you restart the container as Coolify will now NOT autogenerate the labels for you (ofc you can always reset the labels to the coolify defaults manually)."
|
helper="Labels are readonly by default. Readonly means that edits you do to the labels could be lost and Coolify will autogenerate the labels for you. If you want to edit the labels directly, disable this option. <br><br>Be careful, it could break the proxy configuration after you restart the container as Coolify will now NOT autogenerate the labels for you (ofc you can always reset the labels to the coolify defaults manually)."
|
||||||
id="application.settings.is_container_label_readonly_enabled" instantSave></x-forms.checkbox> --}}
|
id="application.settings.is_container_label_readonly_enabled" instantSave></x-forms.checkbox> --}}
|
||||||
@@ -358,32 +359,36 @@
|
|||||||
@endif
|
@endif
|
||||||
@if ($application->dockerfile)
|
@if ($application->dockerfile)
|
||||||
<x-forms.textarea label="Dockerfile" id="application.dockerfile" monacoEditorLanguage="dockerfile"
|
<x-forms.textarea label="Dockerfile" id="application.dockerfile" monacoEditorLanguage="dockerfile"
|
||||||
useMonacoEditor rows="6"> </x-forms.textarea>
|
useMonacoEditor rows="6" x-bind:disabled="!canUpdate"> </x-forms.textarea>
|
||||||
@endif
|
@endif
|
||||||
@if ($application->build_pack !== 'dockercompose')
|
@if ($application->build_pack !== 'dockercompose')
|
||||||
<h3 class="pt-8">Network</h3>
|
<h3 class="pt-8">Network</h3>
|
||||||
<div class="flex flex-col gap-2 xl:flex-row">
|
<div class="flex flex-col gap-2 xl:flex-row">
|
||||||
@if ($application->settings->is_static || $application->build_pack === 'static')
|
@if ($application->settings->is_static || $application->build_pack === 'static')
|
||||||
<x-forms.input id="application.ports_exposes" label="Ports Exposes" readonly />
|
<x-forms.input id="application.ports_exposes" label="Ports Exposes" readonly
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@else
|
@else
|
||||||
@if ($application->settings->is_container_label_readonly_enabled === false)
|
@if ($application->settings->is_container_label_readonly_enabled === false)
|
||||||
<x-forms.input placeholder="3000,3001" id="application.ports_exposes"
|
<x-forms.input placeholder="3000,3001" id="application.ports_exposes"
|
||||||
label="Ports Exposes" readonly
|
label="Ports Exposes" readonly
|
||||||
helper="Readonly labels are disabled. You can set the ports manually in the labels section." />
|
helper="Readonly labels are disabled. You can set the ports manually in the labels section."
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@else
|
@else
|
||||||
<x-forms.input placeholder="3000,3001" id="application.ports_exposes"
|
<x-forms.input placeholder="3000,3001" id="application.ports_exposes"
|
||||||
label="Ports Exposes" required
|
label="Ports Exposes" required
|
||||||
helper="A comma separated list of ports your application uses. The first port will be used as default healthcheck port if nothing defined in the Healthcheck menu. Be sure to set this correctly." />
|
helper="A comma separated list of ports your application uses. The first port will be used as default healthcheck port if nothing defined in the Healthcheck menu. Be sure to set this correctly."
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
@if (!$application->destination->server->isSwarm())
|
@if (!$application->destination->server->isSwarm())
|
||||||
<x-forms.input placeholder="3000:3000" id="application.ports_mappings" label="Ports Mappings"
|
<x-forms.input placeholder="3000:3000" id="application.ports_mappings" label="Ports Mappings"
|
||||||
helper="A comma separated list of ports you would like to map to the host system. Useful when you do not want to use domains.<br><br><span class='inline-block font-bold dark:text-warning'>Example:</span><br>3000:3000,3002:3002<br><br>Rolling update is not supported if you have a port mapped to the host." />
|
helper="A comma separated list of ports you would like to map to the host system. Useful when you do not want to use domains.<br><br><span class='inline-block font-bold dark:text-warning'>Example:</span><br>3000:3000,3002:3002<br><br>Rolling update is not supported if you have a port mapped to the host."
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
@endif
|
@endif
|
||||||
@if (!$application->destination->server->isSwarm())
|
@if (!$application->destination->server->isSwarm())
|
||||||
<x-forms.input id="application.custom_network_aliases" label="Network Aliases"
|
<x-forms.input id="application.custom_network_aliases" label="Network Aliases"
|
||||||
helper="A comma separated list of custom network aliases you would like to add for container in Docker network.<br><br><span class='inline-block font-bold dark:text-warning'>Example:</span><br>api.internal,api.local"
|
helper="A comma separated list of custom network aliases you would like to add for container in Docker network.<br><br><span class='inline-block font-bold dark:text-warning'>Example:</span><br>api.internal,api.local"
|
||||||
wire:model="application.custom_network_aliases" />
|
wire:model="application.custom_network_aliases" x-bind:disabled="!canUpdate" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -391,60 +396,66 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox helper="This will add the proper proxy labels to the container." instantSave
|
<x-forms.checkbox helper="This will add the proper proxy labels to the container." instantSave
|
||||||
label="Enable" id="application.is_http_basic_auth_enabled" />
|
label="Enable" id="application.is_http_basic_auth_enabled"
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
</div>
|
</div>
|
||||||
@if ($application->is_http_basic_auth_enabled)
|
@if ($application->is_http_basic_auth_enabled)
|
||||||
<div class="flex gap-2 py-2">
|
<div class="flex gap-2 py-2">
|
||||||
<x-forms.input id="application.http_basic_auth_username" label="Username" required />
|
<x-forms.input id="application.http_basic_auth_username" label="Username" required
|
||||||
|
x-bind:disabled="!canUpdate" />
|
||||||
<x-forms.input id="application.http_basic_auth_password" type="password" label="Password"
|
<x-forms.input id="application.http_basic_auth_password" type="password" label="Password"
|
||||||
required />
|
required x-bind:disabled="!canUpdate" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if ($application->settings->is_container_label_readonly_enabled)
|
@if ($application->settings->is_container_label_readonly_enabled)
|
||||||
<x-forms.textarea readonly disabled label="Container Labels" rows="15" id="customLabels"
|
<x-forms.textarea readonly disabled label="Container Labels" rows="15" id="customLabels"
|
||||||
monacoEditorLanguage="ini" useMonacoEditor></x-forms.textarea>
|
monacoEditorLanguage="ini" useMonacoEditor x-bind:disabled="!canUpdate"></x-forms.textarea>
|
||||||
@else
|
@else
|
||||||
<x-forms.textarea label="Container Labels" rows="15" id="customLabels"
|
<x-forms.textarea label="Container Labels" rows="15" id="customLabels"
|
||||||
monacoEditorLanguage="ini" useMonacoEditor></x-forms.textarea>
|
monacoEditorLanguage="ini" useMonacoEditor x-bind:disabled="!canUpdate"></x-forms.textarea>
|
||||||
@endif
|
@endif
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<x-forms.checkbox label="Readonly labels"
|
<x-forms.checkbox label="Readonly labels"
|
||||||
helper="Labels are readonly by default. Readonly means that edits you do to the labels could be lost and Coolify will autogenerate the labels for you. If you want to edit the labels directly, disable this option. <br><br>Be careful, it could break the proxy configuration after you restart the container as Coolify will now NOT autogenerate the labels for you (ofc you can always reset the labels to the coolify defaults manually)."
|
helper="Labels are readonly by default. Readonly means that edits you do to the labels could be lost and Coolify will autogenerate the labels for you. If you want to edit the labels directly, disable this option. <br><br>Be careful, it could break the proxy configuration after you restart the container as Coolify will now NOT autogenerate the labels for you (ofc you can always reset the labels to the coolify defaults manually)."
|
||||||
id="application.settings.is_container_label_readonly_enabled" instantSave></x-forms.checkbox>
|
id="application.settings.is_container_label_readonly_enabled" instantSave
|
||||||
|
x-bind:disabled="!canUpdate"></x-forms.checkbox>
|
||||||
<x-forms.checkbox label="Escape special characters in labels?"
|
<x-forms.checkbox label="Escape special characters in labels?"
|
||||||
helper="By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$.<br><br>If you want to use env variables inside the labels, turn this off."
|
helper="By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$.<br><br>If you want to use env variables inside the labels, turn this off."
|
||||||
id="application.settings.is_container_label_escape_enabled" instantSave></x-forms.checkbox>
|
id="application.settings.is_container_label_escape_enabled" instantSave
|
||||||
|
x-bind:disabled="!canUpdate"></x-forms.checkbox>
|
||||||
</div>
|
</div>
|
||||||
<x-modal-confirmation title="Confirm Labels Reset to Coolify Defaults?"
|
@can('update', $application)
|
||||||
buttonTitle="Reset Labels to Defaults" buttonFullWidth submitAction="resetDefaultLabels(true)"
|
<x-modal-confirmation title="Confirm Labels Reset to Coolify Defaults?"
|
||||||
:actions="[
|
buttonTitle="Reset Labels to Defaults" buttonFullWidth submitAction="resetDefaultLabels(true)"
|
||||||
'All your custom proxy labels will be lost.',
|
:actions="[
|
||||||
'Proxy labels (traefik, caddy, etc) will be reset to the coolify defaults.',
|
'All your custom proxy labels will be lost.',
|
||||||
]" confirmationText="{{ $application->fqdn . '/' }}"
|
'Proxy labels (traefik, caddy, etc) will be reset to the coolify defaults.',
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Application URL below"
|
]" confirmationText="{{ $application->fqdn . '/' }}"
|
||||||
shortConfirmationLabel="Application URL" :confirmWithPassword="false"
|
confirmationLabel="Please confirm the execution of the actions by entering the Application URL below"
|
||||||
step2ButtonText="Permanently Reset Labels" />
|
shortConfirmationLabel="Application URL" :confirmWithPassword="false"
|
||||||
|
step2ButtonText="Permanently Reset Labels" />
|
||||||
|
@endcan
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<h3 class="pt-8">Pre/Post Deployment Commands</h3>
|
<h3 class="pt-8">Pre/Post Deployment Commands</h3>
|
||||||
<div class="flex flex-col gap-2 xl:flex-row">
|
<div class="flex flex-col gap-2 xl:flex-row">
|
||||||
<x-forms.input x-bind:disabled="initLoadingCompose" placeholder="php artisan migrate"
|
<x-forms.input x-bind:disabled="shouldDisable()" placeholder="php artisan migrate"
|
||||||
id="application.pre_deployment_command" label="Pre-deployment "
|
id="application.pre_deployment_command" label="Pre-deployment "
|
||||||
helper="An optional script or command to execute in the existing container before the deployment begins.<br>It is always executed with 'sh -c', so you do not need add it manually." />
|
helper="An optional script or command to execute in the existing container before the deployment begins.<br>It is always executed with 'sh -c', so you do not need add it manually." />
|
||||||
@if ($application->build_pack === 'dockercompose')
|
@if ($application->build_pack === 'dockercompose')
|
||||||
<x-forms.input x-bind:disabled="initLoadingCompose"
|
<x-forms.input x-bind:disabled="shouldDisable()" id="application.pre_deployment_command_container"
|
||||||
id="application.pre_deployment_command_container" label="Container Name"
|
label="Container Name"
|
||||||
helper="The name of the container to execute within. You can leave it blank if your application only has one container." />
|
helper="The name of the container to execute within. You can leave it blank if your application only has one container." />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2 xl:flex-row">
|
<div class="flex flex-col gap-2 xl:flex-row">
|
||||||
<x-forms.input x-bind:disabled="initLoadingCompose" placeholder="php artisan migrate"
|
<x-forms.input x-bind:disabled="shouldDisable()" placeholder="php artisan migrate"
|
||||||
id="application.post_deployment_command" label="Post-deployment "
|
id="application.post_deployment_command" label="Post-deployment "
|
||||||
helper="An optional script or command to execute in the newly built container after the deployment completes.<br>It is always executed with 'sh -c', so you do not need add it manually." />
|
helper="An optional script or command to execute in the newly built container after the deployment completes.<br>It is always executed with 'sh -c', so you do not need add it manually." />
|
||||||
@if ($application->build_pack === 'dockercompose')
|
@if ($application->build_pack === 'dockercompose')
|
||||||
<x-forms.input x-bind:disabled="initLoadingCompose"
|
<x-forms.input x-bind:disabled="shouldDisable()"
|
||||||
id="application.post_deployment_command_container" label="Container Name"
|
id="application.post_deployment_command_container" label="Container Name"
|
||||||
helper="The name of the container to execute within. You can leave it blank if your application only has one container." />
|
helper="The name of the container to execute within. You can leave it blank if your application only has one container." />
|
||||||
@endif
|
@endif
|
||||||
|
@@ -15,10 +15,12 @@
|
|||||||
Logs
|
Logs
|
||||||
</a>
|
</a>
|
||||||
@if (!$application->destination->server->isSwarm())
|
@if (!$application->destination->server->isSwarm())
|
||||||
<a class="{{ request()->routeIs('project.application.command') ? 'dark:text-white' : '' }}"
|
@can('canAccessTerminal')
|
||||||
href="{{ route('project.application.command', $parameters) }}">
|
<a class="{{ request()->routeIs('project.application.command') ? 'dark:text-white' : '' }}"
|
||||||
Terminal
|
href="{{ route('project.application.command', $parameters) }}">
|
||||||
</a>
|
Terminal
|
||||||
|
</a>
|
||||||
|
@endcan
|
||||||
@endif
|
@endif
|
||||||
<x-applications.links :application="$application" />
|
<x-applications.links :application="$application" />
|
||||||
</nav>
|
</nav>
|
||||||
|
@@ -1,13 +1,15 @@
|
|||||||
<form wire:submit='submit'>
|
<form wire:submit='submit'>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>Preview Deployments</h2>
|
<h2>Preview Deployments</h2>
|
||||||
<x-forms.button type="submit">Save</x-forms.button>
|
@can('update', $application)
|
||||||
<x-forms.button isHighlighted wire:click="resetToDefault">Reset template to default</x-forms.button>
|
<x-forms.button type="submit">Save</x-forms.button>
|
||||||
|
<x-forms.button isHighlighted wire:click="resetToDefault">Reset template to default</x-forms.button>
|
||||||
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
<div class="pb-4 ">Preview Deployments based on pull requests are here.</div>
|
<div class="pb-4 ">Preview Deployments based on pull requests are here.</div>
|
||||||
<div class="flex flex-col gap-2 pb-4">
|
<div class="flex flex-col gap-2 pb-4">
|
||||||
<x-forms.input id="previewUrlTemplate" label="Preview URL Template"
|
<x-forms.input id="previewUrlTemplate" label="Preview URL Template"
|
||||||
helper="Templates:<br/><span class='text-helper'>@@{{ random }}</span> to generate random sub-domain each time a PR is deployed<br/><span class='text-helper'>@@{{ pr_id }}</span> to use pull request ID as sub-domain or <span class='text-helper'>@@{{ domain }}</span> to replace the domain name with the application's domain name." />
|
helper="Templates:<br/><span class='text-helper'>@@{{ random }}</span> to generate random sub-domain each time a PR is deployed<br/><span class='text-helper'>@@{{ pr_id }}</span> to use pull request ID as sub-domain or <span class='text-helper'>@@{{ domain }}</span> to replace the domain name with the application's domain name." canGate="update" :canResource="$application" />
|
||||||
@if ($previewUrlTemplate)
|
@if ($previewUrlTemplate)
|
||||||
<div class="">Domain Preview: {{ $previewUrlTemplate }}</div>
|
<div class="">Domain Preview: {{ $previewUrlTemplate }}</div>
|
||||||
@endif
|
@endif
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<form wire:submit="save" class="flex items-end gap-2">
|
<form wire:submit="save" class="flex items-end gap-2">
|
||||||
<x-forms.input helper="One domain per preview." label="Domains for {{ str($serviceName)->headline() }}"
|
<x-forms.input helper="One domain per preview." label="Domains for {{ str($serviceName)->headline() }}"
|
||||||
id="service.domain"></x-forms.input>
|
id="service.domain" canGate="update" :canResource="$preview->application"></x-forms.input>
|
||||||
<x-forms.button type="submit">Save</x-forms.button>
|
<x-forms.button type="submit">Save</x-forms.button>
|
||||||
<x-forms.button wire:click="generate">Generate
|
<x-forms.button wire:click="generate">Generate
|
||||||
Domain</x-forms.button>
|
Domain</x-forms.button>
|
||||||
|
@@ -7,9 +7,11 @@
|
|||||||
<div>
|
<div>
|
||||||
@if ($application->is_github_based())
|
@if ($application->is_github_based())
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h3>Pull Requests on Git</h3>
|
@can('update', $application)
|
||||||
<x-forms.button wire:click="load_prs">Load Pull Requests
|
<h3>Pull Requests on Git</h3>
|
||||||
</x-forms.button>
|
<x-forms.button wire:click="load_prs">Load Pull Requests
|
||||||
|
</x-forms.button>
|
||||||
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@isset($rate_limit_remaining)
|
@isset($rate_limit_remaining)
|
||||||
@@ -40,19 +42,23 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="flex flex-col gap-1 md:flex-row">
|
<td class="flex flex-col gap-1 md:flex-row">
|
||||||
<x-forms.button
|
@can('update', $application)
|
||||||
wire:click="add('{{ data_get($pull_request, 'number') }}', '{{ data_get($pull_request, 'html_url') }}')">
|
<x-forms.button
|
||||||
Configure
|
wire:click="add('{{ data_get($pull_request, 'number') }}', '{{ data_get($pull_request, 'html_url') }}')">
|
||||||
</x-forms.button>
|
Configure
|
||||||
<x-forms.button
|
</x-forms.button>
|
||||||
wire:click="add_and_deploy('{{ data_get($pull_request, 'number') }}', '{{ data_get($pull_request, 'html_url') }}')">
|
@endcan
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 dark:text-warning"
|
@can('deploy', $application)
|
||||||
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
<x-forms.button
|
||||||
fill="none" stroke-linecap="round" stroke-linejoin="round">
|
wire:click="add_and_deploy('{{ data_get($pull_request, 'number') }}', '{{ data_get($pull_request, 'html_url') }}')">
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 dark:text-warning"
|
||||||
<path d="M7 4v16l13 -8z" />
|
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||||
</svg>Deploy
|
fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
</x-forms.button>
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M7 4v16l13 -8z" />
|
||||||
|
</svg>Deploy
|
||||||
|
</x-forms.button>
|
||||||
|
@endcan
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
@@ -106,10 +112,12 @@
|
|||||||
<form wire:submit="save_preview('{{ $preview->id }}')"
|
<form wire:submit="save_preview('{{ $preview->id }}')"
|
||||||
class="flex items-end gap-2 pt-4">
|
class="flex items-end gap-2 pt-4">
|
||||||
<x-forms.input label="Domain" helper="One domain per preview."
|
<x-forms.input label="Domain" helper="One domain per preview."
|
||||||
id="application.previews.{{ $previewName }}.fqdn"></x-forms.input>
|
id="application.previews.{{ $previewName }}.fqdn" canGate="update" :canResource="$application"></x-forms.input>
|
||||||
<x-forms.button type="submit">Save</x-forms.button>
|
@can('update', $application)
|
||||||
<x-forms.button wire:click="generate_preview('{{ $preview->id }}')">Generate
|
<x-forms.button type="submit">Save</x-forms.button>
|
||||||
Domain</x-forms.button>
|
<x-forms.button wire:click="generate_preview('{{ $preview->id }}')">Generate
|
||||||
|
Domain</x-forms.button>
|
||||||
|
@endcan
|
||||||
</form>
|
</form>
|
||||||
@else
|
@else
|
||||||
@foreach (collect(json_decode($preview->docker_compose_domains)) as $serviceName => $service)
|
@foreach (collect(json_decode($preview->docker_compose_domains)) as $serviceName => $service)
|
||||||
@@ -122,82 +130,90 @@
|
|||||||
@else
|
@else
|
||||||
<form wire:submit="save_preview('{{ $preview->id }}')" class="flex items-end gap-2 pt-4">
|
<form wire:submit="save_preview('{{ $preview->id }}')" class="flex items-end gap-2 pt-4">
|
||||||
<x-forms.input label="Domain" helper="One domain per preview."
|
<x-forms.input label="Domain" helper="One domain per preview."
|
||||||
id="application.previews.{{ $previewName }}.fqdn"></x-forms.input>
|
id="application.previews.{{ $previewName }}.fqdn" canGate="update" :canResource="$application"></x-forms.input>
|
||||||
<x-forms.button type="submit">Save</x-forms.button>
|
@can('update', $application)
|
||||||
<x-forms.button wire:click="generate_preview('{{ $preview->id }}')">Generate
|
<x-forms.button type="submit">Save</x-forms.button>
|
||||||
Domain</x-forms.button>
|
<x-forms.button wire:click="generate_preview('{{ $preview->id }}')">Generate
|
||||||
|
Domain</x-forms.button>
|
||||||
|
@endcan
|
||||||
</form>
|
</form>
|
||||||
@endif
|
@endif
|
||||||
<div class="flex flex-col xl:flex-row xl:items-center gap-2 pt-6">
|
<div class="flex flex-col xl:flex-row xl:items-center gap-2 pt-6">
|
||||||
<div class="flex-1"></div>
|
<div class="flex-1"></div>
|
||||||
<x-forms.button
|
@can('deploy', $application)
|
||||||
wire:click="force_deploy_without_cache({{ data_get($preview, 'pull_request_id') }})">
|
<x-forms.button
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" viewBox="0 0 24 24"
|
wire:click="force_deploy_without_cache({{ data_get($preview, 'pull_request_id') }})">
|
||||||
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" viewBox="0 0 24 24"
|
||||||
stroke-linejoin="round">
|
stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round"
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
stroke-linejoin="round">
|
||||||
<path
|
|
||||||
d="M12.983 8.978c3.955 -.182 7.017 -1.446 7.017 -2.978c0 -1.657 -3.582 -3 -8 -3c-1.661 0 -3.204 .19 -4.483 .515m-2.783 1.228c-.471 .382 -.734 .808 -.734 1.257c0 1.22 1.944 2.271 4.734 2.74" />
|
|
||||||
<path
|
|
||||||
d="M4 6v6c0 1.657 3.582 3 8 3c.986 0 1.93 -.067 2.802 -.19m3.187 -.82c1.251 -.53 2.011 -1.228 2.011 -1.99v-6" />
|
|
||||||
<path d="M4 12v6c0 1.657 3.582 3 8 3c3.217 0 5.991 -.712 7.261 -1.74m.739 -3.26v-4" />
|
|
||||||
<path d="M3 3l18 18" />
|
|
||||||
</svg>
|
|
||||||
Force deploy (without
|
|
||||||
cache)
|
|
||||||
</x-forms.button>
|
|
||||||
<x-forms.button wire:click="deploy({{ data_get($preview, 'pull_request_id') }})">
|
|
||||||
@if (data_get($preview, 'status') === 'exited')
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 dark:text-warning"
|
|
||||||
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none"
|
|
||||||
stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
<path d="M7 4v16l13 -8z" />
|
|
||||||
</svg>
|
|
||||||
Deploy
|
|
||||||
@else
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 dark:text-orange-400"
|
|
||||||
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
|
|
||||||
stroke-linecap="round" stroke-linejoin="round">
|
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
|
||||||
<path
|
<path
|
||||||
d="M10.09 4.01l.496 -.495a2 2 0 0 1 2.828 0l7.071 7.07a2 2 0 0 1 0 2.83l-7.07 7.07a2 2 0 0 1 -2.83 0l-7.07 -7.07a2 2 0 0 1 0 -2.83l3.535 -3.535h-3.988">
|
d="M12.983 8.978c3.955 -.182 7.017 -1.446 7.017 -2.978c0 -1.657 -3.582 -3 -8 -3c-1.661 0 -3.204 .19 -4.483 .515m-2.783 1.228c-.471 .382 -.734 .808 -.734 1.257c0 1.22 1.944 2.271 4.734 2.74" />
|
||||||
</path>
|
<path
|
||||||
<path d="M7.05 11.038v-3.988"></path>
|
d="M4 6v6c0 1.657 3.582 3 8 3c.986 0 1.93 -.067 2.802 -.19m3.187 -.82c1.251 -.53 2.011 -1.228 2.011 -1.99v-6" />
|
||||||
</svg> Redeploy
|
<path d="M4 12v6c0 1.657 3.582 3 8 3c3.217 0 5.991 -.712 7.261 -1.74m.739 -3.26v-4" />
|
||||||
@endif
|
<path d="M3 3l18 18" />
|
||||||
</x-forms.button>
|
</svg>
|
||||||
@if (data_get($preview, 'status') !== 'exited')
|
Force deploy (without
|
||||||
<x-modal-confirmation title="Confirm Preview Deployment Stopping?" buttonTitle="Stop"
|
cache)
|
||||||
submitAction="stop({{ data_get($preview, 'pull_request_id') }})" :actions="[
|
</x-forms.button>
|
||||||
'This preview deployment will be stopped.',
|
<x-forms.button wire:click="deploy({{ data_get($preview, 'pull_request_id') }})">
|
||||||
'If the preview deployment is currently in use data could be lost.',
|
@if (data_get($preview, 'status') === 'exited')
|
||||||
'All non-persistent data of this preview deployment (containers, networks, unused images) will be deleted (don\'t worry, no data is lost and you can start the preview deployment again).',
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 dark:text-warning"
|
||||||
]"
|
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none"
|
||||||
:confirmWithText="false" :confirmWithPassword="false" step2ButtonText="Stop Preview Deployment">
|
stroke-linecap="round" stroke-linejoin="round">
|
||||||
<x-slot:customButton>
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-error"
|
<path d="M7 4v16l13 -8z" />
|
||||||
|
</svg>
|
||||||
|
Deploy
|
||||||
|
@else
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 dark:text-orange-400"
|
||||||
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
|
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
|
||||||
stroke-linecap="round" stroke-linejoin="round">
|
stroke-linecap="round" stroke-linejoin="round">
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||||
<path
|
<path
|
||||||
d="M6 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z">
|
d="M10.09 4.01l.496 -.495a2 2 0 0 1 2.828 0l7.071 7.07a2 2 0 0 1 0 2.83l-7.07 7.07a2 2 0 0 1 -2.83 0l-7.07 -7.07a2 2 0 0 1 0 -2.83l3.535 -3.535h-3.988">
|
||||||
</path>
|
</path>
|
||||||
<path
|
<path d="M7.05 11.038v-3.988"></path>
|
||||||
d="M14 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z">
|
</svg> Redeploy
|
||||||
</path>
|
@endif
|
||||||
</svg>
|
</x-forms.button>
|
||||||
Stop
|
@endcan
|
||||||
</x-slot:customButton>
|
@if (data_get($preview, 'status') !== 'exited')
|
||||||
</x-modal-confirmation>
|
@can('deploy', $application)
|
||||||
|
<x-modal-confirmation title="Confirm Preview Deployment Stopping?" buttonTitle="Stop"
|
||||||
|
submitAction="stop({{ data_get($preview, 'pull_request_id') }})" :actions="[
|
||||||
|
'This preview deployment will be stopped.',
|
||||||
|
'If the preview deployment is currently in use data could be lost.',
|
||||||
|
'All non-persistent data of this preview deployment (containers, networks, unused images) will be deleted (don\'t worry, no data is lost and you can start the preview deployment again).',
|
||||||
|
]"
|
||||||
|
:confirmWithText="false" :confirmWithPassword="false" step2ButtonText="Stop Preview Deployment">
|
||||||
|
<x-slot:customButton>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-error"
|
||||||
|
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
|
||||||
|
stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||||||
|
<path
|
||||||
|
d="M6 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z">
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
d="M14 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
Stop
|
||||||
|
</x-slot:customButton>
|
||||||
|
</x-modal-confirmation>
|
||||||
|
@endcan
|
||||||
@endif
|
@endif
|
||||||
<x-modal-confirmation title="Confirm Preview Deployment Deletion?" buttonTitle="Delete"
|
@can('delete', $application)
|
||||||
isErrorButton submitAction="delete({{ data_get($preview, 'pull_request_id') }})"
|
<x-modal-confirmation title="Confirm Preview Deployment Deletion?" buttonTitle="Delete"
|
||||||
:actions="[
|
isErrorButton submitAction="delete({{ data_get($preview, 'pull_request_id') }})"
|
||||||
'All containers of this preview deployment will be stopped and permanently deleted.',
|
:actions="[
|
||||||
]" confirmationText="{{ data_get($preview, 'fqdn') . '/' }}"
|
'All containers of this preview deployment will be stopped and permanently deleted.',
|
||||||
confirmationLabel="Please confirm the execution of the actions by entering the Preview Deployment name below"
|
]" confirmationText="{{ data_get($preview, 'fqdn') . '/' }}"
|
||||||
shortConfirmationLabel="Preview Deployment Name" :confirmWithPassword="false" />
|
confirmationLabel="Please confirm the execution of the actions by entering the Preview Deployment name below"
|
||||||
|
shortConfirmationLabel="Preview Deployment Name" :confirmWithPassword="false" />
|
||||||
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
<div x-init="$wire.loadImages">
|
<div x-init="$wire.loadImages">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>Rollback</h2>
|
<h2>Rollback</h2>
|
||||||
<x-forms.button wire:click='loadImages(true)'>Reload Available Images</x-forms.button>
|
@can('view', $application)
|
||||||
|
<x-forms.button wire:click='loadImages(true)'>Reload Available Images</x-forms.button>
|
||||||
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
<div class="pb-4 ">You can easily rollback to a previously built (local) images
|
<div class="pb-4 ">You can easily rollback to a previously built (local) images
|
||||||
quickly.</div>
|
quickly.</div>
|
||||||
@@ -26,16 +28,18 @@
|
|||||||
<div class="text-xs">{{ $date }}</div>
|
<div class="text-xs">{{ $date }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end p-2">
|
<div class="flex justify-end p-2">
|
||||||
@if (data_get($image, 'is_current'))
|
@can('deploy', $application)
|
||||||
<x-forms.button disabled tooltip="This image is currently running.">
|
@if (data_get($image, 'is_current'))
|
||||||
Rollback
|
<x-forms.button disabled tooltip="This image is currently running.">
|
||||||
</x-forms.button>
|
Rollback
|
||||||
@else
|
</x-forms.button>
|
||||||
<x-forms.button class="dark:bg-coolgray-100"
|
@else
|
||||||
wire:click="rollbackImage('{{ data_get($image, 'tag') }}')">
|
<x-forms.button class="dark:bg-coolgray-100"
|
||||||
Rollback
|
wire:click="rollbackImage('{{ data_get($image, 'tag') }}')">
|
||||||
</x-forms.button>
|
Rollback
|
||||||
@endif
|
</x-forms.button>
|
||||||
|
@endif
|
||||||
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,7 +2,9 @@
|
|||||||
<form wire:submit='submit' class="flex flex-col">
|
<form wire:submit='submit' class="flex flex-col">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>Source</h2>
|
<h2>Source</h2>
|
||||||
<x-forms.button type="submit">Save</x-forms.button>
|
@can('update', $application)
|
||||||
|
<x-forms.button type="submit">Save</x-forms.button>
|
||||||
|
@endcan
|
||||||
<a target="_blank" class="hover:no-underline" href="{{ $application?->gitBranchLocation }}">
|
<a target="_blank" class="hover:no-underline" href="{{ $application?->gitBranchLocation }}">
|
||||||
<x-forms.button>
|
<x-forms.button>
|
||||||
Open Repository
|
Open Repository
|
||||||
@@ -32,11 +34,11 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input placeholder="coollabsio/coolify-example" id="gitRepository" label="Repository" />
|
<x-forms.input placeholder="coollabsio/coolify-example" id="gitRepository" label="Repository" canGate="update" :canResource="$application" />
|
||||||
<x-forms.input placeholder="main" id="gitBranch" label="Branch" />
|
<x-forms.input placeholder="main" id="gitBranch" label="Branch" canGate="update" :canResource="$application" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-end gap-2">
|
<div class="flex items-end gap-2">
|
||||||
<x-forms.input placeholder="HEAD" id="gitCommitSha" placeholder="HEAD" label="Commit SHA" />
|
<x-forms.input placeholder="HEAD" id="gitCommitSha" placeholder="HEAD" label="Commit SHA" canGate="update" :canResource="$application" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -46,45 +48,49 @@
|
|||||||
class="dark:text-warning">{{ $privateKeyName }}</span>
|
class="dark:text-warning">{{ $privateKeyName }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 class="py-2 ">Select another Private Key</h4>
|
@can('update', $application)
|
||||||
<div class="flex flex-wrap gap-2">
|
<h4 class="py-2 ">Select another Private Key</h4>
|
||||||
@foreach ($privateKeys as $key)
|
<div class="flex flex-wrap gap-2">
|
||||||
<x-forms.button wire:click="setPrivateKey('{{ $key->id }}')">{{ $key->name }}
|
@foreach ($privateKeys as $key)
|
||||||
</x-forms.button>
|
<x-forms.button wire:click="setPrivateKey('{{ $key->id }}')">{{ $key->name }}
|
||||||
@endforeach
|
</x-forms.button>
|
||||||
</div>
|
@endforeach
|
||||||
@else
|
|
||||||
<div class="pt-4">
|
|
||||||
<h3 class="pb-2">Change Git Source</h3>
|
|
||||||
<div class="grid grid-cols-1 gap-2">
|
|
||||||
@forelse ($sources as $source)
|
|
||||||
<div wire:key="{{ $source->name }}">
|
|
||||||
<x-modal-confirmation title="Change Git Source" :actions="['Change git source to ' . $source->name]" :buttonFullWidth="true"
|
|
||||||
:isHighlightedButton="$application->source_id === $source->id" :disabled="$application->source_id === $source->id"
|
|
||||||
submitAction="changeSource({{ $source->id }}, {{ $source->getMorphClass() }})"
|
|
||||||
:confirmWithText="true" confirmationText="Change Git Source"
|
|
||||||
confirmationLabel="Please confirm changing the git source by entering the text below"
|
|
||||||
shortConfirmationLabel="Confirmation Text" :confirmWithPassword="false">
|
|
||||||
<x-slot:customButton>
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<div class="box-title">
|
|
||||||
{{ $source->name }}
|
|
||||||
@if ($application->source_id === $source->id)
|
|
||||||
<span class="text-xs">(current)</span>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
<div class="box-description">
|
|
||||||
{{ $source->organization ?? 'Personal Account' }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</x-slot:customButton>
|
|
||||||
</x-modal-confirmation>
|
|
||||||
</div>
|
|
||||||
@empty
|
|
||||||
<div>No other sources found</div>
|
|
||||||
@endforelse
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
@endcan
|
||||||
|
@else
|
||||||
|
@can('update', $application)
|
||||||
|
<div class="pt-4">
|
||||||
|
<h3 class="pb-2">Change Git Source</h3>
|
||||||
|
<div class="grid grid-cols-1 gap-2">
|
||||||
|
@forelse ($sources as $source)
|
||||||
|
<div wire:key="{{ $source->name }}">
|
||||||
|
<x-modal-confirmation title="Change Git Source" :actions="['Change git source to ' . $source->name]" :buttonFullWidth="true"
|
||||||
|
:isHighlightedButton="$application->source_id === $source->id" :disabled="$application->source_id === $source->id"
|
||||||
|
submitAction="changeSource({{ $source->id }}, {{ $source->getMorphClass() }})"
|
||||||
|
:confirmWithText="true" confirmationText="Change Git Source"
|
||||||
|
confirmationLabel="Please confirm changing the git source by entering the text below"
|
||||||
|
shortConfirmationLabel="Confirmation Text" :confirmWithPassword="false">
|
||||||
|
<x-slot:customButton>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<div class="box-title">
|
||||||
|
{{ $source->name }}
|
||||||
|
@if ($application->source_id === $source->id)
|
||||||
|
<span class="text-xs">(current)</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
<div class="box-description">
|
||||||
|
{{ $source->organization ?? 'Personal Account' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</x-slot:customButton>
|
||||||
|
</x-modal-confirmation>
|
||||||
|
</div>
|
||||||
|
@empty
|
||||||
|
<div>No other sources found</div>
|
||||||
|
@endforelse
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endcan
|
||||||
@endif
|
@endif
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -15,14 +15,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2 py-4">
|
<div class="flex flex-col gap-2 py-4">
|
||||||
<div class="flex flex-col items-end gap-2 xl:flex-row">
|
<div class="flex flex-col items-end gap-2 xl:flex-row">
|
||||||
<x-forms.input id="swarmReplicas" label="Replicas" required />
|
<x-forms.input id="swarmReplicas" label="Replicas" required canGate="update" :canResource="$application" />
|
||||||
<x-forms.checkbox instantSave helper="If turned off, this resource will start on manager nodes too."
|
<x-forms.checkbox instantSave helper="If turned off, this resource will start on manager nodes too."
|
||||||
id="isSwarmOnlyWorkerNodes" label="Only Start on Worker nodes" />
|
id="isSwarmOnlyWorkerNodes" label="Only Start on Worker nodes" canGate="update" :canResource="$application" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.textarea id="swarmPlacementConstraints" rows="7" label="Custom Placement Constraints"
|
<x-forms.textarea id="swarmPlacementConstraints" rows="7" label="Custom Placement Constraints"
|
||||||
placeholder="placement:
|
placeholder="placement:
|
||||||
constraints:
|
constraints:
|
||||||
- 'node.role == worker'" />
|
- 'node.role == worker'" canGate="update" :canResource="$application" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
@@ -8,9 +8,11 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<h2 class="pb-4">Scheduled Backups</h2>
|
<h2 class="pb-4">Scheduled Backups</h2>
|
||||||
<x-modal-input buttonTitle="+ Add" title="New Scheduled Backup">
|
@can('update', $database)
|
||||||
<livewire:project.database.create-scheduled-backup :database="$database" />
|
<x-modal-input buttonTitle="+ Add" title="New Scheduled Backup">
|
||||||
</x-modal-input>
|
<livewire:project.database.create-scheduled-backup :database="$database" />
|
||||||
|
</x-modal-input>
|
||||||
|
@endcan
|
||||||
</div>
|
</div>
|
||||||
<livewire:project.database.scheduled-backups :database="$database" />
|
<livewire:project.database.scheduled-backups :database="$database" />
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,54 +2,56 @@
|
|||||||
<form wire:submit="submit" class="flex flex-col gap-2">
|
<form wire:submit="submit" class="flex flex-col gap-2">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>General</h2>
|
<h2>General</h2>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit" canGate="update" :canResource="$database">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input label="Name" id="name" />
|
<x-forms.input label="Name" id="name" canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Description" id="description" />
|
<x-forms.input label="Description" id="description" canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Image" id="image" required
|
<x-forms.input label="Image" id="image" required canGate="update" :canResource="$database"
|
||||||
helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/r/clickhouse/clickhouse-server/'>https://hub.docker.com/r/clickhouse/clickhouse-server/</a>" />
|
helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/r/clickhouse/clickhouse-server/'>https://hub.docker.com/r/clickhouse/clickhouse-server/</a>" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if ($database->started_at)
|
@if ($database->started_at)
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input label="Initial Username" id="clickhouseAdminUser" placeholder="If empty: clickhouse"
|
<x-forms.input label="Initial Username" id="clickhouseAdminUser" placeholder="If empty: clickhouse"
|
||||||
readonly helper="You can only change this in the database." />
|
readonly helper="You can only change this in the database." canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Initial Password" id="clickhouseAdminPassword" type="password" required readonly
|
<x-forms.input label="Initial Password" id="clickhouseAdminPassword" type="password" required readonly
|
||||||
helper="You can only change this in the database." />
|
helper="You can only change this in the database." canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<div class=" dark:text-warning">Please verify these values. You can only modify them before the initial
|
<div class=" dark:text-warning">Please verify these values. You can only modify them before the initial
|
||||||
start. After that, you need to modify it in the database.
|
start. After that, you need to modify it in the database.
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input label="Username" id="clickhouseAdminUser" required />
|
<x-forms.input label="Username" id="clickhouseAdminUser" required canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Password" id="clickhouseAdminPassword" type="password" required />
|
<x-forms.input label="Password" id="clickhouseAdminPassword" type="password" required canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<x-forms.input
|
<x-forms.input
|
||||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
||||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
||||||
id="customDockerRunOptions" label="Custom Docker Options" />
|
id="customDockerRunOptions" label="Custom Docker Options" canGate="update" :canResource="$database" />
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<h3 class="py-2">Network</h3>
|
<h3 class="py-2">Network</h3>
|
||||||
<div class="flex items-end gap-2">
|
<div class="flex items-end gap-2">
|
||||||
<x-forms.input placeholder="3000:5432" id="portsMappings" label="Ports Mappings"
|
<x-forms.input placeholder="3000:5432" id="portsMappings" label="Ports Mappings"
|
||||||
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
|
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input label="Clickhouse URL (internal)"
|
<x-forms.input label="Clickhouse URL (internal)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
type="password" readonly wire:model="dbUrl" />
|
type="password" readonly wire:model="dbUrl" canGate="update" :canResource="$database" />
|
||||||
@if ($dbUrlPublic)
|
@if ($dbUrlPublic)
|
||||||
<x-forms.input label="Clickhouse URL (public)"
|
<x-forms.input label="Clickhouse URL (public)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
type="password" readonly wire:model="dbUrlPublic" />
|
type="password" readonly wire:model="dbUrlPublic" canGate="update" :canResource="$database" />
|
||||||
@else
|
@else
|
||||||
<x-forms.input label="Clickhouse URL (public)"
|
<x-forms.input label="Clickhouse URL (public)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
readonly value="Starting the database will generate this." />
|
readonly value="Starting the database will generate this." canGate="update" :canResource="$database" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -71,14 +73,17 @@
|
|||||||
</x-slide-over>
|
</x-slide-over>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" />
|
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" />
|
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<h3 class="pt-4">Advanced</h3>
|
<h3 class="pt-4">Advanced</h3>
|
||||||
<div class="w-64">
|
<div class="w-64">
|
||||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||||
instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" />
|
instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -17,9 +17,11 @@
|
|||||||
<a class='menu-item' wire:current.exact="menu-item-active"
|
<a class='menu-item' wire:current.exact="menu-item-active"
|
||||||
href="{{ route('project.database.persistent-storage', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'database_uuid' => $database->uuid]) }}">Persistent
|
href="{{ route('project.database.persistent-storage', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'database_uuid' => $database->uuid]) }}">Persistent
|
||||||
Storage</a>
|
Storage</a>
|
||||||
<a class='menu-item' wire:current.exact="menu-item-active"
|
@can('update', $database)
|
||||||
href="{{ route('project.database.import-backups', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'database_uuid' => $database->uuid]) }}">Import
|
<a class='menu-item' wire:current.exact="menu-item-active"
|
||||||
Backups</a>
|
href="{{ route('project.database.import-backups', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'database_uuid' => $database->uuid]) }}">Import
|
||||||
|
Backups</a>
|
||||||
|
@endcan
|
||||||
<a class='menu-item' wire:current.exact="menu-item-active"
|
<a class='menu-item' wire:current.exact="menu-item-active"
|
||||||
href="{{ route('project.database.webhooks', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'database_uuid' => $database->uuid]) }}">Webhooks</a>
|
href="{{ route('project.database.webhooks', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'database_uuid' => $database->uuid]) }}">Webhooks</a>
|
||||||
<a class="menu-item" wire:current.exact="menu-item-active"
|
<a class="menu-item" wire:current.exact="menu-item-active"
|
||||||
|
@@ -2,51 +2,53 @@
|
|||||||
<form wire:submit="submit" class="flex flex-col gap-2">
|
<form wire:submit="submit" class="flex flex-col gap-2">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>General</h2>
|
<h2>General</h2>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit" canGate="update" :canResource="$database">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input label="Name" id="name" />
|
<x-forms.input label="Name" id="name" canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Description" id="description" />
|
<x-forms.input label="Description" id="description" canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Image" id="image" required />
|
<x-forms.input label="Image" id="image" required canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input
|
<x-forms.input
|
||||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
||||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
||||||
id="customDockerRunOptions" label="Custom Docker Options" />
|
id="customDockerRunOptions" label="Custom Docker Options" canGate="update" :canResource="$database" />
|
||||||
|
|
||||||
@if ($database->started_at)
|
@if ($database->started_at)
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input label="Initial Password" id="dragonflyPassword" type="password" required readonly
|
<x-forms.input label="Initial Password" id="dragonflyPassword" type="password" required readonly
|
||||||
helper="You can only change this in the database." />
|
helper="You can only change this in the database." canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<div class=" dark:text-warning">Please verify these values. You can only modify them before the initial
|
<div class=" dark:text-warning">Please verify these values. You can only modify them before the initial
|
||||||
start. After that, you need to modify it in the database.
|
start. After that, you need to modify it in the database.
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input label="Password" id="dragonflyPassword" type="password" required />
|
<x-forms.input label="Password" id="dragonflyPassword" type="password" required canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<h3 class="py-2">Network</h3>
|
<h3 class="py-2">Network</h3>
|
||||||
<div class="flex items-end gap-2">
|
<div class="flex items-end gap-2">
|
||||||
<x-forms.input placeholder="3000:5432" id="portsMappings" label="Ports Mappings"
|
<x-forms.input placeholder="3000:5432" id="portsMappings" label="Ports Mappings"
|
||||||
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
|
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input label="Dragonfly URL (internal)"
|
<x-forms.input label="Dragonfly URL (internal)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
type="password" readonly wire:model="dbUrl" />
|
type="password" readonly wire:model="dbUrl" canGate="update" :canResource="$database" />
|
||||||
|
|
||||||
@if ($dbUrlPublic)
|
@if ($dbUrlPublic)
|
||||||
<x-forms.input label="Dragonfly URL (public)"
|
<x-forms.input label="Dragonfly URL (public)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
type="password" readonly wire:model="dbUrlPublic" />
|
type="password" readonly wire:model="dbUrlPublic" canGate="update" :canResource="$database" />
|
||||||
@else
|
@else
|
||||||
<x-forms.input label="Dragonfly URL (public)"
|
<x-forms.input label="Dragonfly URL (public)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
readonly value="Starting the database will generate this." />
|
readonly value="Starting the database will generate this." canGate="update" :canResource="$database" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
@@ -79,11 +81,12 @@
|
|||||||
<div class="w-64">
|
<div class="w-64">
|
||||||
@if (str($database->status)->contains('exited'))
|
@if (str($database->status)->contains('exited'))
|
||||||
<x-forms.checkbox id="enable_ssl" label="Enable SSL" wire:model.live="enable_ssl"
|
<x-forms.checkbox id="enable_ssl" label="Enable SSL" wire:model.live="enable_ssl"
|
||||||
instantSave="instantSaveSSL" />
|
instantSave="instantSaveSSL" canGate="update" :canResource="$database" />
|
||||||
@else
|
@else
|
||||||
<x-forms.checkbox id="enable_ssl" label="Enable SSL" wire:model.live="enable_ssl"
|
<x-forms.checkbox id="enable_ssl" label="Enable SSL" wire:model.live="enable_ssl"
|
||||||
instantSave="instantSaveSSL" disabled
|
instantSave="instantSaveSSL" disabled
|
||||||
helper="Database should be stopped to change this settings." />
|
helper="Database should be stopped to change this settings." canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -107,14 +110,17 @@
|
|||||||
</x-slide-over>
|
</x-slide-over>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" />
|
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" />
|
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<h3 class="pt-4">Advanced</h3>
|
<h3 class="pt-4">Advanced</h3>
|
||||||
<div class="w-64">
|
<div class="w-64">
|
||||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||||
instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" />
|
instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -18,10 +18,12 @@
|
|||||||
href="{{ route('project.database.logs', $parameters) }}">
|
href="{{ route('project.database.logs', $parameters) }}">
|
||||||
Logs
|
Logs
|
||||||
</a>
|
</a>
|
||||||
<a class="{{ request()->routeIs('project.database.command') ? 'dark:text-white' : '' }}"
|
@can('canAccessTerminal')
|
||||||
href="{{ route('project.database.command', $parameters) }}">
|
<a class="{{ request()->routeIs('project.database.command') ? 'dark:text-white' : '' }}"
|
||||||
Terminal
|
href="{{ route('project.database.command', $parameters) }}">
|
||||||
</a>
|
Terminal
|
||||||
|
</a>
|
||||||
|
@endcan
|
||||||
@if (
|
@if (
|
||||||
$database->getMorphClass() === 'App\Models\StandalonePostgresql' ||
|
$database->getMorphClass() === 'App\Models\StandalonePostgresql' ||
|
||||||
$database->getMorphClass() === 'App\Models\StandaloneMongodb' ||
|
$database->getMorphClass() === 'App\Models\StandaloneMongodb' ||
|
||||||
|
@@ -108,8 +108,8 @@
|
|||||||
<div>Location: <span x-text="filename ?? 'N/A'"></span> <span x-text="filesize">/ </span></div>
|
<div>Location: <span x-text="filename ?? 'N/A'"></span> <span x-text="filesize">/ </span></div>
|
||||||
<x-forms.button class="w-full my-4" wire:click='runImport'>Restore Backup</x-forms.button>
|
<x-forms.button class="w-full my-4" wire:click='runImport'>Restore Backup</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
<div class="container w-full mx-auto">
|
<div class="container w-full mx-auto" x-show="$wire.importRunning">
|
||||||
<livewire:activity-monitor header="Database Restore Output" />
|
<livewire:activity-monitor header="Database Restore Output" :showWaiting="false" />
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<div>Database must be running to restore a backup.</div>
|
<div>Database must be running to restore a backup.</div>
|
||||||
|
@@ -2,51 +2,53 @@
|
|||||||
<form wire:submit="submit" class="flex flex-col gap-2">
|
<form wire:submit="submit" class="flex flex-col gap-2">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>General</h2>
|
<h2>General</h2>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit" canGate="update" :canResource="$database">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input label="Name" id="name" />
|
<x-forms.input label="Name" id="name" canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Description" id="description" />
|
<x-forms.input label="Description" id="description" canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Image" id="image" required
|
<x-forms.input label="Image" id="image" required canGate="update" :canResource="$database"
|
||||||
helper="For all available images, check here:<br><br><a target='_blank' href=https://hub.docker.com/r/eqalpha/keydb'>https://hub.docker.com/r/eqalpha/keydb</a>" />
|
helper="For all available images, check here:<br><br><a target='_blank' href=https://hub.docker.com/r/eqalpha/keydb'>https://hub.docker.com/r/eqalpha/keydb</a>" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if ($database->started_at)
|
@if ($database->started_at)
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input label="Initial Password" id="keydbPassword" type="password" required readonly
|
<x-forms.input label="Initial Password" id="keydbPassword" type="password" required readonly
|
||||||
helper="You can only change this in the database." />
|
helper="You can only change this in the database." canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<div class=" dark:text-warning">Please verify these values. You can only modify them before the initial
|
<div class=" dark:text-warning">Please verify these values. You can only modify them before the initial
|
||||||
start. After that, you need to modify it in the database.
|
start. After that, you need to modify it in the database.
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input label="Password" id="keydbPassword" type="password" required />
|
<x-forms.input label="Password" id="keydbPassword" type="password" required canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<x-forms.input
|
<x-forms.input
|
||||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
||||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
||||||
id="customDockerRunOptions" label="Custom Docker Options" />
|
id="customDockerRunOptions" label="Custom Docker Options" canGate="update" :canResource="$database" />
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<h3 class="py-2">Network</h3>
|
<h3 class="py-2">Network</h3>
|
||||||
<div class="flex items-end gap-2">
|
<div class="flex items-end gap-2">
|
||||||
<x-forms.input placeholder="3000:5432" id="portsMappings" label="Ports Mappings"
|
<x-forms.input placeholder="3000:5432" id="portsMappings" label="Ports Mappings"
|
||||||
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
|
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input label="KeyDB URL (internal)"
|
<x-forms.input label="KeyDB URL (internal)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
type="password" readonly wire:model="dbUrl" />
|
type="password" readonly wire:model="dbUrl" canGate="update" :canResource="$database" />
|
||||||
@if ($dbUrlPublic)
|
@if ($dbUrlPublic)
|
||||||
<x-forms.input label="KeyDB URL (public)"
|
<x-forms.input label="KeyDB URL (public)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
type="password" readonly wire:model="dbUrlPublic" />
|
type="password" readonly wire:model="dbUrlPublic" canGate="update" :canResource="$database" />
|
||||||
@else
|
@else
|
||||||
<x-forms.input label="KeyDB URL (public)"
|
<x-forms.input label="KeyDB URL (public)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
readonly value="Starting the database will generate this." />
|
readonly value="Starting the database will generate this." canGate="update" :canResource="$database" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
@@ -79,11 +81,12 @@
|
|||||||
<div class="w-64">
|
<div class="w-64">
|
||||||
@if (str($database->status)->contains('exited'))
|
@if (str($database->status)->contains('exited'))
|
||||||
<x-forms.checkbox id="enable_ssl" label="Enable SSL" wire:model.live="enable_ssl"
|
<x-forms.checkbox id="enable_ssl" label="Enable SSL" wire:model.live="enable_ssl"
|
||||||
instantSave="instantSaveSSL" />
|
instantSave="instantSaveSSL" canGate="update" :canResource="$database" />
|
||||||
@else
|
@else
|
||||||
<x-forms.checkbox id="enable_ssl" label="Enable SSL" wire:model.live="enable_ssl"
|
<x-forms.checkbox id="enable_ssl" label="Enable SSL" wire:model.live="enable_ssl"
|
||||||
instantSave="instantSaveSSL" disabled
|
instantSave="instantSaveSSL" disabled
|
||||||
helper="Database should be stopped to change this settings." />
|
helper="Database should be stopped to change this settings." canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -107,17 +110,20 @@
|
|||||||
</x-slide-over>
|
</x-slide-over>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" />
|
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" />
|
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.textarea
|
<x-forms.textarea
|
||||||
helper="<a target='_blank' class='underline dark:text-white' href='https://raw.githubusercontent.com/Snapchat/KeyDB/unstable/keydb.conf'>KeyDB Default Configuration</a>"
|
helper="<a target='_blank' class='underline dark:text-white' href='https://raw.githubusercontent.com/Snapchat/KeyDB/unstable/keydb.conf'>KeyDB Default Configuration</a>"
|
||||||
label="Custom KeyDB Configuration" rows="10" id="keydbConf" />
|
label="Custom KeyDB Configuration" rows="10" id="keydbConf" canGate="update" :canResource="$database" />
|
||||||
</form>
|
</form>
|
||||||
<h3 class="pt-4">Advanced</h3>
|
<h3 class="pt-4">Advanced</h3>
|
||||||
<div class="w-64">
|
<div class="w-64">
|
||||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||||
instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" />
|
instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,14 +2,14 @@
|
|||||||
<form wire:submit="submit" class="flex flex-col gap-2">
|
<form wire:submit="submit" class="flex flex-col gap-2">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>General</h2>
|
<h2>General</h2>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit" canGate="update" :canResource="$database">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input label="Name" id="database.name" />
|
<x-forms.input label="Name" id="database.name" canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Description" id="database.description" />
|
<x-forms.input label="Description" id="database.description" canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Image" id="database.image" required
|
<x-forms.input label="Image" id="database.image" required canGate="update" :canResource="$database"
|
||||||
helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/_/mariadb'>https://hub.docker.com/_/mariadb</a>" />
|
helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/_/mariadb'>https://hub.docker.com/_/mariadb</a>" />
|
||||||
</div>
|
</div>
|
||||||
<div class="pt-2 dark:text-warning">If you change the values in the database, please sync it here, otherwise
|
<div class="pt-2 dark:text-warning">If you change the values in the database, please sync it here, otherwise
|
||||||
@@ -18,11 +18,14 @@
|
|||||||
@if ($database->started_at)
|
@if ($database->started_at)
|
||||||
<div class="flex xl:flex-row flex-col gap-2">
|
<div class="flex xl:flex-row flex-col gap-2">
|
||||||
<x-forms.input label="Root Password" id="database.mariadb_root_password" type="password" required
|
<x-forms.input label="Root Password" id="database.mariadb_root_password" type="password" required
|
||||||
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
|
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work."
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Normal User" id="database.mariadb_user" required
|
<x-forms.input label="Normal User" id="database.mariadb_user" required
|
||||||
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
|
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work."
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Normal User Password" id="database.mariadb_password" type="password" required
|
<x-forms.input label="Normal User Password" id="database.mariadb_password" type="password" required
|
||||||
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
|
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work."
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<x-forms.input label="Initial Database" id="database.mariadb_database"
|
<x-forms.input label="Initial Database" id="database.mariadb_database"
|
||||||
@@ -32,37 +35,39 @@
|
|||||||
@else
|
@else
|
||||||
<div class="flex xl:flex-row flex-col gap-2 pb-2">
|
<div class="flex xl:flex-row flex-col gap-2 pb-2">
|
||||||
<x-forms.input label="Root Password" id="database.mariadb_root_password" type="password"
|
<x-forms.input label="Root Password" id="database.mariadb_root_password" type="password"
|
||||||
helper="You can only change this in the database." />
|
helper="You can only change this in the database." canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Normal User" id="database.mariadb_user" required
|
<x-forms.input label="Normal User" id="database.mariadb_user" required
|
||||||
helper="You can only change this in the database." />
|
helper="You can only change this in the database." canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Normal User Password" id="database.mariadb_password" type="password" required
|
<x-forms.input label="Normal User Password" id="database.mariadb_password" type="password" required
|
||||||
helper="You can only change this in the database." />
|
helper="You can only change this in the database." canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<x-forms.input label="Initial Database" id="database.mariadb_database"
|
<x-forms.input label="Initial Database" id="database.mariadb_database"
|
||||||
placeholder="If empty, it will be the same as Username."
|
placeholder="If empty, it will be the same as Username."
|
||||||
helper="You can only change this in the database." />
|
helper="You can only change this in the database." canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<div class="pt-2">
|
<div class="pt-2">
|
||||||
<x-forms.input
|
<x-forms.input
|
||||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
||||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
||||||
id="database.custom_docker_run_options" label="Custom Docker Options" />
|
id="database.custom_docker_run_options" label="Custom Docker Options" canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<h3 class="py-2">Network</h3>
|
<h3 class="py-2">Network</h3>
|
||||||
<div class="flex items-end gap-2">
|
<div class="flex items-end gap-2">
|
||||||
<x-forms.input placeholder="3000:5432" id="database.ports_mappings" label="Ports Mappings"
|
<x-forms.input placeholder="3000:5432" id="database.ports_mappings" label="Ports Mappings"
|
||||||
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
|
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input label="MariaDB URL (internal)"
|
<x-forms.input label="MariaDB URL (internal)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
type="password" readonly wire:model="db_url" />
|
type="password" readonly wire:model="db_url" canGate="update" :canResource="$database" />
|
||||||
@if ($db_url_public)
|
@if ($db_url_public)
|
||||||
<x-forms.input label="MariaDB URL (public)"
|
<x-forms.input label="MariaDB URL (public)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
type="password" readonly wire:model="db_url_public" />
|
type="password" readonly wire:model="db_url_public" canGate="update" :canResource="$database" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -98,11 +103,13 @@
|
|||||||
<div class="w-64">
|
<div class="w-64">
|
||||||
@if (str($database->status)->contains('exited'))
|
@if (str($database->status)->contains('exited'))
|
||||||
<x-forms.checkbox id="database.enable_ssl" label="Enable SSL"
|
<x-forms.checkbox id="database.enable_ssl" label="Enable SSL"
|
||||||
wire:model.live="database.enable_ssl" instantSave="instantSaveSSL" />
|
wire:model.live="database.enable_ssl" instantSave="instantSaveSSL" canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
@else
|
@else
|
||||||
<x-forms.checkbox id="database.enable_ssl" label="Enable SSL"
|
<x-forms.checkbox id="database.enable_ssl" label="Enable SSL"
|
||||||
wire:model.live="database.enable_ssl" instantSave="instantSaveSSL" disabled
|
wire:model.live="database.enable_ssl" instantSave="instantSaveSSL" disabled
|
||||||
helper="Database should be stopped to change this settings." />
|
helper="Database should be stopped to change this settings." canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -127,16 +134,19 @@
|
|||||||
</x-slide-over>
|
</x-slide-over>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" />
|
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||||
id="database.public_port" label="Public Port" />
|
id="database.public_port" label="Public Port" canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.textarea label="Custom MariaDB Configuration" rows="10" id="database.mariadb_conf" />
|
<x-forms.textarea label="Custom MariaDB Configuration" rows="10" id="database.mariadb_conf"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
<h3 class="pt-4">Advanced</h3>
|
<h3 class="pt-4">Advanced</h3>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||||
instantSave="instantSaveAdvanced" id="database.is_log_drain_enabled" label="Drain Logs" />
|
instantSave="instantSaveAdvanced" id="database.is_log_drain_enabled" label="Drain Logs"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,14 +2,14 @@
|
|||||||
<form wire:submit="submit" class="flex flex-col gap-2">
|
<form wire:submit="submit" class="flex flex-col gap-2">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h2>General</h2>
|
<h2>General</h2>
|
||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit" canGate="update" :canResource="$database">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<x-forms.input label="Name" id="database.name" />
|
<x-forms.input label="Name" id="database.name" canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Description" id="database.description" />
|
<x-forms.input label="Description" id="database.description" canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Image" id="database.image" required
|
<x-forms.input label="Image" id="database.image" required canGate="update" :canResource="$database"
|
||||||
helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/_/mongo'>https://hub.docker.com/_/mongo</a>" />
|
helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/_/mongo'>https://hub.docker.com/_/mongo</a>" />
|
||||||
</div>
|
</div>
|
||||||
<div class="pt-2 dark:text-warning">If you change the values in the database, please sync it here, otherwise
|
<div class="pt-2 dark:text-warning">If you change the values in the database, please sync it here, otherwise
|
||||||
@@ -19,40 +19,44 @@
|
|||||||
<div class="flex xl:flex-row flex-col gap-2">
|
<div class="flex xl:flex-row flex-col gap-2">
|
||||||
<x-forms.input label="Initial Username" id="database.mongo_initdb_root_username"
|
<x-forms.input label="Initial Username" id="database.mongo_initdb_root_username"
|
||||||
placeholder="If empty: postgres"
|
placeholder="If empty: postgres"
|
||||||
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
|
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work."
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Initial Password" id="database.mongo_initdb_root_password" type="password"
|
<x-forms.input label="Initial Password" id="database.mongo_initdb_root_password" type="password"
|
||||||
required
|
required
|
||||||
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work." />
|
helper="If you change this in the database, please sync it here, otherwise automations (like backups) won't work."
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Initial Database" id="database.mongo_initdb_database"
|
<x-forms.input label="Initial Database" id="database.mongo_initdb_database"
|
||||||
placeholder="If empty, it will be the same as Username." readonly
|
placeholder="If empty, it will be the same as Username." readonly
|
||||||
helper="You can only change this in the database." />
|
helper="You can only change this in the database." canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<div class="flex xl:flex-row flex-col gap-2 pb-2">
|
<div class="flex xl:flex-row flex-col gap-2 pb-2">
|
||||||
<x-forms.input required label="Username" id="database.mongo_initdb_root_username"
|
<x-forms.input required label="Username" id="database.mongo_initdb_root_username"
|
||||||
placeholder="If empty: postgres" />
|
placeholder="If empty: postgres" canGate="update" :canResource="$database" />
|
||||||
<x-forms.input label="Password" id="database.mongo_initdb_root_password" type="password" required />
|
<x-forms.input label="Password" id="database.mongo_initdb_root_password" type="password" required
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
<x-forms.input required label="Database" id="database.mongo_initdb_database"
|
<x-forms.input required label="Database" id="database.mongo_initdb_database"
|
||||||
placeholder="If empty, it will be the same as Username." />
|
placeholder="If empty, it will be the same as Username." canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<x-forms.input
|
<x-forms.input
|
||||||
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
|
||||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
|
||||||
id="database.custom_docker_run_options" label="Custom Docker Options" />
|
id="database.custom_docker_run_options" label="Custom Docker Options" canGate="update" :canResource="$database" />
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<h3 class="py-2">Network</h3>
|
<h3 class="py-2">Network</h3>
|
||||||
<div class="flex items-end gap-2">
|
<div class="flex items-end gap-2">
|
||||||
<x-forms.input placeholder="3000:5432" id="database.ports_mappings" label="Ports Mappings"
|
<x-forms.input placeholder="3000:5432" id="database.ports_mappings" label="Ports Mappings"
|
||||||
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
|
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input label="Mongo URL (internal)"
|
<x-forms.input label="Mongo URL (internal)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
type="password" readonly wire:model="db_url" />
|
type="password" readonly wire:model="db_url" canGate="update" :canResource="$database" />
|
||||||
@if ($db_url_public)
|
@if ($db_url_public)
|
||||||
<x-forms.input label="Mongo URL (public)"
|
<x-forms.input label="Mongo URL (public)"
|
||||||
helper="If you change the user/password/port, this could be different. This is with the default values."
|
helper="If you change the user/password/port, this could be different. This is with the default values."
|
||||||
type="password" readonly wire:model="db_url_public" />
|
type="password" readonly wire:model="db_url_public" canGate="update" :canResource="$database" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -88,11 +92,13 @@
|
|||||||
<div class="w-64">
|
<div class="w-64">
|
||||||
@if (str($database->status)->contains('exited'))
|
@if (str($database->status)->contains('exited'))
|
||||||
<x-forms.checkbox id="database.enable_ssl" label="Enable SSL"
|
<x-forms.checkbox id="database.enable_ssl" label="Enable SSL"
|
||||||
wire:model.live="database.enable_ssl" instantSave="instantSaveSSL" />
|
wire:model.live="database.enable_ssl" instantSave="instantSaveSSL" canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
@else
|
@else
|
||||||
<x-forms.checkbox id="database.enable_ssl" label="Enable SSL"
|
<x-forms.checkbox id="database.enable_ssl" label="Enable SSL"
|
||||||
wire:model.live="database.enable_ssl" instantSave="instantSaveSSL" disabled
|
wire:model.live="database.enable_ssl" instantSave="instantSaveSSL" disabled
|
||||||
helper="Database should be stopped to change this settings." />
|
helper="Database should be stopped to change this settings." canGate="update"
|
||||||
|
:canResource="$database" />
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@if ($database->enable_ssl)
|
@if ($database->enable_ssl)
|
||||||
@@ -100,7 +106,8 @@
|
|||||||
@if (str($database->status)->contains('exited'))
|
@if (str($database->status)->contains('exited'))
|
||||||
<x-forms.select id="database.ssl_mode" label="SSL Mode" wire:model.live="database.ssl_mode"
|
<x-forms.select id="database.ssl_mode" label="SSL Mode" wire:model.live="database.ssl_mode"
|
||||||
instantSave="instantSaveSSL"
|
instantSave="instantSaveSSL"
|
||||||
helper="Choose the SSL verification mode for MongoDB connections">
|
helper="Choose the SSL verification mode for MongoDB connections" canGate="update"
|
||||||
|
:canResource="$database">
|
||||||
<option value="allow" title="Allow insecure connections">allow (insecure)</option>
|
<option value="allow" title="Allow insecure connections">allow (insecure)</option>
|
||||||
<option value="prefer" title="Prefer secure connections">prefer (secure)</option>
|
<option value="prefer" title="Prefer secure connections">prefer (secure)</option>
|
||||||
<option value="require" title="Require secure connections">require (secure)</option>
|
<option value="require" title="Require secure connections">require (secure)</option>
|
||||||
@@ -109,7 +116,8 @@
|
|||||||
</x-forms.select>
|
</x-forms.select>
|
||||||
@else
|
@else
|
||||||
<x-forms.select id="database.ssl_mode" label="SSL Mode" instantSave="instantSaveSSL"
|
<x-forms.select id="database.ssl_mode" label="SSL Mode" instantSave="instantSaveSSL"
|
||||||
disabled helper="Database should be stopped to change this settings.">
|
disabled helper="Database should be stopped to change this settings." canGate="update"
|
||||||
|
:canResource="$database">
|
||||||
<option value="allow" title="Allow insecure connections">allow (insecure)</option>
|
<option value="allow" title="Allow insecure connections">allow (insecure)</option>
|
||||||
<option value="prefer" title="Prefer secure connections">prefer (secure)</option>
|
<option value="prefer" title="Prefer secure connections">prefer (secure)</option>
|
||||||
<option value="require" title="Require secure connections">require (secure)</option>
|
<option value="require" title="Require secure connections">require (secure)</option>
|
||||||
@@ -140,16 +148,20 @@
|
|||||||
</x-slide-over>
|
</x-slide-over>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" />
|
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}"
|
||||||
id="database.public_port" label="Public Port" />
|
id="database.public_port" label="Public Port" canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
<x-forms.textarea label="Custom MongoDB Configuration" rows="10" id="database.mongo_conf" />
|
<x-forms.textarea label="Custom MongoDB Configuration" rows="10" id="database.mongo_conf"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
<h3 class="pt-4">Advanced</h3>
|
<h3 class="pt-4">Advanced</h3>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
|
||||||
instantSave="instantSaveAdvanced" id="database.is_log_drain_enabled" label="Drain Logs" />
|
instantSave="instantSaveAdvanced" id="database.is_log_drain_enabled" label="Drain Logs"
|
||||||
|
canGate="update" :canResource="$database" />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user