refactor: move isolation/settings logic to Plan.hs
This commit is contained in:
committed by
Steve Chavez
parent
c33ca4e60c
commit
06ff56d323
+4
-18
@@ -9,7 +9,6 @@ Some of its functionality includes:
|
|||||||
- Producing HTTP Headers according to RFCs.
|
- Producing HTTP Headers according to RFCs.
|
||||||
- Content Negotiation
|
- Content Negotiation
|
||||||
-}
|
-}
|
||||||
{-# LANGUAGE NamedFieldPuns #-}
|
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
module PostgREST.App
|
module PostgREST.App
|
||||||
( postgrest
|
( postgrest
|
||||||
@@ -24,7 +23,6 @@ import Data.String (IsString (..))
|
|||||||
import Network.Wai.Handler.Warp (defaultSettings, setHost, setPort,
|
import Network.Wai.Handler.Warp (defaultSettings, setHost, setPort,
|
||||||
setServerName)
|
setServerName)
|
||||||
|
|
||||||
import qualified Data.HashMap.Strict as HM
|
|
||||||
import qualified Data.Text.Encoding as T
|
import qualified Data.Text.Encoding as T
|
||||||
import qualified Hasql.Transaction.Sessions as SQL
|
import qualified Hasql.Transaction.Sessions as SQL
|
||||||
import qualified Network.Wai as Wai
|
import qualified Network.Wai as Wai
|
||||||
@@ -54,7 +52,6 @@ import PostgREST.Query (DbHandler)
|
|||||||
import PostgREST.Response.Performance (ServerTiming (..),
|
import PostgREST.Response.Performance (ServerTiming (..),
|
||||||
serverTimingHeader)
|
serverTimingHeader)
|
||||||
import PostgREST.SchemaCache (SchemaCache (..))
|
import PostgREST.SchemaCache (SchemaCache (..))
|
||||||
import PostgREST.SchemaCache.Routine (Routine (..))
|
|
||||||
import PostgREST.Version (docsVersion, prettyVersion)
|
import PostgREST.Version (docsVersion, prettyVersion)
|
||||||
|
|
||||||
import qualified Data.ByteString.Char8 as BS
|
import qualified Data.ByteString.Char8 as BS
|
||||||
@@ -172,7 +169,10 @@ handleRequest AuthResult{..} conf appState authenticated prepared pgVer apiReq@A
|
|||||||
case iAction of
|
case iAction of
|
||||||
ActDb dbAct -> do
|
ActDb dbAct -> do
|
||||||
(planTime', plan) <- withTiming $ liftEither $ Plan.actionPlan dbAct conf apiReq sCache
|
(planTime', plan) <- withTiming $ liftEither $ Plan.actionPlan dbAct conf apiReq sCache
|
||||||
(txTime', queryResult) <- withTiming $ runQuery (planIsoLvl plan) (planFunSettings plan) (Plan.actionPlanTxMode plan) $ Query.actionQuery plan conf apiReq pgVer sCache
|
(txTime', queryResult) <- withTiming $ runDbHandler appState conf (Plan.planIsoLvl conf authRole plan) (Plan.planTxMode plan) authenticated prepared observer $ do
|
||||||
|
Query.setPgLocals plan conf authClaims authRole apiReq
|
||||||
|
Query.runPreReq conf
|
||||||
|
Query.actionQuery plan conf apiReq pgVer sCache
|
||||||
(respTime', pgrst) <- withTiming $ liftEither $ Response.actionResponse queryResult (dbActQi dbAct) apiReq (T.decodeUtf8 prettyVersion, docsVersion) conf sCache iSchema iNegotiatedByProfile
|
(respTime', pgrst) <- withTiming $ liftEither $ Response.actionResponse queryResult (dbActQi dbAct) apiReq (T.decodeUtf8 prettyVersion, docsVersion) conf sCache iSchema iNegotiatedByProfile
|
||||||
return $ pgrstResponse (ServerTiming jwtTime parseTime planTime' txTime' respTime') pgrst
|
return $ pgrstResponse (ServerTiming jwtTime parseTime planTime' txTime' respTime') pgrst
|
||||||
|
|
||||||
@@ -190,20 +190,6 @@ handleRequest AuthResult{..} conf appState authenticated prepared pgVer apiReq@A
|
|||||||
return $ pgrstResponse (ServerTiming jwtTime parseTime Nothing Nothing respTime') pgrst
|
return $ pgrstResponse (ServerTiming jwtTime parseTime Nothing Nothing respTime') pgrst
|
||||||
|
|
||||||
where
|
where
|
||||||
roleSettings = fromMaybe mempty (HM.lookup authRole $ configRoleSettings conf)
|
|
||||||
roleIsoLvl = HM.findWithDefault SQL.ReadCommitted authRole $ configRoleIsoLvl conf
|
|
||||||
runQuery isoLvl funcSets mode query =
|
|
||||||
runDbHandler appState conf isoLvl mode authenticated prepared observer $ do
|
|
||||||
Query.setPgLocals conf authClaims authRole (HM.toList roleSettings) funcSets apiReq
|
|
||||||
Query.runPreReq conf
|
|
||||||
query
|
|
||||||
|
|
||||||
planIsoLvl (Plan.Db Plan.CallReadPlan{crProc}) = fromMaybe roleIsoLvl $ pdIsoLvl crProc
|
|
||||||
planIsoLvl _ = roleIsoLvl
|
|
||||||
|
|
||||||
planFunSettings (Plan.Db Plan.CallReadPlan{crProc}) = pdFuncSettings crProc
|
|
||||||
planFunSettings _ = mempty
|
|
||||||
|
|
||||||
pgrstResponse :: ServerTiming -> Response.PgrstResponse -> Wai.Response
|
pgrstResponse :: ServerTiming -> Response.PgrstResponse -> Wai.Response
|
||||||
pgrstResponse timing (Response.PgrstResponse st hdrs bod) = Wai.responseLBS st (hdrs ++ ([serverTimingHeader timing | configServerTimingEnabled conf])) bod
|
pgrstResponse timing (Response.PgrstResponse st hdrs bod) = Wai.responseLBS st (hdrs ++ ([serverTimingHeader timing | configServerTimingEnabled conf])) bod
|
||||||
|
|
||||||
|
|||||||
+12
-4
@@ -22,7 +22,8 @@ module PostgREST.Plan
|
|||||||
, InspectPlan(..)
|
, InspectPlan(..)
|
||||||
, inspectPlan
|
, inspectPlan
|
||||||
, callReadPlan
|
, callReadPlan
|
||||||
, actionPlanTxMode
|
, planTxMode
|
||||||
|
, planIsoLvl
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import qualified Data.ByteString.Lazy as LBS
|
import qualified Data.ByteString.Lazy as LBS
|
||||||
@@ -127,9 +128,16 @@ data InspectPlan = InspectPlan {
|
|||||||
|
|
||||||
data ActionPlan = Db DbActionPlan | MaybeDb InspectPlan
|
data ActionPlan = Db DbActionPlan | MaybeDb InspectPlan
|
||||||
|
|
||||||
actionPlanTxMode :: ActionPlan -> SQL.Mode
|
planTxMode :: ActionPlan -> SQL.Mode
|
||||||
actionPlanTxMode (Db x) = pTxMode x
|
planTxMode (Db x) = pTxMode x
|
||||||
actionPlanTxMode (MaybeDb x) = ipTxmode x
|
planTxMode (MaybeDb x) = ipTxmode x
|
||||||
|
|
||||||
|
planIsoLvl :: AppConfig -> ByteString -> ActionPlan -> SQL.IsolationLevel
|
||||||
|
planIsoLvl AppConfig{configRoleIsoLvl} role actPlan = case actPlan of
|
||||||
|
Db CallReadPlan{crProc} -> fromMaybe roleIsoLvl $ pdIsoLvl crProc
|
||||||
|
_ -> roleIsoLvl
|
||||||
|
where
|
||||||
|
roleIsoLvl = HM.findWithDefault SQL.ReadCommitted role configRoleIsoLvl
|
||||||
|
|
||||||
actionPlan :: DbAction -> AppConfig -> ApiRequest -> SchemaCache -> Either Error ActionPlan
|
actionPlan :: DbAction -> AppConfig -> ApiRequest -> SchemaCache -> Either Error ActionPlan
|
||||||
actionPlan dbAct conf apiReq sCache = case dbAct of
|
actionPlan dbAct conf apiReq sCache = case dbAct of
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ import PostgREST.Query.SqlFragment (escapeIdentList, fromQi,
|
|||||||
import PostgREST.Query.Statements (ResultSet (..))
|
import PostgREST.Query.Statements (ResultSet (..))
|
||||||
import PostgREST.SchemaCache (SchemaCache (..))
|
import PostgREST.SchemaCache (SchemaCache (..))
|
||||||
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..))
|
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..))
|
||||||
import PostgREST.SchemaCache.Routine (MediaHandler, RoutineMap)
|
import PostgREST.SchemaCache.Routine (MediaHandler, Routine (..),
|
||||||
|
RoutineMap)
|
||||||
import PostgREST.SchemaCache.Table (TablesMap)
|
import PostgREST.SchemaCache.Table (TablesMap)
|
||||||
|
|
||||||
import Protolude hiding (Handler)
|
import Protolude hiding (Handler)
|
||||||
@@ -238,9 +239,8 @@ optionalRollback AppConfig{..} ApiRequest{iPreferences=Preferences{..}} = do
|
|||||||
preferTransaction == Just Rollback
|
preferTransaction == Just Rollback
|
||||||
|
|
||||||
-- | Set transaction scoped settings
|
-- | Set transaction scoped settings
|
||||||
setPgLocals :: AppConfig -> KM.KeyMap JSON.Value -> BS.ByteString -> [(ByteString, ByteString)] ->
|
setPgLocals :: ActionPlan -> AppConfig -> KM.KeyMap JSON.Value -> BS.ByteString -> ApiRequest -> DbHandler ()
|
||||||
[(Text,Text)] -> ApiRequest -> DbHandler ()
|
setPgLocals actPlan AppConfig{..} claims role ApiRequest{..} = lift $
|
||||||
setPgLocals AppConfig{..} claims role roleSettings funcSettings ApiRequest{..} = lift $
|
|
||||||
SQL.statement mempty $ SQL.dynamicallyParameterized
|
SQL.statement mempty $ SQL.dynamicallyParameterized
|
||||||
-- To ensure `GRANT SET ON PARAMETER <superuser_setting> TO authenticator` works, the role settings must be set before the impersonated role.
|
-- To ensure `GRANT SET ON PARAMETER <superuser_setting> TO authenticator` works, the role settings must be set before the impersonated role.
|
||||||
-- Otherwise the GRANT SET would have to be applied to the impersonated role. See https://github.com/PostgREST/postgrest/issues/3045
|
-- Otherwise the GRANT SET would have to be applied to the impersonated role. See https://github.com/PostgREST/postgrest/issues/3045
|
||||||
@@ -253,13 +253,16 @@ setPgLocals AppConfig{..} claims role roleSettings funcSettings ApiRequest{..} =
|
|||||||
cookiesSql = setConfigWithConstantNameJSON "request.cookies" iCookies
|
cookiesSql = setConfigWithConstantNameJSON "request.cookies" iCookies
|
||||||
claimsSql = [setConfigWithConstantName ("request.jwt.claims", LBS.toStrict $ JSON.encode claims)]
|
claimsSql = [setConfigWithConstantName ("request.jwt.claims", LBS.toStrict $ JSON.encode claims)]
|
||||||
roleSql = [setConfigWithConstantName ("role", role)]
|
roleSql = [setConfigWithConstantName ("role", role)]
|
||||||
roleSettingsSql = setConfigWithDynamicName <$> roleSettings
|
roleSettingsSql = setConfigWithDynamicName <$> HM.toList (fromMaybe mempty $ HM.lookup role configRoleSettings)
|
||||||
appSettingsSql = setConfigWithDynamicName <$> (join bimap toUtf8 <$> configAppSettings)
|
appSettingsSql = setConfigWithDynamicName <$> (join bimap toUtf8 <$> configAppSettings)
|
||||||
timezoneSql = maybe mempty (\(PreferTimezone tz) -> [setConfigWithConstantName ("timezone", tz)]) $ preferTimezone iPreferences
|
timezoneSql = maybe mempty (\(PreferTimezone tz) -> [setConfigWithConstantName ("timezone", tz)]) $ preferTimezone iPreferences
|
||||||
funcSettingsSql = setConfigWithDynamicName <$> (join bimap toUtf8 <$> funcSettings)
|
funcSettingsSql = setConfigWithDynamicName <$> (join bimap toUtf8 <$> funcSettings)
|
||||||
searchPathSql =
|
searchPathSql =
|
||||||
let schemas = escapeIdentList (iSchema : configDbExtraSearchPath) in
|
let schemas = escapeIdentList (iSchema : configDbExtraSearchPath) in
|
||||||
setConfigWithConstantName ("search_path", schemas)
|
setConfigWithConstantName ("search_path", schemas)
|
||||||
|
funcSettings = case actPlan of
|
||||||
|
Db CallReadPlan{crProc} -> pdFuncSettings crProc
|
||||||
|
_ -> mempty
|
||||||
|
|
||||||
-- | Runs the pre-request function.
|
-- | Runs the pre-request function.
|
||||||
runPreReq :: AppConfig -> DbHandler ()
|
runPreReq :: AppConfig -> DbHandler ()
|
||||||
|
|||||||
Reference in New Issue
Block a user