server: log operation details for each query in a batch query execution

https://github.com/hasura/graphql-engine-mono/pull/2306

GitOrigin-RevId: 066a02fc57711b1faad447e6e448e3e004376c74
This commit is contained in:
Karthikeyan Chinnakonda 2021-09-15 13:59:34 +05:30 committed by hasura-bot
parent f2971dd515
commit 982b5a3d15
10 changed files with 178 additions and 78 deletions

View File

@ -4,8 +4,8 @@
(Add entries below in the order of server, console, cli, docs, others)
- server: support MSSQL transactions
- server: log individual operation details in the http-log during a batch graphQL query execution
- console: support tracking of functions with return a single row
- server: update `create_scheduled_event` API to return `event_id` in response
- server: fix bug which allowed inconsistent metadata to exist after the `replace_metadata` API even though `allow_inconsistent_object` is set to `false`.

View File

@ -840,9 +840,9 @@ instance (MonadIO m) => HttpLog (PGMetadataStorageAppT m) where
unLogger logger $ mkHttpLog $
mkHttpErrorLogContext userInfoM enabledLogTypes reqId waiReq req qErr Nothing Nothing headers
logHttpSuccess logger enabledLogTypes userInfoM reqId waiReq reqBody _response compressedResponse qTime cType headers (CommonHttpLogMetadata rb, ()) =
logHttpSuccess logger enabledLogTypes userInfoM reqId waiReq reqBody _response compressedResponse qTime cType headers (CommonHttpLogMetadata rb batchQueryOpLogs, ()) =
unLogger logger $ mkHttpLog $
mkHttpAccessLogContext userInfoM enabledLogTypes reqId waiReq reqBody compressedResponse qTime cType headers rb
mkHttpAccessLogContext userInfoM enabledLogTypes reqId waiReq reqBody compressedResponse qTime cType headers rb batchQueryOpLogs
instance (Monad m) => MonadExecuteQuery (PGMetadataStorageAppT m) where
cacheLookup _ _ _ _ = pure ([], Nothing)

View File

