mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
v4.7 (#12478)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Co-authored-by: Aditya Tripathi <aditya@climactic.co>
This commit is contained in:
co-authored by
Claude Opus 5.5
peaklabs-dev
Aditya Tripathi
parent
b7dc2e435b
commit
033f0c84da
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\ImageSbom;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<ImageSbom>
|
||||
*/
|
||||
class ImageSbomFactory extends Factory
|
||||
{
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'server_id' => Server::factory(),
|
||||
'image_id' => 'sha256:'.fake()->sha256(),
|
||||
'platform' => 'linux/amd64',
|
||||
'packages' => [],
|
||||
'packages_truncated' => false,
|
||||
'last_used_at' => now(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Enums\ImageScanStatus;
|
||||
use App\Models\Application;
|
||||
use App\Models\ImageScan;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<ImageScan>
|
||||
*/
|
||||
class ImageScanFactory extends Factory
|
||||
{
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'server_id' => Server::factory(),
|
||||
'image_id' => 'sha256:'.fake()->sha256(),
|
||||
'resource_type' => (new Application)->getMorphClass(),
|
||||
'resource_id' => fake()->unique()->numberBetween(1, 1_000_000),
|
||||
'image_ref' => 'nginx:1.27',
|
||||
'status' => ImageScanStatus::Completed,
|
||||
'builds_image' => false,
|
||||
'scanned_at' => now(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\ImageScanIgnore;
|
||||
use App\Models\Team;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<ImageScanIgnore>
|
||||
*/
|
||||
class ImageScanIgnoreFactory extends Factory
|
||||
{
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'team_id' => Team::factory(),
|
||||
'vulnerability_id' => 'CVE-2024-'.fake()->numerify('#####'),
|
||||
'reason' => 'Not reachable in this application',
|
||||
'expires_at' => null,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\ImageScanNotificationState;
|
||||
use App\Models\Team;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<ImageScanNotificationState>
|
||||
*/
|
||||
class ImageScanNotificationStateFactory extends Factory
|
||||
{
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'resource_type' => (new Application)->getMorphClass(),
|
||||
'resource_id' => fake()->unique()->numberBetween(1, 1_000_000),
|
||||
'team_id' => Team::factory(),
|
||||
'notified_ids' => [],
|
||||
'notified_candidates' => [],
|
||||
'is_baseline' => false,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Enums\ImageScanGateMode;
|
||||
use App\Enums\ImageScanOnError;
|
||||
use App\Models\ImageScanPolicy;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends Factory<ImageScanPolicy>
|
||||
*/
|
||||
class ImageScanPolicyFactory extends Factory
|
||||
{
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'scope_type' => null,
|
||||
'scope_id' => null,
|
||||
'gate_mode' => null,
|
||||
'on_scan_error' => null,
|
||||
'count_medium' => null,
|
||||
];
|
||||
}
|
||||
|
||||
public function concrete(): static
|
||||
{
|
||||
return $this->state([
|
||||
'gate_mode' => ImageScanGateMode::Off,
|
||||
'on_scan_error' => ImageScanOnError::Deploy,
|
||||
'count_medium' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/** @var array<string, array{0: string, 1: bool}> notification settings table => [alert column, default] */
|
||||
private const NOTIFICATION_COLUMNS = [
|
||||
'email_notification_settings' => ['image_vulnerabilities_email_notifications', true],
|
||||
'discord_notification_settings' => ['image_vulnerabilities_discord_notifications', false],
|
||||
'telegram_notification_settings' => ['image_vulnerabilities_telegram_notifications', false],
|
||||
'slack_notification_settings' => ['image_vulnerabilities_slack_notifications', false],
|
||||
'pushover_notification_settings' => ['image_vulnerabilities_pushover_notifications', false],
|
||||
'webhook_notification_settings' => ['image_vulnerabilities_webhook_notifications', false],
|
||||
];
|
||||
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('image_scan_policies', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uuid')->unique();
|
||||
$table->string('scope_type')->nullable();
|
||||
$table->unsignedBigInteger('scope_id')->nullable();
|
||||
$table->string('gate_mode')->nullable();
|
||||
$table->string('on_scan_error')->nullable();
|
||||
$table->boolean('count_medium')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['scope_type', 'scope_id']);
|
||||
});
|
||||
|
||||
DB::table('image_scan_policies')->insert([
|
||||
'uuid' => new_public_id(),
|
||||
'scope_type' => null,
|
||||
'scope_id' => null,
|
||||
'gate_mode' => 'off',
|
||||
'on_scan_error' => 'deploy',
|
||||
'count_medium' => false,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
Schema::create('image_scan_ignores', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uuid')->unique();
|
||||
$table->foreignId('team_id')->constrained()->cascadeOnDelete();
|
||||
$table->nullableMorphs('resource');
|
||||
$table->string('vulnerability_id', 64)->nullable();
|
||||
$table->string('package', 214)->nullable();
|
||||
$table->string('reason', 500);
|
||||
$table->timestamp('expires_at')->nullable();
|
||||
$table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['team_id', 'resource_type', 'resource_id']);
|
||||
});
|
||||
|
||||
Schema::create('image_sboms', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('server_id')->constrained()->cascadeOnDelete();
|
||||
$table->string('image_id', 80);
|
||||
$table->string('platform', 32);
|
||||
$table->jsonb('packages');
|
||||
$table->boolean('packages_truncated')->default(false);
|
||||
$table->timestamp('last_used_at');
|
||||
|
||||
$table->unique(['server_id', 'image_id']);
|
||||
});
|
||||
|
||||
Schema::create('image_scans', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uuid')->unique();
|
||||
$table->foreignId('server_id')->constrained()->cascadeOnDelete();
|
||||
$table->foreignId('image_sbom_id')->nullable()->constrained('image_sboms')->nullOnDelete();
|
||||
$table->string('image_id', 80);
|
||||
$table->string('repo_digest', 80)->nullable();
|
||||
$table->morphs('resource');
|
||||
$table->string('image_ref', 512);
|
||||
$table->foreignId('deployment_queue_id')->nullable()->constrained('application_deployment_queues')->nullOnDelete();
|
||||
$table->string('status');
|
||||
$table->string('error_code')->nullable();
|
||||
$table->jsonb('error_context')->nullable();
|
||||
$table->jsonb('summary')->nullable();
|
||||
$table->jsonb('findings')->nullable();
|
||||
$table->jsonb('candidates')->nullable();
|
||||
$table->string('base_image_ref', 512)->nullable();
|
||||
$table->boolean('builds_image')->default(false);
|
||||
$table->boolean('is_baseline')->default(true);
|
||||
$table->timestamp('grype_db_built_at')->nullable();
|
||||
$table->timestamp('scanned_at')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['resource_type', 'resource_id', 'image_id']);
|
||||
$table->index(['server_id', 'image_id']);
|
||||
});
|
||||
|
||||
Schema::create('image_scan_notification_states', function (Blueprint $table) {
|
||||
$table->id();
|
||||
// No morphs(): its index would repeat the unique key below.
|
||||
$table->string('resource_type');
|
||||
$table->unsignedBigInteger('resource_id');
|
||||
$table->foreignId('team_id')->constrained()->cascadeOnDelete();
|
||||
$table->jsonb('notified_ids')->nullable();
|
||||
$table->jsonb('notified_candidates')->nullable();
|
||||
$table->jsonb('digest_ids')->nullable();
|
||||
$table->boolean('is_baseline')->default(true);
|
||||
$table->boolean('check_reported')->default(false);
|
||||
$table->unsignedSmallInteger('held_digests')->default(0);
|
||||
$table->unsignedBigInteger('baseline_deployment_queue_id')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['resource_type', 'resource_id']);
|
||||
});
|
||||
|
||||
Schema::table('server_settings', function (Blueprint $table) {
|
||||
$table->boolean('is_image_scan_enabled')->default(false);
|
||||
$table->unsignedInteger('image_candidate_scans_today')->default(0);
|
||||
$table->date('image_candidate_scans_date')->nullable();
|
||||
});
|
||||
|
||||
Schema::table('instance_settings', function (Blueprint $table) {
|
||||
$table->boolean('is_image_scanning_allowed')->default(true);
|
||||
$table->string('image_scan_db_url')->nullable();
|
||||
});
|
||||
|
||||
Schema::table('teams', function (Blueprint $table) {
|
||||
$table->boolean('scan_images_on_new_servers')->default(false);
|
||||
});
|
||||
|
||||
Schema::table('application_settings', function (Blueprint $table) {
|
||||
$table->boolean('is_image_scan_enabled')->default(true);
|
||||
$table->boolean('image_builds_by_team')->nullable();
|
||||
});
|
||||
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
// Security updates of a Compose app: {service: {from, to}}; applied while the compose file still names `from`.
|
||||
$table->json('docker_compose_image_overrides')->nullable();
|
||||
});
|
||||
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->jsonb('scan_gate_result')->nullable();
|
||||
$table->foreignId('scan_gate_bypassed_by')->nullable()->constrained('users')->nullOnDelete();
|
||||
});
|
||||
|
||||
foreach (self::NOTIFICATION_COLUMNS as $tableName => [$column, $default]) {
|
||||
Schema::table($tableName, function (Blueprint $table) use ($column, $default) {
|
||||
$table->boolean($column)->default($default);
|
||||
});
|
||||
}
|
||||
|
||||
Schema::table('telegram_notification_settings', function (Blueprint $table) {
|
||||
$table->text('telegram_notifications_image_vulnerabilities_thread_id')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('telegram_notification_settings', function (Blueprint $table) {
|
||||
$table->dropColumn('telegram_notifications_image_vulnerabilities_thread_id');
|
||||
});
|
||||
|
||||
foreach (self::NOTIFICATION_COLUMNS as $tableName => [$column]) {
|
||||
Schema::table($tableName, function (Blueprint $table) use ($column) {
|
||||
$table->dropColumn($column);
|
||||
});
|
||||
}
|
||||
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->dropConstrainedForeignId('scan_gate_bypassed_by');
|
||||
$table->dropColumn('scan_gate_result');
|
||||
});
|
||||
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
$table->dropColumn('docker_compose_image_overrides');
|
||||
});
|
||||
|
||||
Schema::table('application_settings', function (Blueprint $table) {
|
||||
$table->dropColumn(['is_image_scan_enabled', 'image_builds_by_team']);
|
||||
});
|
||||
|
||||
Schema::table('teams', function (Blueprint $table) {
|
||||
$table->dropColumn('scan_images_on_new_servers');
|
||||
});
|
||||
|
||||
Schema::table('instance_settings', function (Blueprint $table) {
|
||||
$table->dropColumn(['is_image_scanning_allowed', 'image_scan_db_url']);
|
||||
});
|
||||
|
||||
Schema::table('server_settings', function (Blueprint $table) {
|
||||
$table->dropColumn(['is_image_scan_enabled', 'image_candidate_scans_today', 'image_candidate_scans_date']);
|
||||
});
|
||||
|
||||
Schema::dropIfExists('image_scan_notification_states');
|
||||
Schema::dropIfExists('image_scans');
|
||||
Schema::dropIfExists('image_sboms');
|
||||
Schema::dropIfExists('image_scan_ignores');
|
||||
Schema::dropIfExists('image_scan_policies');
|
||||
}
|
||||
};
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
$table->text('git_ssh_known_hosts')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
$table->dropColumn('git_ssh_known_hosts');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('server_settings', function (Blueprint $table) {
|
||||
$table->text('ssh_host_key')->nullable();
|
||||
$table->string('ssh_host_key_source')->nullable();
|
||||
$table->timestamp('ssh_host_key_trusted_at')->nullable();
|
||||
$table->text('ssh_host_key_pending')->nullable();
|
||||
$table->boolean('is_ssh_host_key_check_disabled')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('server_settings', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'ssh_host_key',
|
||||
'ssh_host_key_source',
|
||||
'ssh_host_key_trusted_at',
|
||||
'ssh_host_key_pending',
|
||||
'is_ssh_host_key_check_disabled',
|
||||
]);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* The protocol of the storage: s3, sftp, ftps, or webdav. Storages that are not S3 have no bucket. An SFTP storage
|
||||
* logs in with a private key of its team or with a password.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('s3_storages', function (Blueprint $table) {
|
||||
$table->string('type')->default('s3');
|
||||
$table->longText('bucket')->nullable()->change();
|
||||
$table->foreignId('private_key_id')->nullable()->constrained('private_keys')->nullOnDelete();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
DB::table('s3_storages')->whereNull('bucket')->update(['bucket' => '']);
|
||||
|
||||
Schema::table('s3_storages', function (Blueprint $table) {
|
||||
$table->dropConstrainedForeignId('private_key_id');
|
||||
$table->dropColumn('type');
|
||||
$table->longText('bucket')->nullable(false)->change();
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* The public host key of an SFTP server ("ssh-ed25519 AAAA..."), saved on the first successful connection. Every
|
||||
* later connection of Coolify and rclone must see the same key. Null: the next connection test saves it.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('s3_storages', function (Blueprint $table) {
|
||||
$table->text('sftp_host_key')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('s3_storages', function (Blueprint $table) {
|
||||
$table->dropColumn('sftp_host_key');
|
||||
});
|
||||
}
|
||||
};
|
||||
+10
-3
@@ -9,10 +9,17 @@ return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// A nightly build of `next` added `failing_since` in an earlier version of this feature.
|
||||
Schema::table('scheduled_tasks', function (Blueprint $table) {
|
||||
$table->unsignedInteger('consecutive_failures')->default(0);
|
||||
$table->timestamp('failing_since')->nullable();
|
||||
$table->text('disabled_reason')->nullable();
|
||||
if (! Schema::hasColumn('scheduled_tasks', 'consecutive_failures')) {
|
||||
$table->unsignedInteger('consecutive_failures')->default(0);
|
||||
}
|
||||
if (! Schema::hasColumn('scheduled_tasks', 'failing_since')) {
|
||||
$table->timestamp('failing_since')->nullable();
|
||||
}
|
||||
if (! Schema::hasColumn('scheduled_tasks', 'disabled_reason')) {
|
||||
$table->text('disabled_reason')->nullable();
|
||||
}
|
||||
});
|
||||
|
||||
$this->setExecutionStatuses(['success', 'failed', 'running', 'skipped']);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('github_apps', function (Blueprint $table) {
|
||||
$table->string('deployments')->nullable()->after('pull_requests');
|
||||
});
|
||||
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('github_deployment_id')->nullable();
|
||||
$table->string('github_deployment_state')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('github_apps', function (Blueprint $table) {
|
||||
$table->dropColumn('deployments');
|
||||
});
|
||||
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->dropColumn(['github_deployment_id', 'github_deployment_state']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* The smtp_* columns stay the SMTP server in use. smtp_server_name is its name, and
|
||||
* smtp_servers holds the other saved servers (encrypted, because they contain passwords).
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
foreach (['instance_settings', 'email_notification_settings'] as $tableName) {
|
||||
if (Schema::hasColumn($tableName, 'smtp_servers')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Schema::table($tableName, function (Blueprint $table) {
|
||||
$table->string('smtp_server_name')->nullable();
|
||||
$table->text('smtp_servers')->nullable();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
foreach (['instance_settings', 'email_notification_settings'] as $tableName) {
|
||||
Schema::table($tableName, function (Blueprint $table) {
|
||||
$table->dropColumn(['smtp_server_name', 'smtp_servers']);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('instance_settings', function (Blueprint $table) {
|
||||
$table->string('auto_update_target_version')->nullable();
|
||||
$table->timestamp('auto_update_started_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('instance_settings', function (Blueprint $table) {
|
||||
$table->dropColumn(['auto_update_target_version', 'auto_update_started_at']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Resend gets its own sender. It starts as a copy of the current sender, so that nothing changes
|
||||
* for existing installs. Both columns use the same encrypted cast, so the stored values copy as they are.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
foreach (['instance_settings', 'email_notification_settings'] as $tableName) {
|
||||
if (Schema::hasColumn($tableName, 'resend_from_address')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Schema::table($tableName, function (Blueprint $table) {
|
||||
$table->text('resend_from_address')->nullable();
|
||||
$table->text('resend_from_name')->nullable();
|
||||
});
|
||||
|
||||
DB::table($tableName)->update([
|
||||
'resend_from_address' => DB::raw('smtp_from_address'),
|
||||
'resend_from_name' => DB::raw('smtp_from_name'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
foreach (['instance_settings', 'email_notification_settings'] as $tableName) {
|
||||
Schema::table($tableName, function (Blueprint $table) {
|
||||
$table->dropColumn(['resend_from_address', 'resend_from_name']);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -92,13 +92,16 @@ class ProductionSeeder extends Seeder
|
||||
if ($coolify_key) {
|
||||
$user = str($coolify_key)->before('@')->after('id.');
|
||||
$coolify_key = Storage::disk('ssh-keys')->get($coolify_key);
|
||||
PrivateKey::create([
|
||||
$localhostKey = (new PrivateKey)->forceFill([
|
||||
'id' => 0,
|
||||
'team_id' => 0,
|
||||
'name' => 'localhost\'s key',
|
||||
'description' => 'The private key for the Coolify host machine (localhost).',
|
||||
'private_key' => $coolify_key,
|
||||
]);
|
||||
// The install script created this key, so an older key type must not block the localhost server.
|
||||
$localhostKey->allowLegacyKey = true;
|
||||
$localhostKey->save();
|
||||
echo "SSH key found for the Coolify host machine (localhost).\n";
|
||||
} else {
|
||||
echo "No SSH key found for the Coolify host machine (localhost).\n";
|
||||
|
||||
Reference in New Issue
Block a user