diff --git a/src/PostgREST/Auth.hs b/src/PostgREST/Auth.hs index d14c50ff4..29521948b 100644 --- a/src/PostgREST/Auth.hs +++ b/src/PostgREST/Auth.hs @@ -23,8 +23,8 @@ import qualified Data.Aeson as JSON import qualified Data.Aeson.Key as K import qualified Data.Aeson.KeyMap as KM import qualified Data.Aeson.Types as JSON +import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy.Char8 as LBS -import qualified Data.Text.Encoding as T import qualified Data.Vault.Lazy as Vault import qualified Data.Vector as V import qualified Network.HTTP.Types.Header as HTTP @@ -47,7 +47,7 @@ import Protolude data AuthResult = AuthResult { authClaims :: KM.KeyMap JSON.Value - , authRole :: Text + , authRole :: BS.ByteString } -- | Receives the JWT secret and audience (from config) and a JWT and returns a @@ -79,7 +79,7 @@ parseClaims AppConfig{..} jclaims@(JSON.Object mclaims) = do role <- liftEither . maybeToRight JwtTokenRequired $ unquoted <$> walkJSPath (Just jclaims) configJwtRoleClaimKey <|> configDbAnonRole return AuthResult - { authClaims = mclaims & KM.insert "role" (JSON.toJSON role) + { authClaims = mclaims & KM.insert "role" (JSON.toJSON $ decodeUtf8 role) , authRole = role } where @@ -89,9 +89,9 @@ parseClaims AppConfig{..} jclaims@(JSON.Object mclaims) = do walkJSPath (Just (JSON.Array ar)) (JSPIdx idx:rest) = walkJSPath (ar V.!? idx) rest walkJSPath _ _ = Nothing - unquoted :: JSON.Value -> Text - unquoted (JSON.String t) = t - unquoted v = T.decodeUtf8 . LBS.toStrict $ JSON.encode v + unquoted :: JSON.Value -> BS.ByteString + unquoted (JSON.String t) = encodeUtf8 t + unquoted v = LBS.toStrict $ JSON.encode v -- impossible case - just added to please -Wincomplete-patterns parseClaims _ _ = return AuthResult { authClaims = KM.empty, authRole = mempty } @@ -117,5 +117,5 @@ authResultKey = unsafePerformIO Vault.newKey getResult :: Wai.Request -> Maybe (Either Error AuthResult) getResult = Vault.lookup authResultKey . Wai.vault -getRole :: Wai.Request -> Maybe Text +getRole :: Wai.Request -> Maybe BS.ByteString getRole req = authRole <$> (rightToMaybe =<< getResult req) diff --git a/src/PostgREST/Config.hs b/src/PostgREST/Config.hs index 5bbffb306..18e9825a8 100644 --- a/src/PostgREST/Config.hs +++ b/src/PostgREST/Config.hs @@ -65,7 +65,7 @@ import Protolude hiding (Proxy, toList) data AppConfig = AppConfig { configAppSettings :: [(Text, Text)] - , configDbAnonRole :: Maybe Text + , configDbAnonRole :: Maybe BS.ByteString , configDbChannel :: Text , configDbChannelEnabled :: Bool , configDbExtraSearchPath :: [Text] @@ -128,7 +128,7 @@ toText conf = where -- apply conf to all pgrst settings pgrstSettings = (\(k, v) -> (k, v conf)) <$> - [("db-anon-role", q . fromMaybe "" . configDbAnonRole) + [("db-anon-role", q . T.decodeUtf8 . fromMaybe "" . configDbAnonRole) ,("db-channel", q . configDbChannel) ,("db-channel-enabled", T.toLower . show . configDbChannelEnabled) ,("db-extra-search-path", q . T.intercalate "," . configDbExtraSearchPath) @@ -218,7 +218,7 @@ parser :: Maybe FilePath -> Environment -> [(Text, Text)] -> RoleSettings -> C.P parser optPath env dbSettings roleSettings = AppConfig <$> parseAppSettings "app.settings" - <*> optString "db-anon-role" + <*> (fmap encodeUtf8 <$> optString "db-anon-role") <*> (fromMaybe "pgrst" <$> optString "db-channel") <*> (fromMaybe True <$> optBool "db-channel-enabled") <*> (maybe ["public"] splitOnCommas <$> optValue "db-extra-search-path") diff --git a/src/PostgREST/Logger.hs b/src/PostgREST/Logger.hs index b5bac1cda..08d43b2d0 100644 --- a/src/PostgREST/Logger.hs +++ b/src/PostgREST/Logger.hs @@ -26,5 +26,5 @@ middleware logLevel = case logLevel of { Wai.outputFormat = Wai.ApacheWithSettings $ Wai.defaultApacheSettings & Wai.setApacheRequestFilter (\_ res -> filterStatus $ Wai.responseStatus res) - & Wai.setApacheUserGetter (fmap encodeUtf8 . Auth.getRole) + & Wai.setApacheUserGetter Auth.getRole } diff --git a/src/PostgREST/Query.hs b/src/PostgREST/Query.hs index 65a4164b7..2464f2c49 100644 --- a/src/PostgREST/Query.hs +++ b/src/PostgREST/Query.hs @@ -16,6 +16,7 @@ module PostgREST.Query import qualified Data.Aeson as JSON import qualified Data.Aeson.Key as K import qualified Data.Aeson.KeyMap as KM +import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy.Char8 as LBS import qualified Data.HashMap.Strict as HM import qualified Data.Set as S @@ -234,7 +235,7 @@ optionalRollback AppConfig{..} ApiRequest{iPreferences=Preferences{..}} = do configDbTxAllowOverride && preferTransaction == Just Rollback -- | Runs local (transaction scoped) GUCs for every request. -setPgLocals :: AppConfig -> KM.KeyMap JSON.Value -> Text -> +setPgLocals :: AppConfig -> KM.KeyMap JSON.Value -> BS.ByteString -> ApiRequest -> PgVersion -> DbHandler () setPgLocals AppConfig{..} claims role req actualPgVersion = lift $ SQL.statement mempty $ SQL.dynamicallyParameterized @@ -252,11 +253,10 @@ setPgLocals AppConfig{..} claims role req actualPgVersion = lift $ claimsSql = if usesLegacyGucs then setConfigLocal "request.jwt.claim." <$> [(toUtf8 $ K.toText c, toUtf8 $ unquoted v) | (c,v) <- KM.toList claims] else [setConfigLocal mempty ("request.jwt.claims", LBS.toStrict $ JSON.encode claims)] - roleBs = toUtf8 role - roleSql = [setConfigLocal mempty ("role", roleBs)] + roleSql = [setConfigLocal mempty ("role", role)] roleSettingsSql = if null configRoleSettings then mempty - else setConfigLocal mempty <$> fromMaybe mempty (HM.lookup roleBs configRoleSettings) + else setConfigLocal mempty <$> fromMaybe mempty (HM.lookup role configRoleSettings) appSettingsSql = setConfigLocal mempty <$> (join bimap toUtf8 <$> configAppSettings) searchPathSql = let schemas = pgFmtIdentList (iSchema req : configDbExtraSearchPath) in