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 {-# OPTIONS_GHC -fno-warn-unused-imports #-}
9 module Gargantext.API.GraphQL where
11 import Control.Lens ((#))
12 import Control.Monad.Base (liftBase)
13 import Control.Monad.IO.Class (liftIO)
14 import Data.ByteString.Lazy.Char8
17 import Data.List.NonEmpty (NonEmpty ((:|)))
18 import Data.Maybe (fromMaybe)
22 import Data.Morpheus.Server
25 import Data.Morpheus.Subscriptions
33 import Data.Morpheus.Types
45 import Data.Morpheus.Types.Internal.AST
47 import Data.Text (Text)
48 import qualified Data.Text.Lazy as LT
49 import Data.Text.Lazy.Encoding (decodeUtf8)
50 import Data.Typeable (Typeable)
51 import Gargantext.API.Admin.Auth.Types (AuthenticatedUser)
52 import qualified Gargantext.API.GraphQL.User as GQLUser
53 import qualified Gargantext.API.GraphQL.UserInfo as GQLUserInfo
54 import Gargantext.API.Prelude (GargServerT, GargM, GargError, _ServerError)
55 import Gargantext.Core.Mail.Types (HasMail)
56 import Gargantext.Database.Prelude (Cmd, HasConnectionPool, HasConfig)
57 import Gargantext.Database.Schema.User (UserPoly(..))
58 import Gargantext.Prelude
59 import GHC.Generics (Generic)
61 import Network.HTTP.Media ((//), (/:))
62 import Network.WebSockets
65 import qualified Prelude as Prelude
79 import qualified Servant.Auth as SA
80 import qualified Servant.Auth.Server as SAS
82 -- | Represents possible GraphQL queries.
85 { user_infos :: GQLUserInfo.UserInfoArgs -> m [GQLUserInfo.UserInfo]
86 , users :: GQLUser.UserArgs -> m [GQLUser.User m]
87 } deriving (Generic, GQLType)
91 { update_user_info :: GQLUserInfo.UserInfoMArgs -> m Int }
92 deriving (Generic, GQLType)
94 -- | Possible GraphQL Events, i.e. here we describe how we will
95 -- manipulate the data.
96 type EVENT m = Event Channel (Contet m)
98 -- | Channels are possible actions to call when manipulating the data.
102 deriving (Eq, Show, Generic, Hashable)
104 -- | This type describes what data we will operate on.
106 = UserContet [GQLUser.User m]
107 | UserInfoContet [GQLUserInfo.UserInfo]
109 -- | The main GraphQL resolver: how queries, mutations and
110 -- subscriptions are handled.
112 :: (HasConnectionPool env, HasConfig env, HasMail env)
113 => RootResolver (GargM env GargError) e Query Mutation Undefined
116 { queryResolver = Query { user_infos = GQLUserInfo.resolveUserInfos
117 , users = GQLUser.resolveUsers }
118 , mutationResolver = Mutation { update_user_info = GQLUserInfo.updateUserInfo }
119 , subscriptionResolver = Undefined }
121 -- | Main GraphQL "app".
123 :: (Typeable env, HasConnectionPool env, HasConfig env, HasMail env)
124 => App (EVENT (GargM env GargError)) (GargM env GargError)
125 app = deriveApp rootResolver
127 ----------------------------------------------
129 -- Now for some boilerplate to integrate the above GraphQL app with
132 -- | HTML type is needed for the GraphQL Playground.
133 data HTML deriving (Typeable)
134 instance Accept HTML where
135 contentTypes _ = "text" // "html" /: ("charset", "utf-8") :| ["text" // "html"]
136 instance MimeRender HTML ByteString where
137 mimeRender _ = Prelude.id
139 -- | Servant route for the app we defined above.
140 type GQAPI = ReqBody '[JSON] GQLRequest :> Post '[JSON] GQLResponse
141 -- type Schema = "schema" :> Get '[PlainText] Text
142 -- | Servant route for the playground.
143 type Playground = Get '[HTML] ByteString
144 -- type API' (name :: Symbol) = name :> (GQAPI :<|> Schema :<|> Playground)
145 -- | Our API consists of `GQAPI` and `Playground`.
146 type API = SA.Auth '[SA.JWT, SA.Cookie] AuthenticatedUser
147 :> "gql" :> (GQAPI :<|> Playground)
150 -- ( SubApp ServerApp e
156 -- serveEndpoint publish app' = (liftIO . httpPubApp publish app') :<|> withSchema app' :<|> pure httpPlayground
158 -- withSchema :: (Applicative f) => App e m -> f Text
159 -- withSchema = pure . LT.toStrict . decodeUtf8 . render
161 -- | Implementation of our API.
164 :: (Typeable env, HasConnectionPool env, HasConfig env, HasMail env)
165 => ServerT API (GargM env GargError)
166 api (SAS.Authenticated _auser) = httpPubApp [] app :<|> pure httpPlayground
167 api _ = panic "401 in graphql" --SAS.throwAll (_ServerError # err401)