Compare commits

...

25 Commits

Author SHA1 Message Date
Andras Bacsai
46ed17c99e Merge pull request #1812 from coollabsio/next
v4.0.0-beta.236
2024-03-05 16:25:08 +01:00
Andras Bacsai
fadff798a7 Update server installation method 2024-03-05 16:23:46 +01:00
Andras Bacsai
81512bb3b7 Update server and version configurations 2024-03-05 15:47:43 +01:00
Andras Bacsai
3dd00dd91a Merge pull request #1811 from coollabsio/next
v4.0.0-beta.235
2024-03-05 10:29:41 +01:00
Andras Bacsai
fd97c5085b Update devDependencies in package.json 2024-03-05 10:26:32 +01:00
Andras Bacsai
fa6a249fb4 Update Docker installation for AlmaLinux 2024-03-05 10:24:02 +01:00
Andras Bacsai
0aa9b1735b Update currentState in selectExistingServer method 2024-03-05 10:07:28 +01:00
Andras Bacsai
6027bee3b8 Refactor repository selection logic in GithubPrivateRepository.php 2024-03-05 09:58:02 +01:00
Andras Bacsai
4d72787c83 fix: sort repositories by name 2024-03-05 09:40:38 +01:00
Andras Bacsai
c6740cfea0 fix: make sure to show some buttons 2024-03-05 09:37:35 +01:00
Andras Bacsai
9c1d585c43 Fix condition to return current team if user has teams 2024-03-05 09:22:38 +01:00
Andras Bacsai
863acf988e Fix selected repository ID assignment in loadRepositories method 2024-03-05 09:21:12 +01:00
Andras Bacsai
a6b3beafbb Fix issue with loading repositories in GithubPrivateRepository.php 2024-03-05 09:20:50 +01:00
Andras Bacsai
2ffc3f497b fix: should note delete personal teams 2024-03-05 09:19:15 +01:00
Andras Bacsai
f3a279be26 revert delayed jobs 2024-03-05 08:49:11 +01:00
Andras Bacsai
9ad6631747 Update version numbers 2024-03-04 14:32:17 +01:00
Andras Bacsai
0131f5e341 Merge pull request #1807 from coollabsio/next
v4.0.0-beta.234
2024-03-04 13:40:42 +01:00
Andras Bacsai
b5ab9a8da6 Add custom docker run options for application 2024-03-04 13:39:34 +01:00
Andras Bacsai
57fa2709da Add font preloading and DNS prefetching 2024-03-04 13:34:20 +01:00
Andras Bacsai
96c6a198d7 Fix base64 encoding for TOTP_VAULT_KEY 2024-03-04 12:50:56 +01:00
Andras Bacsai
d106d4bd4e Refactor generateEnvValue function to use base64 encoding for certain cases 2024-03-04 12:46:37 +01:00
Andras Bacsai
53cd3091f7 Add Directus service fields to extraFields method 2024-03-04 12:46:33 +01:00
Andras Bacsai
f1e7b870aa Add TOTP_VAULT_KEY environment variable to Plausible service 2024-03-04 12:30:32 +01:00
Andras Bacsai
99fe076b5a Add scheduled task for database cleanup if not in cloud environment 2024-03-04 12:17:33 +01:00
Andras Bacsai
65fcaa17d9 Update exception in PreventRequestsDuringMaintenance middleware and version numbers 2024-03-04 11:41:02 +01:00
27 changed files with 687 additions and 545 deletions

View File