@ -232,9 +232,9 @@ runGQ
-> [HTTP.Header]
-> E.GraphQLQueryType
-> GQLReqUnparsed
-> m (ParameterizedQueryHash, HttpResponse (Maybe GQResponse, EncJSON))
-> m (GQLQueryOperationSuccessLog, HttpResponse (Maybe GQResponse, EncJSON))
runGQ env logger reqId userInfo ipAddress reqHeaders queryType reqUnparsed = do
(telemTimeTot_DT, (telemQueryType, telemTimeIO_DT, telemLocality, resp, parameterizedQueryHash)) <- withElapsedTime $ do
(totalTime, (telemQueryType, telemTimeIO_DT, telemLocality, resp, parameterizedQueryHash)) <- withElapsedTime $ do
E.ExecutionCtx _ sqlGenCtx sc scVer httpManager enableAL <- ask
-- run system authorization on the GraphQL API
@ -380,10 +380,12 @@ runGQ env logger reqId userInfo ipAddress reqHeaders queryType reqUnparsed = do
throw400 UnexpectedPayload "subscriptions are not supported over HTTP, use websockets instead"
-- The response and misc telemetry data:
let telemTimeIO = convertDuration telemTimeIO_DT
telemTimeTot = convertDuration telemTimeTot_DT
telemTimeTot = convertDuration totalTime
telemTransport = Telem.HTTP
requestSize = LBS.length $ J.encode reqUnparsed
responseSize = LBS.length $ encJToLBS $ snd $ _hrBody resp
Telem.recordTimingMetric Telem.RequestDimensions{..} Telem.RequestTimings{..}
return (parameterizedQueryHash, resp)
return (GQLQueryOperationSuccessLog reqUnparsed totalTime responseSize requestSize parameterizedQueryHash, resp)
where
getExecStepActionWithActionInfo acc execStep = case execStep of
EB.ExecStepAction _ actionInfo _remoteJoins -> (actionInfo:acc)
@ -539,14 +541,14 @@ runGQBatched
-> Wai.IpAddress
-> [HTTP.Header]
-> E.GraphQLQueryType
-> GQLBatchedReqs GQLQueryText
-> GQLBatchedReqs (GQLReq GQLQueryText)
-- ^ the batched request with unparsed GraphQL query
-> m (HttpLogMetadata m, HttpResponse EncJSON)
runGQBatched env logger reqId responseErrorsConfig userInfo ipAddress reqHdrs queryType query =
case query of
GQLSingleRequest req -> do
(parameterizedQueryHash, httpResp) <- runGQ env logger reqId userInfo ipAddress reqHdrs queryType req
let httpLoggingMetadata = buildHttpLogMetadata @m (PQHSetSingleton parameterizedQueryHash) L.RequestModeSingle
(gqlQueryOperationLog, httpResp) <- runGQ env logger reqId userInfo ipAddress reqHdrs queryType req
let httpLoggingMetadata = buildHttpLogMetadata @m (PQHSetSingleton (gqolParameterizedQueryHash gqlQueryOperationLog)) L.RequestModeSingle (Just (GQLSingleRequest (GQLQueryOperationSuccess gqlQueryOperationLog)))
pure (httpLoggingMetadata, snd <$> httpResp)
GQLBatchedReqs reqs -> do
-- It's unclear what we should do if we receive multiple
@ -557,8 +559,15 @@ runGQBatched env logger reqId responseErrorsConfig userInfo ipAddress reqHdrs qu
flip HttpResponse []
. encJFromList
. map (either (encJFromJValue . encodeGQErr includeInternal) _hrBody)
responses <- traverse (try . (fmap . fmap . fmap) snd . runGQ env logger reqId userInfo ipAddress reqHdrs queryType) reqs
let httpLoggingMetadata = buildHttpLogMetadata @m (PQHSetBatched $ rights $ map (fmap fst) responses) L.RequestModeBatched
pure (httpLoggingMetadata, removeHeaders (map (fmap snd) responses))
responses <- traverse (\req -> fmap (req, ) . try . (fmap . fmap . fmap) snd . runGQ env logger reqId userInfo ipAddress reqHdrs queryType $ req) reqs
let requestsOperationLogs = map fst $ rights $ map snd responses
batchOperationLogs = map (\(req, resp) ->
case resp of
Left err -> GQLQueryOperationError $ GQLQueryOperationErrorLog req err
Right (successOpLog, _) -> GQLQueryOperationSuccess successOpLog
) responses
parameterizedQueryHashes = map gqolParameterizedQueryHash requestsOperationLogs
httpLoggingMetadata = buildHttpLogMetadata @m (PQHSetBatched parameterizedQueryHashes) L.RequestModeBatched (Just (GQLBatchedReqs batchOperationLogs))
pure (httpLoggingMetadata, removeHeaders (map ((fmap snd) . snd) responses))
where
try = flip catchError (pure . Left) . fmap Right

View File

@ -20,6 +20,7 @@ module Hasura.GraphQL.Transport.HTTP.Protocol
, GQExecError(..)
, GQResponse
, isExecError
, ReqsText
) where
import Data.Text.Extended (dquote)
@ -83,9 +84,9 @@ instance (Hashable a) => Hashable (GQLReq a)
--
-- See <https://github.com/hasura/graphql-engine/issues/1812>.
data GQLBatchedReqs a
= GQLSingleRequest (GQLReq a)
| GQLBatchedReqs [GQLReq a]
deriving (Show, Eq, Generic)
= GQLSingleRequest a
| GQLBatchedReqs [a]
deriving (Show, Eq, Generic, Functor)
instance J.ToJSON a => J.ToJSON (GQLBatchedReqs a) where
toJSON (GQLSingleRequest q) = J.toJSON q
@ -112,6 +113,8 @@ type GQLReqUnparsed = GQLReq GQLQueryText
-- 'ExecutableDefinitionOperation' in '_grQuery'
type GQLReqParsed = GQLReq GQLExecDoc
type ReqsText = GQLBatchedReqs (GQLReq GQLQueryText)
-- | A simplified form of 'GQLReqParsed' which is more ergonomic in particular
-- for APIs that act as graphql /clients/ (e.g. in remote relationship
-- execution). This is a "desugared" request in which fragments have been

