diff --git a/runner/src/hasura-client/hasura-client.ts b/runner/src/hasura-client/hasura-client.ts index 8e987f225..8c6bbc086 100644 --- a/runner/src/hasura-client/hasura-client.ts +++ b/runner/src/hasura-client/hasura-client.ts @@ -16,7 +16,7 @@ interface TableDefinition { name: string schema: string } -interface HasuraRolePermission { +export interface HasuraRolePermission { role: string permission: { check?: Record @@ -26,13 +26,12 @@ interface HasuraRolePermission { allow_aggregations?: boolean } } -type HasuraPermissions = HasuraRolePermission[]; export interface HasuraTableMetadata { table: TableDefinition - insert_permissions?: HasuraPermissions - select_permissions?: HasuraPermissions - update_permissions?: HasuraPermissions - delete_permissions?: HasuraPermissions + insert_permissions?: HasuraRolePermission[] + select_permissions?: HasuraRolePermission[] + update_permissions?: HasuraRolePermission[] + delete_permissions?: HasuraRolePermission[] } export interface HasuraDatabaseConnectionParameters { diff --git a/runner/src/hasura-client/index.ts b/runner/src/hasura-client/index.ts index 79f16d692..fa21831b8 100644 --- a/runner/src/hasura-client/index.ts +++ b/runner/src/hasura-client/index.ts @@ -1,2 +1,2 @@ export { default } from './hasura-client'; -export type { HasuraMetadata, HasuraSource, HasuraConfiguration, HasuraDatabaseConnectionParameters, HasuraTableMetadata, HasuraPermission } from './hasura-client'; +export type { HasuraMetadata, HasuraSource, HasuraConfiguration, HasuraDatabaseConnectionParameters, HasuraTableMetadata, HasuraRolePermission, HasuraPermission } from './hasura-client'; diff --git a/runner/src/provisioner/provisioner.ts b/runner/src/provisioner/provisioner.ts index 55239399e..1e5ec5213 100644 --- a/runner/src/provisioner/provisioner.ts +++ b/runner/src/provisioner/provisioner.ts @@ -3,7 +3,7 @@ import pgFormatLib from 'pg-format'; import { wrapError } from '../utility'; import cryptoModule from 'crypto'; -import HasuraClient, { type HasuraDatabaseConnectionParameters, type HasuraPermission, type HasuraTableMetadata } from '../hasura-client'; +import HasuraClient, { HasuraPermissionMetadata, type HasuraDatabaseConnectionParameters, type HasuraPermission, type HasuraTableMetadata } from '../hasura-client'; import { logsTableDDL } from './schemas/logs-table'; import { metadataTableDDL } from './schemas/metadata-table'; import PgClientClass, { type PostgresConnectionParams } from '../pg-client'; @@ -320,30 +320,41 @@ export default class Provisioner { return trackedTablePermissions; } - private getUntrackedTables (shouldBeTrackedTables: string[], tableMetadata: Map): string[] { - return shouldBeTrackedTables.filter((tableName: string) => !tableMetadata.has(tableName)); + private getUntrackedTables (allTables: string[], tableMetadata: Map): string[] { + return allTables.filter((tableName: string) => !tableMetadata.has(tableName)); } - private getTablesWithoutPermissions ( - userName: string, - shouldHavePermissionsTables: string[], + private getTablesWithoutRole ( + roleName: string, + allTables: string[], tableMetadata: Map, permissionsToCheck: HasuraPermission[] ): string[] { - return shouldHavePermissionsTables.filter((tableName: string) => { - const tablePermissions = tableMetadata.get(tableName); - if (tablePermissions) { - return permissionsToCheck.some((permission: string) => { - const permissionAttribute = `${permission}_permissions` as keyof Omit; - // Returns true if the table does not have the permission or the role doesn't have the permission - const roleIsLackingPermission = !tablePermissions[permissionAttribute]?.some((role: { role: string }) => role.role === userName); - return roleIsLackingPermission; - }); + 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; + return this.roleLacksPermissionInTable(roleName, tablePermissionsMetadata[permissionAttribute]); + }); }); } + private roleLacksPermissionsInTable (roleName: string, tablePermissionsMetadata: HasuraTableMetadata, permissionsToCheck: HasuraPermission[]): boolean { + return permissionsToCheck.some((permission: string) => { + const permissionAttribute = `${permission}_permissions` as keyof Omit; + 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 + return !tablePermission?.some((roleWithPermission: { role: string }) => roleWithPermission.role === roleName); + } + async provisionUserApi (indexerConfig: IndexerConfig): Promise { // replace any with actual type const provisioningSpan = this.tracer.startSpan('Provision indexer resources'); const userName = indexerConfig.userName();