mirror of
https://github.com/zhigang1992/graphql-engine.git
synced 2026-05-28 15:23:56 +08:00
committed by
Vamshi Surabhi
parent
9675e036ea
commit
9eb38e6c96
@@ -136,7 +136,7 @@ mkHsraObjFldInfo
|
||||
-> G.GType
|
||||
-> ObjFldInfo
|
||||
mkHsraObjFldInfo descM name params ty =
|
||||
ObjFldInfo descM name params ty HasuraType
|
||||
ObjFldInfo descM name params ty TLHasuraType
|
||||
|
||||
mkHsraObjTyInfo
|
||||
:: Maybe G.Description
|
||||
@@ -145,7 +145,7 @@ mkHsraObjTyInfo
|
||||
-> ObjFieldMap
|
||||
-> ObjTyInfo
|
||||
mkHsraObjTyInfo descM ty implIFaces flds =
|
||||
mkObjTyInfo descM ty implIFaces flds HasuraType
|
||||
mkObjTyInfo descM ty implIFaces flds TLHasuraType
|
||||
|
||||
mkHsraInpTyInfo
|
||||
:: Maybe G.Description
|
||||
@@ -153,7 +153,7 @@ mkHsraInpTyInfo
|
||||
-> InpObjFldMap
|
||||
-> InpObjTyInfo
|
||||
mkHsraInpTyInfo descM ty flds =
|
||||
InpObjTyInfo descM ty flds HasuraType
|
||||
InpObjTyInfo descM ty flds TLHasuraType
|
||||
|
||||
mkHsraEnumTyInfo
|
||||
:: Maybe G.Description
|
||||
@@ -161,10 +161,10 @@ mkHsraEnumTyInfo
|
||||
-> Map.HashMap G.EnumValue EnumValInfo
|
||||
-> EnumTyInfo
|
||||
mkHsraEnumTyInfo descM ty enumVals =
|
||||
EnumTyInfo descM ty enumVals HasuraType
|
||||
EnumTyInfo descM ty enumVals TLHasuraType
|
||||
|
||||
mkHsraScalarTyInfo :: PGColType -> ScalarTyInfo
|
||||
mkHsraScalarTyInfo ty = ScalarTyInfo Nothing ty HasuraType
|
||||
mkHsraScalarTyInfo ty = ScalarTyInfo Nothing ty TLHasuraType
|
||||
|
||||
fromInpValL :: [InpValInfo] -> Map.HashMap G.Name InpValInfo
|
||||
fromInpValL = mapFromL _iviName
|
||||
@@ -211,7 +211,7 @@ mkCompExpInp colTy =
|
||||
, bool [] (stDWithinGeoOpInpVal stDWithinGeographyInpTy :
|
||||
map geoOpToInpVal geoOps) isGeographyType
|
||||
, [InpValInfo Nothing "_is_null" Nothing $ G.TypeNamed (G.Nullability True) $ G.NamedType "Boolean"]
|
||||
]) HasuraType
|
||||
]) TLHasuraType
|
||||
where
|
||||
tyDesc = mconcat
|
||||
[ "expression to compare columns of type "
|
||||
@@ -349,7 +349,7 @@ ordByEnumTy =
|
||||
]
|
||||
|
||||
defaultTypes :: [TypeInfo]
|
||||
defaultTypes = $(fromSchemaDocQ defaultSchema HasuraType)
|
||||
defaultTypes = $(fromSchemaDocQ defaultSchema TLHasuraType)
|
||||
|
||||
|
||||
mkGCtx :: TyAgg -> RootFlds -> InsCtxMap -> GCtx
|
||||
@@ -397,10 +397,10 @@ mkGCtx tyAgg (RootFlds flds) insCtxMap =
|
||||
|
||||
-- _st_d_within has to stay with geometry type
|
||||
stDWithinGeometryInpM =
|
||||
bool Nothing (Just $ stDWithinGeomInp) (PGGeometry `elem` colTys)
|
||||
bool Nothing (Just stDWithinGeomInp) (PGGeometry `elem` colTys)
|
||||
-- _st_d_within_geography is created for geography type
|
||||
stDWithinGeographyInpM =
|
||||
bool Nothing (Just $ stDWithinGeogInp) (PGGeography `elem` colTys)
|
||||
bool Nothing (Just stDWithinGeogInp) (PGGeography `elem` colTys)
|
||||
|
||||
stDWithinGeomInp =
|
||||
mkHsraInpTyInfo Nothing stDWithinGeometryInpTy $ fromInpValL
|
||||
@@ -417,3 +417,11 @@ mkGCtx tyAgg (RootFlds flds) insCtxMap =
|
||||
|
||||
emptyGCtx :: GCtx
|
||||
emptyGCtx = mkGCtx mempty mempty mempty
|
||||
|
||||
data RemoteGCtx
|
||||
= RemoteGCtx
|
||||
{ _rgTypes :: !TypeMap
|
||||
, _rgQueryRoot :: !ObjTyInfo
|
||||
, _rgMutationRoot :: !(Maybe ObjTyInfo)
|
||||
, _rgSubscriptionRoot :: !(Maybe ObjTyInfo)
|
||||
} deriving (Show, Eq)
|
||||
|
||||
@@ -69,7 +69,7 @@ assertSameLocationNodes
|
||||
assertSameLocationNodes typeLocs =
|
||||
case Set.toList (Set.fromList typeLocs) of
|
||||
-- this shouldn't happen
|
||||
[] -> return VT.HasuraType
|
||||
[] -> return VT.TLHasuraType
|
||||
[loc] -> return loc
|
||||
_ -> throw400 NotSupported msg
|
||||
where
|
||||
@@ -124,11 +124,11 @@ getExecPlanPartial userInfo sc enableAL req = do
|
||||
typeLoc <- assertSameLocationNodes typeLocs
|
||||
|
||||
case typeLoc of
|
||||
VT.HasuraType -> do
|
||||
VT.TLHasuraType -> do
|
||||
rootSelSet <- runReaderT (VQ.validateGQ queryParts) gCtx
|
||||
let varDefs = G._todVariableDefinitions $ VQ.qpOpDef queryParts
|
||||
return $ GExPHasura (gCtx, rootSelSet, varDefs)
|
||||
VT.RemoteType _ rsi ->
|
||||
VT.TLRemoteType _ rsi ->
|
||||
return $ GExPRemote rsi opDef
|
||||
where
|
||||
role = userRole userInfo
|
||||
|
||||
@@ -22,12 +22,12 @@ import qualified Network.Wreq as Wreq
|
||||
import Hasura.HTTP (wreqOptions)
|
||||
import Hasura.RQL.DDL.Headers (getHeadersFromConf)
|
||||
import Hasura.RQL.Types
|
||||
import Hasura.Server.Utils (bsToTxt, httpExceptToJSON)
|
||||
|
||||
import qualified Hasura.GraphQL.Context as GC
|
||||
import qualified Hasura.GraphQL.Schema as GS
|
||||
import qualified Hasura.GraphQL.Validate.Types as VT
|
||||
|
||||
|
||||
|
||||
introspectionQuery :: BL.ByteString
|
||||
introspectionQuery = $(embedStringFile "src-rsr/introspection.json")
|
||||
|
||||
@@ -36,61 +36,75 @@ fetchRemoteSchema
|
||||
=> HTTP.Manager
|
||||
-> RemoteSchemaName
|
||||
-> RemoteSchemaInfo
|
||||
-> m GS.RemoteGCtx
|
||||
-> m GC.RemoteGCtx
|
||||
fetchRemoteSchema manager name def@(RemoteSchemaInfo url headerConf _) = do
|
||||
headers <- getHeadersFromConf headerConf
|
||||
let hdrs = map (\(hn, hv) -> (CI.mk . T.encodeUtf8 $ hn, T.encodeUtf8 hv)) headers
|
||||
let hdrs = flip map headers $
|
||||
\(hn, hv) -> (CI.mk . T.encodeUtf8 $ hn, T.encodeUtf8 hv)
|
||||
options = wreqOptions manager hdrs
|
||||
res <- liftIO $ try $ Wreq.postWith options (show url) introspectionQuery
|
||||
resp <- either throwHttpErr return res
|
||||
|
||||
let respData = resp ^. Wreq.responseBody
|
||||
statusCode = resp ^. Wreq.responseStatus . Wreq.statusCode
|
||||
when (statusCode /= 200) $ schemaErr $ show respData
|
||||
when (statusCode /= 200) $ throwNon200 statusCode respData
|
||||
|
||||
introspectRes :: (FromIntrospection IntrospectionResult) <-
|
||||
either schemaErr return $ J.eitherDecode respData
|
||||
either (remoteSchemaErr . T.pack) return $ J.eitherDecode respData
|
||||
let (sDoc, qRootN, mRootN, sRootN) =
|
||||
fromIntrospection introspectRes
|
||||
typMap <- either remoteSchemaErr return $ VT.fromSchemaDoc sDoc $
|
||||
VT.RemoteType name def
|
||||
VT.TLRemoteType name def
|
||||
let mQrTyp = Map.lookup qRootN typMap
|
||||
mMrTyp = maybe Nothing (\mr -> Map.lookup mr typMap) mRootN
|
||||
mSrTyp = maybe Nothing (\sr -> Map.lookup sr typMap) sRootN
|
||||
mMrTyp = maybe Nothing (`Map.lookup` typMap) mRootN
|
||||
mSrTyp = maybe Nothing (`Map.lookup` typMap) sRootN
|
||||
qrTyp <- liftMaybe noQueryRoot mQrTyp
|
||||
let mRmQR = VT.getObjTyM qrTyp
|
||||
mRmMR = join $ VT.getObjTyM <$> mMrTyp
|
||||
mRmSR = join $ VT.getObjTyM <$> mSrTyp
|
||||
rmQR <- liftMaybe (err400 Unexpected "query root has to be an object type") mRmQR
|
||||
return $ GS.RemoteGCtx typMap rmQR mRmMR mRmSR
|
||||
return $ GC.RemoteGCtx typMap rmQR mRmMR mRmSR
|
||||
|
||||
where
|
||||
noQueryRoot = err400 Unexpected "query root not found in remote schema"
|
||||
remoteSchemaErr :: (MonadError QErr m) => T.Text -> m a
|
||||
remoteSchemaErr = throw400 RemoteSchemaError
|
||||
|
||||
schemaErr err = remoteSchemaErr (T.pack err)
|
||||
|
||||
throwHttpErr :: (MonadError QErr m) => HTTP.HttpException -> m a
|
||||
throwHttpErr _ = schemaErr $
|
||||
throwHttpErr = throwWithInternal httpExceptMsg . httpExceptToJSON
|
||||
|
||||
throwNon200 st = throwWithInternal (non200Msg st) . decodeNon200Resp
|
||||
|
||||
throwWithInternal msg v =
|
||||
let err = err400 RemoteSchemaError $ T.pack msg
|
||||
in throwError err{qeInternal = Just $ J.toJSON v}
|
||||
|
||||
httpExceptMsg =
|
||||
"HTTP exception occurred while sending the request to " <> show url
|
||||
|
||||
non200Msg st = "introspection query to " <> show url
|
||||
<> " has responded with " <> show st <> " status code"
|
||||
|
||||
decodeNon200Resp bs = case J.eitherDecode bs of
|
||||
Right a -> J.object ["response" J..= (a :: J.Value)]
|
||||
Left _ -> J.object ["raw_body" J..= bsToTxt (BL.toStrict bs)]
|
||||
|
||||
mergeSchemas
|
||||
:: (MonadIO m, MonadError QErr m)
|
||||
:: (MonadError QErr m)
|
||||
=> RemoteSchemaMap
|
||||
-> GS.GCtxMap
|
||||
-> HTTP.Manager
|
||||
-> m (GS.GCtxMap, GS.GCtx) -- the merged GCtxMap and the default GCtx without roles
|
||||
mergeSchemas rmSchemaMap gCtxMap httpManager = do
|
||||
remoteSchemas <- forM (Map.toList rmSchemaMap) $ \(name, def) ->
|
||||
fetchRemoteSchema httpManager name def
|
||||
-- the merged GCtxMap and the default GCtx without roles
|
||||
-> m (GS.GCtxMap, GS.GCtx)
|
||||
mergeSchemas rmSchemaMap gCtxMap = do
|
||||
def <- mkDefaultRemoteGCtx remoteSchemas
|
||||
merged <- mergeRemoteSchema gCtxMap def
|
||||
return (merged, def)
|
||||
where
|
||||
remoteSchemas = map rscGCtx $ Map.elems rmSchemaMap
|
||||
|
||||
mkDefaultRemoteGCtx
|
||||
:: (MonadError QErr m)
|
||||
=> [GS.RemoteGCtx] -> m GS.GCtx
|
||||
=> [GC.RemoteGCtx] -> m GS.GCtx
|
||||
mkDefaultRemoteGCtx =
|
||||
foldlM (\combG -> mergeGCtx combG . convRemoteGCtx) GS.emptyGCtx
|
||||
|
||||
@@ -126,12 +140,12 @@ mergeGCtx gCtx rmMergedGCtx = do
|
||||
}
|
||||
return updatedGCtx
|
||||
|
||||
convRemoteGCtx :: GS.RemoteGCtx -> GS.GCtx
|
||||
convRemoteGCtx :: GC.RemoteGCtx -> GS.GCtx
|
||||
convRemoteGCtx rmGCtx =
|
||||
GS.emptyGCtx { GS._gTypes = GS._rgTypes rmGCtx
|
||||
, GS._gQueryRoot = GS._rgQueryRoot rmGCtx
|
||||
, GS._gMutRoot = GS._rgMutationRoot rmGCtx
|
||||
, GS._gSubRoot = GS._rgSubscriptionRoot rmGCtx
|
||||
GS.emptyGCtx { GS._gTypes = GC._rgTypes rmGCtx
|
||||
, GS._gQueryRoot = GC._rgQueryRoot rmGCtx
|
||||
, GS._gMutRoot = GC._rgMutationRoot rmGCtx
|
||||
, GS._gSubRoot = GC._rgSubscriptionRoot rmGCtx
|
||||
}
|
||||
|
||||
|
||||
@@ -185,8 +199,8 @@ mergeTyMaps
|
||||
-> VT.TypeMap
|
||||
mergeTyMaps hTyMap rmTyMap newQR newMR =
|
||||
let newTyMap = hTyMap <> rmTyMap
|
||||
newTyMap' = Map.insert (G.NamedType "query_root") (VT.TIObj newQR) $
|
||||
newTyMap
|
||||
newTyMap' =
|
||||
Map.insert (G.NamedType "query_root") (VT.TIObj newQR) newTyMap
|
||||
in maybe newTyMap' (\mr -> Map.insert
|
||||
(G.NamedType "mutation_root")
|
||||
(VT.TIObj mr) newTyMap') newMR
|
||||
@@ -280,28 +294,6 @@ instance J.FromJSON (FromIntrospection G.ValueConst) where
|
||||
parseJSON = J.withText "defaultValue" $ \t -> fmap FromIntrospection
|
||||
$ either (fail . T.unpack) return $ G.parseValueConst t
|
||||
|
||||
-- instance J.FromJSON (FromIntrospection G.ListType) where
|
||||
-- parseJSON = parseJSON
|
||||
|
||||
-- instance (J.FromJSON (G.ObjectFieldG a)) =>
|
||||
-- J.FromJSON (FromIntrospection (G.ObjectValueG a)) where
|
||||
-- parseJSON = fmap (FromIntrospection . G.ObjectValueG) . J.parseJSON
|
||||
|
||||
-- instance (J.FromJSON a) => J.FromJSON (FromIntrospection (G.ObjectFieldG a)) where
|
||||
-- parseJSON = J.withObject "ObjectValueG a" $ \o -> do
|
||||
-- name <- o .: "name"
|
||||
-- ofVal <- o .: "value"
|
||||
-- return $ FromIntrospection $ G.ObjectFieldG name ofVal
|
||||
|
||||
-- instance J.FromJSON (FromIntrospection G.Value) where
|
||||
-- parseJSON =
|
||||
-- fmap FromIntrospection .
|
||||
-- $(J.mkParseJSON J.defaultOptions{J.sumEncoding=J.UntaggedValue} ''G.Value)
|
||||
|
||||
|
||||
-- $(J.deriveFromJSON J.defaultOptions{J.sumEncoding=J.UntaggedValue} ''G.Value)
|
||||
|
||||
|
||||
instance J.FromJSON (FromIntrospection G.InterfaceTypeDefinition) where
|
||||
parseJSON = J.withObject "InterfaceTypeDefinition" $ \o -> do
|
||||
kind <- o .: "kind"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module Hasura.GraphQL.Schema
|
||||
( mkGCtxMap
|
||||
, updateSCWithGCtx
|
||||
, GCtxMap
|
||||
, buildGCtxMapPG
|
||||
, getGCtx
|
||||
, GCtx(..)
|
||||
, OpCtx(..)
|
||||
@@ -11,7 +11,6 @@ module Hasura.GraphQL.Schema
|
||||
, isAggFld
|
||||
, qualObjectToName
|
||||
-- Schema stitching related
|
||||
, RemoteGCtx (..)
|
||||
, checkSchemaConflicts
|
||||
, checkConflictingNode
|
||||
, emptyGCtx
|
||||
@@ -20,7 +19,6 @@ module Hasura.GraphQL.Schema
|
||||
) where
|
||||
|
||||
|
||||
import Data.Has
|
||||
import Data.Maybe (maybeToList)
|
||||
|
||||
import qualified Data.HashMap.Strict as Map
|
||||
@@ -53,18 +51,6 @@ getTabInfo tc t =
|
||||
onNothing (Map.lookup t tc) $
|
||||
throw500 $ "table not found: " <>> t
|
||||
|
||||
data RemoteGCtx
|
||||
= RemoteGCtx
|
||||
{ _rgTypes :: !TypeMap
|
||||
, _rgQueryRoot :: !ObjTyInfo
|
||||
, _rgMutationRoot :: !(Maybe ObjTyInfo)
|
||||
, _rgSubscriptionRoot :: !(Maybe ObjTyInfo)
|
||||
} deriving (Show, Eq)
|
||||
|
||||
instance Has TypeMap RemoteGCtx where
|
||||
getter = _rgTypes
|
||||
modifier f ctx = ctx { _rgTypes = f $ _rgTypes ctx }
|
||||
|
||||
type SelField = Either PGColInfo (RelInfo, Bool, AnnBoolExpPartialSQL, Maybe Int, Bool)
|
||||
|
||||
qualObjectToName :: (ToTxt a) => QualifiedObject a -> G.Name
|
||||
@@ -265,7 +251,7 @@ mkTableObj
|
||||
-> [SelField]
|
||||
-> ObjTyInfo
|
||||
mkTableObj tn allowedFlds =
|
||||
mkObjTyInfo (Just desc) (mkTableTy tn) Set.empty (mapFromL _fiName flds) HasuraType
|
||||
mkObjTyInfo (Just desc) (mkTableTy tn) Set.empty (mapFromL _fiName flds) TLHasuraType
|
||||
where
|
||||
flds = concatMap (either (pure . mkPGColFld) mkRelFld') allowedFlds
|
||||
mkRelFld' (relInfo, allowAgg, _, _, isNullable) =
|
||||
@@ -1778,12 +1764,14 @@ mkGCtxMap tableCache functionCache = do
|
||||
tableFltr ti = not (tiSystemDefined ti)
|
||||
&& isValidObjectName (tiName ti)
|
||||
|
||||
updateSCWithGCtx
|
||||
:: (MonadError QErr m)
|
||||
=> SchemaCache -> m SchemaCache
|
||||
updateSCWithGCtx sc = do
|
||||
-- | build GraphQL schema from postgres tables and functions
|
||||
buildGCtxMapPG
|
||||
:: (QErrM m, CacheRWM m)
|
||||
=> m ()
|
||||
buildGCtxMapPG = do
|
||||
sc <- askSchemaCache
|
||||
gCtxMap <- mkGCtxMap (scTables sc) (scFunctions sc)
|
||||
return $ sc {scGCtxMap = gCtxMap}
|
||||
writeSchemaCache sc {scGCtxMap = gCtxMap}
|
||||
|
||||
getGCtx :: (CacheRM m) => RoleName -> GCtxMap -> m GCtx
|
||||
getGCtx rn ctxMap = do
|
||||
|
||||
@@ -126,8 +126,8 @@ type ParamMap = Map.HashMap G.Name InpValInfo
|
||||
|
||||
-- | location of the type: a hasura type or a remote type
|
||||
data TypeLoc
|
||||
= HasuraType
|
||||
| RemoteType RemoteSchemaName RemoteSchemaInfo
|
||||
= TLHasuraType
|
||||
| TLRemoteType !RemoteSchemaName !RemoteSchemaInfo
|
||||
deriving (Show, Eq, TH.Lift, Generic)
|
||||
|
||||
instance Hashable TypeLoc
|
||||
|
||||
@@ -41,7 +41,6 @@ import Hasura.RQL.Types
|
||||
import Hasura.SQL.Types
|
||||
|
||||
import qualified Database.PG.Query as Q
|
||||
import qualified Hasura.GraphQL.Schema as GS
|
||||
import qualified Hasura.RQL.DDL.EventTrigger as DE
|
||||
import qualified Hasura.RQL.DDL.Permission as DP
|
||||
import qualified Hasura.RQL.DDL.Permission.Internal as DP
|
||||
@@ -287,17 +286,10 @@ applyQP2 (ReplaceMetadata tables templates mFunctions mSchemas mCollections mAll
|
||||
-- remote schemas
|
||||
onJust mSchemas $ \schemas ->
|
||||
withPathK "remote_schemas" $
|
||||
indexedForM_ schemas $ \conf ->
|
||||
void $ DRS.addRemoteSchemaP1 conf
|
||||
>>= DRS.addRemoteSchemaP2 conf
|
||||
indexedMapM_ (void . DRS.addRemoteSchemaP2) schemas
|
||||
|
||||
-- build GraphQL Context
|
||||
sc <- GS.updateSCWithGCtx =<< askSchemaCache
|
||||
|
||||
-- resolve remote schemas
|
||||
httpMgr <- askHttpManager
|
||||
newSc <- DRS.resolveRemoteSchemas sc httpMgr
|
||||
writeSchemaCache newSc
|
||||
-- build GraphQL Context with Remote schemas
|
||||
DRS.buildGCtxMap
|
||||
|
||||
return successMsg
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
module Hasura.RQL.DDL.RemoteSchema
|
||||
( runAddRemoteSchema
|
||||
, addRemoteSchemaToCache
|
||||
, resolveRemoteSchemas
|
||||
, runRemoveRemoteSchema
|
||||
, removeRemoteSchemaFromCache
|
||||
, removeRemoteSchemaFromCatalog
|
||||
, refreshGCtxMapInSchema
|
||||
, runReloadRemoteSchema
|
||||
, buildGCtxMap
|
||||
, fetchRemoteSchemas
|
||||
, addRemoteSchemaP1
|
||||
, addRemoteSchemaP2Setup
|
||||
, addRemoteSchemaP2
|
||||
) where
|
||||
|
||||
@@ -17,10 +16,10 @@ import Hasura.Prelude
|
||||
import qualified Data.Aeson as J
|
||||
import qualified Data.HashMap.Strict as Map
|
||||
import qualified Database.PG.Query as Q
|
||||
import qualified Network.HTTP.Client as HTTP
|
||||
|
||||
import Hasura.GraphQL.RemoteServer
|
||||
import Hasura.RQL.Types
|
||||
import Hasura.SQL.Types
|
||||
|
||||
import qualified Hasura.GraphQL.Schema as GS
|
||||
|
||||
@@ -31,20 +30,30 @@ runAddRemoteSchema
|
||||
)
|
||||
=> AddRemoteSchemaQuery -> m EncJSON
|
||||
runAddRemoteSchema q = do
|
||||
addRemoteSchemaP1 q >>= addRemoteSchemaP2 q
|
||||
addRemoteSchemaP1 name >> addRemoteSchemaP2 q
|
||||
where
|
||||
name = _arsqName q
|
||||
|
||||
addRemoteSchemaP1
|
||||
:: ( QErrM m, UserInfoM m
|
||||
, MonadIO m, HasHttpManager m
|
||||
)
|
||||
=> AddRemoteSchemaQuery -> m RemoteSchemaInfo
|
||||
addRemoteSchemaP1 q = do
|
||||
:: (QErrM m, UserInfoM m, CacheRM m)
|
||||
=> RemoteSchemaName -> m ()
|
||||
addRemoteSchemaP1 name = do
|
||||
adminOnly
|
||||
remoteSchemaMap <- scRemoteSchemas <$> askSchemaCache
|
||||
onJust (Map.lookup name remoteSchemaMap) $ const $
|
||||
throw400 AlreadyExists $ "remote schema with name "
|
||||
<> name <<> " already exists"
|
||||
|
||||
addRemoteSchemaP2Setup
|
||||
:: (QErrM m, CacheRWM m, MonadIO m, HasHttpManager m)
|
||||
=> AddRemoteSchemaQuery -> m RemoteSchemaCtx
|
||||
addRemoteSchemaP2Setup q = do
|
||||
httpMgr <- askHttpManager
|
||||
rsi <- validateRemoteSchemaDef def
|
||||
-- TODO:- Maintain a cache of remote schema with it's GCtx
|
||||
void $ fetchRemoteSchema httpMgr name rsi
|
||||
return rsi
|
||||
gCtx <- fetchRemoteSchema httpMgr name rsi
|
||||
let rsCtx = RemoteSchemaCtx name gCtx rsi
|
||||
addRemoteSchemaToCache rsCtx
|
||||
return rsCtx
|
||||
where
|
||||
AddRemoteSchemaQuery name def _ = q
|
||||
|
||||
@@ -52,44 +61,19 @@ addRemoteSchemaP2
|
||||
:: ( QErrM m
|
||||
, CacheRWM m
|
||||
, MonadTx m
|
||||
, MonadIO m, HasHttpManager m
|
||||
)
|
||||
=> AddRemoteSchemaQuery
|
||||
-> RemoteSchemaInfo
|
||||
-> m EncJSON
|
||||
addRemoteSchemaP2 q rsi = do
|
||||
addRemoteSchemaToCache name rsi
|
||||
addRemoteSchemaP2 q = do
|
||||
void $ addRemoteSchemaP2Setup q
|
||||
liftTx $ addRemoteSchemaToCatalog q
|
||||
return successMsg
|
||||
where
|
||||
name = _arsqName q
|
||||
|
||||
addRemoteSchemaToCache
|
||||
:: CacheRWM m
|
||||
=> RemoteSchemaName
|
||||
-> RemoteSchemaInfo
|
||||
-> m ()
|
||||
addRemoteSchemaToCache name rmDef = do
|
||||
sc <- askSchemaCache
|
||||
let resolvers = scRemoteResolvers sc
|
||||
writeSchemaCache sc
|
||||
{scRemoteResolvers = Map.insert name rmDef resolvers}
|
||||
|
||||
refreshGCtxMapInSchema
|
||||
:: (CacheRWM m, MonadIO m, MonadError QErr m, HasHttpManager m)
|
||||
=> m ()
|
||||
refreshGCtxMapInSchema = do
|
||||
sc <- askSchemaCache
|
||||
gCtxMap <- GS.mkGCtxMap (scTables sc) (scFunctions sc)
|
||||
httpMgr <- askHttpManager
|
||||
(mergedGCtxMap, defGCtx) <-
|
||||
mergeSchemas (scRemoteResolvers sc) gCtxMap httpMgr
|
||||
writeSchemaCache sc { scGCtxMap = mergedGCtxMap
|
||||
, scDefaultRemoteGCtx = defGCtx }
|
||||
|
||||
runRemoveRemoteSchema
|
||||
:: (QErrM m, UserInfoM m, CacheRWM m, MonadTx m)
|
||||
=> RemoveRemoteSchemaQuery -> m EncJSON
|
||||
runRemoveRemoteSchema (RemoveRemoteSchemaQuery rsn)= do
|
||||
=> RemoteSchemaNameQuery -> m EncJSON
|
||||
runRemoveRemoteSchema (RemoteSchemaNameQuery rsn)= do
|
||||
removeRemoteSchemaP1 rsn
|
||||
removeRemoteSchemaP2 rsn
|
||||
|
||||
@@ -99,10 +83,9 @@ removeRemoteSchemaP1
|
||||
removeRemoteSchemaP1 rsn = do
|
||||
adminOnly
|
||||
sc <- askSchemaCache
|
||||
let resolvers = scRemoteResolvers sc
|
||||
case Map.lookup rsn resolvers of
|
||||
Just _ -> return ()
|
||||
Nothing -> throw400 NotExists "no such remote schema"
|
||||
let rmSchemas = scRemoteSchemas sc
|
||||
void $ onNothing (Map.lookup rsn rmSchemas) $
|
||||
throw400 NotExists "no such remote schema"
|
||||
|
||||
removeRemoteSchemaP2
|
||||
:: ( CacheRWM m
|
||||
@@ -111,30 +94,40 @@ removeRemoteSchemaP2
|
||||
=> RemoteSchemaName
|
||||
-> m EncJSON
|
||||
removeRemoteSchemaP2 rsn = do
|
||||
removeRemoteSchemaFromCache rsn
|
||||
delRemoteSchemaFromCache rsn
|
||||
liftTx $ removeRemoteSchemaFromCatalog rsn
|
||||
return successMsg
|
||||
|
||||
removeRemoteSchemaFromCache
|
||||
:: CacheRWM m => RemoteSchemaName -> m ()
|
||||
removeRemoteSchemaFromCache rsn = do
|
||||
sc <- askSchemaCache
|
||||
let resolvers = scRemoteResolvers sc
|
||||
writeSchemaCache sc {scRemoteResolvers = Map.delete rsn resolvers}
|
||||
|
||||
resolveRemoteSchemas
|
||||
:: ( MonadError QErr m
|
||||
, MonadIO m
|
||||
runReloadRemoteSchema
|
||||
:: ( QErrM m, UserInfoM m , CacheRWM m
|
||||
, MonadIO m, HasHttpManager m
|
||||
)
|
||||
=> SchemaCache -> HTTP.Manager -> m SchemaCache
|
||||
resolveRemoteSchemas sc httpMgr = do
|
||||
(mergedGCtxMap, defGCtx) <-
|
||||
mergeSchemas (scRemoteResolvers sc) gCtxMap httpMgr
|
||||
return $ sc { scGCtxMap = mergedGCtxMap
|
||||
, scDefaultRemoteGCtx = defGCtx
|
||||
}
|
||||
where
|
||||
gCtxMap = scGCtxMap sc
|
||||
=> RemoteSchemaNameQuery -> m EncJSON
|
||||
runReloadRemoteSchema (RemoteSchemaNameQuery name) = do
|
||||
adminOnly
|
||||
rmSchemas <- scRemoteSchemas <$> askSchemaCache
|
||||
rsi <- fmap rscInfo $ onNothing (Map.lookup name rmSchemas) $
|
||||
throw400 NotExists $ "remote schema with name "
|
||||
<> name <<> " does not exist"
|
||||
httpMgr <- askHttpManager
|
||||
gCtx <- fetchRemoteSchema httpMgr name rsi
|
||||
delRemoteSchemaFromCache name
|
||||
addRemoteSchemaToCache $ RemoteSchemaCtx name gCtx rsi
|
||||
return successMsg
|
||||
|
||||
-- | build GraphQL schema
|
||||
buildGCtxMap
|
||||
:: (QErrM m, CacheRWM m) => m ()
|
||||
buildGCtxMap = do
|
||||
-- build GraphQL Context with Hasura schema
|
||||
GS.buildGCtxMapPG
|
||||
sc <- askSchemaCache
|
||||
let gCtxMap = scGCtxMap sc
|
||||
-- Stitch remote schemas
|
||||
(mergedGCtxMap, defGCtx) <- mergeSchemas (scRemoteSchemas sc) gCtxMap
|
||||
writeSchemaCache sc { scGCtxMap = mergedGCtxMap
|
||||
, scDefaultRemoteGCtx = defGCtx
|
||||
}
|
||||
|
||||
addRemoteSchemaToCatalog
|
||||
:: AddRemoteSchemaQuery
|
||||
|
||||
@@ -65,7 +65,7 @@ trackExistingTableOrViewP1 (TrackTable vn) = do
|
||||
throw400 AlreadyTracked $ "view/table already tracked : " <>> vn
|
||||
|
||||
trackExistingTableOrViewP2
|
||||
:: (QErrM m, CacheRWM m, MonadTx m, MonadIO m, HasHttpManager m)
|
||||
:: (QErrM m, CacheRWM m, MonadTx m)
|
||||
=> QualifiedTable -> Bool -> m EncJSON
|
||||
trackExistingTableOrViewP2 vn isSystemDefined = do
|
||||
sc <- askSchemaCache
|
||||
@@ -79,9 +79,6 @@ trackExistingTableOrViewP2 vn isSystemDefined = do
|
||||
_ -> throw500 $ "more than one row found for: " <>> vn
|
||||
liftTx $ Q.catchE defaultTxErrorHandler $ saveTableToCatalog vn
|
||||
|
||||
-- refresh the gCtx in schema cache
|
||||
refreshGCtxMapInSchema
|
||||
|
||||
return successMsg
|
||||
where
|
||||
QualifiedObject sn tn = vn
|
||||
@@ -99,9 +96,7 @@ trackExistingTableOrViewP2 vn isSystemDefined = do
|
||||
|] (sn, tn) True
|
||||
|
||||
runTrackTableQ
|
||||
:: ( QErrM m, CacheRWM m, MonadTx m
|
||||
, MonadIO m, HasHttpManager m, UserInfoM m
|
||||
)
|
||||
:: (QErrM m, CacheRWM m, MonadTx m, UserInfoM m)
|
||||
=> TrackTable -> m EncJSON
|
||||
runTrackTableQ q = do
|
||||
trackExistingTableOrViewP1 q
|
||||
@@ -257,7 +252,7 @@ unTrackExistingTableOrViewP1 (UntrackTable vn _) = do
|
||||
"view/table already untracked : " <>> vn
|
||||
|
||||
unTrackExistingTableOrViewP2
|
||||
:: (QErrM m, CacheRWM m, MonadTx m, MonadIO m, HasHttpManager m)
|
||||
:: (QErrM m, CacheRWM m, MonadTx m)
|
||||
=> UntrackTable -> m EncJSON
|
||||
unTrackExistingTableOrViewP2 (UntrackTable qtn cascade) = do
|
||||
sc <- askSchemaCache
|
||||
@@ -275,9 +270,6 @@ unTrackExistingTableOrViewP2 (UntrackTable qtn cascade) = do
|
||||
-- delete the table and its direct dependencies
|
||||
delTableAndDirectDeps qtn
|
||||
|
||||
-- refresh the gctxmap in schema cache
|
||||
refreshGCtxMapInSchema
|
||||
|
||||
return successMsg
|
||||
where
|
||||
isDirectDep = \case
|
||||
@@ -285,9 +277,7 @@ unTrackExistingTableOrViewP2 (UntrackTable qtn cascade) = do
|
||||
_ -> False
|
||||
|
||||
runUntrackTableQ
|
||||
:: ( QErrM m, CacheRWM m, MonadTx m
|
||||
, MonadIO m, HasHttpManager m, UserInfoM m
|
||||
)
|
||||
:: (QErrM m, CacheRWM m, MonadTx m, UserInfoM m)
|
||||
=> UntrackTable -> m EncJSON
|
||||
runUntrackTableQ q = do
|
||||
unTrackExistingTableOrViewP1 q
|
||||
@@ -349,7 +339,6 @@ buildSchemaCacheG withSetup = do
|
||||
when withSetup $ liftTx $ Q.catchE defaultTxErrorHandler clearHdbViews
|
||||
-- reset the current schemacache
|
||||
writeSchemaCache emptySchemaCache
|
||||
hMgr <- askHttpManager
|
||||
sqlGenCtx <- askSQLGenCtx
|
||||
|
||||
-- fetch all catalog metadata
|
||||
@@ -442,12 +431,11 @@ buildSchemaCacheG withSetup = do
|
||||
-- allow list
|
||||
replaceAllowlist $ concatMap _cdQueries allowlistDefs
|
||||
|
||||
-- build GraphQL context
|
||||
postGCtxSc <- askSchemaCache >>= GS.updateSCWithGCtx
|
||||
writeSchemaCache postGCtxSc
|
||||
-- build GraphQL context with tables and functions
|
||||
GS.buildGCtxMapPG
|
||||
|
||||
-- remote schemas
|
||||
forM_ remoteSchemas $ resolveSingleRemoteSchema hMgr
|
||||
forM_ remoteSchemas resolveSingleRemoteSchema
|
||||
|
||||
where
|
||||
permHelper setup sqlGenCtx qt rn pDef pa = do
|
||||
@@ -460,17 +448,16 @@ buildSchemaCacheG withSetup = do
|
||||
addPermToCache qt rn pa permInfo deps
|
||||
-- p2F qt rn p1Res
|
||||
|
||||
resolveSingleRemoteSchema hMgr rs = do
|
||||
let AddRemoteSchemaQuery name def _ = rs
|
||||
resolveSingleRemoteSchema rs = do
|
||||
let AddRemoteSchemaQuery name _ _ = rs
|
||||
mkInconsObj = InconsistentMetadataObj (MORemoteSchema name)
|
||||
MOTRemoteSchema (toJSON rs)
|
||||
handleInconsistentObj mkInconsObj $ do
|
||||
rsi <- validateRemoteSchemaDef def
|
||||
addRemoteSchemaToCache name rsi
|
||||
rsCtx <- addRemoteSchemaP2Setup rs
|
||||
sc <- askSchemaCache
|
||||
let gCtxMap = scGCtxMap sc
|
||||
defGCtx = scDefaultRemoteGCtx sc
|
||||
rGCtx <- convRemoteGCtx <$> fetchRemoteSchema hMgr name rsi
|
||||
rGCtx = convRemoteGCtx $ rscGCtx rsCtx
|
||||
mergedGCtxMap <- mergeRemoteSchema gCtxMap rGCtx
|
||||
mergedDefGCtx <- mergeGCtx defGCtx rGCtx
|
||||
writeSchemaCache sc { scGCtxMap = mergedGCtxMap
|
||||
@@ -599,9 +586,6 @@ execWithMDCheck (RunSQL t cascade _) = do
|
||||
|
||||
bool withoutReload withReload reloadRequired
|
||||
|
||||
-- refresh the gCtxMap in schema cache
|
||||
refreshGCtxMapInSchema
|
||||
|
||||
return res
|
||||
where
|
||||
reportFuncs = T.intercalate ", " . map dquoteTxt
|
||||
|
||||
@@ -7,20 +7,22 @@ import System.Environment (lookupEnv)
|
||||
import qualified Data.Aeson as J
|
||||
import qualified Data.Aeson.Casing as J
|
||||
import qualified Data.Aeson.TH as J
|
||||
import qualified Data.HashMap.Strict as Map
|
||||
import qualified Data.Text as T
|
||||
import qualified Database.PG.Query as Q
|
||||
import qualified Network.URI.Extended as N
|
||||
|
||||
import Hasura.RQL.DDL.Headers (HeaderConf (..))
|
||||
import Hasura.RQL.Types.Error
|
||||
import Hasura.SQL.Types (DQuote)
|
||||
|
||||
type UrlFromEnv = Text
|
||||
|
||||
newtype RemoteSchemaName
|
||||
= RemoteSchemaName
|
||||
{ unRemoteSchemaName :: Text}
|
||||
deriving (Show, Eq, Lift, Hashable, J.ToJSON, J.ToJSONKey, J.FromJSON, Q.ToPrepArg, Q.FromCol)
|
||||
deriving ( Show, Eq, Lift, Hashable, J.ToJSON, J.ToJSONKey
|
||||
, J.FromJSON, Q.ToPrepArg, Q.FromCol, DQuote
|
||||
)
|
||||
|
||||
data RemoteSchemaInfo
|
||||
= RemoteSchemaInfo
|
||||
@@ -43,25 +45,6 @@ data RemoteSchemaDef
|
||||
|
||||
$(J.deriveJSON (J.aesonDrop 4 J.snakeCase) ''RemoteSchemaDef)
|
||||
|
||||
type RemoteSchemaMap = Map.HashMap RemoteSchemaName RemoteSchemaInfo
|
||||
|
||||
-- instance J.ToJSON RemoteSchemaDef where
|
||||
-- toJSON (RemoteSchemaDef name eUrlVal headers fwdHdrs) =
|
||||
-- case eUrlVal of
|
||||
-- Left url ->
|
||||
-- J.object [ "url" J..= url
|
||||
-- , "headers" J..= headers
|
||||
-- , "name" J..= name
|
||||
-- , "forward_client_headers" J..= fwdHdrs
|
||||
-- ]
|
||||
-- Right urlFromEnv ->
|
||||
-- J.object [ "url_from_env" J..= urlFromEnv
|
||||
-- , "headers" J..= headers
|
||||
-- , "name" J..= name
|
||||
-- , "forward_client_headers" J..= fwdHdrs
|
||||
-- ]
|
||||
|
||||
|
||||
data AddRemoteSchemaQuery
|
||||
= AddRemoteSchemaQuery
|
||||
{ _arsqName :: !RemoteSchemaName -- TODO: name validation: cannot be empty?
|
||||
@@ -71,20 +54,12 @@ data AddRemoteSchemaQuery
|
||||
|
||||
$(J.deriveJSON (J.aesonDrop 5 J.snakeCase) ''AddRemoteSchemaQuery)
|
||||
|
||||
-- data AddRemoteSchemaQuery'
|
||||
-- = AddRemoteSchemaQuery'
|
||||
-- { _arsqUrl :: !(Maybe N.URI)
|
||||
-- , _arsqUrlFromEnv :: !(Maybe Text)
|
||||
-- , _arsqHeaders :: !(Maybe [HeaderConf])
|
||||
-- , _arsqForwardClientHeaders :: !Bool
|
||||
-- } deriving (Show, Eq, Lift)
|
||||
|
||||
data RemoveRemoteSchemaQuery
|
||||
= RemoveRemoteSchemaQuery
|
||||
{ _rrsqName :: !RemoteSchemaName
|
||||
newtype RemoteSchemaNameQuery
|
||||
= RemoteSchemaNameQuery
|
||||
{ _rsnqName :: RemoteSchemaName
|
||||
} deriving (Show, Eq, Lift)
|
||||
|
||||
$(J.deriveJSON (J.aesonDrop 5 J.snakeCase) ''RemoveRemoteSchemaQuery)
|
||||
$(J.deriveJSON (J.aesonDrop 5 J.snakeCase) ''RemoteSchemaNameQuery)
|
||||
|
||||
getUrlFromEnv :: (MonadIO m, MonadError QErr m) => Text -> m N.URI
|
||||
getUrlFromEnv urlFromEnv = do
|
||||
|
||||
@@ -24,6 +24,11 @@ module Hasura.RQL.Types.SchemaCache
|
||||
, modTableInCache
|
||||
, delTableFromCache
|
||||
|
||||
, RemoteSchemaCtx(..)
|
||||
, RemoteSchemaMap
|
||||
, addRemoteSchemaToCache
|
||||
, delRemoteSchemaFromCache
|
||||
|
||||
, WithDeps
|
||||
|
||||
, CacheRM(..)
|
||||
@@ -103,6 +108,7 @@ module Hasura.RQL.Types.SchemaCache
|
||||
) where
|
||||
|
||||
import qualified Hasura.GraphQL.Context as GC
|
||||
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.BoolExp
|
||||
import Hasura.RQL.Types.Common
|
||||
@@ -410,6 +416,18 @@ $(deriveToJSON (aesonDrop 2 snakeCase) ''FunctionInfo)
|
||||
type TableCache = M.HashMap QualifiedTable TableInfo -- info of all tables
|
||||
type FunctionCache = M.HashMap QualifiedFunction FunctionInfo -- info of all functions
|
||||
|
||||
data RemoteSchemaCtx
|
||||
= RemoteSchemaCtx
|
||||
{ rscName :: !RemoteSchemaName
|
||||
, rscGCtx :: !GC.RemoteGCtx
|
||||
, rscInfo :: !RemoteSchemaInfo
|
||||
} deriving (Show, Eq)
|
||||
|
||||
instance ToJSON RemoteSchemaCtx where
|
||||
toJSON = toJSON . rscInfo
|
||||
|
||||
type RemoteSchemaMap = M.HashMap RemoteSchemaName RemoteSchemaCtx
|
||||
|
||||
type DepMap = M.HashMap SchemaObjId (HS.HashSet SchemaDependency)
|
||||
|
||||
addToDepMap :: SchemaObjId -> [SchemaDependency] -> DepMap -> DepMap
|
||||
@@ -443,8 +461,8 @@ data SchemaCache
|
||||
{ scTables :: !TableCache
|
||||
, scFunctions :: !FunctionCache
|
||||
, scQTemplates :: !QTemplateCache
|
||||
, scRemoteSchemas :: !RemoteSchemaMap
|
||||
, scAllowlist :: !(HS.HashSet GQLQuery)
|
||||
, scRemoteResolvers :: !RemoteSchemaMap
|
||||
, scGCtxMap :: !GC.GCtxMap
|
||||
, scDefaultRemoteGCtx :: !GC.GCtx
|
||||
, scDepMap :: !DepMap
|
||||
@@ -513,8 +531,8 @@ delQTemplateFromCache qtn = do
|
||||
|
||||
emptySchemaCache :: SchemaCache
|
||||
emptySchemaCache =
|
||||
SchemaCache M.empty M.empty M.empty HS.empty
|
||||
M.empty M.empty GC.emptyGCtx mempty []
|
||||
SchemaCache M.empty M.empty M.empty M.empty
|
||||
HS.empty M.empty GC.emptyGCtx mempty []
|
||||
|
||||
modTableCache :: (CacheRWM m) => TableCache -> m ()
|
||||
modTableCache tc = do
|
||||
@@ -789,6 +807,32 @@ data TemplateParamInfo
|
||||
, tpiDefault :: !(Maybe Value)
|
||||
} deriving (Show, Eq)
|
||||
|
||||
addRemoteSchemaToCache
|
||||
:: (QErrM m, CacheRWM m) => RemoteSchemaCtx -> m ()
|
||||
addRemoteSchemaToCache rmCtx = do
|
||||
sc <- askSchemaCache
|
||||
let rmSchemas = scRemoteSchemas sc
|
||||
name = rscName rmCtx
|
||||
-- ideally, remote schema shouldn't present in cache
|
||||
-- if present unexpected 500 is thrown
|
||||
onJust (M.lookup name rmSchemas) $ const $
|
||||
throw500 $ "remote schema with name " <> name
|
||||
<<> " already found in cache"
|
||||
writeSchemaCache sc
|
||||
{scRemoteSchemas = M.insert name rmCtx rmSchemas}
|
||||
|
||||
delRemoteSchemaFromCache
|
||||
:: (QErrM m, CacheRWM m) => RemoteSchemaName -> m ()
|
||||
delRemoteSchemaFromCache name = do
|
||||
sc <- askSchemaCache
|
||||
let rmSchemas = scRemoteSchemas sc
|
||||
-- ideally, remote schema should be present in cache
|
||||
-- if not present unexpected 500 is thrown
|
||||
void $ onNothing (M.lookup name rmSchemas) $
|
||||
throw500 $ "remote schema with name " <> name
|
||||
<<> " not found in cache"
|
||||
writeSchemaCache sc {scRemoteSchemas = M.delete name rmSchemas}
|
||||
|
||||
replaceAllowlist
|
||||
:: (CacheRWM m)
|
||||
=> QueryList -> m ()
|
||||
|
||||
@@ -35,7 +35,6 @@ import qualified Database.PG.Query as Q
|
||||
import qualified Hasura.GraphQL.Execute as E
|
||||
import qualified Hasura.GraphQL.Execute.LiveQuery as EL
|
||||
import qualified Hasura.GraphQL.Explain as GE
|
||||
import qualified Hasura.GraphQL.Schema as GS
|
||||
import qualified Hasura.GraphQL.Transport.HTTP as GH
|
||||
import qualified Hasura.GraphQL.Transport.HTTP.Protocol as GH
|
||||
import qualified Hasura.GraphQL.Transport.WebSocket as WS
|
||||
@@ -43,7 +42,6 @@ import qualified Hasura.Logging as L
|
||||
|
||||
import Hasura.EncJSON
|
||||
import Hasura.Prelude hiding (get, put)
|
||||
import Hasura.RQL.DDL.RemoteSchema
|
||||
import Hasura.RQL.DDL.Schema.Table
|
||||
import Hasura.RQL.DML.QueryTemplate
|
||||
import Hasura.RQL.Types
|
||||
@@ -188,7 +186,7 @@ logResult
|
||||
-> Either QErr BL.ByteString -> Maybe (UTCTime, UTCTime)
|
||||
-> m ()
|
||||
logResult userInfoM req reqBody logger res qTime =
|
||||
liftIO $ (L.unLogger logger) $ mkAccessLog userInfoM req (reqBody, res) qTime
|
||||
liftIO $ L.unLogger logger $ mkAccessLog userInfoM req (reqBody, res) qTime
|
||||
|
||||
logError
|
||||
:: MonadIO m
|
||||
@@ -254,7 +252,7 @@ v1QueryHandler :: RQLQuery -> Handler (HttpResponse EncJSON)
|
||||
v1QueryHandler query = do
|
||||
scRef <- scCacheRef . hcServerCtx <$> ask
|
||||
logger <- scLogger . hcServerCtx <$> ask
|
||||
res <- bool (fst <$> dbAction) (withSCUpdate scRef logger dbActionReload) $
|
||||
res <- bool (fst <$> dbAction) (withSCUpdate scRef logger dbAction) $
|
||||
queryNeedsReload query
|
||||
return $ HttpResponse res Nothing
|
||||
where
|
||||
@@ -269,14 +267,6 @@ v1QueryHandler query = do
|
||||
instanceId <- scInstanceId . hcServerCtx <$> ask
|
||||
runQuery pgExecCtx instanceId userInfo schemaCache httpMgr sqlGenCtx query
|
||||
|
||||
-- Also update the schema cache
|
||||
dbActionReload = do
|
||||
(resp, newSc) <- dbAction
|
||||
httpMgr <- scManager . hcServerCtx <$> ask
|
||||
--FIXME: should we be fetching the remote schema again? if not how do we get the remote schema?
|
||||
newSc' <- GS.updateSCWithGCtx newSc >>= flip resolveRemoteSchemas httpMgr
|
||||
return (resp, newSc')
|
||||
|
||||
v1Alpha1GQHandler :: GH.GQLReqUnparsed -> Handler (HttpResponse EncJSON)
|
||||
v1Alpha1GQHandler query = do
|
||||
userInfo <- asks hcUser
|
||||
@@ -335,7 +325,7 @@ consoleAssetsHandler logger dir path = do
|
||||
headers = ("Content-Type", mimeType) : encHeader
|
||||
|
||||
mkConsoleHTML :: T.Text -> AuthMode -> Bool -> Maybe Text -> Either String T.Text
|
||||
mkConsoleHTML path authMode enableTelemetry consoleAssetsDir = do
|
||||
mkConsoleHTML path authMode enableTelemetry consoleAssetsDir =
|
||||
bool (Left errMsg) (Right res) $ null errs
|
||||
where
|
||||
(errs, res) = M.checkedSubstitute consoleTmplt $
|
||||
@@ -451,8 +441,7 @@ httpApp corsCfg serverCtx enableConsole consoleAssetsDir enableTelemetry = do
|
||||
middleware $ corsMiddleware (mkDefaultCorsPolicy corsCfg)
|
||||
|
||||
-- API Console and Root Dir
|
||||
when (enableConsole && enableMetadata) $ do
|
||||
serveApiConsole
|
||||
when (enableConsole && enableMetadata) serveApiConsole
|
||||
|
||||
-- Health check endpoint
|
||||
get "healthz" $ do
|
||||
|
||||
@@ -68,7 +68,8 @@ data RQLQuery
|
||||
|
||||
-- schema-stitching, custom resolver related
|
||||
| RQAddRemoteSchema !AddRemoteSchemaQuery
|
||||
| RQRemoveRemoteSchema !RemoveRemoteSchemaQuery
|
||||
| RQRemoveRemoteSchema !RemoteSchemaNameQuery
|
||||
| RQReloadRemoteSchema !RemoteSchemaNameQuery
|
||||
|
||||
| RQCreateEventTrigger !CreateEventTriggerQuery
|
||||
| RQDeleteEventTrigger !DeleteEventTriggerQuery
|
||||
@@ -214,6 +215,7 @@ queryNeedsReload qi = case qi of
|
||||
|
||||
RQAddRemoteSchema _ -> True
|
||||
RQRemoveRemoteSchema _ -> True
|
||||
RQReloadRemoteSchema _ -> True
|
||||
|
||||
RQCreateEventTrigger _ -> True
|
||||
RQDeleteEventTrigger _ -> True
|
||||
@@ -249,67 +251,73 @@ runQueryM
|
||||
)
|
||||
=> RQLQuery
|
||||
-> m EncJSON
|
||||
runQueryM rq = withPathK "args" $ case rq of
|
||||
RQAddExistingTableOrView q -> runTrackTableQ q
|
||||
RQTrackTable q -> runTrackTableQ q
|
||||
RQUntrackTable q -> runUntrackTableQ q
|
||||
runQueryM rq =
|
||||
withPathK "args" $ runQueryM' <* rebuildGCtx
|
||||
where
|
||||
rebuildGCtx = when (queryNeedsReload rq) buildGCtxMap
|
||||
|
||||
RQTrackFunction q -> runTrackFunc q
|
||||
RQUntrackFunction q -> runUntrackFunc q
|
||||
runQueryM' = case rq of
|
||||
RQAddExistingTableOrView q -> runTrackTableQ q
|
||||
RQTrackTable q -> runTrackTableQ q
|
||||
RQUntrackTable q -> runUntrackTableQ q
|
||||
|
||||
RQCreateObjectRelationship q -> runCreateObjRel q
|
||||
RQCreateArrayRelationship q -> runCreateArrRel q
|
||||
RQDropRelationship q -> runDropRel q
|
||||
RQSetRelationshipComment q -> runSetRelComment q
|
||||
RQRenameRelationship q -> runRenameRel q
|
||||
RQTrackFunction q -> runTrackFunc q
|
||||
RQUntrackFunction q -> runUntrackFunc q
|
||||
|
||||
RQCreateInsertPermission q -> runCreatePerm q
|
||||
RQCreateSelectPermission q -> runCreatePerm q
|
||||
RQCreateUpdatePermission q -> runCreatePerm q
|
||||
RQCreateDeletePermission q -> runCreatePerm q
|
||||
RQCreateObjectRelationship q -> runCreateObjRel q
|
||||
RQCreateArrayRelationship q -> runCreateArrRel q
|
||||
RQDropRelationship q -> runDropRel q
|
||||
RQSetRelationshipComment q -> runSetRelComment q
|
||||
RQRenameRelationship q -> runRenameRel q
|
||||
|
||||
RQDropInsertPermission q -> runDropPerm q
|
||||
RQDropSelectPermission q -> runDropPerm q
|
||||
RQDropUpdatePermission q -> runDropPerm q
|
||||
RQDropDeletePermission q -> runDropPerm q
|
||||
RQSetPermissionComment q -> runSetPermComment q
|
||||
RQCreateInsertPermission q -> runCreatePerm q
|
||||
RQCreateSelectPermission q -> runCreatePerm q
|
||||
RQCreateUpdatePermission q -> runCreatePerm q
|
||||
RQCreateDeletePermission q -> runCreatePerm q
|
||||
|
||||
RQGetInconsistentMetadata q -> runGetInconsistentMetadata q
|
||||
RQDropInconsistentMetadata q -> runDropInconsistentMetadata q
|
||||
RQDropInsertPermission q -> runDropPerm q
|
||||
RQDropSelectPermission q -> runDropPerm q
|
||||
RQDropUpdatePermission q -> runDropPerm q
|
||||
RQDropDeletePermission q -> runDropPerm q
|
||||
RQSetPermissionComment q -> runSetPermComment q
|
||||
|
||||
RQInsert q -> runInsert q
|
||||
RQSelect q -> runSelect q
|
||||
RQUpdate q -> runUpdate q
|
||||
RQDelete q -> runDelete q
|
||||
RQCount q -> runCount q
|
||||
RQGetInconsistentMetadata q -> runGetInconsistentMetadata q
|
||||
RQDropInconsistentMetadata q -> runDropInconsistentMetadata q
|
||||
|
||||
RQAddRemoteSchema q -> runAddRemoteSchema q
|
||||
RQRemoveRemoteSchema q -> runRemoveRemoteSchema q
|
||||
RQInsert q -> runInsert q
|
||||
RQSelect q -> runSelect q
|
||||
RQUpdate q -> runUpdate q
|
||||
RQDelete q -> runDelete q
|
||||
RQCount q -> runCount q
|
||||
|
||||
RQCreateEventTrigger q -> runCreateEventTriggerQuery q
|
||||
RQDeleteEventTrigger q -> runDeleteEventTriggerQuery q
|
||||
RQRedeliverEvent q -> runRedeliverEvent q
|
||||
RQInvokeEventTrigger q -> runInvokeEventTrigger q
|
||||
RQAddRemoteSchema q -> runAddRemoteSchema q
|
||||
RQRemoveRemoteSchema q -> runRemoveRemoteSchema q
|
||||
RQReloadRemoteSchema q -> runReloadRemoteSchema q
|
||||
|
||||
RQCreateQueryTemplate q -> runCreateQueryTemplate q
|
||||
RQDropQueryTemplate q -> runDropQueryTemplate q
|
||||
RQExecuteQueryTemplate q -> runExecQueryTemplate q
|
||||
RQSetQueryTemplateComment q -> runSetQueryTemplateComment q
|
||||
RQCreateEventTrigger q -> runCreateEventTriggerQuery q
|
||||
RQDeleteEventTrigger q -> runDeleteEventTriggerQuery q
|
||||
RQRedeliverEvent q -> runRedeliverEvent q
|
||||
RQInvokeEventTrigger q -> runInvokeEventTrigger q
|
||||
|
||||
RQCreateQueryCollection q -> runCreateCollection q
|
||||
RQDropQueryCollection q -> runDropCollection q
|
||||
RQAddQueryToCollection q -> runAddQueryToCollection q
|
||||
RQDropQueryFromCollection q -> runDropQueryFromCollection q
|
||||
RQAddCollectionToAllowlist q -> runAddCollectionToAllowlist q
|
||||
RQDropCollectionFromAllowlist q -> runDropCollectionFromAllowlist q
|
||||
RQCreateQueryTemplate q -> runCreateQueryTemplate q
|
||||
RQDropQueryTemplate q -> runDropQueryTemplate q
|
||||
RQExecuteQueryTemplate q -> runExecQueryTemplate q
|
||||
RQSetQueryTemplateComment q -> runSetQueryTemplateComment q
|
||||
|
||||
RQReplaceMetadata q -> runReplaceMetadata q
|
||||
RQClearMetadata q -> runClearMetadata q
|
||||
RQExportMetadata q -> runExportMetadata q
|
||||
RQReloadMetadata q -> runReloadMetadata q
|
||||
RQCreateQueryCollection q -> runCreateCollection q
|
||||
RQDropQueryCollection q -> runDropCollection q
|
||||
RQAddQueryToCollection q -> runAddQueryToCollection q
|
||||
RQDropQueryFromCollection q -> runDropQueryFromCollection q
|
||||
RQAddCollectionToAllowlist q -> runAddCollectionToAllowlist q
|
||||
RQDropCollectionFromAllowlist q -> runDropCollectionFromAllowlist q
|
||||
|
||||
RQDumpInternalState q -> runDumpInternalState q
|
||||
RQReplaceMetadata q -> runReplaceMetadata q
|
||||
RQClearMetadata q -> runClearMetadata q
|
||||
RQExportMetadata q -> runExportMetadata q
|
||||
RQReloadMetadata q -> runReloadMetadata q
|
||||
|
||||
RQRunSql q -> runRunSQL q
|
||||
RQDumpInternalState q -> runDumpInternalState q
|
||||
|
||||
RQBulk qs -> encJFromList <$> indexedMapM runQueryM qs
|
||||
RQRunSql q -> runRunSQL q
|
||||
|
||||
RQBulk qs -> encJFromList <$> indexedMapM runQueryM qs
|
||||
|
||||
@@ -145,7 +145,7 @@ computeMetrics sc =
|
||||
PermissionMetric selPerms insPerms updPerms delPerms nRoles
|
||||
evtTriggers = Map.size $ Map.filter (not . Map.null)
|
||||
$ Map.map tiEventTriggerInfoMap usrTbls
|
||||
rmSchemas = Map.size $ scRemoteResolvers sc
|
||||
rmSchemas = Map.size $ scRemoteSchemas sc
|
||||
funcs = Map.size $ Map.filter (not . fiSystemDefined) $ scFunctions sc
|
||||
|
||||
in Metrics nTables nViews relMetrics permMetrics evtTriggers rmSchemas funcs
|
||||
|
||||
@@ -17,6 +17,7 @@ import qualified Data.Text.Encoding as TE
|
||||
import qualified Data.Text.Encoding.Error as TE
|
||||
import qualified Data.Text.IO as TI
|
||||
import qualified Language.Haskell.TH.Syntax as TH
|
||||
import qualified Network.HTTP.Client as HC
|
||||
import qualified Network.HTTP.Types as HTTP
|
||||
import qualified Text.Ginger as TG
|
||||
import qualified Text.Regex.TDFA as TDFA
|
||||
@@ -166,8 +167,29 @@ diffTimeToMicro diff =
|
||||
where
|
||||
aSecond = 1000 * 1000
|
||||
|
||||
-- ignore the following request headers from the client
|
||||
-- json representation of HTTP exception
|
||||
httpExceptToJSON :: HC.HttpException -> Value
|
||||
httpExceptToJSON e = case e of
|
||||
HC.HttpExceptionRequest x c ->
|
||||
let reqObj = object
|
||||
[ "host" .= bsToTxt (HC.host x)
|
||||
, "port" .= show (HC.port x)
|
||||
, "secure" .= HC.secure x
|
||||
, "path" .= bsToTxt (HC.path x)
|
||||
, "method" .= bsToTxt (HC.method x)
|
||||
, "proxy" .= (showProxy <$> HC.proxy x)
|
||||
, "redirectCount" .= show (HC.redirectCount x)
|
||||
, "responseTimeout" .= show (HC.responseTimeout x)
|
||||
, "requestVersion" .= show (HC.requestVersion x)
|
||||
]
|
||||
msg = show c
|
||||
in object ["request" .= reqObj, "message" .= msg]
|
||||
_ -> toJSON $ show e
|
||||
where
|
||||
showProxy (HC.Proxy h p) =
|
||||
"host: " <> bsToTxt h <> " port: " <> T.pack (show p)
|
||||
|
||||
-- ignore the following request headers from the client
|
||||
commonClientHeadersIgnored :: (IsString a) => [a]
|
||||
commonClientHeadersIgnored =
|
||||
[ "Content-Length", "Content-MD5", "User-Agent", "Host"
|
||||
|
||||
Reference in New Issue
Block a user