View File

@ -141,8 +141,6 @@ data APIResp
= JSONResp !(HttpResponse EncJSON)
| RawResp !(HttpResponse BL.ByteString)
type ReqsText = GH.GQLBatchedReqs GH.GQLQueryText
-- | API request handlers for different endpoints
data APIHandler m a where
-- | A simple GET request
@ -152,7 +150,7 @@ data APIHandler m a where
-- | A general GraphQL request (query or mutation) for which the content of the query
-- is made available to the handler for authentication.
-- This is a more specific version of the 'AHPost' constructor.
AHGraphQLRequest :: !(ReqsText -> Handler m (HttpLogMetadata m, APIResp)) -> APIHandler m ReqsText
AHGraphQLRequest :: !(GH.ReqsText -> Handler m (HttpLogMetadata m, APIResp)) -> APIHandler m GH.ReqsText
boolToText :: Bool -> Text
boolToText = bool "false" "true"
@ -210,7 +208,7 @@ mkGetHandler = AHGet
mkPostHandler :: (a -> Handler m (HttpLogMetadata m, APIResp)) -> APIHandler m a
mkPostHandler = AHPost
mkGQLRequestHandler :: (ReqsText -> Handler m (HttpLogMetadata m, APIResp)) -> APIHandler m ReqsText
mkGQLRequestHandler :: (GH.ReqsText -> Handler m (HttpLogMetadata m, APIResp)) -> APIHandler m GH.ReqsText
mkGQLRequestHandler = AHGraphQLRequest
mkAPIRespHandler :: (Functor m) => (a -> Handler m (HttpResponse EncJSON)) -> (a -> Handler m APIResp)
@ -550,7 +548,7 @@ v1Alpha1GQHandler
, MonadMetadataStorage (MetadataStorageT m)
, EB.MonadQueryTags m
)
=> E.GraphQLQueryType -> GH.GQLBatchedReqs GH.GQLQueryText
=> E.GraphQLQueryType -> GH.GQLBatchedReqs (GH.GQLReq GH.GQLQueryText)
-> m (HttpLogMetadata m, HttpResponse EncJSON)
v1Alpha1GQHandler queryType query = do
userInfo <- asks hcUser
@ -600,7 +598,7 @@ v1GQHandler
, MonadMetadataStorage (MetadataStorageT m)
, EB.MonadQueryTags m
)
=> GH.GQLBatchedReqs GH.GQLQueryText
=> GH.GQLBatchedReqs (GH.GQLReq GH.GQLQueryText)
-> m (HttpLogMetadata m, HttpResponse EncJSON)
v1GQHandler = v1Alpha1GQHandler E.QueryHasura
@ -618,7 +616,7 @@ v1GQRelayHandler
, MonadMetadataStorage (MetadataStorageT m)
, EB.MonadQueryTags m
)
=> GH.GQLBatchedReqs GH.GQLQueryText
=> GH.GQLBatchedReqs (GH.GQLReq GH.GQLQueryText)
-> m (HttpLogMetadata m, HttpResponse EncJSON)
v1GQRelayHandler = v1Alpha1GQHandler E.QueryRelay

View File

