mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-22 15:01:39 +03:00
a26bc80496
* add new optional field `claims_namespace_path` in JWT config * return value when empty array is found in executeJSONPath * update the docs related to claims_namespace_path * improve encodeJSONPath, add property tests for parseJSONPath * throw error if both claims_namespace_path and claims_namespace are set * refactor the Data.Parser.JsonPath to Data.Parser.JSONPathSpec * update the JWT docs Co-Authored-By: Marion Schleifer <marion@hasura.io> Co-authored-by: Marion Schleifer <marion@hasura.io> Co-authored-by: rakeshkky <12475069+rakeshkky@users.noreply.github.com> Co-authored-by: Tirumarai Selvan <tirumarai.selvan@gmail.com>
65 lines
2.3 KiB
Haskell
65 lines
2.3 KiB
Haskell
module Data.Parser.JSONPath
|
|
( parseJSONPath
|
|
, JSONPathElement(..)
|
|
, JSONPath
|
|
) where
|
|
|
|
import Control.Applicative ((<|>))
|
|
import Data.Aeson.Internal (JSONPath, JSONPathElement (..))
|
|
import Data.Attoparsec.Text
|
|
import Data.Bool (bool)
|
|
import Prelude hiding (takeWhile)
|
|
import Text.Read (readMaybe)
|
|
import qualified Data.Text as T
|
|
|
|
parseSimpleKeyText :: Parser T.Text
|
|
parseSimpleKeyText = takeWhile1 (inClass "a-zA-Z0-9_-")
|
|
|
|
parseKey :: Parser JSONPathElement
|
|
parseKey = Key <$>
|
|
( (char '.' *> parseSimpleKeyText) -- Parse `.key`
|
|
<|> T.pack <$> ((string ".['" <|> string "['") *> manyTill anyChar (string "']")) -- Parse `['key']` or `.['key']`
|
|
<|> fail "invalid key element"
|
|
)
|
|
|
|
parseIndex :: Parser JSONPathElement
|
|
parseIndex = Index <$>
|
|
( ((char '[' *> manyTill anyChar (char ']')) >>= maybe (fail "invalid array index") pure . readMaybe) -- Parse `[Int]`
|
|
<|> fail "invalid index element"
|
|
)
|
|
|
|
parseElements :: Parser JSONPath
|
|
parseElements = skipWhile (== '$') *> parseRemaining
|
|
where
|
|
parseFirstKey = Key <$> parseSimpleKeyText
|
|
parseElements' = many1 (parseIndex <|> parseKey)
|
|
parseRemaining = do
|
|
maybeFirstChar <- peekChar
|
|
case maybeFirstChar of
|
|
Nothing -> pure []
|
|
Just firstChar ->
|
|
-- If first char is not any of '.' and '[', then parse first key
|
|
-- Eg:- Parse "key1.key2[0]"
|
|
if firstChar `notElem` (".[" :: String) then do
|
|
firstKey <- parseFirstKey
|
|
remainingElements <- parseElements'
|
|
pure $ firstKey:remainingElements
|
|
else parseElements'
|
|
|
|
-- | Parse jsonpath String value
|
|
parseJSONPath :: T.Text -> Either String JSONPath
|
|
parseJSONPath = parseResult . parse parseElements
|
|
where
|
|
parseResult = \case
|
|
Fail _ pos err ->
|
|
Left $ bool (head pos) err (null pos)
|
|
Partial p -> parseResult $ p ""
|
|
Done remain r ->
|
|
if not $ T.null remain then
|
|
Left $ invalidMessage remain
|
|
else
|
|
Right r
|
|
invalidMessage s = "invalid property name: " ++ T.unpack s
|
|
++ ". Accept letters, digits, underscore (_) or hyphen (-) only"
|
|
++ ". Use single quotes enclosed in bracket if there are any special characters"
|