mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 21:24:10 +00:00
fix: avoid admin credential prompt on fresh mariadb install
This commit is contained in:
parent
fa73367e7e
commit
326abb3a44
4 changed files with 158 additions and 12 deletions
|
|
@ -0,0 +1,51 @@
|
|||
Task Record:
|
||||
|
||||
Date: 2026-04-22
|
||||
Related Module: MariaDB admin auth in installer and menu script
|
||||
Change Type: Fix
|
||||
|
||||
Background
|
||||
|
||||
During local MariaDB setup, when socket auth failed the script asked for admin credentials.
|
||||
On hosts where admin/root password is empty, the previous command construction always appended `-p`, which can cause authentication checks to fail for empty-password accounts.
|
||||
This led to false "管理员账号连接失败" and blocked install/uninstall flows.
|
||||
|
||||
Changes
|
||||
|
||||
Updated MariaDB connection execution in both `install.sh` and `x-ui.sh`:
|
||||
- Build MariaDB client command with optional password flag.
|
||||
- Append `-p<password>` only when password is non-empty.
|
||||
- Apply this to server-connection check, database-connection check, and admin SQL execution.
|
||||
- Prompt text updated to indicate admin password can be empty.
|
||||
- Added retry logic (up to 10 seconds) before declaring socket auth failure.
|
||||
- Added automatic fallback to `root@127.0.0.1` with empty password before prompting admin credentials.
|
||||
- For freshly installed local MariaDB in script flow, set an install marker and prefer non-interactive auto init path.
|
||||
|
||||
Added `tests/mariadb_admin_empty_password_test.sh` for static regression checks.
|
||||
|
||||
Impact
|
||||
|
||||
Affected files:
|
||||
- `install.sh`
|
||||
- `x-ui.sh`
|
||||
- `tests/mariadb_admin_empty_password_test.sh`
|
||||
|
||||
No API/database schema change.
|
||||
Install, DB switching, and uninstall paths are more compatible with empty-password admin setups.
|
||||
|
||||
Verification
|
||||
|
||||
Commands:
|
||||
- `bash -n install.sh`
|
||||
- `bash -n x-ui.sh`
|
||||
- `bash tests/mariadb_admin_empty_password_test.sh`
|
||||
- `bash tests/install_uninstall_resilience_test.sh`
|
||||
- `bash tests/panel_port_prompt_test.sh`
|
||||
- `bash tests/mariadb_install_switch_test.sh`
|
||||
|
||||
Result:
|
||||
- All checks passed.
|
||||
|
||||
Risks And Follow-Up
|
||||
|
||||
Current tests are static assertions. Full runtime verification still depends on real MariaDB environment variants (socket auth, TCP auth, empty password, root-password mode).
|
||||
48
install.sh
48
install.sh
|
|
@ -222,6 +222,7 @@ ensure_mariadb_client_ready() {
|
|||
ensure_local_mariadb_ready() {
|
||||
if ! has_local_mariadb_service; then
|
||||
install_local_mariadb_server || return 1
|
||||
LOCAL_MARIADB_JUST_INSTALLED="1"
|
||||
fi
|
||||
ensure_mariadb_client_ready || return 1
|
||||
start_mariadb_service || true
|
||||
|
|
@ -231,15 +232,27 @@ ensure_local_mariadb_ready() {
|
|||
test_mariadb_server_connection() {
|
||||
local host="$1" port="$2" user="$3" pass="$4"
|
||||
local bin
|
||||
local -a cmd
|
||||
bin=$(mariadb_cli_bin) || return 1
|
||||
"$bin" -h "$host" -P "$port" -u "$user" -p"$pass" -e "SELECT 1;" >/dev/null 2>&1
|
||||
cmd=("$bin" -h "$host" -P "$port" -u "$user")
|
||||
if [[ -n "$pass" ]]; then
|
||||
cmd+=("-p$pass")
|
||||
fi
|
||||
cmd+=(-e "SELECT 1;")
|
||||
"${cmd[@]}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
test_mariadb_database_connection() {
|
||||
local host="$1" port="$2" dbname="$3" user="$4" pass="$5"
|
||||
local bin
|
||||
local -a cmd
|
||||
bin=$(mariadb_cli_bin) || return 1
|
||||
"$bin" -h "$host" -P "$port" -u "$user" -p"$pass" -D "$dbname" -e "SELECT 1;" >/dev/null 2>&1
|
||||
cmd=("$bin" -h "$host" -P "$port" -u "$user" -D "$dbname")
|
||||
if [[ -n "$pass" ]]; then
|
||||
cmd+=("-p$pass")
|
||||
fi
|
||||
cmd+=(-e "SELECT 1;")
|
||||
"${cmd[@]}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
is_safe_mariadb_identifier() {
|
||||
|
|
@ -254,6 +267,7 @@ LOCAL_MARIADB_ADMIN_MODE=""
|
|||
LOCAL_MARIADB_ADMIN_USER=""
|
||||
LOCAL_MARIADB_ADMIN_PASS=""
|
||||
LOCAL_MARIADB_ADMIN_PORT="3306"
|
||||
LOCAL_MARIADB_JUST_INSTALLED="0"
|
||||
|
||||
try_local_mariadb_socket_admin() {
|
||||
local bin
|
||||
|
|
@ -263,10 +277,26 @@ try_local_mariadb_socket_admin() {
|
|||
|
||||
ensure_local_mariadb_admin_access() {
|
||||
local port="${1:-3306}"
|
||||
local i
|
||||
LOCAL_MARIADB_ADMIN_PORT="$port"
|
||||
|
||||
if try_local_mariadb_socket_admin; then
|
||||
LOCAL_MARIADB_ADMIN_MODE="socket"
|
||||
# Fresh installs may need a few seconds before local socket auth is ready.
|
||||
for ((i = 0; i < 10; i++)); do
|
||||
if try_local_mariadb_socket_admin; then
|
||||
LOCAL_MARIADB_ADMIN_MODE="socket"
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Common default on fresh installs: root can connect via TCP without password.
|
||||
if test_mariadb_server_connection "127.0.0.1" "$port" "root" ""; then
|
||||
LOCAL_MARIADB_ADMIN_MODE="password"
|
||||
LOCAL_MARIADB_ADMIN_USER="root"
|
||||
LOCAL_MARIADB_ADMIN_PASS=""
|
||||
if [[ "$LOCAL_MARIADB_JUST_INSTALLED" == "1" ]]; then
|
||||
echo -e "${green}检测到新安装 MariaDB,已自动使用 root 免密权限初始化数据库。${plain}"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
|
|
@ -274,7 +304,7 @@ ensure_local_mariadb_admin_access() {
|
|||
echo -e "${yellow}无法通过 root socket 直接连接本地 MariaDB,请输入管理员账号信息。${plain}"
|
||||
read -rp "MariaDB 管理员用户名 [root]: " admin_user
|
||||
admin_user="${admin_user:-root}"
|
||||
read -rsp "MariaDB 管理员密码: " admin_pass
|
||||
read -rsp "MariaDB 管理员密码(可留空): " admin_pass
|
||||
echo
|
||||
|
||||
if ! test_mariadb_server_connection "127.0.0.1" "$port" "$admin_user" "$admin_pass"; then
|
||||
|
|
@ -290,6 +320,7 @@ ensure_local_mariadb_admin_access() {
|
|||
run_local_mariadb_admin_sql() {
|
||||
local sql="$1"
|
||||
local bin
|
||||
local -a cmd
|
||||
bin=$(mariadb_cli_bin) || return 1
|
||||
|
||||
case "$LOCAL_MARIADB_ADMIN_MODE" in
|
||||
|
|
@ -297,7 +328,12 @@ run_local_mariadb_admin_sql() {
|
|||
"$bin" -e "$sql" >/dev/null 2>&1 || "$bin" -uroot -e "$sql" >/dev/null 2>&1
|
||||
;;
|
||||
password)
|
||||
"$bin" -h "127.0.0.1" -P "$LOCAL_MARIADB_ADMIN_PORT" -u "$LOCAL_MARIADB_ADMIN_USER" -p"$LOCAL_MARIADB_ADMIN_PASS" -e "$sql" >/dev/null 2>&1
|
||||
cmd=("$bin" -h "127.0.0.1" -P "$LOCAL_MARIADB_ADMIN_PORT" -u "$LOCAL_MARIADB_ADMIN_USER")
|
||||
if [[ -n "$LOCAL_MARIADB_ADMIN_PASS" ]]; then
|
||||
cmd+=("-p$LOCAL_MARIADB_ADMIN_PASS")
|
||||
fi
|
||||
cmd+=(-e "$sql")
|
||||
"${cmd[@]}" >/dev/null 2>&1
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
|
|
|
|||
25
tests/mariadb_admin_empty_password_test.sh
Normal file
25
tests/mariadb_admin_empty_password_test.sh
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
assert_contains() {
|
||||
local file="$1"
|
||||
local pattern="$2"
|
||||
if ! grep -Fq "$pattern" "$file"; then
|
||||
echo "missing pattern in $file: $pattern" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_contains "install.sh" "MariaDB 管理员密码(可留空)"
|
||||
assert_contains "install.sh" "if [[ -n \"\$pass\" ]]; then"
|
||||
assert_contains "install.sh" "if [[ -n \"\$LOCAL_MARIADB_ADMIN_PASS\" ]]; then"
|
||||
assert_contains "install.sh" "test_mariadb_server_connection \"127.0.0.1\" \"\$port\" \"root\" \"\""
|
||||
assert_contains "install.sh" "LOCAL_MARIADB_JUST_INSTALLED=\"1\""
|
||||
|
||||
assert_contains "x-ui.sh" "MariaDB 管理员密码(可留空)"
|
||||
assert_contains "x-ui.sh" "if [[ -n \"\$pass\" ]]; then"
|
||||
assert_contains "x-ui.sh" "if [[ -n \"\$LOCAL_MARIADB_ADMIN_PASS\" ]]; then"
|
||||
assert_contains "x-ui.sh" "test_mariadb_server_connection \"127.0.0.1\" \"\$port\" \"root\" \"\""
|
||||
assert_contains "x-ui.sh" "LOCAL_MARIADB_JUST_INSTALLED=\"1\""
|
||||
|
||||
echo "mariadb admin empty-password flow looks correct"
|
||||
46
x-ui.sh
46
x-ui.sh
|
|
@ -2655,6 +2655,7 @@ ensure_local_mariadb_ready() {
|
|||
echo -e "${yellow}未检测到本地 MariaDB 服务${plain}"
|
||||
confirm "是否安装本地 MariaDB?" "y" || return 1
|
||||
install_local_mariadb_server || return 1
|
||||
LOCAL_MARIADB_JUST_INSTALLED="1"
|
||||
fi
|
||||
ensure_mariadb_client_ready || return 1
|
||||
start_mariadb_service || true
|
||||
|
|
@ -2664,15 +2665,27 @@ ensure_local_mariadb_ready() {
|
|||
test_mariadb_server_connection() {
|
||||
local host="$1" port="$2" user="$3" pass="$4"
|
||||
local bin
|
||||
local -a cmd
|
||||
bin=$(mariadb_cli_bin) || return 1
|
||||
"$bin" -h "$host" -P "$port" -u "$user" -p"$pass" -e "SELECT 1;" >/dev/null 2>&1
|
||||
cmd=("$bin" -h "$host" -P "$port" -u "$user")
|
||||
if [[ -n "$pass" ]]; then
|
||||
cmd+=("-p$pass")
|
||||
fi
|
||||
cmd+=(-e "SELECT 1;")
|
||||
"${cmd[@]}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
test_mariadb_database_connection() {
|
||||
local host="$1" port="$2" dbname="$3" user="$4" pass="$5"
|
||||
local bin
|
||||
local -a cmd
|
||||
bin=$(mariadb_cli_bin) || return 1
|
||||
"$bin" -h "$host" -P "$port" -u "$user" -p"$pass" -D "$dbname" -e "SELECT 1;" >/dev/null 2>&1
|
||||
cmd=("$bin" -h "$host" -P "$port" -u "$user" -D "$dbname")
|
||||
if [[ -n "$pass" ]]; then
|
||||
cmd+=("-p$pass")
|
||||
fi
|
||||
cmd+=(-e "SELECT 1;")
|
||||
"${cmd[@]}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
is_safe_mariadb_identifier() {
|
||||
|
|
@ -2687,6 +2700,7 @@ LOCAL_MARIADB_ADMIN_MODE=""
|
|||
LOCAL_MARIADB_ADMIN_USER=""
|
||||
LOCAL_MARIADB_ADMIN_PASS=""
|
||||
LOCAL_MARIADB_ADMIN_PORT="3306"
|
||||
LOCAL_MARIADB_JUST_INSTALLED="0"
|
||||
|
||||
try_local_mariadb_socket_admin() {
|
||||
local bin
|
||||
|
|
@ -2696,10 +2710,24 @@ try_local_mariadb_socket_admin() {
|
|||
|
||||
ensure_local_mariadb_admin_access() {
|
||||
local port="${1:-3306}"
|
||||
local i
|
||||
LOCAL_MARIADB_ADMIN_PORT="$port"
|
||||
|
||||
if try_local_mariadb_socket_admin; then
|
||||
LOCAL_MARIADB_ADMIN_MODE="socket"
|
||||
for ((i = 0; i < 10; i++)); do
|
||||
if try_local_mariadb_socket_admin; then
|
||||
LOCAL_MARIADB_ADMIN_MODE="socket"
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if test_mariadb_server_connection "127.0.0.1" "$port" "root" ""; then
|
||||
LOCAL_MARIADB_ADMIN_MODE="password"
|
||||
LOCAL_MARIADB_ADMIN_USER="root"
|
||||
LOCAL_MARIADB_ADMIN_PASS=""
|
||||
if [[ "$LOCAL_MARIADB_JUST_INSTALLED" == "1" ]]; then
|
||||
echo -e "${green}检测到新安装 MariaDB,已自动使用 root 免密权限初始化数据库。${plain}"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
|
|
@ -2707,7 +2735,7 @@ ensure_local_mariadb_admin_access() {
|
|||
echo -e "${yellow}无法通过 root socket 直接连接本地 MariaDB,请输入管理员账号信息。${plain}"
|
||||
read -rp "MariaDB 管理员用户名 [root]: " admin_user
|
||||
admin_user="${admin_user:-root}"
|
||||
read -rsp "MariaDB 管理员密码: " admin_pass
|
||||
read -rsp "MariaDB 管理员密码(可留空): " admin_pass
|
||||
echo
|
||||
|
||||
if ! test_mariadb_server_connection "127.0.0.1" "$port" "$admin_user" "$admin_pass"; then
|
||||
|
|
@ -2723,6 +2751,7 @@ ensure_local_mariadb_admin_access() {
|
|||
run_local_mariadb_admin_sql() {
|
||||
local sql="$1"
|
||||
local bin
|
||||
local -a cmd
|
||||
bin=$(mariadb_cli_bin) || return 1
|
||||
|
||||
case "$LOCAL_MARIADB_ADMIN_MODE" in
|
||||
|
|
@ -2730,7 +2759,12 @@ run_local_mariadb_admin_sql() {
|
|||
"$bin" -e "$sql" >/dev/null 2>&1 || "$bin" -uroot -e "$sql" >/dev/null 2>&1
|
||||
;;
|
||||
password)
|
||||
"$bin" -h "127.0.0.1" -P "$LOCAL_MARIADB_ADMIN_PORT" -u "$LOCAL_MARIADB_ADMIN_USER" -p"$LOCAL_MARIADB_ADMIN_PASS" -e "$sql" >/dev/null 2>&1
|
||||
cmd=("$bin" -h "127.0.0.1" -P "$LOCAL_MARIADB_ADMIN_PORT" -u "$LOCAL_MARIADB_ADMIN_USER")
|
||||
if [[ -n "$LOCAL_MARIADB_ADMIN_PASS" ]]; then
|
||||
cmd+=("-p$LOCAL_MARIADB_ADMIN_PASS")
|
||||
fi
|
||||
cmd+=(-e "$sql")
|
||||
"${cmd[@]}" >/dev/null 2>&1
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
|
|
|
|||
Loading…
Reference in a new issue