@@ -47,6 +47,10 @@ class Kernel extends ConsoleKernel
$this->check_resources($schedule); $this->check_resources($schedule);
$this->pull_helper_image($schedule); $this->pull_helper_image($schedule);
$this->check_scheduled_tasks($schedule); $this->check_scheduled_tasks($schedule);
if (!isCloud()) {
$schedule->command('cleanup:database --yes')->daily();
}
} }
} }
private function pull_helper_image($schedule) private function pull_helper_image($schedule)
@@ -69,35 +73,42 @@ class Kernel extends ConsoleKernel
} }
foreach ($containerServers as $server) { foreach ($containerServers as $server) {
$schedule->job(new ContainerStatusJob($server))->everyMinute()->onOneServer(); $schedule->job(new ContainerStatusJob($server))->everyMinute()->onOneServer();
// $schedule
// ->call(function () use ($server) {
// $randomSeconds = rand(1, 40);
// $job = new ContainerStatusJob($server);
// $job->delay($randomSeconds);
// ray('dispatching container status job in ' . $randomSeconds . ' seconds');
// dispatch($job);
// })->name('container-status-' . $server->id)->everyMinute()->onOneServer();
if ($server->isLogDrainEnabled()) { if ($server->isLogDrainEnabled()) {
$schedule->job(new CheckLogDrainContainerJob($server))->everyMinute()->onOneServer(); $schedule->job(new CheckLogDrainContainerJob($server))->everyMinute()->onOneServer();
// $schedule
// ->call(function () use ($server) {
// $randomSeconds = rand(1, 40);
// $job = new CheckLogDrainContainerJob($server);
// $job->delay($randomSeconds);
// dispatch($job);
// })->name('log-drain-container-check-' . $server->id)->everyMinute()->onOneServer();
} }
} }
foreach ($servers as $server) { foreach ($servers as $server) {
$schedule->job(new ServerStatusJob($server))->everyMinute()->onOneServer(); $schedule->job(new ServerStatusJob($server))->everyMinute()->onOneServer();
// $schedule
// ->call(function () use ($server) {
// $randomSeconds = rand(1, 40);
// $job = new ServerStatusJob($server);
// $job->delay($randomSeconds);
// dispatch($job);
// })->name('server-status-job-' . $server->id)->everyMinute()->onOneServer();
} }
// Delayed Jobs
// foreach ($containerServers as $server) {
// $schedule
// ->call(function () use ($server) {
// $randomSeconds = rand(1, 40);
// $job = new ContainerStatusJob($server);
// $job->delay($randomSeconds);
// ray('dispatching container status job in ' . $randomSeconds . ' seconds');
// dispatch($job);
// })->name('container-status-' . $server->id)->everyMinute()->onOneServer();
// if ($server->isLogDrainEnabled()) {
// $schedule
// ->call(function () use ($server) {
// $randomSeconds = rand(1, 40);
// $job = new CheckLogDrainContainerJob($server);
// $job->delay($randomSeconds);
// dispatch($job);
// })->name('log-drain-container-check-' . $server->id)->everyMinute()->onOneServer();
// }
// }
// foreach ($servers as $server) {
// $schedule
// ->call(function () use ($server) {
// $randomSeconds = rand(1, 40);
// $job = new ServerStatusJob($server);
// $job->delay($randomSeconds);
// dispatch($job);
// })->name('server-status-job-' . $server->id)->everyMinute()->onOneServer();
// }
} }
private function instance_auto_update($schedule) private function instance_auto_update($schedule)
{ {

View File

@@ -19,11 +19,11 @@ class Server extends Controller
$server['is_usable'] = $server->settings->is_usable; $server['is_usable'] = $server->settings->is_usable;
return $server; return $server;
}); });
ray($servers);
return response()->json($servers); return response()->json($servers);
} }
public function server_by_uuid(Request $request) public function server_by_uuid(Request $request)
{ {
$with_resources = $request->query('resources');
$teamId = get_team_id_from_token(); $teamId = get_team_id_from_token();
if (is_null($teamId)) { if (is_null($teamId)) {
return response()->json(['error' => 'Invalid token.', 'docs' => 'https://coolify.io/docs/api/authentication'], 400); return response()->json(['error' => 'Invalid token.', 'docs' => 'https://coolify.io/docs/api/authentication'], 400);
@@ -32,23 +32,26 @@ class Server extends Controller
if (is_null($server)) { if (is_null($server)) {
return response()->json(['error' => 'Server not found.'], 404); return response()->json(['error' => 'Server not found.'], 404);
} }
$server->load(['settings']); if ($with_resources) {
$server['resources'] = $server->definedResources()->map(function ($resource) { $server['resources'] = $server->definedResources()->map(function ($resource) {
$payload = [ $payload = [
'id' => $resource->id, 'id' => $resource->id,
'uuid' => $resource->uuid, 'uuid' => $resource->uuid,
'name' => $resource->name, 'name' => $resource->name,
'type' => $resource->type(), 'type' => $resource->type(),
'created_at' => $resource->created_at, 'created_at' => $resource->created_at,
'updated_at' => $resource->updated_at, 'updated_at' => $resource->updated_at,
]; ];
if ($resource->type() === 'service') { if ($resource->type() === 'service') {
$payload['status'] = $resource->status(); $payload['status'] = $resource->status();
} else { } else {
$payload['status'] = $resource->status; $payload['status'] = $resource->status;
} }
return $payload; return $payload;
}); });
} else {
$server->load(['settings']);
}
return response()->json($server); return response()->json($server);
} }
} }

View File

@@ -12,6 +12,10 @@ class DecideWhatToDoWithUser
{ {
public function handle(Request $request, Closure $next): Response public function handle(Request $request, Closure $next): Response
{ {
if (auth()?->user()?->teams?->count() === 0) {
$currentTeam = auth()->user()?->recreate_personal_team();
refreshSession($currentTeam);
}
if(auth()?->user()?->currentTeam()){ if(auth()?->user()?->currentTeam()){
refreshSession(auth()->user()->currentTeam()); refreshSession(auth()->user()->currentTeam());
} }

View File

@@ -13,5 +13,6 @@ class PreventRequestsDuringMaintenance extends Middleware
*/ */
protected $except = [ protected $except = [
'webhooks/*', 'webhooks/*',
'/api/health'
]; ];
} }

View File

@@ -122,7 +122,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
} }
$this->selectedExistingPrivateKey = $this->createdServer->privateKey->id; $this->selectedExistingPrivateKey = $this->createdServer->privateKey->id;
$this->serverPublicKey = $this->createdServer->privateKey->publicKey(); $this->serverPublicKey = $this->createdServer->privateKey->publicKey();
$this->installServer(); $this->currentState = 'validate-server';
} }
public function getProxyType() public function getProxyType()
{ {
@@ -199,7 +199,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
} }
public function installServer() public function installServer()
{ {
$this->dispatch('validateServer', true); $this->dispatch('init', true);
} }
public function validateServer() public function validateServer()
{ {

View File

@@ -79,7 +79,10 @@ class GithubPrivateRepository extends Component
$this->loadRepositoryByPage(); $this->loadRepositoryByPage();
} }
} }
$this->selected_repository_id = $this->repositories[0]['id']; $this->repositories = $this->repositories->sortBy('name');
if ($this->repositories->count() > 0) {
$this->selected_repository_id = data_get($this->repositories->first(), 'id');
}
$this->current_step = 'repository'; $this->current_step = 'repository';
} }

View File

