diff --git a/server/src-lib/Hasura/RQL/GBoolExp.hs b/server/src-lib/Hasura/RQL/GBoolExp.hs index 8ec26253..ef8131c7 100644 --- a/server/src-lib/Hasura/RQL/GBoolExp.hs +++ b/server/src-lib/Hasura/RQL/GBoolExp.hs @@ -387,9 +387,11 @@ mkColCompExp qual lhsCol = \case getColExpDeps :: QualifiedTable -> AnnBoolExpFld a -> [SchemaDependency] getColExpDeps tn = \case - AVCol colInfo _ -> + AVCol colInfo opExps -> let cn = pgiName colInfo - in [SchemaDependency (SOTableObj tn (TOCol cn)) "on_type"] + depColsInOpExp = mapMaybe opExpDepCol opExps + allDepCols = cn:depColsInOpExp + in map (mkColDep "on_type" tn) allDepCols AVRel relInfo relBoolExp -> let rn = riName relInfo relTN = riRTable relInfo diff --git a/server/src-lib/Hasura/RQL/Types/BoolExp.hs b/server/src-lib/Hasura/RQL/Types/BoolExp.hs index defb8417..d9ab43b3 100644 --- a/server/src-lib/Hasura/RQL/Types/BoolExp.hs +++ b/server/src-lib/Hasura/RQL/Types/BoolExp.hs @@ -7,6 +7,7 @@ module Hasura.RQL.Types.BoolExp , DWithinGeomOp(..) , DWithinGeogOp(..) , OpExpG(..) + , opExpDepCol , AnnBoolExpFld(..) , AnnBoolExp @@ -29,17 +30,17 @@ module Hasura.RQL.Types.BoolExp import Hasura.Prelude import Hasura.RQL.Types.Common import Hasura.RQL.Types.Permission -import qualified Hasura.SQL.DML as S +import qualified Hasura.SQL.DML as S import Hasura.SQL.Types import Data.Aeson import Data.Aeson.Casing import Data.Aeson.Internal import Data.Aeson.TH -import qualified Data.Aeson.Types as J -import qualified Data.HashMap.Strict as M -import Instances.TH.Lift () -import Language.Haskell.TH.Syntax (Lift) +import qualified Data.Aeson.Types as J +import qualified Data.HashMap.Strict as M +import Instances.TH.Lift () +import Language.Haskell.TH.Syntax (Lift) data GBoolExp a = BoolAnd ![GBoolExp a] @@ -166,6 +167,15 @@ data OpExpG a | CLTE !PGCol deriving (Eq, Show, Functor, Foldable, Traversable) +opExpDepCol :: OpExpG a -> Maybe PGCol +opExpDepCol = \case + CEQ c -> Just c + CNE c -> Just c + CGT c -> Just c + CLT c -> Just c + CGTE c -> Just c + CLTE c -> Just c + _ -> Nothing opExpToJPair :: (a -> Value) -> OpExpG a -> (Text, Value) opExpToJPair f = \case diff --git a/server/tests-py/queries/graphql_query/permissions/setup.yaml b/server/tests-py/queries/graphql_query/permissions/setup.yaml index 06408f46..a7642575 100644 --- a/server/tests-py/queries/graphql_query/permissions/setup.yaml +++ b/server/tests-py/queries/graphql_query/permissions/setup.yaml @@ -6,7 +6,7 @@ args: args: sql: | create table author( - id serial primary key, + id serial primary key, name text unique, is_registered boolean not null default false, remarks_internal text @@ -98,7 +98,7 @@ args: permission: columns: - id - - name + - name - is_registered filter: _or: @@ -116,7 +116,7 @@ args: permission: columns: - id - - name + - name filter: articles: is_published: @@ -151,7 +151,7 @@ args: - title: Article 1 content: Sample article content 1 author_id: 1 - is_published: false + is_published: false - title: Article 2 content: Sample article content 2 @@ -367,7 +367,7 @@ args: filter: jsonb_col: $has_key: age - + - type: create_select_permission args: table: jsonb_table @@ -428,3 +428,33 @@ args: - id - student_name filter: {} + +#Auction table +- type: run_sql + args: + sql: | + CREATE TABLE auction ( + id serial primary key, + price integer not null DEFAULT 250, + bid_price integer + ); + INSERT INTO auction + (bid_price) + VALUES + (100), (120), (300), (260) + ; +- type: track_table + args: + name: auction + schema: public +- type: create_select_permission + args: + role: user + table: auction + permission: + filter: + bid_price: + $cgt: price + columns: + - id + - bid_price diff --git a/server/tests-py/queries/graphql_query/permissions/teardown.yaml b/server/tests-py/queries/graphql_query/permissions/teardown.yaml index aada095f..3ae9e98b 100644 --- a/server/tests-py/queries/graphql_query/permissions/teardown.yaml +++ b/server/tests-py/queries/graphql_query/permissions/teardown.yaml @@ -10,4 +10,5 @@ args: DROP TABLE geom_table; DROP TABLE jsonb_table; DROP TABLE gpa cascade; + DROP TABLE auction; cascade: true diff --git a/server/tests-py/queries/graphql_query/permissions/user_query_auction.yaml b/server/tests-py/queries/graphql_query/permissions/user_query_auction.yaml new file mode 100644 index 00000000..51c818e9 --- /dev/null +++ b/server/tests-py/queries/graphql_query/permissions/user_query_auction.yaml @@ -0,0 +1,21 @@ +description: Query bid prices more than actual price +url: /v1alpha1/graphql +status: 200 +headers: + X-Hasura-Role: user +response: + data: + auction: + - id: 4 + bid_price: 260 +query: + query: | + query { + auction( + order_by: {bid_price: asc} + limit: 1 + ) { + id + bid_price + } + } diff --git a/server/tests-py/queries/v1/select/permissions/setup.yaml b/server/tests-py/queries/v1/select/permissions/setup.yaml index c5739aca..8616d618 100644 --- a/server/tests-py/queries/v1/select/permissions/setup.yaml +++ b/server/tests-py/queries/v1/select/permissions/setup.yaml @@ -6,7 +6,7 @@ args: args: sql: | create table author( - id serial primary key, + id serial primary key, name text unique, is_registered boolean not null default false, remarks_internal text @@ -98,7 +98,7 @@ args: permission: columns: - id - - name + - name - is_registered filter: _or: @@ -116,7 +116,7 @@ args: permission: columns: - id - - name + - name filter: articles: is_published: @@ -151,7 +151,7 @@ args: - title: Article 1 content: Sample article content 1 author_id: 1 - is_published: false + is_published: false - title: Article 2 content: Sample article content 2 @@ -338,7 +338,7 @@ args: filter: jsonb_col: $has_key: age - + - type: create_select_permission args: table: jsonb_table @@ -361,3 +361,33 @@ args: age: 7 - jsonb_col: name: Cross + +#Auction table +- type: run_sql + args: + sql: | + CREATE TABLE auction ( + id serial primary key, + price integer not null DEFAULT 250, + bid_price integer + ); + INSERT INTO auction + (bid_price) + VALUES + (100), (120), (300), (260) + ; +- type: track_table + args: + name: auction + schema: public +- type: create_select_permission + args: + role: user + table: auction + permission: + filter: + bid_price: + $cgt: price + columns: + - id + - bid_price diff --git a/server/tests-py/queries/v1/select/permissions/teardown.yaml b/server/tests-py/queries/v1/select/permissions/teardown.yaml index 06dfc080..2c1f6ace 100644 --- a/server/tests-py/queries/v1/select/permissions/teardown.yaml +++ b/server/tests-py/queries/v1/select/permissions/teardown.yaml @@ -8,4 +8,5 @@ args: DROP TABLE geom_table; DROP TABLE geog_table; DROP TABLE jsonb_table; + DROP TABLE auction; cascade: true diff --git a/server/tests-py/queries/v1/select/permissions/user_query_auction.yaml b/server/tests-py/queries/v1/select/permissions/user_query_auction.yaml new file mode 100644 index 00000000..9abb6806 --- /dev/null +++ b/server/tests-py/queries/v1/select/permissions/user_query_auction.yaml @@ -0,0 +1,18 @@ +description: Query bid prices more than action price +url: /v1/query +status: 200 +headers: + X-Hasura-Role: user +response: +- id: 4 + bid_price: 260 +query: + type: select + args: + table: auction + columns: + - id + - bid_price + order_by: + - bid_price + limit: 1 diff --git a/server/tests-py/test_graphql_queries.py b/server/tests-py/test_graphql_queries.py index fda52312..816daa28 100644 --- a/server/tests-py/test_graphql_queries.py +++ b/server/tests-py/test_graphql_queries.py @@ -240,6 +240,9 @@ class TestGraphqlQueryPermissions(DefaultTestSelectQueries): def test_staff_passed_students(self, hge_ctx, transport): check_query_f(hge_ctx, self.dir() + '/staff_passed_students.yaml', transport) + def test_user_query_auction(self, hge_ctx, transport): + check_query_f(hge_ctx, self.dir() + '/user_query_auction.yaml', transport) + @classmethod def dir(cls): return 'queries/graphql_query/permissions' diff --git a/server/tests-py/test_v1_queries.py b/server/tests-py/test_v1_queries.py index 85ee2659..75f153dd 100644 --- a/server/tests-py/test_v1_queries.py +++ b/server/tests-py/test_v1_queries.py @@ -248,6 +248,9 @@ class TestV1SelectPermissions(DefaultTestSelectQueries): def test_user_can_query_jsonb_values_filter_session_vars(self, hge_ctx): check_query_f(hge_ctx, self.dir() + '/user_can_query_jsonb_values_filter_session_vars.yaml') + def test_user_query_auction(self, hge_ctx): + check_query_f(hge_ctx, self.dir() + '/user_query_auction.yaml') + @classmethod def dir(cls): return 'queries/v1/select/permissions'