feat: renamed config options with prefixes; added aliases for old names
* secret-is-base64 -> jwt-secret-is-base64 * role-claim-key -> jwt-role-claim-key * max-rows -> db-max-rows * pre-request -> db-pre-request * root-spec -> db-root-spec * db-schema -> db-schemas This is not a breaking change, because aliases are added as well. refactor: sorted all config keys alphabetically where applicable
This commit is contained in:
committed by
Wolfgang Walther
parent
ab3375998d
commit
ed58511de3
+8
-8
@@ -28,7 +28,7 @@ import System.IO (BufferMode (..), hSetBuffering)
|
||||
|
||||
import PostgREST.App (postgrest)
|
||||
import PostgREST.Config (AppConfig (..), CLI (..), Command (..),
|
||||
configPoolTimeout', dumpAppConfig,
|
||||
configDbPoolTimeout', dumpAppConfig,
|
||||
prettyVersion, readCLIShowHelp,
|
||||
readValidateConfig)
|
||||
import PostgREST.DbStructure (getDbStructure, getPgVersion)
|
||||
@@ -68,11 +68,11 @@ main = do
|
||||
|
||||
-- These are config values that can't be reloaded at runtime. Reloading some of them would imply restarting the web server.
|
||||
let
|
||||
host = configHost conf
|
||||
port = configPort conf
|
||||
maybeSocketAddr = configSocket conf
|
||||
host = configServerHost conf
|
||||
port = configServerPort conf
|
||||
maybeSocketAddr = configServerUnixSocket conf
|
||||
#ifndef mingw32_HOST_OS
|
||||
socketFileMode = configSocketMode conf
|
||||
socketFileMode = configServerUnixSocketMode conf
|
||||
#endif
|
||||
dbUri = toS (configDbUri conf)
|
||||
(dbChannelEnabled, dbChannel) = (configDbChannelEnabled conf, toS $ configDbChannel conf)
|
||||
@@ -81,8 +81,8 @@ main = do
|
||||
. setPort port
|
||||
. setServerName (toS $ "postgrest/" <> prettyVersion) $
|
||||
defaultSettings
|
||||
poolSize = configPoolSize conf
|
||||
poolTimeout = configPoolTimeout' conf
|
||||
poolSize = configDbPoolSize conf
|
||||
poolTimeout = configDbPoolTimeout' conf
|
||||
logLevel = configLogLevel conf
|
||||
|
||||
-- create connection pool with the provided settings, returns either a 'Connection' or a 'ConnectionError'. Does not throw.
|
||||
@@ -248,7 +248,7 @@ connectionStatus pool =
|
||||
fillSchemaCache :: P.Pool -> PgVersion -> IORef AppConfig -> IORef (Maybe DbStructure) -> IO ()
|
||||
fillSchemaCache pool actualPgVersion refConf refDbStructure = do
|
||||
conf <- readIORef refConf
|
||||
result <- P.use pool $ HT.transaction HT.ReadCommitted HT.Read $ getDbStructure (toList $ configSchemas conf) (configExtraSearchPath conf) actualPgVersion (configDbPrepared conf)
|
||||
result <- P.use pool $ HT.transaction HT.ReadCommitted HT.Read $ getDbStructure (toList $ configDbSchemas conf) (configDbExtraSearchPath conf) actualPgVersion (configDbPreparedStatements conf)
|
||||
case result of
|
||||
Left e -> do
|
||||
-- If this error happens it would mean the connection is down again. Improbable because connectionStatus ensured the connection.
|
||||
|
||||
+10
-10
@@ -75,25 +75,25 @@ postgrest logLev refConf refDbStructure pool getTime connWorker =
|
||||
Nothing -> respond . errorResponseFor $ ConnectionLostError
|
||||
Just dbStructure -> do
|
||||
response <- do
|
||||
let apiReq = userApiRequest (configSchemas conf) (configRootSpec conf) dbStructure req body
|
||||
let apiReq = userApiRequest (configDbSchemas conf) (configDbRootSpec conf) dbStructure req body
|
||||
case apiReq of
|
||||
Left err -> return . errorResponseFor $ err
|
||||
Right apiRequest -> do
|
||||
-- The jwt must be checked before touching the db.
|
||||
attempt <- attemptJwtClaims (configJWKS conf) (configJwtAudience conf) (toS $ iJWT apiRequest) time (rightToMaybe $ configRoleClaimKey conf)
|
||||
attempt <- attemptJwtClaims (configJWKS conf) (configJwtAudience conf) (toS $ iJWT apiRequest) time (rightToMaybe $ configJwtRoleClaimKey conf)
|
||||
case jwtClaims attempt of
|
||||
Left errJwt -> return . errorResponseFor $ errJwt
|
||||
Right claims -> do
|
||||
let
|
||||
authed = containsRole claims
|
||||
shouldCommit = configTxAllowOverride conf && iPreferTransaction apiRequest == Just Commit
|
||||
shouldRollback = configTxAllowOverride conf && iPreferTransaction apiRequest == Just Rollback
|
||||
shouldCommit = configDbTxAllowOverride conf && iPreferTransaction apiRequest == Just Commit
|
||||
shouldRollback = configDbTxAllowOverride conf && iPreferTransaction apiRequest == Just Rollback
|
||||
preferenceApplied
|
||||
| shouldCommit = addHeadersIfNotIncluded [(hPreferenceApplied, BS.pack (show Commit))]
|
||||
| shouldRollback = addHeadersIfNotIncluded [(hPreferenceApplied, BS.pack (show Rollback))]
|
||||
| otherwise = identity
|
||||
handleReq = do
|
||||
when (shouldRollback || (configTxRollbackAll conf && not shouldCommit)) HT.condemn
|
||||
when (shouldRollback || (configDbTxRollbackAll conf && not shouldCommit)) HT.condemn
|
||||
mapResponseHeaders preferenceApplied <$> runPgLocals conf claims (app dbStructure conf) apiRequest
|
||||
dbResp <- P.use pool $ HT.transaction HT.ReadCommitted (txMode apiRequest) handleReq
|
||||
return $ either (errorResponseFor . PgError authed) identity dbResp
|
||||
@@ -320,9 +320,9 @@ app dbStructure conf apiRequest =
|
||||
return $ responseLBS status headers rBody
|
||||
|
||||
(ActionInspect headersOnly, TargetDefaultSpec tSchema) -> do
|
||||
let host = configHost conf
|
||||
port = toInteger $ configPort conf
|
||||
proxy = pickProxy $ toS <$> configOpenAPIProxyUri conf
|
||||
let host = configServerHost conf
|
||||
port = toInteger $ configServerPort conf
|
||||
proxy = pickProxy $ toS <$> configOpenApiServerProxyUri conf
|
||||
uri Nothing = ("http", host, port, "/")
|
||||
uri (Just Proxy { proxyScheme = s, proxyHost = h, proxyPort = p, proxyPath = b }) = (s, h, p, b)
|
||||
uri' = uri proxy
|
||||
@@ -340,8 +340,8 @@ app dbStructure conf apiRequest =
|
||||
|
||||
where
|
||||
notFound = responseLBS status404 [] ""
|
||||
maxRows = configMaxRows conf
|
||||
prepared = configDbPrepared conf
|
||||
maxRows = configDbMaxRows conf
|
||||
prepared = configDbPreparedStatements conf
|
||||
exactCount = iPreferCount apiRequest == Just ExactCount
|
||||
estimatedCount = iPreferCount apiRequest == Just EstimatedCount
|
||||
plannedCount = iPreferCount apiRequest == Just PlannedCount
|
||||
|
||||
+111
-99
@@ -22,7 +22,7 @@ module PostgREST.Config ( prettyVersion
|
||||
, CLI (..)
|
||||
, Command (..)
|
||||
, AppConfig (..)
|
||||
, configPoolTimeout'
|
||||
, configDbPoolTimeout'
|
||||
, dumpAppConfig
|
||||
, readCLIShowHelp
|
||||
, readValidateConfig
|
||||
@@ -78,46 +78,39 @@ data Command = CmdRun | CmdDumpConfig deriving (Eq)
|
||||
|
||||
-- | Config file settings for the server
|
||||
data AppConfig = AppConfig {
|
||||
configDbUri :: Text
|
||||
, configAnonRole :: Text
|
||||
, configOpenAPIProxyUri :: Maybe Text
|
||||
, configSchemas :: NonEmpty Text
|
||||
, configHost :: Text
|
||||
, configPort :: Int
|
||||
, configSocket :: Maybe FilePath
|
||||
, configSocketMode :: Either Text FileMode
|
||||
, configDbChannel :: Text
|
||||
, configDbChannelEnabled :: Bool
|
||||
|
||||
, configJwtSecret :: Maybe B.ByteString
|
||||
, configJwtSecretIsBase64 :: Bool
|
||||
, configJwtAudience :: Maybe StringOrURI
|
||||
|
||||
, configPoolSize :: Int
|
||||
, configPoolTimeout :: Int
|
||||
, configMaxRows :: Maybe Integer
|
||||
, configPreReq :: Maybe Text
|
||||
, configSettings :: [(Text, Text)]
|
||||
, configRoleClaimKey :: Either Text JSPath
|
||||
, configExtraSearchPath :: [Text]
|
||||
|
||||
, configRootSpec :: Maybe Text
|
||||
, configRawMediaTypes :: [B.ByteString]
|
||||
|
||||
, configJWKS :: Maybe JWKSet
|
||||
|
||||
, configLogLevel :: LogLevel
|
||||
|
||||
, configTxRollbackAll :: Bool
|
||||
, configTxAllowOverride :: Bool
|
||||
|
||||
, configDbPrepared :: Bool
|
||||
configAppSettings :: [(Text, Text)]
|
||||
, configDbAnonRole :: Text
|
||||
, configDbChannel :: Text
|
||||
, configDbChannelEnabled :: Bool
|
||||
, configDbExtraSearchPath :: [Text]
|
||||
, configDbMaxRows :: Maybe Integer
|
||||
, configDbPoolSize :: Int
|
||||
, configDbPoolTimeout :: Int
|
||||
, configDbPreRequest :: Maybe Text
|
||||
, configDbPreparedStatements :: Bool
|
||||
, configDbRootSpec :: Maybe Text
|
||||
, configDbSchemas :: NonEmpty Text
|
||||
, configDbTxAllowOverride :: Bool
|
||||
, configDbTxRollbackAll :: Bool
|
||||
, configDbUri :: Text
|
||||
, configJWKS :: Maybe JWKSet
|
||||
, configJwtAudience :: Maybe StringOrURI
|
||||
, configJwtRoleClaimKey :: Either Text JSPath
|
||||
, configJwtSecret :: Maybe B.ByteString
|
||||
, configJwtSecretIsBase64 :: Bool
|
||||
, configLogLevel :: LogLevel
|
||||
, configOpenApiServerProxyUri :: Maybe Text
|
||||
, configRawMediaTypes :: [B.ByteString]
|
||||
, configServerHost :: Text
|
||||
, configServerPort :: Int
|
||||
, configServerUnixSocket :: Maybe FilePath
|
||||
, configServerUnixSocketMode :: Either Text FileMode
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
configPoolTimeout' :: (Fractional a) => AppConfig -> a
|
||||
configPoolTimeout' =
|
||||
fromRational . toRational . configPoolTimeout
|
||||
configDbPoolTimeout' :: (Fractional a) => AppConfig -> a
|
||||
configDbPoolTimeout' =
|
||||
fromRational . toRational . configDbPoolTimeout
|
||||
|
||||
-- | User friendly version number
|
||||
prettyVersion :: Text
|
||||
@@ -179,6 +172,16 @@ readCLIShowHelp = customExecParser parserPrefs opts
|
||||
|## extra schemas to add to the search_path of every request
|
||||
|db-extra-search-path = "public"
|
||||
|
|
||||
|## limit rows in response
|
||||
|# db-max-rows = 1000
|
||||
|
|
||||
|## stored proc to exec immediately after auth
|
||||
|# db-pre-request = "stored_proc_name"
|
||||
|
|
||||
|## stored proc that overrides the root "/" spec
|
||||
|## it must be inside the db-schema
|
||||
|# db-root-spec = "stored_proc_name"
|
||||
|
|
||||
|## Notification channel for reloading the schema cache
|
||||
|db-channel = "pgrst"
|
||||
|
|
||||
@@ -219,20 +222,10 @@ readCLIShowHelp = customExecParser parserPrefs opts
|
||||
|## (use "@filename" to load from separate file)
|
||||
|# jwt-secret = "secret_with_at_least_32_characters"
|
||||
|# jwt-aud = "your_audience_claim"
|
||||
|secret-is-base64 = false
|
||||
|jwt-secret-is-base64 = false
|
||||
|
|
||||
|## jspath to the role claim key
|
||||
|role-claim-key = ".role"
|
||||
|
|
||||
|## limit rows in response
|
||||
|# max-rows = 1000
|
||||
|
|
||||
|## stored proc to exec immediately after auth
|
||||
|# pre-request = "stored_proc_name"
|
||||
|
|
||||
|## stored proc that overrides the root "/" spec
|
||||
|## it must be inside the db-schema
|
||||
|# root-spec = "stored_proc_name"
|
||||
|jwt-role-claim-key = ".role"
|
||||
|
|
||||
|## content types to produce raw output
|
||||
|# raw-media-types="image/png, image/jpg"
|
||||
@@ -253,49 +246,49 @@ dumpAppConfig conf = do
|
||||
|
||||
-- apply conf to all pgrst settings
|
||||
pgrstSettings = (\(k, v) -> (k, v conf)) <$>
|
||||
[("db-uri", q . configDbUri)
|
||||
,("db-schema", q . intercalate "," . toList . configSchemas)
|
||||
,("db-anon-role", q . configAnonRole)
|
||||
,("db-pool", show . configPoolSize)
|
||||
,("db-pool-timeout", show . configPoolTimeout)
|
||||
,("db-extra-search-path", q . intercalate "," . configExtraSearchPath)
|
||||
[("db-anon-role", q . configDbAnonRole)
|
||||
,("db-channel", q . configDbChannel)
|
||||
,("db-channel-enabled", toLower . show . configDbChannelEnabled)
|
||||
,("db-extra-search-path", q . intercalate "," . configDbExtraSearchPath)
|
||||
,("db-max-rows", maybe "\"\"" show . configDbMaxRows)
|
||||
,("db-pool", show . configDbPoolSize)
|
||||
,("db-pool-timeout", show . configDbPoolTimeout)
|
||||
,("db-pre-request", q . fromMaybe mempty . configDbPreRequest)
|
||||
,("db-prepared-statements", toLower . show . configDbPreparedStatements)
|
||||
,("db-root-spec", q . fromMaybe mempty . configDbRootSpec)
|
||||
,("db-schemas", q . intercalate "," . toList . configDbSchemas)
|
||||
,("db-tx-end", q . showTxEnd)
|
||||
,("db-prepared-statements", toLower . show . configDbPrepared)
|
||||
,("server-host", q . configHost)
|
||||
,("server-port", show . configPort)
|
||||
,("server-unix-socket", q . maybe mempty pack . configSocket)
|
||||
,("server-unix-socket-mode", q . pack . showSocketMode)
|
||||
,("openapi-server-proxy-uri", q . fromMaybe mempty . configOpenAPIProxyUri)
|
||||
,("jwt-secret", q . toS . showJwtSecret)
|
||||
,("db-uri", q . configDbUri)
|
||||
,("jwt-aud", toS . encode . maybe "" toJSON . configJwtAudience)
|
||||
,("secret-is-base64", toLower . show . configJwtSecretIsBase64)
|
||||
,("role-claim-key", q . intercalate mempty . fmap show . fromRight' . configRoleClaimKey)
|
||||
,("max-rows", maybe "\"\"" show . configMaxRows)
|
||||
,("pre-request", q . fromMaybe mempty . configPreReq)
|
||||
,("root-spec", q . fromMaybe mempty . configRootSpec)
|
||||
,("raw-media-types", q . toS . B.intercalate "," . configRawMediaTypes)
|
||||
,("jwt-role-claim-key", q . intercalate mempty . fmap show . fromRight' . configJwtRoleClaimKey)
|
||||
,("jwt-secret", q . toS . showJwtSecret)
|
||||
,("jwt-secret-is-base64", toLower . show . configJwtSecretIsBase64)
|
||||
,("log-level", q . show . configLogLevel)
|
||||
,("openapi-server-proxy-uri", q . fromMaybe mempty . configOpenApiServerProxyUri)
|
||||
,("raw-media-types", q . toS . B.intercalate "," . configRawMediaTypes)
|
||||
,("server-host", q . configServerHost)
|
||||
,("server-port", show . configServerPort)
|
||||
,("server-unix-socket", q . maybe mempty pack . configServerUnixSocket)
|
||||
,("server-unix-socket-mode", q . pack . showSocketMode)
|
||||
]
|
||||
|
||||
-- quote all app.settings
|
||||
appSettings = second q <$> configSettings conf
|
||||
appSettings = second q <$> configAppSettings conf
|
||||
|
||||
-- quote strings and replace " with \"
|
||||
q s = "\"" <> replace "\"" "\\\"" s <> "\""
|
||||
|
||||
showTxEnd c = case (configTxRollbackAll c, configTxAllowOverride c) of
|
||||
showTxEnd c = case (configDbTxRollbackAll c, configDbTxAllowOverride c) of
|
||||
( False, False ) -> "commit"
|
||||
( False, True ) -> "commit-allow-override"
|
||||
( True , False ) -> "rollback"
|
||||
( True , True ) -> "rollback-allow-override"
|
||||
showSocketMode c = showOct (fromRight' $ configSocketMode c) ""
|
||||
showJwtSecret c
|
||||
| configJwtSecretIsBase64 c = B64.encode secret
|
||||
| otherwise = toS secret
|
||||
where
|
||||
secret = fromMaybe mempty $ configJwtSecret c
|
||||
showSocketMode c = showOct (fromRight' $ configServerUnixSocketMode c) ""
|
||||
|
||||
-- | Parse the config file
|
||||
readAppConfig :: FilePath -> IO AppConfig
|
||||
@@ -315,33 +308,40 @@ readAppConfig cfgPath = do
|
||||
where
|
||||
parseConfig =
|
||||
AppConfig
|
||||
<$> reqString "db-uri"
|
||||
<$> (fmap (fmap coerceText) <$> C.subassocs "app.settings" C.value)
|
||||
<*> reqString "db-anon-role"
|
||||
<*> (fromMaybe "pgrst" <$> optString "db-channel")
|
||||
<*> (fromMaybe False <$> optBool "db-channel-enabled")
|
||||
<*> (maybe ["public"] splitOnCommas <$> optValue "db-extra-search-path")
|
||||
<*> optWithAlias (optInt "db-max-rows")
|
||||
(optInt "max-rows")
|
||||
<*> (fromMaybe 10 <$> optInt "db-pool")
|
||||
<*> (fromMaybe 10 <$> optInt "db-pool-timeout")
|
||||
<*> optWithAlias (optString "db-pre-request")
|
||||
(optString "pre-request")
|
||||
<*> (fromMaybe True <$> optBool "db-prepared-statements")
|
||||
<*> optWithAlias (optString "db-root-spec")
|
||||
(optString "root-spec")
|
||||
<*> (fromList . splitOnCommas <$> reqWithAlias (optValue "db-schemas")
|
||||
(optValue "db-schema")
|
||||
"missing key: either db-schemas or db-schema must be set")
|
||||
<*> parseTxEnd "db-tx-end" snd
|
||||
<*> parseTxEnd "db-tx-end" fst
|
||||
<*> reqString "db-uri"
|
||||
<*> pure Nothing
|
||||
<*> parseJwtAudience "jwt-aud"
|
||||
<*> (maybe (Right [JSPKey "role"]) parseRoleClaimKey <$> optWithAlias (optValue "jwt-role-claim-key")
|
||||
(optValue "role-claim-key"))
|
||||
<*> (fmap encodeUtf8 <$> optString "jwt-secret")
|
||||
<*> (fromMaybe False <$> optWithAlias (optBool "jwt-secret-is-base64")
|
||||
(optBool "secret-is-base64"))
|
||||
<*> parseLogLevel "log-level"
|
||||
<*> optString "openapi-server-proxy-uri"
|
||||
<*> (fromList . splitOnCommas <$> reqValue "db-schema")
|
||||
<*> (maybe [] (fmap encodeUtf8 . splitOnCommas) <$> optValue "raw-media-types")
|
||||
<*> (fromMaybe "!4" <$> optString "server-host")
|
||||
<*> (fromMaybe 3000 <$> optInt "server-port")
|
||||
<*> (fmap unpack <$> optString "server-unix-socket")
|
||||
<*> parseSocketFileMode "server-unix-socket-mode"
|
||||
<*> (fromMaybe "pgrst" <$> optString "db-channel")
|
||||
<*> (fromMaybe False <$> optBool "db-channel-enabled")
|
||||
<*> (fmap encodeUtf8 <$> optString "jwt-secret")
|
||||
<*> (fromMaybe False <$> optBool "secret-is-base64")
|
||||
<*> parseJwtAudience "jwt-aud"
|
||||
<*> (fromMaybe 10 <$> optInt "db-pool")
|
||||
<*> (fromMaybe 10 <$> optInt "db-pool-timeout")
|
||||
<*> optInt "max-rows"
|
||||
<*> optString "pre-request"
|
||||
<*> (fmap (fmap coerceText) <$> C.subassocs "app.settings" C.value)
|
||||
<*> (maybe (Right [JSPKey "role"]) parseRoleClaimKey <$> optValue "role-claim-key")
|
||||
<*> (maybe ["public"] splitOnCommas <$> optValue "db-extra-search-path")
|
||||
<*> optString "root-spec"
|
||||
<*> (maybe [] (fmap encodeUtf8 . splitOnCommas) <$> optValue "raw-media-types")
|
||||
<*> pure Nothing
|
||||
<*> parseLogLevel "log-level"
|
||||
<*> parseTxEnd "db-tx-end" fst
|
||||
<*> parseTxEnd "db-tx-end" snd
|
||||
<*> (fromMaybe True <$> optBool "db-prepared-statements")
|
||||
|
||||
parseSocketFileMode :: C.Key -> C.Parser C.Config (Either Text FileMode)
|
||||
parseSocketFileMode k =
|
||||
@@ -388,12 +388,24 @@ readAppConfig cfgPath = do
|
||||
Just "rollback-allow-override" -> pure $ f (True, True)
|
||||
Just _ -> fail "Invalid transaction termination. Check your configuration."
|
||||
|
||||
reqWithAlias :: C.Parser C.Config (Maybe a) -> C.Parser C.Config (Maybe a) -> [Char] -> C.Parser C.Config a
|
||||
reqWithAlias orig alias err =
|
||||
orig >>= \case
|
||||
Just v -> pure v
|
||||
Nothing ->
|
||||
alias >>= \case
|
||||
Just v -> pure v
|
||||
Nothing -> fail err
|
||||
|
||||
optWithAlias :: C.Parser C.Config (Maybe a) -> C.Parser C.Config (Maybe a) -> C.Parser C.Config (Maybe a)
|
||||
optWithAlias orig alias =
|
||||
orig >>= \case
|
||||
Just v -> pure $ Just v
|
||||
Nothing -> alias
|
||||
|
||||
reqString :: C.Key -> C.Parser C.Config Text
|
||||
reqString k = C.required k C.string
|
||||
|
||||
reqValue :: C.Key -> C.Parser C.Config C.Value
|
||||
reqValue k = C.required k C.value
|
||||
|
||||
optString :: C.Key -> C.Parser C.Config (Maybe Text)
|
||||
optString k = mfilter (/= "") <$> C.optional k C.string
|
||||
|
||||
@@ -438,13 +450,13 @@ readValidateConfig :: FilePath -> IO AppConfig
|
||||
readValidateConfig path = do
|
||||
conf <- loadDbUriFile =<< loadSecretFile =<< readAppConfig path
|
||||
-- Checks that the provided proxy uri is formated correctly
|
||||
when (isMalformedProxyUri $ toS <$> configOpenAPIProxyUri conf) $
|
||||
when (isMalformedProxyUri $ toS <$> configOpenApiServerProxyUri conf) $
|
||||
panic
|
||||
"Malformed proxy uri, a correct example: https://example.com:8443/basePath"
|
||||
-- Checks that the provided jspath is valid
|
||||
whenLeft (configRoleClaimKey conf) panic
|
||||
whenLeft (configJwtRoleClaimKey conf) panic
|
||||
-- Check the file mode is valid
|
||||
whenLeft (configSocketMode conf) panic
|
||||
whenLeft (configServerUnixSocketMode conf) panic
|
||||
return $ conf { configJWKS = parseSecret <$> configJwtSecret conf}
|
||||
|
||||
{-|
|
||||
|
||||
@@ -53,14 +53,14 @@ runPgLocals conf claims app req = do
|
||||
headersSql = setLocalQuery "request.header." <$> iHeaders req
|
||||
cookiesSql = setLocalQuery "request.cookie." <$> iCookies req
|
||||
claimsSql = setLocalQuery "request.jwt.claim." <$> [(c,unquoted v) | (c,v) <- M.toList claimsWithRole]
|
||||
appSettingsSql = setLocalQuery mempty <$> configSettings conf
|
||||
appSettingsSql = setLocalQuery mempty <$> configAppSettings conf
|
||||
setRoleSql = maybeToList $ (\x ->
|
||||
setLocalQuery mempty ("role", unquoted x)) <$> M.lookup "role" claimsWithRole
|
||||
setSearchPathSql = setLocalSearchPathQuery (iSchema req : configExtraSearchPath conf)
|
||||
setSearchPathSql = setLocalSearchPathQuery (iSchema req : configDbExtraSearchPath conf)
|
||||
-- role claim defaults to anon if not specified in jwt
|
||||
claimsWithRole = M.union claims (M.singleton "role" anon)
|
||||
anon = JSON.String . toS $ configAnonRole conf
|
||||
preReq = (\f -> "select " <> toS f <> "();") <$> configPreReq conf
|
||||
anon = JSON.String . toS $ configDbAnonRole conf
|
||||
preReq = (\f -> "select " <> toS f <> "();") <$> configDbPreRequest conf
|
||||
|
||||
-- | Log in apache format. Only requests that have a status greater than minStatus are logged.
|
||||
-- | There's no way to filter logs in the apache format on wai-extra: https://hackage.haskell.org/package/wai-extra-3.0.29.2/docs/Network-Wai-Middleware-RequestLogger.html#t:OutputFormat.
|
||||
|
||||
+2
-2
@@ -63,7 +63,7 @@ main = do
|
||||
|
||||
actualPgVersion <- either (panic.show) id <$> P.use pool getPgVersion
|
||||
|
||||
refDbStructure <- (newIORef . Just) =<< setupDbStructure pool (configSchemas $ testCfg testDbConn) (configExtraSearchPath $ testCfg testDbConn) actualPgVersion
|
||||
refDbStructure <- (newIORef . Just) =<< setupDbStructure pool (configDbSchemas $ testCfg testDbConn) (configDbExtraSearchPath $ testCfg testDbConn) actualPgVersion
|
||||
|
||||
let
|
||||
-- For tests that run with the same refDbStructure
|
||||
@@ -73,7 +73,7 @@ main = do
|
||||
|
||||
-- For tests that run with a different DbStructure(depends on configSchemas)
|
||||
appDbs cfg = do
|
||||
dbs <- (newIORef . Just) =<< setupDbStructure pool (configSchemas $ cfg testDbConn) (configExtraSearchPath $ cfg testDbConn) actualPgVersion
|
||||
dbs <- (newIORef . Just) =<< setupDbStructure pool (configDbSchemas $ cfg testDbConn) (configDbExtraSearchPath $ cfg testDbConn) actualPgVersion
|
||||
refConf <- newIORef $ cfg testDbConn
|
||||
return ((), postgrest LogCrit refConf dbs pool getTime $ pure ())
|
||||
|
||||
|
||||
+37
-37
@@ -66,55 +66,55 @@ getEnvVarWithDefault var def = toS <$>
|
||||
_baseCfg :: AppConfig
|
||||
_baseCfg = let secret = Just $ encodeUtf8 "reallyreallyreallyreallyverysafe" in
|
||||
AppConfig {
|
||||
configDbUri = mempty
|
||||
, configAnonRole = "postgrest_test_anonymous"
|
||||
, configOpenAPIProxyUri = Nothing
|
||||
, configSchemas = fromList ["test"]
|
||||
, configHost = "localhost"
|
||||
, configPort = 3000
|
||||
, configSocket = Nothing
|
||||
, configSocketMode = Right 432
|
||||
, configDbChannel = mempty
|
||||
, configDbChannelEnabled = False
|
||||
, configJwtSecret = secret
|
||||
, configJwtSecretIsBase64 = False
|
||||
, configJwtAudience = Nothing
|
||||
, configPoolSize = 10
|
||||
, configPoolTimeout = 10
|
||||
, configMaxRows = Nothing
|
||||
, configPreReq = Just "test.switch_role"
|
||||
, configSettings = [ ("app.settings.app_host", "localhost") , ("app.settings.external_api_secret", "0123456789abcdef") ]
|
||||
, configRoleClaimKey = Right [JSPKey "role"]
|
||||
, configExtraSearchPath = []
|
||||
, configRootSpec = Nothing
|
||||
, configRawMediaTypes = []
|
||||
, configJWKS = parseSecret <$> secret
|
||||
, configLogLevel = LogCrit
|
||||
, configTxRollbackAll = True
|
||||
, configTxAllowOverride = True
|
||||
, configDbPrepared = True
|
||||
configAppSettings = [ ("app.settings.app_host", "localhost") , ("app.settings.external_api_secret", "0123456789abcdef") ]
|
||||
, configDbAnonRole = "postgrest_test_anonymous"
|
||||
, configDbChannel = mempty
|
||||
, configDbChannelEnabled = False
|
||||
, configDbExtraSearchPath = []
|
||||
, configDbMaxRows = Nothing
|
||||
, configDbPoolSize = 10
|
||||
, configDbPoolTimeout = 10
|
||||
, configDbPreRequest = Just "test.switch_role"
|
||||
, configDbPreparedStatements = True
|
||||
, configDbRootSpec = Nothing
|
||||
, configDbSchemas = fromList ["test"]
|
||||
, configDbUri = mempty
|
||||
, configJWKS = parseSecret <$> secret
|
||||
, configJwtAudience = Nothing
|
||||
, configJwtRoleClaimKey = Right [JSPKey "role"]
|
||||
, configJwtSecret = secret
|
||||
, configJwtSecretIsBase64 = False
|
||||
, configLogLevel = LogCrit
|
||||
, configOpenApiServerProxyUri = Nothing
|
||||
, configRawMediaTypes = []
|
||||
, configServerHost = "localhost"
|
||||
, configServerPort = 3000
|
||||
, configServerUnixSocket = Nothing
|
||||
, configServerUnixSocketMode = Right 432
|
||||
, configDbTxAllowOverride = True
|
||||
, configDbTxRollbackAll = True
|
||||
}
|
||||
|
||||
testCfg :: Text -> AppConfig
|
||||
testCfg testDbConn = _baseCfg { configDbUri = testDbConn }
|
||||
|
||||
testCfgDisallowRollback :: Text -> AppConfig
|
||||
testCfgDisallowRollback testDbConn = (testCfg testDbConn) { configTxRollbackAll = False, configTxAllowOverride = False }
|
||||
testCfgDisallowRollback testDbConn = (testCfg testDbConn) { configDbTxAllowOverride = False, configDbTxRollbackAll = False }
|
||||
|
||||
testCfgForceRollback :: Text -> AppConfig
|
||||
testCfgForceRollback testDbConn = (testCfg testDbConn) { configTxRollbackAll = True, configTxAllowOverride = False }
|
||||
testCfgForceRollback testDbConn = (testCfg testDbConn) { configDbTxAllowOverride = False, configDbTxRollbackAll = True }
|
||||
|
||||
testCfgNoJWT :: Text -> AppConfig
|
||||
testCfgNoJWT testDbConn = (testCfg testDbConn) { configJwtSecret = Nothing, configJWKS = Nothing }
|
||||
|
||||
testUnicodeCfg :: Text -> AppConfig
|
||||
testUnicodeCfg testDbConn = (testCfg testDbConn) { configSchemas = fromList ["تست"] }
|
||||
testUnicodeCfg testDbConn = (testCfg testDbConn) { configDbSchemas = fromList ["تست"] }
|
||||
|
||||
testMaxRowsCfg :: Text -> AppConfig
|
||||
testMaxRowsCfg testDbConn = (testCfg testDbConn) { configMaxRows = Just 2 }
|
||||
testMaxRowsCfg testDbConn = (testCfg testDbConn) { configDbMaxRows = Just 2 }
|
||||
|
||||
testProxyCfg :: Text -> AppConfig
|
||||
testProxyCfg testDbConn = (testCfg testDbConn) { configOpenAPIProxyUri = Just "https://postgrest.com/openapi.json" }
|
||||
testProxyCfg testDbConn = (testCfg testDbConn) { configOpenApiServerProxyUri = Just "https://postgrest.com/openapi.json" }
|
||||
|
||||
testCfgBinaryJWT :: Text -> AppConfig
|
||||
testCfgBinaryJWT testDbConn =
|
||||
@@ -150,22 +150,22 @@ testCfgAsymJWKSet testDbConn =
|
||||
}
|
||||
|
||||
testNonexistentSchemaCfg :: Text -> AppConfig
|
||||
testNonexistentSchemaCfg testDbConn = (testCfg testDbConn) { configSchemas = fromList ["nonexistent"] }
|
||||
testNonexistentSchemaCfg testDbConn = (testCfg testDbConn) { configDbSchemas = fromList ["nonexistent"] }
|
||||
|
||||
testCfgExtraSearchPath :: Text -> AppConfig
|
||||
testCfgExtraSearchPath testDbConn = (testCfg testDbConn) { configExtraSearchPath = ["public", "extensions"] }
|
||||
testCfgExtraSearchPath testDbConn = (testCfg testDbConn) { configDbExtraSearchPath = ["public", "extensions"] }
|
||||
|
||||
testCfgRootSpec :: Text -> AppConfig
|
||||
testCfgRootSpec testDbConn = (testCfg testDbConn) { configRootSpec = Just "root"}
|
||||
testCfgRootSpec testDbConn = (testCfg testDbConn) { configDbRootSpec = Just "root"}
|
||||
|
||||
testCfgHtmlRawOutput :: Text -> AppConfig
|
||||
testCfgHtmlRawOutput testDbConn = (testCfg testDbConn) { configRawMediaTypes = ["text/html"] }
|
||||
|
||||
testCfgResponseHeaders :: Text -> AppConfig
|
||||
testCfgResponseHeaders testDbConn = (testCfg testDbConn) { configPreReq = Just "custom_headers" }
|
||||
testCfgResponseHeaders testDbConn = (testCfg testDbConn) { configDbPreRequest = Just "custom_headers" }
|
||||
|
||||
testMultipleSchemaCfg :: Text -> AppConfig
|
||||
testMultipleSchemaCfg testDbConn = (testCfg testDbConn) { configSchemas = fromList ["v1", "v2"] }
|
||||
testMultipleSchemaCfg testDbConn = (testCfg testDbConn) { configDbSchemas = fromList ["v1", "v2"] }
|
||||
|
||||
resetDb :: Text -> IO ()
|
||||
resetDb dbConn = loadFixture dbConn "data"
|
||||
|
||||
+4
-4
@@ -316,17 +316,17 @@ checkDbSchemaReload(){
|
||||
# wait for the server to start
|
||||
sleep 0.1
|
||||
done
|
||||
# add v1 schema to db-schema
|
||||
replaceConfigValue "db-schema" "test, v1" "$configFile"
|
||||
# add v1 schema to db-schemas
|
||||
replaceConfigValue "db-schemas" "test, v1" "$configFile"
|
||||
# reload
|
||||
kill -s SIGUSR2 $pgrPID
|
||||
kill -s SIGUSR1 $pgrPID
|
||||
httpStatus="$(v1SchemaParentsStatus)"
|
||||
if test "$httpStatus" -eq 200
|
||||
then
|
||||
ok "db-schema config reloaded with SIGUSR2"
|
||||
ok "db-schemas config reloaded with SIGUSR2"
|
||||
else
|
||||
ko "db-schema config not reloaded with SIGUSR2. Got: $httpStatus"
|
||||
ko "db-schemas config not reloaded with SIGUSR2. Got: $httpStatus"
|
||||
fi
|
||||
pgrStop
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
db-anon-role = "required"
|
||||
db-uri = "required"
|
||||
|
||||
db-schema = "provided_through_alias"
|
||||
max-rows = 1000
|
||||
pre-request = "check_alias"
|
||||
role-claim-key = ".aliased"
|
||||
root-spec = "open_alias"
|
||||
secret-is-base64 = true
|
||||
@@ -1,5 +1,5 @@
|
||||
db-uri = "$(POSTGREST_TEST_CONNECTION)"
|
||||
db-schema = "test"
|
||||
db-schemas = "test"
|
||||
db-anon-role = "postgrest_test_anonymous"
|
||||
db-pool = 1
|
||||
db-pool-timeout = 1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
db-uri = "$(POSTGREST_TEST_CONNECTION)"
|
||||
db-schema = "test"
|
||||
db-schemas = "test"
|
||||
db-anon-role = "postgrest_test_anonymous"
|
||||
db-pool = 1
|
||||
server-host = "127.0.0.1"
|
||||
@@ -7,4 +7,4 @@ server-port = 49421
|
||||
|
||||
# Read secret from a file: /dev/stdin (alias for standard input)
|
||||
jwt-secret = "@/dev/stdin"
|
||||
secret-is-base64 = true
|
||||
jwt-secret-is-base64 = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
db-uri = "@/dev/stdin"
|
||||
db-schema = "test"
|
||||
db-schemas = "test"
|
||||
db-anon-role = "postgrest_test_anonymous"
|
||||
db-pool = 1
|
||||
server-host = "127.0.0.1"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
db-uri = "required"
|
||||
db-schema = "required"
|
||||
db-schemas = "required"
|
||||
db-anon-role = "required"
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
db-anon-role = "required"
|
||||
db-channel = "pgrst"
|
||||
db-channel-enabled = false
|
||||
db-extra-search-path = "public"
|
||||
db-max-rows = 1000
|
||||
db-pool = 10
|
||||
db-pool-timeout = 10
|
||||
db-pre-request = "check_alias"
|
||||
db-prepared-statements = true
|
||||
db-root-spec = "open_alias"
|
||||
db-schemas = "provided_through_alias"
|
||||
db-tx-end = "commit"
|
||||
db-uri = "required"
|
||||
jwt-aud = ""
|
||||
jwt-role-claim-key = ".\"aliased\""
|
||||
jwt-secret = ""
|
||||
jwt-secret-is-base64 = true
|
||||
log-level = "error"
|
||||
openapi-server-proxy-uri = ""
|
||||
raw-media-types = ""
|
||||
server-host = "!4"
|
||||
server-port = 3000
|
||||
server-unix-socket = ""
|
||||
server-unix-socket-mode = "660"
|
||||
@@ -1,24 +1,24 @@
|
||||
db-uri = "required"
|
||||
db-schema = "required"
|
||||
db-anon-role = "required"
|
||||
db-pool = 10
|
||||
db-pool-timeout = 10
|
||||
db-extra-search-path = "public"
|
||||
db-channel = "pgrst"
|
||||
db-channel-enabled = false
|
||||
db-tx-end = "commit"
|
||||
db-extra-search-path = "public"
|
||||
db-max-rows = ""
|
||||
db-pool = 10
|
||||
db-pool-timeout = 10
|
||||
db-pre-request = ""
|
||||
db-prepared-statements = true
|
||||
db-root-spec = ""
|
||||
db-schemas = "required"
|
||||
db-tx-end = "commit"
|
||||
db-uri = "required"
|
||||
jwt-aud = ""
|
||||
jwt-role-claim-key = ".\"role\""
|
||||
jwt-secret = ""
|
||||
jwt-secret-is-base64 = false
|
||||
log-level = "error"
|
||||
openapi-server-proxy-uri = ""
|
||||
raw-media-types = ""
|
||||
server-host = "!4"
|
||||
server-port = 3000
|
||||
server-unix-socket = ""
|
||||
server-unix-socket-mode = "660"
|
||||
openapi-server-proxy-uri = ""
|
||||
jwt-secret = ""
|
||||
jwt-aud = ""
|
||||
secret-is-base64 = false
|
||||
role-claim-key = ".\"role\""
|
||||
max-rows = ""
|
||||
pre-request = ""
|
||||
root-spec = ""
|
||||
raw-media-types = ""
|
||||
log-level = "error"
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
db-uri = "tmp_db"
|
||||
db-schema = "multi,tenant,setup"
|
||||
db-anon-role = "root"
|
||||
db-pool = 1
|
||||
db-pool-timeout = 100
|
||||
db-extra-search-path = "public,test"
|
||||
db-channel = "postgrest"
|
||||
db-channel-enabled = true
|
||||
db-tx-end = "rollback-allow-override"
|
||||
db-extra-search-path = "public,test"
|
||||
db-max-rows = 1000
|
||||
db-pool = 1
|
||||
db-pool-timeout = 100
|
||||
db-pre-request = "please_run_fast"
|
||||
db-prepared-statements = false
|
||||
db-root-spec = "openapi_v3"
|
||||
db-schemas = "multi,tenant,setup"
|
||||
db-tx-end = "rollback-allow-override"
|
||||
db-uri = "tmp_db"
|
||||
jwt-aud = "https://postgrest.org"
|
||||
jwt-role-claim-key = ".\"user\"[0].\"real-role\""
|
||||
jwt-secret = "c2VjdXJpdHl0aHJvdWdob2JzY3VyaXR5"
|
||||
jwt-secret-is-base64 = true
|
||||
log-level = "info"
|
||||
openapi-server-proxy-uri = "https://postgrest.org"
|
||||
raw-media-types = "application/vnd.pgrst.config"
|
||||
server-host = "0.0.0.0"
|
||||
server-port = 80
|
||||
server-unix-socket = "/tmp/pgrst_io_test.sock"
|
||||
server-unix-socket-mode = "777"
|
||||
openapi-server-proxy-uri = "https://postgrest.org"
|
||||
jwt-secret = "c2VjdXJpdHl0aHJvdWdob2JzY3VyaXR5"
|
||||
jwt-aud = "https://postgrest.org"
|
||||
secret-is-base64 = true
|
||||
role-claim-key = ".\"user\"[0].\"real-role\""
|
||||
max-rows = 1000
|
||||
pre-request = "please_run_fast"
|
||||
root-spec = "openapi_v3"
|
||||
raw-media-types = "application/vnd.pgrst.config"
|
||||
log-level = "info"
|
||||
app.settings.test = "test"
|
||||
app.settings.test2 = "test"
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
db-uri = "tmp_db"
|
||||
db-schema = "multi, tenant,setup"
|
||||
db-anon-role = "root"
|
||||
db-pool = 1
|
||||
db-pool-timeout = 100
|
||||
db-extra-search-path = "public, test"
|
||||
db-channel = "postgrest"
|
||||
db-channel-enabled = true
|
||||
db-tx-end = "rollback-allow-override"
|
||||
db-extra-search-path = "public, test"
|
||||
db-max-rows = 1000
|
||||
db-pool = 1
|
||||
db-pool-timeout = 100
|
||||
db-pre-request = "please_run_fast"
|
||||
db-prepared-statements = false
|
||||
db-root-spec = "openapi_v3"
|
||||
db-schemas = "multi, tenant,setup"
|
||||
db-tx-end = "rollback-allow-override"
|
||||
db-uri = "tmp_db"
|
||||
jwt-aud = "https://postgrest.org"
|
||||
jwt-role-claim-key = ".user[0].\"real-role\""
|
||||
jwt-secret = "c2VjdXJpdHl0aHJvdWdob2JzY3VyaXR5"
|
||||
jwt-secret-is-base64 = true
|
||||
log-level = "info"
|
||||
openapi-server-proxy-uri = "https://postgrest.org"
|
||||
raw-media-types = "application/vnd.pgrst.config"
|
||||
server-host = "0.0.0.0"
|
||||
server-port = 80
|
||||
server-unix-socket = "/tmp/pgrst_io_test.sock"
|
||||
server-unix-socket-mode = "777"
|
||||
openapi-server-proxy-uri = "https://postgrest.org"
|
||||
jwt-secret = "c2VjdXJpdHl0aHJvdWdob2JzY3VyaXR5"
|
||||
jwt-aud = "https://postgrest.org"
|
||||
secret-is-base64 = true
|
||||
role-claim-key = ".user[0].\"real-role\""
|
||||
max-rows = 1000
|
||||
pre-request = "please_run_fast"
|
||||
root-spec = "openapi_v3"
|
||||
raw-media-types = "application/vnd.pgrst.config"
|
||||
log-level = "info"
|
||||
app.settings.test = "test"
|
||||
app.settings.test2 = "test"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
db-uri = "$(POSTGREST_TEST_CONNECTION)"
|
||||
db-schema = "test"
|
||||
db-schemas = "test"
|
||||
db-anon-role = "postgrest_test_anonymous"
|
||||
db-pool = 1
|
||||
server-host = "127.0.0.1"
|
||||
server-port = 49421
|
||||
role-claim-key = "$(ROLE_CLAIM_KEY)"
|
||||
jwt-role-claim-key = "$(ROLE_CLAIM_KEY)"
|
||||
jwt-secret = "reallyreallyreallyreallyverysafe"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
db-uri = "$(POSTGREST_TEST_CONNECTION)"
|
||||
db-schema = "test"
|
||||
db-schemas = "test"
|
||||
db-anon-role = "postgrest_test_anonymous"
|
||||
db-pool = 1
|
||||
server-host = "127.0.0.1"
|
||||
@@ -7,4 +7,4 @@ server-port = 49421
|
||||
|
||||
# Read secret from a file: /dev/stdin (alias for standard input)
|
||||
jwt-secret = "@/dev/stdin"
|
||||
secret-is-base64 = false
|
||||
jwt-secret-is-base64 = false
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
db-uri = "$(POSTGREST_TEST_CONNECTION)"
|
||||
db-schema = "test"
|
||||
db-schemas = "test"
|
||||
db-anon-role = "postgrest_test_anonymous"
|
||||
db-pool = 1
|
||||
server-host = "127.0.0.1"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
db-uri = "$(POSTGREST_TEST_CONNECTION)"
|
||||
db-schema = "test"
|
||||
db-schemas = "test"
|
||||
db-anon-role = "postgrest_test_anonymous"
|
||||
db-pool = 1
|
||||
server-host = "127.0.0.1"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
db-uri = "$(POSTGREST_TEST_CONNECTION)"
|
||||
db-schema = "test"
|
||||
db-schemas = "test"
|
||||
db-anon-role = "postgrest_test_anonymous"
|
||||
db-pool = 1
|
||||
server-host = "127.0.0.1"
|
||||
|
||||
Reference in New Issue
Block a user