@@ -45,60 +45,64 @@ class Logs extends Component
} }
public function mount() public function mount()
{ {
$this->containers = collect(); try {
$this->servers = collect(); $this->containers = collect();
$this->parameters = get_route_parameters(); $this->servers = collect();
$this->query = request()->query(); $this->parameters = get_route_parameters();
if (data_get($this->parameters, 'application_uuid')) { $this->query = request()->query();
$this->type = 'application'; if (data_get($this->parameters, 'application_uuid')) {
$this->resource = Application::where('uuid', $this->parameters['application_uuid'])->firstOrFail(); $this->type = 'application';
$this->status = $this->resource->status; $this->resource = Application::where('uuid', $this->parameters['application_uuid'])->firstOrFail();
if ($this->resource->destination->server->isFunctional()) { $this->status = $this->resource->status;
$this->servers = $this->servers->push($this->resource->destination->server); if ($this->resource->destination->server->isFunctional()) {
} $this->servers = $this->servers->push($this->resource->destination->server);
foreach ($this->resource->additional_servers as $server) {
if ($server->isFunctional()) {
$this->servers = $this->servers->push($server);
} }
} foreach ($this->resource->additional_servers as $server) {
} else if (data_get($this->parameters, 'database_uuid')) { if ($server->isFunctional()) {
$this->type = 'database'; $this->servers = $this->servers->push($server);
$resource = StandalonePostgresql::where('uuid', $this->parameters['database_uuid'])->first(); }
if (is_null($resource)) { }
$resource = StandaloneRedis::where('uuid', $this->parameters['database_uuid'])->first(); } else if (data_get($this->parameters, 'database_uuid')) {
$this->type = 'database';
$resource = StandalonePostgresql::where('uuid', $this->parameters['database_uuid'])->first();
if (is_null($resource)) { if (is_null($resource)) {
$resource = StandaloneMongodb::where('uuid', $this->parameters['database_uuid'])->first(); $resource = StandaloneRedis::where('uuid', $this->parameters['database_uuid'])->first();
if (is_null($resource)) { if (is_null($resource)) {
$resource = StandaloneMysql::where('uuid', $this->parameters['database_uuid'])->first(); $resource = StandaloneMongodb::where('uuid', $this->parameters['database_uuid'])->first();
if (is_null($resource)) { if (is_null($resource)) {
$resource = StandaloneMariadb::where('uuid', $this->parameters['database_uuid'])->first(); $resource = StandaloneMysql::where('uuid', $this->parameters['database_uuid'])->first();
if (is_null($resource)) { if (is_null($resource)) {
abort(404); $resource = StandaloneMariadb::where('uuid', $this->parameters['database_uuid'])->first();
if (is_null($resource)) {
abort(404);
}
} }
} }
} }
} }
} $this->resource = $resource;
$this->resource = $resource; $this->status = $this->resource->status;
$this->status = $this->resource->status; if ($this->resource->destination->server->isFunctional()) {
if ($this->resource->destination->server->isFunctional()) { $this->servers = $this->servers->push($this->resource->destination->server);
$this->servers = $this->servers->push($this->resource->destination->server); }
} $this->container = $this->resource->uuid;
$this->container = $this->resource->uuid; $this->containers->push($this->container);
$this->containers->push($this->container); } else if (data_get($this->parameters, 'service_uuid')) {
} else if (data_get($this->parameters, 'service_uuid')) { $this->type = 'service';
$this->type = 'service'; $this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail();
$this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail(); $this->resource->applications()->get()->each(function ($application) {
$this->resource->applications()->get()->each(function ($application) { $this->containers->push(data_get($application, 'name') . '-' . data_get($this->resource, 'uuid'));
$this->containers->push(data_get($application, 'name') . '-' . data_get($this->resource, 'uuid')); });
}); $this->resource->databases()->get()->each(function ($database) {
$this->resource->databases()->get()->each(function ($database) { $this->containers->push(data_get($database, 'name') . '-' . data_get($this->resource, 'uuid'));
$this->containers->push(data_get($database, 'name') . '-' . data_get($this->resource, 'uuid')); });
});
if ($this->resource->server->isFunctional()) { if ($this->resource->server->isFunctional()) {
$this->servers = $this->servers->push($this->resource->server); $this->servers = $this->servers->push($this->resource->server);
}
} }
} catch (\Exception $e) {
return handleError($e, $this);
} }
} }

View File

@@ -102,6 +102,32 @@ class Service extends BaseModel
foreach ($applications as $application) { foreach ($applications as $application) {
$image = str($application->image)->before(':')->value(); $image = str($application->image)->before(':')->value();
switch ($image) { switch ($image) {
case str($image)?->contains('directus'):
$data = collect([]);
$admin_email = $this->environment_variables()->where('key', 'ADMIN_EMAIL')->first();
$admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first();
if ($admin_email) {
$data = $data->merge([
'Admin Email' => [
'key' => data_get($admin_email, 'key'),
'value' => data_get($admin_email, 'value'),
'rules' => 'required|email',
],
]);
}
if ($admin_password) {
$data = $data->merge([
'Admin Password' => [
'key' => data_get($admin_password, 'key'),
'value' => data_get($admin_password, 'value'),
'rules' => 'required',
'isPassword' => true,
],
]);
}
$fields->put('Directus', $data);
break;
case str($image)?->contains('kong'): case str($image)?->contains('kong'):
$data = collect([]); $data = collect([]);
$dashboard_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first(); $dashboard_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first();

View File

@@ -144,7 +144,6 @@ class Team extends Model implements SendsDiscord, SendsEmail
$sources = collect([]); $sources = collect([]);
$github_apps = $this->hasMany(GithubApp::class)->whereisPublic(false)->get(); $github_apps = $this->hasMany(GithubApp::class)->whereisPublic(false)->get();
$gitlab_apps = $this->hasMany(GitlabApp::class)->whereisPublic(false)->get(); $gitlab_apps = $this->hasMany(GitlabApp::class)->whereisPublic(false)->get();
// $bitbucket_apps = $this->hasMany(BitbucketApp::class)->get();
$sources = $sources->merge($github_apps)->merge($gitlab_apps); $sources = $sources->merge($github_apps)->merge($gitlab_apps);
return $sources; return $sources;
} }

View File

@@ -26,6 +26,7 @@ class TeamInvitation extends Model
return true; return true;
} else { } else {
$this->delete(); $this->delete();
return false;
} }
} }
} }

View File

