Skip to content

Commit

Permalink
Add revoke tests
Browse files Browse the repository at this point in the history
  • Loading branch information
littlewhywhat committed Jan 10, 2022
1 parent 0f3c332 commit 25b36f8
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 15 deletions.
31 changes: 31 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,23 @@ import {
RefreshMaterializedViewOptions,
} from './operations/viewsMaterializedTypes'

import {
TablePrivilege,
SchemaPrivilege,
GrantRoles,
GrantRolesOptions,
GrantOnTables,
GrantOnTablesProps,
GrantOnSchemas,
GrantOnSchemasProps,
RevokeRoles,
RevokeRolesOptions,
RevokeOnTables,
RevokeOnTablesProps,
RevokeOnSchemas,
RevokeOnSchemasProps,
} from './operations/grants'

export {
PgLiteral,
Migration,
Expand Down Expand Up @@ -235,6 +252,20 @@ export {
CreateMaterializedViewOptions,
AlterMaterializedViewOptions,
RefreshMaterializedViewOptions,
TablePrivilege,
SchemaPrivilege,
GrantRoles,
GrantRolesOptions,
GrantOnTables,
GrantOnTablesProps,
GrantOnSchemas,
GrantOnSchemasProps,
RevokeRoles,
RevokeRolesOptions,
RevokeOnTables,
RevokeOnTablesProps,
RevokeOnSchemas,
RevokeOnSchemasProps,
}

export default runner
26 changes: 24 additions & 2 deletions src/operations/grants.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
import { MigrationOptions } from '../types'
import {
TablePrivilege,
SchemaPrivilege,
GrantRoles,
GrantRolesOptions,
GrantOnTables,
GrantOnSchemas,
GrantOnTablesProps,
GrantOnAllTablesProps,
GrantOnSchemas,
GrantOnSchemasProps,
RevokeRoles,
RevokeRolesOptions,
RevokeOnTables,
RevokeOnTablesProps,
RevokeOnSchemas,
RevokeOnSchemasProps,
} from './grantsTypes'

export { GrantRoles, RevokeRoles, GrantOnTables, RevokeOnTables, GrantOnSchemas, RevokeOnSchemas }
export {
TablePrivilege,
SchemaPrivilege,
GrantRoles,
GrantRolesOptions,
GrantOnTables,
GrantOnTablesProps,
GrantOnSchemas,
GrantOnSchemasProps,
RevokeRoles,
RevokeRolesOptions,
RevokeOnTables,
RevokeOnTablesProps,
RevokeOnSchemas,
RevokeOnSchemasProps,
}

const isArray = <T>(item: T | T[]): item is T[] => {
return typeof item !== 'string' && Boolean((item as Array<T>).length !== undefined)
Expand Down
21 changes: 11 additions & 10 deletions src/operations/grantsTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,22 @@ interface WithGrantOption {
readonly withGrantOption?: boolean
}

type DropRolesOptions = OnlyAdminOption & RestrictOption

export type RevokeRolesOptions = OnlyAdminOption & RestrictOption
export type GrantRolesOptions = WithAdminOption & RevokeRolesOptions
type GrantRolesFn = (
rolesFrom: Name | Name[],
rolesTo: Name | Name[],
grantRolesOptions?: WithAdminOption & DropRolesOptions,
grantRolesOptions?: GrantRolesOptions,
) => string | string[]
export type GrantRoles = GrantRolesFn & { reverse: GrantRolesFn }
export type RevokeRoles = (
roles: Name | Name[],
rolesFrom: Name | Name[],
dropRolesOptions?: DropRolesOptions,
RevokeRolesOptions?: RevokeRolesOptions,
) => string | string[]

type TablePrivilege = 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE' | 'TRUNCATE' | 'REFERENCES' | 'TRIGGER'
type SchemaPrivilege = 'CREATE' | 'USAGE'
export type TablePrivilege = 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE' | 'TRUNCATE' | 'REFERENCES' | 'TRIGGER'
export type SchemaPrivilege = 'CREATE' | 'USAGE'

interface CommonOnTablesProps {
privileges: TablePrivilege | TablePrivilege[] | 'ALL'
Expand Down Expand Up @@ -68,12 +68,13 @@ type GrantOnTablesFn = (props: GrantOnTablesProps & RevokeOnObjectsProps) => str
export type GrantOnTables = GrantOnTablesFn & { reverse: GrantOnTablesFn }
export type RevokeOnTables = (props: RevokeOnTablesProps) => string | string[]

interface GrantOnSchemasProps {
export interface OnlyGrantOnSchemasProps {
privileges: SchemaPrivilege | SchemaPrivilege[] | 'ALL'
schemas: string[] | string
roles: Name | Name[]
}

type GrantOnSchemasFn = (props: GrantOnSchemasProps & WithGrantOption & RevokeOnObjectsProps) => string | string[]
export type GrantOnSchemasProps = OnlyGrantOnSchemasProps & WithGrantOption & RevokeOnObjectsProps
export type RevokeOnSchemasProps = OnlyGrantOnSchemasProps & RevokeOnObjectsProps
type GrantOnSchemasFn = (props: GrantOnSchemasProps) => string | string[]
export type GrantOnSchemas = GrantOnSchemasFn & { reverse: GrantOnSchemasFn }
export type RevokeOnSchemas = (props: GrantOnSchemasProps & RevokeOnObjectsProps) => string | string[]
export type RevokeOnSchemas = (props: RevokeOnSchemasProps) => string | string[]
6 changes: 3 additions & 3 deletions test/migrations/086_grant_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const {
constants: { schema, table, role1, role2, tablePrivileges, schemaPrivilege },
} = require('./085_grant_tables_schemas_roles')

const hasTablePrivileges = async (pgm, role, tableName, privileges) => {
export const hasTablePrivileges = async (pgm, role, tableName, privileges) => {
const rows = await pgm.db.select(`
SELECT grantee, privilege_type
FROM information_schema.role_table_grants
Expand All @@ -13,14 +13,14 @@ const hasTablePrivileges = async (pgm, role, tableName, privileges) => {
return privileges.reduce((acc, privilege) => acc && foundPrivileges.includes(privilege), true)
}

const hasSchemaPrivilege = async (pgm, role, schemaName, privilege) => {
export const hasSchemaPrivilege = async (pgm, role, schemaName, privilege) => {
const rows = await pgm.db.select(`
SELECT has_schema_privilege('${role}', '${schemaName}', '${privilege}');
`)
return rows.length && rows[0].has_schema_privilege
}

const isMemberOf = async (pgm, role, roleGroups) => {
export const isMemberOf = async (pgm, role, roleGroups) => {
const rows = await pgm.db.select(`
SELECT rolname FROM pg_roles WHERE pg_has_role('${role}', oid, 'member') AND rolname <> '${role}';
`)
Expand Down
17 changes: 17 additions & 0 deletions test/migrations/087_revoke_tables_schemas_roles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const {
constants: { schema, table, role1, role2, tablePrivileges, schemaPrivilege },
} = require('./085_grant_tables_schemas_roles')

exports.up = (pgm) => {
pgm.revokeRoles(role1, role2)
pgm.revokeOnSchemas({
privileges: schemaPrivilege,
schemas: schema,
roles: role1,
})
pgm.revokeOnTables({
privileges: tablePrivileges,
tables: table,
roles: role1,
})
}
22 changes: 22 additions & 0 deletions test/migrations/088_revoke_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const {
constants: { schema, table, role1, role2, tablePrivileges, schemaPrivilege },
} = require('./085_grant_tables_schemas_roles')

const { hasTablePrivileges, hasSchemaPrivilege, isMemberOf } = require('./086_grant_test')

exports.up = async (pgm) => {
const hasGrantedTablePrivileges = await hasTablePrivileges(pgm, role1, table, tablePrivileges)
if (hasGrantedTablePrivileges) {
throw new Error(`${role1}'s table privileges were not revoked`)
}
const hasGrantedSchemaPrivilege = await hasSchemaPrivilege(pgm, role1, schema, schemaPrivilege)
if (hasGrantedSchemaPrivilege) {
throw new Error(`${role1}'s USAGE schema privilege was not revoked`)
}
const isMemberOfRole1 = await isMemberOf(pgm, role2, [role1])
if (isMemberOfRole1) {
throw new Error(`${role2}'s membership of ${role1} was not revoked`)
}
}

exports.down = () => null

0 comments on commit 25b36f8

Please sign in to comment.