diff --git a/src/PostgREST/App.hs b/src/PostgREST/App.hs index ad21b2456..46463bf3a 100644 --- a/src/PostgREST/App.hs +++ b/src/PostgREST/App.hs @@ -178,7 +178,7 @@ app dbStructure conf reqBody req = else return notFound (ActionRead, TargetRoot, Nothing) -> do - body <- encode <$> accessibleTables (filter ((== cs schema) . tableSchema) (dbTables dbStructure)) + body <- encode <$> accessibleTables (cs schema) return $ responseLBS status200 [jsonH] $ cs body (ActionUnknown _, _, _) -> return notFound diff --git a/src/PostgREST/DbStructure.hs b/src/PostgREST/DbStructure.hs index c1a8cb8d4..c5dd29bc8 100644 --- a/src/PostgREST/DbStructure.hs +++ b/src/PostgREST/DbStructure.hs @@ -71,25 +71,33 @@ doesProcReturnJWT = doesProc [H.stmt| AND pg_catalog.pg_get_function_result(p.oid) like '%jwt_claims' |] -accessibleTables :: [Table] -> H.Tx P.Postgres s [Table] -accessibleTables allTabs = do - accessible <- H.listEx $ [H.stmt| - SELECT - n.nspname AS table_schema, - c.relname AS table_name - 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 ('pg_catalog', 'information_schema') 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) +accessibleTables :: Schema -> H.Tx P.Postgres s [Table] +accessibleTables schema = 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 = ? + 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 table_schema, table_name - |] - let isAccessible table = isJust $ find (\(s,n) -> tableSchema table == s && tableName table == n) accessible - return $ filter isAccessible allTabs + order by relname + |] schema + return $ map tableFromRow rows synonymousColumns :: [(Column,Column)] -> [Column] -> [[Column]] synonymousColumns allSyns cols = synCols'