1 {-# LANGUAGE DeriveAnyClass #-}
2 {-# LANGUAGE DuplicateRecordFields #-} -- permit duplications for field names in multiple constructors
3 {-# LANGUAGE KindSignatures #-} -- for use of Endpoint (name :: Symbol)
4 {-# LANGUAGE PartialTypeSignatures #-} -- to automatically use suggested type hole signatures during compilation
5 {-# LANGUAGE TypeOperators #-}
7 module Gargantext.API.GraphQL where
9 import Data.ByteString.Lazy.Char8
12 import Data.List.NonEmpty (NonEmpty ((:|)))
17 import Data.Morpheus.Server
20 import Data.Morpheus.Subscriptions
25 import Data.Morpheus.Types
32 import Gargantext.API.Admin.Auth.Types (AuthenticatedUser)
33 import Gargantext.API.Admin.Orchestrator.Types (JobLog)
34 import Gargantext.API.Prelude (HasJobEnv')
35 import qualified Gargantext.API.GraphQL.AsyncTask as GQLAT
36 import qualified Gargantext.API.GraphQL.IMT as GQLIMT
37 import qualified Gargantext.API.GraphQL.Node as GQLNode
38 import qualified Gargantext.API.GraphQL.User as GQLUser
39 import qualified Gargantext.API.GraphQL.UserInfo as GQLUserInfo
40 import qualified Gargantext.API.GraphQL.TreeFirstLevel as GQLTree
41 import Gargantext.API.Prelude (GargM, GargError)
42 import Gargantext.Core.Mail.Types (HasMail)
43 import Gargantext.Database.Prelude (HasConnectionPool, HasConfig)
44 import Gargantext.Prelude
45 import GHC.Generics (Generic)
46 import Network.HTTP.Media ((//), (/:))
47 import qualified Prelude
59 import qualified Servant.Auth as SA
60 import qualified Servant.Auth.Server as SAS
62 -- | Represents possible GraphQL queries.
65 { imt_schools :: GQLIMT.SchoolsArgs -> m [GQLIMT.School]
66 , job_logs :: GQLAT.JobLogArgs -> m (Map Int JobLog)
67 , nodes :: GQLNode.NodeArgs -> m [GQLNode.Node]
68 , node_parent :: GQLNode.NodeParentArgs -> m [GQLNode.Node]
69 , user_infos :: GQLUserInfo.UserInfoArgs -> m [GQLUserInfo.UserInfo]
70 , users :: GQLUser.UserArgs -> m [GQLUser.User m]
71 , tree :: GQLTree.TreeArgs -> m GQLTree.TreeFirstLevel
72 } deriving (Generic, GQLType)
76 { update_user_info :: GQLUserInfo.UserInfoMArgs -> m Int }
77 deriving (Generic, GQLType)
79 -- | Possible GraphQL Events, i.e. here we describe how we will
80 -- manipulate the data.
81 type EVENT m = Event Channel (Contet m)
83 -- | Channels are possible actions to call when manipulating the data.
87 deriving (Eq, Show, Generic, Hashable)
89 -- | This type describes what data we will operate on.
91 = UserContet [GQLUser.User m]
92 | UserInfoContet [GQLUserInfo.UserInfo]
94 -- | The main GraphQL resolver: how queries, mutations and
95 -- subscriptions are handled.
97 :: (HasConnectionPool env, HasConfig env, HasMail env, HasJobEnv' env)
98 => RootResolver (GargM env GargError) e Query Mutation Undefined
101 { queryResolver = Query { imt_schools = GQLIMT.resolveSchools
102 , job_logs = GQLAT.resolveJobLogs
103 , nodes = GQLNode.resolveNodes
104 , node_parent = GQLNode.resolveNodeParent
105 , user_infos = GQLUserInfo.resolveUserInfos
106 , users = GQLUser.resolveUsers
107 , tree = GQLTree.resolveTree }
108 , mutationResolver = Mutation { update_user_info = GQLUserInfo.updateUserInfo }
109 , subscriptionResolver = Undefined }
111 -- | Main GraphQL "app".
113 :: (Typeable env, HasConnectionPool env, HasConfig env, HasMail env, HasJobEnv' env)
114 => App (EVENT (GargM env GargError)) (GargM env GargError)
115 app = deriveApp rootResolver
117 ----------------------------------------------
119 -- Now for some boilerplate to integrate the above GraphQL app with
122 -- | HTML type is needed for the GraphQL Playground.
123 data HTML deriving (Typeable)
124 instance Accept HTML where
125 contentTypes _ = "text" // "html" /: ("charset", "utf-8") :| ["text" // "html"]
126 instance MimeRender HTML ByteString where
127 mimeRender _ = Prelude.id
129 -- | Servant route for the app we defined above.
130 type GQAPI = ReqBody '[JSON] GQLRequest :> Post '[JSON] GQLResponse
131 -- type Schema = "schema" :> Get '[PlainText] Text
132 -- | Servant route for the playground.
133 type Playground = Get '[HTML] ByteString
134 -- type API' (name :: Symbol) = name :> (GQAPI :<|> Schema :<|> Playground)
135 -- | Our API consists of `GQAPI` and `Playground`.
136 type API = SA.Auth '[SA.JWT, SA.Cookie] AuthenticatedUser
137 :> "gql" :> (GQAPI :<|> Playground)
140 -- ( SubApp ServerApp e
146 -- serveEndpoint publish app' = (liftIO . httpPubApp publish app') :<|> withSchema app' :<|> pure httpPlayground
148 -- withSchema :: (Applicative f) => App e m -> f Text
149 -- withSchema = pure . LT.toStrict . decodeUtf8 . render
151 -- | Implementation of our API.
154 :: (Typeable env, HasConnectionPool env, HasConfig env, HasMail env, HasJobEnv' env)
155 => ServerT API (GargM env GargError)
156 api (SAS.Authenticated _auser) = httpPubApp [] app :<|> pure httpPlayground
157 --api _ = panic "401 in graphql" --SAS.throwAll (_ServerError # err401)
158 api _ = httpPubApp [] app :<|> pure httpPlayground