@@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
namespace App\Actions\Database;
 | 
			
		||||
 | 
			
		||||
use App\Models\ServiceDatabase;
 | 
			
		||||
use App\Models\StandaloneMariadb;
 | 
			
		||||
use App\Models\StandaloneMongodb;
 | 
			
		||||
use App\Models\StandaloneMysql;
 | 
			
		||||
@@ -14,18 +15,44 @@ class StartDatabaseProxy
 | 
			
		||||
{
 | 
			
		||||
    use AsAction;
 | 
			
		||||
 | 
			
		||||
    public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb $database)
 | 
			
		||||
    public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|ServiceDatabase $database)
 | 
			
		||||
    {
 | 
			
		||||
        $internalPort = null;
 | 
			
		||||
        if ($database->getMorphClass() === 'App\Models\StandaloneRedis') {
 | 
			
		||||
        $type = $database->getMorphClass();
 | 
			
		||||
        $network = data_get($database, 'destination.network');
 | 
			
		||||
        $server = data_get($database, 'destination.server');
 | 
			
		||||
        if ($database->getMorphClass() === 'App\Models\ServiceDatabase') {
 | 
			
		||||
            $databaseType = $database->databaseType();
 | 
			
		||||
            $network = data_get($database, 'service.destination.network');
 | 
			
		||||
            $server = data_get($database, 'service.destination.server');
 | 
			
		||||
            ray($databaseType, $network);
 | 
			
		||||
            switch ($databaseType) {
 | 
			
		||||
                case 'standalone-mariadb':
 | 
			
		||||
                    $type = 'App\Models\StandaloneMariadb';
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'standalone-mongodb':
 | 
			
		||||
                    $type = 'App\Models\StandaloneMongodb';
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'standalone-mysql':
 | 
			
		||||
                    $type = 'App\Models\StandaloneMysql';
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'standalone-postgresql':
 | 
			
		||||
                    $type = 'App\Models\StandalonePostgresql';
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'standalone-redis':
 | 
			
		||||
                    $type = 'App\Models\StandaloneRedis';
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if ($type === 'App\Models\StandaloneRedis') {
 | 
			
		||||
            $internalPort = 6379;
 | 
			
		||||
        } else if ($database->getMorphClass() === 'App\Models\StandalonePostgresql') {
 | 
			
		||||
        } else if ($type === 'App\Models\StandalonePostgresql') {
 | 
			
		||||
            $internalPort = 5432;
 | 
			
		||||
        } else if ($database->getMorphClass() === 'App\Models\StandaloneMongodb') {
 | 
			
		||||
        } else if ($type === 'App\Models\StandaloneMongodb') {
 | 
			
		||||
            $internalPort = 27017;
 | 
			
		||||
        } else if ($database->getMorphClass() === 'App\Models\StandaloneMysql') {
 | 
			
		||||
        } else if ($type === 'App\Models\StandaloneMysql') {
 | 
			
		||||
            $internalPort = 3306;
 | 
			
		||||
        } else if ($database->getMorphClass() === 'App\Models\StandaloneMariadb') {
 | 
			
		||||
        } else if ($type === 'App\Models\StandaloneMariadb') {
 | 
			
		||||
            $internalPort = 3306;
 | 
			
		||||
        }
 | 
			
		||||
        $containerName = "{$database->uuid}-proxy";
 | 
			
		||||
@@ -66,7 +93,7 @@ class StartDatabaseProxy
 | 
			
		||||
                        "$database->public_port:$database->public_port",
 | 
			
		||||
                    ],
 | 
			
		||||
                    'networks' => [
 | 
			
		||||
                        $database->destination->network,
 | 
			
		||||
                        $network,
 | 
			
		||||
                    ],
 | 
			
		||||
                    'healthcheck' => [
 | 
			
		||||
                        'test' => [
 | 
			
		||||
@@ -81,9 +108,9 @@ class StartDatabaseProxy
 | 
			
		||||
                ]
 | 
			
		||||
            ],
 | 
			
		||||
            'networks' => [
 | 
			
		||||
                $database->destination->network => [
 | 
			
		||||
                $network => [
 | 
			
		||||
                    'external' => true,
 | 
			
		||||
                    'name' => $database->destination->network,
 | 
			
		||||
                    'name' => $network,
 | 
			
		||||
                    'attachable' => true,
 | 
			
		||||
                ]
 | 
			
		||||
            ]
 | 
			
		||||
@@ -97,6 +124,6 @@ class StartDatabaseProxy
 | 
			
		||||
            "echo '{$nginxconf_base64}' | base64 -d > $configuration_dir/nginx.conf",
 | 
			
		||||
            "echo '{$dockercompose_base64}' | base64 -d > $configuration_dir/docker-compose.yaml",
 | 
			
		||||
            "docker compose --project-directory {$configuration_dir} up --build -d",
 | 
			
		||||
        ], $database->destination->server);
 | 
			
		||||
        ], $server);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
