]> Git — Sourcephile - gargantext.git/blob - src/Gargantext/API/GraphQL.hs
[graphql] implement an endpoint for node contexts
[gargantext.git] / src / Gargantext / API / GraphQL.hs
1 {-# OPTIONS_GHC -fprint-potential-instances #-}
2
3 {-# LANGUAGE DeriveAnyClass #-}
4 {-# LANGUAGE DuplicateRecordFields #-} -- permit duplications for field names in multiple constructors
5 {-# LANGUAGE KindSignatures #-} -- for use of Endpoint (name :: Symbol)
6 {-# LANGUAGE PartialTypeSignatures #-} -- to automatically use suggested type hole signatures during compilation
7 {-# LANGUAGE TypeOperators #-}
8
9 module Gargantext.API.GraphQL where
10
11 import Data.ByteString.Lazy.Char8
12 ( ByteString
13 )
14 import Data.Map (Map)
15 import Data.Morpheus
16 ( App
17 , deriveApp )
18 import Data.Morpheus.Server
19 ( httpPlayground
20 )
21 import Data.Morpheus.Subscriptions
22 ( Event (..)
23 , Hashable
24 , httpPubApp
25 )
26 import Data.Morpheus.Types
27 ( GQLRequest
28 , GQLResponse
29 , GQLType
30 , RootResolver(..)
31 , Undefined(..)
32 )
33 import Data.Proxy
34 import Gargantext.API.Admin.Auth.Types (AuthenticatedUser)
35 import Gargantext.API.Admin.Orchestrator.Types (JobLog)
36 import Gargantext.API.Prelude (HasJobEnv')
37 import qualified Gargantext.API.GraphQL.Annuaire as GQLA
38 import qualified Gargantext.API.GraphQL.AsyncTask as GQLAT
39 import qualified Gargantext.API.GraphQL.Context as GQLCTX
40 import qualified Gargantext.API.GraphQL.IMT as GQLIMT
41 import qualified Gargantext.API.GraphQL.Node as GQLNode
42 import qualified Gargantext.API.GraphQL.User as GQLUser
43 import qualified Gargantext.API.GraphQL.UserInfo as GQLUserInfo
44 import qualified Gargantext.API.GraphQL.TreeFirstLevel as GQLTree
45 import qualified Gargantext.API.GraphQL.Team as GQLTeam
46 import Gargantext.API.Prelude (GargM, GargError)
47 import Gargantext.API.Types
48 import Gargantext.Core.Mail.Types (HasMail)
49 import Gargantext.Database.Prelude (HasConnectionPool, HasConfig)
50 import Gargantext.Prelude
51 import GHC.Generics (Generic)
52 import Servant
53 ( (:<|>) (..)
54 , (:>)
55 , Get
56 , JSON
57 , Post
58 , ReqBody
59 , ServerT
60 )
61 import qualified Servant.Auth as SA
62 import qualified Servant.Auth.Server as SAS
63 import Gargantext.API.Admin.Types (HasSettings)
64
65
66 -- | Represents possible GraphQL queries.
67 data Query m
68 = Query
69 { annuaire_contacts :: GQLA.AnnuaireContactArgs -> m [GQLA.AnnuaireContact]
70 , contexts :: GQLCTX.NodeContextArgs -> m [GQLCTX.NodeContextGQL]
71 , imt_schools :: GQLIMT.SchoolsArgs -> m [GQLIMT.School]
72 , job_logs :: GQLAT.JobLogArgs -> m (Map Int JobLog)
73 , nodes :: GQLNode.NodeArgs -> m [GQLNode.Node]
74 , node_parent :: GQLNode.NodeParentArgs -> m [GQLNode.Node]
75 , user_infos :: GQLUserInfo.UserInfoArgs -> m [GQLUserInfo.UserInfo]
76 , users :: GQLUser.UserArgs -> m [GQLUser.User m]
77 , tree :: GQLTree.TreeArgs -> m (GQLTree.TreeFirstLevel m)
78 , team :: GQLTeam.TeamArgs -> m GQLTeam.Team
79 } deriving (Generic, GQLType)
80
81 data Mutation m
82 = Mutation
83 { update_user_info :: GQLUserInfo.UserInfoMArgs -> m Int
84 , delete_team_membership :: GQLTeam.TeamDeleteMArgs -> m [Int]
85 } deriving (Generic, GQLType)
86
87 -- | Possible GraphQL Events, i.e. here we describe how we will
88 -- manipulate the data.
89 type EVENT m = Event Channel (Contet m)
90
91 -- | Channels are possible actions to call when manipulating the data.
92 data Channel
93 = Update
94 | New
95 deriving (Eq, Show, Generic, Hashable)
96
97 -- | This type describes what data we will operate on.
98 data Contet m
99 = UserContet [GQLUser.User m]
100 | UserInfoContet [GQLUserInfo.UserInfo]
101
102 -- | The main GraphQL resolver: how queries, mutations and
103 -- subscriptions are handled.
104 rootResolver
105 :: (HasConnectionPool env, HasConfig env, HasMail env, HasJobEnv' env, HasSettings env)
106 => RootResolver (GargM env GargError) e Query Mutation Undefined
107 rootResolver =
108 RootResolver
109 { queryResolver = Query { annuaire_contacts = GQLA.resolveAnnuaireContacts
110 , contexts = GQLCTX.resolveNodeContext
111 , imt_schools = GQLIMT.resolveSchools
112 , job_logs = GQLAT.resolveJobLogs
113 , nodes = GQLNode.resolveNodes
114 , node_parent = GQLNode.resolveNodeParent
115 , user_infos = GQLUserInfo.resolveUserInfos
116 , users = GQLUser.resolveUsers
117 , tree = GQLTree.resolveTree
118 , team = GQLTeam.resolveTeam }
119 , mutationResolver = Mutation { update_user_info = GQLUserInfo.updateUserInfo
120 , delete_team_membership = GQLTeam.deleteTeamMembership }
121 , subscriptionResolver = Undefined }
122
123 -- | Main GraphQL "app".
124 app
125 :: (Typeable env, HasConnectionPool env, HasConfig env, HasMail env, HasJobEnv' env, HasSettings env)
126 => App (EVENT (GargM env GargError)) (GargM env GargError)
127 app = deriveApp rootResolver
128
129 ----------------------------------------------
130
131 -- Now for some boilerplate to integrate the above GraphQL app with
132 -- servant.
133
134 -- | Servant route for the app we defined above.
135 type GQAPI = ReqBody '[JSON] GQLRequest :> Post '[JSON] GQLResponse
136 -- type Schema = "schema" :> Get '[PlainText] Text
137 -- | Servant route for the playground.
138 type Playground = Get '[HTML] ByteString
139 -- type API' (name :: Symbol) = name :> (GQAPI :<|> Schema :<|> Playground)
140 -- | Our API consists of `GQAPI` and `Playground`.
141 type API = SA.Auth '[SA.JWT, SA.Cookie] AuthenticatedUser
142 :> "gql" :> (GQAPI :<|> Playground)
143
144 gqapi :: Proxy API
145 gqapi = Proxy
146
147 -- serveEndpoint ::
148 -- ( SubApp ServerApp e
149 -- , PubApp e
150 -- ) =>
151 -- [e -> IO ()] ->
152 -- App e IO ->
153 -- Server (API name)
154 -- serveEndpoint publish app' = (liftIO . httpPubApp publish app') :<|> withSchema app' :<|> pure httpPlayground
155 --
156 -- withSchema :: (Applicative f) => App e m -> f Text
157 -- withSchema = pure . LT.toStrict . decodeUtf8 . render
158
159 -- | Implementation of our API.
160 --api :: Server API
161 api
162 :: (Typeable env, HasConnectionPool env, HasConfig env, HasMail env, HasJobEnv' env, HasSettings env)
163 => ServerT API (GargM env GargError)
164 api (SAS.Authenticated _auser) = httpPubApp [] app :<|> pure httpPlayground
165 api _ = panic "401 in graphql" -- SAS.throwAll (_ServerError # err401)