mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
fix(databases): show custom configuration only to admins (#12353)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
bc0cb1b37d
commit
fae2752346
@@ -251,6 +251,7 @@ class DatabasesController extends Controller
|
||||
'mysql_root_password',
|
||||
'mariadb_password',
|
||||
'mariadb_root_password',
|
||||
...$database::CONFIGURATION_ATTRIBUTES,
|
||||
]);
|
||||
$this->exposeNestedServerSecrets($database);
|
||||
} else {
|
||||
|
||||
@@ -137,17 +137,17 @@ class General extends Component
|
||||
$this->database->save();
|
||||
$this->dispatch('name-changed', uuid: $this->database->uuid, name: $this->database->name);
|
||||
} else {
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->name = $this->database->name;
|
||||
$this->description = $this->database->description;
|
||||
$this->clickhouseAdminUser = $this->database->clickhouse_admin_user;
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->clickhouseAdminPassword = $canSeeCredentials ? $this->database->clickhouse_admin_password : '';
|
||||
$this->image = $this->database->image;
|
||||
$this->portsMappings = $this->database->ports_mappings;
|
||||
$this->isPublic = $this->database->is_public;
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->customDockerRunOptions = $canSeeCredentials ? $this->database->custom_docker_run_options : null;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,16 +124,16 @@ class General extends Component
|
||||
$this->database->save();
|
||||
$this->dispatch('name-changed', uuid: $this->database->uuid, name: $this->database->name);
|
||||
} else {
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->name = $this->database->name;
|
||||
$this->description = $this->database->description;
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->dragonflyPassword = $canSeeCredentials ? $this->database->dragonfly_password : '';
|
||||
$this->image = $this->database->image;
|
||||
$this->portsMappings = $this->database->ports_mappings;
|
||||
$this->isPublic = $this->database->is_public;
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->customDockerRunOptions = $canSeeCredentials ? $this->database->custom_docker_run_options : null;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,9 +128,9 @@ class General extends Component
|
||||
$this->database->save();
|
||||
$this->dispatch('name-changed', uuid: $this->database->uuid, name: $this->database->name);
|
||||
} else {
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->name = $this->database->name;
|
||||
$this->description = $this->database->description;
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->keydbConf = $canSeeCredentials ? $this->database->keydb_conf : null;
|
||||
$this->keydbPassword = $canSeeCredentials ? $this->database->keydb_password : '';
|
||||
$this->image = $this->database->image;
|
||||
@@ -138,7 +138,7 @@ class General extends Component
|
||||
$this->isPublic = $this->database->is_public;
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->customDockerRunOptions = $canSeeCredentials ? $this->database->custom_docker_run_options : null;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,9 +153,9 @@ class General extends Component
|
||||
$this->database->save();
|
||||
$this->dispatch('name-changed', uuid: $this->database->uuid, name: $this->database->name);
|
||||
} else {
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->name = $this->database->name;
|
||||
$this->description = $this->database->description;
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->mariadbRootPassword = $canSeeCredentials ? $this->database->mariadb_root_password : '';
|
||||
$this->mariadbUser = $this->database->mariadb_user;
|
||||
$this->mariadbPassword = $canSeeCredentials ? $this->database->mariadb_password : '';
|
||||
@@ -167,7 +167,7 @@ class General extends Component
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->customDockerRunOptions = $canSeeCredentials ? $this->database->custom_docker_run_options : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -145,9 +145,9 @@ class General extends Component
|
||||
$this->database->save();
|
||||
$this->dispatch('name-changed', uuid: $this->database->uuid, name: $this->database->name);
|
||||
} else {
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->name = $this->database->name;
|
||||
$this->description = $this->database->description;
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->mongoConf = $canSeeCredentials ? $this->database->mongo_conf : null;
|
||||
$this->mongoInitdbRootUsername = $this->database->mongo_initdb_root_username;
|
||||
$this->mongoInitdbRootPassword = $canSeeCredentials ? $this->database->mongo_initdb_root_password : '';
|
||||
@@ -158,7 +158,7 @@ class General extends Component
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->customDockerRunOptions = $canSeeCredentials ? $this->database->custom_docker_run_options : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,9 +153,9 @@ class General extends Component
|
||||
$this->database->save();
|
||||
$this->dispatch('name-changed', uuid: $this->database->uuid, name: $this->database->name);
|
||||
} else {
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->name = $this->database->name;
|
||||
$this->description = $this->database->description;
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->mysqlRootPassword = $canSeeCredentials ? $this->database->mysql_root_password : '';
|
||||
$this->mysqlUser = $this->database->mysql_user;
|
||||
$this->mysqlPassword = $canSeeCredentials ? $this->database->mysql_password : '';
|
||||
@@ -167,7 +167,7 @@ class General extends Component
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->customDockerRunOptions = $canSeeCredentials ? $this->database->custom_docker_run_options : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -169,10 +169,10 @@ class General extends Component
|
||||
$this->database->save();
|
||||
$this->dispatch('name-changed', uuid: $this->database->uuid, name: $this->database->name);
|
||||
} else {
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->name = $this->database->name;
|
||||
$this->description = $this->database->description;
|
||||
$this->postgresUser = $this->database->postgres_user;
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->postgresPassword = $canSeeCredentials ? $this->database->postgres_password : '';
|
||||
$this->postgresDb = $this->database->postgres_db;
|
||||
$this->postgresInitdbArgs = $this->database->postgres_initdb_args;
|
||||
@@ -185,7 +185,7 @@ class General extends Component
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->customDockerRunOptions = $canSeeCredentials ? $this->database->custom_docker_run_options : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,7 @@ class General extends Component
|
||||
$this->database->save();
|
||||
$this->dispatch('name-changed', uuid: $this->database->uuid, name: $this->database->name);
|
||||
} else {
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->name = $this->database->name;
|
||||
$this->description = $this->database->description;
|
||||
$this->image = $this->database->image;
|
||||
@@ -154,10 +155,9 @@ class General extends Component
|
||||
$this->publicPort = $this->database->public_port;
|
||||
$this->publicPortTimeout = $this->database->public_port_timeout;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->customDockerRunOptions = $canSeeCredentials ? $this->database->custom_docker_run_options : null;
|
||||
$this->redisVersion = $this->database->getRedisVersion();
|
||||
$this->redisUsername = $this->database->redis_username;
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->redisConf = $canSeeCredentials ? $this->database->redis_conf : null;
|
||||
$this->isPasswordLocked = $this->database->isCredentialLocked();
|
||||
$this->redisPassword = $canSeeCredentials && ! $this->isPasswordLocked ? $this->database->redis_password : null;
|
||||
|
||||
@@ -29,6 +29,8 @@ class General extends Component
|
||||
|
||||
public bool $isLogDrainEnabled = false;
|
||||
|
||||
public bool $isPasswordHiddenForMember = false;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
try {
|
||||
@@ -43,6 +45,8 @@ class General extends Component
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
$this->isPasswordHiddenForMember = ! (auth()->user()?->can('update', $this->database) ?? false);
|
||||
}
|
||||
|
||||
protected function rules(): array
|
||||
@@ -83,11 +87,12 @@ class General extends Component
|
||||
$this->database->save();
|
||||
$this->dispatch('name-changed', uuid: $this->database->uuid, name: $this->database->name);
|
||||
} else {
|
||||
$canSeeCredentials = auth()->user()?->can('update', $this->database) ?? false;
|
||||
$this->name = $this->database->name;
|
||||
$this->description = $this->database->description;
|
||||
$this->sqliteDatabases = $this->database->sqlite_databases;
|
||||
$this->image = $this->database->image;
|
||||
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
|
||||
$this->customDockerRunOptions = $canSeeCredentials ? $this->database->custom_docker_run_options : null;
|
||||
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,14 @@ class StandaloneClickhouse extends BaseModel
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
/**
|
||||
* Free-form configuration that can embed credentials. Only users who can
|
||||
* update the database and `read:sensitive` tokens may read it.
|
||||
*/
|
||||
public const CONFIGURATION_ATTRIBUTES = [
|
||||
'custom_docker_run_options',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sensitive fields hidden by default in serialized output (toArray/toJson).
|
||||
* API controllers should call makeVisible([...]) for callers with the
|
||||
@@ -69,6 +77,7 @@ class StandaloneClickhouse extends BaseModel
|
||||
*/
|
||||
protected $hidden = [
|
||||
'clickhouse_admin_password',
|
||||
...self::CONFIGURATION_ATTRIBUTES,
|
||||
'internal_db_url',
|
||||
'external_db_url',
|
||||
];
|
||||
|
||||
@@ -56,6 +56,14 @@ class StandaloneDragonfly extends BaseModel
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
/**
|
||||
* Free-form configuration that can embed credentials. Only users who can
|
||||
* update the database and `read:sensitive` tokens may read it.
|
||||
*/
|
||||
public const CONFIGURATION_ATTRIBUTES = [
|
||||
'custom_docker_run_options',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sensitive fields hidden by default in serialized output (toArray/toJson).
|
||||
* API controllers should call makeVisible([...]) for callers with the
|
||||
@@ -63,6 +71,7 @@ class StandaloneDragonfly extends BaseModel
|
||||
*/
|
||||
protected $hidden = [
|
||||
'dragonfly_password',
|
||||
...self::CONFIGURATION_ATTRIBUTES,
|
||||
'internal_db_url',
|
||||
'external_db_url',
|
||||
// Internal start-command state, not part of the API.
|
||||
|
||||
@@ -57,6 +57,15 @@ class StandaloneKeydb extends BaseModel
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
/**
|
||||
* Free-form configuration that can embed credentials. Only users who can
|
||||
* update the database and `read:sensitive` tokens may read it.
|
||||
*/
|
||||
public const CONFIGURATION_ATTRIBUTES = [
|
||||
'keydb_conf',
|
||||
'custom_docker_run_options',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sensitive fields hidden by default in serialized output (toArray/toJson).
|
||||
* API controllers should call makeVisible([...]) for callers with the
|
||||
@@ -64,6 +73,7 @@ class StandaloneKeydb extends BaseModel
|
||||
*/
|
||||
protected $hidden = [
|
||||
'keydb_password',
|
||||
...self::CONFIGURATION_ATTRIBUTES,
|
||||
'internal_db_url',
|
||||
'external_db_url',
|
||||
// Internal start-command state, not part of the API.
|
||||
|
||||
@@ -60,6 +60,15 @@ class StandaloneMariadb extends BaseModel
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
/**
|
||||
* Free-form configuration that can embed credentials. Only users who can
|
||||
* update the database and `read:sensitive` tokens may read it.
|
||||
*/
|
||||
public const CONFIGURATION_ATTRIBUTES = [
|
||||
'mariadb_conf',
|
||||
'custom_docker_run_options',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sensitive fields hidden by default in serialized output (toArray/toJson).
|
||||
* API controllers should call makeVisible([...]) for callers with the
|
||||
@@ -68,6 +77,7 @@ class StandaloneMariadb extends BaseModel
|
||||
protected $hidden = [
|
||||
'mariadb_password',
|
||||
'mariadb_root_password',
|
||||
...self::CONFIGURATION_ATTRIBUTES,
|
||||
'internal_db_url',
|
||||
'external_db_url',
|
||||
];
|
||||
|
||||
@@ -60,6 +60,15 @@ class StandaloneMongodb extends BaseModel
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
/**
|
||||
* Free-form configuration that can embed credentials. Only users who can
|
||||
* update the database and `read:sensitive` tokens may read it.
|
||||
*/
|
||||
public const CONFIGURATION_ATTRIBUTES = [
|
||||
'mongo_conf',
|
||||
'custom_docker_run_options',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sensitive fields hidden by default in serialized output (toArray/toJson).
|
||||
* API controllers should call makeVisible([...]) for callers with the
|
||||
@@ -67,6 +76,7 @@ class StandaloneMongodb extends BaseModel
|
||||
*/
|
||||
protected $hidden = [
|
||||
'mongo_initdb_root_password',
|
||||
...self::CONFIGURATION_ATTRIBUTES,
|
||||
'internal_db_url',
|
||||
'external_db_url',
|
||||
];
|
||||
|
||||
@@ -61,6 +61,15 @@ class StandaloneMysql extends BaseModel
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
/**
|
||||
* Free-form configuration that can embed credentials. Only users who can
|
||||
* update the database and `read:sensitive` tokens may read it.
|
||||
*/
|
||||
public const CONFIGURATION_ATTRIBUTES = [
|
||||
'mysql_conf',
|
||||
'custom_docker_run_options',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sensitive fields hidden by default in serialized output (toArray/toJson).
|
||||
* API controllers should call makeVisible([...]) for callers with the
|
||||
@@ -69,6 +78,7 @@ class StandaloneMysql extends BaseModel
|
||||
protected $hidden = [
|
||||
'mysql_password',
|
||||
'mysql_root_password',
|
||||
...self::CONFIGURATION_ATTRIBUTES,
|
||||
'internal_db_url',
|
||||
'external_db_url',
|
||||
];
|
||||
|
||||
@@ -63,6 +63,15 @@ class StandalonePostgresql extends BaseModel
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
/**
|
||||
* Free-form configuration that can embed credentials. Only users who can
|
||||
* update the database and `read:sensitive` tokens may read it.
|
||||
*/
|
||||
public const CONFIGURATION_ATTRIBUTES = [
|
||||
'postgres_conf',
|
||||
'custom_docker_run_options',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sensitive fields hidden by default in serialized output (toArray/toJson).
|
||||
* API controllers should call makeVisible([...]) for callers with the
|
||||
@@ -71,6 +80,7 @@ class StandalonePostgresql extends BaseModel
|
||||
protected $hidden = [
|
||||
'postgres_password',
|
||||
'init_scripts',
|
||||
...self::CONFIGURATION_ATTRIBUTES,
|
||||
'internal_db_url',
|
||||
'external_db_url',
|
||||
];
|
||||
|
||||
@@ -58,6 +58,15 @@ class StandaloneRedis extends BaseModel
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
/**
|
||||
* Free-form configuration that can embed credentials. Only users who can
|
||||
* update the database and `read:sensitive` tokens may read it.
|
||||
*/
|
||||
public const CONFIGURATION_ATTRIBUTES = [
|
||||
'redis_conf',
|
||||
'custom_docker_run_options',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sensitive fields hidden by default in serialized output (toArray/toJson).
|
||||
* API controllers should call makeVisible([...]) for callers with the
|
||||
@@ -65,6 +74,7 @@ class StandaloneRedis extends BaseModel
|
||||
*/
|
||||
protected $hidden = [
|
||||
'redis_password',
|
||||
...self::CONFIGURATION_ATTRIBUTES,
|
||||
'internal_db_url',
|
||||
'external_db_url',
|
||||
// Internal start-command state, not part of the API.
|
||||
|
||||
@@ -57,6 +57,23 @@ class StandaloneSqlite extends BaseModel
|
||||
'health_check_start_period',
|
||||
];
|
||||
|
||||
/**
|
||||
* Free-form configuration that can embed credentials. Only users who can
|
||||
* update the database and `read:sensitive` tokens may read it.
|
||||
*/
|
||||
public const CONFIGURATION_ATTRIBUTES = [
|
||||
'custom_docker_run_options',
|
||||
];
|
||||
|
||||
/**
|
||||
* Sensitive fields hidden by default in serialized output (toArray/toJson).
|
||||
* API controllers should call makeVisible([...]) for callers with the
|
||||
* `read:sensitive` or `root` token ability.
|
||||
*/
|
||||
protected $hidden = [
|
||||
...self::CONFIGURATION_ATTRIBUTES,
|
||||
];
|
||||
|
||||
protected $appends = ['database_type', 'server_status'];
|
||||
|
||||
protected $casts = [
|
||||
|
||||
@@ -104,11 +104,15 @@
|
||||
|
||||
<x-application.settings-section id="container-section" title="Container"
|
||||
description="Docker options and log forwarding for the database container.">
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom Docker options" disabled value="Hidden (only admins can view)" />
|
||||
@else
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@endif
|
||||
<x-application.settings-subsection id="log-delivery-section" title="Log delivery" helper="Forward container logs to the drain configured on the server.">
|
||||
<x-forms.listbox canGate="update" :canResource="$database" id="isLogDrainEnabled" label="Log drain" live onChange="instantSaveAdvanced"
|
||||
:disabled="! auth()->user()->can('update', $database)" :options="[
|
||||
|
||||
@@ -82,11 +82,15 @@
|
||||
|
||||
<x-application.settings-section id="container-section" title="Container"
|
||||
description="Docker options and log forwarding for the database container.">
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom Docker options" disabled value="Hidden (only admins can view)" />
|
||||
@else
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@endif
|
||||
<x-application.settings-subsection id="log-delivery-section" title="Log delivery" helper="Forward container logs to the drain configured on the server.">
|
||||
<x-forms.listbox canGate="update" :canResource="$database" id="isLogDrainEnabled" label="Log drain" live onChange="instantSaveAdvanced"
|
||||
:disabled="! auth()->user()->can('update', $database)" :options="[
|
||||
|
||||
@@ -83,11 +83,15 @@
|
||||
|
||||
<x-application.settings-section id="container-section" title="Container"
|
||||
description="Docker options, configuration, and log forwarding for the database container.">
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom Docker options" disabled value="Hidden (only admins can view)" />
|
||||
@else
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@endif
|
||||
<x-application.settings-subsection id="configuration-section" title="Configuration" helper="Override only the KeyDB directives you need. All other defaults remain active.">
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom KeyDB configuration" disabled value="Hidden (only admins can view)" />
|
||||
|
||||
@@ -88,11 +88,15 @@
|
||||
|
||||
<x-application.settings-section id="container-section" title="Container"
|
||||
description="Docker options, configuration, and log forwarding for the database container.">
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom Docker options" disabled value="Hidden (only admins can view)" />
|
||||
@else
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@endif
|
||||
<x-application.settings-subsection id="configuration-section" title="Configuration" helper="Override the MariaDB configuration used by this container.">
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom MariaDB configuration" disabled value="Hidden (only admins can view)" />
|
||||
|
||||
@@ -85,11 +85,15 @@
|
||||
|
||||
<x-application.settings-section id="container-section" title="Container"
|
||||
description="Docker options, configuration, and log forwarding for the database container.">
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom Docker options" disabled value="Hidden (only admins can view)" />
|
||||
@else
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@endif
|
||||
<x-application.settings-subsection id="configuration-section" title="Configuration" helper="Override the MongoDB configuration used by this container.">
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom MongoDB configuration" disabled value="Hidden (only admins can view)" />
|
||||
|
||||
@@ -88,11 +88,15 @@
|
||||
|
||||
<x-application.settings-section id="container-section" title="Container"
|
||||
description="Docker options, configuration, and log forwarding for the database container.">
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom Docker options" disabled value="Hidden (only admins can view)" />
|
||||
@else
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@endif
|
||||
<x-application.settings-subsection id="configuration-section" title="Configuration" helper="Override the MySQL configuration used by this container.">
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom MySQL configuration" disabled value="Hidden (only admins can view)" />
|
||||
|
||||
@@ -90,11 +90,15 @@
|
||||
|
||||
<x-application.settings-section id="container-section" title="Container"
|
||||
description="Docker options, configuration, and log forwarding for the database container.">
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom Docker options" disabled value="Hidden (only admins can view)" />
|
||||
@else
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@endif
|
||||
<x-application.settings-subsection id="configuration-section" title="Configuration" helper="Override the PostgreSQL configuration used by this container.">
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom PostgreSQL configuration" disabled value="Hidden (only admins can view)" />
|
||||
|
||||
@@ -90,11 +90,15 @@
|
||||
|
||||
<x-application.settings-section id="container-section" title="Container"
|
||||
description="Docker options, configuration, and log forwarding for the database container.">
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom Docker options" disabled value="Hidden (only admins can view)" />
|
||||
@else
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@endif
|
||||
<x-application.settings-subsection id="configuration-section" title="Configuration" helper="Override only the Redis directives you need. All other defaults remain active.">
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom Redis configuration" disabled value="Hidden (only admins can view)" />
|
||||
|
||||
@@ -31,11 +31,15 @@
|
||||
|
||||
<x-application.settings-section id="container-section" title="Container"
|
||||
description="Docker options and log forwarding for the database container.">
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@if ($isPasswordHiddenForMember)
|
||||
<x-forms.input label="Custom Docker options" disabled value="Hidden (only admins can view)" />
|
||||
@else
|
||||
<x-forms.input
|
||||
helper="Add supported docker run options used when the container starts. Unsupported options can interfere with Coolify automation."
|
||||
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse"
|
||||
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
|
||||
:canResource="$database" />
|
||||
@endif
|
||||
<x-application.settings-subsection id="log-delivery-section" title="Log delivery" helper="Forward container logs to the drain configured on the server.">
|
||||
<x-forms.listbox canGate="update" :canResource="$database" id="isLogDrainEnabled" label="Log drain" live onChange="instantSaveAdvanced"
|
||||
:disabled="! auth()->user()->can('update', $database)" :options="[
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use App\Livewire\Project\Database\Clickhouse\General as ClickhouseGeneral;
|
||||
use App\Livewire\Project\Database\Dragonfly\General as DragonflyGeneral;
|
||||
use App\Livewire\Project\Database\Dragonfly\StatusInfo as DragonflyStatusInfo;
|
||||
use App\Livewire\Project\Database\Keydb\General as KeydbGeneral;
|
||||
use App\Livewire\Project\Database\Keydb\StatusInfo as KeydbStatusInfo;
|
||||
@@ -9,6 +11,7 @@ use App\Livewire\Project\Database\Mysql\General as MysqlGeneral;
|
||||
use App\Livewire\Project\Database\Postgresql\General as PostgresqlGeneral;
|
||||
use App\Livewire\Project\Database\Redis\General as RedisGeneral;
|
||||
use App\Livewire\Project\Database\Redis\StatusInfo as RedisStatusInfo;
|
||||
use App\Livewire\Project\Database\Sqlite\General as SqliteGeneral;
|
||||
use App\Models\Environment;
|
||||
use App\Models\EnvironmentVariable;
|
||||
use App\Models\InstanceSettings;
|
||||
@@ -239,3 +242,129 @@ it('still returns the connection url of an unlocked redis password in the api',
|
||||
->assertOk()
|
||||
->assertJsonPath('internal_db_url', "redis://default:visible-redis-secret@{$redis->uuid}:6379/0");
|
||||
});
|
||||
|
||||
dataset('database-api-config', [
|
||||
'postgresql' => ['create_standalone_postgresql', 'postgresqls', ['postgres_conf' => "primary_conninfo = 'password=secret-config-value'"]],
|
||||
'mysql' => ['create_standalone_mysql', 'mysqls', ['mysql_conf' => 'password=secret-config-value']],
|
||||
'mariadb' => ['create_standalone_mariadb', 'mariadbs', ['mariadb_conf' => 'password=secret-config-value']],
|
||||
'mongodb' => ['create_standalone_mongodb', 'mongodbs', ['mongo_conf' => 'keyFile: secret-config-value']],
|
||||
'redis' => ['create_standalone_redis', 'redis', ['redis_conf' => 'masterauth secret-config-value']],
|
||||
'keydb' => ['create_standalone_keydb', null, ['keydb_conf' => 'masterauth secret-config-value']],
|
||||
'dragonfly' => ['create_standalone_dragonfly', null, []],
|
||||
'clickhouse' => ['create_standalone_clickhouse', null, []],
|
||||
]);
|
||||
|
||||
function apiTokenHeaders(User $user, Team $team, array $abilities): array
|
||||
{
|
||||
$token = $user->createToken('config-test', $abilities);
|
||||
DB::table('personal_access_tokens')->where('id', $token->accessToken->id)->update(['team_id' => $team->id]);
|
||||
|
||||
return ['Authorization' => 'Bearer '.$token->plainTextToken];
|
||||
}
|
||||
|
||||
it('hides custom configs and docker run options from a token without sensitive read access', function (string $createDatabase, ?string $environmentRelation, array $config) {
|
||||
$database = createDatabaseWithConfig($createDatabase, [
|
||||
...$config,
|
||||
'custom_docker_run_options' => '--env API_TOKEN=secret-docker-value',
|
||||
]);
|
||||
session(['currentTeam' => $this->team]);
|
||||
$project = $this->environment->project;
|
||||
|
||||
foreach ([
|
||||
[$this->member, ['read']],
|
||||
[$this->member, ['read', 'read:sensitive']],
|
||||
[$this->owner, ['read']],
|
||||
] as [$user, $abilities]) {
|
||||
$headers = apiTokenHeaders($user, $this->team, $abilities);
|
||||
|
||||
$single = $this->withHeaders($headers)->getJson("/api/v1/databases/{$database->uuid}")->assertOk();
|
||||
expect($single->json('uuid'))->toBe($database->uuid)
|
||||
->and($single->getContent())->not->toContain('secret-config-value')->not->toContain('secret-docker-value');
|
||||
|
||||
$list = $this->withHeaders($headers)->getJson('/api/v1/databases')->assertOk();
|
||||
expect($list->getContent())->toContain($database->uuid)
|
||||
->not->toContain('secret-config-value')->not->toContain('secret-docker-value');
|
||||
|
||||
if ($environmentRelation !== null) {
|
||||
$environment = $this->withHeaders($headers)->getJson("/api/v1/projects/{$project->uuid}/{$this->environment->uuid}")->assertOk();
|
||||
expect($environment->getContent())->toContain($database->uuid)
|
||||
->not->toContain('secret-config-value')->not->toContain('secret-docker-value');
|
||||
}
|
||||
}
|
||||
})->with('database-api-config');
|
||||
|
||||
it('returns custom configs and docker run options to an owner token with sensitive read access', function (string $createDatabase, ?string $environmentRelation, array $config) {
|
||||
$database = createDatabaseWithConfig($createDatabase, [
|
||||
...$config,
|
||||
'custom_docker_run_options' => '--env API_TOKEN=secret-docker-value',
|
||||
]);
|
||||
session(['currentTeam' => $this->team]);
|
||||
$headers = apiTokenHeaders($this->owner, $this->team, ['read', 'read:sensitive']);
|
||||
|
||||
$single = $this->withHeaders($headers)->getJson("/api/v1/databases/{$database->uuid}")->assertOk()
|
||||
->assertJsonPath('custom_docker_run_options', '--env API_TOKEN=secret-docker-value');
|
||||
foreach ($config as $key => $value) {
|
||||
$single->assertJsonPath($key, $value);
|
||||
}
|
||||
|
||||
if ($environmentRelation !== null) {
|
||||
$project = $this->environment->project;
|
||||
$this->withHeaders($headers)->getJson("/api/v1/projects/{$project->uuid}/{$this->environment->uuid}")->assertOk()
|
||||
->assertJsonPath("{$environmentRelation}.0.custom_docker_run_options", '--env API_TOKEN=secret-docker-value');
|
||||
}
|
||||
})->with('database-api-config');
|
||||
|
||||
dataset('database-docker-options-components', [
|
||||
'postgresql' => ['create_standalone_postgresql', PostgresqlGeneral::class],
|
||||
'mysql' => ['create_standalone_mysql', MysqlGeneral::class],
|
||||
'mariadb' => ['create_standalone_mariadb', MariadbGeneral::class],
|
||||
'mongodb' => ['create_standalone_mongodb', MongodbGeneral::class],
|
||||
'redis' => ['create_standalone_redis', RedisGeneral::class],
|
||||
'keydb' => ['create_standalone_keydb', KeydbGeneral::class],
|
||||
'dragonfly' => ['create_standalone_dragonfly', DragonflyGeneral::class],
|
||||
'clickhouse' => ['create_standalone_clickhouse', ClickhouseGeneral::class],
|
||||
'sqlite' => ['create_standalone_sqlite', SqliteGeneral::class],
|
||||
]);
|
||||
|
||||
it('keeps custom docker run options out of member state and html', function (string $createDatabase, string $generalClass) {
|
||||
$database = createDatabaseWithConfig($createDatabase, ['custom_docker_run_options' => '--env API_TOKEN=secret-docker-value']);
|
||||
$ownTeam = Team::factory()->create();
|
||||
$ownTeam->members()->attach($this->member->id, ['role' => 'owner']);
|
||||
|
||||
$this->actingAs($this->member);
|
||||
foreach ([$this->team, $ownTeam] as $sessionTeam) {
|
||||
session(['currentTeam' => $sessionTeam]);
|
||||
|
||||
$general = Livewire::test($generalClass, ['database' => $database])
|
||||
->assertSet('customDockerRunOptions', null);
|
||||
expect(json_encode($general->snapshot))->not->toContain('secret-docker-value')
|
||||
->and($general->html())->not->toContain('secret-docker-value')
|
||||
->and($general->html())->toContain('Hidden (only admins can view)');
|
||||
}
|
||||
})->with('database-docker-options-components');
|
||||
|
||||
it('keeps custom docker run options available to an owner', function (string $createDatabase, string $generalClass) {
|
||||
$database = createDatabaseWithConfig($createDatabase, ['custom_docker_run_options' => '--env API_TOKEN=secret-docker-value']);
|
||||
|
||||
$this->actingAs($this->owner);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
Livewire::test($generalClass, ['database' => $database])
|
||||
->assertSet('customDockerRunOptions', '--env API_TOKEN=secret-docker-value');
|
||||
})->with('database-docker-options-components');
|
||||
|
||||
it('does not let a member save over hidden custom configs and docker run options', function (string $createDatabase, string $generalClass) {
|
||||
$database = createDatabaseWithConfig($createDatabase, ['custom_docker_run_options' => '--env API_TOKEN=secret-docker-value']);
|
||||
|
||||
$this->actingAs($this->member);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
Livewire::test($generalClass, ['database' => $database])
|
||||
->set('name', 'renamed-by-member')
|
||||
->call('submit')
|
||||
->call('instantSaveAdvanced');
|
||||
|
||||
$database = $database->fresh();
|
||||
expect($database->name)->not->toBe('renamed-by-member')
|
||||
->and($database->custom_docker_run_options)->toBe('--env API_TOKEN=secret-docker-value');
|
||||
})->with('database-docker-options-components');
|
||||
|
||||
Reference in New Issue
Block a user