2018-07-20 10:22:46 +03:00
|
|
|
module Hasura.GraphQL.Resolve
|
|
|
|
( resolveSelSet
|
|
|
|
) where
|
|
|
|
|
|
|
|
import Hasura.Prelude
|
|
|
|
|
|
|
|
import qualified Data.Aeson as J
|
|
|
|
import qualified Data.ByteString.Lazy as BL
|
|
|
|
import qualified Data.HashMap.Strict as Map
|
|
|
|
import qualified Database.PG.Query as Q
|
|
|
|
import qualified Language.GraphQL.Draft.Syntax as G
|
|
|
|
|
2018-11-23 16:02:46 +03:00
|
|
|
|
2019-02-22 13:27:38 +03:00
|
|
|
import Hasura.GraphQL.Context
|
2018-07-20 10:22:46 +03:00
|
|
|
import Hasura.GraphQL.Resolve.Context
|
|
|
|
import Hasura.GraphQL.Resolve.Introspect
|
|
|
|
import Hasura.GraphQL.Transport.HTTP.Protocol
|
|
|
|
import Hasura.GraphQL.Validate.Field
|
|
|
|
import Hasura.RQL.Types
|
|
|
|
import Hasura.SQL.Types
|
|
|
|
|
2018-10-05 18:13:51 +03:00
|
|
|
import qualified Hasura.GraphQL.Resolve.Insert as RI
|
2018-07-20 10:22:46 +03:00
|
|
|
import qualified Hasura.GraphQL.Resolve.Mutation as RM
|
|
|
|
import qualified Hasura.GraphQL.Resolve.Select as RS
|
|
|
|
|
|
|
|
-- {-# SCC buildTx #-}
|
2019-03-01 14:45:04 +03:00
|
|
|
buildTx :: UserInfo -> GCtx -> SQLGenCtx -> Field -> Q.TxE QErr BL.ByteString
|
|
|
|
buildTx userInfo gCtx sqlCtx fld = do
|
2018-07-20 10:22:46 +03:00
|
|
|
opCxt <- getOpCtx $ _fName fld
|
2019-03-01 14:45:04 +03:00
|
|
|
join $ fmap fst $ runConvert ( fldMap
|
|
|
|
, orderByCtx
|
|
|
|
, insCtxMap
|
|
|
|
, sqlCtx
|
|
|
|
) $ case opCxt of
|
2018-07-20 10:22:46 +03:00
|
|
|
|
2019-02-22 13:27:38 +03:00
|
|
|
OCSelect ctx ->
|
|
|
|
validateHdrs (_socHeaders ctx) >> RS.convertSelect ctx fld
|
2018-08-27 17:17:03 +03:00
|
|
|
|
2019-02-22 13:27:38 +03:00
|
|
|
OCSelectPkey ctx ->
|
|
|
|
validateHdrs (_spocHeaders ctx) >> RS.convertSelectByPKey ctx fld
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2019-02-22 13:27:38 +03:00
|
|
|
OCSelectAgg ctx ->
|
|
|
|
validateHdrs (_socHeaders ctx) >> RS.convertAggSelect ctx fld
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2019-02-22 13:27:38 +03:00
|
|
|
OCFuncQuery ctx ->
|
|
|
|
validateHdrs (_fqocHeaders ctx) >> RS.convertFuncQuery ctx False fld
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2019-02-22 13:27:38 +03:00
|
|
|
OCFuncAggQuery ctx ->
|
|
|
|
validateHdrs (_fqocHeaders ctx) >> RS.convertFuncQuery ctx True fld
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2019-02-22 13:27:38 +03:00
|
|
|
OCInsert ctx ->
|
|
|
|
validateHdrs (_iocHeaders ctx) >> RI.convertInsert roleName (_iocTable ctx) fld
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2019-02-22 13:27:38 +03:00
|
|
|
OCUpdate ctx ->
|
|
|
|
validateHdrs (_uocHeaders ctx) >> RM.convertUpdate ctx fld
|
2019-01-25 06:31:54 +03:00
|
|
|
|
2019-02-22 13:27:38 +03:00
|
|
|
OCDelete ctx ->
|
|
|
|
validateHdrs (_docHeaders ctx) >> RM.convertDelete ctx fld
|
2018-07-20 10:22:46 +03:00
|
|
|
where
|
2018-08-17 17:44:43 +03:00
|
|
|
roleName = userRole userInfo
|
2018-07-20 10:22:46 +03:00
|
|
|
opCtxMap = _gOpCtxMap gCtx
|
|
|
|
fldMap = _gFields gCtx
|
2018-10-26 14:57:33 +03:00
|
|
|
orderByCtx = _gOrdByCtx gCtx
|
2018-10-05 18:13:51 +03:00
|
|
|
insCtxMap = _gInsCtxMap gCtx
|
2018-07-20 10:22:46 +03:00
|
|
|
|
|
|
|
getOpCtx f =
|
|
|
|
onNothing (Map.lookup f opCtxMap) $ throw500 $
|
|
|
|
"lookup failed: opctx: " <> showName f
|
|
|
|
|
|
|
|
validateHdrs hdrs = do
|
2018-10-26 18:57:22 +03:00
|
|
|
let receivedVars = userVars userInfo
|
2018-07-20 10:22:46 +03:00
|
|
|
forM_ hdrs $ \hdr ->
|
2018-10-26 18:57:22 +03:00
|
|
|
unless (isJust $ getVarVal hdr receivedVars) $
|
2018-07-20 10:22:46 +03:00
|
|
|
throw400 NotFound $ hdr <<> " header is expected but not found"
|
|
|
|
|
|
|
|
-- {-# SCC resolveFld #-}
|
|
|
|
resolveFld
|
2018-12-13 10:26:15 +03:00
|
|
|
:: (MonadTx m)
|
2019-03-01 14:45:04 +03:00
|
|
|
=> UserInfo -> GCtx -> SQLGenCtx
|
2018-07-20 10:22:46 +03:00
|
|
|
-> G.OperationType
|
|
|
|
-> Field
|
2018-12-13 10:26:15 +03:00
|
|
|
-> m BL.ByteString
|
2019-03-01 14:45:04 +03:00
|
|
|
resolveFld userInfo gCtx sqlGenCtx opTy fld =
|
2018-07-20 10:22:46 +03:00
|
|
|
case _fName fld of
|
|
|
|
"__type" -> J.encode <$> runReaderT (typeR fld) gCtx
|
|
|
|
"__schema" -> J.encode <$> runReaderT (schemaR fld) gCtx
|
|
|
|
"__typename" -> return $ J.encode $ mkRootTypeName opTy
|
2019-03-01 14:45:04 +03:00
|
|
|
_ -> liftTx $ buildTx userInfo gCtx sqlGenCtx fld
|
2018-07-20 10:22:46 +03:00
|
|
|
where
|
|
|
|
mkRootTypeName :: G.OperationType -> Text
|
|
|
|
mkRootTypeName = \case
|
|
|
|
G.OperationTypeQuery -> "query_root"
|
|
|
|
G.OperationTypeMutation -> "mutation_root"
|
|
|
|
G.OperationTypeSubscription -> "subscription_root"
|
|
|
|
|
|
|
|
resolveSelSet
|
2018-12-13 10:26:15 +03:00
|
|
|
:: (MonadTx m)
|
2019-03-01 14:45:04 +03:00
|
|
|
=> UserInfo -> GCtx -> SQLGenCtx
|
2018-07-20 10:22:46 +03:00
|
|
|
-> G.OperationType
|
|
|
|
-> SelSet
|
2018-12-13 10:26:15 +03:00
|
|
|
-> m BL.ByteString
|
2019-03-01 14:45:04 +03:00
|
|
|
resolveSelSet userInfo gCtx sqlGenCtx opTy fields =
|
2018-07-20 10:22:46 +03:00
|
|
|
fmap mkJSONObj $ forM (toList fields) $ \fld -> do
|
2019-03-01 14:45:04 +03:00
|
|
|
fldResp <- resolveFld userInfo gCtx sqlGenCtx opTy fld
|
2018-07-20 10:22:46 +03:00
|
|
|
return (G.unName $ G.unAlias $ _fAlias fld, fldResp)
|