@transitive-sdk/clickhouse 0.5.2 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +71 -0
- package/package.json +1 -1
- package/test/clickhouse.test.js +11 -0
package/index.js
CHANGED
|
@@ -5,6 +5,17 @@ const { createClient } = require('@clickhouse/client');
|
|
|
5
5
|
|
|
6
6
|
const { topicToPath, topicMatch } = require('@transitive-sdk/datacache');
|
|
7
7
|
|
|
8
|
+
/** Generate a random id (base36) */
|
|
9
|
+
const getRandomId = (bytes = 6) => {
|
|
10
|
+
const buffer = new Uint8Array(bytes);
|
|
11
|
+
crypto.getRandomValues(buffer);
|
|
12
|
+
return buffer.reduce((memo, i) => memo + i.toString(36), '');
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const log = {
|
|
16
|
+
debug: console.log
|
|
17
|
+
}
|
|
18
|
+
|
|
8
19
|
// Default TTL in days for mqtt_history table
|
|
9
20
|
const DEFAULT_TTL_DAYS = 30;
|
|
10
21
|
|
|
@@ -466,7 +477,67 @@ class ClickHouse {
|
|
|
466
477
|
return row;
|
|
467
478
|
});
|
|
468
479
|
}
|
|
480
|
+
|
|
481
|
+
/* Creates ClickHouse user for an organisation/user with SELECT access for all
|
|
482
|
+
dbs and tables. `accountsCollection` is the mongo accounts collection and
|
|
483
|
+
needs to be provided, only optional for testing. */
|
|
484
|
+
async ensureClickHouseOrgUser(orgId, accountsCollection = undefined) {
|
|
485
|
+
const orgUser = `org_${orgId}_user`;
|
|
486
|
+
|
|
487
|
+
// Check if user exists
|
|
488
|
+
const userExists = await this.client.query({
|
|
489
|
+
query: `SELECT name FROM system.users WHERE name = '${orgUser}'`,
|
|
490
|
+
format: 'JSONEachRow'
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
const users = await userExists.json();
|
|
494
|
+
|
|
495
|
+
if (users.length > 0) {
|
|
496
|
+
log.debug(`ClickHouse user for organization ${orgId} already exists`);
|
|
497
|
+
if (!accountsCollection) return;
|
|
498
|
+
const orgDoc = await accountsCollection.findOne({ _id: orgId });
|
|
499
|
+
const { user: orgUser, password } = orgDoc.clickhouseCredentials;
|
|
500
|
+
if (!password) {
|
|
501
|
+
throw new Error(`ClickHouse user for organization ${orgId} exists but no password found in mongo`);
|
|
502
|
+
} else {
|
|
503
|
+
log.debug(`retrieved ClickHouse credentials for organization ${orgId} from mongo: ${orgUser} / ${password}`);
|
|
504
|
+
return {
|
|
505
|
+
user: orgUser,
|
|
506
|
+
password: password
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const orgPassword = getRandomId(15);
|
|
512
|
+
|
|
513
|
+
log.debug(`creating ClickHouse user for organization ${orgId} : ${orgUser} / ${orgPassword}`);
|
|
514
|
+
|
|
515
|
+
for (let query of [
|
|
516
|
+
// Create user:
|
|
517
|
+
`CREATE USER IF NOT EXISTS ${orgUser} IDENTIFIED WITH plaintext_password BY '${orgPassword}'`,
|
|
518
|
+
// Grant read only access to all databases and tables - row level security
|
|
519
|
+
// will limit access to own org data:
|
|
520
|
+
`GRANT SELECT ON *.* TO ${orgUser}`,
|
|
521
|
+
// Immediately revoke select access to system tables again (see
|
|
522
|
+
// https://clickhouse.com/docs/sql-reference/statements/revoke#examples):
|
|
523
|
+
`REVOKE SELECT ON system.* FROM ${orgUser}`,
|
|
524
|
+
]) await this.client.command({ query });
|
|
525
|
+
|
|
526
|
+
// store user and password in mongo
|
|
527
|
+
if (accountsCollection) {
|
|
528
|
+
await accountsCollection.updateOne(
|
|
529
|
+
{ _id: orgId },
|
|
530
|
+
{ $set: { clickhouseCredentials: { user: orgUser, password: orgPassword } } }
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
return {
|
|
535
|
+
user: orgUser,
|
|
536
|
+
password: orgPassword
|
|
537
|
+
};
|
|
538
|
+
}
|
|
469
539
|
}
|
|
470
540
|
|
|
541
|
+
|
|
471
542
|
const instance = new ClickHouse();
|
|
472
543
|
module.exports = instance;
|
package/package.json
CHANGED
package/test/clickhouse.test.js
CHANGED
|
@@ -476,4 +476,15 @@ describe('ClickHouse', function() {
|
|
|
476
476
|
assertTimelimit(ROWS / 1000);
|
|
477
477
|
});
|
|
478
478
|
});
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
describe('users', () => {
|
|
482
|
+
it('create a user', async () => {
|
|
483
|
+
const result = await clickhouse.ensureClickHouseOrgUser('test');
|
|
484
|
+
console.log({result});
|
|
485
|
+
|
|
486
|
+
const result2 = await clickhouse.ensureClickHouseOrgUser('test');
|
|
487
|
+
assert.equal(result2, undefined);
|
|
488
|
+
});
|
|
489
|
+
});
|
|
479
490
|
});
|