Skip to content

Commit 791301a

Browse files
committed
fix(mysql): use % during user creation if remote db host
closes #642 - use % rather than the db host if host isn't localhost
1 parent 7d0c330 commit 791301a

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

extensions/mysql/index.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
const Promise = require('bluebird');
44
const mysql = require('mysql');
55
const omit = require('lodash/omit');
6+
const includes = require('lodash/includes');
67
const cli = require('../../lib');
78
const generator = require('generate-password');
89

10+
const localhostAliases = ['localhost', '127.0.0.1'];
11+
912
class MySQLExtension extends cli.Extension {
1013
setup(cmd, argv) {
1114
// Case 1: ghost install local OR ghost setup --local
@@ -84,6 +87,11 @@ class MySQLExtension extends cli.Extension {
8487
strict: true
8588
});
8689

90+
// This will be the "allowed connections from" host of the mysql user.
91+
// If the db connection host is something _other_ than localhost (e.g. a remote db connection)
92+
// we want the host to be `%` rather than the db host.
93+
const host = !includes(localhostAliases, dbconfig.host) ? '%' : dbconfig.host;
94+
8795
let username;
8896

8997
// Ensure old passwords is set to 0
@@ -103,7 +111,7 @@ class MySQLExtension extends cli.Extension {
103111
username = `ghost-${Math.floor(Math.random() * 1000)}`;
104112

105113
return this._query(
106-
`CREATE USER '${username}'@'${dbconfig.host}' ` +
114+
`CREATE USER '${username}'@'${host}' ` +
107115
`IDENTIFIED WITH mysql_native_password AS '${result[0].password}';`
108116
).catch((error) => {
109117
// User already exists, run this method again
@@ -121,6 +129,7 @@ class MySQLExtension extends cli.Extension {
121129
this.ui.logVerbose(`MySQL: successfully created new user ${username}`, 'green');
122130

123131
ctx.mysql = {
132+
host: host,
124133
username: username,
125134
password: randomPassword
126135
};
@@ -132,7 +141,7 @@ class MySQLExtension extends cli.Extension {
132141
}
133142

134143
grantPermissions(ctx, dbconfig) {
135-
return this._query(`GRANT ALL PRIVILEGES ON ${dbconfig.database}.* TO '${ctx.mysql.username}'@'${dbconfig.host}';`).then(() => {
144+
return this._query(`GRANT ALL PRIVILEGES ON ${dbconfig.database}.* TO '${ctx.mysql.username}'@'${ctx.mysql.host}';`).then(() => {
136145
this.ui.logVerbose(`MySQL: Successfully granted privileges for user "${ctx.mysql.username}"`, 'green');
137146
return this._query('FLUSH PRIVILEGES;');
138147
}).then(() => {

extensions/mysql/test/extension-spec.js

+24-2
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,28 @@ describe('Unit: Mysql extension', function () {
204204
});
205205
});
206206

207+
it('uses % for user host if db host is not localhost or 127.0.0.1', function () {
208+
const logStub = sinon.stub();
209+
const instance = new MysqlExtension({logVerbose: logStub}, {}, {}, '/some/dir');
210+
const queryStub = sinon.stub(instance, '_query').resolves();
211+
queryStub.onSecondCall().resolves([{password: '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19'}]);
212+
const ctx = {};
213+
214+
return instance.createUser(ctx, {host: '117.241.162.107'}).then(() => {
215+
expect(queryStub.calledThrice).to.be.true;
216+
expect(queryStub.args[0][0]).to.equal('SET old_passwords = 0;');
217+
expect(queryStub.args[1][0]).to.match(/^SELECT PASSWORD\('[a-zA-Z0-9!@#$%^&*()+_\-=}{[\]|:;"/?.><,`~]*'\) AS password;$/);
218+
expect(queryStub.args[2][0]).to.match(/^CREATE USER 'ghost-[0-9]{1,4}'@'%' IDENTIFIED WITH mysql_native_password AS '\*[0-9A-F]*';$/);
219+
expect(logStub.calledThrice).to.be.true;
220+
expect(logStub.args[0][0]).to.match(/disabled old_password/);
221+
expect(logStub.args[1][0]).to.match(/created password hash/);
222+
expect(logStub.args[2][0]).to.match(/successfully created new user/);
223+
expect(ctx.mysql).to.exist;
224+
expect(ctx.mysql.username).to.match(/^ghost-[0-9]{1,4}$/);
225+
expect(ctx.mysql.password).to.match(/^[a-zA-Z0-9!@#$%^&*()+_\-=}{[\]|:;"/?.><,`~]*$/);
226+
});
227+
});
228+
207229
it('retries creating user if username already exists', function () {
208230
const logStub = sinon.stub();
209231
const instance = new MysqlExtension({logVerbose: logStub}, {}, {}, '/some/dir');
@@ -288,9 +310,9 @@ describe('Unit: Mysql extension', function () {
288310
const instance = new MysqlExtension({logVerbose: logStub}, {}, {}, '/some/dir');
289311
const queryStub = sinon.stub(instance, '_query').resolves();
290312

291-
return instance.grantPermissions({mysql: {username: 'testuser'}}, {host: 'localhost', database: 'ghost'}).then(() => {
313+
return instance.grantPermissions({mysql: {username: 'testuser', host: '%'}}, {host: 'localhost', database: 'ghost'}).then(() => {
292314
expect(queryStub.calledTwice).to.be.true;
293-
expect(queryStub.calledWithExactly('GRANT ALL PRIVILEGES ON ghost.* TO \'testuser\'@\'localhost\';')).to.be.true;
315+
expect(queryStub.calledWithExactly('GRANT ALL PRIVILEGES ON ghost.* TO \'testuser\'@\'%\';')).to.be.true;
294316
expect(queryStub.calledWithExactly('FLUSH PRIVILEGES;')).to.be.true;
295317
expect(logStub.calledTwice).to.be.true;
296318
expect(logStub.args[0][0]).to.match(/Successfully granted privileges/);

0 commit comments

Comments
 (0)