diff --git a/.dockerignore b/.dockerignore
index 090a80fbb..d6abd1451 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -20,3 +20,5 @@ yarn-error.log
/.npm
/.bash_history
/_data
+.rnd
+/.ssh
diff --git a/.env.development.example b/.env.development.example
index e73b8c1dd..43d3a10fd 100644
--- a/.env.development.example
+++ b/.env.development.example
@@ -14,3 +14,9 @@ APP_URL=http://localhost
APP_PORT=8000
DUSK_DRIVER_URL=http://selenium:4444
+
+## For Andras only
+# To purge cache
+BUNNY_API_KEY=
+# To upload assets
+BUNNY_STORAGE_API_KEY=
diff --git a/.env.secrets.example b/.env.secrets.example
deleted file mode 100644
index a114f6982..000000000
--- a/.env.secrets.example
+++ /dev/null
@@ -1,6 +0,0 @@
-# Secrets related to pushing to GH, Sync files to BunnyCDN etc. Only for maintainers.
-# Not related to Coolify, but to how we publish new versions.
-
-GITHUB_TOKEN=
-BUNNY_API_KEY=
-BUNNY_STORAGE_API_KEY=
diff --git a/.gitignore b/.gitignore
index e1b6b679e..d75e3c80f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,5 @@ _ide_helper.php
.gitignore
.phpstorm.meta.php
_ide_helper_models.php
+.rnd
+/.ssh
diff --git a/app/Actions/Database/StartPostgresql.php b/app/Actions/Database/StartPostgresql.php
index 1b5d22f44..ba427a93d 100644
--- a/app/Actions/Database/StartPostgresql.php
+++ b/app/Actions/Database/StartPostgresql.php
@@ -17,7 +17,7 @@ class StartPostgresql
public function __invoke(Server $server, StandalonePostgresql $database)
{
$this->database = $database;
- $container_name = generate_container_name($this->database->uuid);
+ $container_name = $this->database->uuid;
$this->configuration_dir = database_configuration_dir() . '/' . $container_name;
$this->commands = [
@@ -36,7 +36,7 @@ class StartPostgresql
'image' => $this->database->image,
'container_name' => $container_name,
'environment' => $environment_variables,
- 'restart' => 'always',
+ 'restart' => RESTART_MODE,
'networks' => [
$this->database->destination->network,
],
diff --git a/app/Actions/License/CheckResaleLicense.php b/app/Actions/License/CheckResaleLicense.php
index e7dcecdb6..54f97c834 100644
--- a/app/Actions/License/CheckResaleLicense.php
+++ b/app/Actions/License/CheckResaleLicense.php
@@ -14,14 +14,14 @@ class CheckResaleLicense
$settings->update([
'is_resale_license_active' => false,
]);
- if (is_dev()) {
+ if (isDev()) {
return;
}
if (!$settings->resale_license) {
return;
}
$base_url = config('coolify.license_url');
- if (is_dev()) {
+ if (isDev()) {
$base_url = 'http://host.docker.internal:8787';
}
$instance_id = config('app.id');
diff --git a/app/Actions/Server/InstallDocker.php b/app/Actions/Server/InstallDocker.php
index 7c58445dc..a26fadc05 100644
--- a/app/Actions/Server/InstallDocker.php
+++ b/app/Actions/Server/InstallDocker.php
@@ -12,29 +12,38 @@ class InstallDocker
{
$dockerVersion = '23.0';
$config = base64_encode('{ "live-restore": true }');
- $activity = remote_process([
- "echo ####### Installing Prerequisites...",
- "command -v jq >/dev/null || apt-get update",
- "command -v jq >/dev/null || apt install -y jq",
- "echo ####### Installing/updating Docker Engine...",
- "curl https://releases.rancher.com/install-docker/{$dockerVersion}.sh | sh",
- "echo ####### Configuring Docker Engine (merging existing configuration with the required)...",
- "test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json \"/etc/docker/daemon.json.original-`date +\"%Y%m%d-%H%M%S\"`\" || echo '{$config}' | base64 -d > /etc/docker/daemon.json",
- "echo '{$config}' | base64 -d > /etc/docker/daemon.json.coolify",
- "cat <<< $(jq . /etc/docker/daemon.json.coolify) > /etc/docker/daemon.json.coolify",
- "cat <<< $(jq -s '.[0] * .[1]' /etc/docker/daemon.json /etc/docker/daemon.json.coolify) > /etc/docker/daemon.json",
- "echo ####### Restarting Docker Engine...",
- "systemctl restart docker",
- "echo ####### Creating default network...",
- "docker network create --attachable coolify",
- "echo ####### Done!"
- ], $server);
- StandaloneDocker::create([
- 'name' => 'coolify',
- 'network' => 'coolify',
- 'server_id' => $server->id,
- 'team_id' => $team->id
- ]);
+ if (isDev()) {
+ $activity = remote_process([
+ "echo ####### Installing Prerequisites...",
+ "echo ####### Installing/updating Docker Engine...",
+ "echo ####### Configuring Docker Engine (merging existing configuration with the required)...",
+ "echo ####### Restarting Docker Engine...",
+ ], $server);
+ } else {
+ $activity = remote_process([
+ "echo ####### Installing Prerequisites...",
+ "command -v jq >/dev/null || apt-get update",
+ "command -v jq >/dev/null || apt install -y jq",
+ "echo ####### Installing/updating Docker Engine...",
+ "curl https://releases.rancher.com/install-docker/{$dockerVersion}.sh | sh",
+ "echo ####### Configuring Docker Engine (merging existing configuration with the required)...",
+ "test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json \"/etc/docker/daemon.json.original-`date +\"%Y%m%d-%H%M%S\"`\" || echo '{$config}' | base64 -d > /etc/docker/daemon.json",
+ "echo '{$config}' | base64 -d > /etc/docker/daemon.json.coolify",
+ "cat <<< $(jq . /etc/docker/daemon.json.coolify) > /etc/docker/daemon.json.coolify",
+ "cat <<< $(jq -s '.[0] * .[1]' /etc/docker/daemon.json /etc/docker/daemon.json.coolify) > /etc/docker/daemon.json",
+ "echo ####### Restarting Docker Engine...",
+ "systemctl restart docker",
+ "echo ####### Creating default network...",
+ "docker network create --attachable coolify",
+ "echo ####### Done!"
+ ], $server);
+ StandaloneDocker::create([
+ 'name' => 'coolify',
+ 'network' => 'coolify',
+ 'server_id' => $server->id,
+ ]);
+ }
+
return $activity;
}
diff --git a/app/Actions/Server/UpdateCoolify.php b/app/Actions/Server/UpdateCoolify.php
index 8f81852d8..0be05894f 100644
--- a/app/Actions/Server/UpdateCoolify.php
+++ b/app/Actions/Server/UpdateCoolify.php
@@ -17,9 +17,6 @@ class UpdateCoolify
$settings = InstanceSettings::get();
ray('Running InstanceAutoUpdateJob');
$localhost_name = 'localhost';
- if (is_dev()) {
- $localhost_name = 'testing-local-docker-container';
- }
$this->server = Server::where('name', $localhost_name)->firstOrFail();
$this->latest_version = get_latest_version_of_coolify();
$this->current_version = config('version');
@@ -32,27 +29,28 @@ class UpdateCoolify
$this->update();
} else {
if (!$settings->is_auto_update_enabled) {
- throw new \Exception('Auto update is disabled');
+ return 'Auto update is disabled';
}
if ($this->latest_version === $this->current_version) {
- throw new \Exception('Already on latest version');
+ return 'Already on latest version';
}
if (version_compare($this->latest_version, $this->current_version, '<')) {
- throw new \Exception('Latest version is lower than current version?!');
+ return 'Latest version is lower than current version?!';
}
$this->update();
}
- return;
- } catch (\Exception $e) {
+ send_internal_notification('InstanceAutoUpdateJob done to version: ' . $this->latest_version . ' from version: ' . $this->current_version);
+ } catch (\Exception $th) {
ray('InstanceAutoUpdateJob failed');
- ray($e->getMessage());
- return;
+ ray($th->getMessage());
+ send_internal_notification('InstanceAutoUpdateJob failed: ' . $th->getMessage());
+ throw $th;
}
}
private function update()
{
- if (is_dev()) {
+ if (isDev()) {
ray("Running update on local docker container. Updating to $this->latest_version");
remote_process([
"sleep 10"
diff --git a/app/Console/Commands/InviteFromWaitlist.php b/app/Console/Commands/InviteFromWaitlist.php
index 4adc60693..2794b7441 100644
--- a/app/Console/Commands/InviteFromWaitlist.php
+++ b/app/Console/Commands/InviteFromWaitlist.php
@@ -19,21 +19,29 @@ class InviteFromWaitlist extends Command
*
* @var string
*/
- protected $signature = 'app:invite-from-waitlist';
+ protected $signature = 'app:invite-from-waitlist {email?}';
/**
* The console command description.
*
* @var string
*/
- protected $description = 'Send invitation to the next user in the waitlist';
+ protected $description = 'Send invitation to the next user (or by email) in the waitlist';
/**
* Execute the console command.
*/
public function handle()
{
- $this->next_patient = Waitlist::orderBy('created_at', 'asc')->where('verified', true)->first();
+ if ($this->argument('email')) {
+ $this->next_patient = Waitlist::where('email', $this->argument('email'))->first();
+ if (!$this->next_patient) {
+ $this->error("{$this->argument('email')} not found in the waitlist.");
+ return;
+ }
+ } else {
+ $this->next_patient = Waitlist::orderBy('created_at', 'asc')->where('verified', true)->first();
+ }
if ($this->next_patient) {
$this->register_user();
$this->remove_from_waitlist();
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index 047f037d7..0dc99ba8a 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -18,7 +18,7 @@ class Kernel extends ConsoleKernel
protected function schedule(Schedule $schedule): void
{
// $schedule->call(fn() => $this->check_scheduled_backups($schedule))->everyTenSeconds();
- if (is_dev()) {
+ if (isDev()) {
$schedule->command('horizon:snapshot')->everyMinute();
$schedule->job(new ResourceStatusJob)->everyMinute();
$schedule->job(new ProxyCheckJob)->everyFiveMinutes();
diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index b08c07012..9d9dabab6 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -45,7 +45,7 @@ class Handler extends ExceptionHandler
{
$this->reportable(function (Throwable $e) {
$this->settings = InstanceSettings::get();
- if ($this->settings->do_not_track || is_dev()) {
+ if ($this->settings->do_not_track || isDev()) {
return;
}
Integration::captureUnhandledException($e);
diff --git a/app/Http/Controllers/ApplicationController.php b/app/Http/Controllers/ApplicationController.php
index 9b87492e4..aa2787de7 100644
--- a/app/Http/Controllers/ApplicationController.php
+++ b/app/Http/Controllers/ApplicationController.php
@@ -12,7 +12,7 @@ class ApplicationController extends Controller
public function configuration()
{
- $project = auth()->user()->currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
+ $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
if (!$project) {
return redirect()->route('dashboard');
}
@@ -29,7 +29,7 @@ class ApplicationController extends Controller
public function deployments()
{
- $project = auth()->user()->currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
+ $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
if (!$project) {
return redirect()->route('dashboard');
}
@@ -49,7 +49,7 @@ class ApplicationController extends Controller
{
$deploymentUuid = request()->route('deployment_uuid');
- $project = auth()->user()->currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
+ $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
if (!$project) {
return redirect()->route('dashboard');
}
diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php
index 84da5de2e..4fd997055 100644
--- a/app/Http/Controllers/Controller.php
+++ b/app/Http/Controllers/Controller.php
@@ -30,7 +30,7 @@ class Controller extends BaseController
if (!is_cloud()) {
abort(404);
}
- return view('subscription', [
+ return view('subscription.show', [
'settings' => InstanceSettings::get(),
]);
}
@@ -58,7 +58,6 @@ class Controller extends BaseController
$resources += $project->applications->count();
$resources += $project->postgresqls->count();
}
-
return view('dashboard', [
'servers' => $servers->count(),
'projects' => $projects->count(),
@@ -66,10 +65,17 @@ class Controller extends BaseController
's3s' => $s3s,
]);
}
+ public function boarding() {
+ if (currentTeam()->boarding || isDev()) {
+ return view('boarding');
+ } else {
+ return redirect()->route('dashboard');
+ }
+ }
public function settings()
{
- if (is_instance_admin()) {
+ if (isInstanceAdmin()) {
$settings = InstanceSettings::get();
$database = StandalonePostgresql::whereName('coolify-db')->first();
if ($database) {
@@ -89,7 +95,7 @@ class Controller extends BaseController
{
$invitations = [];
if (auth()->user()->isAdminFromSession()) {
- $invitations = TeamInvitation::whereTeamId(auth()->user()->currentTeam()->id)->get();
+ $invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get();
}
return view('team.show', [
'invitations' => $invitations,
@@ -116,7 +122,7 @@ class Controller extends BaseController
{
$invitations = [];
if (auth()->user()->isAdminFromSession()) {
- $invitations = TeamInvitation::whereTeamId(auth()->user()->currentTeam()->id)->get();
+ $invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get();
}
return view('team.members', [
'invitations' => $invitations,
diff --git a/app/Http/Controllers/DatabaseController.php b/app/Http/Controllers/DatabaseController.php
index bb6baf5ec..958d6d5ab 100644
--- a/app/Http/Controllers/DatabaseController.php
+++ b/app/Http/Controllers/DatabaseController.php
@@ -11,7 +11,7 @@ class DatabaseController extends Controller
public function configuration()
{
- $project = auth()->user()->currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
+ $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
if (!$project) {
return redirect()->route('dashboard');
}
@@ -29,7 +29,7 @@ class DatabaseController extends Controller
public function executions()
{
$backup_uuid = request()->route('backup_uuid');
- $project = auth()->user()->currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
+ $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
if (!$project) {
return redirect()->route('dashboard');
}
@@ -50,13 +50,13 @@ class DatabaseController extends Controller
'database' => $database,
'backup' => $backup,
'executions' => $executions,
- 's3s' => auth()->user()->currentTeam()->s3s,
+ 's3s' => currentTeam()->s3s,
]);
}
public function backups()
{
- $project = auth()->user()->currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
+ $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
if (!$project) {
return redirect()->route('dashboard');
}
@@ -70,7 +70,7 @@ class DatabaseController extends Controller
}
return view('project.database.backups.all', [
'database' => $database,
- 's3s' => auth()->user()->currentTeam()->s3s,
+ 's3s' => currentTeam()->s3s,
]);
}
}
diff --git a/app/Http/Controllers/MagicController.php b/app/Http/Controllers/MagicController.php
index 515bc14d1..d7635fda0 100644
--- a/app/Http/Controllers/MagicController.php
+++ b/app/Http/Controllers/MagicController.php
@@ -41,7 +41,7 @@ class MagicController extends Controller
{
$project = Project::firstOrCreate(
['name' => request()->query('name') ?? generate_random_name()],
- ['team_id' => auth()->user()->currentTeam()->id]
+ ['team_id' => currentTeam()->id]
);
return response()->json([
'project_uuid' => $project->uuid
@@ -68,7 +68,7 @@ class MagicController extends Controller
],
);
auth()->user()->teams()->attach($team, ['role' => 'admin']);
- session(['currentTeam' => $team]);
+ refreshSession();
return redirect(request()->header('Referer'));
}
}
diff --git a/app/Http/Controllers/ProjectController.php b/app/Http/Controllers/ProjectController.php
index 2ad941e92..476d54437 100644
--- a/app/Http/Controllers/ProjectController.php
+++ b/app/Http/Controllers/ProjectController.php
@@ -18,7 +18,7 @@ class ProjectController extends Controller
public function edit()
{
$projectUuid = request()->route('project_uuid');
- $teamId = auth()->user()->currentTeam()->id;
+ $teamId = currentTeam()->id;
$project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first();
if (!$project) {
return redirect()->route('dashboard');
@@ -29,7 +29,7 @@ class ProjectController extends Controller
public function show()
{
$projectUuid = request()->route('project_uuid');
- $teamId = auth()->user()->currentTeam()->id;
+ $teamId = currentTeam()->id;
$project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first();
if (!$project) {
@@ -44,7 +44,7 @@ class ProjectController extends Controller
$type = request()->query('type');
$destination_uuid = request()->query('destination');
- $project = auth()->user()->currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
+ $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
if (!$project) {
return redirect()->route('dashboard');
}
@@ -67,7 +67,7 @@ class ProjectController extends Controller
public function resources()
{
- $project = auth()->user()->currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
+ $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
if (!$project) {
return redirect()->route('dashboard');
}
diff --git a/app/Http/Controllers/ServerController.php b/app/Http/Controllers/ServerController.php
index e7f9feb57..54b8c7a8c 100644
--- a/app/Http/Controllers/ServerController.php
+++ b/app/Http/Controllers/ServerController.php
@@ -12,16 +12,16 @@ class ServerController extends Controller
public function new_server()
{
- if (!is_cloud() || is_instance_admin()) {
+ if (!is_cloud() || isInstanceAdmin()) {
return view('server.create', [
'limit_reached' => false,
'private_keys' => PrivateKey::ownedByCurrentTeam()->get(),
]);
}
- $servers = auth()->user()->currentTeam()->servers->count();
- $subscription = auth()->user()->currentTeam()?->subscription->type();
- $limits = config('constants.limits.server')[strtolower($subscription)];
- $limit_reached = true ?? $servers >= $limits[$subscription];
+ $servers = currentTeam()->servers->count();
+ $subscription = currentTeam()?->subscription->type();
+ $your_limit = config('constants.limits.server')[strtolower($subscription)];
+ $limit_reached = $servers >= $your_limit;
return view('server.create', [
'limit_reached' => $limit_reached,
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index 57b5edfec..eb93b6d35 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -39,6 +39,7 @@ class Kernel extends HttpKernel
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\CheckForcePasswordReset::class,
\App\Http\Middleware\SubscriptionValid::class,
+ \App\Http\Middleware\IsBoardingFlow::class,
],
diff --git a/app/Http/Livewire/Boarding.php b/app/Http/Livewire/Boarding.php
new file mode 100644
index 000000000..7ec11a3bc
--- /dev/null
+++ b/app/Http/Livewire/Boarding.php
@@ -0,0 +1,181 @@
+privateKeyName = generate_random_name();
+ $this->remoteServerName = generate_random_name();
+ if (isDev()) {
+ $this->privateKey = '-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk
+hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA
+AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV
+uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
+-----END OPENSSH PRIVATE KEY-----';
+ $this->privateKeyDescription = 'Created by Coolify';
+ $this->remoteServerDescription = 'Created by Coolify';
+ $this->remoteServerHost = 'coolify-testing-host';
+ }
+ }
+ public function restartBoarding()
+ {
+ if ($this->createdServer) {
+ $this->createdServer->delete();
+ }
+ if ($this->createdPrivateKey) {
+ $this->createdPrivateKey->delete();
+ }
+ return redirect()->route('boarding');
+ }
+ public function skipBoarding()
+ {
+ currentTeam()->update([
+ 'show_boarding' => false
+ ]);
+ refreshSession();
+ return redirect()->route('dashboard');
+ }
+ public function setServer(string $type)
+ {
+ if ($type === 'localhost') {
+ $this->createdServer = Server::find(0);
+ if (!$this->createdServer) {
+ return $this->emit('error', 'Localhost server is not found. Something went wrong during installation. Please try to reinstall or contact support.');
+ }
+ $this->currentState = 'select-proxy';
+ } elseif ($type === 'remote') {
+ $this->currentState = 'private-key';
+ }
+ }
+ public function setPrivateKey(string $type)
+ {
+ $this->privateKeyType = $type;
+ if ($type === 'create' && !isDev()) {
+ $this->createNewPrivateKey();
+ }
+ $this->currentState = 'create-private-key';
+ }
+ public function savePrivateKey()
+ {
+ $this->validate([
+ 'privateKeyName' => 'required',
+ 'privateKey' => 'required',
+ ]);
+ $this->currentState = 'create-server';
+ }
+ public function saveServer()
+ {
+ $this->validate([
+ 'remoteServerName' => 'required',
+ 'remoteServerHost' => 'required',
+ 'remoteServerPort' => 'required',
+ 'remoteServerUser' => 'required',
+ ]);
+ $this->privateKey = formatPrivateKey($this->privateKey);
+ $this->createdPrivateKey = PrivateKey::create([
+ 'name' => $this->privateKeyName,
+ 'description' => $this->privateKeyDescription,
+ 'private_key' => $this->privateKey,
+ 'team_id' => currentTeam()->id
+ ]);
+ $this->createdServer = Server::create([
+ 'name' => $this->remoteServerName,
+ 'ip' => $this->remoteServerHost,
+ 'port' => $this->remoteServerPort,
+ 'user' => $this->remoteServerUser,
+ 'description' => $this->remoteServerDescription,
+ 'private_key_id' => $this->createdPrivateKey->id,
+ 'team_id' => currentTeam()->id
+ ]);
+ try {
+ ['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->createdServer);
+ if (!$uptime) {
+ $this->createdServer->delete();
+ $this->createdPrivateKey->delete();
+ throw new \Exception('Server is not reachable.');
+ } else {
+ $this->createdServer->settings->update([
+ 'is_reachable' => true,
+ ]);
+ $this->emit('success', 'Server is reachable.');
+ }
+ if ($dockerVersion) {
+ $this->emit('error', 'Docker is not installed on the server.');
+ $this->currentState = 'install-docker';
+ return;
+ }
+ } catch (\Exception $e) {
+ return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this);
+ }
+ }
+ public function installDocker()
+ {
+ $activity = resolve(InstallDocker::class)($this->createdServer, currentTeam());
+ $this->emit('newMonitorActivity', $activity->id);
+ $this->currentState = 'select-proxy';
+ }
+ public function selectProxy(string|null $proxyType = null)
+ {
+ if (!$proxyType) {
+ return $this->currentState = 'create-project';
+ }
+ $this->createdServer->proxy->type = $proxyType;
+ $this->createdServer->proxy->status = 'exited';
+ $this->createdServer->save();
+ $this->currentState = 'create-project';
+ }
+ public function createNewProject()
+ {
+ $this->createdProject = Project::create([
+ 'name' => "My first project",
+ 'team_id' => currentTeam()->id
+ ]);
+ $this->currentState = 'create-resource';
+ }
+ public function showNewResource()
+ {
+ $this->skipBoarding();
+ return redirect()->route(
+ 'project.resources.new',
+ [
+ 'project_uuid' => $this->createdProject->uuid,
+ 'environment_name' => 'production',
+
+ ]
+ );
+ }
+ private function createNewPrivateKey()
+ {
+ $this->privateKeyName = generate_random_name();
+ $this->privateKeyDescription = 'Created by Coolify';
+ ['private' => $this->privateKey, 'public'=> $this->publicKey] = generateSSHKey();
+ }
+}
diff --git a/app/Http/Livewire/Destination/New/StandaloneDocker.php b/app/Http/Livewire/Destination/New/StandaloneDocker.php
index fa884ec37..1af7bc2df 100644
--- a/app/Http/Livewire/Destination/New/StandaloneDocker.php
+++ b/app/Http/Livewire/Destination/New/StandaloneDocker.php
@@ -60,20 +60,19 @@ class StandaloneDocker extends Component
$found = $this->server->standaloneDockers()->where('network', $this->network)->first();
if ($found) {
$this->createNetworkAndAttachToProxy();
- $this->addError('network', 'Network already added to this server.');
+ $this->emit('error', 'Network already added to this server.');
return;
} else {
$docker = ModelsStandaloneDocker::create([
'name' => $this->name,
'network' => $this->network,
'server_id' => $this->server_id,
- 'team_id' => auth()->user()->currentTeam()->id
]);
}
$this->createNetworkAndAttachToProxy();
return redirect()->route('destination.show', $docker->uuid);
} catch (\Exception $e) {
- return general_error_handler(err: $e);
+ return general_error_handler(err: $e, that: $this);
}
}
diff --git a/app/Http/Livewire/Notifications/DiscordSettings.php b/app/Http/Livewire/Notifications/DiscordSettings.php
index 03cac4753..f9de6d662 100644
--- a/app/Http/Livewire/Notifications/DiscordSettings.php
+++ b/app/Http/Livewire/Notifications/DiscordSettings.php
@@ -41,10 +41,9 @@ class DiscordSettings extends Component
public function saveModel()
{
- ray($this->model);
$this->model->save();
if (is_a($this->model, Team::class)) {
- session(['currentTeam' => $this->model]);
+ refreshSession();
}
$this->emit('success', 'Settings saved.');
}
diff --git a/app/Http/Livewire/Notifications/EmailSettings.php b/app/Http/Livewire/Notifications/EmailSettings.php
index eceb4e88b..a2887f989 100644
--- a/app/Http/Livewire/Notifications/EmailSettings.php
+++ b/app/Http/Livewire/Notifications/EmailSettings.php
@@ -59,7 +59,7 @@ class EmailSettings extends Component
{
$settings = InstanceSettings::get();
if ($settings->smtp_enabled) {
- $team = auth()->user()->currentTeam();
+ $team = currentTeam();
$team->update([
'smtp_enabled' => $settings->smtp_enabled,
'smtp_from_address' => $settings->smtp_from_address,
@@ -74,7 +74,7 @@ class EmailSettings extends Component
]);
$this->decrypt();
if (is_a($team, Team::class)) {
- session(['currentTeam' => $team]);
+ refreshSession();
}
$this->model = $team;
$this->emit('success', 'Settings saved.');
@@ -119,7 +119,7 @@ class EmailSettings extends Component
$this->model->save();
$this->decrypt();
if (is_a($this->model, Team::class)) {
- session(['currentTeam' => $this->model]);
+ refreshSession();
}
$this->emit('success', 'Settings saved.');
}
diff --git a/app/Http/Livewire/PrivateKey/Change.php b/app/Http/Livewire/PrivateKey/Change.php
index 91d42bd7a..bd9332ca2 100644
--- a/app/Http/Livewire/PrivateKey/Change.php
+++ b/app/Http/Livewire/PrivateKey/Change.php
@@ -26,7 +26,7 @@ class Change extends Component
try {
if ($this->private_key->isEmpty()) {
$this->private_key->delete();
- auth()->user()->currentTeam()->privateKeys = PrivateKey::where('team_id', auth()->user()->currentTeam()->id)->get();
+ currentTeam()->privateKeys = PrivateKey::where('team_id', currentTeam()->id)->get();
return redirect()->route('private-key.all');
}
$this->emit('error', 'This private key is in use and cannot be deleted. Please delete all servers, applications, and GitHub/GitLab apps that use this private key before deleting it.');
@@ -38,10 +38,7 @@ class Change extends Component
public function changePrivateKey()
{
try {
- $this->private_key->private_key = trim($this->private_key->private_key);
- if (!str_ends_with($this->private_key->private_key, "\n")) {
- $this->private_key->private_key .= "\n";
- }
+ $this->private_key->private_key = formatPrivateKey($this->private_key->private_key);
$this->private_key->save();
refresh_server_connection($this->private_key);
} catch (\Exception $e) {
diff --git a/app/Http/Livewire/PrivateKey/Create.php b/app/Http/Livewire/PrivateKey/Create.php
index 82218f4a5..d8d3cc41a 100644
--- a/app/Http/Livewire/PrivateKey/Create.php
+++ b/app/Http/Livewire/PrivateKey/Create.php
@@ -32,7 +32,7 @@ class Create extends Component
'name' => $this->name,
'description' => $this->description,
'private_key' => $this->value,
- 'team_id' => auth()->user()->currentTeam()->id
+ 'team_id' => currentTeam()->id
]);
if ($this->from === 'server') {
return redirect()->route('server.create');
diff --git a/app/Http/Livewire/Project/AddEmpty.php b/app/Http/Livewire/Project/AddEmpty.php
index 1024bc66f..fc20f9850 100644
--- a/app/Http/Livewire/Project/AddEmpty.php
+++ b/app/Http/Livewire/Project/AddEmpty.php
@@ -25,7 +25,7 @@ class AddEmpty extends Component
$project = Project::create([
'name' => $this->name,
'description' => $this->description,
- 'team_id' => auth()->user()->currentTeam()->id,
+ 'team_id' => currentTeam()->id,
]);
return redirect()->route('project.show', $project->uuid);
} catch (\Exception $e) {
diff --git a/app/Http/Livewire/Project/Application/General.php b/app/Http/Livewire/Project/Application/General.php
index 04be74140..80054d5db 100644
--- a/app/Http/Livewire/Project/Application/General.php
+++ b/app/Http/Livewire/Project/Application/General.php
@@ -136,15 +136,20 @@ class General extends Component
public function submit()
{
+ ray($this->application);
try {
$this->validate();
-
- $domains = Str::of($this->application->fqdn)->trim()->explode(',')->map(function ($domain) {
- return Str::of($domain)->trim()->lower();
- });
- $port = get_port_from_dockerfile($this->application->dockerfile);
- if ($port) {
- $this->application->ports_exposes = $port;
+ if (data_get($this->application,'fqdn')) {
+ $domains = Str::of($this->application->fqdn)->trim()->explode(',')->map(function ($domain) {
+ return Str::of($domain)->trim()->lower();
+ });
+ $this->application->fqdn = $domains->implode(',');
+ }
+ if ($this->application->dockerfile) {
+ $port = get_port_from_dockerfile($this->application->dockerfile);
+ if ($port) {
+ $this->application->ports_exposes = $port;
+ }
}
if ($this->application->base_directory && $this->application->base_directory !== '/') {
$this->application->base_directory = rtrim($this->application->base_directory, '/');
@@ -152,7 +157,6 @@ class General extends Component
if ($this->application->publish_directory && $this->application->publish_directory !== '/') {
$this->application->publish_directory = rtrim($this->application->publish_directory, '/');
}
- $this->application->fqdn = data_get($domains->implode(','), '', null);
$this->application->save();
$this->emit('success', 'Application settings updated!');
} catch (\Exception $e) {
diff --git a/app/Http/Livewire/Project/Application/Heading.php b/app/Http/Livewire/Project/Application/Heading.php
index fdbe5f71e..5b9560007 100644
--- a/app/Http/Livewire/Project/Application/Heading.php
+++ b/app/Http/Livewire/Project/Application/Heading.php
@@ -2,7 +2,7 @@
namespace App\Http\Livewire\Project\Application;
-use App\Jobs\ContainerStatusJob;
+use App\Jobs\ApplicationContainerStatusJob;
use App\Models\Application;
use App\Notifications\Application\StatusChanged;
use Livewire\Component;
@@ -22,9 +22,8 @@ class Heading extends Component
public function check_status()
{
- dispatch_sync(new ContainerStatusJob(
- resource: $this->application,
- container_name: generate_container_name($this->application->uuid),
+ dispatch_sync(new ApplicationContainerStatusJob(
+ application: $this->application,
));
$this->application->refresh();
}
@@ -58,12 +57,21 @@ class Heading extends Component
public function stop()
{
- remote_process(
- ["docker rm -f {$this->application->uuid}"],
- $this->application->destination->server
- );
- $this->application->status = 'stopped';
- $this->application->save();
- $this->application->environment->project->team->notify(new StatusChanged($this->application));
+ $containers = getCurrentApplicationContainerStatus($this->application->destination->server, $this->application->id);
+ if ($containers->count() === 0) {
+ return;
+ }
+ foreach ($containers as $container) {
+ $containerName = data_get($container, 'Names');
+ if ($containerName) {
+ remote_process(
+ ["docker rm -f {$containerName}"],
+ $this->application->destination->server
+ );
+ $this->application->status = 'stopped';
+ $this->application->save();
+ // $this->application->environment->project->team->notify(new StatusChanged($this->application));
+ }
+ }
}
}
diff --git a/app/Http/Livewire/Project/Application/Previews.php b/app/Http/Livewire/Project/Application/Previews.php
index b3582fbef..ad3ca5ad9 100644
--- a/app/Http/Livewire/Project/Application/Previews.php
+++ b/app/Http/Livewire/Project/Application/Previews.php
@@ -2,7 +2,7 @@
namespace App\Http\Livewire\Project\Application;
-use App\Jobs\ContainerStatusJob;
+use App\Jobs\ApplicationContainerStatusJob;
use App\Models\Application;
use App\Models\ApplicationPreview;
use Illuminate\Support\Collection;
@@ -25,10 +25,9 @@ class Previews extends Component
public function loadStatus($pull_request_id)
{
- dispatch(new ContainerStatusJob(
- resource: $this->application,
- container_name: generate_container_name($this->application->uuid, $pull_request_id),
- pull_request_id: $pull_request_id
+ dispatch(new ApplicationContainerStatusJob(
+ application: $this->application,
+ pullRequestId: $pull_request_id
));
}
@@ -82,7 +81,7 @@ class Previews extends Component
public function stop(int $pull_request_id)
{
try {
- $container_name = generate_container_name($this->application->uuid, $pull_request_id);
+ $container_name = generateApplicationContainerName($this->application->uuid, $pull_request_id);
ray('Stopping container: ' . $container_name);
instant_remote_process(["docker rm -f $container_name"], $this->application->destination->server, throwError: false);
diff --git a/app/Http/Livewire/Project/Application/Source.php b/app/Http/Livewire/Project/Application/Source.php
index 5affe9e45..801d533aa 100644
--- a/app/Http/Livewire/Project/Application/Source.php
+++ b/app/Http/Livewire/Project/Application/Source.php
@@ -29,7 +29,7 @@ class Source extends Component
private function get_private_keys()
{
- $this->private_keys = PrivateKey::whereTeamId(auth()->user()->currentTeam()->id)->get()->reject(function ($key) {
+ $this->private_keys = PrivateKey::whereTeamId(currentTeam()->id)->get()->reject(function ($key) {
return $key->id == $this->application->private_key_id;
});
}
diff --git a/app/Http/Livewire/Project/Database/CreateScheduledBackup.php b/app/Http/Livewire/Project/Database/CreateScheduledBackup.php
index e3ea97735..9297f65f6 100644
--- a/app/Http/Livewire/Project/Database/CreateScheduledBackup.php
+++ b/app/Http/Livewire/Project/Database/CreateScheduledBackup.php
@@ -39,7 +39,7 @@ class CreateScheduledBackup extends Component
's3_storage_id' => $this->s3_storage_id,
'database_id' => $this->database->id,
'database_type' => $this->database->getMorphClass(),
- 'team_id' => auth()->user()->currentTeam()->id,
+ 'team_id' => currentTeam()->id,
]);
$this->emit('refreshScheduledBackups');
} catch (\Exception $e) {
diff --git a/app/Http/Livewire/Project/Database/Heading.php b/app/Http/Livewire/Project/Database/Heading.php
index 59f4955a6..347c439a6 100644
--- a/app/Http/Livewire/Project/Database/Heading.php
+++ b/app/Http/Livewire/Project/Database/Heading.php
@@ -3,7 +3,7 @@
namespace App\Http\Livewire\Project\Database;
use App\Actions\Database\StartPostgresql;
-use App\Jobs\ContainerStatusJob;
+use App\Jobs\DatabaseContainerStatusJob;
use App\Notifications\Application\StatusChanged;
use Livewire\Component;
@@ -25,9 +25,8 @@ class Heading extends Component
public function check_status()
{
- dispatch_sync(new ContainerStatusJob(
- resource: $this->database,
- container_name: generate_container_name($this->database->uuid),
+ dispatch_sync(new DatabaseContainerStatusJob(
+ database: $this->database,
));
$this->database->refresh();
}
@@ -45,7 +44,7 @@ class Heading extends Component
);
$this->database->status = 'stopped';
$this->database->save();
- $this->database->environment->project->team->notify(new StatusChanged($this->database));
+ // $this->database->environment->project->team->notify(new StatusChanged($this->database));
}
public function start()
diff --git a/app/Http/Livewire/Project/New/EmptyProject.php b/app/Http/Livewire/Project/New/EmptyProject.php
index e77ab983e..9dba4338b 100644
--- a/app/Http/Livewire/Project/New/EmptyProject.php
+++ b/app/Http/Livewire/Project/New/EmptyProject.php
@@ -11,7 +11,7 @@ class EmptyProject extends Component
{
$project = Project::create([
'name' => generate_random_name(),
- 'team_id' => auth()->user()->currentTeam()->id,
+ 'team_id' => currentTeam()->id,
]);
return redirect()->route('project.show', ['project_uuid' => $project->uuid, 'environment_name' => 'production']);
}
diff --git a/app/Http/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php b/app/Http/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php
index a1f275f32..d18fe2541 100644
--- a/app/Http/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php
+++ b/app/Http/Livewire/Project/New/GithubPrivateRepositoryDeployKey.php
@@ -43,19 +43,19 @@ class GithubPrivateRepositoryDeployKey extends Component
'publish_directory' => 'Publish directory',
];
private object $repository_url_parsed;
- private GithubApp|GitlabApp $git_source;
+ private GithubApp|GitlabApp|null $git_source = null;
private string $git_host;
private string $git_repository;
private string $git_branch;
public function mount()
{
- if (is_dev()) {
+ if (isDev()) {
$this->repository_url = 'https://github.com/coollabsio/coolify-examples';
}
$this->parameters = get_route_parameters();
$this->query = request()->query();
- $this->private_keys = PrivateKey::where('team_id', auth()->user()->currentTeam()->id)->where('id', '!=', 0)->get();
+ $this->private_keys = PrivateKey::where('team_id', currentTeam()->id)->where('id', '!=', 0)->get();
}
public function instantSave()
diff --git a/app/Http/Livewire/Project/New/PublicGitRepository.php b/app/Http/Livewire/Project/New/PublicGitRepository.php
index 7fd15cd34..6229a7fc6 100644
--- a/app/Http/Livewire/Project/New/PublicGitRepository.php
+++ b/app/Http/Livewire/Project/New/PublicGitRepository.php
@@ -45,7 +45,7 @@ class PublicGitRepository extends Component
public function mount()
{
- if (is_dev()) {
+ if (isDev()) {
$this->repository_url = 'https://github.com/coollabsio/coolify-examples';
$this->port = 3000;
}
diff --git a/app/Http/Livewire/Project/New/Select.php b/app/Http/Livewire/Project/New/Select.php
index f95599154..b3109ef8c 100644
--- a/app/Http/Livewire/Project/New/Select.php
+++ b/app/Http/Livewire/Project/New/Select.php
@@ -3,6 +3,7 @@
namespace App\Http\Livewire\Project\New;
use App\Models\Server;
+use Countable;
use Livewire\Component;
class Select extends Component
@@ -11,7 +12,7 @@ class Select extends Component
public string $type;
public string $server_id;
public string $destination_uuid;
- public $servers = [];
+ public Countable|array|Server $servers;
public $destinations = [];
public array $parameters;
@@ -23,6 +24,13 @@ class Select extends Component
public function set_type(string $type)
{
$this->type = $type;
+ if (count($this->servers) === 1) {
+ $server = $this->servers->first();
+ $this->set_server($server);
+ if (count($server->destinations()) === 1) {
+ $this->set_destination($server->destinations()->first()->uuid);
+ }
+ }
$this->current_step = 'servers';
}
@@ -46,6 +54,6 @@ class Select extends Component
public function load_servers()
{
- $this->servers = Server::ownedByCurrentTeam()->get();
+ $this->servers = Server::isUsable()->get();
}
}
diff --git a/app/Http/Livewire/Project/New/SimpleDockerfile.php b/app/Http/Livewire/Project/New/SimpleDockerfile.php
index bbc82fcd5..e755c8c0f 100644
--- a/app/Http/Livewire/Project/New/SimpleDockerfile.php
+++ b/app/Http/Livewire/Project/New/SimpleDockerfile.php
@@ -19,7 +19,7 @@ class SimpleDockerfile extends Component
{
$this->parameters = get_route_parameters();
$this->query = request()->query();
- if (is_dev()) {
+ if (isDev()) {
$this->dockerfile = 'FROM nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
@@ -59,6 +59,10 @@ CMD ["nginx", "-g", "daemon off;"]
'source_id' => 0,
'source_type' => GithubApp::class
]);
+ $application->update([
+ 'name' => 'dockerfile-' . $application->id
+ ]);
+
redirect()->route('project.application.configuration', [
'application_uuid' => $application->uuid,
'environment_name' => $environment->name,
diff --git a/app/Http/Livewire/Server/Form.php b/app/Http/Livewire/Server/Form.php
index 4dcebc101..290c06dd7 100644
--- a/app/Http/Livewire/Server/Form.php
+++ b/app/Http/Livewire/Server/Form.php
@@ -42,7 +42,7 @@ class Form extends Component
public function installDocker()
{
- $activity = resolve(InstallDocker::class)($this->server, auth()->user()->currentTeam());
+ $activity = resolve(InstallDocker::class)($this->server, currentTeam());
$this->emit('newMonitorActivity', $activity->id);
}
diff --git a/app/Http/Livewire/Server/New/ByIp.php b/app/Http/Livewire/Server/New/ByIp.php
index c4f340413..e6813a55f 100644
--- a/app/Http/Livewire/Server/New/ByIp.php
+++ b/app/Http/Livewire/Server/New/ByIp.php
@@ -65,7 +65,7 @@ class ByIp extends Component
'ip' => $this->ip,
'user' => $this->user,
'port' => $this->port,
- 'team_id' => auth()->user()->currentTeam()->id,
+ 'team_id' => currentTeam()->id,
'private_key_id' => $this->private_key_id,
]);
$server->settings->is_part_of_swarm = $this->is_part_of_swarm;
diff --git a/app/Http/Livewire/Server/Proxy.php b/app/Http/Livewire/Server/Proxy.php
index 1f51d1b1c..944b5e898 100644
--- a/app/Http/Livewire/Server/Proxy.php
+++ b/app/Http/Livewire/Server/Proxy.php
@@ -35,7 +35,7 @@ class Proxy extends Component
$this->emit('proxyStatusUpdated');
}
- public function select_proxy(string $proxy_type)
+ public function select_proxy(ProxyTypes $proxy_type)
{
$this->server->proxy->type = $proxy_type;
$this->server->proxy->status = 'exited';
diff --git a/app/Http/Livewire/Server/Proxy/Deploy.php b/app/Http/Livewire/Server/Proxy/Deploy.php
index 9ec3898f1..f78763479 100644
--- a/app/Http/Livewire/Server/Proxy/Deploy.php
+++ b/app/Http/Livewire/Server/Proxy/Deploy.php
@@ -17,7 +17,7 @@ class Deploy extends Component
$this->server->proxy->last_applied_settings &&
$this->server->proxy->last_saved_settings !== $this->server->proxy->last_applied_settings
) {
- $this->emit('saveConfiguration', $server);
+ $this->emit('saveConfiguration', $this->server);
}
$activity = resolve(StartProxy::class)($this->server);
$this->emit('newMonitorActivity', $activity->id);
diff --git a/app/Http/Livewire/Settings/Backup.php b/app/Http/Livewire/Settings/Backup.php
index fcb105fd4..263db027d 100644
--- a/app/Http/Livewire/Settings/Backup.php
+++ b/app/Http/Livewire/Settings/Backup.php
@@ -65,7 +65,7 @@ class Backup extends Component
'frequency' => '0 0 * * *',
'database_id' => $this->database->id,
'database_type' => 'App\Models\StandalonePostgresql',
- 'team_id' => auth()->user()->currentTeam()->id,
+ 'team_id' => currentTeam()->id,
]);
$this->database->refresh();
$this->backup->refresh();
diff --git a/app/Http/Livewire/Source/Github/Create.php b/app/Http/Livewire/Source/Github/Create.php
index 862964c45..4d6f8b26b 100644
--- a/app/Http/Livewire/Source/Github/Create.php
+++ b/app/Http/Livewire/Source/Github/Create.php
@@ -40,7 +40,7 @@ class Create extends Component
'custom_user' => $this->custom_user,
'custom_port' => $this->custom_port,
'is_system_wide' => $this->is_system_wide,
- 'team_id' => auth()->user()->currentTeam()->id,
+ 'team_id' => currentTeam()->id,
]);
redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]);
} catch (\Exception $e) {
diff --git a/app/Http/Livewire/Subscription/Actions.php b/app/Http/Livewire/Subscription/Actions.php
index 588a0521c..7de0ec728 100644
--- a/app/Http/Livewire/Subscription/Actions.php
+++ b/app/Http/Livewire/Subscription/Actions.php
@@ -10,14 +10,14 @@ class Actions extends Component
public function cancel()
{
try {
- $subscription_id = auth()->user()->currentTeam()->subscription->lemon_subscription_id;
+ $subscription_id = currentTeam()->subscription->lemon_subscription_id;
if (!$subscription_id) {
throw new \Exception('No subscription found');
}
$response = Http::withHeaders([
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
- 'Authorization' => 'Bearer ' . config('coolify.lemon_squeezy_api_key'),
+ 'Authorization' => 'Bearer ' . config('subscription.lemon_squeezy_api_key'),
])->delete('https://api.lemonsqueezy.com/v1/subscriptions/' . $subscription_id);
$json = $response->json();
if ($response->failed()) {
@@ -37,14 +37,14 @@ class Actions extends Component
public function resume()
{
try {
- $subscription_id = auth()->user()->currentTeam()->subscription->lemon_subscription_id;
+ $subscription_id = currentTeam()->subscription->lemon_subscription_id;
if (!$subscription_id) {
throw new \Exception('No subscription found');
}
$response = Http::withHeaders([
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
- 'Authorization' => 'Bearer ' . config('coolify.lemon_squeezy_api_key'),
+ 'Authorization' => 'Bearer ' . config('subscription.lemon_squeezy_api_key'),
])->patch('https://api.lemonsqueezy.com/v1/subscriptions/' . $subscription_id, [
'data' => [
'type' => 'subscriptions',
@@ -69,4 +69,8 @@ class Actions extends Component
return general_error_handler($e, $this);
}
}
+ public function stripeCustomerPortal() {
+ $session = getStripeCustomerPortalSession(currentTeam());
+ redirect($session->url);
+ }
}
diff --git a/app/Http/Livewire/Subscription/PricingPlans.php b/app/Http/Livewire/Subscription/PricingPlans.php
new file mode 100644
index 000000000..fcf24237f
--- /dev/null
+++ b/app/Http/Livewire/Subscription/PricingPlans.php
@@ -0,0 +1,66 @@
+emit('error', 'Price ID not found! Please contact the administrator.');
+ return;
+ }
+ $payload = [
+ 'client_reference_id' => auth()->user()->id . ':' . currentTeam()->id,
+ 'line_items' => [[
+ 'price' => $priceId,
+ 'quantity' => 1,
+ ]],
+ 'tax_id_collection' => [
+ 'enabled' => true,
+ ],
+ 'mode' => 'subscription',
+ 'success_url' => route('subscription.success'),
+ 'cancel_url' => route('subscription.show',['cancelled' => true]),
+ ];
+ $customer = currentTeam()->subscription?->stripe_customer_id ?? null;
+ if ($customer) {
+ $payload['customer'] = $customer;
+ $payload['customer_update'] = [
+ 'name' => 'auto'
+ ];
+ } else {
+ $payload['customer_email'] = auth()->user()->email;
+ }
+ $session = Session::create($payload);
+ return redirect($session->url, 303);
+ }
+}
diff --git a/app/Http/Livewire/Team/Create.php b/app/Http/Livewire/Team/Create.php
index 6c1c71580..bd2c24313 100644
--- a/app/Http/Livewire/Team/Create.php
+++ b/app/Http/Livewire/Team/Create.php
@@ -29,7 +29,7 @@ class Create extends Component
'personal_team' => false,
]);
auth()->user()->teams()->attach($team, ['role' => 'admin']);
- session(['currentTeam' => $team]);
+ refreshSession();
return redirect()->route('team.show');
} catch (\Throwable $th) {
return general_error_handler($th, $this);
diff --git a/app/Http/Livewire/Team/Delete.php b/app/Http/Livewire/Team/Delete.php
index d14e82ccc..5e206704b 100644
--- a/app/Http/Livewire/Team/Delete.php
+++ b/app/Http/Livewire/Team/Delete.php
@@ -9,7 +9,7 @@ class Delete extends Component
{
public function delete()
{
- $currentTeam = auth()->user()->currentTeam();
+ $currentTeam = currentTeam();
$currentTeam->delete();
$team = auth()->user()->teams()->first();
@@ -24,7 +24,7 @@ class Delete extends Component
}
});
- session(['currentTeam' => $team]);
+ refreshSession();
return redirect()->route('team.show');
}
}
diff --git a/app/Http/Livewire/Team/Form.php b/app/Http/Livewire/Team/Form.php
index eedd60c83..caa6d2c9e 100644
--- a/app/Http/Livewire/Team/Form.php
+++ b/app/Http/Livewire/Team/Form.php
@@ -19,7 +19,7 @@ class Form extends Component
public function mount()
{
- $this->team = auth()->user()->currentTeam();
+ $this->team = currentTeam();
}
public function submit()
@@ -27,7 +27,7 @@ class Form extends Component
$this->validate();
try {
$this->team->save();
- session(['currentTeam' => $this->team]);
+ refreshSession();
$this->emit('reloadWindow');
} catch (\Throwable $th) {
return general_error_handler($th, $this);
diff --git a/app/Http/Livewire/Team/Invitations.php b/app/Http/Livewire/Team/Invitations.php
index ba0b654aa..ba6c1e91f 100644
--- a/app/Http/Livewire/Team/Invitations.php
+++ b/app/Http/Livewire/Team/Invitations.php
@@ -18,6 +18,6 @@ class Invitations extends Component
public function refreshInvitations()
{
- $this->invitations = TeamInvitation::whereTeamId(auth()->user()->currentTeam()->id)->get();
+ $this->invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get();
}
}
diff --git a/app/Http/Livewire/Team/InviteLink.php b/app/Http/Livewire/Team/InviteLink.php
index ddbe75182..b554e6575 100644
--- a/app/Http/Livewire/Team/InviteLink.php
+++ b/app/Http/Livewire/Team/InviteLink.php
@@ -15,7 +15,7 @@ class InviteLink extends Component
public function mount()
{
- $this->email = is_dev() ? 'test3@example.com' : '';
+ $this->email = isDev() ? 'test3@example.com' : '';
}
public function viaEmail()
@@ -35,9 +35,9 @@ class InviteLink extends Component
return general_error_handler(that: $this, customErrorMessage: "$this->email must be registered first (or activate transactional emails to invite via email).");
}
- $member_emails = auth()->user()->currentTeam()->members()->get()->pluck('email');
+ $member_emails = currentTeam()->members()->get()->pluck('email');
if ($member_emails->contains($this->email)) {
- return general_error_handler(that: $this, customErrorMessage: "$this->email is already a member of " . auth()->user()->currentTeam()->name . ".");
+ return general_error_handler(that: $this, customErrorMessage: "$this->email is already a member of " . currentTeam()->name . ".");
}
$invitation = TeamInvitation::whereEmail($this->email);
@@ -53,7 +53,7 @@ class InviteLink extends Component
}
TeamInvitation::firstOrCreate([
- 'team_id' => auth()->user()->currentTeam()->id,
+ 'team_id' => currentTeam()->id,
'uuid' => $uuid,
'email' => $this->email,
'role' => $this->role,
diff --git a/app/Http/Livewire/Team/Member.php b/app/Http/Livewire/Team/Member.php
index 237d38818..df8fcd7af 100644
--- a/app/Http/Livewire/Team/Member.php
+++ b/app/Http/Livewire/Team/Member.php
@@ -11,19 +11,19 @@ class Member extends Component
public function makeAdmin()
{
- $this->member->teams()->updateExistingPivot(auth()->user()->currentTeam()->id, ['role' => 'admin']);
+ $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'admin']);
$this->emit('reloadWindow');
}
public function makeReadonly()
{
- $this->member->teams()->updateExistingPivot(auth()->user()->currentTeam()->id, ['role' => 'member']);
+ $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'member']);
$this->emit('reloadWindow');
}
public function remove()
{
- $this->member->teams()->detach(auth()->user()->currentTeam());
+ $this->member->teams()->detach(currentTeam());
$this->emit('reloadWindow');
}
}
diff --git a/app/Http/Livewire/Team/Storage/Create.php b/app/Http/Livewire/Team/Storage/Create.php
index ed7d277fb..e1330784a 100644
--- a/app/Http/Livewire/Team/Storage/Create.php
+++ b/app/Http/Livewire/Team/Storage/Create.php
@@ -36,7 +36,7 @@ class Create extends Component
public function mount()
{
- if (is_dev()) {
+ if (isDev()) {
$this->name = 'Local MinIO';
$this->description = 'Local MinIO';
$this->key = 'minioadmin';
@@ -62,7 +62,7 @@ class Create extends Component
} else {
$this->storage->endpoint = $this->endpoint;
}
- $this->storage->team_id = auth()->user()->currentTeam()->id;
+ $this->storage->team_id = currentTeam()->id;
$this->storage->testConnection();
$this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
$this->storage->save();
diff --git a/app/Http/Livewire/Upgrade.php b/app/Http/Livewire/Upgrade.php
index f46e37ff7..e79c73fb7 100644
--- a/app/Http/Livewire/Upgrade.php
+++ b/app/Http/Livewire/Upgrade.php
@@ -18,7 +18,7 @@ class Upgrade extends Component
$this->latestVersion = get_latest_version_of_coolify();
$currentVersion = config('version');
version_compare($currentVersion, $this->latestVersion, '<') ? $this->isUpgradeAvailable = true : $this->isUpgradeAvailable = false;
- if (is_dev()) {
+ if (isDev()) {
$this->isUpgradeAvailable = true;
}
$settings = InstanceSettings::get();
diff --git a/app/Http/Livewire/Waitlist.php b/app/Http/Livewire/Waitlist.php
index de633ceac..d9b3b92ab 100644
--- a/app/Http/Livewire/Waitlist.php
+++ b/app/Http/Livewire/Waitlist.php
@@ -17,7 +17,7 @@ class Waitlist extends Component
];
public function mount()
{
- if (is_dev()) {
+ if (isDev()) {
$this->email = 'waitlist@example.com';
}
}
diff --git a/app/Http/Middleware/IsBoardingFlow.php b/app/Http/Middleware/IsBoardingFlow.php
new file mode 100644
index 000000000..83662a073
--- /dev/null
+++ b/app/Http/Middleware/IsBoardingFlow.php
@@ -0,0 +1,24 @@
+path(), allowedPathsForBoardingAccounts())) {
+ return redirect('boarding');
+ }
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/SubscriptionValid.php b/app/Http/Middleware/SubscriptionValid.php
index f84e6eede..824133f5a 100644
--- a/app/Http/Middleware/SubscriptionValid.php
+++ b/app/Http/Middleware/SubscriptionValid.php
@@ -10,6 +10,9 @@ class SubscriptionValid
{
public function handle(Request $request, Closure $next): Response
{
+ if (isInstanceAdmin()) {
+ return $next($request);
+ }
if (!auth()->user() || !is_cloud()) {
if ($request->path() === 'subscription') {
return redirect('/');
@@ -17,32 +20,17 @@ class SubscriptionValid
return $next($request);
}
}
- $is_instance_admin = is_instance_admin();
- if ($is_instance_admin) {
- return $next($request);
- }
-
- if (is_subscription_active() && $request->path() === 'subscription') {
+ if (isSubscriptionActive() && $request->path() === 'subscription') {
+ // ray('active subscription Middleware');
return redirect('/');
}
- if (is_subscription_in_grace_period()) {
+ if (isSubscriptionOnGracePeriod()) {
+ // ray('is_subscription_in_grace_period Middleware');
return $next($request);
}
- if (!is_subscription_active() && !is_subscription_in_grace_period()) {
- ray('SubscriptionValid Middleware');
-
- $allowed_paths = [
- 'subscription',
- 'login',
- 'register',
- 'waitlist',
- 'force-password-reset',
- 'logout',
- 'livewire/message/force-password-reset',
- 'livewire/message/check-license',
- 'livewire/message/switch-team',
- ];
- if (!in_array($request->path(), $allowed_paths)) {
+ if (!isSubscriptionActive() && !isSubscriptionOnGracePeriod()) {
+ // ray('SubscriptionValid Middleware');
+ if (!in_array($request->path(), allowedPathsForUnsubscribedAccounts())) {
return redirect('subscription');
} else {
return $next($request);
diff --git a/app/Jobs/ApplicationContainerStatusJob.php b/app/Jobs/ApplicationContainerStatusJob.php
new file mode 100644
index 000000000..f7496770d
--- /dev/null
+++ b/app/Jobs/ApplicationContainerStatusJob.php
@@ -0,0 +1,54 @@
+containerName = generateApplicationContainerName($application->uuid, $pullRequestId);
+ }
+
+ public function uniqueId(): string
+ {
+ return $this->containerName;
+ }
+
+ public function handle(): void
+ {
+ try {
+ $status = getApplicationContainerStatus(application: $this->application);
+ if ($this->application->status === 'running' && $status !== 'running') {
+ // $this->application->environment->project->team->notify(new StatusChanged($this->application));
+ }
+
+ if ($this->pullRequestId !== 0) {
+ $preview = ApplicationPreview::findPreviewByApplicationAndPullId($this->application->id, $this->pullRequestId);
+ $preview->status = $status;
+ $preview->save();
+ } else {
+ $this->application->status = $status;
+ $this->application->save();
+ }
+ } catch (\Exception $th) {
+ ray($th->getMessage());
+ throw $th;
+ }
+ }
+}
diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php
index fc0a3a1b7..5f24d4ab8 100644
--- a/app/Jobs/ApplicationDeploymentJob.php
+++ b/app/Jobs/ApplicationDeploymentJob.php
@@ -50,6 +50,7 @@ class ApplicationDeploymentJob implements ShouldQueue
private ApplicationPreview|null $preview = null;
private string $container_name;
+ private string|null $currently_running_container_name = null;
private string $workdir;
private string $configuration_dir;
private string $build_workdir;
@@ -86,7 +87,7 @@ class ApplicationDeploymentJob implements ShouldQueue
$this->build_workdir = "{$this->workdir}" . rtrim($this->application->base_directory, '/');
$this->is_debug_enabled = $this->application->settings->is_debug_enabled;
- $this->container_name = generate_container_name($this->application->uuid, $this->pull_request_id);
+ $this->container_name = generateApplicationContainerName($this->application->uuid, $this->pull_request_id);
$this->private_key_location = save_private_key_for_server($this->server);
$this->saved_outputs = collect();
@@ -113,6 +114,10 @@ class ApplicationDeploymentJob implements ShouldQueue
public function handle(): void
{
// ray()->measure();
+ $containers = getCurrentApplicationContainerStatus($this->server, $this->application->id);
+ if ($containers->count() > 0) {
+ $this->currently_running_container_name = data_get($containers[0], 'Names');
+ }
$this->application_deployment_queue->update([
'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
]);
@@ -131,6 +136,7 @@ class ApplicationDeploymentJob implements ShouldQueue
} catch (Exception $e) {
ray($e);
$this->fail($e);
+ throw $e;
} finally {
if (isset($this->docker_compose_base64)) {
$readme = generate_readme_file($this->application->name, $this->application_deployment_queue->updated_at);
@@ -175,9 +181,9 @@ class ApplicationDeploymentJob implements ShouldQueue
$this->generate_build_env_variables();
$this->add_build_env_variables_to_dockerfile();
$this->build_image();
- $this->stop_running_container();
- $this->start_by_compose_file();
+ $this->rolling_update();
}
+
private function deploy()
{
$this->execute_remote_command(
@@ -206,8 +212,7 @@ class ApplicationDeploymentJob implements ShouldQueue
"echo 'Docker Image found locally with the same Git Commit SHA {$this->application->uuid}:{$this->commit}. Build step skipped...'"
]);
$this->generate_compose_file();
- $this->stop_running_container();
- $this->start_by_compose_file();
+ $this->rolling_update();
return;
}
}
@@ -219,8 +224,54 @@ class ApplicationDeploymentJob implements ShouldQueue
$this->generate_build_env_variables();
$this->add_build_env_variables_to_dockerfile();
$this->build_image();
- $this->stop_running_container();
+ $this->rolling_update();
+ }
+
+ private function rolling_update()
+ {
$this->start_by_compose_file();
+ $this->health_check();
+ $this->stop_running_container();
+ }
+ private function health_check()
+ {
+ ray('New container name: ',$this->container_name);
+ if ($this->container_name) {
+ $counter = 0;
+ $this->execute_remote_command(
+ [
+ "echo 'Waiting for health check to pass on the new version of your application.'"
+ ],
+ );
+ while ($counter < $this->application->health_check_retries) {
+ $this->execute_remote_command(
+ [
+ "echo 'Attempt {$counter} of {$this->application->health_check_retries}'"
+ ],
+ [
+ "docker inspect --format='{{json .State.Health.Status}}' {$this->container_name}",
+ "hidden" => true,
+ "save" => "health_check"
+ ],
+
+ );
+ $this->execute_remote_command(
+ [
+ "echo 'New application version health check status: {$this->saved_outputs->get('health_check')}'"
+ ],
+ );
+ if (Str::of($this->saved_outputs->get('health_check'))->contains('healthy')) {
+ $this->execute_remote_command(
+ [
+ "echo 'Rolling update completed.'"
+ ],
+ );
+ break;
+ }
+ $counter++;
+ sleep($this->application->health_check_interval);
+ }
+ }
}
private function deploy_pull_request()
{
@@ -241,8 +292,7 @@ class ApplicationDeploymentJob implements ShouldQueue
// $this->generate_build_env_variables();
// $this->add_build_env_variables_to_dockerfile();
$this->build_image();
- $this->stop_running_container();
- $this->start_by_compose_file();
+ $this->rolling_update();
}
private function prepare_builder_image()
@@ -409,7 +459,7 @@ class ApplicationDeploymentJob implements ShouldQueue
$this->container_name => [
'image' => $this->production_image_name,
'container_name' => $this->container_name,
- 'restart' => 'always',
+ 'restart' => RESTART_MODE,
'environment' => $environment_variables,
'labels' => $this->set_labels_for_applications(),
'expose' => $ports,
@@ -539,8 +589,8 @@ class ApplicationDeploymentJob implements ShouldQueue
$schema = $url->getScheme();
$slug = Str::slug($host . $path);
- $http_label = "{$this->application->uuid}-{$slug}-http";
- $https_label = "{$this->application->uuid}-{$slug}-https";
+ $http_label = "{$this->container_name}-{$slug}-http";
+ $https_label = "{$this->container_name}-{$slug}-https";
if ($schema === 'https') {
// Set labels for https
@@ -647,23 +697,22 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
private function stop_running_container()
{
- $this->execute_remote_command(
- ["echo -n 'Removing old running application.'"],
- [$this->execute_in_builder("docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true],
- );
+ if ($this->currently_running_container_name) {
+ $this->execute_remote_command(
+ ["echo -n 'Removing old application version.'"],
+ [$this->execute_in_builder("docker rm -f $this->currently_running_container_name >/dev/null 2>&1"), "hidden" => true],
+ );
+ }
}
private function start_by_compose_file()
{
$this->execute_remote_command(
- ["echo -n 'Starting new application... '"],
+ ["echo -n 'Rolling update started.'"],
[$this->execute_in_builder("docker compose --project-directory {$this->workdir} up -d >/dev/null"), "hidden" => true],
- ["echo 'Done. 🎉'"],
);
}
-
-
private function generate_build_env_variables()
{
$this->build_args = collect(["--build-arg SOURCE_COMMIT={$this->commit}"]);
diff --git a/app/Jobs/CheckResaleLicenseJob.php b/app/Jobs/CheckResaleLicenseJob.php
index f14214733..30f9ff198 100644
--- a/app/Jobs/CheckResaleLicenseJob.php
+++ b/app/Jobs/CheckResaleLicenseJob.php
@@ -22,7 +22,9 @@ class CheckResaleLicenseJob implements ShouldQueue
try {
resolve(CheckResaleLicense::class)();
} catch (\Throwable $th) {
+ send_internal_notification('CheckResaleLicenseJob failed with: ' . $th->getMessage());
ray($th);
+ throw $th;
}
}
}
diff --git a/app/Jobs/CleanupInstanceStuffsJob.php b/app/Jobs/CleanupInstanceStuffsJob.php
index e67a562bd..b133279ea 100644
--- a/app/Jobs/CleanupInstanceStuffsJob.php
+++ b/app/Jobs/CleanupInstanceStuffsJob.php
@@ -31,6 +31,7 @@ class CleanupInstanceStuffsJob implements ShouldQueue, ShouldBeUnique
} catch (\Exception $e) {
send_internal_notification('CleanupInstanceStuffsJob failed with error: ' . $e->getMessage());
ray($e->getMessage());
+ throw $e;
}
}
diff --git a/app/Jobs/ContainerStatusJob.php b/app/Jobs/ContainerStatusJob.php
deleted file mode 100644
index f2be8b4d7..000000000
--- a/app/Jobs/ContainerStatusJob.php
+++ /dev/null
@@ -1,54 +0,0 @@
-resource = $resource;
- $this->container_name = $container_name;
- $this->pull_request_id = $pull_request_id;
- }
-
- public function uniqueId(): string
- {
- return $this->container_name;
- }
-
- public function handle(): void
- {
- try {
- $status = get_container_status(server: $this->resource->destination->server, container_id: $this->container_name, throwError: false);
- if ($this->resource->status === 'running' && $status !== 'running') {
- $this->resource->environment->project->team->notify(new StatusChanged($this->resource));
- }
-
- if ($this->pull_request_id) {
- $preview = ApplicationPreview::findPreviewByApplicationAndPullId($this->resource->id, $this->pull_request_id);
- $preview->status = $status;
- $preview->save();
- } else {
- $this->resource->status = $status;
- $this->resource->save();
- }
- } catch (\Exception $e) {
- ray($e->getMessage());
- }
- }
-}
diff --git a/app/Jobs/CoolifyTask.php b/app/Jobs/CoolifyTask.php
index e3dd9640f..176841b20 100755
--- a/app/Jobs/CoolifyTask.php
+++ b/app/Jobs/CoolifyTask.php
@@ -28,7 +28,6 @@ class CoolifyTask implements ShouldQueue
*/
public function handle(): void
{
-
$remote_process = resolve(RunRemoteProcess::class, [
'activity' => $this->activity,
'ignore_errors' => $this->ignore_errors,
diff --git a/app/Jobs/DatabaseBackupJob.php b/app/Jobs/DatabaseBackupJob.php
index eed6c5de8..6e1ee2f0c 100644
--- a/app/Jobs/DatabaseBackupJob.php
+++ b/app/Jobs/DatabaseBackupJob.php
@@ -64,35 +64,42 @@ class DatabaseBackupJob implements ShouldQueue
public function handle(): void
{
- if ($this->database_status !== 'running') {
- ray('database not running');
- return;
- }
- $this->container_name = $this->database->uuid;
- $this->backup_dir = backup_dir() . "/databases/" . Str::of($this->team->name)->slug() . '-' . $this->team->id . '/' . $this->container_name;
+ try {
+ if ($this->database_status !== 'running') {
+ ray('database not running');
+ return;
+ }
+ $this->container_name = $this->database->uuid;
+ $this->backup_dir = backup_dir() . "/databases/" . Str::of($this->team->name)->slug() . '-' . $this->team->id . '/' . $this->container_name;
- if ($this->database->name === 'coolify-db') {
- $this->container_name = "coolify-db";
- $ip = Str::slug($this->server->ip);
- $this->backup_dir = backup_dir() . "/coolify" . "/coolify-db-$ip";
- }
- $this->backup_file = "/dumpall-" . Carbon::now()->timestamp . ".sql";
- $this->backup_location = $this->backup_dir . $this->backup_file;
+ if ($this->database->name === 'coolify-db') {
+ $this->container_name = "coolify-db";
+ $ip = Str::slug($this->server->ip);
+ $this->backup_dir = backup_dir() . "/coolify" . "/coolify-db-$ip";
+ }
+ $this->backup_file = "/dumpall-" . Carbon::now()->timestamp . ".sql";
+ $this->backup_location = $this->backup_dir . $this->backup_file;
- $this->backup_log = ScheduledDatabaseBackupExecution::create([
- 'filename' => $this->backup_location,
- 'scheduled_database_backup_id' => $this->backup->id,
- ]);
- if ($this->database_type === 'standalone-postgresql') {
- $this->backup_standalone_postgresql();
+ $this->backup_log = ScheduledDatabaseBackupExecution::create([
+ 'filename' => $this->backup_location,
+ 'scheduled_database_backup_id' => $this->backup->id,
+ ]);
+ if ($this->database_type === 'standalone-postgresql') {
+ $this->backup_standalone_postgresql();
+ }
+ $this->calculate_size();
+ $this->remove_old_backups();
+ if ($this->backup->save_s3) {
+ $this->upload_to_s3();
+ }
+ $this->save_backup_logs();
+ // TODO: Notify user
+ } catch (\Throwable $th) {
+ ray($th->getMessage());
+ send_internal_notification('DatabaseBackupJob failed with: ' . $th->getMessage());
+ throw $th;
}
- $this->calculate_size();
- $this->remove_old_backups();
- if ($this->backup->save_s3) {
- $this->upload_to_s3();
- }
- $this->save_backup_logs();
- // TODO: Notify user
+
}
private function backup_standalone_postgresql(): void
diff --git a/app/Jobs/DatabaseContainerStatusJob.php b/app/Jobs/DatabaseContainerStatusJob.php
new file mode 100644
index 000000000..1630545c5
--- /dev/null
+++ b/app/Jobs/DatabaseContainerStatusJob.php
@@ -0,0 +1,56 @@
+containerName = $database->uuid;
+ }
+
+ public function uniqueId(): string
+ {
+ return $this->containerName;
+ }
+
+ public function handle(): void
+ {
+ try {
+ $status = getContainerStatus(
+ server: $this->database->destination->server,
+ container_id: $this->containerName,
+ throwError: false
+ );
+
+ if ($this->database->status === 'running' && $status !== 'running') {
+ if (data_get($this->database, 'environment.project.team')) {
+ // $this->database->environment->project->team->notify(new StatusChanged($this->database));
+ }
+ }
+ if ($this->database->status !== $status) {
+ $this->database->status = $status;
+ $this->database->save();
+ }
+ } catch (\Exception $e) {
+ send_internal_notification('DatabaseContainerStatusJob failed with: ' . $e->getMessage());
+ ray($e->getMessage());
+ throw $e;
+ }
+ }
+}
diff --git a/app/Jobs/DockerCleanupJob.php b/app/Jobs/DockerCleanupJob.php
index 52279c241..7a8571c00 100644
--- a/app/Jobs/DockerCleanupJob.php
+++ b/app/Jobs/DockerCleanupJob.php
@@ -32,7 +32,7 @@ class DockerCleanupJob implements ShouldQueue
try {
$servers = Server::all();
foreach ($servers as $server) {
- if (is_dev()) {
+ if (isDev()) {
$docker_root_filesystem = "/";
} else {
$docker_root_filesystem = instant_remote_process(['stat --printf=%m $(docker info --format "{{json .DockerRootDir}}" |sed \'s/"//g\')'], $server);
@@ -49,14 +49,17 @@ class DockerCleanupJob implements ShouldQueue
}
}
} catch (\Exception $e) {
+ send_internal_notification('DockerCleanupJob failed with: ' . $e->getMessage());
ray($e->getMessage());
+ throw $e;
}
}
private function get_disk_usage(Server $server, string $docker_root_filesystem)
{
- $disk_usage = json_decode(instant_remote_process(['df -hP | awk \'BEGIN {printf"{\"disks\":["}{if($1=="Filesystem")next;if(a)printf",";printf"{\"mount\":\""$6"\",\"size\":\""$2"\",\"used\":\""$3"\",\"avail\":\""$4"\",\"use%\":\""$5"\"}";a++;}END{print"]}";}\''], $server), true);
+ $disk_usage = json_decode(instant_remote_process(['df -hP | awk \'BEGIN {printf"{\\"disks\\":["}{if($1=="Filesystem")next;if(a)printf",";printf"{\\"mount\\":\\""$6"\\",\\"size\\":\\""$2"\\",\\"used\\":\\""$3"\\",\\"avail\\":\\""$4"\\",\\"use%\\":\\""$5"\\"}";a++;}END{print"]}";}\''], $server), true);
$mount_point = collect(data_get($disk_usage, 'disks'))->where('mount', $docker_root_filesystem)->first();
+ ray($mount_point);
return Str::of(data_get($mount_point, 'use%'))->trim()->replace('%', '')->value();
}
}
diff --git a/app/Jobs/ProxyCheckJob.php b/app/Jobs/ProxyCheckJob.php
index 7c498107d..9d5559053 100755
--- a/app/Jobs/ProxyCheckJob.php
+++ b/app/Jobs/ProxyCheckJob.php
@@ -22,9 +22,14 @@ class ProxyCheckJob implements ShouldQueue
{
try {
$container_name = 'coolify-proxy';
- $servers = Server::isUsable()->whereNotNull('proxy')->get();
+ $servers = Server::all();
foreach ($servers as $server) {
- $status = get_container_status(server: $server, container_id: $container_name);
+ if (
+ $server->settings->is_reachable === false || $server->settings->is_usable === false
+ ) {
+ continue;
+ }
+ $status = getContainerStatus(server: $server, container_id: $container_name);
if ($status === 'running') {
continue;
}
@@ -33,7 +38,8 @@ class ProxyCheckJob implements ShouldQueue
}
} catch (\Throwable $th) {
ray($th->getMessage());
- //throw $th;
+ send_internal_notification('ProxyCheckJob failed with: ' . $th->getMessage());
+ throw $th;
}
}
}
diff --git a/app/Jobs/ProxyContainerStatusJob.php b/app/Jobs/ProxyContainerStatusJob.php
index 68372895a..aa6056434 100644
--- a/app/Jobs/ProxyContainerStatusJob.php
+++ b/app/Jobs/ProxyContainerStatusJob.php
@@ -39,9 +39,9 @@ class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique
public function handle(): void
{
try {
- $container = get_container_status(server: $this->server, all_data: true, container_id: 'coolify-proxy', throwError: true);
- $status = $container['State']['Status'];
- if ($this->server->proxy->status !== $status) {
+ $container = getContainerStatus(server: $this->server, all_data: true, container_id: 'coolify-proxy', throwError: true);
+ $status = data_get($container, 'State.Status');
+ if (data_get($this->server,'proxy.status') !== $status) {
$this->server->proxy->status = $status;
if ($this->server->proxy->status === 'running') {
$traefik = $container['Config']['Labels']['org.opencontainers.image.title'];
@@ -57,6 +57,9 @@ class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique
$this->server->proxy->status = 'exited';
$this->server->save();
}
+ send_internal_notification('ProxyContainerStatusJob failed with: ' . $e->getMessage());
+ ray($e->getMessage());
+ throw $e;
}
}
}
diff --git a/app/Jobs/ProxyStartJob.php b/app/Jobs/ProxyStartJob.php
index 5119210fc..4e2331a68 100755
--- a/app/Jobs/ProxyStartJob.php
+++ b/app/Jobs/ProxyStartJob.php
@@ -23,14 +23,15 @@ class ProxyStartJob implements ShouldQueue
try {
$container_name = 'coolify-proxy';
ray('Starting proxy for server: ' . $this->server->name);
- $status = get_container_status(server: $this->server, container_id: $container_name);
+ $status = getContainerStatus(server: $this->server, container_id: $container_name);
if ($status === 'running') {
return;
}
resolve(StartProxy::class)($this->server);
} catch (\Throwable $th) {
+ send_internal_notification('ProxyStartJob failed with: ' . $th->getMessage());
ray($th->getMessage());
- //throw $th;
+ throw $th;
}
}
}
diff --git a/app/Jobs/ResourceStatusJob.php b/app/Jobs/ResourceStatusJob.php
index 5ac162d3f..efd6d1445 100644
--- a/app/Jobs/ResourceStatusJob.php
+++ b/app/Jobs/ResourceStatusJob.php
@@ -3,6 +3,7 @@
namespace App\Jobs;
use App\Models\Application;
+use App\Models\StandalonePostgresql;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
@@ -15,23 +16,31 @@ class ResourceStatusJob implements ShouldQueue, ShouldBeUnique
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $applications;
+ public $postgresqls;
public function __construct()
{
$this->applications = Application::all();
+ $this->postgresqls = StandalonePostgresql::all();
}
public function handle(): void
{
try {
foreach ($this->applications as $application) {
- dispatch(new ContainerStatusJob(
- resource: $application,
- container_name: generate_container_name($application->uuid),
+ dispatch(new ApplicationContainerStatusJob(
+ application: $application,
));
}
- } catch (\Exception $e) {
- ray($e->getMessage());
+ foreach ($this->postgresqls as $postgresql) {
+ dispatch(new DatabaseContainerStatusJob(
+ database: $postgresql,
+ ));
+ }
+ } catch (\Exception $th) {
+ send_internal_notification('ResourceStatusJob failed with: ' . $th->getMessage());
+ ray($th);
+ throw $th;
}
}
}
diff --git a/app/Jobs/SubscriptionInvoiceFailedJob.php b/app/Jobs/SubscriptionInvoiceFailedJob.php
new file mode 100755
index 000000000..d6750f953
--- /dev/null
+++ b/app/Jobs/SubscriptionInvoiceFailedJob.php
@@ -0,0 +1,43 @@
+team);
+ $mail = new MailMessage();
+ $mail->view('emails.subscription-invoice-failed', [
+ 'stripeCustomerPortal' => $session->url,
+ ]);
+ $mail->subject('Your last payment was failed for Coolify Cloud.');
+ $this->team->members()->each(function ($member) use ($mail) {
+ ray($member);
+ if ($member->isAdmin()) {
+ send_user_an_email($mail, $member->email);
+ }
+ });
+ } catch (\Throwable $th) {
+ send_internal_notification('SubscriptionInvoiceFailedJob failed with: ' . $th->getMessage());
+ ray($th->getMessage());
+ throw $th;
+ }
+ }
+}
diff --git a/app/Models/EnvironmentVariable.php b/app/Models/EnvironmentVariable.php
index bb4a5ca47..62a08c87f 100644
--- a/app/Models/EnvironmentVariable.php
+++ b/app/Models/EnvironmentVariable.php
@@ -41,7 +41,7 @@ class EnvironmentVariable extends Model
private function get_environment_variables(string $environment_variable): string|null
{
- // $team_id = auth()->user()->currentTeam()->id;
+ // $team_id = currentTeam()->id;
if (str_contains(trim($environment_variable), '{{') && str_contains(trim($environment_variable), '}}')) {
$environment_variable = preg_replace('/\s+/', '', $environment_variable);
$environment_variable = str_replace('{{', '', $environment_variable);
diff --git a/app/Models/GithubApp.php b/app/Models/GithubApp.php
index 74462e8d7..c4cd3568d 100644
--- a/app/Models/GithubApp.php
+++ b/app/Models/GithubApp.php
@@ -19,12 +19,12 @@ class GithubApp extends BaseModel
static public function public()
{
- return GithubApp::whereTeamId(auth()->user()->currentTeam()->id)->whereisPublic(true)->whereNotNull('app_id')->get();
+ return GithubApp::whereTeamId(currentTeam()->id)->whereisPublic(true)->whereNotNull('app_id')->get();
}
static public function private()
{
- return GithubApp::whereTeamId(auth()->user()->currentTeam()->id)->whereisPublic(false)->whereNotNull('app_id')->get();
+ return GithubApp::whereTeamId(currentTeam()->id)->whereisPublic(false)->whereNotNull('app_id')->get();
}
protected static function booted(): void
diff --git a/app/Models/PrivateKey.php b/app/Models/PrivateKey.php
index 4d59e9ca8..d4fd0bfa2 100644
--- a/app/Models/PrivateKey.php
+++ b/app/Models/PrivateKey.php
@@ -16,7 +16,7 @@ class PrivateKey extends BaseModel
static public function ownedByCurrentTeam(array $select = ['*'])
{
$selectArray = collect($select)->concat(['id']);
- return PrivateKey::whereTeamId(auth()->user()->currentTeam()->id)->select($selectArray->all());
+ return PrivateKey::whereTeamId(currentTeam()->id)->select($selectArray->all());
}
public function isEmpty()
diff --git a/app/Models/Project.php b/app/Models/Project.php
index a50dde167..9bcd2a0fe 100644
--- a/app/Models/Project.php
+++ b/app/Models/Project.php
@@ -4,16 +4,11 @@ namespace App\Models;
class Project extends BaseModel
{
- protected $fillable = [
- 'name',
- 'description',
- 'team_id',
- 'project_id'
- ];
+ protected $guarded = [];
static public function ownedByCurrentTeam()
{
- return Project::whereTeamId(auth()->user()->currentTeam()->id)->orderBy('name');
+ return Project::whereTeamId(currentTeam()->id)->orderBy('name');
}
protected static function booted()
diff --git a/app/Models/S3Storage.php b/app/Models/S3Storage.php
index 5cd2f1318..cbcdb97a9 100644
--- a/app/Models/S3Storage.php
+++ b/app/Models/S3Storage.php
@@ -17,7 +17,7 @@ class S3Storage extends BaseModel
static public function ownedByCurrentTeam(array $select = ['*'])
{
$selectArray = collect($select)->concat(['id']);
- return S3Storage::whereTeamId(auth()->user()->currentTeam()->id)->select($selectArray->all())->orderBy('name');
+ return S3Storage::whereTeamId(currentTeam()->id)->select($selectArray->all())->orderBy('name');
}
public function awsUrl()
diff --git a/app/Models/Server.php b/app/Models/Server.php
index 91adb6b9b..764c58246 100644
--- a/app/Models/Server.php
+++ b/app/Models/Server.php
@@ -10,21 +10,40 @@ class Server extends BaseModel
{
use SchemalessAttributesTrait;
+ protected static function booted()
+ {
+ static::created(function ($server) {
+ ServerSetting::create([
+ 'server_id' => $server->id,
+ ]);
+ if ($server->id === 0) {
+ StandaloneDocker::create([
+ 'id' => 0,
+ 'name' => 'coolify',
+ 'network' => 'coolify',
+ 'server_id' => $server->id,
+ ]);
+ } else {
+ StandaloneDocker::create([
+ 'name' => 'coolify',
+ 'network' => 'coolify',
+ 'server_id' => $server->id,
+ ]);
+ }
+
+ });
+ static::deleting(function ($server) {
+ $server->settings()->delete();
+ });
+ }
+
public $casts = [
'proxy' => SchemalessAttributes::class,
];
protected $schemalessAttributes = [
'proxy',
];
- protected $fillable = [
- 'name',
- 'ip',
- 'user',
- 'port',
- 'team_id',
- 'private_key_id',
- 'proxy',
- ];
+ protected $guarded = [];
static public function isReachable()
{
@@ -33,8 +52,9 @@ class Server extends BaseModel
static public function ownedByCurrentTeam(array $select = ['*'])
{
+ $teamId = currentTeam()->id;
$selectArray = collect($select)->concat(['id']);
- return Server::whereTeamId(auth()->user()->currentTeam()->id)->with('settings')->select($selectArray->all())->orderBy('name');
+ return Server::whereTeamId($teamId)->with('settings')->select($selectArray->all())->orderBy('name');
}
static public function isUsable()
@@ -50,17 +70,7 @@ class Server extends BaseModel
return $standaloneDocker->concat($swarmDocker);
}
- protected static function booted()
- {
- static::created(function ($server) {
- ServerSetting::create([
- 'server_id' => $server->id,
- ]);
- });
- static::deleting(function ($server) {
- $server->settings()->delete();
- });
- }
+
public function settings()
{
diff --git a/app/Models/Subscription.php b/app/Models/Subscription.php
index 4b78c37a9..e0a52d5b1 100644
--- a/app/Models/Subscription.php
+++ b/app/Models/Subscription.php
@@ -14,9 +14,9 @@ class Subscription extends Model
}
public function type()
{
- $basic = explode(',', config('coolify.lemon_squeezy_basic_plan_ids'));
- $pro = explode(',', config('coolify.lemon_squeezy_pro_plan_ids'));
- $ultimate = explode(',', config('coolify.lemon_squeezy_ultimate_plan_ids'));
+ $basic = explode(',', config('subscription.lemon_squeezy_basic_plan_ids'));
+ $pro = explode(',', config('subscription.lemon_squeezy_pro_plan_ids'));
+ $ultimate = explode(',', config('subscription.lemon_squeezy_ultimate_plan_ids'));
$subscription = $this->lemon_variant_id;
if (in_array($subscription, $basic)) {
diff --git a/app/Models/User.php b/app/Models/User.php
index b048ef9e6..13140f133 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -22,6 +22,7 @@ class User extends Authenticatable implements SendsEmail
protected $casts = [
'email_verified_at' => 'datetime',
'force_password_reset' => 'boolean',
+ 'show_boarding' => 'boolean',
];
protected static function boot()
@@ -102,7 +103,7 @@ class User extends Authenticatable implements SendsEmail
public function otherTeams()
{
- $team_id = auth()->user()->currentTeam()->id;
+ $team_id = currentTeam()->id;
return auth()->user()->teams->filter(function ($team) use ($team_id) {
return $team->id != $team_id;
});
@@ -113,13 +114,6 @@ class User extends Authenticatable implements SendsEmail
if ($this->teams()->where('team_id', 0)->first()) {
return 'admin';
}
- return $this->teams()->where('team_id', auth()->user()->currentTeam()->id)->first()->pivot->role;
- }
-
- public function resources()
- {
- $team_id = auth()->user()->currentTeam()->id;
- $data = Application::where('team_id', $team_id)->get();
- return $data;
+ return $this->teams()->where('team_id', currentTeam()->id)->first()->pivot->role;
}
}
diff --git a/app/Models/Webhook.php b/app/Models/Webhook.php
index 308f17370..e259d16c1 100644
--- a/app/Models/Webhook.php
+++ b/app/Models/Webhook.php
@@ -8,6 +8,7 @@ class Webhook extends Model
{
protected $guarded = [];
protected $casts = [
+ 'type' => 'string',
'payload' => 'encrypted',
];
}
diff --git a/app/Notifications/Channels/DiscordChannel.php b/app/Notifications/Channels/DiscordChannel.php
index 7032a0796..6c361f89e 100644
--- a/app/Notifications/Channels/DiscordChannel.php
+++ b/app/Notifications/Channels/DiscordChannel.php
@@ -14,6 +14,9 @@ class DiscordChannel
{
$message = $notification->toDiscord($notifiable);
$webhookUrl = $notifiable->routeNotificationForDiscord();
+ if (!$webhookUrl) {
+ return;
+ }
dispatch(new SendMessageToDiscordJob($message, $webhookUrl));
}
}
diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php
index 638939589..b412bebd6 100644
--- a/app/Notifications/Channels/EmailChannel.php
+++ b/app/Notifications/Channels/EmailChannel.php
@@ -6,13 +6,13 @@ use Exception;
use Illuminate\Mail\Message;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail;
+use Illuminate\Support\Str;
class EmailChannel
{
public function send(SendsEmail $notifiable, Notification $notification): void
{
$this->bootConfigs($notifiable);
- ray($notification);
$recepients = $notifiable->getRecepients($notification);
if (count($recepients) === 0) {
@@ -39,16 +39,21 @@ class EmailChannel
$password = data_get($notifiable, 'smtp_password');
if ($password) $password = decrypt($password);
- config()->set('mail.default', 'smtp');
- config()->set('mail.mailers.smtp', [
- "transport" => "smtp",
- "host" => data_get($notifiable, 'smtp_host'),
- "port" => data_get($notifiable, 'smtp_port'),
- "encryption" => data_get($notifiable, 'smtp_encryption'),
- "username" => data_get($notifiable, 'smtp_username'),
- "password" => $password,
- "timeout" => data_get($notifiable, 'smtp_timeout'),
- "local_domain" => null,
- ]);
+ if (Str::contains(data_get($notifiable, 'smtp_host'),'resend.com')) {
+ config()->set('mail.default', 'resend');
+ config()->set('resend.api_key', $password);
+ } else {
+ config()->set('mail.default', 'smtp');
+ config()->set('mail.mailers.smtp', [
+ "transport" => "smtp",
+ "host" => data_get($notifiable, 'smtp_host'),
+ "port" => data_get($notifiable, 'smtp_port'),
+ "encryption" => data_get($notifiable, 'smtp_encryption'),
+ "username" => data_get($notifiable, 'smtp_username'),
+ "password" => $password,
+ "timeout" => data_get($notifiable, 'smtp_timeout'),
+ "local_domain" => null,
+ ]);
+ }
}
}
diff --git a/bootstrap/helpers/constants.php b/bootstrap/helpers/constants.php
index 0e42b311e..cea780c24 100644
--- a/bootstrap/helpers/constants.php
+++ b/bootstrap/helpers/constants.php
@@ -9,3 +9,4 @@ const VALID_CRON_STRINGS = [
'monthly' => '0 0 1 * *',
'yearly' => '0 0 1 1 *',
];
+const RESTART_MODE = 'unless-stopped';
diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php
index 7b78abe8a..8ee0765a5 100644
--- a/bootstrap/helpers/docker.php
+++ b/bootstrap/helpers/docker.php
@@ -1,14 +1,27 @@
reject(fn ($line) => empty($line))
->map(fn ($outputLine) => json_decode($outputLine, true, flags: JSON_THROW_ON_ERROR));
}
@@ -44,9 +57,20 @@ function format_docker_envs_to_json($rawOutput)
}
}
-function get_container_status(Server $server, string $container_id, bool $all_data = false, bool $throwError = false)
+function getApplicationContainerStatus(Application $application) {
+ $server = $application->destination->server;
+ $id = $application->id;
+
+ $containers = getCurrentApplicationContainerStatus($server, $id);
+ if ($containers->count() > 0) {
+ $status = data_get($containers[0], 'State', 'exited');
+ return $status;
+ }
+ return 'exited';
+}
+function getContainerStatus(Server $server, string $container_id, bool $all_data = false, bool $throwError = false)
{
- check_server_connection($server);
+ // check_server_connection($server);
$container = instant_remote_process(["docker inspect --format '{{json .}}' {$container_id}"], $server, $throwError);
if (!$container) {
return 'exited';
@@ -58,12 +82,13 @@ function get_container_status(Server $server, string $container_id, bool $all_da
return data_get($container[0], 'State.Status', 'exited');
}
-function generate_container_name(string $uuid, int $pull_request_id = 0)
+function generateApplicationContainerName(string $uuid, int $pull_request_id = 0)
{
- if ($pull_request_id !== 0) {
- return $uuid . '-pr-' . $pull_request_id;
+ $now = now()->format('YmdHis');
+ if ($pull_request_id !== 0 && $pull_request_id !== null) {
+ return $uuid . '-pr-' . $pull_request_id . '-' . $now;
} else {
- return $uuid;
+ return $uuid . '-' . $now;
}
}
function get_port_from_dockerfile($dockerfile): int
diff --git a/bootstrap/helpers/proxy.php b/bootstrap/helpers/proxy.php
index 86c9ca528..164c46e94 100644
--- a/bootstrap/helpers/proxy.php
+++ b/bootstrap/helpers/proxy.php
@@ -32,7 +32,7 @@ function generate_default_proxy_configuration(Server $server)
"traefik" => [
"container_name" => "coolify-proxy",
"image" => "traefik:v2.10",
- "restart" => "always",
+ "restart" => RESTART_MODE,
"extra_hosts" => [
"host.docker.internal:host-gateway",
],
@@ -82,7 +82,7 @@ function generate_default_proxy_configuration(Server $server)
],
],
];
- if (is_dev()) {
+ if (isDev()) {
$config['services']['traefik']['command'][] = "--log.level=debug";
}
return Yaml::dump($config, 4, 2);
diff --git a/bootstrap/helpers/remoteProcess.php b/bootstrap/helpers/remoteProcess.php
index ecc679b3f..86e11bcf3 100644
--- a/bootstrap/helpers/remoteProcess.php
+++ b/bootstrap/helpers/remoteProcess.php
@@ -66,8 +66,6 @@ function get_private_key_for_server(Server $server)
function save_private_key_for_server(Server $server)
{
if (data_get($server, 'privateKey.private_key') === null) {
- $server->settings->is_reachable = false;
- $server->settings->save();
throw new \Exception("Server {$server->name} does not have a private key");
}
$temp_file = "id.root@{$server->ip}";
@@ -159,8 +157,8 @@ function refresh_server_connection(PrivateKey $private_key)
// Delete the old ssh mux file to force a new one to be created
Storage::disk('ssh-mux')->delete($server->muxFilename());
// check if user is authenticated
- if (auth()?->user()?->currentTeam()->id) {
- auth()->user()->currentTeam()->privateKeys = PrivateKey::where('team_id', auth()->user()->currentTeam()->id)->get();
+ if (currentTeam()->id) {
+ currentTeam()->privateKeys = PrivateKey::where('team_id', currentTeam()->id)->get();
}
}
}
diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php
index 4b470cb48..f1670723e 100644
--- a/bootstrap/helpers/shared.php
+++ b/bootstrap/helpers/shared.php
@@ -14,6 +14,7 @@ use Illuminate\Support\Str;
use Nubs\RandomNameGenerator\All;
use Poliander\Cron\CronExpression;
use Visus\Cuid2\Cuid2;
+use phpseclib3\Crypt\RSA;
function application_configuration_dir(): string
{
@@ -35,11 +36,25 @@ function generate_readme_file(string $name, string $updated_at): string
return "Resource name: $name\nLatest Deployment Date: $updated_at";
}
-function is_instance_admin()
+function isInstanceAdmin()
{
- return auth()->user()?->isInstanceAdmin();
+ return auth()?->user()?->isInstanceAdmin() ?? false;
}
+function currentTeam()
+{
+ return auth()?->user()?->currentTeam() ?? null;
+}
+
+function showBoarding(): bool
+{
+ return currentTeam()->show_boarding ?? false;
+}
+function refreshSession(): void
+{
+ $team = currentTeam();
+ session(['currentTeam' => $team]);
+}
function general_error_handler(Throwable | null $err = null, $that = null, $isJson = false, $customErrorMessage = null): mixed
{
try {
@@ -97,7 +112,21 @@ function generate_random_name(): string
$cuid = new Cuid2(7);
return Str::kebab("{$generator->getName()}-$cuid");
}
-
+function generateSSHKey()
+{
+ $key = RSA::createKey();
+ return [
+ 'private' => $key->toString('PKCS1'),
+ 'public' => $key->getPublicKey()->toString('OpenSSH',['comment' => 'coolify-generated-ssh-key'])
+ ];
+}
+function formatPrivateKey(string $privateKey) {
+ $privateKey = trim($privateKey);
+ if (!str_ends_with($privateKey, "\n")) {
+ $privateKey .= "\n";
+ }
+ return $privateKey;
+}
function generate_application_name(string $git_repository, string $git_branch): string
{
$cuid = new Cuid2(7);
@@ -134,7 +163,7 @@ function set_transanctional_email_settings(InstanceSettings | null $settings = n
function base_ip(): string
{
- if (is_dev()) {
+ if (isDev()) {
return "localhost";
}
$settings = InstanceSettings::get();
@@ -159,12 +188,12 @@ function base_url(bool $withPort = true): string
$port = config('app.port');
if ($settings->public_ipv4) {
if ($withPort) {
- if (is_dev()) {
+ if (isDev()) {
return "http://localhost:$port";
}
return "http://$settings->public_ipv4:$port";
}
- if (is_dev()) {
+ if (isDev()) {
return "http://localhost";
}
return "http://$settings->public_ipv4";
@@ -178,7 +207,7 @@ function base_url(bool $withPort = true): string
return url('/');
}
-function is_dev(): bool
+function isDev(): bool
{
return config('app.env') === 'local';
}
@@ -202,8 +231,9 @@ function validate_cron_expression($expression_to_validate): bool
function send_internal_notification(string $message): void
{
try {
+ $baseUrl = base_url(false);
$team = Team::find(0);
- $team->notify(new GeneralNotification('👀 Internal notifications: ' . $message));
+ $team->notify(new GeneralNotification("👀 Internal notifications from {$baseUrl}: " . $message));
} catch (\Throwable $th) {
ray($th->getMessage());
}
diff --git a/bootstrap/helpers/subscriptions.php b/bootstrap/helpers/subscriptions.php
index 90d0947ad..ab266da2c 100644
--- a/bootstrap/helpers/subscriptions.php
+++ b/bootstrap/helpers/subscriptions.php
@@ -1,15 +1,17 @@
user()->id;
- $team_id = auth()->user()->currentTeam()->id ?? null;
+ $team_id = currentTeam()->id ?? null;
$email = auth()->user()->email ?? null;
$name = auth()->user()->name ?? null;
$url = "https://store.coollabs.io/checkout/buy/$checkout_id?";
@@ -30,53 +32,98 @@ function getSubscriptionLink($type)
function getPaymentLink()
{
- return auth()->user()->currentTeam()->subscription->lemon_update_payment_menthod_url;
+ return currentTeam()->subscription->lemon_update_payment_menthod_url;
}
function getRenewDate()
{
- return Carbon::parse(auth()->user()->currentTeam()->subscription->lemon_renews_at)->format('Y-M-d H:i:s');
+ return Carbon::parse(currentTeam()->subscription->lemon_renews_at)->format('Y-M-d H:i:s');
}
function getEndDate()
{
- return Carbon::parse(auth()->user()->currentTeam()->subscription->lemon_renews_at)->format('Y-M-d H:i:s');
+ return Carbon::parse(currentTeam()->subscription->lemon_renews_at)->format('Y-M-d H:i:s');
}
-function is_subscription_active()
+function isSubscriptionActive()
{
- $team = auth()->user()?->currentTeam();
-
+ $team = currentTeam();
if (!$team) {
return false;
}
- if (is_instance_admin()) {
- return true;
- }
$subscription = $team?->subscription;
if (!$subscription) {
return false;
}
- $is_active = $subscription->lemon_status === 'active';
+ if (config('subscription.provider') === 'lemon') {
+ return $subscription->lemon_status === 'active';
+ }
+ if (config('subscription.provider') === 'stripe') {
+ return $subscription->stripe_invoice_paid === true && $subscription->stripe_cancel_at_period_end === false;
+ }
+ return false;
+ // if (config('subscription.provider') === 'paddle') {
+ // return $subscription->paddle_status === 'active';
+ // }
- return $is_active;
}
-function is_subscription_in_grace_period()
+function isSubscriptionOnGracePeriod()
{
- $team = auth()->user()?->currentTeam();
+
+ $team = currentTeam();
if (!$team) {
return false;
}
- if (is_instance_admin()) {
- return true;
- }
$subscription = $team?->subscription;
if (!$subscription) {
return false;
}
- $is_still_grace_period = $subscription->lemon_ends_at &&
- Carbon::parse($subscription->lemon_ends_at) > Carbon::now();
-
- return $is_still_grace_period;
+ if (config('subscription.provider') === 'lemon') {
+ $is_still_grace_period = $subscription->lemon_ends_at &&
+ Carbon::parse($subscription->lemon_ends_at) > Carbon::now();
+ return $is_still_grace_period;
+ }
+ if (config('subscription.provider') === 'stripe') {
+ return $subscription->stripe_cancel_at_period_end;
+ }
+ return false;
+}
+function subscriptionProvider()
+{
+ return config('subscription.provider');
+}
+function getStripeCustomerPortalSession(Team $team)
+{
+ Stripe::setApiKey(config('subscription.stripe_api_key'));
+ $return_url = route('team.show');
+ $stripe_customer_id = $team->subscription->stripe_customer_id;
+ $session = \Stripe\BillingPortal\Session::create([
+ 'customer' => $stripe_customer_id,
+ 'return_url' => $return_url,
+ ]);
+ return $session;
+}
+function allowedPathsForUnsubscribedAccounts()
+{
+ return [
+ 'subscription',
+ 'login',
+ 'register',
+ 'waitlist',
+ 'force-password-reset',
+ 'logout',
+ 'livewire/message/force-password-reset',
+ 'livewire/message/check-license',
+ 'livewire/message/switch-team',
+ 'livewire/message/subscription.pricing-plans'
+ ];
+}
+function allowedPathsForBoardingAccounts()
+{
+ return [
+ ...allowedPathsForUnsubscribedAccounts(),
+ 'boarding',
+ 'livewire/message/boarding',
+ ];
}
diff --git a/composer.json b/composer.json
index 7fcdd9e26..bcb74242b 100644
--- a/composer.json
+++ b/composer.json
@@ -23,13 +23,16 @@
"livewire/livewire": "^v2.12.3",
"masmerise/livewire-toaster": "^1.2",
"nubs/random-name-generator": "^2.2",
+ "phpseclib/phpseclib": "~3.0",
"poliander/cron": "^3.0",
+ "resend/resend-laravel": "^0.5.0",
"sentry/sentry-laravel": "^3.4",
"spatie/laravel-activitylog": "^4.7.3",
"spatie/laravel-data": "^3.4.3",
"spatie/laravel-ray": "^1.32.4",
"spatie/laravel-schemaless-attributes": "^2.4",
"spatie/url": "^2.2",
+ "stripe/stripe-php": "^12.0",
"symfony/yaml": "^6.2",
"visus/cuid2": "^2.0.0"
},
diff --git a/composer.lock b/composer.lock
index 45671727a..871f9f577 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "0c023bed552776ee5e4eeda1ff0a5e19",
+ "content-hash": "da14dce99d76abcaaa6393166eda049a",
"packages": [
{
"name": "aws/aws-crt-php",
@@ -62,16 +62,16 @@
},
{
"name": "aws/aws-sdk-php",
- "version": "3.269.0",
+ "version": "3.279.6",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
- "reference": "6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78"
+ "reference": "e83376ac8e88ed99c3d75d1309a2cb1148d31fd9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78",
- "reference": "6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78",
+ "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/e83376ac8e88ed99c3d75d1309a2cb1148d31fd9",
+ "reference": "e83376ac8e88ed99c3d75d1309a2cb1148d31fd9",
"shasum": ""
},
"require": {
@@ -80,10 +80,11 @@
"ext-pcre": "*",
"ext-simplexml": "*",
"guzzlehttp/guzzle": "^6.5.8 || ^7.4.5",
- "guzzlehttp/promises": "^1.4.0",
+ "guzzlehttp/promises": "^1.4.0 || ^2.0",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"mtdowling/jmespath.php": "^2.6",
- "php": ">=5.5"
+ "php": ">=7.2.5",
+ "psr/http-message": "^1.0 || ^2.0"
},
"require-dev": {
"andrewsville/php-token-reflection": "^1.4",
@@ -98,9 +99,8 @@
"ext-sockets": "*",
"nette/neon": "^2.3",
"paragonie/random_compat": ">= 2",
- "phpunit/phpunit": "^4.8.35 || ^5.6.3 || ^9.5",
+ "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5",
"psr/cache": "^1.0",
- "psr/http-message": "^1.0",
"psr/simple-cache": "^1.0",
"sebastian/comparator": "^1.2.3 || ^4.0",
"yoast/phpunit-polyfills": "^1.0"
@@ -151,9 +151,9 @@
"support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues",
- "source": "https://github.com/aws/aws-sdk-php/tree/3.269.0"
+ "source": "https://github.com/aws/aws-sdk-php/tree/3.279.6"
},
- "time": "2023-04-26T18:21:04+00:00"
+ "time": "2023-08-24T18:07:59+00:00"
},
{
"name": "bacon/bacon-qr-code",
@@ -603,16 +603,16 @@
},
{
"name": "doctrine/dbal",
- "version": "3.6.5",
+ "version": "3.6.6",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
- "reference": "96d5a70fd91efdcec81fc46316efc5bf3da17ddf"
+ "reference": "63646ffd71d1676d2f747f871be31b7e921c7864"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/dbal/zipball/96d5a70fd91efdcec81fc46316efc5bf3da17ddf",
- "reference": "96d5a70fd91efdcec81fc46316efc5bf3da17ddf",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/63646ffd71d1676d2f747f871be31b7e921c7864",
+ "reference": "63646ffd71d1676d2f747f871be31b7e921c7864",
"shasum": ""
},
"require": {
@@ -628,10 +628,11 @@
"doctrine/coding-standard": "12.0.0",
"fig/log-test": "^1",
"jetbrains/phpstorm-stubs": "2023.1",
- "phpstan/phpstan": "1.10.21",
+ "phpstan/phpstan": "1.10.29",
"phpstan/phpstan-strict-rules": "^1.5",
"phpunit/phpunit": "9.6.9",
"psalm/plugin-phpunit": "0.18.4",
+ "slevomat/coding-standard": "8.13.1",
"squizlabs/php_codesniffer": "3.7.2",
"symfony/cache": "^5.4|^6.0",
"symfony/console": "^4.4|^5.4|^6.0",
@@ -695,7 +696,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
- "source": "https://github.com/doctrine/dbal/tree/3.6.5"
+ "source": "https://github.com/doctrine/dbal/tree/3.6.6"
},
"funding": [
{
@@ -711,7 +712,7 @@
"type": "tidelift"
}
],
- "time": "2023-07-17T09:15:50+00:00"
+ "time": "2023-08-17T05:38:17+00:00"
},
{
"name": "doctrine/deprecations",
@@ -1021,16 +1022,16 @@
},
{
"name": "dragonmantank/cron-expression",
- "version": "v3.3.2",
+ "version": "v3.3.3",
"source": {
"type": "git",
"url": "https://github.com/dragonmantank/cron-expression.git",
- "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8"
+ "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8",
- "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8",
+ "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
+ "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
"shasum": ""
},
"require": {
@@ -1070,7 +1071,7 @@
],
"support": {
"issues": "https://github.com/dragonmantank/cron-expression/issues",
- "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2"
+ "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3"
},
"funding": [
{
@@ -1078,7 +1079,7 @@
"type": "github"
}
],
- "time": "2022-09-10T18:51:20+00:00"
+ "time": "2023-08-10T19:36:49+00:00"
},
{
"name": "egulias/email-validator",
@@ -1408,29 +1409,33 @@
},
{
"name": "guzzlehttp/promises",
- "version": "1.5.3",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
- "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e"
+ "reference": "111166291a0f8130081195ac4556a5587d7f1b5d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e",
- "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d",
+ "reference": "111166291a0f8130081195ac4556a5587d7f1b5d",
"shasum": ""
},
"require": {
- "php": ">=5.5"
+ "php": "^7.2.5 || ^8.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "^4.4 || ^5.1"
+ "bamarni/composer-bin-plugin": "^1.8.1",
+ "phpunit/phpunit": "^8.5.29 || ^9.5.23"
},
"type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
"autoload": {
- "files": [
- "src/functions_include.php"
- ],
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
}
@@ -1467,7 +1472,7 @@
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
- "source": "https://github.com/guzzle/promises/tree/1.5.3"
+ "source": "https://github.com/guzzle/promises/tree/2.0.1"
},
"funding": [
{
@@ -1483,7 +1488,7 @@
"type": "tidelift"
}
],
- "time": "2023-05-21T12:31:43+00:00"
+ "time": "2023-08-03T15:11:55+00:00"
},
{
"name": "guzzlehttp/psr7",
@@ -1804,16 +1809,16 @@
},
{
"name": "laravel/fortify",
- "version": "v1.17.4",
+ "version": "v1.17.5",
"source": {
"type": "git",
"url": "https://github.com/laravel/fortify.git",
- "reference": "110dd0d09b70461d651218240120e24ba8d8cbe1"
+ "reference": "3d3ad9aaa46f686a5fe46a0af2ba907702019451"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/fortify/zipball/110dd0d09b70461d651218240120e24ba8d8cbe1",
- "reference": "110dd0d09b70461d651218240120e24ba8d8cbe1",
+ "url": "https://api.github.com/repos/laravel/fortify/zipball/3d3ad9aaa46f686a5fe46a0af2ba907702019451",
+ "reference": "3d3ad9aaa46f686a5fe46a0af2ba907702019451",
"shasum": ""
},
"require": {
@@ -1864,20 +1869,20 @@
"issues": "https://github.com/laravel/fortify/issues",
"source": "https://github.com/laravel/fortify"
},
- "time": "2023-06-18T09:17:00+00:00"
+ "time": "2023-08-02T13:57:32+00:00"
},
{
"name": "laravel/framework",
- "version": "v10.18.0",
+ "version": "v10.20.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "9d41928900f7ecf409627a7d06c0a4dfecff2ea7"
+ "reference": "a655dca3fbe83897e22adff652b1878ba352d041"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/9d41928900f7ecf409627a7d06c0a4dfecff2ea7",
- "reference": "9d41928900f7ecf409627a7d06c0a4dfecff2ea7",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/a655dca3fbe83897e22adff652b1878ba352d041",
+ "reference": "a655dca3fbe83897e22adff652b1878ba352d041",
"shasum": ""
},
"require": {
@@ -2064,7 +2069,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2023-08-08T14:30:38+00:00"
+ "time": "2023-08-22T13:37:09+00:00"
},
{
"name": "laravel/horizon",
@@ -2146,16 +2151,16 @@
},
{
"name": "laravel/prompts",
- "version": "v0.1.4",
+ "version": "v0.1.6",
"source": {
"type": "git",
"url": "https://github.com/laravel/prompts.git",
- "reference": "1b3ab520a75eddefcda99f49fb551d231769b1fa"
+ "reference": "b514c5620e1b3b61221b0024dc88def26d9654f4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/prompts/zipball/1b3ab520a75eddefcda99f49fb551d231769b1fa",
- "reference": "1b3ab520a75eddefcda99f49fb551d231769b1fa",
+ "url": "https://api.github.com/repos/laravel/prompts/zipball/b514c5620e1b3b61221b0024dc88def26d9654f4",
+ "reference": "b514c5620e1b3b61221b0024dc88def26d9654f4",
"shasum": ""
},
"require": {
@@ -2188,22 +2193,22 @@
],
"support": {
"issues": "https://github.com/laravel/prompts/issues",
- "source": "https://github.com/laravel/prompts/tree/v0.1.4"
+ "source": "https://github.com/laravel/prompts/tree/v0.1.6"
},
- "time": "2023-08-07T13:14:59+00:00"
+ "time": "2023-08-18T13:32:23+00:00"
},
{
"name": "laravel/sanctum",
- "version": "v3.2.5",
+ "version": "v3.2.6",
"source": {
"type": "git",
"url": "https://github.com/laravel/sanctum.git",
- "reference": "8ebda85d59d3c414863a7f4d816ef8302faad876"
+ "reference": "217e8a2bc5aa6a827ced97fcb76504029d3115d7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/sanctum/zipball/8ebda85d59d3c414863a7f4d816ef8302faad876",
- "reference": "8ebda85d59d3c414863a7f4d816ef8302faad876",
+ "url": "https://api.github.com/repos/laravel/sanctum/zipball/217e8a2bc5aa6a827ced97fcb76504029d3115d7",
+ "reference": "217e8a2bc5aa6a827ced97fcb76504029d3115d7",
"shasum": ""
},
"require": {
@@ -2216,9 +2221,9 @@
},
"require-dev": {
"mockery/mockery": "^1.0",
- "orchestra/testbench": "^7.0|^8.0",
+ "orchestra/testbench": "^7.28.2|^8.8.3",
"phpstan/phpstan": "^1.10",
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^9.6"
},
"type": "library",
"extra": {
@@ -2256,7 +2261,7 @@
"issues": "https://github.com/laravel/sanctum/issues",
"source": "https://github.com/laravel/sanctum"
},
- "time": "2023-05-01T19:39:51+00:00"
+ "time": "2023-08-22T13:21:11+00:00"
},
{
"name": "laravel/serializable-closure",
@@ -2983,16 +2988,16 @@
},
{
"name": "livewire/livewire",
- "version": "v2.12.5",
+ "version": "v2.12.6",
"source": {
"type": "git",
"url": "https://github.com/livewire/livewire.git",
- "reference": "96a249f5ab51d8377817d802f91d1e440869c1d6"
+ "reference": "7d3a57b3193299cf1a0639a3935c696f4da2cf92"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/livewire/livewire/zipball/96a249f5ab51d8377817d802f91d1e440869c1d6",
- "reference": "96a249f5ab51d8377817d802f91d1e440869c1d6",
+ "url": "https://api.github.com/repos/livewire/livewire/zipball/7d3a57b3193299cf1a0639a3935c696f4da2cf92",
+ "reference": "7d3a57b3193299cf1a0639a3935c696f4da2cf92",
"shasum": ""
},
"require": {
@@ -3044,7 +3049,7 @@
"description": "A front-end framework for Laravel.",
"support": {
"issues": "https://github.com/livewire/livewire/issues",
- "source": "https://github.com/livewire/livewire/tree/v2.12.5"
+ "source": "https://github.com/livewire/livewire/tree/v2.12.6"
},
"funding": [
{
@@ -3052,7 +3057,7 @@
"type": "github"
}
],
- "time": "2023-08-02T06:31:31+00:00"
+ "time": "2023-08-11T04:02:34+00:00"
},
{
"name": "masmerise/livewire-toaster",
@@ -3286,25 +3291,29 @@
},
{
"name": "nesbot/carbon",
- "version": "2.68.1",
+ "version": "2.69.0",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
- "reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da"
+ "reference": "4308217830e4ca445583a37d1bf4aff4153fa81c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4f991ed2a403c85efbc4f23eb4030063fdbe01da",
- "reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da",
+ "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4308217830e4ca445583a37d1bf4aff4153fa81c",
+ "reference": "4308217830e4ca445583a37d1bf4aff4153fa81c",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.1.8 || ^8.0",
+ "psr/clock": "^1.0",
"symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php80": "^1.16",
"symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0"
},
+ "provide": {
+ "psr/clock-implementation": "1.0"
+ },
"require-dev": {
"doctrine/dbal": "^2.0 || ^3.1.4",
"doctrine/orm": "^2.7",
@@ -3384,7 +3393,7 @@
"type": "tidelift"
}
],
- "time": "2023-06-20T18:29:04+00:00"
+ "time": "2023-08-03T09:00:52+00:00"
},
{
"name": "nette/schema",
@@ -3537,16 +3546,16 @@
},
{
"name": "nikic/php-parser",
- "version": "v4.16.0",
+ "version": "v4.17.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "19526a33fb561ef417e822e85f08a00db4059c17"
+ "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17",
- "reference": "19526a33fb561ef417e822e85f08a00db4059c17",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
+ "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
"shasum": ""
},
"require": {
@@ -3587,9 +3596,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1"
},
- "time": "2023-06-25T14:52:30+00:00"
+ "time": "2023-08-13T19:53:39+00:00"
},
{
"name": "nubs/random-name-generator",
@@ -3875,6 +3884,56 @@
},
"time": "2022-06-14T06:56:20+00:00"
},
+ {
+ "name": "paragonie/random_compat",
+ "version": "v9.99.100",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/random_compat.git",
+ "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a",
+ "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">= 7"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*|5.*",
+ "vimeo/psalm": "^1"
+ },
+ "suggest": {
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ },
+ "type": "library",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com"
+ }
+ ],
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "keywords": [
+ "csprng",
+ "polyfill",
+ "pseudorandom",
+ "random"
+ ],
+ "support": {
+ "email": "info@paragonie.com",
+ "issues": "https://github.com/paragonie/random_compat/issues",
+ "source": "https://github.com/paragonie/random_compat"
+ },
+ "time": "2020-10-15T08:29:30+00:00"
+ },
{
"name": "php-http/client-common",
"version": "2.7.0",
@@ -4315,16 +4374,16 @@
},
{
"name": "phpdocumentor/type-resolver",
- "version": "1.7.2",
+ "version": "1.7.3",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
- "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d"
+ "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b2fe4d22a5426f38e014855322200b97b5362c0d",
- "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d",
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419",
+ "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419",
"shasum": ""
},
"require": {
@@ -4367,9 +4426,9 @@
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
- "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.2"
+ "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.3"
},
- "time": "2023-05-30T18:13:47+00:00"
+ "time": "2023-08-12T11:01:26+00:00"
},
{
"name": "phpoption/phpoption",
@@ -4446,6 +4505,116 @@
],
"time": "2023-02-25T19:38:58+00:00"
},
+ {
+ "name": "phpseclib/phpseclib",
+ "version": "3.0.21",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpseclib/phpseclib.git",
+ "reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/4580645d3fc05c189024eb3b834c6c1e4f0f30a1",
+ "reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1",
+ "shasum": ""
+ },
+ "require": {
+ "paragonie/constant_time_encoding": "^1|^2",
+ "paragonie/random_compat": "^1.4|^2.0|^9.99.99",
+ "php": ">=5.6.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "*"
+ },
+ "suggest": {
+ "ext-dom": "Install the DOM extension to load XML formatted public keys.",
+ "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
+ "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
+ "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
+ "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "phpseclib/bootstrap.php"
+ ],
+ "psr-4": {
+ "phpseclib3\\": "phpseclib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jim Wigginton",
+ "email": "terrafrost@php.net",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Patrick Monnerat",
+ "email": "pm@datasphere.ch",
+ "role": "Developer"
+ },
+ {
+ "name": "Andreas Fischer",
+ "email": "bantu@phpbb.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Hans-Jürgen Petrich",
+ "email": "petrich@tronic-media.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Graham Campbell",
+ "email": "graham@alt-three.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
+ "homepage": "http://phpseclib.sourceforge.net",
+ "keywords": [
+ "BigInteger",
+ "aes",
+ "asn.1",
+ "asn1",
+ "blowfish",
+ "crypto",
+ "cryptography",
+ "encryption",
+ "rsa",
+ "security",
+ "sftp",
+ "signature",
+ "signing",
+ "ssh",
+ "twofish",
+ "x.509",
+ "x509"
+ ],
+ "support": {
+ "issues": "https://github.com/phpseclib/phpseclib/issues",
+ "source": "https://github.com/phpseclib/phpseclib/tree/3.0.21"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/terrafrost",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/phpseclib",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-07-09T15:24:48+00:00"
+ },
{
"name": "phpstan/phpdoc-parser",
"version": "1.23.1",
@@ -5404,6 +5573,131 @@
],
"time": "2023-04-15T23:01:58+00:00"
},
+ {
+ "name": "resend/resend-laravel",
+ "version": "v0.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/resendlabs/resend-laravel.git",
+ "reference": "e598d1e25e49a7aa4c35f653d1d828f69ee4fc1d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/resendlabs/resend-laravel/zipball/e598d1e25e49a7aa4c35f653d1d828f69ee4fc1d",
+ "reference": "e598d1e25e49a7aa4c35f653d1d828f69ee4fc1d",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/support": "^9.21|^10.0",
+ "php": "^8.1",
+ "resend/resend-php": "^0.7.1",
+ "symfony/mailer": "^6.2"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.14",
+ "mockery/mockery": "^1.5",
+ "orchestra/testbench": "^7.22|^8.0",
+ "pestphp/pest": "^1.22"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Resend\\Laravel\\ResendServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Resend\\Laravel\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Resend and contributors",
+ "homepage": "https://github.com/resendlabs/resend-laravel/contributors"
+ }
+ ],
+ "description": "Resend for Laravel",
+ "homepage": "https://resend.com/",
+ "keywords": [
+ "api",
+ "client",
+ "laravel",
+ "php",
+ "resend",
+ "sdk"
+ ],
+ "support": {
+ "issues": "https://github.com/resendlabs/resend-laravel/issues",
+ "source": "https://github.com/resendlabs/resend-laravel/tree/v0.5.0"
+ },
+ "time": "2023-07-15T17:56:14+00:00"
+ },
+ {
+ "name": "resend/resend-php",
+ "version": "v0.7.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/resendlabs/resend-php.git",
+ "reference": "3b2e2eae0ded191b2ea67d0ee2e87cdc442316a0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/resendlabs/resend-php/zipball/3b2e2eae0ded191b2ea67d0ee2e87cdc442316a0",
+ "reference": "3b2e2eae0ded191b2ea67d0ee2e87cdc442316a0",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "^7.5",
+ "php": "^8.1.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.13",
+ "pestphp/pest": "^2.0",
+ "pestphp/pest-plugin-mock": "^2.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/Resend.php"
+ ],
+ "psr-4": {
+ "Resend\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Resend and contributors",
+ "homepage": "https://github.com/resendlabs/resend-php/contributors"
+ }
+ ],
+ "description": "Resend PHP library.",
+ "homepage": "https://resend.com/",
+ "keywords": [
+ "api",
+ "client",
+ "php",
+ "resend",
+ "sdk"
+ ],
+ "support": {
+ "issues": "https://github.com/resendlabs/resend-php/issues",
+ "source": "https://github.com/resendlabs/resend-php/tree/v0.7.1"
+ },
+ "time": "2023-07-12T07:08:27+00:00"
+ },
{
"name": "sentry/sdk",
"version": "3.5.0",
@@ -5807,16 +6101,16 @@
},
{
"name": "spatie/laravel-data",
- "version": "3.8.0",
+ "version": "3.8.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-data.git",
- "reference": "0de2ecfc8fa98bcca6e2e041d22de8c74a19c45b"
+ "reference": "7ead3d8f761846185a94d06e584bfe17e43b9239"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/laravel-data/zipball/0de2ecfc8fa98bcca6e2e041d22de8c74a19c45b",
- "reference": "0de2ecfc8fa98bcca6e2e041d22de8c74a19c45b",
+ "url": "https://api.github.com/repos/spatie/laravel-data/zipball/7ead3d8f761846185a94d06e584bfe17e43b9239",
+ "reference": "7ead3d8f761846185a94d06e584bfe17e43b9239",
"shasum": ""
},
"require": {
@@ -5878,7 +6172,7 @@
],
"support": {
"issues": "https://github.com/spatie/laravel-data/issues",
- "source": "https://github.com/spatie/laravel-data/tree/3.8.0"
+ "source": "https://github.com/spatie/laravel-data/tree/3.8.1"
},
"funding": [
{
@@ -5886,20 +6180,20 @@
"type": "github"
}
],
- "time": "2023-08-09T14:09:06+00:00"
+ "time": "2023-08-11T11:59:07+00:00"
},
{
"name": "spatie/laravel-package-tools",
- "version": "1.16.0",
+ "version": "1.16.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-package-tools.git",
- "reference": "38fe533e93f86a1b2fb1000bf7df09c4748e6458"
+ "reference": "cc7c991555a37f9fa6b814aa03af73f88026a83d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/38fe533e93f86a1b2fb1000bf7df09c4748e6458",
- "reference": "38fe533e93f86a1b2fb1000bf7df09c4748e6458",
+ "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/cc7c991555a37f9fa6b814aa03af73f88026a83d",
+ "reference": "cc7c991555a37f9fa6b814aa03af73f88026a83d",
"shasum": ""
},
"require": {
@@ -5938,7 +6232,7 @@
],
"support": {
"issues": "https://github.com/spatie/laravel-package-tools/issues",
- "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.0"
+ "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.1"
},
"funding": [
{
@@ -5946,7 +6240,7 @@
"type": "github"
}
],
- "time": "2023-08-09T14:08:04+00:00"
+ "time": "2023-08-23T09:04:39+00:00"
},
{
"name": "spatie/laravel-ray",
@@ -6297,6 +6591,67 @@
],
"time": "2023-04-27T11:07:22+00:00"
},
+ {
+ "name": "stripe/stripe-php",
+ "version": "v12.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/stripe/stripe-php.git",
+ "reference": "732996be0714154716f19f73f956d77bafc99334"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/stripe/stripe-php/zipball/732996be0714154716f19f73f956d77bafc99334",
+ "reference": "732996be0714154716f19f73f956d77bafc99334",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "ext-json": "*",
+ "ext-mbstring": "*",
+ "php": ">=5.6.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "3.5.0",
+ "php-coveralls/php-coveralls": "^2.5",
+ "phpstan/phpstan": "^1.2",
+ "phpunit/phpunit": "^5.7 || ^9.0",
+ "squizlabs/php_codesniffer": "^3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Stripe\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Stripe and contributors",
+ "homepage": "https://github.com/stripe/stripe-php/contributors"
+ }
+ ],
+ "description": "Stripe PHP Library",
+ "homepage": "https://stripe.com/",
+ "keywords": [
+ "api",
+ "payment processing",
+ "stripe"
+ ],
+ "support": {
+ "issues": "https://github.com/stripe/stripe-php/issues",
+ "source": "https://github.com/stripe/stripe-php/tree/v12.0.0"
+ },
+ "time": "2023-08-18T18:55:28+00:00"
+ },
{
"name": "symfony/console",
"version": "v6.3.2",
@@ -10049,16 +10404,16 @@
},
{
"name": "laravel/pint",
- "version": "v1.10.6",
+ "version": "v1.11.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
- "reference": "d1915b6ecc6406c00472c6b9ae75b46aa153bbb2"
+ "reference": "88e835bf922b94017778bde89ef8f215e1ea40db"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/pint/zipball/d1915b6ecc6406c00472c6b9ae75b46aa153bbb2",
- "reference": "d1915b6ecc6406c00472c6b9ae75b46aa153bbb2",
+ "url": "https://api.github.com/repos/laravel/pint/zipball/88e835bf922b94017778bde89ef8f215e1ea40db",
+ "reference": "88e835bf922b94017778bde89ef8f215e1ea40db",
"shasum": ""
},
"require": {
@@ -10111,7 +10466,7 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
- "time": "2023-08-08T15:17:16+00:00"
+ "time": "2023-08-15T15:30:00+00:00"
},
{
"name": "mockery/mockery",
@@ -10352,16 +10707,16 @@
},
{
"name": "pestphp/pest",
- "version": "v2.13.0",
+ "version": "v2.16.0",
"source": {
"type": "git",
"url": "https://github.com/pestphp/pest.git",
- "reference": "47f2ae32c14cd3f15520f5a12a3c36fdec25a2ee"
+ "reference": "cbd6a650576714c673dbb0575989663f7f5c8b6d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pestphp/pest/zipball/47f2ae32c14cd3f15520f5a12a3c36fdec25a2ee",
- "reference": "47f2ae32c14cd3f15520f5a12a3c36fdec25a2ee",
+ "url": "https://api.github.com/repos/pestphp/pest/zipball/cbd6a650576714c673dbb0575989663f7f5c8b6d",
+ "reference": "cbd6a650576714c673dbb0575989663f7f5c8b6d",
"shasum": ""
},
"require": {
@@ -10369,16 +10724,16 @@
"nunomaduro/collision": "^7.8.1",
"nunomaduro/termwind": "^1.15.1",
"pestphp/pest-plugin": "^2.0.1",
- "pestphp/pest-plugin-arch": "^2.2.3",
+ "pestphp/pest-plugin-arch": "^2.3.1",
"php": "^8.1.0",
- "phpunit/phpunit": "^10.3.1"
+ "phpunit/phpunit": "^10.3.2"
},
"conflict": {
- "phpunit/phpunit": ">10.3.1",
+ "phpunit/phpunit": ">10.3.2",
"webmozart/assert": "<1.11.0"
},
"require-dev": {
- "pestphp/pest-dev-tools": "^2.14.0",
+ "pestphp/pest-dev-tools": "^2.16.0",
"pestphp/pest-plugin-type-coverage": "^2.0.0",
"symfony/process": "^6.3.2"
},
@@ -10438,7 +10793,7 @@
],
"support": {
"issues": "https://github.com/pestphp/pest/issues",
- "source": "https://github.com/pestphp/pest/tree/v2.13.0"
+ "source": "https://github.com/pestphp/pest/tree/v2.16.0"
},
"funding": [
{
@@ -10450,33 +10805,34 @@
"type": "github"
}
],
- "time": "2023-08-09T11:14:39+00:00"
+ "time": "2023-08-21T08:42:07+00:00"
},
{
"name": "pestphp/pest-plugin",
- "version": "v2.0.1",
+ "version": "v2.1.1",
"source": {
"type": "git",
"url": "https://github.com/pestphp/pest-plugin.git",
- "reference": "e3a3da262b73bdcbf3fad4dc9846c3c4921f2147"
+ "reference": "e05d2859e08c2567ee38ce8b005d044e72648c0b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/e3a3da262b73bdcbf3fad4dc9846c3c4921f2147",
- "reference": "e3a3da262b73bdcbf3fad4dc9846c3c4921f2147",
+ "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/e05d2859e08c2567ee38ce8b005d044e72648c0b",
+ "reference": "e05d2859e08c2567ee38ce8b005d044e72648c0b",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.0.0",
+ "composer-runtime-api": "^2.2.2",
"php": "^8.1"
},
"conflict": {
"pestphp/pest": "<2.2.3"
},
"require-dev": {
- "composer/composer": "^2.5.5",
- "pestphp/pest": "^2.2.3",
- "pestphp/pest-dev-tools": "^2.5.0"
+ "composer/composer": "^2.5.8",
+ "pestphp/pest": "^2.16.0",
+ "pestphp/pest-dev-tools": "^2.16.0"
},
"type": "composer-plugin",
"extra": {
@@ -10503,7 +10859,7 @@
"unit"
],
"support": {
- "source": "https://github.com/pestphp/pest-plugin/tree/v2.0.1"
+ "source": "https://github.com/pestphp/pest-plugin/tree/v2.1.1"
},
"funding": [
{
@@ -10519,31 +10875,31 @@
"type": "patreon"
}
],
- "time": "2023-03-24T11:21:05+00:00"
+ "time": "2023-08-22T08:40:06+00:00"
},
{
"name": "pestphp/pest-plugin-arch",
- "version": "v2.2.3",
+ "version": "v2.3.3",
"source": {
"type": "git",
"url": "https://github.com/pestphp/pest-plugin-arch.git",
- "reference": "f44834b728b44028fb7d99c4e3efc88b699728a8"
+ "reference": "b758990e83f89daba3c45672398579cf8692213f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/f44834b728b44028fb7d99c4e3efc88b699728a8",
- "reference": "f44834b728b44028fb7d99c4e3efc88b699728a8",
+ "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/b758990e83f89daba3c45672398579cf8692213f",
+ "reference": "b758990e83f89daba3c45672398579cf8692213f",
"shasum": ""
},
"require": {
- "nunomaduro/collision": "^7.7.0",
+ "nunomaduro/collision": "^7.8.1",
"pestphp/pest-plugin": "^2.0.1",
"php": "^8.1",
- "ta-tikoma/phpunit-architecture-test": "^0.7.3"
+ "ta-tikoma/phpunit-architecture-test": "^0.7.4"
},
"require-dev": {
- "pestphp/pest": "^2.9.4",
- "pestphp/pest-dev-tools": "^2.12.0"
+ "pestphp/pest": "^2.16.0",
+ "pestphp/pest-dev-tools": "^2.16.0"
},
"type": "library",
"autoload": {
@@ -10571,7 +10927,7 @@
"unit"
],
"support": {
- "source": "https://github.com/pestphp/pest-plugin-arch/tree/v2.2.3"
+ "source": "https://github.com/pestphp/pest-plugin-arch/tree/v2.3.3"
},
"funding": [
{
@@ -10583,7 +10939,7 @@
"type": "github"
}
],
- "time": "2023-07-24T18:04:14+00:00"
+ "time": "2023-08-21T16:06:30+00:00"
},
{
"name": "phar-io/manifest",
@@ -10821,16 +11177,16 @@
},
{
"name": "phpstan/phpstan",
- "version": "1.10.28",
+ "version": "1.10.32",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "e4545b55904ebef470423d3ddddb74fa7325497a"
+ "reference": "c47e47d3ab03137c0e121e77c4d2cb58672f6d44"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e4545b55904ebef470423d3ddddb74fa7325497a",
- "reference": "e4545b55904ebef470423d3ddddb74fa7325497a",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c47e47d3ab03137c0e121e77c4d2cb58672f6d44",
+ "reference": "c47e47d3ab03137c0e121e77c4d2cb58672f6d44",
"shasum": ""
},
"require": {
@@ -10879,7 +11235,7 @@
"type": "tidelift"
}
],
- "time": "2023-08-08T12:33:42+00:00"
+ "time": "2023-08-24T21:54:50+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -11203,16 +11559,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "10.3.1",
+ "version": "10.3.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "d442ce7c4104d5683c12e67e4dcb5058159e9804"
+ "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d442ce7c4104d5683c12e67e4dcb5058159e9804",
- "reference": "d442ce7c4104d5683c12e67e4dcb5058159e9804",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0dafb1175c366dd274eaa9a625e914451506bcd1",
+ "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1",
"shasum": ""
},
"require": {
@@ -11284,7 +11640,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.1"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.2"
},
"funding": [
{
@@ -11300,7 +11656,7 @@
"type": "tidelift"
}
],
- "time": "2023-08-04T06:48:08+00:00"
+ "time": "2023-08-15T05:34:23+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -11471,16 +11827,16 @@
},
{
"name": "sebastian/comparator",
- "version": "5.0.0",
+ "version": "5.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c"
+ "reference": "2db5010a484d53ebf536087a70b4a5423c102372"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/72f01e6586e0caf6af81297897bd112eb7e9627c",
- "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372",
+ "reference": "2db5010a484d53ebf536087a70b4a5423c102372",
"shasum": ""
},
"require": {
@@ -11491,7 +11847,7 @@
"sebastian/exporter": "^5.0"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^10.3"
},
"type": "library",
"extra": {
@@ -11535,7 +11891,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
- "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.0"
+ "security": "https://github.com/sebastianbergmann/comparator/security/policy",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1"
},
"funding": [
{
@@ -11543,7 +11900,7 @@
"type": "github"
}
],
- "time": "2023-02-03T07:07:16+00:00"
+ "time": "2023-08-14T13:18:12+00:00"
},
{
"name": "sebastian/complexity",
@@ -12330,16 +12687,16 @@
},
{
"name": "spatie/ignition",
- "version": "1.9.0",
+ "version": "1.10.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/ignition.git",
- "reference": "de24ff1e01814d5043bd6eb4ab36a5a852a04973"
+ "reference": "d92b9a081e99261179b63a858c7a4b01541e7dd1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/ignition/zipball/de24ff1e01814d5043bd6eb4ab36a5a852a04973",
- "reference": "de24ff1e01814d5043bd6eb4ab36a5a852a04973",
+ "url": "https://api.github.com/repos/spatie/ignition/zipball/d92b9a081e99261179b63a858c7a4b01541e7dd1",
+ "reference": "d92b9a081e99261179b63a858c7a4b01541e7dd1",
"shasum": ""
},
"require": {
@@ -12409,20 +12766,20 @@
"type": "github"
}
],
- "time": "2023-06-28T13:24:59+00:00"
+ "time": "2023-08-21T15:06:37+00:00"
},
{
"name": "spatie/laravel-ignition",
- "version": "2.2.0",
+ "version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-ignition.git",
- "reference": "dd15fbe82ef5392798941efae93c49395a87d943"
+ "reference": "4ed813d16edb5a1ab0d7f4b1d116c37ee8cdf3c0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/dd15fbe82ef5392798941efae93c49395a87d943",
- "reference": "dd15fbe82ef5392798941efae93c49395a87d943",
+ "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/4ed813d16edb5a1ab0d7f4b1d116c37ee8cdf3c0",
+ "reference": "4ed813d16edb5a1ab0d7f4b1d116c37ee8cdf3c0",
"shasum": ""
},
"require": {
@@ -12501,7 +12858,7 @@
"type": "github"
}
],
- "time": "2023-06-28T13:51:52+00:00"
+ "time": "2023-08-23T06:24:34+00:00"
},
{
"name": "ta-tikoma/phpunit-architecture-test",
diff --git a/config/coolify.php b/config/coolify.php
index 0276b9a78..f3485f0da 100644
--- a/config/coolify.php
+++ b/config/coolify.php
@@ -4,17 +4,6 @@ return [
'self_hosted' => env('SELF_HOSTED', true),
'waitlist' => env('WAITLIST', false),
'license_url' => 'https://license.coolify.io',
- 'lemon_squeezy_api_key' => env('LEMON_SQUEEZY_API_KEY', null),
- 'lemon_squeezy_webhook_secret' => env('LEMON_SQUEEZY_WEBHOOK_SECRET', null),
- 'lemon_squeezy_checkout_id_monthly_basic' => env('LEMON_SQUEEZY_CHECKOUT_ID_MONTHLY_BASIC', null),
- 'lemon_squeezy_checkout_id_monthly_pro' => env('LEMON_SQUEEZY_CHECKOUT_ID_MONTHLY_PRO', null),
- 'lemon_squeezy_checkout_id_monthly_ultimate' => env('LEMON_SQUEEZY_CHECKOUT_ID_MONTHLY_ULTIMATE', null),
- 'lemon_squeezy_checkout_id_yearly_basic' => env('LEMON_SQUEEZY_CHECKOUT_ID_YEARLY_BASIC', null),
- 'lemon_squeezy_checkout_id_yearly_pro' => env('LEMON_SQUEEZY_CHECKOUT_ID_YEARLY_PRO', null),
- 'lemon_squeezy_checkout_id_yearly_ultimate' => env('LEMON_SQUEEZY_CHECKOUT_ID_YEARLY_ULTIMATE', null),
- 'lemon_squeezy_basic_plan_ids' => env('LEMON_SQUEEZY_BASIC_PLAN_IDS', ""),
- 'lemon_squeezy_pro_plan_ids' => env('LEMON_SQUEEZY_PRO_PLAN_IDS', ""),
- 'lemon_squeezy_ultimate_plan_ids' => env('LEMON_SQUEEZY_ULTIMATE_PLAN_IDS', ""),
'mux_enabled' => env('MUX_ENABLED', true),
'dev_webhook' => env('SERVEO_URL'),
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),
diff --git a/config/mail.php b/config/mail.php
index 4c63daf4f..ec2125fab 100644
--- a/config/mail.php
+++ b/config/mail.php
@@ -44,7 +44,9 @@ return [
'timeout' => null,
'local_domain' => env('MAIL_EHLO_DOMAIN'),
],
-
+ 'resend'=> [
+ 'transport' => 'resend'
+ ],
'ses' => [
'transport' => 'ses',
],
diff --git a/config/subscription.php b/config/subscription.php
new file mode 100644
index 000000000..f646723f8
--- /dev/null
+++ b/config/subscription.php
@@ -0,0 +1,42 @@
+ env('SUBSCRIPTION_PROVIDER', null), // stripe, paddle, lemon
+ // Stripe
+ 'stripe_api_key' => env('STRIPE_API_KEY', null),
+ 'stripe_webhook_secret' => env('STRIPE_WEBHOOK_SECRET', null),
+ 'stripe_price_id_basic_monthly' => env('STRIPE_PRICE_ID_BASIC_MONTHLY', null),
+ 'stripe_price_id_basic_yearly' => env('STRIPE_PRICE_ID_BASIC_YEARLY', null),
+ 'stripe_price_id_pro_monthly' => env('STRIPE_PRICE_ID_PRO_MONTHLY', null),
+ 'stripe_price_id_pro_yearly' => env('STRIPE_PRICE_ID_PRO_YEARLY', null),
+ 'stripe_price_id_ultimate_monthly' => env('STRIPE_PRICE_ID_ULTIMATE_MONTHLY', null),
+ 'stripe_price_id_ultimate_yearly' => env('STRIPE_PRICE_ID_ULTIMATE_YEARLY', null),
+
+
+ // Paddle
+ 'paddle_vendor_id' => env('PADDLE_VENDOR_ID', null),
+ 'paddle_vendor_auth_code' => env('PADDLE_VENDOR_AUTH_CODE', null),
+ 'paddle_webhook_secret' => env('PADDLE_WEBHOOK_SECRET', null),
+ 'paddle_public_key' => env('PADDLE_PUBLIC_KEY', null),
+ 'paddle_price_id_basic_monthly' => env('PADDLE_PRICE_ID_BASIC_MONTHLY', null),
+ 'paddle_price_id_basic_yearly' => env('PADDLE_PRICE_ID_BASIC_YEARLY', null),
+ 'paddle_price_id_pro_monthly' => env('PADDLE_PRICE_ID_PRO_MONTHLY', null),
+ 'paddle_price_id_pro_yearly' => env('PADDLE_PRICE_ID_PRO_YEARLY', null),
+ 'paddle_price_id_ultimate_monthly' => env('PADDLE_PRICE_ID_ULTIMATE_MONTHLY', null),
+ 'paddle_price_id_ultimate_yearly' => env('PADDLE_PRICE_ID_ULTIMATE_YEARLY', null),
+
+
+
+ // Lemon
+ 'lemon_squeezy_api_key' => env('LEMON_SQUEEZY_API_KEY', null),
+ 'lemon_squeezy_webhook_secret' => env('LEMON_SQUEEZY_WEBHOOK_SECRET', null),
+ 'lemon_squeezy_checkout_id_basic_monthly' => env('LEMON_SQUEEZY_CHECKOUT_ID_BASIC_MONTHLY', null),
+ 'lemon_squeezy_checkout_id_basic_yearly' => env('LEMON_SQUEEZY_CHECKOUT_ID_BASIC_YEARLY', null),
+ 'lemon_squeezy_checkout_id_pro_monthly' => env('LEMON_SQUEEZY_CHECKOUT_ID_PRO_MONTHLY', null),
+ 'lemon_squeezy_checkout_id_pro_yearly' => env('LEMON_SQUEEZY_CHECKOUT_ID_PRO_YEARLY', null),
+ 'lemon_squeezy_checkout_id_ultimate_monthly' => env('LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_MONTHLY', null),
+ 'lemon_squeezy_checkout_id_ultimate_yearly' => env('LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_YEARLY', null),
+ 'lemon_squeezy_basic_plan_ids' => env('LEMON_SQUEEZY_BASIC_PLAN_IDS', ""),
+ 'lemon_squeezy_pro_plan_ids' => env('LEMON_SQUEEZY_PRO_PLAN_IDS', ""),
+ 'lemon_squeezy_ultimate_plan_ids' => env('LEMON_SQUEEZY_ULTIMATE_PLAN_IDS', ""),
+];
diff --git a/config/version.php b/config/version.php
index 7764582fa..7ea9c5731 100644
--- a/config/version.php
+++ b/config/version.php
@@ -1,3 +1,3 @@
boolean('show_boarding')->default(false);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('teams', function (Blueprint $table) {
+ $table->dropColumn('show_boarding');
+ });
+ }
+};
diff --git a/database/migrations/2023_08_22_071049_update_webhooks_type.php b/database/migrations/2023_08_22_071049_update_webhooks_type.php
new file mode 100644
index 000000000..7f60ca973
--- /dev/null
+++ b/database/migrations/2023_08_22_071049_update_webhooks_type.php
@@ -0,0 +1,29 @@
+string('type')->change();
+ });
+ DB::statement("ALTER TABLE webhooks DROP CONSTRAINT webhooks_type_check");
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('webhooks', function (Blueprint $table) {
+ $table->string('type')->change();
+ });
+ }
+};
diff --git a/database/migrations/2023_08_22_071050_update_subscriptions_stripe.php b/database/migrations/2023_08_22_071050_update_subscriptions_stripe.php
new file mode 100644
index 000000000..70462fe20
--- /dev/null
+++ b/database/migrations/2023_08_22_071050_update_subscriptions_stripe.php
@@ -0,0 +1,52 @@
+boolean('stripe_invoice_paid')->default(false);
+ $table->string('stripe_subscription_id')->nullable();
+ $table->string('stripe_customer_id')->nullable();
+ $table->boolean('stripe_cancel_at_period_end')->default(false);
+ $table->string('lemon_subscription_id')->nullable()->change();
+ $table->string('lemon_order_id')->nullable()->change();
+ $table->string('lemon_product_id')->nullable()->change();
+ $table->string('lemon_variant_id')->nullable()->change();
+ $table->string('lemon_variant_name')->nullable()->change();
+ $table->string('lemon_customer_id')->nullable()->change();
+ $table->string('lemon_status')->nullable()->change();
+ $table->string('lemon_renews_at')->nullable()->change();
+ $table->string('lemon_update_payment_menthod_url')->nullable()->change();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('subscriptions', function (Blueprint $table) {
+ $table->dropColumn('stripe_invoice_paid');
+ $table->dropColumn('stripe_subscription_id');
+ $table->dropColumn('stripe_customer_id');
+ $table->dropColumn('stripe_cancel_at_period_end');
+ $table->string('lemon_subscription_id')->change();
+ $table->string('lemon_order_id')->change();
+ $table->string('lemon_product_id')->change();
+ $table->string('lemon_variant_id')->change();
+ $table->string('lemon_variant_name')->change();
+ $table->string('lemon_customer_id')->change();
+ $table->string('lemon_status')->change();
+ $table->string('lemon_renews_at')->change();
+ $table->string('lemon_update_payment_menthod_url')->change();
+ });
+ }
+};
diff --git a/database/seeders/ApplicationSeeder.php b/database/seeders/ApplicationSeeder.php
index a43e0f19a..2d2d00cb7 100644
--- a/database/seeders/ApplicationSeeder.php
+++ b/database/seeders/ApplicationSeeder.php
@@ -17,13 +17,12 @@ class ApplicationSeeder extends Seeder
Application::create([
'name' => 'coollabsio/coolify-examples:nodejs-fastify',
'description' => 'NodeJS Fastify Example',
- 'fqdn' => 'http://foo.com',
+ 'fqdn' => 'http://nodejs.127.0.0.1.sslip.io',
'repository_project_id' => 603035348,
'git_repository' => 'coollabsio/coolify-examples',
'git_branch' => 'nodejs-fastify',
'build_pack' => 'nixpacks',
'ports_exposes' => '3000',
- 'ports_mappings' => '3005:3000',
'environment_id' => 1,
'destination_id' => 0,
'destination_type' => StandaloneDocker::class,
@@ -33,18 +32,36 @@ class ApplicationSeeder extends Seeder
Application::create([
'name' => 'coollabsio/coolify-examples:dockerfile',
'description' => 'Dockerfile Example',
- 'fqdn' => 'http://foos.com',
+ 'fqdn' => 'http://dockerfile.127.0.0.1.sslip.io',
'repository_project_id' => 603035348,
'git_repository' => 'coollabsio/coolify-examples',
'git_branch' => 'dockerfile',
'build_pack' => 'dockerfile',
'ports_exposes' => '3000',
- 'ports_mappings' => '3080:80',
'environment_id' => 1,
'destination_id' => 0,
'destination_type' => StandaloneDocker::class,
'source_id' => 0,
'source_type' => GithubApp::class
]);
+ Application::create([
+ 'name' => 'pure-dockerfile',
+ 'description' => 'Pure Dockerfile Example',
+ 'fqdn' => 'http://pure-dockerfile.127.0.0.1.sslip.io',
+ 'git_repository' => 'coollabsio/coolify',
+ 'git_branch' => 'main',
+ 'git_commit_sha' => 'HEAD',
+ 'build_pack' => 'dockerfile',
+ 'ports_exposes' => '80',
+ 'environment_id' => 1,
+ 'destination_id' => 0,
+ 'destination_type' => StandaloneDocker::class,
+ 'source_id' => 0,
+ 'source_type' => GithubApp::class,
+ 'dockerfile' => 'FROM nginx
+EXPOSE 80
+CMD ["nginx", "-g", "daemon off;"]
+'
+ ]);
}
}
diff --git a/database/seeders/InstanceSettingsSeeder.php b/database/seeders/InstanceSettingsSeeder.php
index a00d8715c..1be6462c9 100644
--- a/database/seeders/InstanceSettingsSeeder.php
+++ b/database/seeders/InstanceSettingsSeeder.php
@@ -16,6 +16,7 @@ class InstanceSettingsSeeder extends Seeder
InstanceSettings::create([
'id' => 0,
'is_registration_enabled' => true,
+ 'is_resale_license_active' => true,
'smtp_enabled' => true,
'smtp_host' => 'coolify-mail',
'smtp_port' => 1025,
diff --git a/database/seeders/ScheduledDatabaseBackupExecutionSeeder.php b/database/seeders/ScheduledDatabaseBackupExecutionSeeder.php
index e4b5780c9..7e4c33764 100644
--- a/database/seeders/ScheduledDatabaseBackupExecutionSeeder.php
+++ b/database/seeders/ScheduledDatabaseBackupExecutionSeeder.php
@@ -12,17 +12,17 @@ class ScheduledDatabaseBackupExecutionSeeder extends Seeder
*/
public function run(): void
{
- ScheduledDatabaseBackupExecution::create([
- 'status' => 'success',
- 'message' => 'Backup created successfully.',
- 'size' => '10243467789556',
- 'scheduled_database_backup_id' => 1,
- ]);
- ScheduledDatabaseBackupExecution::create([
- 'status' => 'failed',
- 'message' => 'Backup failed.',
- 'size' => '10243456',
- 'scheduled_database_backup_id' => 1,
- ]);
+ // ScheduledDatabaseBackupExecution::create([
+ // 'status' => 'success',
+ // 'message' => 'Backup created successfully.',
+ // 'size' => '10243467789556',
+ // 'scheduled_database_backup_id' => 1,
+ // ]);
+ // ScheduledDatabaseBackupExecution::create([
+ // 'status' => 'failed',
+ // 'message' => 'Backup failed.',
+ // 'size' => '10243456',
+ // 'scheduled_database_backup_id' => 1,
+ // ]);
}
}
diff --git a/database/seeders/ScheduledDatabaseBackupSeeder.php b/database/seeders/ScheduledDatabaseBackupSeeder.php
index 96ca0c012..fefbada0d 100644
--- a/database/seeders/ScheduledDatabaseBackupSeeder.php
+++ b/database/seeders/ScheduledDatabaseBackupSeeder.php
@@ -12,22 +12,22 @@ class ScheduledDatabaseBackupSeeder extends Seeder
*/
public function run(): void
{
- ScheduledDatabaseBackup::create([
- 'enabled' => true,
- 'frequency' => '* * * * *',
- 'number_of_backups_locally' => 2,
- 'database_id' => 1,
- 'database_type' => 'App\Models\StandalonePostgresql',
- 's3_storage_id' => 1,
- 'team_id' => 0,
- ]);
- ScheduledDatabaseBackup::create([
- 'enabled' => true,
- 'frequency' => '* * * * *',
- 'number_of_backups_locally' => 3,
- 'database_id' => 1,
- 'database_type' => 'App\Models\StandalonePostgresql',
- 'team_id' => 0,
- ]);
+ // ScheduledDatabaseBackup::create([
+ // 'enabled' => true,
+ // 'frequency' => '* * * * *',
+ // 'number_of_backups_locally' => 2,
+ // 'database_id' => 1,
+ // 'database_type' => 'App\Models\StandalonePostgresql',
+ // 's3_storage_id' => 1,
+ // 'team_id' => 0,
+ // ]);
+ // ScheduledDatabaseBackup::create([
+ // 'enabled' => true,
+ // 'frequency' => '* * * * *',
+ // 'number_of_backups_locally' => 3,
+ // 'database_id' => 1,
+ // 'database_type' => 'App\Models\StandalonePostgresql',
+ // 'team_id' => 0,
+ // ]);
}
}
diff --git a/database/seeders/ServerSeeder.php b/database/seeders/ServerSeeder.php
index 77a4516e5..f201862f0 100644
--- a/database/seeders/ServerSeeder.php
+++ b/database/seeders/ServerSeeder.php
@@ -11,8 +11,8 @@ class ServerSeeder extends Seeder
{
Server::create([
'id' => 0,
- 'name' => "testing-local-docker-container",
- 'description' => "This is a test docker container",
+ 'name' => "localhost",
+ 'description' => "This is a test docker container in development mode",
'ip' => "coolify-testing-host",
'team_id' => 0,
'private_key_id' => 0,
diff --git a/database/seeders/StandaloneDockerSeeder.php b/database/seeders/StandaloneDockerSeeder.php
index 9f67de710..1e9a749dd 100644
--- a/database/seeders/StandaloneDockerSeeder.php
+++ b/database/seeders/StandaloneDockerSeeder.php
@@ -13,11 +13,11 @@ class StandaloneDockerSeeder extends Seeder
*/
public function run(): void
{
- StandaloneDocker::create([
- 'id' => 0,
- 'name' => 'Standalone Docker 1',
- 'network' => 'coolify',
- 'server_id' => 0,
- ]);
+ // StandaloneDocker::create([
+ // 'id' => 0,
+ // 'name' => 'Standalone Docker 1',
+ // 'network' => 'coolify',
+ // 'server_id' => 0,
+ // ]);
}
}
diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml
index 4a9e0c192..710f44f2c 100644
--- a/docker-compose.prod.yml
+++ b/docker-compose.prod.yml
@@ -34,13 +34,33 @@ services:
- PHP_PM_MAX_SPARE_SERVERS=10
- SELF_HOSTED
- WAITLIST
+ - SUBSCRIPTION_PROVIDER
+ - STRIPE_API_KEY
+ - STRIPE_WEBHOOK_SECRET
+ - STRIPE_PRICE_ID_BASIC_MONTHLY
+ - STRIPE_PRICE_ID_BASIC_YEARLY
+ - STRIPE_PRICE_ID_PRO_MONTHLY
+ - STRIPE_PRICE_ID_PRO_YEARLY
+ - STRIPE_PRICE_ID_ULTIMATE_MONTHLY
+ - STRIPE_PRICE_ID_ULTIMATE_YEARLY
+ - PADDLE_VENDOR_ID
+ - PADDLE_WEBHOOK_SECRET
+ - PADDLE_VENDOR_AUTH_CODE
+ - PADDLE_PUBLIC_KEY
+ - PADDLE_PRICE_ID_BASIC_MONTHLY
+ - PADDLE_PRICE_ID_BASIC_YEARLY
+ - PADDLE_PRICE_ID_PRO_MONTHLY
+ - PADDLE_PRICE_ID_PRO_YEARLY
+ - PADDLE_PRICE_ID_ULTIMATE_MONTHLY
+ - PADDLE_PRICE_ID_ULTIMATE_YEARLY
+ - LEMON_SQUEEZY_API_KEY
- LEMON_SQUEEZY_WEBHOOK_SECRET
- - LEMON_SQUEEZY_CHECKOUT_ID_MONTHLY_BASIC
- - LEMON_SQUEEZY_CHECKOUT_ID_MONTHLY_PRO
- - LEMON_SQUEEZY_CHECKOUT_ID_MONTHLY_ULTIMATE
- - LEMON_SQUEEZY_CHECKOUT_ID_YEARLY_BASIC
- - LEMON_SQUEEZY_CHECKOUT_ID_YEARLY_PRO
- - LEMON_SQUEEZY_CHECKOUT_ID_YEARLY_ULTIMATE
+ - LEMON_SQUEEZY_CHECKOUT_ID_BASIC_MONTHLY
+ - LEMON_SQUEEZY_CHECKOUT_ID_BASIC_YEARLY
+ - LEMON_SQUEEZY_CHECKOUT_ID_PRO_MONTHLY
+ - LEMON_SQUEEZY_CHECKOUT_ID_PRO_YEARLY
+ - LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_MONTHLY
+ - LEMON_SQUEEZY_CHECKOUT_ID_ULTIMATE_YEARLY
- LEMON_SQUEEZY_BASIC_PLAN_IDS
- LEMON_SQUEEZY_PRO_PLAN_IDS
- LEMON_SQUEEZY_ULTIMATE_PLAN_IDS
diff --git a/package.json b/package.json
index ed81d6a26..81e0dd5a8 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,6 @@
{
"private": true,
+ "type": "module",
"scripts": {
"dev": "vite",
"build": "vite build"
@@ -20,4 +21,4 @@
"daisyui": "3.2.1",
"tailwindcss-scrollbar": "0.1.0"
}
-}
\ No newline at end of file
+}
diff --git a/postcss.config.js b/postcss.config.cjs
similarity index 100%
rename from postcss.config.js
rename to postcss.config.cjs
diff --git a/resources/css/app.css b/resources/css/app.css
index b5f58fc74..7703ef608 100644
--- a/resources/css/app.css
+++ b/resources/css/app.css
@@ -53,7 +53,7 @@ a {
@apply text-white;
}
.box {
- @apply flex items-center justify-center p-2 transition-colors rounded min-h-12 bg-coolgray-200 hover:bg-coollabs-100 hover:text-white hover:no-underline;
+ @apply flex items-center p-2 transition-colors cursor-pointer min-h-16 bg-coolgray-200 hover:bg-coollabs-100 hover:text-white hover:no-underline min-w-[24rem];
}
.lds-heart {
diff --git a/resources/js/components/MagicBar.vue b/resources/js/components/MagicBar.vue
index f0203b885..a0e8f762c 100644
--- a/resources/js/components/MagicBar.vue
+++ b/resources/js/components/MagicBar.vue
@@ -53,12 +53,12 @@
{{
sequenceState.sequence[sequenceState.currentActionIndex] }} name
will be:
- {{ search
- }}
+ {{ search }}
+
{{
sequenceState.sequence[sequenceState.currentActionIndex] }} name
will be:
- randomly generated (type to change)
+ randomly generated (type to change)
diff --git a/resources/views/boarding.blade.php b/resources/views/boarding.blade.php
new file mode 100644
index 000000000..bdf229935
--- /dev/null
+++ b/resources/views/boarding.blade.php
@@ -0,0 +1,13 @@
+
+ {{$question}} +
+ @endisset +