52 lines
1.6 KiB
Haskell
52 lines
1.6 KiB
Haskell
module PostgREST.Config.JSPath
|
|
( JSPath
|
|
, JSPathExp(..)
|
|
, dumpJSPath
|
|
, pRoleClaimKey
|
|
) where
|
|
|
|
import qualified Text.ParserCombinators.Parsec as P
|
|
|
|
import Data.Either.Combinators (mapLeft)
|
|
import Text.ParserCombinators.Parsec ((<?>))
|
|
import Text.Read (read)
|
|
|
|
import Protolude
|
|
|
|
|
|
-- | full jspath, e.g. .property[0].attr.detail
|
|
type JSPath = [JSPathExp]
|
|
|
|
-- | jspath expression, e.g. .property, .property[0] or ."property-dash"
|
|
data JSPathExp
|
|
= JSPKey Text
|
|
| JSPIdx Int
|
|
|
|
dumpJSPath :: JSPathExp -> Text
|
|
-- TODO: this needs to be quoted properly for special chars
|
|
dumpJSPath (JSPKey k) = "." <> show k
|
|
dumpJSPath (JSPIdx i) = "[" <> show i <> "]"
|
|
|
|
-- Used for the config value "role-claim-key"
|
|
pRoleClaimKey :: Text -> Either Text JSPath
|
|
pRoleClaimKey selStr =
|
|
mapLeft show $ P.parse pJSPath ("failed to parse role-claim-key value (" <> toS selStr <> ")") (toS selStr)
|
|
|
|
pJSPath :: P.Parser JSPath
|
|
pJSPath = toJSPath <$> (period *> pPath `P.sepBy` period <* P.eof)
|
|
where
|
|
toJSPath :: [(Text, Maybe Int)] -> JSPath
|
|
toJSPath = concatMap (\(key, idx) -> JSPKey key : maybeToList (JSPIdx <$> idx))
|
|
period = P.char '.' <?> "period (.)"
|
|
pPath :: P.Parser (Text, Maybe Int)
|
|
pPath = (,) <$> pJSPKey <*> P.optionMaybe pJSPIdx
|
|
|
|
pJSPKey :: P.Parser Text
|
|
pJSPKey = toS <$> P.many1 (P.alphaNum <|> P.oneOf "_$@") <|> pQuotedValue <?> "attribute name [a..z0..9_$@])"
|
|
|
|
pJSPIdx :: P.Parser Int
|
|
pJSPIdx = P.char '[' *> (read <$> P.many1 P.digit) <* P.char ']' <?> "array index [0..n]"
|
|
|
|
pQuotedValue :: P.Parser Text
|
|
pQuotedValue = toS <$> (P.char '"' *> P.many (P.noneOf "\"") <* P.char '"')
|