Revert "add: string slicing operator for jwt-role-claim-key"
This reverts commit fe0386e9c4.
As discussed in https://github.com/PostgREST/postgrest/pull/4984#issuecomment-4652725178.
This commit is contained in:
@@ -7,7 +7,6 @@ All notable changes to this project will be documented in this file. From versio
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Log error when `db-schemas` config contains schema `pg_catalog` or `information_schema` by @taimoorzaeem in #4359
|
- Log error when `db-schemas` config contains schema `pg_catalog` or `information_schema` by @taimoorzaeem in #4359
|
||||||
- Add string slicing operator for `jwt-role-claim-key` by @taimoorzaeem in #4599
|
|
||||||
- Optimize requests with `Prefer: count=exact` that do not use ranges or `db-max-rows` by @laurenceisla in #3957
|
- Optimize requests with `Prefer: count=exact` that do not use ranges or `db-max-rows` by @laurenceisla in #3957
|
||||||
+ Removed unnecessary double count when building the `Content-Range`.
|
+ Removed unnecessary double count when building the `Content-Range`.
|
||||||
- Add config `client-error-verbosity` to customize error verbosity by @taimoorzaeem in #4088, #3980, #3824
|
- Add config `client-error-verbosity` to customize error verbosity by @taimoorzaeem in #4088, #3980, #3824
|
||||||
|
|||||||
@@ -234,17 +234,6 @@ The DSL follows the `JSONPath <https://goessner.net/articles/JsonPath/>`_ expres
|
|||||||
- ``==^`` selects the first array element that ends with the right operand
|
- ``==^`` selects the first array element that ends with the right operand
|
||||||
- ``*==`` selects the first array element that contains the right operand
|
- ``*==`` selects the first array element that contains the right operand
|
||||||
|
|
||||||
The selected role value can also be sliced using the slice operator ``[a:b]``. It is similar to `slice operator in python <https://docs.python.org/3/library/functions.html#slice>`_. Negative index values are also supported. The syntax is as:
|
|
||||||
|
|
||||||
- ``[a:b]`` take slice from index ``a`` up to ``b``
|
|
||||||
- ``[a:]`` take slice from index ``a`` to end
|
|
||||||
- ``[:b]`` take slice from start to index ``b``
|
|
||||||
- ``[:]`` select everything, no slicing
|
|
||||||
|
|
||||||
.. important::
|
|
||||||
|
|
||||||
Make sure that you are not taking a slice where the start index comes after the end index like ``[11:2]``. The result of this would be empty string and so no role would get selected.
|
|
||||||
|
|
||||||
Usage examples:
|
Usage examples:
|
||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
@@ -266,11 +255,6 @@ Usage examples:
|
|||||||
jwt-role-claim-key = ".postgrest.roles[?(@ ==^ \"hor\")]"
|
jwt-role-claim-key = ".postgrest.roles[?(@ ==^ \"hor\")]"
|
||||||
jwt-role-claim-key = ".postgrest.roles[?(@ *== \"utho\")]"
|
jwt-role-claim-key = ".postgrest.roles[?(@ *== \"utho\")]"
|
||||||
|
|
||||||
# {"postgrest":{"wlcg": ["/groupa", "/groupb/"]}}
|
|
||||||
# skip the "/" character using slice operator
|
|
||||||
jwt-role-claim-key = ".postgrest.wlcg[0][1:]"
|
|
||||||
jwt-role-claim-key = ".postgrest.wlcg[1][1:-1]"
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
The string comparison operators are implemented as a custom extension to the JSPath and does not strictly follow the `RFC 9535 <https://www.rfc-editor.org/rfc/rfc9535.html>`_.
|
The string comparison operators are implemented as a custom extension to the JSPath and does not strictly follow the `RFC 9535 <https://www.rfc-editor.org/rfc/rfc9535.html>`_.
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ type JSPath = [JSPathExp]
|
|||||||
data JSPathExp
|
data JSPathExp
|
||||||
= JSPKey Text -- .property or ."property-dash"
|
= JSPKey Text -- .property or ."property-dash"
|
||||||
| JSPIdx Int -- [0]
|
| JSPIdx Int -- [0]
|
||||||
| JSPSlice (Maybe Int) (Maybe Int) -- [0:5] or [0:] or [:5] or [:]
|
|
||||||
| JSPFilter FilterExp -- [?(@ == "match")]
|
| JSPFilter FilterExp -- [?(@ == "match")]
|
||||||
|
|
||||||
data FilterExp
|
data FilterExp
|
||||||
@@ -45,7 +44,6 @@ dumpJSPath :: JSPathExp -> Text
|
|||||||
-- TODO: this needs to be quoted properly for special chars
|
-- TODO: this needs to be quoted properly for special chars
|
||||||
dumpJSPath (JSPKey k) = "." <> show k
|
dumpJSPath (JSPKey k) = "." <> show k
|
||||||
dumpJSPath (JSPIdx i) = "[" <> show i <> "]"
|
dumpJSPath (JSPIdx i) = "[" <> show i <> "]"
|
||||||
dumpJSPath (JSPSlice s e) = "[" <> maybe "" show s <> ":" <> maybe "" show e <> "]"
|
|
||||||
dumpJSPath (JSPFilter cond) = "[?(@" <> expr <> ")]"
|
dumpJSPath (JSPFilter cond) = "[?(@" <> expr <> ")]"
|
||||||
where
|
where
|
||||||
expr =
|
expr =
|
||||||
@@ -61,25 +59,12 @@ walkJSPath :: Maybe JSON.Value -> JSPath -> Maybe JSON.Value
|
|||||||
walkJSPath x [] = x
|
walkJSPath x [] = x
|
||||||
walkJSPath (Just (JSON.Object o)) (JSPKey key:rest) = walkJSPath (KM.lookup (K.fromText key) o) rest
|
walkJSPath (Just (JSON.Object o)) (JSPKey key:rest) = walkJSPath (KM.lookup (K.fromText key) o) rest
|
||||||
walkJSPath (Just (JSON.Array ar)) (JSPIdx idx:rest) = walkJSPath (ar V.!? idx) rest
|
walkJSPath (Just (JSON.Array ar)) (JSPIdx idx:rest) = walkJSPath (ar V.!? idx) rest
|
||||||
walkJSPath (Just (JSON.String str)) (JSPSlice start end:rest) =
|
walkJSPath (Just (JSON.Array ar)) [JSPFilter jspFilter] = case jspFilter of
|
||||||
let
|
EqualsCond txt -> findFirstMatch (==) txt ar
|
||||||
len = T.length str
|
NotEqualsCond txt -> findFirstMatch (/=) txt ar
|
||||||
|
StartsWithCond txt -> findFirstMatch T.isPrefixOf txt ar
|
||||||
norm :: Maybe Int -> Maybe Int -- Normalize negative indices to positive
|
EndsWithCond txt -> findFirstMatch T.isSuffixOf txt ar
|
||||||
norm = fmap (\i -> max 0 $ min len $ if i < 0 then len + i else i)
|
ContainsCond txt -> findFirstMatch T.isInfixOf txt ar
|
||||||
|
|
||||||
s = fromMaybe 0 $ norm start -- normalized start index
|
|
||||||
e = fromMaybe len $ norm end -- normalized end index
|
|
||||||
slicedString = if s >= e then T.empty else T.take (e-s) $ T.drop s str
|
|
||||||
in
|
|
||||||
walkJSPath (Just $ JSON.String slicedString) rest
|
|
||||||
|
|
||||||
walkJSPath (Just (JSON.Array ar)) (JSPFilter jspFilter:rest) = case jspFilter of
|
|
||||||
EqualsCond txt -> walkJSPath (findFirstMatch (==) txt ar) rest
|
|
||||||
NotEqualsCond txt -> walkJSPath (findFirstMatch (/=) txt ar) rest
|
|
||||||
StartsWithCond txt -> walkJSPath (findFirstMatch T.isPrefixOf txt ar) rest
|
|
||||||
EndsWithCond txt -> walkJSPath (findFirstMatch T.isSuffixOf txt ar) rest
|
|
||||||
ContainsCond txt -> walkJSPath (findFirstMatch T.isInfixOf txt ar) rest
|
|
||||||
where
|
where
|
||||||
findFirstMatch matchWith pattern = find (\case
|
findFirstMatch matchWith pattern = find (\case
|
||||||
JSON.String txt -> pattern `matchWith` txt
|
JSON.String txt -> pattern `matchWith` txt
|
||||||
@@ -95,7 +80,7 @@ pJSPath :: P.Parser JSPath
|
|||||||
pJSPath = P.many1 pJSPathExp <* P.eof
|
pJSPath = P.many1 pJSPathExp <* P.eof
|
||||||
|
|
||||||
pJSPathExp :: P.Parser JSPathExp
|
pJSPathExp :: P.Parser JSPathExp
|
||||||
pJSPathExp = P.try pJSPKey <|> P.try pJSPFilter <|> P.try pJSPIdx <|> pJSPSlice
|
pJSPathExp = pJSPKey <|> pJSPFilter <|> pJSPIdx
|
||||||
|
|
||||||
pJSPKey :: P.Parser JSPathExp
|
pJSPKey :: P.Parser JSPathExp
|
||||||
pJSPKey = do
|
pJSPKey = do
|
||||||
@@ -110,25 +95,13 @@ pJSPIdx = do
|
|||||||
P.char ']'
|
P.char ']'
|
||||||
return (JSPIdx num) <?> "pJSPIdx: JSPath array index"
|
return (JSPIdx num) <?> "pJSPIdx: JSPath array index"
|
||||||
|
|
||||||
pJSPSlice :: P.Parser JSPathExp
|
|
||||||
pJSPSlice = do
|
|
||||||
P.char '['
|
|
||||||
startSign <- P.optionMaybe $ P.char '-'
|
|
||||||
startIndex <- P.optionMaybe (read <$> P.many1 P.digit)
|
|
||||||
P.char ':'
|
|
||||||
endSign <- P.optionMaybe $ P.char '-'
|
|
||||||
endIndex <- P.optionMaybe (read <$> P.many1 P.digit)
|
|
||||||
P.char ']'
|
|
||||||
let start' = if isJust startSign then ((-1) *) <$> startIndex else startIndex
|
|
||||||
end' = if isJust endSign then ((-1) *) <$> endIndex else endIndex
|
|
||||||
return (JSPSlice start' end') <?> "pJSPSlice: JSPath string slice"
|
|
||||||
|
|
||||||
pJSPFilter :: P.Parser JSPathExp
|
pJSPFilter :: P.Parser JSPathExp
|
||||||
pJSPFilter = do
|
pJSPFilter = do
|
||||||
P.try $ P.string "[?("
|
P.try $ P.string "[?("
|
||||||
condition <- pFilterConditionParser
|
condition <- pFilterConditionParser
|
||||||
P.char ')'
|
P.char ')'
|
||||||
P.char ']'
|
P.char ']'
|
||||||
|
P.eof -- this should be the last jspath expression
|
||||||
return (JSPFilter condition) <?> "pJSPFilter: JSPath filter exp"
|
return (JSPFilter condition) <?> "pJSPFilter: JSPath filter exp"
|
||||||
|
|
||||||
pFilterConditionParser :: P.Parser FilterExp
|
pFilterConditionParser :: P.Parser FilterExp
|
||||||
|
|||||||
@@ -194,44 +194,6 @@ roleclaims:
|
|||||||
roles:
|
roles:
|
||||||
- obj_key: obj_value
|
- obj_key: obj_value
|
||||||
expected_status: 401 # fails because it compares an object with a string
|
expected_status: 401 # fails because it compares an object with a string
|
||||||
- key: '.realm_access.roles[0][7:]'
|
|
||||||
data:
|
|
||||||
realm_access:
|
|
||||||
roles:
|
|
||||||
- prefix_postgrest_test_author
|
|
||||||
expected_status: 200 # passes because it removes the "prefix_" part using slice
|
|
||||||
- key: '.realm_access.roles[0][:-7]'
|
|
||||||
data:
|
|
||||||
realm_access:
|
|
||||||
roles:
|
|
||||||
- postgrest_test_author_suffix
|
|
||||||
expected_status: 200 # passes because it removes the "_suffix" part using slice
|
|
||||||
- key: '.realm_access.roles[0][7:-7]'
|
|
||||||
data:
|
|
||||||
realm_access:
|
|
||||||
roles:
|
|
||||||
- prefix_postgrest_test_author_suffix
|
|
||||||
expected_status: 200 # passes because it removes the "prefix_" and "_suffix" part using slice
|
|
||||||
- key: '.realm_access.roles[0][:]'
|
|
||||||
data:
|
|
||||||
realm_access:
|
|
||||||
roles:
|
|
||||||
- postgrest_test_author
|
|
||||||
expected_status: 200 # passes because nothing gets sliced
|
|
||||||
- key: '.realm_access.roles[?(@ *== "_test_")][7:]'
|
|
||||||
data:
|
|
||||||
realm_access:
|
|
||||||
roles:
|
|
||||||
- other
|
|
||||||
- prefix_postgrest_test_author
|
|
||||||
expected_status: 200 # passes on both comparison operators and slicing
|
|
||||||
- key: '.realm_access.roles[?(@ *== "_test_")][200:]'
|
|
||||||
data:
|
|
||||||
realm_access:
|
|
||||||
roles:
|
|
||||||
- other
|
|
||||||
- prefix_postgrest_test_author
|
|
||||||
expected_status: 401 # fails due to slicing results in empty string
|
|
||||||
|
|
||||||
jwtaudroleclaims:
|
jwtaudroleclaims:
|
||||||
- key: '.aud'
|
- key: '.aud'
|
||||||
|
|||||||
Reference in New Issue
Block a user