hasura / graphql-engine

Blazing fast, instant realtime GraphQL APIs on your DB with fine grained access control, also trigger webhooks on database events.
https://hasura.io
Apache License 2.0
31.18k stars 2.77k forks source link

Cannot assign permissions for cross-schema scalar calculated fields #4766

Open nottheswimmer opened 4 years ago

nottheswimmer commented 4 years ago

Whenever creating a calculated field for a table in a schema (let's say the not_public schema), it seems that if the function used for the calculated field is from a different schema (let's say the public schema), then the calculated field will work for the administrator but you cannot assign permissions to it (at least through the GUI).

Steps to reproduce:

  1. Create a new user such as...
    CREATE ROLE not_public_user WITH
    LOGIN
    NOSUPERUSER
    INHERIT
    CREATEDB
    NOCREATEROLE
    NOREPLICATION;
  2. Create a new schema such as...
    CREATE SCHEMA not_public
    AUTHORIZATION not_public_user;
    GRANT USAGE ON SCHEMA not_public TO hasurauser;
    GRANT ALL ON SCHEMA not_public TO not_public_user;
  3. Create a table in your new schema such as...
    CREATE TABLE not_public.person
    (
    per_id not_public.per_id_type NOT NULL,
    first_name text COLLATE pg_catalog."default",
    chosen_first_name text COLLATE pg_catalog."default",
    CONSTRAINT person_pkey PRIMARY KEY (per_id),
    )
    WITH (
    OIDS = FALSE
    )
    TABLESPACE pg_default;
    ALTER TABLE not_public.person
    OWNER to not_public_user;
    GRANT ALL ON TABLE not_public.person TO hasurauser;
    GRANT ALL ON TABLE not_public.person TO not_public_user;
  4. Create a function that could be used for a scalar calculated field in a different schema such as...
    CREATE OR REPLACE FUNCTION public.person_chosen_or_first_name(person_row not_public.person)
    RETURNS text
    LANGUAGE sql
    STABLE
    AS $function$
    SELECT COALESCE(person_row.chosen_first_name, person_row.first_name)
    $function$
  5. Go to a table in a schema other than the one you created the function in and add it as a calculated field such as...
    # https://example.com/console/data/schema/not_public/tables/person/modify`
    Computed field name: chosen_or_first_name
    Function schema: public
    Function name: person_chosen_or_first_name
    Table row argument: # leave empty
    Comment: Returns the chosen first name of the person if it is not null. Otherwise, returns the person's legal first name.
  6. Verify that it works by running a query from GraphiQL as an administrator by running a query such as...
    query ExapleQuery {
    not_public_person(limit: 10) {
    chosen_or_first_name
    }
    }
  7. Verify the issue exists by adding a new role to the permissions table and trying to assign it permissions to select your new calculated field, for example...
    # https://example.com/console/data/schema/not_public/tables/person/permissions
    Role: examplerole
    Action: select
    Row select permissions: without any checks
    Column select permissions: chosen_or_first_name  # <-- This should be here but it is not.
rikinsk commented 4 years ago

This is an issue with the console.

Till this is fixed you can get around this by using the permissions metadata api or by exporting the metadata, adding the computed field in the permissions section of the table and then applying the metadata back.