Skip to content

Commit

Permalink
Revert "DPLT-1049 Revert separate user DB provisioning (#143)"
Browse files Browse the repository at this point in the history
This reverts commit 858eea3.
  • Loading branch information
morgsmccauley authored Jul 21, 2023
1 parent 858eea3 commit 84bf283
Show file tree
Hide file tree
Showing 12 changed files with 712 additions and 274 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/deploy-lambdas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,8 @@ jobs:
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
HASURA_ENDPOINT: ${{ vars.HASURA_ENDPOINT }}
HASURA_ADMIN_SECRET: ${{ secrets.HASURA_ADMIN_SECRET }}
PG_ADMIN_USER: ${{ secrets.PG_ADMIN_USER }}
PG_ADMIN_PASSWORD: ${{ secrets.PG_ADMIN_PASSWORD }}
PG_ADMIN_DATABASE: ${{ secrets.PG_ADMIN_DATABASE }}
PG_HOST: ${{ secrets.PG_HOST }}
PG_PORT: ${{ secrets.PG_PORT }}
105 changes: 75 additions & 30 deletions indexer-js-queue-handler/__snapshots__/hasura-client.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`HasuraClient adds a datasource 1`] = `
{
"args": {
"configuration": {
"connection_info": {
"database_url": {
"connection_parameters": {
"database": "morgs_near",
"host": "localhost",
"password": "password",
"port": 5432,
"username": "morgs_near",
},
},
},
},
"customization": {
"root_fields": {
"namespace": "morgs_near",
},
"type_names": {
"prefix": "morgs_near_",
},
},
"name": "morgs_near",
},
"type": "pg_add_source",
}
`;

exports[`HasuraClient adds the specified permissions for the specified roles/table/schema 1`] = `
{
"args": [
Expand Down Expand Up @@ -152,51 +182,66 @@ exports[`HasuraClient adds the specified permissions for the specified roles/tab
}
`;

exports[`HasuraClient checks if a schema exists 1`] = `
exports[`HasuraClient checks if a schema exists within source 1`] = `
[
[
"mock-hasura-endpoint/v2/query",
{
"body": "{"type":"run_sql","args":{"sql":"SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'schema'","read_only":true,"source":"source"}}",
"headers": {
"X-Hasura-Admin-Secret": "mock-hasura-admin-secret",
},
"method": "POST",
},
],
]
`;

exports[`HasuraClient checks if datasource exists 1`] = `
{
"args": {
"read_only": true,
"source": "default",
"sql": "SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'name'",
},
"type": "run_sql",
"args": {},
"type": "export_metadata",
"version": 2,
}
`;

exports[`HasuraClient creates a schema 1`] = `
{
"args": {
"read_only": false,
"source": "default",
"sql": "CREATE schema name",
},
"type": "run_sql",
}
[
[
"mock-hasura-endpoint/v2/query",
{
"body": "{"type":"run_sql","args":{"sql":"CREATE schema schemaName","read_only":false,"source":"dbName"}}",
"headers": {
"X-Hasura-Admin-Secret": "mock-hasura-admin-secret",
},
"method": "POST",
},
],
]
`;

exports[`HasuraClient gets table names within a schema 1`] = `
{
"args": {
"read_only": true,
"source": "default",
"sql": "SELECT table_name FROM information_schema.tables WHERE table_schema = 'schema'",
"source": "source",
},
"type": "run_sql",
"type": "pg_get_source_tables",
}
`;

exports[`HasuraClient runs migrations for the specified schema 1`] = `
{
"args": {
"read_only": false,
"source": "default",
"sql": "
set schema 'schema';
CREATE TABLE blocks (height numeric)
",
},
"type": "run_sql",
}
[
[
"mock-hasura-endpoint/v2/query",
{
"body": "{"type":"run_sql","args":{"sql":"\\n set schema 'schemaName';\\n CREATE TABLE blocks (height numeric)\\n ","read_only":false,"source":"dbName"}}",
"headers": {
"X-Hasura-Admin-Secret": "mock-hasura-admin-secret",
},
"method": "POST",
},
],
]
`;

exports[`HasuraClient tracks foreign key relationships 1`] = `
Expand Down
22 changes: 22 additions & 0 deletions indexer-js-queue-handler/__snapshots__/provisioner.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Provisioner provisionUserApi formats user input before executing the query 1`] = `
[
[
"CREATE DATABASE "databaseName UNION SELECT * FROM users --"",
[],
],
[
"CREATE USER morgs_near WITH PASSWORD 'pass; DROP TABLE users;--'",
[],
],
[
"GRANT ALL PRIVILEGES ON DATABASE "databaseName UNION SELECT * FROM users --" TO morgs_near",
[],
],
[
"REVOKE CONNECT ON DATABASE "databaseName UNION SELECT * FROM users --" FROM PUBLIC",
[],
],
]
`;
89 changes: 67 additions & 22 deletions indexer-js-queue-handler/hasura-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default class HasuraClient {
args: {
sql,
read_only: opts.readOnly,
source: 'default',
source: opts.source || 'default',
}
}),
});
Expand All @@ -36,7 +36,7 @@ export default class HasuraClient {
return JSON.parse(body)
};

