Skip to content

Commit

Permalink
Merge pull request #477 from supabase/or/function_return_row_must_be_…
Browse files Browse the repository at this point in the history
…selectable

If a Function returns a table type, the table must be selectable
  • Loading branch information
imor authored Dec 25, 2023
2 parents 08df171 + 7df8838 commit 490214d
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 1 deletion.
12 changes: 11 additions & 1 deletion src/graphql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1284,10 +1284,20 @@ fn function_fields(schema: &Arc<__Schema>, volatilities: &[FunctionVolatility])
return None;
}
}

gql_args.extend(connection_args);
}

// If the return type is a table type, it must be selectable
if !match &return_type {
__Type::Node(table_type) => table_type.table.permissions.is_selectable,
__Type::Connection(table_type) => {
table_type.table.permissions.is_selectable
}
_ => true,
} {
return None;
}

Some(__Field {
name_: schema.graphql_function_field_name(func),
type_: __Type::FuncCallResponse(FuncCallResponseType {
Expand Down
128 changes: 128 additions & 0 deletions test/expected/function_return_row_is_selectable.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
begin;
create table account(
id serial primary key,
email varchar(255) not null
);
create function returns_account()
returns account language sql stable
as $$ select id, email from account; $$;
insert into account(email)
values
('[email protected]');
create role anon;
grant usage on schema graphql to anon;
grant select on account to anon;
savepoint a;
set local role anon;
-- Should be visible
select jsonb_pretty(
graphql.resolve($$
{
__type(name: "Account") {
__typename
}
}
$$)
);
jsonb_pretty
-------------------------------------
{ +
"data": { +
"__type": { +
"__typename": "Account"+
} +
} +
}
(1 row)

-- Should show an entrypoint on Query for returnAccount
select jsonb_pretty(
graphql.resolve($$
query IntrospectionQuery {
__schema {
queryType {
fields {
name
}
}
}
}
$$)
);
jsonb_pretty
-----------------------------------------------------
{ +
"data": { +
"__schema": { +
"queryType": { +
"fields": [ +
{ +
"name": "accountCollection"+
}, +
{ +
"name": "node" +
}, +
{ +
"name": "returnsAccount" +
} +
] +
} +
} +
} +
}
(1 row)

rollback to a;
revoke select on account from anon;
set local role anon;
-- We should no longer see "Account" types after revoking access
select jsonb_pretty(
graphql.resolve($$
{
__type(name: "Account") {
__typename
}
}
$$)
);
jsonb_pretty
------------------------
{ +
"data": { +
"__type": null+
} +
}
(1 row)

-- We should no longer see returnAccount since it references an unknown return type "Account"
select jsonb_pretty(
graphql.resolve($$
query IntrospectionQuery {
__schema {
queryType {
fields {
name
}
}
}
}
$$)
);
jsonb_pretty
----------------------------------------
{ +
"data": { +
"__schema": { +
"queryType": { +
"fields": [ +
{ +
"name": "node"+
} +
] +
} +
} +
} +
}
(1 row)

rollback;
82 changes: 82 additions & 0 deletions test/sql/function_return_row_is_selectable.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
begin;

create table account(
id serial primary key,
email varchar(255) not null
);

create function returns_account()
returns account language sql stable
as $$ select id, email from account; $$;

insert into account(email)
values
('[email protected]');


create role anon;
grant usage on schema graphql to anon;
grant select on account to anon;

savepoint a;

set local role anon;

-- Should be visible
select jsonb_pretty(
graphql.resolve($$
{
__type(name: "Account") {
__typename
}
}
$$)
);

-- Should show an entrypoint on Query for returnAccount
select jsonb_pretty(
graphql.resolve($$
query IntrospectionQuery {
__schema {
queryType {
fields {
name
}
}
}
}
$$)
);

rollback to a;

revoke select on account from anon;
set local role anon;

-- We should no longer see "Account" types after revoking access
select jsonb_pretty(
graphql.resolve($$
{
__type(name: "Account") {
__typename
}
}
$$)
);

-- We should no longer see returnAccount since it references an unknown return type "Account"
select jsonb_pretty(
graphql.resolve($$
query IntrospectionQuery {
__schema {
queryType {
fields {
name
}
}
}
}
$$)
);

rollback;

0 comments on commit 490214d

Please sign in to comment.