fix: create DB user with correct host scope for TCP connections to MariaDB#13
fix: create DB user with correct host scope for TCP connections to MariaDB#13amitascra wants to merge 2 commits into
Conversation
f11975c to
e919f9f
Compare
| only when a unix socket is detected — in MySQL's privilege tables | ||
| 'localhost' matches socket connections exclusively. | ||
| """ | ||
| return "localhost" if self._detect_socket() else "%" |
There was a problem hiding this comment.
You're right to question this i did some more digging. After reviewing Frappe's new-site code, I realized the current approach is unnecessarily implicit.
Frappe already has a --mariadb-user-host-login-scope option specifically for this purpose:
@click.option( "--mariadb-user-host-login-scope", help=( "Set the mariadb host for the user login scope if you don't want to use the current host as login " "scope which typically is ''@'localhost' - may be used when initializing a user on a remote host." ), )
The post-processing approach with create_user() was implicit because I was trying to work around what I thought was a Frappe limitation, but Frappe already provides the right mechanism.
| """ | ||
| return "localhost" if self._detect_socket() else "%" | ||
|
|
||
| def create_user(self, username: str, password: str, db_name: str) -> None: |
There was a problem hiding this comment.
bench new-site is managed by frappe. how is this managed in the old bench?
There was a problem hiding this comment.
Old bench never managed this at all — it always delegated to Frappe completely, and users had to work around the @'localhost' issue manually (e.g., by creating sites locally then dumping/restoring to remote DBs, as seen in frappe/bench#1513).
The correct fix is to use Frappe's built-in --mariadb-user-host-login-scope='%' option when calling frappe new-site for TCP connections, rather than doing post-processing.
I'll update the PR to:
Remove the implicit create_user() post-processing from site.create()
- Add --mariadb-user-host-login-scope='%' to the frappe new-site command when no socket is detected
- This makes the fix explicit and uses Frappe's intended mechanism
- Thanks for the review — this is a much cleaner approach.
Frappe's new-site always creates the site DB user as @'localhost'. In MySQL's privilege tables 'localhost' matches only unix socket connections — TCP connections from 127.0.0.1 are rejected even on the same host, breaking bench when MariaDB is running in Docker or over any remote TCP connection. Fix: - Add MariaDBManager._grant_host(): returns '%' when no unix socket is detected (TCP mode), 'localhost' when a socket is present. - Add MariaDBManager.create_user(): uses the mysql/mariadb CLI (zero new dependencies) to run CREATE USER IF NOT EXISTS and GRANT with the correct host scope. - Wire create_user() into Site.create(): after frappe new-site completes, read the generated site_config.json for db_name and db_password, then call create_user() to ensure the user exists with @'%' scope for TCP connections. Fixes frappe#4
Use Frappe's built-in --mariadb-user-host-login-scope option instead of post-processing with create_user(). This is cleaner and more explicit. Changes: - Pass --mariadb-user-host-login-scope='%' when no unix socket detected - Remove implicit create_user() post-processing from site.create() - Update tests to verify the flag is passed correctly - Add research-folder/ to .gitignore Addresses review feedback from @rmehta on PR frappe#13
e919f9f to
21ba004
Compare
Problem
Frappe's
new-sitealways creates the site DB user as@'localhost'. In MySQL's privilege tables,'localhost'matches only unix socket connections — TCP connections from127.0.0.1are rejected even on the same host. This breaksbench new-sitewhen MariaDB is running in Docker, on a remote host, or over any TCP connection with no local unix socket.Fixes #4
Root cause
MariaDBManager.create_user() existed at
dea8638with@'localhost'hardcoded, but was never wired into any code path — it was dead code. The actual user creation was always delegated to Frappe'snew-site, which also creates@'localhost'unconditionally. The result is a user that cannot connect over TCP.Solution
'%'when no unix socket is detected (TCP mode),'localhost'when a socket is present.mysql/mariadbCLI (zero new dependencies — MariaDB is already installed) to runCREATE USER IF NOT EXISTSandGRANTwith the correct host scope.frappe new-sitecompletes, reads the generatedsite_config.jsonfordb_nameanddb_password, then calls create_user() to ensure the user exists with@'%'scope for TCP connections. Skipped entirely when a unix socket is in use.Testing
Added 12 unit tests in tests/test_mariadb_manager.py:
'%'for TCP,'localhost'for socketmariadbbinary, falls back tomysql-h,-P,--socketflagsfrappe new-sitewith credentials fromsite_config.jsonsite_config.jsonis missingAll 12 new tests pass. No regressions in existing tests.