@@ -50,6 +50,21 @@ class User extends Authenticatable implements SendsEmail
$user->teams()->attach($new_team, ['role' => 'owner']); $user->teams()->attach($new_team, ['role' => 'owner']);
}); });
} }
public function recreate_personal_team()
{
$team = [
'name' => $this->name . "'s Team",
'personal_team' => true,
'show_boarding' => true
];
if ($this->id === 0) {
$team['id'] = 0;
$team['name'] = 'Root Team';
}
$new_team = Team::create($team);
$this->teams()->attach($new_team, ['role' => 'owner']);
return $new_team;
}
public function createToken(string $name, array $abilities = ['*'], DateTimeInterface $expiresAt = null) public function createToken(string $name, array $abilities = ['*'], DateTimeInterface $expiresAt = null)
{ {
$plainTextToken = sprintf( $plainTextToken = sprintf(
@@ -143,7 +158,7 @@ class User extends Authenticatable implements SendsEmail
public function currentTeam() public function currentTeam()
{ {
return Cache::remember('team:' . auth()->user()->id, 3600, function () { return Cache::remember('team:' . auth()->user()->id, 3600, function () {
if (is_null(data_get(session('currentTeam'), 'id'))) { if (is_null(data_get(session('currentTeam'), 'id')) && auth()->user()->teams->count() > 0){
return auth()->user()->teams[0]; return auth()->user()->teams[0];
} }
return Team::find(session('currentTeam')->id); return Team::find(session('currentTeam')->id);

View File

@@ -8,14 +8,12 @@ use App\Actions\Fortify\UpdateUserPassword;
use App\Actions\Fortify\UpdateUserProfileInformation; use App\Actions\Fortify\UpdateUserProfileInformation;
use App\Models\InstanceSettings; use App\Models\InstanceSettings;
use App\Models\User; use App\Models\User;
use App\Models\Waitlist;
use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Contracts\RegisterResponse; use Laravel\Fortify\Contracts\RegisterResponse;
use Laravel\Fortify\Features;
use Laravel\Fortify\Fortify; use Laravel\Fortify\Fortify;
class FortifyServiceProvider extends ServiceProvider class FortifyServiceProvider extends ServiceProvider
@@ -76,7 +74,11 @@ class FortifyServiceProvider extends ServiceProvider
) { ) {
$user->updated_at = now(); $user->updated_at = now();
$user->save(); $user->save();
session(['currentTeam' => $user->currentTeam = $user->teams->firstWhere('personal_team', true)]); $user->currentTeam = $user->teams->firstWhere('personal_team', true);
if (!$user->currentTeam) {
$user->currentTeam = $user->recreate_personal_team();
}
session(['currentTeam' => $user->currentTeam]);
return $user; return $user;
} }
}); });

View File

@@ -1054,8 +1054,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
serviceLabels: $serviceLabels, serviceLabels: $serviceLabels,
is_gzip_enabled: $savedService->isGzipEnabled(), is_gzip_enabled: $savedService->isGzipEnabled(),
is_stripprefix_enabled: $savedService->isStripprefixEnabled(), is_stripprefix_enabled: $savedService->isStripprefixEnabled(),
service_name: $serviceName)); service_name: $serviceName
));
} }
} }
if ($resource->server->isLogDrainEnabled() && $savedService->isLogDrainEnabled()) { if ($resource->server->isLogDrainEnabled() && $savedService->isLogDrainEnabled()) {
@@ -1597,6 +1597,7 @@ function generateEnvValue(string $command, ?Service $service = null)
case 'PASSWORD_64': case 'PASSWORD_64':
$generatedValue = Str::password(length: 64, symbols: false); $generatedValue = Str::password(length: 64, symbols: false);
break; break;
// This is not base64, it's just a random string
case 'BASE64_64': case 'BASE64_64':
$generatedValue = Str::random(64); $generatedValue = Str::random(64);
break; break;
@@ -1604,8 +1605,20 @@ function generateEnvValue(string $command, ?Service $service = null)
$generatedValue = Str::random(128); $generatedValue = Str::random(128);
break; break;
case 'BASE64': case 'BASE64':
case 'BASE64_32':
$generatedValue = Str::random(32); $generatedValue = Str::random(32);
break; break;
// This is base64,
case 'REALBASE64_64':
$generatedValue = base64_encode(Str::random(64));
break;
case 'REALBASE64_128':
$generatedValue = base64_encode(Str::random(128));
break;
case 'REALBASE64':
case 'REALBASE64_32':
$generatedValue = base64_encode(Str::random(32));
break;
case 'USER': case 'USER':
$generatedValue = Str::random(16); $generatedValue = Str::random(16);
break; break;

566
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ return [
// The release version of your application // The release version of your application
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
'release' => '4.0.0-beta.233', 'release' => '4.0.0-beta.236',
// When left empty or `null` the Laravel environment will be used // When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'), 'environment' => config('app.env'),

View File

@@ -1,3 +1,3 @@
<?php <?php
return '4.0.0-beta.233'; return '4.0.0-beta.236';

212
package-lock.json generated
View File

@@ -13,15 +13,15 @@
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "4.5.1", "@vitejs/plugin-vue": "4.5.1",
"autoprefixer": "10.4.17", "autoprefixer": "10.4.18",
"axios": "1.6.7", "axios": "1.6.7",
"laravel-echo": "1.15.3", "laravel-echo": "1.16.0",
"laravel-vite-plugin": "0.8.1", "laravel-vite-plugin": "0.8.1",
"postcss": "8.4.35", "postcss": "8.4.35",
"pusher-js": "8.4.0-rc2", "pusher-js": "8.4.0-rc2",
"tailwindcss": "3.4.1", "tailwindcss": "3.4.1",
"vite": "4.5.2", "vite": "4.5.2",
"vue": "3.4.19" "vue": "3.4.21"
} }
}, },
"node_modules/@alloc/quick-lru": { "node_modules/@alloc/quick-lru": {
@@ -36,9 +36,9 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.23.9", "version": "7.24.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz",
"integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==",
"dev": true, "dev": true,
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@@ -524,77 +524,77 @@
} }
}, },
"node_modules/@vue/compiler-core": { "node_modules/@vue/compiler-core": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.21.tgz",
"integrity": "sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w==", "integrity": "sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/parser": "^7.23.9", "@babel/parser": "^7.23.9",
"@vue/shared": "3.4.19", "@vue/shared": "3.4.21",
"entities": "^4.5.0", "entities": "^4.5.0",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
"source-map-js": "^1.0.2" "source-map-js": "^1.0.2"
} }
}, },
"node_modules/@vue/compiler-core/node_modules/@vue/shared": { "node_modules/@vue/compiler-core/node_modules/@vue/shared": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==", "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==",
"dev": true "dev": true
}, },
"node_modules/@vue/compiler-dom": { "node_modules/@vue/compiler-dom": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.21.tgz",
"integrity": "sha512-vm6+cogWrshjqEHTzIDCp72DKtea8Ry/QVpQRYoyTIg9k7QZDX6D8+HGURjtmatfgM8xgCFtJJaOlCaRYRK3QA==", "integrity": "sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@vue/compiler-core": "3.4.19", "@vue/compiler-core": "3.4.21",
"@vue/shared": "3.4.19" "@vue/shared": "3.4.21"
} }
}, },
"node_modules/@vue/compiler-dom/node_modules/@vue/shared": { "node_modules/@vue/compiler-dom/node_modules/@vue/shared": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==", "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==",
"dev": true "dev": true
}, },
"node_modules/@vue/compiler-sfc": { "node_modules/@vue/compiler-sfc": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.21.tgz",
"integrity": "sha512-LQ3U4SN0DlvV0xhr1lUsgLCYlwQfUfetyPxkKYu7dkfvx7g3ojrGAkw0AERLOKYXuAGnqFsEuytkdcComei3Yg==", "integrity": "sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/parser": "^7.23.9", "@babel/parser": "^7.23.9",
"@vue/compiler-core": "3.4.19", "@vue/compiler-core": "3.4.21",
"@vue/compiler-dom": "3.4.19", "@vue/compiler-dom": "3.4.21",
"@vue/compiler-ssr": "3.4.19", "@vue/compiler-ssr": "3.4.21",
"@vue/shared": "3.4.19", "@vue/shared": "3.4.21",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
"magic-string": "^0.30.6", "magic-string": "^0.30.7",
"postcss": "^8.4.33", "postcss": "^8.4.35",
"source-map-js": "^1.0.2" "source-map-js": "^1.0.2"
} }
}, },
"node_modules/@vue/compiler-sfc/node_modules/@vue/shared": { "node_modules/@vue/compiler-sfc/node_modules/@vue/shared": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==", "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==",
"dev": true "dev": true
}, },
"node_modules/@vue/compiler-ssr": { "node_modules/@vue/compiler-ssr": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.21.tgz",
"integrity": "sha512-P0PLKC4+u4OMJ8sinba/5Z/iDT84uMRRlrWzadgLA69opCpI1gG4N55qDSC+dedwq2fJtzmGald05LWR5TFfLw==", "integrity": "sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@vue/compiler-dom": "3.4.19", "@vue/compiler-dom": "3.4.21",
"@vue/shared": "3.4.19" "@vue/shared": "3.4.21"
} }
}, },
"node_modules/@vue/compiler-ssr/node_modules/@vue/shared": { "node_modules/@vue/compiler-ssr/node_modules/@vue/shared": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==", "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==",
"dev": true "dev": true
}, },
"node_modules/@vue/reactivity": { "node_modules/@vue/reactivity": {
@@ -606,64 +606,64 @@
} }
}, },
"node_modules/@vue/runtime-core": { "node_modules/@vue/runtime-core": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.21.tgz",
"integrity": "sha512-/Z3tFwOrerJB/oyutmJGoYbuoadphDcJAd5jOuJE86THNZji9pYjZroQ2NFsZkTxOq0GJbb+s2kxTYToDiyZzw==", "integrity": "sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@vue/reactivity": "3.4.19", "@vue/reactivity": "3.4.21",
"@vue/shared": "3.4.19" "@vue/shared": "3.4.21"
} }
}, },
"node_modules/@vue/runtime-core/node_modules/@vue/reactivity": { "node_modules/@vue/runtime-core/node_modules/@vue/reactivity": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.21.tgz",
"integrity": "sha512-+VcwrQvLZgEclGZRHx4O2XhyEEcKaBi50WbxdVItEezUf4fqRh838Ix6amWTdX0CNb/b6t3Gkz3eOebfcSt+UA==", "integrity": "sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@vue/shared": "3.4.19" "@vue/shared": "3.4.21"
} }
}, },
"node_modules/@vue/runtime-core/node_modules/@vue/shared": { "node_modules/@vue/runtime-core/node_modules/@vue/shared": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==", "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==",
"dev": true "dev": true
}, },
"node_modules/@vue/runtime-dom": { "node_modules/@vue/runtime-dom": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.21.tgz",
"integrity": "sha512-IyZzIDqfNCF0OyZOauL+F4yzjMPN2rPd8nhqPP2N1lBn3kYqJpPHHru+83Rkvo2lHz5mW+rEeIMEF9qY3PB94g==", "integrity": "sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@vue/runtime-core": "3.4.19", "@vue/runtime-core": "3.4.21",
"@vue/shared": "3.4.19", "@vue/shared": "3.4.21",
"csstype": "^3.1.3" "csstype": "^3.1.3"
} }
}, },
"node_modules/@vue/runtime-dom/node_modules/@vue/shared": { "node_modules/@vue/runtime-dom/node_modules/@vue/shared": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==", "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==",
"dev": true "dev": true
}, },
"node_modules/@vue/server-renderer": { "node_modules/@vue/server-renderer": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.21.tgz",
"integrity": "sha512-eAj2p0c429RZyyhtMRnttjcSToch+kTWxFPHlzGMkR28ZbF1PDlTcmGmlDxccBuqNd9iOQ7xPRPAGgPVj+YpQw==", "integrity": "sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@vue/compiler-ssr": "3.4.19", "@vue/compiler-ssr": "3.4.21",
"@vue/shared": "3.4.19" "@vue/shared": "3.4.21"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "3.4.19" "vue": "3.4.21"
} }
}, },
"node_modules/@vue/server-renderer/node_modules/@vue/shared": { "node_modules/@vue/server-renderer/node_modules/@vue/shared": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==", "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==",
"dev": true "dev": true
}, },
"node_modules/@vue/shared": { "node_modules/@vue/shared": {
@@ -708,9 +708,9 @@
"dev": true "dev": true
}, },
"node_modules/autoprefixer": { "node_modules/autoprefixer": {
"version": "10.4.17", "version": "10.4.18",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz",
"integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==", "integrity": "sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -727,8 +727,8 @@
} }
], ],
"dependencies": { "dependencies": {
"browserslist": "^4.22.2", "browserslist": "^4.23.0",
"caniuse-lite": "^1.0.30001578", "caniuse-lite": "^1.0.30001591",
"fraction.js": "^4.3.7", "fraction.js": "^4.3.7",
"normalize-range": "^0.1.2", "normalize-range": "^0.1.2",
"picocolors": "^1.0.0", "picocolors": "^1.0.0",
@@ -789,9 +789,9 @@
} }
}, },
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.22.2", "version": "4.23.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
"integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -808,8 +808,8 @@
} }
], ],
"dependencies": { "dependencies": {
"caniuse-lite": "^1.0.30001565", "caniuse-lite": "^1.0.30001587",
"electron-to-chromium": "^1.4.601", "electron-to-chromium": "^1.4.668",
"node-releases": "^2.0.14", "node-releases": "^2.0.14",
"update-browserslist-db": "^1.0.13" "update-browserslist-db": "^1.0.13"
}, },
@@ -829,9 +829,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001580", "version": "1.0.30001594",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001580.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001594.tgz",
"integrity": "sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==", "integrity": "sha512-VblSX6nYqyJVs8DKFMldE2IVCJjZ225LW00ydtUWwh5hk9IfkTOffO6r8gJNsH0qqqeAF8KrbMYA2VEwTlGW5g==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -1014,9 +1014,9 @@
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.647", "version": "1.4.692",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.647.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.692.tgz",
"integrity": "sha512-Z/fTNGwc45WrYQhPaEcz5tAJuZZ8G7S/DBnhS6Kgp4BxnS40Z/HqlJ0hHg3Z79IGVzuVartIlTcjw/cQbPLgOw==", "integrity": "sha512-d5rZRka9n2Y3MkWRN74IoAsxR0HK3yaAt7T50e3iT9VZmCCQDT3geXUO5ZRMhDToa1pkCeQXuNo+0g+NfDOVPA==",
"dev": true "dev": true
}, },
"node_modules/entities": { "node_modules/entities": {
@@ -1069,9 +1069,9 @@
} }
}, },
"node_modules/escalade": { "node_modules/escalade": {
"version": "3.1.1", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=6" "node": ">=6"
@@ -1347,9 +1347,9 @@
} }
}, },
"node_modules/laravel-echo": { "node_modules/laravel-echo": {
"version": "1.15.3", "version": "1.16.0",
"resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-1.15.3.tgz", "resolved": "https://registry.npmjs.org/laravel-echo/-/laravel-echo-1.16.0.tgz",
"integrity": "sha512-SRXzccaat6w4qKgZ4/rjFKr3nJfVxB+ly4V0MEJNIF1/TpERNXepo3uk7NnOjBGsiV/np1fl2XitAzW4Sa1s/w==", "integrity": "sha512-BJGUa4tcKvYmTkzTmcBGMHiO2tq+k7Do5wPmLbRswWfzKwyfZEUR+J5iwBTPEfLLwNPZlA9Kjo6R/NV6pmyIpg==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=10" "node": ">=10"
@@ -1410,9 +1410,9 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
}, },
"node_modules/magic-string": { "node_modules/magic-string": {
"version": "0.30.7", "version": "0.30.8",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
"integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15" "@jridgewell/sourcemap-codec": "^1.4.15"
@@ -2106,16 +2106,16 @@
} }
}, },
"node_modules/vue": { "node_modules/vue": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.19.tgz", "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.21.tgz",
"integrity": "sha512-W/7Fc9KUkajFU8dBeDluM4sRGc/aa4YJnOYck8dkjgZoXtVsn3OeTGni66FV1l3+nvPA7VBFYtPioaGKUmEADw==", "integrity": "sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@vue/compiler-dom": "3.4.19", "@vue/compiler-dom": "3.4.21",
"@vue/compiler-sfc": "3.4.19", "@vue/compiler-sfc": "3.4.21",
"@vue/runtime-dom": "3.4.19", "@vue/runtime-dom": "3.4.21",
"@vue/server-renderer": "3.4.19", "@vue/server-renderer": "3.4.21",
"@vue/shared": "3.4.19" "@vue/shared": "3.4.21"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "*" "typescript": "*"
@@ -2127,9 +2127,9 @@
} }
}, },
"node_modules/vue/node_modules/@vue/shared": { "node_modules/vue/node_modules/@vue/shared": {
"version": "3.4.19", "version": "3.4.21",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw==", "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==",
"dev": true "dev": true
}, },
"node_modules/wrappy": { "node_modules/wrappy": {

View File

@@ -7,15 +7,15 @@
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "4.5.1", "@vitejs/plugin-vue": "4.5.1",
"autoprefixer": "10.4.17", "autoprefixer": "10.4.18",
"axios": "1.6.7", "axios": "1.6.7",
"laravel-echo": "1.15.3", "laravel-echo": "1.16.0",
"laravel-vite-plugin": "0.8.1", "laravel-vite-plugin": "0.8.1",
"postcss": "8.4.35", "postcss": "8.4.35",
"pusher-js": "8.4.0-rc2", "pusher-js": "8.4.0-rc2",
"tailwindcss": "3.4.1", "tailwindcss": "3.4.1",
"vite": "4.5.2", "vite": "4.5.2",
"vue": "3.4.19" "vue": "3.4.21"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/typography": "0.5.10", "@tailwindcss/typography": "0.5.10",

View File

@@ -5,27 +5,6 @@
</a> </a>
<x-services.links /> <x-services.links />
<div class="flex-1"></div> <div class="flex-1"></div>
@if (str($service->status())->contains('degraded'))
<button wire:click='deploy' onclick="startService.showModal()"
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<svg class="w-5 h-5 text-warning" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M19.933 13.041a8 8 0 1 1-9.925-8.788c3.899-1 7.935 1.007 9.425 4.747" />
<path d="M20 4v5h-5" />
</g>
</svg>
Restart Degraded Services
</button>
<button wire:click='stop' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<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
</button>
@endif
@if (str($service->status())->contains('running')) @if (str($service->status())->contains('running'))
<button wire:click='restart' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400"> <button wire:click='restart' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<svg class="w-5 h-5 text-warning" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <svg class="w-5 h-5 text-warning" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
@@ -45,8 +24,27 @@
</svg> </svg>
Stop Stop
</button> </button>
@endif @elseif (str($service->status())->contains('degraded'))
@if (str($service->status())->contains('exited')) <button wire:click='deploy' onclick="startService.showModal()"
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<svg class="w-5 h-5 text-warning" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M19.933 13.041a8 8 0 1 1-9.925-8.788c3.899-1 7.935 1.007 9.425 4.747" />
<path d="M20 4v5h-5" />
</g>
</svg>
Restart Degraded Services
</button>
<button wire:click='stop' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<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
</button>
@elseif (str($service->status())->contains('exited'))
<button wire:click='stop(true)' <button wire:click='stop(true)'
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400"> class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<svg class="w-5 h-5 " viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"> <svg class="w-5 h-5 " viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
@@ -65,6 +63,25 @@
</svg> </svg>
Deploy Deploy
</button> </button>
@else
<button wire:click='stop' class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<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
</button>
<button wire:click='deploy' onclick="startService.showModal()"
class="flex items-center gap-2 cursor-pointer hover:text-white text-neutral-400">
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 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 d="M7 4v16l13 -8z" />
</svg>
Deploy
</button>
@endif @endif
</div> </div>

View File

@@ -1,8 +1,8 @@
@if (Str::of($complexStatus)->startsWith('running')) @if (str($complexStatus)->contains('running'))
<x-status.running :status="$complexStatus" /> <x-status.running :status="$complexStatus" />
@elseif(Str::of($complexStatus)->startsWith('restarting')) @elseif(str($complexStatus)->contains('restarting'))
<x-status.restarting :status="$complexStatus" /> <x-status.restarting :status="$complexStatus" />
@elseif(Str::of($complexStatus)->startsWith('degraded')) @elseif(str($complexStatus)->contains('degraded'))
<x-status.degraded :status="$complexStatus" /> <x-status.degraded :status="$complexStatus" />
@else @else
<x-status.stopped :status="$complexStatus" /> <x-status.stopped :status="$complexStatus" />

View File

@@ -5,6 +5,9 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="preconnect" href="https://api.fonts.coollabs.io" crossorigin> <link rel="preconnect" href="https://api.fonts.coollabs.io" crossorigin>
<link rel="dns-prefetch" href="https://api.fonts.coollabs.io" />
<link rel="preload" href="https://api.fonts.coollabs.io/css2?family=Inter&display=swap" as="style" />
<link rel="preload" href="https://cdn.fonts.coollabs.io/inter/normal/400.woff2" as="style" />
<link href="https://api.fonts.coollabs.io/css2?family=Inter&display=swap" rel="stylesheet"> <link href="https://api.fonts.coollabs.io/css2?family=Inter&display=swap" rel="stylesheet">
<meta name="robots" content="noindex"> <meta name="robots" content="noindex">
<title>Coolify</title> <title>Coolify</title>

View File

@@ -209,7 +209,11 @@
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="application.custom_docker_run_options" label="Custom Docker Options" /> id="application.custom_docker_run_options" label="Custom Docker Options" />
@endif @endif
@else
<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='text-white underline' href='https://coolify.io/docs/custom-docker-options'>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"
id="application.custom_docker_run_options" label="Custom Docker Options" />
@endif @endif
@if ($application->build_pack === 'dockercompose') @if ($application->build_pack === 'dockercompose')
<x-forms.button wire:click="loadComposeFile">Reload Compose File</x-forms.button> <x-forms.button wire:click="loadComposeFile">Reload Compose File</x-forms.button>

View File

@@ -12,12 +12,23 @@
</div> </div>
@if (!$branch_found) @if (!$branch_found)
<div class="px-2 pt-4"> <div class="px-2 pt-4">
<p>Public repositories: <span class='text-helper'>https://...</span></p> <div class="flex gap-1">
<p>Private repositories: <span class='text-helper'>git@...</span></p> <div>Public:</div>
<p>Preselect branch: <span <div class='text-helper'>https://..</div>
class='text-helper'>https://github.com/coollabsio/coolify-examples/tree/static</span> to </div>
select 'static' branch.</p> <div class="flex gap-1">
</div> <div>Private:</div>
<div class='text-helper'>git@..</div>
</div>
<div class="flex gap-1">
<div>Preselect branch (eg: static):</div>
<div class='text-helper'>https://github.com/coollabsio/coolify-examples/tree/static</div>
</div>
<div>
For example application deployments, checkout <a class="text-white underline"
href="https://github.com/coollabsio/coolify-examples/" target="_blank">Coolify
Examples</a>.
</div>
@endif @endif
@if ($branch_found) @if ($branch_found)
@if ($rate_limit_remaining && $rate_limit_reset) @if ($rate_limit_remaining && $rate_limit_reset)

View File

@@ -20,10 +20,11 @@
<h4 class="pb-4">Delete Team</h4> <h4 class="pb-4">Delete Team</h4>
@if (session('currentTeam.id') === 0) @if (session('currentTeam.id') === 0)
<div>This is the default team. You can't delete it.</div> <div>This is the default team. You can't delete it.</div>
@elseif(auth()->user()->teams()->get()->count() === 1) @elseif(auth()->user()->teams()->get()->count() === 1 || auth()->user()->currentTeam()->personal_team)
<div>You can't delete your last team.</div> <div>You can't delete your last / personal team.</div>
@elseif(currentTeam()->subscription && currentTeam()->subscription?->lemon_status !== 'cancelled') @elseif(currentTeam()->subscription && currentTeam()->subscription?->lemon_status !== 'cancelled')
<div>Please cancel your subscription <a class="text-white underline" href="{{route('subscription.show')}}">here</a> before delete this team.</div> <div>Please cancel your subscription <a class="text-white underline"
href="{{ route('subscription.show') }}">here</a> before delete this team.</div>
@else @else
@if (currentTeam()->isEmpty()) @if (currentTeam()->isEmpty())
<div class="pb-4">This will delete your team. Beware! There is no coming back!</div> <div class="pb-4">This will delete your team. Beware! There is no coming back!</div>

View File

@@ -6,7 +6,7 @@ set -e # Exit immediately if a command exits with a non-zero status
#set -u # Treat unset variables as an error and exit #set -u # Treat unset variables as an error and exit
set -o pipefail # Cause a pipeline to return the status of the last command that exited with a non-zero status set -o pipefail # Cause a pipeline to return the status of the last command that exited with a non-zero status
VERSION="1.2.1" VERSION="1.2.2"
DOCKER_VERSION="24.0" DOCKER_VERSION="24.0"
CDN="https://cdn.coollabs.io/coolify" CDN="https://cdn.coollabs.io/coolify"
@@ -27,7 +27,7 @@ if [ $EUID != 0 ]; then
fi fi
case "$OS_TYPE" in case "$OS_TYPE" in
arch | ubuntu | debian | raspbian | centos | fedora | rhel | ol | rocky | sles | opensuse-leap | opensuse-tumbleweed) ;; arch | ubuntu | debian | raspbian | centos | fedora | rhel | ol | rocky | sles | opensuse-leap | opensuse-tumbleweed | almalinux) ;;
*) *)
echo "This script only supports Debian, Redhat, Arch Linux, or SLES based operating systems for now." echo "This script only supports Debian, Redhat, Arch Linux, or SLES based operating systems for now."
exit exit
@@ -64,7 +64,7 @@ ubuntu | debian | raspbian)
apt update -y >/dev/null 2>&1 apt update -y >/dev/null 2>&1
apt install -y curl wget git jq >/dev/null 2>&1 apt install -y curl wget git jq >/dev/null 2>&1
;; ;;
centos | fedora | rhel | ol | rocky) centos | fedora | rhel | ol | rocky | almalinux)
dnf install -y curl wget git jq >/dev/null 2>&1 dnf install -y curl wget git jq >/dev/null 2>&1
;; ;;
sles | opensuse-leap | opensuse-tumbleweed) sles | opensuse-leap | opensuse-tumbleweed)
@@ -123,33 +123,48 @@ if [ "$SSH_PERMIT_ROOT_LOGIN" != "true" ]; then
fi fi
if ! [ -x "$(command -v docker)" ]; then if ! [ -x "$(command -v docker)" ]; then
echo "Docker is not installed. Installing Docker." if [ "$OS_TYPE" == 'almalinux' ]; then
if [ "$OS_TYPE" = "arch" ]; then dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
pacman -Sy docker docker-compose --noconfirm dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
systemctl enable docker.service if ! [ -x "$(command -v docker)" ]; then
if [ -x "$(command -v docker)" ]; then echo "Docker could not be installed automatically. Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue."
echo "Docker installed successfully." exit 1
else
echo "Failed to install Docker with pacman. Try to install it manually."
echo "Please visit https://wiki.archlinux.org/title/docker for more information."
exit
fi fi
systemctl start docker
systemctl enable docker
else else
curl https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh set +e
if [ -x "$(command -v docker)" ]; then if ! [ -x "$(command -v docker)" ]; then
echo "Docker installed successfully." echo "Docker is not installed. Installing Docker."
else if [ "$OS_TYPE" = "arch" ]; then
echo "Docker installation failed with Rancher script. Trying with official script." pacman -Sy docker docker-compose --noconfirm
curl https://get.docker.com | sh -s -- --version ${DOCKER_VERSION} systemctl enable docker.service
if [ -x "$(command -v docker)" ]; then if [ -x "$(command -v docker)" ]; then
echo "Docker installed successfully." echo "Docker installed successfully."
else
echo "Failed to install Docker with pacman. Try to install it manually."
echo "Please visit https://wiki.archlinux.org/title/docker for more information."
exit
fi
else else
echo "Docker installation failed with official script." curl https://releases.rancher.com/install-docker/${DOCKER_VERSION}.sh | sh
echo "Maybe your OS is not supported?" if [ -x "$(command -v docker)" ]; then
echo "Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue." echo "Docker installed successfully."
exit 1 else
echo "Docker installation failed with Rancher script. Trying with official script."
curl https://get.docker.com | sh -s -- --version ${DOCKER_VERSION}
if [ -x "$(command -v docker)" ]; then
echo "Docker installed successfully."
else
echo "Docker installation failed with official script."
echo "Maybe your OS is not supported?"
echo "Please visit https://docs.docker.com/engine/install/ and install Docker manually to continue."
exit 1
fi
fi
fi fi
fi fi
set -e
fi fi
fi fi

View File

@@ -12,6 +12,7 @@ services:
- DATABASE_URL=postgres://postgres:$SERVICE_PASSWORD_POSTGRES@plausible_db/plausible - DATABASE_URL=postgres://postgres:$SERVICE_PASSWORD_POSTGRES@plausible_db/plausible
- BASE_URL=$SERVICE_FQDN_PLAUSIBLE - BASE_URL=$SERVICE_FQDN_PLAUSIBLE
- SECRET_KEY_BASE=$SERVICE_BASE64_64_PLAUSIBLE - SECRET_KEY_BASE=$SERVICE_BASE64_64_PLAUSIBLE
- TOTP_VAULT_KEY=$SERVICE_REALBASE64_TOTP
depends_on: depends_on:
- plausible_db - plausible_db
- plausible_events_db - plausible_events_db

View File

@@ -4,7 +4,7 @@
"version": "3.12.36" "version": "3.12.36"
}, },
"v4": { "v4": {
"version": "4.0.0-beta.233" "version": "4.0.0-beta.236"
} }
} }
} }