async executeMetadataRequest (type, args) {
async executeMetadataRequest (type, args, version) {
const response = await this.deps.fetch(`${process.env.HASURA_ENDPOINT}/v1/metadata`, {
method: 'POST',
headers: {
Expand All @@ -45,6 +45,7 @@ export default class HasuraClient {
body: JSON.stringify({
type,
args,
...(version && { version })
}),
});

Expand All @@ -61,46 +62,61 @@ export default class HasuraClient {
return this.executeMetadataRequest('bulk', metadataRequests);
}

async isSchemaCreated (schemaName) {
async exportMetadata() {
const { metadata } = await this.executeMetadataRequest('export_metadata', {}, 2);
return metadata;
}

async doesSourceExist(source) {
const metadata = await this.exportMetadata();
return metadata.sources.filter(({ name }) => name === source).length > 0;
}

async doesSchemaExist(source, schemaName) {
const { result } = await this.executeSql(
`SELECT schema_name FROM information_schema.schemata WHERE schema_name = '${schemaName}'`,
{ readOnly: true }
{ source, readOnly: true }
);

return result.length > 1;
};
}

createSchema (schemaName) {
createSchema (source, schemaName) {
return this.executeSql(
`CREATE schema ${schemaName}`,
{ readOnly: false }
{ source, readOnly: false }
);
}

runMigrations(schemaName, migration) {
runMigrations(source, schemaName, migration) {
return this.executeSql(
`
set schema '${schemaName}';
${migration}
`,
{ readOnly: false }
{ source, readOnly: false }
);
}

async getTableNames(schemaName) {
const { result } = await this.executeSql(
`SELECT table_name FROM information_schema.tables WHERE table_schema = '${schemaName}'`,
{ readOnly: true }
async getTableNames(schemaName, source) {
const tablesInSource = await this.executeMetadataRequest(
'pg_get_source_tables',
{
source
}
);
const [_columnNames, ...tableNames] = result;
return tableNames.flat();

return tablesInSource
.filter(({ name, schema }) => schema === schemaName)
.map(({ name }) => name);
};

async trackTables(schemaName, tableNames) {
async trackTables(schemaName, tableNames, source) {
return this.executeBulkMetadataRequest(
tableNames.map((name) => ({
type: 'pg_track_table',
args: {
source,
table: {
name,
schema: schemaName,
Expand All @@ -110,7 +126,7 @@ export default class HasuraClient {
);
}

async getForeignKeys(schemaName) {
async getForeignKeys(schemaName, source) {
const { result } = await this.executeSql(
`
SELECT
Expand Down Expand Up @@ -158,16 +174,16 @@ export default class HasuraClient {
q.table_name,
q.constraint_name) AS info;
`,
{ readOnly: true }
{ readOnly: true, source }
);

const [_, [foreignKeysJsonString]] = result;

return JSON.parse(foreignKeysJsonString);
}

async trackForeignKeyRelationships(schemaName) {
const foreignKeys = await this.getForeignKeys(schemaName);
async trackForeignKeyRelationships(schemaName, source) {
const foreignKeys = await this.getForeignKeys(schemaName, source);

if (foreignKeys.length === 0) {
return;
Expand All @@ -179,6 +195,7 @@ export default class HasuraClient {
{
type: "pg_create_array_relationship",
args: {
source,
name: foreignKey.table_name,
table: {
name: foreignKey.ref_table,
Expand All @@ -198,6 +215,7 @@ export default class HasuraClient {
{
type: "pg_create_object_relationship",
args: {
source,
name: pluralize.singular(foreignKey.ref_table),
table: {
name: foreignKey.table_name,
Expand All @@ -213,13 +231,14 @@ export default class HasuraClient {
);
}

async addPermissionsToTables(schemaName, tableNames, roleName, permissions) {
async addPermissionsToTables(schemaName, source, tableNames, roleName, permissions) {
return this.executeBulkMetadataRequest(
tableNames
.map((tableName) => (
permissions.map((permission) => ({
type: `pg_create_${permission}_permission`,
args: {
source,
table: {
name: tableName,
schema: schemaName,
Expand All @@ -234,11 +253,37 @@ export default class HasuraClient {
? { allow_aggregations: true }
: { backend_only: true }),
},
source: 'default'
},
}))
))
.flat()
);
}

async addDatasource(userName, password, databaseName) {
return this.executeMetadataRequest("pg_add_source", {
name: databaseName,
configuration: {
connection_info: {
database_url: {
connection_parameters: {
password,
database: databaseName,
username: userName,
host: process.env.PG_HOST,
port: Number(process.env.PG_PORT),
}
},
},
},
customization: {
root_fields: {
namespace: userName,
},
type_names: {
prefix: `${userName}_`,
},
},
});
}
}
Loading

0 comments on commit 84bf283

Please sign in to comment.