diff --git a/app/Actions/Database/RestartDatabase.php b/app/Actions/Database/RestartDatabase.php new file mode 100644 index 000000000..0400d924d --- /dev/null +++ b/app/Actions/Database/RestartDatabase.php @@ -0,0 +1,29 @@ +destination->server; + if (! $server->isFunctional()) { + return 'Server is not functional'; + } + StopDatabase::run($database); + + return StartDatabase::run($database); + } +} diff --git a/app/Actions/Database/StartDatabase.php b/app/Actions/Database/StartDatabase.php new file mode 100644 index 000000000..323c52ff9 --- /dev/null +++ b/app/Actions/Database/StartDatabase.php @@ -0,0 +1,57 @@ +destination->server; + if (! $server->isFunctional()) { + return 'Server is not functional'; + } + switch ($database->getMorphClass()) { + case 'App\Models\StandalonePostgresql': + $activity = StartPostgresql::run($database); + break; + case 'App\Models\StandaloneRedis': + $activity = StartRedis::run($database); + break; + case 'App\Models\StandaloneMongodb': + $activity = StartMongodb::run($database); + break; + case 'App\Models\StandaloneMysql': + $activity = StartMysql::run($database); + break; + case 'App\Models\StandaloneMariadb': + $activity = StartMariadb::run($database); + break; + case 'App\Models\StandaloneKeydb': + $activity = StartKeydb::run($database); + break; + case 'App\Models\StandaloneDragonfly': + $activity = StartDragonfly::run($database); + break; + case 'App\Models\StandaloneClickhouse': + $activity = StartClickhouse::run($database); + break; + } + if ($database->is_public && $database->public_port) { + StartDatabaseProxy::dispatch($database); + } + + return $activity; + } +} diff --git a/app/Actions/Database/StopDatabase.php b/app/Actions/Database/StopDatabase.php index 66a32e811..e4903ff35 100644 --- a/app/Actions/Database/StopDatabase.php +++ b/app/Actions/Database/StopDatabase.php @@ -29,7 +29,5 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St if ($database->is_public) { StopDatabaseProxy::run($database); } - // TODO: make notification for services - // $database->environment->project->team->notify(new StatusChanged($database)); } } diff --git a/app/Actions/Database/StopDatabaseProxy.php b/app/Actions/Database/StopDatabaseProxy.php index 1b262c898..b2092e2ef 100644 --- a/app/Actions/Database/StopDatabaseProxy.php +++ b/app/Actions/Database/StopDatabaseProxy.php @@ -27,7 +27,6 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St $server = data_get($database, 'service.server'); } instant_remote_process(["docker rm -f {$uuid}-proxy"], $server); - $database->is_public = false; $database->save(); DatabaseStatusChanged::dispatch(); } diff --git a/app/Http/Controllers/Api/DatabasesController.php b/app/Http/Controllers/Api/DatabasesController.php index 24530dca6..1a5106d7c 100644 --- a/app/Http/Controllers/Api/DatabasesController.php +++ b/app/Http/Controllers/Api/DatabasesController.php @@ -2,15 +2,10 @@ namespace App\Http\Controllers\Api; -use App\Actions\Database\StartClickhouse; -use App\Actions\Database\StartDragonfly; -use App\Actions\Database\StartKeydb; -use App\Actions\Database\StartMariadb; -use App\Actions\Database\StartMongodb; -use App\Actions\Database\StartMysql; -use App\Actions\Database\StartPostgresql; -use App\Actions\Database\StartRedis; +use App\Actions\Database\StartDatabase; +use App\Actions\Database\StartDatabaseProxy; use App\Actions\Database\StopDatabase; +use App\Actions\Database\StopDatabaseProxy; use App\Enums\NewDatabaseTypes; use App\Http\Controllers\Controller; use App\Models\Project; @@ -82,9 +77,114 @@ public function database_by_uuid(Request $request) ]); } + public function update_by_uuid(Request $request) + { + $allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf', 'clickhouse_admin_user', 'clickhouse_admin_password', 'dragonfly_password', 'redis_password', 'redis_conf', 'keydb_password', 'keydb_conf', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_init_database', 'mysql_root_password', 'mysql_user', 'mysql_database', 'mysql_conf']; + $teamId = getTeamIdFromToken(); + if (is_null($teamId)) { + return invalidTokenResponse(); + } + + $return = validateIncomingRequest($request); + if ($return instanceof \Illuminate\Http\JsonResponse) { + return $return; + } + $validator = customApiValidator($request->all(), [ + 'name' => 'string|max:255', + 'description' => 'string|nullable', + 'image' => 'string', + 'is_public' => 'boolean', + 'public_port' => 'numeric|nullable', + 'limits_memory' => 'string', + 'limits_memory_swap' => 'string', + 'limits_memory_swappiness' => 'numeric', + 'limits_memory_reservation' => 'string', + 'limits_cpus' => 'string', + 'limits_cpuset' => 'string|nullable', + 'limits_cpu_shares' => 'numeric', + 'postgres_user' => 'string', + 'postgres_password' => 'string', + 'postgres_db' => 'string', + 'postgres_initdb_args' => 'string', + 'postgres_host_auth_method' => 'string', + 'postgres_conf' => 'string', + 'clickhouse_admin_user' => 'string', + 'clickhouse_admin_password' => 'string', + 'dragonfly_password' => 'string', + 'redis_password' => 'string', + 'redis_conf' => 'string', + 'keydb_password' => 'string', + 'keydb_conf' => 'string', + 'mariadb_conf' => 'string', + 'mariadb_root_password' => 'string', + 'mariadb_user' => 'string', + 'mariadb_password' => 'string', + 'mariadb_database' => 'string', + 'mongo_conf' => 'string', + 'mongo_initdb_root_username' => 'string', + 'mongo_initdb_root_password' => 'string', + 'mongo_initdb_init_database' => 'string', + 'mysql_root_password' => 'string', + 'mysql_user' => 'string', + 'mysql_database' => 'string', + 'mysql_conf' => 'string', + ]); + + $extraFields = array_diff(array_keys($request->all()), $allowedFields); + if ($validator->fails() || ! empty($extraFields)) { + $errors = $validator->errors(); + if (! empty($extraFields)) { + foreach ($extraFields as $field) { + $errors->add($field, 'This field is not allowed.'); + } + } + + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => $errors, + ], 422); + } + $uuid = $request->uuid; + removeUnnecessaryFieldsFromRequest($request); + $database = queryDatabaseByUuidWithinTeam($uuid, $teamId); + if (! $database) { + return response()->json(['success' => false, 'message' => 'Database not found.'], 404); + } + if ($request->is_public && $request->public_port) { + if (isPublicPortAlreadyUsed($database->destination->server, $request->public_port, $database->id)) { + return response()->json(['success' => false, 'message' => 'Public port already used by another database.'], 400); + } + } + + $whatToDoWithDatabaseProxy = null; + if ($request->is_public === false && $database->is_public === true) { + $whatToDoWithDatabaseProxy = 'stop'; + } + if ($request->is_public === true && $request->public_port && $database->is_public === false) { + $whatToDoWithDatabaseProxy = 'start'; + } + + $database->update($request->all()); + + if ($whatToDoWithDatabaseProxy === 'start') { + StartDatabaseProxy::dispatch($database); + } elseif ($whatToDoWithDatabaseProxy === 'stop') { + StopDatabaseProxy::dispatch($database); + } + + return response()->json([ + 'success' => true, + 'message' => 'Database updated.', + 'data' => $this->removeSensitiveData($database), + ]); + + } + public function create_database(Request $request) { - $allowedFields = ['type', 'name', 'description', 'image', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'postgres_user', 'postgres_password', 'postgres_db', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares']; + $allowedFields = ['type', 'name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf', 'clickhouse_admin_user', 'clickhouse_admin_password', 'dragonfly_password', 'redis_password', 'redis_conf', 'keydb_password', 'keydb_conf', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_init_database', 'mysql_root_password', 'mysql_user', 'mysql_database', 'mysql_conf']; + $teamId = getTeamIdFromToken(); if (is_null($teamId)) { return invalidTokenResponse(); @@ -103,9 +203,8 @@ public function create_database(Request $request) 'environment_name' => 'string|required', 'server_uuid' => 'string|required', 'destination_uuid' => 'string', - 'postgres_user' => 'string', - 'postgres_password' => 'string', - 'postgres_db' => 'string', + 'is_public' => 'boolean', + 'public_port' => 'numeric|nullable', 'limits_memory' => 'string', 'limits_memory_swap' => 'string', 'limits_memory_swappiness' => 'numeric', @@ -113,6 +212,32 @@ public function create_database(Request $request) 'limits_cpus' => 'string', 'limits_cpuset' => 'string|nullable', 'limits_cpu_shares' => 'numeric', + 'postgres_user' => 'string', + 'postgres_password' => 'string', + 'postgres_db' => 'string', + 'postgres_initdb_args' => 'string', + 'postgres_host_auth_method' => 'string', + 'postgres_conf' => 'string', + 'clickhouse_admin_user' => 'string', + 'clickhouse_admin_password' => 'string', + 'dragonfly_password' => 'string', + 'redis_password' => 'string', + 'redis_conf' => 'string', + 'keydb_password' => 'string', + 'keydb_conf' => 'string', + 'mariadb_conf' => 'string', + 'mariadb_root_password' => 'string', + 'mariadb_user' => 'string', + 'mariadb_password' => 'string', + 'mariadb_database' => 'string', + 'mongo_conf' => 'string', + 'mongo_initdb_root_username' => 'string', + 'mongo_initdb_root_password' => 'string', + 'mongo_initdb_init_database' => 'string', + 'mysql_root_password' => 'string', + 'mysql_user' => 'string', + 'mysql_database' => 'string', + 'mysql_conf' => 'string', 'instant_deploy' => 'boolean', ]); @@ -133,7 +258,9 @@ public function create_database(Request $request) } $serverUuid = $request->server_uuid; $instantDeploy = $request->instant_deploy ?? false; - + if ($request->is_public && ! $request->public_port) { + $request->offsetSet('is_public', false); + } $project = Project::whereTeamId($teamId)->whereUuid($request->project_uuid)->first(); if (! $project) { return response()->json(['succes' => false, 'message' => 'Project not found.'], 404); @@ -154,12 +281,41 @@ public function create_database(Request $request) return response()->json(['success' => false, 'message' => 'Server has multiple destinations and you do not set destination_uuid.'], 400); } $destination = $destinations->first(); - + if ($request->has('public_port') && $request->is_public) { + if (isPublicPortAlreadyUsed($server, $request->public_port)) { + return response()->json(['success' => false, 'message' => 'Public port already used by another database.'], 400); + } + } if ($request->type === NewDatabaseTypes::POSTGRESQL->value) { removeUnnecessaryFieldsFromRequest($request); + if ($request->has('postgres_conf')) { + if (! isBase64Encoded($request->postgres_conf)) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'postgres_conf' => 'The postgres_conf should be base64 encoded.', + ], + ], 422); + } + $postgresConf = base64_decode($request->postgres_conf); + if (mb_detect_encoding($postgresConf, 'ASCII', true) === false) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'postgres_conf' => 'The postgres_conf should be base64 encoded.', + ], + ], 422); + } + $request->offsetSet('postgres_conf', $postgresConf); + } $database = create_standalone_postgresql($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { - StartPostgresql::dispatch($database); + StartDatabase::dispatch($database); + if ($request->is_public && $request->public_port) { + StartDatabaseProxy::dispatch($database); + } } return response()->json([ @@ -169,9 +325,34 @@ public function create_database(Request $request) ]); } elseif ($request->type === NewDatabaseTypes::MARIADB->value) { removeUnnecessaryFieldsFromRequest($request); + if ($request->has('mariadb_conf')) { + if (! isBase64Encoded($request->mariadb_conf)) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'mariadb_conf' => 'The mariadb_conf should be base64 encoded.', + ], + ], 422); + } + $mariadbConf = base64_decode($request->mariadb_conf); + if (mb_detect_encoding($mariadbConf, 'ASCII', true) === false) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'mariadb_conf' => 'The mariadb_conf should be base64 encoded.', + ], + ], 422); + } + $request->offsetSet('mariadb_conf', $mariadbConf); + } $database = create_standalone_mariadb($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { - StartMariadb::dispatch($database); + StartDatabase::dispatch($database); + if ($request->is_public && $request->public_port) { + StartDatabaseProxy::dispatch($database); + } } return response()->json([ @@ -181,9 +362,34 @@ public function create_database(Request $request) ]); } elseif ($request->type === NewDatabaseTypes::MYSQL->value) { removeUnnecessaryFieldsFromRequest($request); + if ($request->has('mysql_conf')) { + if (! isBase64Encoded($request->mysql_conf)) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'mysql_conf' => 'The mysql_conf should be base64 encoded.', + ], + ], 422); + } + $mysqlConf = base64_decode($request->mysql_conf); + if (mb_detect_encoding($mysqlConf, 'ASCII', true) === false) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'mysql_conf' => 'The mysql_conf should be base64 encoded.', + ], + ], 422); + } + $request->offsetSet('mysql_conf', $mysqlConf); + } $database = create_standalone_mysql($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { - StartMysql::dispatch($database); + StartDatabase::dispatch($database); + if ($request->is_public && $request->public_port) { + StartDatabaseProxy::dispatch($database); + } } return response()->json([ @@ -193,9 +399,34 @@ public function create_database(Request $request) ]); } elseif ($request->type === NewDatabaseTypes::REDIS->value) { removeUnnecessaryFieldsFromRequest($request); + if ($request->has('redis_conf')) { + if (! isBase64Encoded($request->redis_conf)) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'redis_conf' => 'The redis_conf should be base64 encoded.', + ], + ], 422); + } + $redisConf = base64_decode($request->redis_conf); + if (mb_detect_encoding($redisConf, 'ASCII', true) === false) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'redis_conf' => 'The redis_conf should be base64 encoded.', + ], + ], 422); + } + $request->offsetSet('redis_conf', $redisConf); + } $database = create_standalone_redis($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { - StartRedis::dispatch($database); + StartDatabase::dispatch($database); + if ($request->is_public && $request->public_port) { + StartDatabaseProxy::dispatch($database); + } } return response()->json([ @@ -207,7 +438,10 @@ public function create_database(Request $request) removeUnnecessaryFieldsFromRequest($request); $database = create_standalone_dragonfly($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { - StartDragonfly::dispatch($database); + StartDatabase::dispatch($database); + if ($request->is_public && $request->public_port) { + StartDatabaseProxy::dispatch($database); + } } return response()->json([ @@ -217,9 +451,34 @@ public function create_database(Request $request) ]); } elseif ($request->type === NewDatabaseTypes::KEYDB->value) { removeUnnecessaryFieldsFromRequest($request); + if ($request->has('keydb_conf')) { + if (! isBase64Encoded($request->keydb_conf)) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'keydb_conf' => 'The keydb_conf should be base64 encoded.', + ], + ], 422); + } + $keydbConf = base64_decode($request->keydb_conf); + if (mb_detect_encoding($keydbConf, 'ASCII', true) === false) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'keydb_conf' => 'The keydb_conf should be base64 encoded.', + ], + ], 422); + } + $request->offsetSet('keydb_conf', $keydbConf); + } $database = create_standalone_keydb($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { - StartKeydb::dispatch($database); + StartDatabase::dispatch($database); + if ($request->is_public && $request->public_port) { + StartDatabaseProxy::dispatch($database); + } } return response()->json([ @@ -231,7 +490,10 @@ public function create_database(Request $request) removeUnnecessaryFieldsFromRequest($request); $database = create_standalone_clickhouse($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { - StartClickhouse::dispatch($database); + StartDatabase::dispatch($database); + if ($request->is_public && $request->public_port) { + StartDatabaseProxy::dispatch($database); + } } return response()->json([ @@ -241,9 +503,34 @@ public function create_database(Request $request) ]); } elseif ($request->type === NewDatabaseTypes::MONGODB->value) { removeUnnecessaryFieldsFromRequest($request); + if ($request->has('mongo_conf')) { + if (! isBase64Encoded($request->mongo_conf)) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'mongo_conf' => 'The mongo_conf should be base64 encoded.', + ], + ], 422); + } + $mongoConf = base64_decode($request->mongo_conf); + if (mb_detect_encoding($mongoConf, 'ASCII', true) === false) { + return response()->json([ + 'success' => false, + 'message' => 'Validation failed.', + 'errors' => [ + 'mongo_conf' => 'The mongo_conf should be base64 encoded.', + ], + ], 422); + } + $request->offsetSet('mongo_conf', $mongoConf); + } $database = create_standalone_mongodb($environment->id, $destination->uuid, $request->all()); if ($instantDeploy) { - StartMongodb::dispatch($database); + StartDatabase::dispatch($database); + if ($request->is_public && $request->public_port) { + StartDatabaseProxy::dispatch($database); + } } return response()->json([ diff --git a/app/Http/Controllers/Api/DeployController.php b/app/Http/Controllers/Api/DeployController.php index 7add22bd0..79d98df0c 100644 --- a/app/Http/Controllers/Api/DeployController.php +++ b/app/Http/Controllers/Api/DeployController.php @@ -2,14 +2,7 @@ namespace App\Http\Controllers\Api; -use App\Actions\Database\StartClickhouse; -use App\Actions\Database\StartDragonfly; -use App\Actions\Database\StartKeydb; -use App\Actions\Database\StartMariadb; -use App\Actions\Database\StartMongodb; -use App\Actions\Database\StartMysql; -use App\Actions\Database\StartPostgresql; -use App\Actions\Database\StartRedis; +use App\Actions\Database\StartDatabase; use App\Actions\Service\StartService; use App\Http\Controllers\Controller; use App\Models\ApplicationDeploymentQueue; @@ -192,66 +185,28 @@ public function deploy_resource($resource, bool $force = false): array if (gettype($resource) !== 'object') { return ['success' => false, 'message' => "Resource ($resource) not found.", 'deployment_uuid' => $deployment_uuid]; } - $type = $resource?->getMorphClass(); - if ($type === 'App\Models\Application') { - $deployment_uuid = new Cuid2(7); - queue_application_deployment( - application: $resource, - deployment_uuid: $deployment_uuid, - force_rebuild: $force, - ); - $message = "Application {$resource->name} deployment queued."; - } elseif ($type === 'App\Models\StandalonePostgresql') { - StartPostgresql::run($resource); - $resource->update([ - 'started_at' => now(), - ]); - $message = "Database {$resource->name} started."; - } elseif ($type === 'App\Models\StandaloneRedis') { - StartRedis::run($resource); - $resource->update([ - 'started_at' => now(), - ]); - $message = "Database {$resource->name} started."; - } elseif ($type === 'App\Models\StandaloneKeydb') { - StartKeydb::run($resource); - $resource->update([ - 'started_at' => now(), - ]); - $message = "Database {$resource->name} started."; - } elseif ($type === 'App\Models\StandaloneDragonfly') { - StartDragonfly::run($resource); - $resource->update([ - 'started_at' => now(), - ]); - $message = "Database {$resource->name} started."; - } elseif ($type === 'App\Models\StandaloneClickhouse') { - StartClickhouse::run($resource); - $resource->update([ - 'started_at' => now(), - ]); - $message = "Database {$resource->name} started."; - } elseif ($type === 'App\Models\StandaloneMongodb') { - StartMongodb::run($resource); - $resource->update([ - 'started_at' => now(), - ]); - $message = "Database {$resource->name} started."; - } elseif ($type === 'App\Models\StandaloneMysql') { - StartMysql::run($resource); - $resource->update([ - 'started_at' => now(), - ]); - $message = "Database {$resource->name} started."; - } elseif ($type === 'App\Models\StandaloneMariadb') { - StartMariadb::run($resource); - $resource->update([ - 'started_at' => now(), - ]); - $message = "Database {$resource->name} started."; - } elseif ($type === 'App\Models\Service') { - StartService::run($resource); - $message = "Service {$resource->name} started. It could take a while, be patient."; + switch ($resource?->getMorphClass()) { + case 'App\Models\Application': + $deployment_uuid = new Cuid2(7); + queue_application_deployment( + application: $resource, + deployment_uuid: $deployment_uuid, + force_rebuild: $force, + ); + $message = "Application {$resource->name} deployment queued."; + break; + case 'App\Models\Service': + StartService::run($resource); + $message = "Service {$resource->name} started. It could take a while, be patient."; + break; + default: + // Database resource + StartDatabase::dispatch($resource); + $resource->update([ + 'started_at' => now(), + ]); + $message = "Database {$resource->name} started."; + break; } return ['success' => true, 'message' => $message, 'deployment_uuid' => $deployment_uuid]; diff --git a/app/Livewire/Project/Database/Heading.php b/app/Livewire/Project/Database/Heading.php index ae88ac12b..6435f6781 100644 --- a/app/Livewire/Project/Database/Heading.php +++ b/app/Livewire/Project/Database/Heading.php @@ -2,14 +2,8 @@ namespace App\Livewire\Project\Database; -use App\Actions\Database\StartClickhouse; -use App\Actions\Database\StartDragonfly; -use App\Actions\Database\StartKeydb; -use App\Actions\Database\StartMariadb; -use App\Actions\Database\StartMongodb; -use App\Actions\Database\StartMysql; -use App\Actions\Database\StartPostgresql; -use App\Actions\Database\StartRedis; +use App\Actions\Database\RestartDatabase; +use App\Actions\Database\StartDatabase; use App\Actions\Database\StopDatabase; use App\Actions\Docker\GetContainersStatus; use Livewire\Component; @@ -47,7 +41,6 @@ public function activityFinished() public function check_status($showNotification = false) { GetContainersStatus::run($this->database->destination->server); - // dispatch_sync(new ContainerStatusJob($this->database->destination->server)); $this->database->refresh(); if ($showNotification) { $this->dispatch('success', 'Database status updated.'); @@ -67,32 +60,15 @@ public function stop() $this->check_status(); } + public function restart() + { + $activity = RestartDatabase::run($this->database); + $this->dispatch('activityMonitor', $activity->id); + } + public function start() { - if ($this->database->type() === 'standalone-postgresql') { - $activity = StartPostgresql::run($this->database); - $this->dispatch('activityMonitor', $activity->id); - } elseif ($this->database->type() === 'standalone-redis') { - $activity = StartRedis::run($this->database); - $this->dispatch('activityMonitor', $activity->id); - } elseif ($this->database->type() === 'standalone-mongodb') { - $activity = StartMongodb::run($this->database); - $this->dispatch('activityMonitor', $activity->id); - } elseif ($this->database->type() === 'standalone-mysql') { - $activity = StartMysql::run($this->database); - $this->dispatch('activityMonitor', $activity->id); - } elseif ($this->database->type() === 'standalone-mariadb') { - $activity = StartMariadb::run($this->database); - $this->dispatch('activityMonitor', $activity->id); - } elseif ($this->database->type() === 'standalone-keydb') { - $activity = StartKeydb::run($this->database); - $this->dispatch('activityMonitor', $activity->id); - } elseif ($this->database->type() === 'standalone-dragonfly') { - $activity = StartDragonfly::run($this->database); - $this->dispatch('activityMonitor', $activity->id); - } elseif ($this->database->type() === 'standalone-clickhouse') { - $activity = StartClickhouse::run($this->database); - $this->dispatch('activityMonitor', $activity->id); - } + $activity = StartDatabase::run($this->database); + $this->dispatch('activityMonitor', $activity->id); } } diff --git a/app/Livewire/Project/Database/Postgresql/General.php b/app/Livewire/Project/Database/Postgresql/General.php index 76bc97901..eabbbd679 100644 --- a/app/Livewire/Project/Database/Postgresql/General.php +++ b/app/Livewire/Project/Database/Postgresql/General.php @@ -27,10 +27,7 @@ class General extends Component public function getListeners() { - $userId = auth()->user()->id; - return [ - "echo-private:user.{$userId},DatabaseStatusChanged" => 'database_stopped', 'refresh', 'save_init_script', 'delete_init_script', @@ -77,11 +74,6 @@ public function mount() $this->server = data_get($this->database, 'destination.server'); } - public function database_stopped() - { - $this->dispatch('success', 'Database proxy stopped. Database is no longer publicly accessible.'); - } - public function instantSaveAdvanced() { try { diff --git a/bootstrap/helpers/api.php b/bootstrap/helpers/api.php index 00fccda74..e4da4a563 100644 --- a/bootstrap/helpers/api.php +++ b/bootstrap/helpers/api.php @@ -151,6 +151,14 @@ function validateIncomingRequest(Request $request) 'error' => 'Invalid JSON.', ], 400); } + // check if valid json is empty + if (empty($request->json()->all())) { + return response()->json([ + 'success' => false, + 'message' => 'Invalid request.', + 'error' => 'Empty JSON.', + ], 400); + } } function removeUnnecessaryFieldsFromRequest(Request $request) diff --git a/bootstrap/helpers/databases.php b/bootstrap/helpers/databases.php index ef3f8ac9b..089298956 100644 --- a/bootstrap/helpers/databases.php +++ b/bootstrap/helpers/databases.php @@ -178,9 +178,6 @@ function create_standalone_clickhouse($environment_id, $destination_uuid, ?array return $database; } -/** - * Delete file locally on the filesystem. - */ function delete_backup_locally(?string $filename, Server $server): void { if (empty($filename)) { @@ -188,3 +185,17 @@ function delete_backup_locally(?string $filename, Server $server): void } instant_remote_process(["rm -f \"{$filename}\""], $server, throwError: false); } + +function isPublicPortAlreadyUsed(Server $server, int $port, ?string $id = null): bool +{ + if ($id) { + $foundDatabase = $server->databases()->where('public_port', $port)->where('is_public', true)->where('id', '!=', $id)->first(); + } else { + $foundDatabase = $server->databases()->where('public_port', $port)->where('is_public', true)->first(); + } + if ($foundDatabase) { + return true; + } + + return false; +} diff --git a/resources/views/livewire/project/database/heading.blade.php b/resources/views/livewire/project/database/heading.blade.php index 0c0647324..cee1f0520 100644 --- a/resources/views/livewire/project/database/heading.blade.php +++ b/resources/views/livewire/project/database/heading.blade.php @@ -7,7 +7,8 @@