Skip to content

Commit

Permalink
Add revoke declarations
Browse files Browse the repository at this point in the history
  • Loading branch information
littlewhywhat committed Jan 10, 2022
1 parent ff3441b commit 0f3c332
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 50 deletions.
9 changes: 9 additions & 0 deletions src/migration-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,16 @@ export default class MigrationBuilderImpl implements MigrationBuilder {

public readonly grantRoles: (...args: Parameters<grants.GrantRoles>) => void

public readonly revokeRoles: (...args: Parameters<grants.RevokeRoles>) => void

public readonly grantOnTables: (...args: Parameters<grants.GrantOnTables>) => void

public readonly revokeOnTables: (...args: Parameters<grants.RevokeOnTables>) => void

public readonly grantOnSchemas: (...args: Parameters<grants.GrantOnSchemas>) => void

public readonly revokeOnSchemas: (...args: Parameters<grants.RevokeOnSchemas>) => void

public readonly sql: (...args: Parameters<other.Sql>) => void

public readonly func: (sql: string) => PgLiteral
Expand Down Expand Up @@ -331,8 +337,11 @@ export default class MigrationBuilderImpl implements MigrationBuilder {
this.refreshMaterializedView = wrap(mViews.refreshMaterializedView(options))

this.grantRoles = wrap(grants.grantRoles(options))
this.revokeRoles = wrap(grants.revokeRoles(options))
this.grantOnTables = wrap(grants.grantOnTables(options))
this.revokeOnTables = wrap(grants.revokeOnTables(options))
this.grantOnSchemas = wrap(grants.grantOnSchemas(options))
this.revokeOnSchemas = wrap(grants.revokeOnSchemas(options))

this.sql = wrap(other.sql(options))

Expand Down
45 changes: 30 additions & 15 deletions src/operations/grants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import { MigrationOptions } from '../types'
import { GrantRoles, GrantOnTables, GrantOnSchemas, GrantOnTablesProps, GrantOnAllTablesProps } from './grantsTypes'
import {
GrantRoles,
GrantOnTables,
GrantOnSchemas,
GrantOnTablesProps,
GrantOnAllTablesProps,
RevokeRoles,
RevokeOnTables,
RevokeOnSchemas,
} from './grantsTypes'

export { GrantRoles, GrantOnTables, GrantOnSchemas }
export { GrantRoles, RevokeRoles, GrantOnTables, RevokeOnTables, GrantOnSchemas, RevokeOnSchemas }

const isArray = <T>(item: T | T[]): item is T[] => {
return typeof item !== 'string' && Boolean((item as Array<T>).length !== undefined)
Expand All @@ -13,19 +22,26 @@ const isGrantOnAllTablesProps = (props: GrantOnTablesProps): props is GrantOnAll
return 'schema' in props
}

export function revokeRoles(mOptions: MigrationOptions) {
const _revokeRoles: RevokeRoles = () => ''
return _revokeRoles
}

export function grantRoles(mOptions: MigrationOptions) {
const _grantRoles: GrantRoles = (rolesFrom, rolesTo) => {
const _grantRoles: GrantRoles = (rolesFrom, rolesTo, options) => {
const rolesFromStr = asArray(rolesFrom).map(mOptions.literal).join(',')
const rolesToStr = asArray(rolesTo).map(mOptions.literal).join(',')
return `GRANT ${rolesFromStr} TO ${rolesToStr};`
}
_grantRoles.reverse = () => {
console.log('reverse')
return ''
}
_grantRoles.reverse = revokeRoles(mOptions)
return _grantRoles
}

export function revokeOnTables(mOptions: MigrationOptions) {
const _revokeOnTables: RevokeOnTables = () => ''
return _revokeOnTables
}

export function grantOnTables(mOptions: MigrationOptions) {
const _grantOnTables: GrantOnTables = (props) => {
const { privileges, roles, withGrantOption } = props
Expand All @@ -42,13 +58,15 @@ export function grantOnTables(mOptions: MigrationOptions) {
const withGrantOptionStr = withGrantOption ? ' WITH GRANT OPTION' : ''
return `GRANT ${privilegesStr} ON ${tablesStr} TO ${rolesStr}${withGrantOptionStr};`
}
_grantOnTables.reverse = () => {
console.log('grantOnTables reverse')
return ''
}
_grantOnTables.reverse = revokeOnTables(mOptions)
return _grantOnTables
}

export function revokeOnSchemas(mOptions: MigrationOptions) {
const _revokeOnSchemas: RevokeOnSchemas = () => ''
return _revokeOnSchemas
}

export function grantOnSchemas(mOptions: MigrationOptions) {
const _grantOnSchemas: GrantOnSchemas = ({ privileges, schemas, roles, withGrantOption }) => {
const rolesStr = asArray(roles).map(mOptions.literal).join(',')
Expand All @@ -57,9 +75,6 @@ export function grantOnSchemas(mOptions: MigrationOptions) {
const withGrantOptionStr = withGrantOption ? ' WITH GRANT OPTION' : ''
return `GRANT ${privilegesStr} ON SCHEMA ${schemasStr} TO ${rolesStr}${withGrantOptionStr};`
}
_grantOnSchemas.reverse = () => {
console.log('grantOnSchemas reverse')
return ''
}
_grantOnSchemas.reverse = revokeOnSchemas(mOptions)
return _grantOnSchemas
}
50 changes: 41 additions & 9 deletions src/operations/grantsTypes.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,79 @@
import { Name } from '..'
import { CascadeOption, Name } from '..'

interface WithAdminOption {
readonly withAdminOption?: boolean
}

interface OnlyAdminOption {
readonly onlyAdminOption?: boolean
}

interface OnlyGrantOption {
readonly onlyGrantOption?: boolean
}

interface RestrictOption {
readonly restrict?: boolean
}

interface WithGrantOption {
readonly withGrantOption?: boolean
}

type DropRolesOptions = OnlyAdminOption & RestrictOption

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

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

export interface GrantOnSomeTablesProps extends WithGrantOption {
interface CommonOnTablesProps {
privileges: TablePrivilege | TablePrivilege[] | 'ALL'
tables: Name | Name[]
roles: Name | Name[]
}

export interface GrantOnAllTablesProps extends WithGrantOption {
privileges: TablePrivilege | TablePrivilege[] | 'ALL'
type CommonGrantOnTablesProps = CommonOnTablesProps & WithGrantOption

interface OnlyGrantOnSomeTablesProps {
tables: Name | Name[]
}

interface OnlyGrantOnAllTablesProps {
tables: 'ALL'
schema: string
roles: Name | Name[]
}

type RevokeOnObjectsProps = OnlyGrantOption & RestrictOption & CascadeOption

export type GrantOnSomeTablesProps = CommonGrantOnTablesProps & OnlyGrantOnSomeTablesProps
export type GrantOnAllTablesProps = CommonGrantOnTablesProps & OnlyGrantOnAllTablesProps

export type GrantOnTablesProps = GrantOnSomeTablesProps | GrantOnAllTablesProps
export type RevokeOnTablesProps = CommonOnTablesProps &
(OnlyGrantOnAllTablesProps | OnlyGrantOnSomeTablesProps) &
RevokeOnObjectsProps

type GrantOnTablesFn = (props: GrantOnTablesProps) => string | string[]
type GrantOnTablesFn = (props: GrantOnTablesProps & RevokeOnObjectsProps) => string | string[]

export type GrantOnTables = GrantOnTablesFn & { reverse: GrantOnTablesFn }
export type RevokeOnTables = (props: RevokeOnTablesProps) => string | string[]

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

type GrantOnSchemasFn = (props: GrantOnSchemasProps & WithGrantOption) => string | string[]
type GrantOnSchemasFn = (props: GrantOnSchemasProps & WithGrantOption & RevokeOnObjectsProps) => string | string[]
export type GrantOnSchemas = GrantOnSchemasFn & { reverse: GrantOnSchemasFn }
export type RevokeOnSchemas = (props: GrantOnSchemasProps & RevokeOnObjectsProps) => string | string[]
3 changes: 3 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,11 @@ export interface MigrationBuilder {
renameMaterializedViewColumn: (...args: Parameters<mViews.RenameMaterializedViewColumn>) => void
refreshMaterializedView: (...args: Parameters<mViews.RefreshMaterializedView>) => void
grantRoles: (...args: Parameters<grants.GrantRoles>) => void
revokeRoles: (...args: Parameters<grants.RevokeRoles>) => void
grantOnTables: (...args: Parameters<grants.GrantOnTables>) => void
revokeOnTables: (...args: Parameters<grants.RevokeOnTables>) => void
grantOnSchemas: (...args: Parameters<grants.GrantOnSchemas>) => void
revokeOnSchemas: (...args: Parameters<grants.RevokeOnSchemas>) => void
sql: (...args: Parameters<other.Sql>) => void
func: (sql: string) => PgLiteral
noTransaction: () => void
Expand Down
26 changes: 0 additions & 26 deletions test/migrations/085_grant_tables_schemas_roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,3 @@ exports.up = (pgm) => {
})
pgm.grantRoles(role1, role2)
}

// Test table privileges
/*
SELECT grantee, privilege_type
FROM information_schema.role_table_grants
WHERE table_name='Games' AND grantee = 'test2'
// table privileges
SELECT grantor, grantee, table_schema, table_name, privilege_type
FROM information_schema.table_privileges
WHERE grantee = 'myuser'
// schema information
SELECT n.nspname AS "Name",
pg_catalog.pg_get_userbyid(n.nspowner) AS "Owner",
pg_catalog.array_to_string(n.nspacl, E'\n') AS "Access privileges",
pg_catalog.obj_description(n.oid, 'pg_namespace') AS "Description"
FROM pg_catalog.pg_namespace n
WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'
ORDER BY 1;
// concrete schema
SELECT n.nspacl AS "Access privileges"
FROM pg_catalog.pg_namespace n
WHERE n.nspname !~ '^pg_' AND n.nspname = 'hollywood';
*/

0 comments on commit 0f3c332

Please sign in to comment.