From c0e17c44ba3c4b496b5aa253c46957ce550cddf5 Mon Sep 17 00:00:00 2001 From: Ruslan Talpa Date: Wed, 23 Sep 2015 09:38:40 +0300 Subject: [PATCH] all tests passing after moving table structure detection at load time --- src/PostgREST/App.hs | 8 ++-- src/PostgREST/Main.hs | 15 +++---- src/PostgREST/PgStructure.hs | 76 ++++++++++++++++++++---------------- src/PostgREST/Types.hs | 3 +- test/SpecHelper.hs | 15 +++---- 5 files changed, 64 insertions(+), 53 deletions(-) diff --git a/src/PostgREST/App.hs b/src/PostgREST/App.hs index 4785f17b5..748db75ba 100644 --- a/src/PostgREST/App.hs +++ b/src/PostgREST/App.hs @@ -65,7 +65,7 @@ app dbstructure conf reqBody role req = -- $ encode (TableOptions cols pkey) ([], _) -> do - let body = encode $ filter (filterTableAcl allTablesAcl role) $ filter (((cs schema)==).tableSchema) allTables + let body = encode $ filter (filterTableAcl role) $ filter (((cs schema)==).tableSchema) allTables return $ responseLBS status200 [jsonH, ("Custom", "header")] $ cs body ([table], "OPTIONS") -> do @@ -261,12 +261,12 @@ app dbstructure conf reqBody role req = allRelations = relations dbstructure allColumns = columns dbstructure allPrimaryKeys = primaryKeys dbstructure - allTablesAcl = tablesAcl dbstructure + --allTablesAcl = tablesAcl dbstructure filterCol schema table (Column{colSchema=s, colTable=t}) = s==schema && table==t filterPk schema table (PrimaryKey{pkSchema=s, pkTable=t}) = s==schema && table==t - filterTableAcl :: [(Text, Text, Text)] -> Text -> Table -> Bool - filterTableAcl acl r (Table{tableSchema=s, tableName=n}) = isJust $ find (\(as,an,ar)->as==s && an==n && ar==r) acl + filterTableAcl :: Text -> Table -> Bool + filterTableAcl r (Table{tableAcl=a}) = r `elem` a path = pathInfo req verb = requestMethod req qq = queryString req diff --git a/src/PostgREST/Main.hs b/src/PostgREST/Main.hs index 86b6a5252..1921d3dc9 100644 --- a/src/PostgREST/Main.hs +++ b/src/PostgREST/Main.hs @@ -99,16 +99,17 @@ main = do pkRes <- H.session pool $ H.tx txParam $ allprimaryKeys let allPrimaryKeys = either (fail . show) id pkRes - tableAclRes <- H.session pool $ H.tx txParam $ alltablesAcl - let allTablesAcl = either (fail . show) id tableAclRes + -- tableAclRes <- H.session pool $ H.tx txParam $ alltablesAcl + -- let allTablesAcl = either (fail . show) id tableAclRes let dbstructure = DbStructure { - tables=allTables, - columns=allColumns, - relations=allRelations, - primaryKeys=allPrimaryKeys, - tablesAcl=allTablesAcl} + tables=allTables + , columns=allColumns + , relations=allRelations + , primaryKeys=allPrimaryKeys + --, tablesAcl=allTablesAcl + } runSettings appSettings $ middle $ \ req respond -> do body <- strictRequestBody req diff --git a/src/PostgREST/PgStructure.hs b/src/PostgREST/PgStructure.hs index d98c7d429..1422ccf3c 100644 --- a/src/PostgREST/PgStructure.hs +++ b/src/PostgREST/PgStructure.hs @@ -138,8 +138,11 @@ doesProcExist schema proc = do return $ isJust row -tableFromRow :: (Text, Text, Bool) -> Table -tableFromRow (s, n, i) = Table s n i +tableFromRow :: (Text, Text, Bool, Maybe Text) -> Table +tableFromRow (s, n, i, a) = Table s n i (parseAcl a) + where + parseAcl :: Maybe Text -> [Text] + parseAcl str = fromMaybe [] $ split (==',') <$> str columnFromRow :: (Text, Text, Text, Int, Bool, Text, @@ -192,25 +195,30 @@ addFlippedRelation rel@(Relation s t c ft fc _) rels = Relation s ft fc t c "par alltables :: H.Tx P.Postgres s [Table] alltables = do rows <- H.listEx $ [H.stmt| - SELECT n.nspname AS table_schema, - relname AS TABLE_NAME, - c.relkind = 'r' OR (c.relkind IN ('v','f')) - AND (pg_relation_is_updatable(c.oid::regclass, FALSE) & 8) = 8 - OR (EXISTS ( SELECT 1 - FROM pg_trigger - WHERE pg_trigger.tgrelid = c.oid - AND (pg_trigger.tgtype::integer & 69) = 69) - ) AS insertable - FROM pg_class c - JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relkind IN ('v','r','m') - AND n.nspname NOT IN ('information_schema','pg_catalog') - AND ( pg_has_role(c.relowner, 'USAGE'::text) - OR has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER'::text) - OR has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES'::text) - ) - ORDER BY relname - |] + SELECT + n.nspname AS table_schema, + c.relname AS table_name, + c.relkind = 'r' OR (c.relkind IN ('v','f')) + AND (pg_relation_is_updatable(c.oid::regclass, FALSE) & 8) = 8 + OR (EXISTS + ( SELECT 1 + FROM pg_trigger + WHERE pg_trigger.tgrelid = c.oid + AND (pg_trigger.tgtype::integer & 69) = 69) ) AS insertable, + array_to_string(array_agg(r.rolname), ',') AS acl + FROM pg_class c + CROSS JOIN pg_roles r + JOIN pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind IN ('v','r','m') + AND n.nspname NOT IN ('pg_catalog', 'information_schema') + AND ( + pg_has_role(r.rolname, c.relowner, 'USAGE'::text) OR + has_table_privilege(r.rolname, c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER'::text) OR + has_any_column_privilege(r.rolname, c.oid, 'SELECT, INSERT, UPDATE, REFERENCES'::text) ) + + GROUP BY table_schema, table_name, insertable + ORDER BY table_schema, table_name + |] return $ map tableFromRow rows allrelations :: H.Tx P.Postgres s [Relation] @@ -312,16 +320,16 @@ allprimaryKeys = do |] return $ map pkFromRow pks -alltablesAcl :: H.Tx P.Postgres s [(Text, Text, Text)] -alltablesAcl = do - acl <- H.listEx $ [H.stmt| - SELECT - table_schema, - table_name, - grantee as role - FROM information_schema.role_table_grants - WHERE - table_schema NOT IN ('pg_catalog', 'information_schema') AND - privilege_type = 'SELECT' - |] - return acl +-- alltablesAcl :: H.Tx P.Postgres s [(Text, Text, Text)] +-- alltablesAcl = do +-- acl <- H.listEx $ [H.stmt| +-- SELECT +-- table_schema, +-- table_name, +-- grantee as role +-- FROM information_schema.role_table_grants +-- WHERE +-- table_schema NOT IN ('pg_catalog', 'information_schema') AND +-- privilege_type = 'SELECT' +-- |] +-- return acl diff --git a/src/PostgREST/Types.hs b/src/PostgREST/Types.hs index 0c218b394..d9cf4e55d 100644 --- a/src/PostgREST/Types.hs +++ b/src/PostgREST/Types.hs @@ -6,13 +6,14 @@ data DbStructure = DbStructure { , columns :: [Column] , relations :: [Relation] , primaryKeys :: [PrimaryKey] -, tablesAcl :: [(Text, Text, Text)] +--, tablesAcl :: [(Text, Text, Text)] } data Table = Table { tableSchema :: Text , tableName :: Text , tableInsertable :: Bool +, tableAcl :: [Text] } deriving (Show) data ForeignKey = ForeignKey { diff --git a/test/SpecHelper.hs b/test/SpecHelper.hs index f1281c602..cd17e41e6 100644 --- a/test/SpecHelper.hs +++ b/test/SpecHelper.hs @@ -69,16 +69,17 @@ withApp perform = do pkRes <- H.session pool $ H.tx txParam $ allprimaryKeys let allPrimaryKeys = either (fail . show) id pkRes - tableAclRes <- H.session pool $ H.tx txParam $ alltablesAcl - let allTablesAcl = either (fail . show) id tableAclRes + -- tableAclRes <- H.session pool $ H.tx txParam $ alltablesAcl + -- let allTablesAcl = either (fail . show) id tableAclRes let dbstructure = DbStructure { - tables=allTables, - columns=allColumns, - relations=allRelations, - primaryKeys=allPrimaryKeys, - tablesAcl=allTablesAcl} + tables=allTables + , columns=allColumns + , relations=allRelations + , primaryKeys=allPrimaryKeys + --, tablesAcl=allTablesAcl + } perform $ middle $ \req resp -> do