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:
laurenceisla
2021-10-12 12:58:52 -05:00
committed by GitHub
parent ee56dd5db1
commit 627c3c34b7
27 changed files with 250 additions and 34 deletions
+68
View File
@@ -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
View File
@@ -15,7 +15,7 @@ import Text.Heredoc
import PostgREST.Config.PgVersion (PgVersion, pgVersion100,
pgVersion109, pgVersion110,
pgVersion112, pgVersion114,
pgVersion96)
pgVersion140, pgVersion96)
import Protolude hiding (get)
import SpecHelper
@@ -798,7 +798,12 @@ spec actualPgVersion =
it "custom header is set" $
request methodPost "/rpc/get_guc_value"
[("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`
[json|"test"|]
{ matchStatus = 200
@@ -807,7 +812,12 @@ spec actualPgVersion =
it "standard header is set" $
request methodPost "/rpc/get_guc_value"
[("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`
[json|"http://example.com"|]
{ matchStatus = 200
@@ -815,7 +825,12 @@ spec actualPgVersion =
}
it "current role is available as GUC claim" $
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`
[json|"postgrest_test_anonymous"|]
{ matchStatus = 200
@@ -823,7 +838,12 @@ spec actualPgVersion =
}
it "single cookie ends up as claims" $
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`
[json|"cookievalue"|]
{ matchStatus = 200
@@ -831,7 +851,12 @@ spec actualPgVersion =
}
it "multiple cookies ends up as claims" $
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`
[json|"anothervalue"|]
{ matchStatus = 200
@@ -847,7 +872,12 @@ spec actualPgVersion =
}
it "gets the Authorization value" $
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`
[json|"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicG9zdGdyZXN0X3Rlc3RfYXV0aG9yIn0.Xod-F15qsGL0WhdOCr2j3DdKuTw9QJERVgoFD3vGaWA"|]
{ matchStatus = 200