refactor: move accessibleTables to SqlFragment
This commit is contained in:
committed by
Steve Chavez
parent
1ace298a1a
commit
9c07070263
+12
-2
@@ -205,8 +205,8 @@ actionQuery (MayUseDb plan@InspectPlan{ipSchema=tSchema}) AppConfig{..} _ sCache
|
|||||||
mainActionQuery = lift $
|
mainActionQuery = lift $
|
||||||
case configOpenApiMode of
|
case configOpenApiMode of
|
||||||
OAFollowPriv -> do
|
OAFollowPriv -> do
|
||||||
tableAccess <- SQL.statement [tSchema] (SchemaCache.accessibleTables configDbPreparedStatements)
|
tableAccess <- SQL.statement mempty $ SQL.dynamicallyParameterized (SqlFragment.accessibleTables tSchema) decodeAccessibleIdentifiers configDbPreparedStatements
|
||||||
schDesc <- SQL.statement mempty (SQL.dynamicallyParameterized (SqlFragment.schemaDescription tSchema) decodeSchemaDesc configDbPreparedStatements)
|
schDesc <- SQL.statement mempty $ SQL.dynamicallyParameterized (SqlFragment.schemaDescription tSchema) decodeSchemaDesc configDbPreparedStatements
|
||||||
|
|
||||||
MaybeDbResult plan . Just <$> ((,,)
|
MaybeDbResult plan . Just <$> ((,,)
|
||||||
(HM.filterWithKey (\qi _ -> S.member qi tableAccess) $ SchemaCache.dbTables sCache)
|
(HM.filterWithKey (\qi _ -> S.member qi tableAccess) $ SchemaCache.dbTables sCache)
|
||||||
@@ -214,6 +214,7 @@ actionQuery (MayUseDb plan@InspectPlan{ipSchema=tSchema}) AppConfig{..} _ sCache
|
|||||||
<*> pure schDesc)
|
<*> pure schDesc)
|
||||||
OAIgnorePriv -> do
|
OAIgnorePriv -> do
|
||||||
schDesc <- SQL.statement mempty (SQL.dynamicallyParameterized (SqlFragment.schemaDescription tSchema) decodeSchemaDesc configDbPreparedStatements)
|
schDesc <- SQL.statement mempty (SQL.dynamicallyParameterized (SqlFragment.schemaDescription tSchema) decodeSchemaDesc configDbPreparedStatements)
|
||||||
|
|
||||||
let tbls = HM.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch == tSchema) (SchemaCache.dbTables sCache)
|
let tbls = HM.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch == tSchema) (SchemaCache.dbTables sCache)
|
||||||
routs = HM.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch == tSchema) (SchemaCache.dbRoutines sCache)
|
routs = HM.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch == tSchema) (SchemaCache.dbRoutines sCache)
|
||||||
|
|
||||||
@@ -224,6 +225,15 @@ actionQuery (MayUseDb plan@InspectPlan{ipSchema=tSchema}) AppConfig{..} _ sCache
|
|||||||
decodeSchemaDesc :: HD.Result (Maybe Text)
|
decodeSchemaDesc :: HD.Result (Maybe Text)
|
||||||
decodeSchemaDesc = join <$> HD.rowMaybe (nullableColumn HD.text)
|
decodeSchemaDesc = join <$> HD.rowMaybe (nullableColumn HD.text)
|
||||||
|
|
||||||
|
decodeAccessibleIdentifiers :: HD.Result (S.Set QualifiedIdentifier)
|
||||||
|
decodeAccessibleIdentifiers =
|
||||||
|
let
|
||||||
|
row = QualifiedIdentifier
|
||||||
|
<$> column HD.text
|
||||||
|
<*> column HD.text
|
||||||
|
in
|
||||||
|
S.fromList <$> HD.rowList row
|
||||||
|
|
||||||
-- Makes sure the querystring pk matches the payload pk
|
-- Makes sure the querystring pk matches the payload pk
|
||||||
-- e.g. PUT /items?id=eq.1 { "id" : 1, .. } is accepted,
|
-- e.g. PUT /items?id=eq.1 { "id" : 1, .. } is accepted,
|
||||||
-- PUT /items?id=eq.14 { "id" : 2, .. } is rejected.
|
-- PUT /items?id=eq.14 { "id" : 2, .. } is rejected.
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ module PostgREST.Query.SqlFragment
|
|||||||
, escapeIdent
|
, escapeIdent
|
||||||
, escapeIdentList
|
, escapeIdentList
|
||||||
, schemaDescription
|
, schemaDescription
|
||||||
|
, accessibleTables
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import qualified Data.Aeson as JSON
|
import qualified Data.Aeson as JSON
|
||||||
@@ -597,3 +598,22 @@ schemaDescription schema =
|
|||||||
"SELECT pg_catalog.obj_description(" <> encoded <> "::regnamespace, 'pg_namespace')"
|
"SELECT pg_catalog.obj_description(" <> encoded <> "::regnamespace, 'pg_namespace')"
|
||||||
where
|
where
|
||||||
encoded = SQL.encoderAndParam (HE.nonNullable HE.unknown) $ encodeUtf8 schema
|
encoded = SQL.encoderAndParam (HE.nonNullable HE.unknown) $ encodeUtf8 schema
|
||||||
|
|
||||||
|
accessibleTables :: Text -> SQL.Snippet
|
||||||
|
accessibleTables schema = SQL.sql (encodeUtf8 [trimming|
|
||||||
|
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','f','p')
|
||||||
|
AND c.relnamespace = |]) <> encodedSchema <> "::regnamespace " <> SQL.sql (encodeUtf8 [trimming|
|
||||||
|
AND (
|
||||||
|
pg_has_role(c.relowner, 'USAGE')
|
||||||
|
or has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
|
||||||
|
or has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES')
|
||||||
|
)
|
||||||
|
AND not c.relispartition
|
||||||
|
ORDER BY table_schema, table_name|])
|
||||||
|
where
|
||||||
|
encodedSchema = SQL.encoderAndParam (HE.nonNullable HE.text) schema
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ These queries are executed once at startup or when PostgREST is reloaded.
|
|||||||
module PostgREST.SchemaCache
|
module PostgREST.SchemaCache
|
||||||
( SchemaCache(..)
|
( SchemaCache(..)
|
||||||
, querySchemaCache
|
, querySchemaCache
|
||||||
, accessibleTables
|
|
||||||
, accessibleFuncs
|
, accessibleFuncs
|
||||||
, showSummary
|
, showSummary
|
||||||
) where
|
) where
|
||||||
@@ -46,7 +45,7 @@ import PostgREST.Config (AppConfig (..))
|
|||||||
import PostgREST.Config.Database (TimezoneNames,
|
import PostgREST.Config.Database (TimezoneNames,
|
||||||
toIsolationLevel)
|
toIsolationLevel)
|
||||||
import PostgREST.Query.SqlFragment (escapeIdent)
|
import PostgREST.Query.SqlFragment (escapeIdent)
|
||||||
import PostgREST.SchemaCache.Identifiers (AccessSet, FieldName,
|
import PostgREST.SchemaCache.Identifiers (FieldName,
|
||||||
QualifiedIdentifier (..),
|
QualifiedIdentifier (..),
|
||||||
RelIdentifier (..),
|
RelIdentifier (..),
|
||||||
Schema, isAnyElement)
|
Schema, isAnyElement)
|
||||||
@@ -208,14 +207,6 @@ removeInternal schemas dbStruct =
|
|||||||
M2M Junction{junTable} -> qiSchema junTable `notElem` schemas
|
M2M Junction{junTable} -> qiSchema junTable `notElem` schemas
|
||||||
_ -> False
|
_ -> False
|
||||||
|
|
||||||
decodeAccessibleIdentifiers :: HD.Result AccessSet
|
|
||||||
decodeAccessibleIdentifiers =
|
|
||||||
S.fromList <$> HD.rowList row
|
|
||||||
where
|
|
||||||
row = QualifiedIdentifier
|
|
||||||
<$> column HD.text
|
|
||||||
<*> column HD.text
|
|
||||||
|
|
||||||
decodeTables :: HD.Result TablesMap
|
decodeTables :: HD.Result TablesMap
|
||||||
decodeTables =
|
decodeTables =
|
||||||
HM.fromList . map (\tbl@Table{tableSchema, tableName} -> (QualifiedIdentifier tableSchema tableName, tbl)) <$> HD.rowList tblRow
|
HM.fromList . map (\tbl@Table{tableSchema, tableName} -> (QualifiedIdentifier tableSchema tableName, tbl)) <$> HD.rowList tblRow
|
||||||
@@ -473,28 +464,6 @@ funcsSqlQuery = encodeUtf8 [trimming|
|
|||||||
WHERE t.oid <> 'trigger'::regtype AND COALESCE(a.callable, true)
|
WHERE t.oid <> 'trigger'::regtype AND COALESCE(a.callable, true)
|
||||||
AND prokind = 'f'
|
AND prokind = 'f'
|
||||||
AND p.pronamespace = ANY($$1::regnamespace[]) |]
|
AND p.pronamespace = ANY($$1::regnamespace[]) |]
|
||||||
|
|
||||||
accessibleTables :: Bool -> SQL.Statement [Schema] AccessSet
|
|
||||||
accessibleTables =
|
|
||||||
SQL.Statement sql params decodeAccessibleIdentifiers
|
|
||||||
where
|
|
||||||
params = map escapeIdent >$< arrayParam HE.text
|
|
||||||
sql = encodeUtf8 [trimming|
|
|
||||||
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','f','p')
|
|
||||||
AND c.relnamespace = ANY($$1::regnamespace[])
|
|
||||||
AND (
|
|
||||||
pg_has_role(c.relowner, 'USAGE')
|
|
||||||
or has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
|
|
||||||
or has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES')
|
|
||||||
)
|
|
||||||
AND not c.relispartition
|
|
||||||
ORDER BY table_schema, table_name|]
|
|
||||||
|
|
||||||
{-
|
{-
|
||||||
Adds M2O and O2O relationships for views to tables, tables to views, and views to views. The example below is taken from the test fixtures, but the views names/colnames were modified.
|
Adds M2O and O2O relationships for views to tables, tables to views, and views to views. The example below is taken from the test fixtures, but the views names/colnames were modified.
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,11 @@ module PostgREST.SchemaCache.Identifiers
|
|||||||
, Schema
|
, Schema
|
||||||
, TableName
|
, TableName
|
||||||
, FieldName
|
, FieldName
|
||||||
, AccessSet
|
|
||||||
, dumpQi
|
, dumpQi
|
||||||
, toQi
|
, toQi
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import qualified Data.Aeson as JSON
|
import qualified Data.Aeson as JSON
|
||||||
import qualified Data.Set as S
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
import Protolude
|
import Protolude
|
||||||
@@ -51,5 +49,3 @@ toQi txt = case T.drop 1 <$> T.breakOn "." txt of
|
|||||||
type Schema = Text
|
type Schema = Text
|
||||||
type TableName = Text
|
type TableName = Text
|
||||||
type FieldName = Text
|
type FieldName = Text
|
||||||
|
|
||||||
type AccessSet = S.Set QualifiedIdentifier
|
|
||||||
|
|||||||
Reference in New Issue
Block a user