Skip to content

Commit

Permalink
Refactor getting tables without permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
darunrs committed Apr 18, 2024
1 parent c1d92a7 commit 15d4b4a
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 49 deletions.
58 changes: 26 additions & 32 deletions runner/src/provisioner/provisioner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import pgFormat from 'pg-format';
import Provisioner from './provisioner';
import IndexerConfig from '../indexer-config/indexer-config';
import { LogLevel } from '../indexer-meta/log-entry';
import { type HasuraTableMetadata } from '../hasura-client';
import { type HasuraPermission, type HasuraTableMetadata } from '../hasura-client';

describe('Provisioner', () => {
let adminPgClient: any;
Expand Down Expand Up @@ -251,44 +251,35 @@ describe('Provisioner', () => {
});

it('ensuring consistent state tracks logs and metadata table once, adds permissions twice', async () => {
hasuraClient.getTrackedTablePermissions = jest.fn().mockReturnValueOnce([]).mockReturnValueOnce([
{
table: {
name: 'blocks',
schema: 'morgs_near_test_function',
},
},
{
table: {
name: '__logs',
schema: 'morgs_near_test_function',
},
},
{
table: {
name: '__metadata',
schema: 'morgs_near_test_function',
},
}
]);
hasuraClient.getTableNames = jest.fn().mockReturnValueOnce(['blocks']).mockReturnValueOnce(['blocks', '__logs', '__metadata']);
hasuraClient.getTableNames = jest.fn().mockReturnValue(['blocks', '__logs', '__metadata']);
hasuraClient.getTrackedTablePermissions = jest.fn()
.mockReturnValueOnce([
generateTableConfig('morgs_near_test_function', 'blocks', 'morgs_near', ['select', 'insert', 'update', 'delete']),
])
.mockReturnValueOnce([
generateTableConfig('morgs_near_test_function', 'blocks', 'morgs_near', ['select', 'insert', 'update', 'delete']),
generateTableConfig('morgs_near_test_function', '__logs', 'morgs_near', []),
generateTableConfig('morgs_near_test_function', '__metadata', 'morgs_near', []),
]);
await provisioner.ensureConsistentHasuraState(indexerConfig);
await provisioner.ensureConsistentHasuraState(indexerConfig);

expect(hasuraClient.getTableNames).toBeCalledTimes(2);
expect(hasuraClient.trackTables).toBeCalledTimes(1);
expect(hasuraClient.addPermissionsToTables).toBeCalledTimes(2);
});

it('ensuring consistent state caches result', async () => {
hasuraClient.getTableNames = jest.fn().mockReturnValue(['blocks', '__logs', '__metadata']);
hasuraClient.getTrackedTablePermissions = jest.fn().mockReturnValue([
generateTableConfig('morgs_near_test_function', 'blocks', 'morgs_near'),
generateTableConfig('morgs_near_test_function', '__logs', 'morgs_near'),
generateTableConfig('morgs_near_test_function', '__metadata', 'morgs_near'),
generateTableConfig('morgs_near_test_function', 'blocks', 'morgs_near', ['select', 'insert', 'update', 'delete']),
generateTableConfig('morgs_near_test_function', '__logs', 'morgs_near', ['select', 'insert', 'update', 'delete']),
generateTableConfig('morgs_near_test_function', '__metadata', 'morgs_near', ['select', 'insert', 'update', 'delete']),
]);
hasuraClient.getTableNames = jest.fn().mockReturnValue(['blocks', '__logs', '__metadata']);
await provisioner.ensureConsistentHasuraState(indexerConfig);
await provisioner.ensureConsistentHasuraState(indexerConfig);

expect(hasuraClient.getTableNames).toBeCalledTimes(1);
expect(hasuraClient.trackTables).not.toBeCalled();
expect(hasuraClient.addPermissionsToTables).not.toBeCalled();
expect(userPgClientQuery).not.toBeCalled();
Expand Down Expand Up @@ -352,15 +343,18 @@ describe('Provisioner', () => {
});
});

function generateTableConfig (schemaName: string, tableName: string, role: string): HasuraTableMetadata {
return {
function generateTableConfig (schemaName: string, tableName: string, role: string, permissionsToAdd: HasuraPermission[]): HasuraTableMetadata {
const config: HasuraTableMetadata = {
table: {
name: tableName,
schema: schemaName,
},
insert_permissions: [{ role, permission: {} }],
select_permissions: [{ role, permission: {} }],
update_permissions: [{ role, permission: {} }],
delete_permissions: [{ role, permission: {} }],
};

permissionsToAdd.forEach((permission) => {
const permissionKey: keyof Omit<HasuraTableMetadata, 'table'> = `${permission}_permissions`;
config[permissionKey] = [{ role, permission: {} }];
});

return config;
}
38 changes: 21 additions & 17 deletions runner/src/provisioner/provisioner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import pgFormatLib from 'pg-format';

import { wrapError } from '../utility';
import cryptoModule from 'crypto';
import HasuraClient, { HasuraPermissionMetadata, type HasuraDatabaseConnectionParameters, type HasuraPermission, type HasuraTableMetadata } from '../hasura-client';
import HasuraClient, {
type HasuraDatabaseConnectionParameters,
type HasuraPermission,
type HasuraTableMetadata,
type HasuraRolePermission
} from '../hasura-client';
import { logsTableDDL } from './schemas/logs-table';
import { metadataTableDDL } from './schemas/metadata-table';
import PgClientClass, { type PostgresConnectionParams } from '../pg-client';
Expand Down Expand Up @@ -289,22 +294,25 @@ export default class Provisioner {

const hasuraTablesMetadata = await this.getTrackedTablesWithPermissions(indexerConfig);
const untrackedTables = this.getUntrackedTables(tableNamesToCheck, hasuraTablesMetadata);
const tablesWithoutPermissions = this.getTablesWithoutPermissions(
const tablesWithoutPermissions = this.getTablesWithoutRole(
indexerConfig.hasuraRoleName(),
tableNamesToCheck,
hasuraTablesMetadata,
permissionsToAdd
);
console.log('untrackedTables', untrackedTables);
console.log('tablesWithoutPermissions', tablesWithoutPermissions);

if (untrackedTables.length === 0 && tablesWithoutPermissions.length === 0) {
console.log('Consistent state achieved');
this.setConsistentState(indexerConfig.accountId, indexerConfig.functionName);
} else {
if (untrackedTables.length > 0) {
await this.trackTables(indexerConfig.schemaName(), untrackedTables, indexerConfig.databaseName());
}
if (tablesWithoutPermissions.length > 0) {
await this.addPermissionsToTables(indexerConfig, tablesWithoutPermissions, permissionsToAdd);
}
return;
}
if (untrackedTables.length > 0) {
await this.trackTables(indexerConfig.schemaName(), untrackedTables, indexerConfig.databaseName());
}
if (tablesWithoutPermissions.length > 0) {
await this.addPermissionsToTables(indexerConfig, tablesWithoutPermissions, permissionsToAdd);
}
}, 'Failed to ensure consistent Hasura state');
}
Expand Down Expand Up @@ -333,25 +341,21 @@ export default class Provisioner {
return allTables.filter((tableName: string) => {
const tablePermissionsMetadata = tableMetadata.get(tableName);
if (!tablePermissionsMetadata) {
return false;
return true;
}

return permissionsToCheck.some((permission: string) => {
const permissionAttribute = `${permission}_permissions` as keyof Omit<HasuraTableMetadata, 'table'>;
return this.roleLacksPermissionInTable(roleName, tablePermissionsMetadata[permissionAttribute]);
});
return this.roleLacksPermissionsForTable(roleName, tablePermissionsMetadata, permissionsToCheck);
});
}

private roleLacksPermissionsInTable (roleName: string, tablePermissionsMetadata: HasuraTableMetadata, permissionsToCheck: HasuraPermission[]): boolean {
private roleLacksPermissionsForTable (roleName: string, tablePermissionsMetadata: HasuraTableMetadata, permissionsToCheck: HasuraPermission[]): boolean {
return permissionsToCheck.some((permission: string) => {
const permissionAttribute = `${permission}_permissions` as keyof Omit<HasuraTableMetadata, 'table'>;
return this.roleLacksPermission(roleName, tablePermissionsMetadata[permissionAttribute]);
});
}

private roleLacksPermission (roleName: string, tablePermission: HasuraPermissionMetadata | undefined): boolean {
// Returns true if the table does not have the permission or the specified role lacks the permission
private roleLacksPermission (roleName: string, tablePermission: HasuraRolePermission[] | undefined): boolean {
return !tablePermission?.some((roleWithPermission: { role: string }) => roleWithPermission.role === roleName);
}

Expand Down

0 comments on commit 15d4b4a

Please sign in to comment.