@ -25,26 +25,27 @@ module Hasura.Server.Auth
import Hasura.Prelude
import qualified Crypto.Hash as Crypto
import qualified Data.Text.Encoding as T
import qualified Network.HTTP.Client as H
import qualified Network.HTTP.Types as N
import qualified Crypto.Hash as Crypto
import qualified Data.Text.Encoding as T
import qualified Network.HTTP.Client as H
import qualified Network.HTTP.Types as N
import Control.Concurrent.Extended (ForkableMonadIO, forkManagedT)
import Control.Monad.Morph (hoist)
import Control.Monad.Trans.Control (MonadBaseControl)
import Control.Monad.Trans.Managed (ManagedT)
import Data.IORef (newIORef)
import Data.Time.Clock (UTCTime)
import Control.Concurrent.Extended (ForkableMonadIO, forkManagedT)
import Control.Monad.Morph (hoist)
import Control.Monad.Trans.Control (MonadBaseControl)
import Control.Monad.Trans.Managed (ManagedT)
import Data.IORef (newIORef)
import Data.Time.Clock (UTCTime)
import qualified Hasura.Tracing as Tracing
import qualified Hasura.Tracing as Tracing
import Hasura.Base.Error
import Hasura.GraphQL.Transport.HTTP.Protocol (ReqsText)
import Hasura.Logging
import Hasura.Server.Auth.JWT hiding (processJwt_)
import Hasura.Server.Auth.JWT hiding (processJwt_)
import Hasura.Server.Auth.WebHook
import Hasura.Server.Utils
import Hasura.Server.Version (HasVersion)
import Hasura.Server.Version (HasVersion)
import Hasura.Session

View File

@ -3,7 +3,6 @@ module Hasura.Server.Auth.WebHook
, AuthHookG (..)
, AuthHook
, userInfoFromAuthHook
, type ReqsText
) where
import Hasura.Prelude
@ -59,8 +58,6 @@ hookMethod authHook = case ahType authHook of
AHTGet -> N.GET
AHTPost -> N.POST
type ReqsText = GH.GQLBatchedReqs GH.GQLQueryText
-- | Makes an authentication request to the given AuthHook and returns
-- UserInfo parsed from the response, plus an expiration time if one
-- was returned. Optionally passes a batch of raw GraphQL requests
@ -72,7 +69,7 @@ userInfoFromAuthHook
-> H.Manager
-> AuthHook
-> [N.Header]
-> Maybe ReqsText
-> Maybe GH.ReqsText
-> m (UserInfo, Maybe UTCTime)
userInfoFromAuthHook logger manager hook reqHeaders reqs = do
resp <- (`onLeft` logAndThrow) =<< try performHTTPRequest

View File

