Skip to content

Commit 2ec8f1e

Browse files
committed
fix: [#410] reject 'root' as MySQL app username (Bug 3)
1 parent 8e42698 commit 2ec8f1e

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

  • src/domain/tracker/config/core/database

src/domain/tracker/config/core/database/mysql.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub enum MysqlConfigError {
1919
/// Username cannot be empty
2020
#[error("MySQL username cannot be empty")]
2121
EmptyUsername,
22+
/// Username `root` is reserved by the MySQL Docker image
23+
#[error("MySQL username \"root\" is reserved and cannot be used as the app database username")]
24+
ReservedUsername,
2225
}
2326

2427
impl MysqlConfigError {
@@ -90,6 +93,23 @@ impl MysqlConfigError {
9093
...\n\
9194
}"
9295
}
96+
Self::ReservedUsername => {
97+
"MySQL username \"root\" is reserved by the MySQL Docker image and cannot\n\
98+
be used as the application database username.\n\
99+
\n\
100+
The MySQL container creates a privileged superuser named \"root\" automatically.\n\
101+
Setting MYSQL_USER=root causes the container initialization to fail with:\n\
102+
[ERROR] [Entrypoint]: MYSQL_USER=\"root\", MYSQL_USER and MYSQL_ROOT_USER cannot be the same.\n\
103+
\n\
104+
Fix:\n\
105+
Choose a different username in your database configuration:\n\
106+
\n\
107+
\"database\": {\n\
108+
\"driver\": \"mysql\",\n\
109+
\"username\": \"tracker_user\",\n\
110+
...\n\
111+
}"
112+
}
93113
}
94114
}
95115
}
@@ -160,6 +180,9 @@ impl MysqlConfig {
160180
if username.is_empty() {
161181
return Err(MysqlConfigError::EmptyUsername);
162182
}
183+
if username == "root" {
184+
return Err(MysqlConfigError::ReservedUsername);
185+
}
163186

164187
Ok(Self {
165188
host,
@@ -274,6 +297,20 @@ mod tests {
274297
assert!(matches!(result, Err(MysqlConfigError::EmptyUsername)));
275298
}
276299

300+
#[test]
301+
fn it_should_reject_root_as_username() {
302+
let result = MysqlConfig::new("localhost", 3306, "tracker", "root", Password::from("pass"));
303+
assert!(matches!(result, Err(MysqlConfigError::ReservedUsername)));
304+
}
305+
306+
#[test]
307+
fn it_should_provide_actionable_help_for_reserved_username_error() {
308+
let error = MysqlConfigError::ReservedUsername;
309+
let help = error.help();
310+
assert!(help.contains("root"));
311+
assert!(help.contains("tracker_user"));
312+
}
313+
277314
#[test]
278315
fn it_should_serialize_mysql_config() {
279316
let config = MysqlConfig::new(

0 commit comments

Comments
 (0)