feat: Make GUC names for headers, cookies and jwt claims compatible with PostgreSQL v14
Getting the value for a header GUC on PostgreSQL v14 is done using `current_setting('request.headers')::json->>'name-of-header'` and in a similar way for `request.cookies` and `request.jwt.claims`
PostgreSQL versions below 14 can opt in to the new JSON GUCs by setting the `db-use-legacy-gucs` config option to false (true by default)
This commit is contained in:
@@ -41,13 +41,16 @@ jobs:
|
|||||||
- name: Install testing scripts
|
- name: Install testing scripts
|
||||||
run: nix-env -f default.nix -iA tests withTools
|
run: nix-env -f default.nix -iA tests withTools
|
||||||
|
|
||||||
- name: Run coverage (IO tests and Spec tests against PostgreSQL 13)
|
- name: Run coverage (IO tests and Spec tests against PostgreSQL 14)
|
||||||
run: postgrest-coverage
|
run: postgrest-coverage
|
||||||
- name: Upload coverage to codecov
|
- name: Upload coverage to codecov
|
||||||
uses: codecov/codecov-action@v2
|
uses: codecov/codecov-action@v2
|
||||||
with:
|
with:
|
||||||
files: ./coverage/codecov.json
|
files: ./coverage/codecov.json
|
||||||
|
|
||||||
|
- name: Run the spec tests against PostgreSQL 13
|
||||||
|
if: always()
|
||||||
|
run: postgrest-with-postgresql-13 postgrest-test-spec
|
||||||
- name: Run the spec tests against PostgreSQL 12
|
- name: Run the spec tests against PostgreSQL 12
|
||||||
if: always()
|
if: always()
|
||||||
run: postgrest-with-postgresql-12 postgrest-test-spec
|
run: postgrest-with-postgresql-12 postgrest-test-spec
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- #1927, Overloaded Functions: If there's a function "my_func" having a single unnamed json param and other overloaded pairs(with any number of params), PostgREST won't be able to resolve a POST request to "my_func". For solving this, you can name the unnamed json param `my_func(json) -> my_func(prm json)`.
|
- #1927, Overloaded Functions: If there's a function "my_func" having a single unnamed json param and other overloaded pairs(with any number of params), PostgREST won't be able to resolve a POST request to "my_func". For solving this, you can name the unnamed json param `my_func(json) -> my_func(prm json)`.
|
||||||
|
- #1857, Make GUC names for headers, cookies and jwt claims compatible with PostgreSQL v14 - @laurenceisla, @robertsosinski
|
||||||
|
+ Getting the value for a header GUC on PostgreSQL 14 is done using `current_setting('request.headers')::json->>'name-of-header'` and in a similar way for `request.cookies` and `request.jwt.claims`
|
||||||
|
+ PostgreSQL versions below 14 can opt in to the new JSON GUCs by setting the `db-use-legacy-gucs` config option to false (true by default)
|
||||||
|
|
||||||
## [8.0.0] - 2021-07-25
|
## [8.0.0] - 2021-07-25
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ let
|
|||||||
allOverlays.gitignore
|
allOverlays.gitignore
|
||||||
allOverlays.postgresql-default
|
allOverlays.postgresql-default
|
||||||
allOverlays.postgresql-legacy
|
allOverlays.postgresql-legacy
|
||||||
|
allOverlays.postgresql-future
|
||||||
(allOverlays.haskell-packages { inherit compiler; })
|
(allOverlays.haskell-packages { inherit compiler; })
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ let
|
|||||||
|
|
||||||
postgresqlVersions =
|
postgresqlVersions =
|
||||||
[
|
[
|
||||||
|
{ name = "postgresql-14"; postgresql = pkgs.postgresql_14; }
|
||||||
{ name = "postgresql-13"; postgresql = pkgs.postgresql_13; }
|
{ name = "postgresql-13"; postgresql = pkgs.postgresql_13; }
|
||||||
{ name = "postgresql-12"; postgresql = pkgs.postgresql_12; }
|
{ name = "postgresql-12"; postgresql = pkgs.postgresql_12; }
|
||||||
{ name = "postgresql-11"; postgresql = pkgs.postgresql_11; }
|
{ name = "postgresql-11"; postgresql = pkgs.postgresql_11; }
|
||||||
|
|||||||
@@ -5,4 +5,5 @@
|
|||||||
haskell-packages = import ./haskell-packages.nix;
|
haskell-packages = import ./haskell-packages.nix;
|
||||||
postgresql-default = import ./postgresql-default.nix;
|
postgresql-default = import ./postgresql-default.nix;
|
||||||
postgresql-legacy = import ./postgresql-legacy.nix;
|
postgresql-legacy = import ./postgresql-legacy.nix;
|
||||||
|
postgresql-future = import ./postgresql-future.nix;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
self: super:
|
self: super:
|
||||||
# Overlay that sets the default version of PostgreSQL.
|
# Overlay that sets the default version of PostgreSQL.
|
||||||
{
|
{
|
||||||
postgresql = super.postgresql_13;
|
postgresql = super.postgresql_14;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
self: super:
|
||||||
|
# Overlay that adds future versions of PostgreSQL that are supported by
|
||||||
|
# PostgREST.
|
||||||
|
{
|
||||||
|
postgresql_14 =
|
||||||
|
let
|
||||||
|
rev = "76b1e16c6659ccef7187ca69b287525fea133244";
|
||||||
|
tarballHash = "1vsahpcx80k2bgslspb0sa6j4bmhdx77sw6la455drqcrqhdqj6a";
|
||||||
|
|
||||||
|
pinnedPkgs =
|
||||||
|
builtins.fetchTarball {
|
||||||
|
url = "https://github.com/nixos/nixpkgs/archive/${rev}.tar.gz";
|
||||||
|
sha256 = tarballHash;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
(import pinnedPkgs { }).pkgs.postgresql_14;
|
||||||
|
}
|
||||||
@@ -182,6 +182,7 @@ test-suite spec
|
|||||||
Feature.InsertSpec
|
Feature.InsertSpec
|
||||||
Feature.IgnorePrivOpenApiSpec
|
Feature.IgnorePrivOpenApiSpec
|
||||||
Feature.JsonOperatorSpec
|
Feature.JsonOperatorSpec
|
||||||
|
Feature.LegacyGucsSpec
|
||||||
Feature.MultipleSchemaSpec
|
Feature.MultipleSchemaSpec
|
||||||
Feature.NoJwtSpec
|
Feature.NoJwtSpec
|
||||||
Feature.NonexistentSchemaSpec
|
Feature.NonexistentSchemaSpec
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ postgrestResponse conf maybeDbStructure jsonDbS pgVer pool time req = do
|
|||||||
|
|
||||||
runDbHandler pool (txMode apiRequest) jwtClaims (configDbPreparedStatements conf) .
|
runDbHandler pool (txMode apiRequest) jwtClaims (configDbPreparedStatements conf) .
|
||||||
Middleware.optionalRollback conf apiRequest $
|
Middleware.optionalRollback conf apiRequest $
|
||||||
Middleware.runPgLocals conf jwtClaims handleReq apiRequest jsonDbS
|
Middleware.runPgLocals conf jwtClaims handleReq apiRequest jsonDbS pgVer
|
||||||
|
|
||||||
runDbHandler :: SQL.Pool -> SQL.Mode -> Auth.JWTClaims -> Bool -> DbHandler a -> Handler IO a
|
runDbHandler :: SQL.Pool -> SQL.Mode -> Auth.JWTClaims -> Bool -> DbHandler a -> Handler IO a
|
||||||
runDbHandler pool mode jwtClaims prepared handler = do
|
runDbHandler pool mode jwtClaims prepared handler = do
|
||||||
|
|||||||
@@ -166,6 +166,10 @@ exampleConfigFile =
|
|||||||
|## Enable in-database configuration
|
|## Enable in-database configuration
|
||||||
|db-config = true
|
|db-config = true
|
||||||
|
|
|
|
||||||
|
|## Determine if GUC request settings for headers, cookies and jwt claims use the legacy names (string with dashes, invalid starting from PostgreSQL v14) with text values instead of the new names (string without dashes, valid on all PostgreSQL versions) with json values.
|
||||||
|
|## For PostgreSQL v14 and up, this setting will be ignored.
|
||||||
|
|db-use-legacy-gucs = true
|
||||||
|
|
|
||||||
|## how to terminate database transactions
|
|## how to terminate database transactions
|
||||||
|## possible values are:
|
|## possible values are:
|
||||||
|## commit (default)
|
|## commit (default)
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ data AppConfig = AppConfig
|
|||||||
, configDbTxRollbackAll :: Bool
|
, configDbTxRollbackAll :: Bool
|
||||||
, configDbUri :: Text
|
, configDbUri :: Text
|
||||||
, configDbEmbedDefaultJoin :: JoinType
|
, configDbEmbedDefaultJoin :: JoinType
|
||||||
|
, configDbUseLegacyGucs :: Bool
|
||||||
, configFilePath :: Maybe FilePath
|
, configFilePath :: Maybe FilePath
|
||||||
, configJWKS :: Maybe JWKSet
|
, configJWKS :: Maybe JWKSet
|
||||||
, configJwtAudience :: Maybe StringOrURI
|
, configJwtAudience :: Maybe StringOrURI
|
||||||
@@ -135,6 +136,7 @@ toText conf =
|
|||||||
,("db-tx-end", q . showTxEnd)
|
,("db-tx-end", q . showTxEnd)
|
||||||
,("db-uri", q . configDbUri)
|
,("db-uri", q . configDbUri)
|
||||||
,("db-embed-default-join", q . show . configDbEmbedDefaultJoin)
|
,("db-embed-default-join", q . show . configDbEmbedDefaultJoin)
|
||||||
|
,("db-use-legacy-gucs", T.toLower . show . configDbUseLegacyGucs)
|
||||||
,("jwt-aud", toS . encode . maybe "" toJSON . configJwtAudience)
|
,("jwt-aud", toS . encode . maybe "" toJSON . configJwtAudience)
|
||||||
,("jwt-role-claim-key", q . T.intercalate mempty . fmap show . configJwtRoleClaimKey)
|
,("jwt-role-claim-key", q . T.intercalate mempty . fmap show . configJwtRoleClaimKey)
|
||||||
,("jwt-secret", q . toS . showJwtSecret)
|
,("jwt-secret", q . toS . showJwtSecret)
|
||||||
@@ -226,6 +228,7 @@ parser optPath env dbSettings =
|
|||||||
<*> parseTxEnd "db-tx-end" fst
|
<*> parseTxEnd "db-tx-end" fst
|
||||||
<*> reqString "db-uri"
|
<*> reqString "db-uri"
|
||||||
<*> parseEmbedDefaultJoin "db-embed-default-join"
|
<*> parseEmbedDefaultJoin "db-embed-default-join"
|
||||||
|
<*> (fromMaybe True <$> optBool "db-use-legacy-gucs")
|
||||||
<*> pure optPath
|
<*> pure optPath
|
||||||
<*> pure Nothing
|
<*> pure Nothing
|
||||||
<*> parseJwtAudience "jwt-aud"
|
<*> parseJwtAudience "jwt-aud"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ module PostgREST.Config.PgVersion
|
|||||||
, pgVersion114
|
, pgVersion114
|
||||||
, pgVersion121
|
, pgVersion121
|
||||||
, pgVersion130
|
, pgVersion130
|
||||||
|
, pgVersion140
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import qualified Data.Aeson as JSON
|
import qualified Data.Aeson as JSON
|
||||||
@@ -58,3 +59,6 @@ pgVersion121 = PgVersion 120001 "12.1"
|
|||||||
|
|
||||||
pgVersion130 :: PgVersion
|
pgVersion130 :: PgVersion
|
||||||
pgVersion130 = PgVersion 130000 "13.0"
|
pgVersion130 = PgVersion 130000 "13.0"
|
||||||
|
|
||||||
|
pgVersion140 :: PgVersion
|
||||||
|
pgVersion140 = PgVersion 140000 "14.0"
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ module PostgREST.Middleware
|
|||||||
|
|
||||||
import qualified Data.Aeson as JSON
|
import qualified Data.Aeson as JSON
|
||||||
import qualified Data.ByteString.Char8 as BS
|
import qualified Data.ByteString.Char8 as BS
|
||||||
|
import qualified Data.ByteString.Lazy.Char8 as BSL
|
||||||
import qualified Data.CaseInsensitive as CI
|
import qualified Data.CaseInsensitive as CI
|
||||||
import qualified Data.HashMap.Strict as M
|
import qualified Data.HashMap.Strict as M
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
@@ -30,6 +31,8 @@ import qualified Network.Wai.Middleware.Gzip as Wai
|
|||||||
import qualified Network.Wai.Middleware.RequestLogger as Wai
|
import qualified Network.Wai.Middleware.RequestLogger as Wai
|
||||||
import qualified Network.Wai.Middleware.Static as Wai
|
import qualified Network.Wai.Middleware.Static as Wai
|
||||||
|
|
||||||
|
import Control.Arrow ((***))
|
||||||
|
|
||||||
import Data.Function (id)
|
import Data.Function (id)
|
||||||
import Data.List (lookup)
|
import Data.List (lookup)
|
||||||
import Data.Scientific (FPFormat (..), formatScientific,
|
import Data.Scientific (FPFormat (..), formatScientific,
|
||||||
@@ -40,6 +43,7 @@ import System.IO.Unsafe (unsafePerformIO)
|
|||||||
import System.Log.FastLogger (toLogStr)
|
import System.Log.FastLogger (toLogStr)
|
||||||
|
|
||||||
import PostgREST.Config (AppConfig (..), LogLevel (..))
|
import PostgREST.Config (AppConfig (..), LogLevel (..))
|
||||||
|
import PostgREST.Config.PgVersion (PgVersion (..), pgVersion140)
|
||||||
import PostgREST.Error (Error, errorResponseFor)
|
import PostgREST.Error (Error, errorResponseFor)
|
||||||
import PostgREST.GucHeader (addHeadersIfNotIncluded)
|
import PostgREST.GucHeader (addHeadersIfNotIncluded)
|
||||||
import PostgREST.Query.SqlFragment (fromQi, intercalateSnippet,
|
import PostgREST.Query.SqlFragment (fromQi, intercalateSnippet,
|
||||||
@@ -54,8 +58,8 @@ import Protolude.Conv (toS)
|
|||||||
-- | Runs local(transaction scoped) GUCs for every request, plus the pre-request function
|
-- | Runs local(transaction scoped) GUCs for every request, plus the pre-request function
|
||||||
runPgLocals :: AppConfig -> M.HashMap Text JSON.Value ->
|
runPgLocals :: AppConfig -> M.HashMap Text JSON.Value ->
|
||||||
(ApiRequest -> ExceptT Error H.Transaction Wai.Response) ->
|
(ApiRequest -> ExceptT Error H.Transaction Wai.Response) ->
|
||||||
ApiRequest -> ByteString -> ExceptT Error H.Transaction Wai.Response
|
ApiRequest -> ByteString -> PgVersion -> ExceptT Error H.Transaction Wai.Response
|
||||||
runPgLocals conf claims app req jsonDbS = do
|
runPgLocals conf claims app req jsonDbS actualPgVersion = do
|
||||||
lift $ H.statement mempty $ H.dynamicallyParameterized
|
lift $ H.statement mempty $ H.dynamicallyParameterized
|
||||||
("select " <> intercalateSnippet ", " (searchPathSql : roleSql ++ claimsSql ++ [methodSql, pathSql] ++ headersSql ++ cookiesSql ++ appSettingsSql ++ specSql))
|
("select " <> intercalateSnippet ", " (searchPathSql : roleSql ++ claimsSql ++ [methodSql, pathSql] ++ headersSql ++ cookiesSql ++ appSettingsSql ++ specSql))
|
||||||
HD.noResult (configDbPreparedStatements conf)
|
HD.noResult (configDbPreparedStatements conf)
|
||||||
@@ -64,12 +68,18 @@ runPgLocals conf claims app req jsonDbS = do
|
|||||||
where
|
where
|
||||||
methodSql = setConfigLocal mempty ("request.method", iMethod req)
|
methodSql = setConfigLocal mempty ("request.method", iMethod req)
|
||||||
pathSql = setConfigLocal mempty ("request.path", iPath req)
|
pathSql = setConfigLocal mempty ("request.path", iPath req)
|
||||||
headersSql = setConfigLocal "request.header." <$> iHeaders req
|
headersSql = if usesLegacyGucs
|
||||||
cookiesSql = setConfigLocal "request.cookie." <$> iCookies req
|
then setConfigLocal "request.header." <$> iHeaders req
|
||||||
|
else setConfigLocalJson "request.headers" (iHeaders req)
|
||||||
|
cookiesSql = if usesLegacyGucs
|
||||||
|
then setConfigLocal "request.cookie." <$> iCookies req
|
||||||
|
else setConfigLocalJson "request.cookies" (iCookies req)
|
||||||
claimsWithRole =
|
claimsWithRole =
|
||||||
let anon = JSON.String . toS $ configDbAnonRole conf in -- role claim defaults to anon if not specified in jwt
|
let anon = JSON.String . toS $ configDbAnonRole conf in -- role claim defaults to anon if not specified in jwt
|
||||||
M.union claims (M.singleton "role" anon)
|
M.union claims (M.singleton "role" anon)
|
||||||
claimsSql = setConfigLocal "request.jwt.claim." <$> [(toS c, toS $ unquoted v) | (c,v) <- M.toList claimsWithRole]
|
claimsSql = if usesLegacyGucs
|
||||||
|
then setConfigLocal "request.jwt.claim." <$> [(toS c, toS $ unquoted v) | (c,v) <- M.toList claimsWithRole]
|
||||||
|
else [setConfigLocal mempty ("request.jwt.claims", BSL.toStrict $ JSON.encode claimsWithRole)]
|
||||||
roleSql = maybeToList $ (\x -> setConfigLocal mempty ("role", toS $ unquoted x)) <$> M.lookup "role" claimsWithRole
|
roleSql = maybeToList $ (\x -> setConfigLocal mempty ("role", toS $ unquoted x)) <$> M.lookup "role" claimsWithRole
|
||||||
appSettingsSql = setConfigLocal mempty <$> (join bimap toS <$> configAppSettings conf)
|
appSettingsSql = setConfigLocal mempty <$> (join bimap toS <$> configAppSettings conf)
|
||||||
searchPathSql =
|
searchPathSql =
|
||||||
@@ -79,10 +89,7 @@ runPgLocals conf claims app req jsonDbS = do
|
|||||||
specSql = case iTarget req of
|
specSql = case iTarget req of
|
||||||
TargetProc{tpIsRootSpec=True} -> [setConfigLocal mempty ("request.spec", jsonDbS)]
|
TargetProc{tpIsRootSpec=True} -> [setConfigLocal mempty ("request.spec", jsonDbS)]
|
||||||
_ -> mempty
|
_ -> mempty
|
||||||
-- | Do a pg set_config(setting, value, true) call. This is equivalent to a SET LOCAL.
|
usesLegacyGucs = configDbUseLegacyGucs conf && actualPgVersion < pgVersion140
|
||||||
setConfigLocal :: ByteString -> (ByteString, ByteString) -> H.Snippet
|
|
||||||
setConfigLocal prefix (k, v) =
|
|
||||||
"set_config(" <> unknownEncoder (prefix <> k) <> ", " <> unknownEncoder v <> ", true)"
|
|
||||||
|
|
||||||
-- | Log in apache format. Only requests that have a status greater than minStatus are logged.
|
-- | 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.
|
-- | 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.
|
||||||
@@ -181,3 +188,18 @@ optionalRollback AppConfig{..} ApiRequest{..} transaction = do
|
|||||||
[(HTTP.hPreferenceApplied, BS.pack (show Rollback))]
|
[(HTTP.hPreferenceApplied, BS.pack (show Rollback))]
|
||||||
| otherwise =
|
| otherwise =
|
||||||
identity
|
identity
|
||||||
|
|
||||||
|
-- | Do a pg set_config(setting, value, true) call. This is equivalent to a SET LOCAL.
|
||||||
|
setConfigLocal :: ByteString -> (ByteString, ByteString) -> H.Snippet
|
||||||
|
setConfigLocal prefix (k, v) =
|
||||||
|
"set_config(" <> unknownEncoder (prefix <> k) <> ", " <> unknownEncoder v <> ", true)"
|
||||||
|
|
||||||
|
-- | Starting from PostgreSQL v14, some characters are not allowed for config names (mostly affecting headers with "-").
|
||||||
|
-- | A JSON format string is used to avoid this problem. See https://github.com/PostgREST/postgrest/issues/1857
|
||||||
|
setConfigLocalJson :: ByteString -> [(ByteString, ByteString)] -> [H.Snippet]
|
||||||
|
setConfigLocalJson prefix keyVals = [setConfigLocal mempty (prefix, gucJsonVal keyVals)]
|
||||||
|
where
|
||||||
|
gucJsonVal :: [(ByteString, ByteString)] -> ByteString
|
||||||
|
gucJsonVal = BSL.toStrict . JSON.encode . M.fromList . arrayByteStringToText
|
||||||
|
arrayByteStringToText :: [(ByteString, ByteString)] -> [(Text,Text)]
|
||||||
|
arrayByteStringToText keyVal = (toS *** toS) <$> keyVal
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
module Feature.LegacyGucsSpec where
|
||||||
|
|
||||||
|
import Network.Wai (Application)
|
||||||
|
|
||||||
|
import Network.HTTP.Types
|
||||||
|
import Test.Hspec hiding (pendingWith)
|
||||||
|
import Test.Hspec.Wai
|
||||||
|
import Test.Hspec.Wai.JSON
|
||||||
|
|
||||||
|
import Protolude hiding (get)
|
||||||
|
import SpecHelper
|
||||||
|
|
||||||
|
spec :: SpecWith ((), Application)
|
||||||
|
spec =
|
||||||
|
describe "remote procedure call with legacy gucs disabled" $ do
|
||||||
|
it "custom header is set" $
|
||||||
|
request methodPost "/rpc/get_guc_value" [("Custom-Header", "test")]
|
||||||
|
[json| { "prefix": "request.headers", "name": "custom-header" } |]
|
||||||
|
`shouldRespondWith`
|
||||||
|
[json|"test"|]
|
||||||
|
{ matchStatus = 200
|
||||||
|
, matchHeaders = [ matchContentTypeJson ]
|
||||||
|
}
|
||||||
|
|
||||||
|
it "standard header is set" $
|
||||||
|
request methodPost "/rpc/get_guc_value" [("Origin", "http://example.com")]
|
||||||
|
[json| { "prefix": "request.headers", "name": "origin" } |]
|
||||||
|
`shouldRespondWith`
|
||||||
|
[json|"http://example.com"|]
|
||||||
|
{ matchStatus = 200
|
||||||
|
, matchHeaders = [ matchContentTypeJson ]
|
||||||
|
}
|
||||||
|
|
||||||
|
it "current role is available as GUC claim" $
|
||||||
|
request methodPost "/rpc/get_guc_value" []
|
||||||
|
[json| { "prefix": "request.jwt.claims", "name": "role" } |]
|
||||||
|
`shouldRespondWith`
|
||||||
|
[json|"postgrest_test_anonymous"|]
|
||||||
|
{ matchStatus = 200
|
||||||
|
, matchHeaders = [ matchContentTypeJson ]
|
||||||
|
}
|
||||||
|
|
||||||
|
it "single cookie ends up as claims" $
|
||||||
|
request methodPost "/rpc/get_guc_value" [("Cookie","acookie=cookievalue")]
|
||||||
|
[json| {"prefix": "request.cookies", "name":"acookie"} |]
|
||||||
|
`shouldRespondWith`
|
||||||
|
[json|"cookievalue"|]
|
||||||
|
{ matchStatus = 200
|
||||||
|
, matchHeaders = []
|
||||||
|
}
|
||||||
|
|
||||||
|
it "multiple cookies ends up as claims" $
|
||||||
|
request methodPost "/rpc/get_guc_value" [("Cookie","acookie=cookievalue;secondcookie=anothervalue")]
|
||||||
|
[json| {"prefix": "request.cookies", "name":"secondcookie"} |]
|
||||||
|
`shouldRespondWith`
|
||||||
|
[json|"anothervalue"|]
|
||||||
|
{ matchStatus = 200
|
||||||
|
, matchHeaders = []
|
||||||
|
}
|
||||||
|
|
||||||
|
it "gets the Authorization value" $
|
||||||
|
request methodPost "/rpc/get_guc_value" [authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.Xod-F15qsGL0WhdOCr2j3DdKuTw9QJERVgoFD3vGaWA"]
|
||||||
|
[json| {"prefix": "request.headers", "name":"authorization"} |]
|
||||||
|
`shouldRespondWith`
|
||||||
|
[json|"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.Xod-F15qsGL0WhdOCr2j3DdKuTw9QJERVgoFD3vGaWA"|]
|
||||||
|
{ matchStatus = 200
|
||||||
|
, matchHeaders = []
|
||||||
|
}
|
||||||
+37
-7
@@ -15,7 +15,7 @@ import Text.Heredoc
|
|||||||
import PostgREST.Config.PgVersion (PgVersion, pgVersion100,
|
import PostgREST.Config.PgVersion (PgVersion, pgVersion100,
|
||||||
pgVersion109, pgVersion110,
|
pgVersion109, pgVersion110,
|
||||||
pgVersion112, pgVersion114,
|
pgVersion112, pgVersion114,
|
||||||
pgVersion96)
|
pgVersion140, pgVersion96)
|
||||||
|
|
||||||
import Protolude hiding (get)
|
import Protolude hiding (get)
|
||||||
import SpecHelper
|
import SpecHelper
|
||||||
@@ -798,7 +798,12 @@ spec actualPgVersion =
|
|||||||
it "custom header is set" $
|
it "custom header is set" $
|
||||||
request methodPost "/rpc/get_guc_value"
|
request methodPost "/rpc/get_guc_value"
|
||||||
[("Custom-Header", "test")]
|
[("Custom-Header", "test")]
|
||||||
[json| { "name": "request.header.custom-header" } |]
|
(
|
||||||
|
if actualPgVersion >= pgVersion140 then
|
||||||
|
[json| { "prefix": "request.headers", "name": "custom-header" } |]
|
||||||
|
else
|
||||||
|
[json| { "name": "request.header.custom-header" } |]
|
||||||
|
)
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|"test"|]
|
[json|"test"|]
|
||||||
{ matchStatus = 200
|
{ matchStatus = 200
|
||||||
@@ -807,7 +812,12 @@ spec actualPgVersion =
|
|||||||
it "standard header is set" $
|
it "standard header is set" $
|
||||||
request methodPost "/rpc/get_guc_value"
|
request methodPost "/rpc/get_guc_value"
|
||||||
[("Origin", "http://example.com")]
|
[("Origin", "http://example.com")]
|
||||||
[json| { "name": "request.header.origin" } |]
|
(
|
||||||
|
if actualPgVersion >= pgVersion140 then
|
||||||
|
[json| { "prefix": "request.headers", "name": "origin" } |]
|
||||||
|
else
|
||||||
|
[json| { "name": "request.header.origin" } |]
|
||||||
|
)
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|"http://example.com"|]
|
[json|"http://example.com"|]
|
||||||
{ matchStatus = 200
|
{ matchStatus = 200
|
||||||
@@ -815,7 +825,12 @@ spec actualPgVersion =
|
|||||||
}
|
}
|
||||||
it "current role is available as GUC claim" $
|
it "current role is available as GUC claim" $
|
||||||
request methodPost "/rpc/get_guc_value" []
|
request methodPost "/rpc/get_guc_value" []
|
||||||
[json| { "name": "request.jwt.claim.role" } |]
|
(
|
||||||
|
if actualPgVersion >= pgVersion140 then
|
||||||
|
[json| { "prefix": "request.jwt.claims", "name": "role" } |]
|
||||||
|
else
|
||||||
|
[json| { "name": "request.jwt.claim.role" } |]
|
||||||
|
)
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|"postgrest_test_anonymous"|]
|
[json|"postgrest_test_anonymous"|]
|
||||||
{ matchStatus = 200
|
{ matchStatus = 200
|
||||||
@@ -823,7 +838,12 @@ spec actualPgVersion =
|
|||||||
}
|
}
|
||||||
it "single cookie ends up as claims" $
|
it "single cookie ends up as claims" $
|
||||||
request methodPost "/rpc/get_guc_value" [("Cookie","acookie=cookievalue")]
|
request methodPost "/rpc/get_guc_value" [("Cookie","acookie=cookievalue")]
|
||||||
[json| {"name":"request.cookie.acookie"} |]
|
(
|
||||||
|
if actualPgVersion >= pgVersion140 then
|
||||||
|
[json| {"prefix": "request.cookies", "name":"acookie"} |]
|
||||||
|
else
|
||||||
|
[json| {"name":"request.cookie.acookie"} |]
|
||||||
|
)
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|"cookievalue"|]
|
[json|"cookievalue"|]
|
||||||
{ matchStatus = 200
|
{ matchStatus = 200
|
||||||
@@ -831,7 +851,12 @@ spec actualPgVersion =
|
|||||||
}
|
}
|
||||||
it "multiple cookies ends up as claims" $
|
it "multiple cookies ends up as claims" $
|
||||||
request methodPost "/rpc/get_guc_value" [("Cookie","acookie=cookievalue;secondcookie=anothervalue")]
|
request methodPost "/rpc/get_guc_value" [("Cookie","acookie=cookievalue;secondcookie=anothervalue")]
|
||||||
[json| {"name":"request.cookie.secondcookie"} |]
|
(
|
||||||
|
if actualPgVersion >= pgVersion140 then
|
||||||
|
[json| {"prefix": "request.cookies", "name":"secondcookie"} |]
|
||||||
|
else
|
||||||
|
[json| {"name":"request.cookie.secondcookie"} |]
|
||||||
|
)
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|"anothervalue"|]
|
[json|"anothervalue"|]
|
||||||
{ matchStatus = 200
|
{ matchStatus = 200
|
||||||
@@ -847,7 +872,12 @@ spec actualPgVersion =
|
|||||||
}
|
}
|
||||||
it "gets the Authorization value" $
|
it "gets the Authorization value" $
|
||||||
request methodPost "/rpc/get_guc_value" [authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.Xod-F15qsGL0WhdOCr2j3DdKuTw9QJERVgoFD3vGaWA"]
|
request methodPost "/rpc/get_guc_value" [authHeaderJWT "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.Xod-F15qsGL0WhdOCr2j3DdKuTw9QJERVgoFD3vGaWA"]
|
||||||
[json| {"name":"request.header.authorization"} |]
|
(
|
||||||
|
if actualPgVersion >= pgVersion140 then
|
||||||
|
[json| {"prefix": "request.headers", "name":"authorization"} |]
|
||||||
|
else
|
||||||
|
[json| {"name":"request.header.authorization"} |]
|
||||||
|
)
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.Xod-F15qsGL0WhdOCr2j3DdKuTw9QJERVgoFD3vGaWA"|]
|
[json|"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.Xod-F15qsGL0WhdOCr2j3DdKuTw9QJERVgoFD3vGaWA"|]
|
||||||
{ matchStatus = 200
|
{ matchStatus = 200
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import qualified Feature.HtmlRawOutputSpec
|
|||||||
import qualified Feature.IgnorePrivOpenApiSpec
|
import qualified Feature.IgnorePrivOpenApiSpec
|
||||||
import qualified Feature.InsertSpec
|
import qualified Feature.InsertSpec
|
||||||
import qualified Feature.JsonOperatorSpec
|
import qualified Feature.JsonOperatorSpec
|
||||||
|
import qualified Feature.LegacyGucsSpec
|
||||||
import qualified Feature.MultipleSchemaSpec
|
import qualified Feature.MultipleSchemaSpec
|
||||||
import qualified Feature.NoJwtSpec
|
import qualified Feature.NoJwtSpec
|
||||||
import qualified Feature.NonexistentSchemaSpec
|
import qualified Feature.NonexistentSchemaSpec
|
||||||
@@ -88,6 +89,7 @@ main = do
|
|||||||
(configDbSchemas config)
|
(configDbSchemas config)
|
||||||
(configDbExtraSearchPath config)
|
(configDbExtraSearchPath config)
|
||||||
appState <- AppState.initWithPool pool config
|
appState <- AppState.initWithPool pool config
|
||||||
|
AppState.putPgVersion appState actualPgVersion
|
||||||
AppState.putDbStructure appState customDbStructure
|
AppState.putDbStructure appState customDbStructure
|
||||||
when (isJust $ configDbRootSpec config) $
|
when (isJust $ configDbRootSpec config) $
|
||||||
AppState.putJsonDbS appState $ toS $ JSON.encode baseDbStructure
|
AppState.putJsonDbS appState $ toS $ JSON.encode baseDbStructure
|
||||||
@@ -108,6 +110,7 @@ main = do
|
|||||||
responseHeadersApp = app testCfgResponseHeaders
|
responseHeadersApp = app testCfgResponseHeaders
|
||||||
disallowRollbackApp = app testCfgDisallowRollback
|
disallowRollbackApp = app testCfgDisallowRollback
|
||||||
forceRollbackApp = app testCfgForceRollback
|
forceRollbackApp = app testCfgForceRollback
|
||||||
|
testCfgLegacyGucsApp = app testCfgLegacyGucs
|
||||||
|
|
||||||
extraSearchPathApp = appDbs testCfgExtraSearchPath
|
extraSearchPathApp = appDbs testCfgExtraSearchPath
|
||||||
unicodeApp = appDbs testUnicodeCfg
|
unicodeApp = appDbs testUnicodeCfg
|
||||||
@@ -210,6 +213,10 @@ main = do
|
|||||||
parallel $ before multipleSchemaApp $
|
parallel $ before multipleSchemaApp $
|
||||||
describe "Feature.MultipleSchemaSpec" $ Feature.MultipleSchemaSpec.spec actualPgVersion
|
describe "Feature.MultipleSchemaSpec" $ Feature.MultipleSchemaSpec.spec actualPgVersion
|
||||||
|
|
||||||
|
-- this test runs with db-uses-legacy-gucs = false
|
||||||
|
parallel $ before testCfgLegacyGucsApp $
|
||||||
|
describe "Feature.LegacyGucsSpec" Feature.LegacyGucsSpec.spec
|
||||||
|
|
||||||
-- this test runs with db-embed-default-join = inner
|
-- this test runs with db-embed-default-join = inner
|
||||||
before embedInnerJoinApp $
|
before embedInnerJoinApp $
|
||||||
describe "Feature.EmbedInnerJoinSpecNotDefaultConfig" Feature.EmbedInnerJoinSpec.notDefaultConfig
|
describe "Feature.EmbedInnerJoinSpecNotDefaultConfig" Feature.EmbedInnerJoinSpec.notDefaultConfig
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ _baseCfg = let secret = Just $ encodeUtf8 "reallyreallyreallyreallyverysafe" in
|
|||||||
, configDbConfig = False
|
, configDbConfig = False
|
||||||
, configDbUri = mempty
|
, configDbUri = mempty
|
||||||
, configDbEmbedDefaultJoin = JTLeft
|
, configDbEmbedDefaultJoin = JTLeft
|
||||||
|
, configDbUseLegacyGucs = True
|
||||||
, configFilePath = Nothing
|
, configFilePath = Nothing
|
||||||
, configJWKS = parseSecret <$> secret
|
, configJWKS = parseSecret <$> secret
|
||||||
, configJwtAudience = Nothing
|
, configJwtAudience = Nothing
|
||||||
@@ -190,6 +191,9 @@ testCfgResponseHeaders testDbConn = (testCfg testDbConn) { configDbPreRequest =
|
|||||||
testMultipleSchemaCfg :: Text -> AppConfig
|
testMultipleSchemaCfg :: Text -> AppConfig
|
||||||
testMultipleSchemaCfg testDbConn = (testCfg testDbConn) { configDbSchemas = fromList ["v1", "v2"] }
|
testMultipleSchemaCfg testDbConn = (testCfg testDbConn) { configDbSchemas = fromList ["v1", "v2"] }
|
||||||
|
|
||||||
|
testCfgLegacyGucs :: Text -> AppConfig
|
||||||
|
testCfgLegacyGucs testDbConn = (testCfg testDbConn) { configDbUseLegacyGucs = False }
|
||||||
|
|
||||||
resetDb :: Text -> IO ()
|
resetDb :: Text -> IO ()
|
||||||
resetDb dbConn = loadFixture dbConn "data"
|
resetDb dbConn = loadFixture dbConn "data"
|
||||||
|
|
||||||
|
|||||||
Vendored
+52
-15
@@ -82,7 +82,10 @@ CREATE FUNCTION set_authors_only_owner() RETURNS trigger
|
|||||||
LANGUAGE plpgsql
|
LANGUAGE plpgsql
|
||||||
AS $$
|
AS $$
|
||||||
begin
|
begin
|
||||||
NEW.owner = current_setting('request.jwt.claim.id');
|
NEW.owner = case when current_setting('server_version_num')::int >= 140000
|
||||||
|
then current_setting('request.jwt.claims')::json->>'id'
|
||||||
|
else current_setting('request.jwt.claim.id')
|
||||||
|
end;
|
||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
end
|
end
|
||||||
$$;
|
$$;
|
||||||
@@ -301,7 +304,10 @@ CREATE OR REPLACE FUNCTION switch_role() RETURNS void
|
|||||||
declare
|
declare
|
||||||
user_id text;
|
user_id text;
|
||||||
Begin
|
Begin
|
||||||
user_id = current_setting('request.jwt.claim.id')::text;
|
user_id = case when current_setting('server_version_num')::int >= 140000
|
||||||
|
then (current_setting('request.jwt.claims')::json->>'id')::text
|
||||||
|
else current_setting('request.jwt.claim.id')::text
|
||||||
|
end;
|
||||||
if user_id = '1'::text then
|
if user_id = '1'::text then
|
||||||
execute 'set local role postgrest_test_author';
|
execute 'set local role postgrest_test_author';
|
||||||
elseif user_id = '2'::text then
|
elseif user_id = '2'::text then
|
||||||
@@ -329,18 +335,33 @@ CREATE FUNCTION reveal_big_jwt() RETURNS TABLE (
|
|||||||
iss text, sub text, exp bigint,
|
iss text, sub text, exp bigint,
|
||||||
nbf bigint, iat bigint, jti text, "http://postgrest.com/foo" boolean
|
nbf bigint, iat bigint, jti text, "http://postgrest.com/foo" boolean
|
||||||
)
|
)
|
||||||
LANGUAGE sql SECURITY DEFINER
|
LANGUAGE plpgsql SECURITY DEFINER
|
||||||
STABLE
|
STABLE
|
||||||
AS $$
|
AS $$
|
||||||
SELECT current_setting('request.jwt.claim.iss') as iss,
|
BEGIN
|
||||||
current_setting('request.jwt.claim.sub') as sub,
|
-- JWT claims are set in JSON format since v14
|
||||||
current_setting('request.jwt.claim.exp')::bigint as exp,
|
IF (current_setting('server_version_num')::INT >= 140000) THEN
|
||||||
current_setting('request.jwt.claim.nbf')::bigint as nbf,
|
RETURN QUERY
|
||||||
current_setting('request.jwt.claim.iat')::bigint as iat,
|
SELECT current_setting('request.jwt.claims')::json->>'iss' as iss,
|
||||||
current_setting('request.jwt.claim.jti') as jti,
|
current_setting('request.jwt.claims')::json->>'sub' as sub,
|
||||||
-- role is not included in the claims list
|
(current_setting('request.jwt.claims')::json->>'exp')::bigint as exp,
|
||||||
current_setting('request.jwt.claim.http://postgrest.com/foo')::boolean
|
(current_setting('request.jwt.claims')::json->>'nbf')::bigint as nbf,
|
||||||
as "http://postgrest.com/foo";
|
(current_setting('request.jwt.claims')::json->>'iat')::bigint as iat,
|
||||||
|
current_setting('request.jwt.claims')::json->>'jti' as jti,
|
||||||
|
(current_setting('request.jwt.claims')::json->>'http://postgrest.com/foo')::boolean
|
||||||
|
as "http://postgrest.com/foo";
|
||||||
|
ELSE
|
||||||
|
RETURN QUERY
|
||||||
|
SELECT current_setting('request.jwt.claim.iss') as iss,
|
||||||
|
current_setting('request.jwt.claim.sub') as sub,
|
||||||
|
current_setting('request.jwt.claim.exp')::bigint as exp,
|
||||||
|
current_setting('request.jwt.claim.nbf')::bigint as nbf,
|
||||||
|
current_setting('request.jwt.claim.iat')::bigint as iat,
|
||||||
|
current_setting('request.jwt.claim.jti') as jti,
|
||||||
|
current_setting('request.jwt.claim.http://postgrest.com/foo')::boolean
|
||||||
|
as "http://postgrest.com/foo";
|
||||||
|
END IF;
|
||||||
|
END;
|
||||||
$$;
|
$$;
|
||||||
|
|
||||||
|
|
||||||
@@ -1093,6 +1114,11 @@ create function test.get_guc_value(name text) returns text as $$
|
|||||||
select nullif(current_setting(name), '')::text;
|
select nullif(current_setting(name), '')::text;
|
||||||
$$ language sql;
|
$$ language sql;
|
||||||
|
|
||||||
|
-- Get the GUC values for Postgres v14.0 and up
|
||||||
|
create function test.get_guc_value(prefix text, name text) returns text as $$
|
||||||
|
select nullif(current_setting(prefix)::json->>name, '')::text;
|
||||||
|
$$ language sql;
|
||||||
|
|
||||||
create table w_or_wo_comma_names ( name text );
|
create table w_or_wo_comma_names ( name text );
|
||||||
|
|
||||||
create table items_with_different_col_types (
|
create table items_with_different_col_types (
|
||||||
@@ -1784,8 +1810,13 @@ openapi json = $$
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$$;
|
$$;
|
||||||
|
accept text;
|
||||||
begin
|
begin
|
||||||
case current_setting('request.header.accept', true)
|
accept = case when current_setting('server_version_num')::int >= 140000
|
||||||
|
then current_setting('request.headers', true)::json->>'accept'
|
||||||
|
else current_setting('request.header.accept', true)
|
||||||
|
end;
|
||||||
|
case accept
|
||||||
when 'application/openapi+json' then
|
when 'application/openapi+json' then
|
||||||
return openapi;
|
return openapi;
|
||||||
when 'application/json' then
|
when 'application/json' then
|
||||||
@@ -1958,9 +1989,15 @@ add constraint snd_shift foreign key (snd_shift_activity_id, snd_shift
|
|||||||
-- for a pre-request function
|
-- for a pre-request function
|
||||||
create or replace function custom_headers() returns void as $$
|
create or replace function custom_headers() returns void as $$
|
||||||
declare
|
declare
|
||||||
user_agent text := current_setting('request.header.user-agent', true);
|
user_agent text := case when current_setting('server_version_num')::int >= 140000
|
||||||
|
then current_setting('request.headers', true)::json->>'user-agent'
|
||||||
|
else current_setting('request.header.user-agent', true)
|
||||||
|
end;
|
||||||
req_path text := current_setting('request.path', true);
|
req_path text := current_setting('request.path', true);
|
||||||
req_accept text := current_setting('request.header.accept', true);
|
req_accept text := case when current_setting('server_version_num')::int >= 140000
|
||||||
|
then current_setting('request.headers', true)::json->>'accept'
|
||||||
|
else current_setting('request.header.accept', true)
|
||||||
|
end;
|
||||||
req_method text := current_setting('request.method', true);
|
req_method text := current_setting('request.method', true);
|
||||||
begin
|
begin
|
||||||
if user_agent similar to 'MSIE (6.0|7.0)' then
|
if user_agent similar to 'MSIE (6.0|7.0)' then
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ db-config = "false"
|
|||||||
db-tx-end = "commit"
|
db-tx-end = "commit"
|
||||||
db-uri = "required"
|
db-uri = "required"
|
||||||
db-embed-default-join = "left"
|
db-embed-default-join = "left"
|
||||||
|
db-use-legacy-gucs = true
|
||||||
jwt-aud = ""
|
jwt-aud = ""
|
||||||
jwt-role-claim-key = ".\"aliased\""
|
jwt-role-claim-key = ".\"aliased\""
|
||||||
jwt-secret = ""
|
jwt-secret = ""
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ db-config = "false"
|
|||||||
db-tx-end = "commit"
|
db-tx-end = "commit"
|
||||||
db-uri = "required"
|
db-uri = "required"
|
||||||
db-embed-default-join = "left"
|
db-embed-default-join = "left"
|
||||||
|
db-use-legacy-gucs = true
|
||||||
jwt-aud = ""
|
jwt-aud = ""
|
||||||
jwt-role-claim-key = ".\"role\""
|
jwt-role-claim-key = ".\"role\""
|
||||||
jwt-secret = ""
|
jwt-secret = ""
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ db-config = "false"
|
|||||||
db-tx-end = "commit"
|
db-tx-end = "commit"
|
||||||
db-uri = "required"
|
db-uri = "required"
|
||||||
db-embed-default-join = "left"
|
db-embed-default-join = "left"
|
||||||
|
db-use-legacy-gucs = true
|
||||||
jwt-aud = ""
|
jwt-aud = ""
|
||||||
jwt-role-claim-key = ".\"role\""
|
jwt-role-claim-key = ".\"role\""
|
||||||
jwt-secret = ""
|
jwt-secret = ""
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ db-config = "false"
|
|||||||
db-tx-end = "commit"
|
db-tx-end = "commit"
|
||||||
db-uri = "required"
|
db-uri = "required"
|
||||||
db-embed-default-join = "left"
|
db-embed-default-join = "left"
|
||||||
|
db-use-legacy-gucs = true
|
||||||
jwt-aud = ""
|
jwt-aud = ""
|
||||||
jwt-role-claim-key = ".\"role\""
|
jwt-role-claim-key = ".\"role\""
|
||||||
jwt-secret = ""
|
jwt-secret = ""
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ db-config = "true"
|
|||||||
db-tx-end = "rollback-allow-override"
|
db-tx-end = "rollback-allow-override"
|
||||||
db-uri = "<REPLACED_WITH_DB_URI>"
|
db-uri = "<REPLACED_WITH_DB_URI>"
|
||||||
db-embed-default-join = "inner"
|
db-embed-default-join = "inner"
|
||||||
|
db-use-legacy-gucs = false
|
||||||
jwt-aud = "https://otherexample.org"
|
jwt-aud = "https://otherexample.org"
|
||||||
jwt-role-claim-key = ".\"other\".\"role\""
|
jwt-role-claim-key = ".\"other\".\"role\""
|
||||||
jwt-secret = "ODERREALLYREALLYREALLYREALLYVERYSAFE"
|
jwt-secret = "ODERREALLYREALLYREALLYREALLYVERYSAFE"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ db-config = "true"
|
|||||||
db-tx-end = "commit-allow-override"
|
db-tx-end = "commit-allow-override"
|
||||||
db-uri = "<REPLACED_WITH_DB_URI>"
|
db-uri = "<REPLACED_WITH_DB_URI>"
|
||||||
db-embed-default-join = "inner"
|
db-embed-default-join = "inner"
|
||||||
|
db-use-legacy-gucs = false
|
||||||
jwt-aud = "https://example.org"
|
jwt-aud = "https://example.org"
|
||||||
jwt-role-claim-key = ".\"a\".\"role\""
|
jwt-role-claim-key = ".\"a\".\"role\""
|
||||||
jwt-secret = "OVERRIDEREALLYREALLYREALLYREALLYVERYSAFE"
|
jwt-secret = "OVERRIDEREALLYREALLYREALLYREALLYVERYSAFE"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ db-config = "false"
|
|||||||
db-tx-end = "rollback-allow-override"
|
db-tx-end = "rollback-allow-override"
|
||||||
db-uri = "tmp_db"
|
db-uri = "tmp_db"
|
||||||
db-embed-default-join = "inner"
|
db-embed-default-join = "inner"
|
||||||
|
db-use-legacy-gucs = false
|
||||||
jwt-aud = "https://postgrest.org"
|
jwt-aud = "https://postgrest.org"
|
||||||
jwt-role-claim-key = ".\"user\"[0].\"real-role\""
|
jwt-role-claim-key = ".\"user\"[0].\"real-role\""
|
||||||
jwt-secret = "c2VjdXJpdHl0aHJvdWdob2JzY3VyaXR5"
|
jwt-secret = "c2VjdXJpdHl0aHJvdWdob2JzY3VyaXR5"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ db-config = "true"
|
|||||||
db-tx-end = "commit"
|
db-tx-end = "commit"
|
||||||
db-uri = "required"
|
db-uri = "required"
|
||||||
db-embed-default-join = "left"
|
db-embed-default-join = "left"
|
||||||
|
db-use-legacy-gucs = true
|
||||||
jwt-aud = ""
|
jwt-aud = ""
|
||||||
jwt-role-claim-key = ".\"role\""
|
jwt-role-claim-key = ".\"role\""
|
||||||
jwt-secret = ""
|
jwt-secret = ""
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ PGRST_DB_CONFIG: false
|
|||||||
PGRST_DB_TX_END: rollback-allow-override
|
PGRST_DB_TX_END: rollback-allow-override
|
||||||
PGRST_DB_URI: tmp_db
|
PGRST_DB_URI: tmp_db
|
||||||
PGRST_DB_EMBED_DEFAULT_JOIN: inner
|
PGRST_DB_EMBED_DEFAULT_JOIN: inner
|
||||||
|
PGRST_DB_USE_LEGACY_GUCS: false
|
||||||
PGRST_JWT_AUD: 'https://postgrest.org'
|
PGRST_JWT_AUD: 'https://postgrest.org'
|
||||||
PGRST_JWT_ROLE_CLAIM_KEY: '.user[0]."real-role"'
|
PGRST_JWT_ROLE_CLAIM_KEY: '.user[0]."real-role"'
|
||||||
PGRST_JWT_SECRET: c2VjdXJpdHl0aHJvdWdob2JzY3VyaXR5
|
PGRST_JWT_SECRET: c2VjdXJpdHl0aHJvdWdob2JzY3VyaXR5
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ db-config = "false"
|
|||||||
db-tx-end = "rollback-allow-override"
|
db-tx-end = "rollback-allow-override"
|
||||||
db-uri = "tmp_db"
|
db-uri = "tmp_db"
|
||||||
db-embed-default-join = "inner"
|
db-embed-default-join = "inner"
|
||||||
|
db-use-legacy-gucs = false
|
||||||
jwt-aud = "https://postgrest.org"
|
jwt-aud = "https://postgrest.org"
|
||||||
jwt-role-claim-key = ".user[0].\"real-role\""
|
jwt-role-claim-key = ".user[0].\"real-role\""
|
||||||
jwt-secret = "c2VjdXJpdHl0aHJvdWdob2JzY3VyaXR5"
|
jwt-secret = "c2VjdXJpdHl0aHJvdWdob2JzY3VyaXR5"
|
||||||
|
|||||||
Reference in New Issue
Block a user