namespace App\Actions\Database;
 | 
			
		||||
 | 
			
		||||
use App\Models\ServiceDatabase;
 | 
			
		||||
use App\Models\StandaloneMariadb;
 | 
			
		||||
use App\Models\StandaloneMongodb;
 | 
			
		||||
use App\Models\StandaloneMysql;
 | 
			
		||||
@@ -13,9 +14,13 @@ class StopDatabaseProxy
 | 
			
		||||
{
 | 
			
		||||
    use AsAction;
 | 
			
		||||
 | 
			
		||||
    public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb $database)
 | 
			
		||||
    public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|ServiceDatabase $database)
 | 
			
		||||
    {
 | 
			
		||||
        instant_remote_process(["docker rm -f {$database->uuid}-proxy"], $database->destination->server);
 | 
			
		||||
        $server = data_get($database, 'destination.server');
 | 
			
		||||
        if ($database->getMorphClass() === 'App\Models\ServiceDatabase') {
 | 
			
		||||
            $server = data_get($database, 'service.server');
 | 
			
		||||
        }
 | 
			
		||||
        instant_remote_process(["docker rm -f {$database->uuid}-proxy"], $server);
 | 
			
		||||
        $database->is_public = false;
 | 
			
		||||
        $database->save();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -2,28 +2,56 @@
 | 
			
		||||
 | 
			
		||||
namespace App\Http\Livewire\Project\Service;
 | 
			
		||||
 | 
			
		||||
use App\Actions\Database\StartDatabaseProxy;
 | 
			
		||||
use App\Actions\Database\StopDatabaseProxy;
 | 
			
		||||
use App\Models\ServiceDatabase;
 | 
			
		||||
use Livewire\Component;
 | 
			
		||||
 | 
			
		||||
class Database extends Component
 | 
			
		||||
{
 | 
			
		||||
    public ServiceDatabase $database;
 | 
			
		||||
    public ?string $db_url_public = null;
 | 
			
		||||
    public $fileStorages;
 | 
			
		||||
 | 
			
		||||
    protected $listeners = ["refreshFileStorages"];
 | 
			
		||||
    protected $rules = [
 | 
			
		||||
        'database.human_name' => 'nullable',
 | 
			
		||||
        'database.description' => 'nullable',
 | 
			
		||||
        'database.image' => 'required',
 | 
			
		||||
        'database.exclude_from_status' => 'required|boolean',
 | 
			
		||||
        'database.public_port' => 'nullable|integer',
 | 
			
		||||
        'database.is_public' => 'required|boolean',
 | 
			
		||||
    ];
 | 
			
		||||
    public function render()
 | 
			
		||||
    {
 | 
			
		||||
        return view('livewire.project.service.database');
 | 
			
		||||
    }
 | 
			
		||||
    public function mount() {
 | 
			
		||||
        if ($this->database->is_public) {
 | 
			
		||||
            $this->db_url_public = $this->database->getServiceDatabaseUrl();
 | 
			
		||||
        }
 | 
			
		||||
        $this->refreshFileStorages();
 | 
			
		||||
    }
 | 
			
		||||
    public function instantSave() {
 | 
			
		||||
        if ($this->database->is_public && !$this->database->public_port) {
 | 
			
		||||
            $this->emit('error', 'Public port is required.');
 | 
			
		||||
            $this->database->is_public = false;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if ($this->database->is_public) {
 | 
			
		||||
            if (!str($this->database->status)->startsWith('running')) {
 | 
			
		||||
                $this->emit('error', 'Database must be started to be publicly accessible.');
 | 
			
		||||
                $this->database->is_public = false;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            StartDatabaseProxy::run($this->database);
 | 
			
		||||
            $this->db_url_public = $this->database->getServiceDatabaseUrl();
 | 
			
		||||
            $this->emit('success', 'Database is now publicly accessible.');
 | 
			
		||||
        } else {
 | 
			
		||||
            StopDatabaseProxy::run($this->database);
 | 
			
		||||
            $this->db_url_public = null;
 | 
			
		||||
            $this->emit('success', 'Database is no longer publicly accessible.');
 | 
			
		||||
        }
 | 
			
		||||
        $this->submit();
 | 
			
		||||
    }
 | 
			
		||||
    public function refreshFileStorages()
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,16 @@ class ServiceDatabase extends BaseModel
 | 
			
		||||
        }
 | 
			
		||||
        return "standalone-$image";
 | 
			
		||||
    }
 | 
			
		||||
    public function getServiceDatabaseUrl() {
 | 
			
		||||
        // $type = $this->databaseType();
 | 
			
		||||
        $port = $this->public_port;
 | 
			
		||||
        $realIp = $this->service->server->ip;
 | 
			
		||||
        if ($realIp === 'host.docker.internal' || isDev()) {
 | 
			
		||||
            $realIp = base_ip();
 | 
			
		||||
        }
 | 
			
		||||
        $url = "{$realIp}:{$port}";
 | 
			
		||||
        return $url;
 | 
			
		||||
    }
 | 
			
		||||
    public function service()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->belongsTo(Service::class);
 | 
			
		||||
 
 | 
			
		||||
@@ -58,8 +58,9 @@ class StandaloneRedis extends BaseModel
 | 
			
		||||
    {
 | 
			
		||||
        return 'standalone-redis';
 | 
			
		||||
    }
 | 
			
		||||
    public function getDbUrl(): string {
 | 
			
		||||
        if ($this->is_public) {
 | 
			
		||||
    public function getDbUrl(bool $useInternal = false): string
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->is_public && !$useInternal) {
 | 
			
		||||
            return "redis://:{$this->redis_password}@{$this->destination->server->getIp}:{$this->public_port}/0";
 | 
			
		||||
        } else {
 | 
			
		||||
            return "redis://:{$this->redis_password}@{$this->uuid}:6379/0";
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ return [
 | 
			
		||||
 | 
			
		||||
    // The release version of your application
 | 
			
		||||
    // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
 | 
			
		||||
    'release' => '4.0.0-beta.118',
 | 
			
		||||
    'release' => '4.0.0-beta.119',
 | 
			
		||||
    // When left empty or `null` the Laravel environment will be used
 | 
			
		||||
    'environment' => config('app.env'),
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
return '4.0.0-beta.118';
 | 
			
		||||
return '4.0.0-beta.119';
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,30 @@
 | 
			
		||||
<?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('service_databases', function (Blueprint $table) {
 | 
			
		||||
            $table->integer('public_port')->nullable();
 | 
			
		||||
            $table->boolean('is_public')->default(false);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reverse the migrations.
 | 
			
		||||
     */
 | 
			
		||||
    public function down(): void
 | 
			
		||||
    {
 | 
			
		||||
        Schema::table('service_databases', function (Blueprint $table) {
 | 
			
		||||
            $table->dropColumn('public_port');
 | 
			
		||||
            $table->dropColumn('is_public');
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@@ -12,10 +12,19 @@
 | 
			
		||||
            <div class="flex gap-2">
 | 
			
		||||
                <x-forms.input label="Name" id="database.human_name" placeholder="Name"></x-forms.input>
 | 
			
		||||
                <x-forms.input label="Description" id="database.description"></x-forms.input>
 | 
			
		||||
                <x-forms.input required
 | 
			
		||||
                    helper="You can change the image you would like to deploy.<br><br><span class='text-warning'>WARNING. You could corrupt your data. Only do it if you know what you are doing.</span>"
 | 
			
		||||
                    label="Image Tag" id="database.image"></x-forms.input>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="flex gap-2">
 | 
			
		||||
                <x-forms.input required helper="You can change the image you would like to deploy.<br><br><span class='text-warning'>WARNING. You could corrupt your data. Only do it if you know what you are doing.</span>" label="Image Tag"
 | 
			
		||||
                    id="database.image"></x-forms.input>
 | 
			
		||||
            <div class="flex items-end gap-2">
 | 
			
		||||
                @if ($db_url_public)
 | 
			
		||||
                    <x-forms.input label="Database URL (public)"
 | 
			
		||||
                        helper="Your credentials are available in your environment variables." type="password" readonly
 | 
			
		||||
                        wire:model="db_url_public" />
 | 
			
		||||
                @endif
 | 
			
		||||
                <x-forms.input placeholder="5432" disabled="{{ $database->is_public }}" id="database.public_port"
 | 
			
		||||
                    label="Public Port" />
 | 
			
		||||
                <x-forms.checkbox instantSave id="database.is_public" label="Accessible over the internet" />
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <h3 class="pt-2">Advanced</h3>
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
            "version": "3.12.36"
 | 
			
		||||
        },
 | 
			
		||||
        "v4": {
 | 
			
		||||
            "version": "4.0.0-beta.118"
 | 
			
		||||
            "version": "4.0.0-beta.119"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user