Skip to content

Commit c18727f

Browse files
taimoorzaeemsteve-chavez
authored andcommitted
refactor: move walkJSPath to Config/JSPath.hs module
The logic to evaluate `JSPath` belongs to `JSPath.hs` module. Hence, moving this logic from `Auth/Jwt.hs` to here. Signed-off-by: Taimoor Zaeem <taimoorzaeem@gmail.com>
1 parent 886df84 commit c18727f

2 files changed

Lines changed: 29 additions & 27 deletions

File tree

src/PostgREST/Auth/Jwt.hs

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,11 @@ module PostgREST.Auth.Jwt
1616
, parseClaims) where
1717

1818
import qualified Data.Aeson as JSON
19-
import qualified Data.Aeson.Key as K
2019
import qualified Data.Aeson.KeyMap as KM
2120
import qualified Data.ByteString as BS
2221
import qualified Data.ByteString.Internal as BS
2322
import qualified Data.ByteString.Lazy.Char8 as LBS
2423
import qualified Data.Scientific as Sci
25-
import qualified Data.Text as T
26-
import qualified Data.Vector as V
2724
import qualified Jose.Jwk as JWT
2825
import qualified Jose.Jwt as JWT
2926

@@ -33,12 +30,12 @@ import Data.Text ()
3330
import Data.Time.Clock (UTCTime, nominalDiffTimeToSeconds)
3431
import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)
3532

36-
import PostgREST.Auth.Types (AuthResult (..))
37-
import PostgREST.Config (AppConfig (..), FilterExp (..), JSPath,
38-
JSPathExp (..), audMatchesCfg)
39-
import PostgREST.Error (Error (..),
40-
JwtClaimsError (AudClaimNotStringOrArray, ExpClaimNotNumber, IatClaimNotNumber, JWTExpired, JWTIssuedAtFuture, JWTNotInAudience, JWTNotYetValid, NbfClaimNotNumber, ParsingClaimsFailed),
41-
JwtDecodeError (..), JwtError (..))
33+
import PostgREST.Auth.Types (AuthResult (..))
34+
import PostgREST.Config (AppConfig (..), audMatchesCfg)
35+
import PostgREST.Config.JSPath (walkJSPath)
36+
import PostgREST.Error (Error (..),
37+
JwtClaimsError (AudClaimNotStringOrArray, ExpClaimNotNumber, IatClaimNotNumber, JWTExpired, JWTIssuedAtFuture, JWTNotInAudience, JWTNotYetValid, NbfClaimNotNumber, ParsingClaimsFailed),
38+
JwtDecodeError (..), JwtError (..))
4239

4340
import Data.Aeson ((.:?))
4441
import Data.Aeson.Types (parseMaybe)
@@ -128,24 +125,6 @@ parseClaims cfg@AppConfig{configJwtRoleClaimKey, configDbAnonRole} time mclaims
128125
, authRole = role
129126
}
130127
where
131-
walkJSPath :: Maybe JSON.Value -> JSPath -> Maybe JSON.Value
132-
walkJSPath x [] = x
133-
walkJSPath (Just (JSON.Object o)) (JSPKey key:rest) = walkJSPath (KM.lookup (K.fromText key) o) rest
134-
walkJSPath (Just (JSON.Array ar)) (JSPIdx idx:rest) = walkJSPath (ar V.!? idx) rest
135-
walkJSPath (Just (JSON.Array ar)) [JSPFilter (EqualsCond txt)] = findFirstMatch (==) txt ar
136-
walkJSPath (Just (JSON.Array ar)) [JSPFilter (NotEqualsCond txt)] = findFirstMatch (/=) txt ar
137-
walkJSPath (Just (JSON.Array ar)) [JSPFilter (StartsWithCond txt)] = findFirstMatch T.isPrefixOf txt ar
138-
walkJSPath (Just (JSON.Array ar)) [JSPFilter (EndsWithCond txt)] = findFirstMatch T.isSuffixOf txt ar
139-
walkJSPath (Just (JSON.Array ar)) [JSPFilter (ContainsCond txt)] = findFirstMatch T.isInfixOf txt ar
140-
walkJSPath _ _ = Nothing
141-
142-
findFirstMatch matchWith pattern = foldr checkMatch Nothing
143-
where
144-
checkMatch (JSON.String txt) acc
145-
| pattern `matchWith` txt = Just $ JSON.String txt
146-
| otherwise = acc
147-
checkMatch _ acc = acc
148-
149128
unquoted :: JSON.Value -> BS.ByteString
150129
unquoted (JSON.String t) = encodeUtf8 t
151130
unquoted v = LBS.toStrict $ JSON.encode v

src/PostgREST/Config/JSPath.hs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
{-# OPTIONS_GHC -Wno-unused-do-bind #-}
2+
{-# LANGUAGE LambdaCase #-}
23
module PostgREST.Config.JSPath
34
( JSPath
45
, JSPathExp(..)
56
, FilterExp(..)
67
, dumpJSPath
78
, pRoleClaimKey
9+
, walkJSPath
810
) where
911

12+
import qualified Data.Aeson as JSON
13+
import qualified Data.Aeson.Key as K
14+
import qualified Data.Aeson.KeyMap as KM
15+
import qualified Data.Text as T
16+
import qualified Data.Vector as V
1017
import qualified Text.ParserCombinators.Parsec as P
1118

1219
import Data.Either.Combinators (mapLeft)
@@ -47,6 +54,22 @@ dumpJSPath (JSPFilter cond) = "[?(@" <> expr <> ")]"
4754
EndsWithCond text -> " ==^ " <> show text
4855
ContainsCond text -> " *== " <> show text
4956

57+
-- | Evaluate JSPath on a JSON
58+
walkJSPath :: Maybe JSON.Value -> JSPath -> Maybe JSON.Value
59+
walkJSPath x [] = x
60+
walkJSPath (Just (JSON.Object o)) (JSPKey key:rest) = walkJSPath (KM.lookup (K.fromText key) o) rest
61+
walkJSPath (Just (JSON.Array ar)) (JSPIdx idx:rest) = walkJSPath (ar V.!? idx) rest
62+
walkJSPath (Just (JSON.Array ar)) [JSPFilter jspFilter] = case jspFilter of
63+
EqualsCond txt -> findFirstMatch (==) txt ar
64+
NotEqualsCond txt -> findFirstMatch (/=) txt ar
65+
StartsWithCond txt -> findFirstMatch T.isPrefixOf txt ar
66+
EndsWithCond txt -> findFirstMatch T.isSuffixOf txt ar
67+
ContainsCond txt -> findFirstMatch T.isInfixOf txt ar
68+
where
69+
findFirstMatch matchWith pattern = find (\case
70+
JSON.String txt -> pattern `matchWith` txt
71+
_ -> False)
72+
walkJSPath _ _ = Nothing
5073

5174
-- Used for the config value "role-claim-key"
5275
pRoleClaimKey :: Text -> Either Text JSPath

0 commit comments

Comments
 (0)