Skip to content

Commit

Permalink
fix: identifier double escaping
Browse files Browse the repository at this point in the history
`::regclass` already escapes identifier names, no need to `%I` it
  • Loading branch information
soedirgo committed Aug 9, 2023
1 parent 34dd105 commit 75da739
Show file tree
Hide file tree
Showing 4 changed files with 372 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/lib/PostgresMetaColumnPrivileges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ where a.attrelid = ${literal(relationId)}
and a.attnum = ${literal(columnNumber)}
into col;
execute format(
'grant ${privilege_type} (%I) on %I to ${
'grant ${privilege_type} (%I) on %s to ${
grantee.toLowerCase() === 'public' ? 'public' : ident(grantee)
} ${is_grantable ? 'with grant option' : ''}',
col.attname,
Expand Down Expand Up @@ -113,7 +113,7 @@ where a.attrelid = ${literal(relationId)}
and a.attnum = ${literal(columnNumber)}
into col;
execute format(
'revoke ${privilege_type} (%I) on %I from ${
'revoke ${privilege_type} (%I) on %s from ${
grantee.toLowerCase() === 'public' ? 'public' : ident(grantee)
}',
col.attname,
Expand Down
4 changes: 2 additions & 2 deletions src/lib/PostgresMetaTablePrivileges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ begin
${grants
.map(
({ privilege_type, relation_id, grantee, is_grantable }) =>
`execute format('grant ${privilege_type} on table %I to ${
`execute format('grant ${privilege_type} on table %s to ${
grantee.toLowerCase() === 'public' ? 'public' : ident(grantee)
} ${is_grantable ? 'with grant option' : ''}', ${relation_id}::regclass);`
)
Expand Down Expand Up @@ -147,7 +147,7 @@ begin
${revokes
.map(
(revoke) =>
`execute format('revoke ${revoke.privilege_type} on table %I from ${revoke.grantee}', ${revoke.relation_id}::regclass);`
`execute format('revoke ${revoke.privilege_type} on table %s from ${revoke.grantee}', ${revoke.relation_id}::regclass);`
)
.join('\n')}
end $$;
Expand Down
159 changes: 157 additions & 2 deletions test/server/column-privileges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ test('revoke & grant column privileges', async () => {
],
})
let privs = res.json<PostgresColumnPrivileges[]>()
expect(privs.length === 1)
expect(privs.length).toBe(1)
expect(privs[0]).toMatchInlineSnapshot(
{ column_id: expect.stringMatching(/^\d+\.\d+$/) },
`
Expand Down Expand Up @@ -156,7 +156,7 @@ test('revoke & grant column privileges', async () => {
],
})
privs = res.json<PostgresColumnPrivileges[]>()
expect(privs.length === 1)
expect(privs.length).toBe(1)
expect(privs[0]).toMatchInlineSnapshot(
{ column_id: expect.stringMatching(/^\d+\.\d+$/) },
`
Expand Down Expand Up @@ -206,3 +206,158 @@ test('revoke & grant column privileges', async () => {
throw new Error(res.payload)
}
})

test('revoke & grant column privileges w/ quoted column name', async () => {
let res = await app.inject({
method: 'POST',
path: '/query',
payload: {
query: `create role r; create table "t 1"("c 1" int8);`,
},
})
if (res.json().error) {
throw new Error(res.payload)
}

res = await app.inject({ method: 'GET', path: '/column-privileges' })
const { column_id } = res
.json<PostgresColumnPrivileges[]>()
.find(({ relation_name, column_name }) => relation_name === 't 1' && column_name === 'c 1')!

res = await app.inject({
method: 'POST',
path: '/column-privileges',
payload: [
{
column_id,
grantee: 'r',
privilege_type: 'ALL',
},
],
})
let privs = res.json<PostgresColumnPrivileges[]>()
expect(privs.length).toBe(1)
expect(privs[0]).toMatchInlineSnapshot(
{ column_id: expect.stringMatching(/^\d+\.\d+$/) },
`
{
"column_id": StringMatching /\\^\\\\d\\+\\\\\\.\\\\d\\+\\$/,
"column_name": "c 1",
"privileges": [
{
"grantee": "r",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "UPDATE",
},
{
"grantee": "r",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "SELECT",
},
{
"grantee": "r",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "REFERENCES",
},
{
"grantee": "r",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "INSERT",
},
{
"grantee": "postgres",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "UPDATE",
},
{
"grantee": "postgres",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "SELECT",
},
{
"grantee": "postgres",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "REFERENCES",
},
{
"grantee": "postgres",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "INSERT",
},
],
"relation_name": "t 1",
"relation_schema": "public",
}
`
)

res = await app.inject({
method: 'DELETE',
path: '/column-privileges',
payload: [
{
column_id,
grantee: 'r',
privilege_type: 'ALL',
},
],
})
privs = res.json<PostgresColumnPrivileges[]>()
expect(privs.length).toBe(1)
expect(privs[0]).toMatchInlineSnapshot(
{ column_id: expect.stringMatching(/^\d+\.\d+$/) },
`
{
"column_id": StringMatching /\\^\\\\d\\+\\\\\\.\\\\d\\+\\$/,
"column_name": "c 1",
"privileges": [
{
"grantee": "postgres",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "UPDATE",
},
{
"grantee": "postgres",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "SELECT",
},
{
"grantee": "postgres",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "REFERENCES",
},
{
"grantee": "postgres",
"grantor": "postgres",
"is_grantable": false,
"privilege_type": "INSERT",
},
],
"relation_name": "t 1",
"relation_schema": "public",
}
`
)

res = await app.inject({
method: 'POST',
path: '/query',
payload: {
query: `drop role r; drop table "t 1";`,
},
})
if (res.json().error) {
throw new Error(res.payload)
}
})
Loading

0 comments on commit 75da739

Please sign in to comment.