@ -14,6 +14,9 @@ module Hasura.Server.Logging
, WebHookLog(..)
, HttpException
, HttpLog (..)
, GQLBatchQueryOperationLog (..)
, GQLQueryOperationSuccessLog (..)
, GQLQueryOperationErrorLog (..)
, MetadataLog(..)
, EnvVarsMovedToMetadata(..)
, DeprecatedEnvVars(..)
@ -26,20 +29,23 @@ module Hasura.Server.Logging
import Hasura.Prelude
import qualified Data.ByteString.Lazy as BL
import qualified Data.Environment as Env
import qualified Data.HashMap.Strict as HM
import qualified Data.HashSet as Set
import qualified Data.TByteString as TBS
import qualified Data.Text as T
import qualified Network.HTTP.Types as HTTP
import qualified Network.Wai.Extended as Wai
import qualified Data.ByteString.Lazy as BL
import qualified Data.Environment as Env
import qualified Data.HashMap.Strict as HM
import qualified Data.HashSet as Set
import qualified Data.List.NonEmpty as NE
import qualified Data.TByteString as TBS
import qualified Data.Text as T
import qualified Network.HTTP.Types as HTTP
import qualified Network.Wai.Extended as Wai
import Data.Aeson
import Data.Aeson.TH
import Data.Int (Int64)
import Data.Int (Int64)
import Data.Text.Extended
import qualified Hasura.GraphQL.Transport.HTTP.Protocol as GH
import Hasura.Base.Error
import Hasura.GraphQL.ParameterizedQueryHash
import Hasura.HTTP
@ -48,11 +54,11 @@ import Hasura.Metadata.Class
import Hasura.RQL.Types
import Hasura.Server.Compression
import Hasura.Server.Types
import Hasura.Server.Utils (DeprecatedEnvVars (..),
EnvVarsMovedToMetadata (..),
deprecatedEnvVars, envVarsMovedToMetadata)
import Hasura.Server.Utils (DeprecatedEnvVars (..),
EnvVarsMovedToMetadata (..),
deprecatedEnvVars, envVarsMovedToMetadata)
import Hasura.Session
import Hasura.Tracing (TraceT)
import Hasura.Tracing (TraceT)
data StartupLog
@ -133,6 +139,36 @@ instance ToJSON WebHookLog where
, "message" .= whlMessage whl
]
-- | GQLQueryOperationSuccessLog captures all the data required to construct
-- an HTTP success log.
data GQLQueryOperationSuccessLog
= GQLQueryOperationSuccessLog
{ gqolQuery :: !GH.GQLReqUnparsed
, gqolQueryExecutionTime :: !DiffTime
, gqolResponseSize :: !Int64
, gqolRequestSize :: !Int64
, gqolParameterizedQueryHash :: !ParameterizedQueryHash
} deriving (Show, Eq)
$(deriveToJSON hasuraJSON{omitNothingFields = True} ''GQLQueryOperationSuccessLog)
-- | GQLQueryOperationErrorLog captures the request along with the error message
data GQLQueryOperationErrorLog
= GQLQueryOperationErrorLog
{ gqelQuery :: !GH.GQLReqUnparsed
, gqelError :: !QErr
} deriving (Show, Eq)
$(deriveToJSON hasuraJSON ''GQLQueryOperationErrorLog)
data GQLBatchQueryOperationLog
= GQLQueryOperationSuccess !GQLQueryOperationSuccessLog
| GQLQueryOperationError !GQLQueryOperationErrorLog
deriving (Show, Eq)
instance ToJSON GQLBatchQueryOperationLog where
toJSON = \case
GQLQueryOperationSuccess successLog -> toJSON successLog
GQLQueryOperationError errorLog -> toJSON errorLog
-- | whether a request is executed in batched mode or not
data RequestMode
= RequestModeBatched
@ -152,7 +188,11 @@ instance ToJSON RequestMode where
RequestModeNonBatchable -> "non-graphql"
RequestModeError -> "error"
newtype CommonHttpLogMetadata = CommonHttpLogMetadata {_chlmRequestMode :: RequestMode}
data CommonHttpLogMetadata
= CommonHttpLogMetadata
{ _chlmRequestMode :: !RequestMode
, _chlmBatchOperationLog :: !(Maybe (GH.GQLBatchedReqs GQLBatchQueryOperationLog))
}
deriving (Show, Eq)
-- | The http-log metadata attached to HTTP requests running in the monad 'm', split into a
@ -168,13 +208,14 @@ buildHttpLogMetadata
. HttpLog m
=> ParameterizedQueryHashList
-> RequestMode
-> Maybe (GH.GQLBatchedReqs GQLBatchQueryOperationLog)
-> HttpLogMetadata m
buildHttpLogMetadata xs rb = (CommonHttpLogMetadata rb, buildExtraHttpLogMetadata @m xs)
buildHttpLogMetadata paramQueryHashList requestMode batchQueryOperationLog =
(CommonHttpLogMetadata requestMode batchQueryOperationLog, buildExtraHttpLogMetadata @m paramQueryHashList)
-- | synonym for clarity, writing `emptyHttpLogMetadata @m` instead of `def @(HttpLogMetadata m)`
emptyHttpLogMetadata :: forall m. HttpLog m => HttpLogMetadata m
emptyHttpLogMetadata = (CommonHttpLogMetadata RequestModeNonBatchable, emptyExtraHttpLogMetadata @m)
emptyHttpLogMetadata = (CommonHttpLogMetadata RequestModeNonBatchable Nothing, emptyExtraHttpLogMetadata @m)
{- Note [Disable query printing when query-log is disabled]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -312,13 +353,43 @@ data OperationLog
$(deriveToJSON hasuraJSON{omitNothingFields = True} ''OperationLog)
-- | @BatchOperationSuccessLog@ contains the information required for a single
-- successful operation in a batch request for OSS. This type is a subset of the @GQLQueryOperationSuccessLog@
data BatchOperationSuccessLog
= BatchOperationSuccessLog
{ bolQuery :: !(Maybe Value)
, bolResponseSize :: !Int64
, bolQueryExecutionTime :: !Seconds
} deriving (Show, Eq)
$(deriveToJSON hasuraJSON{omitNothingFields = True} ''BatchOperationSuccessLog)
-- | @BatchOperationSuccessLog@ contains the information required for a single
-- erroneous operation in a batch request for OSS. This type is a subset of the @GQLQueryOperationErrorLog@
data BatchOperationErrorLog
= BatchOperationErrorLog
{ belQuery :: !(Maybe Value)
, belError :: !QErr
} deriving (Show, Eq)
$(deriveToJSON hasuraJSON{omitNothingFields = True} ''BatchOperationErrorLog)
data BatchOperationLog
= BatchOperationSuccess !BatchOperationSuccessLog
| BatchOperationError !BatchOperationErrorLog
deriving (Show, Eq)
instance ToJSON BatchOperationLog where
toJSON = \case
BatchOperationSuccess successLog -> toJSON successLog
BatchOperationError errorLog -> toJSON errorLog
data HttpLogContext
= HttpLogContext
{ hlcHttpInfo :: !HttpInfoLog
, hlcOperation :: !OperationLog
, hlcRequestId :: !RequestId
{ hlcHttpInfo :: !HttpInfoLog
, hlcOperation :: !OperationLog
, hlcRequestId :: !RequestId
, hlcBatchedOperations :: !(Maybe (NE.NonEmpty BatchOperationLog))
} deriving (Show, Eq)
$(deriveToJSON hasuraJSON ''HttpLogContext)
$(deriveToJSON hasuraJSON {omitNothingFields = True} ''HttpLogContext)
mkHttpAccessLogContext
:: Maybe UserInfo
@ -332,8 +403,9 @@ mkHttpAccessLogContext
-> Maybe CompressionType
-> [HTTP.Header]
-> RequestMode
-> Maybe (GH.GQLBatchedReqs GQLBatchQueryOperationLog)
-> HttpLogContext
mkHttpAccessLogContext userInfoM enabledLogTypes reqId req (_, parsedReq) res mTiming compressTypeM headers batching =
mkHttpAccessLogContext userInfoM enabledLogTypes reqId req (_, parsedReq) res mTiming compressTypeM headers batching queryLogMetadata =
let http = HttpInfoLog
{ hlStatus = status
, hlMethod = bsToTxt $ Wai.requestMethod req
@ -355,7 +427,26 @@ mkHttpAccessLogContext userInfoM enabledLogTypes reqId req (_, parsedReq) res mT
, olRawQuery = Nothing
, olError = Nothing
}
in HttpLogContext http op reqId
batchOpLog =
queryLogMetadata >>= (\case
GH.GQLSingleRequest _ -> Nothing -- This case is aleady handled in the `OperationLog`
GH.GQLBatchedReqs opLogs ->
NE.nonEmpty $
map (\opLog ->
case opLog of
GQLQueryOperationSuccess (GQLQueryOperationSuccessLog {..}) ->
BatchOperationSuccess $
BatchOperationSuccessLog
((bool Nothing (Just $ toJSON gqolQuery)) $ Set.member ELTQueryLog enabledLogTypes)
gqolResponseSize
(convertDuration gqolQueryExecutionTime)
GQLQueryOperationError (GQLQueryOperationErrorLog {..}) ->
BatchOperationError $
BatchOperationErrorLog
(bool Nothing (Just $ toJSON gqelQuery) $ Set.member ELTQueryLog enabledLogTypes)
gqelError
) opLogs)
in HttpLogContext http op reqId batchOpLog
where
status = HTTP.status200
respSize = Just $ BL.length res
@ -398,7 +489,7 @@ mkHttpErrorLogContext userInfoM enabledLogTypes reqId waiReq (reqBody, parsedReq
-- See Note [Disable query printing when query-log is disabled]
reqToLog :: Maybe a -> Maybe a
reqToLog req = bool Nothing req $ Set.member ELTQueryLog enabledLogTypes
in HttpLogContext http op reqId
in HttpLogContext http op reqId Nothing -- Batched operation logs are always reported in logHttpSuccess even if there are errors
data HttpLogLine
= HttpLogLine

View File

@ -161,8 +161,9 @@ runCustomEndpoint env execCtx requestId userInfo reqHeaders ipAddress RestReques
-- with the query string from the schema cache, and pass it
-- through to the /v1/graphql endpoint.
(httpLoggingMetadata, handlerResp) <- flip runReaderT execCtx $ do
(parameterizedQueryHash, resp) <- GH.runGQ env (E._ecxLogger execCtx) requestId userInfo ipAddress reqHeaders E.QueryHasura (mkPassthroughRequest queryx resolvedVariables)
let httpLogMetadata = buildHttpLogMetadata @m (PQHSetSingleton parameterizedQueryHash) RequestModeNonBatchable
(gqlOperationLog, resp) <- GH.runGQ env (E._ecxLogger execCtx) requestId userInfo ipAddress reqHeaders E.QueryHasura (mkPassthroughRequest queryx resolvedVariables)
let httpLogMetadata =
buildHttpLogMetadata @m (PQHSetSingleton (gqolParameterizedQueryHash gqlOperationLog)) RequestModeNonBatchable Nothing
return (httpLogMetadata, fst <$> resp)
case sequence handlerResp of
Just resp -> pure (httpLoggingMetadata, fmap encodeHTTPResp resp)

View File

@ -4,25 +4,25 @@ module Hasura.Server.AuthSpec (spec) where
import Hasura.Prelude
import qualified Crypto.JOSE.JWK as Jose
import qualified Crypto.JWT as JWT
import qualified Data.Aeson as J
import qualified Data.HashMap.Strict as Map
import qualified Network.HTTP.Types as N
import qualified Crypto.JOSE.JWK as Jose
import qualified Crypto.JWT as JWT
import qualified Data.Aeson as J
import qualified Data.HashMap.Strict as Map
import qualified Network.HTTP.Types as N
import Control.Lens hiding ((.=))
import Control.Lens hiding ((.=))
import Control.Monad.Trans.Control
import Control.Monad.Trans.Managed (lowerManagedT)
import Data.Aeson ((.=))
import Control.Monad.Trans.Managed (lowerManagedT)
import Data.Aeson ((.=))
import Data.Parser.JSONPath
import qualified Hasura.Tracing as Tracing
import qualified Hasura.Tracing as Tracing
import Hasura.Base.Error
import Hasura.GraphQL.Transport.HTTP.Protocol (ReqsText)
import Hasura.Logging
import Hasura.Server.Auth hiding (getUserInfoWithExpTime, processJwt)
import Hasura.Server.Auth.JWT hiding (processJwt)
import Hasura.Server.Auth.WebHook (ReqsText)
import Hasura.Server.Auth hiding (getUserInfoWithExpTime, processJwt)
import Hasura.Server.Auth.JWT hiding (processJwt)
import Hasura.Server.Utils
import Hasura.Server.Version
import Hasura.Session