graphql-engine/server/src-lib/Hasura/RQL/DDL/QueryCollection.hs
Antoine Leblanc 3948ca84da server: RQL code health
This PR is a combination of the following other PRs:
- #169: move HasHttpManager out of RQL.Types
- #170: move UserInfoM to Hasura.Session
- #179: delete dead code from RQL.Types
- #180: move event related code to EventTrigger

GitOrigin-RevId: d97608d7945f2c7a0a37e307369983653eb62eb1
2021-01-08 23:10:36 +00:00

154 lines
5.1 KiB
Haskell

module Hasura.RQL.DDL.QueryCollection
( runCreateCollection
, runDropCollection
, runAddQueryToCollection
, runDropQueryFromCollection
, runAddCollectionToAllowlist
, runDropCollectionFromAllowlist
, fetchAllCollections
, fetchAllowlist
, module Hasura.RQL.Types.QueryCollection
) where
import Hasura.Prelude
import qualified Data.HashMap.Strict.InsOrd as OMap
import qualified Data.HashSet.InsOrd as HSIns
import Data.List.Extended (duplicates)
import Data.Text.Extended
import Data.Text.NonEmpty
import Hasura.EncJSON
import Hasura.RQL.Types
import Hasura.RQL.Types.QueryCollection
import Hasura.Session
addCollectionP2
:: (QErrM m)
=> CollectionDef -> m ()
addCollectionP2 (CollectionDef queryList) =
withPathK "queries" $
unless (null duplicateNames) $ throw400 NotSupported $
"found duplicate query names "
<> dquoteList (unNonEmptyText . unQueryName <$> toList duplicateNames)
where
duplicateNames = duplicates $ map _lqName queryList
runCreateCollection
:: (QErrM m, CacheRWM m, MetadataM m)
=> CreateCollection -> m EncJSON
runCreateCollection cc = do
collDetM <- getCollectionDefM collName
withPathK "name" $
onJust collDetM $ const $ throw400 AlreadyExists $
"query collection with name " <> collName <<> " already exists"
withPathK "definition" $ addCollectionP2 def
withNewInconsistentObjsCheck
$ buildSchemaCache
$ MetadataModifier
$ metaQueryCollections %~ OMap.insert collName cc
return successMsg
where
CreateCollection collName def _ = cc
runAddQueryToCollection
:: (CacheRWM m, MonadError QErr m, MetadataM m)
=> AddQueryToCollection -> m EncJSON
runAddQueryToCollection (AddQueryToCollection collName queryName query) = do
(CreateCollection _ (CollectionDef qList) comment) <- getCollectionDef collName
let queryExists = flip any qList $ \q -> _lqName q == queryName
when queryExists $ throw400 AlreadyExists $ "query with name "
<> queryName <<> " already exists in collection " <>> collName
let collDef = CollectionDef $ qList <> pure listQ
withNewInconsistentObjsCheck
$ buildSchemaCache
$ MetadataModifier
$ metaQueryCollections
%~ OMap.insert collName (CreateCollection collName collDef comment)
return successMsg
where
listQ = ListedQuery queryName query
runDropCollection
:: (MonadError QErr m, MetadataM m, CacheRWM m)
=> DropCollection -> m EncJSON
runDropCollection (DropCollection collName cascade) = do
allowlistModifier <- withPathK "collection" $ do
void $ getCollectionDef collName
allowlist <- fetchAllowlist
if collName `elem` allowlist && not cascade then
throw400 DependencyError $ "query collection with name "
<> collName <<> " is present in allowlist; cannot proceed to drop"
else
pure $ metaAllowlist %~ HSIns.delete (CollectionReq collName)
withNewInconsistentObjsCheck
$ buildSchemaCache
$ MetadataModifier
$ allowlistModifier . (metaQueryCollections %~ OMap.delete collName)
pure successMsg
runDropQueryFromCollection
:: (CacheRWM m, MonadError QErr m, MetadataM m)
=> DropQueryFromCollection -> m EncJSON
runDropQueryFromCollection (DropQueryFromCollection collName queryName) = do
CreateCollection _ (CollectionDef qList) _ <- getCollectionDef collName
let queryExists = flip any qList $ \q -> _lqName q == queryName
unless queryExists $ throw400 NotFound $ "query with name "
<> queryName <<> " not found in collection " <>> collName
withNewInconsistentObjsCheck
$ buildSchemaCache
$ MetadataModifier
$ metaQueryCollections.ix collName.ccDefinition.cdQueries
%~ filter ((/=) queryName . _lqName)
pure successMsg
runAddCollectionToAllowlist
:: (MonadError QErr m, MetadataM m, CacheRWM m)
=> CollectionReq -> m EncJSON
runAddCollectionToAllowlist req@(CollectionReq collName) = do
void $ withPathK "collection" $ getCollectionDef collName
withNewInconsistentObjsCheck
$ buildSchemaCache
$ MetadataModifier
$ metaAllowlist %~ HSIns.insert req
pure successMsg
runDropCollectionFromAllowlist
:: (UserInfoM m, MonadError QErr m, MetadataM m, CacheRWM m)
=> CollectionReq -> m EncJSON
runDropCollectionFromAllowlist req@(CollectionReq collName) = do
void $ withPathK "collection" $ getCollectionDef collName
withNewInconsistentObjsCheck
$ buildSchemaCache
$ MetadataModifier
$ metaAllowlist %~ HSIns.delete req
return successMsg
getCollectionDef
:: (QErrM m, MetadataM m)
=> CollectionName -> m CreateCollection
getCollectionDef collName = do
detM <- getCollectionDefM collName
onNothing detM $ throw400 NotExists $
"query collection with name " <> collName <<> " does not exists"
getCollectionDefM
:: (QErrM m, MetadataM m)
=> CollectionName -> m (Maybe CreateCollection)
getCollectionDefM collName =
OMap.lookup collName <$> fetchAllCollections
fetchAllCollections :: MetadataM m => m QueryCollections
fetchAllCollections =
_metaQueryCollections <$> getMetadata
fetchAllowlist :: MetadataM m => m [CollectionName]
fetchAllowlist =
(map _crCollection . toList . _metaAllowlist) <$> getMetadata