From aa2add79a23cbb5fed7cceeea3d272f390ae2ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Delano=C3=AB?= <devel+git@delanoe.org> Date: Mon, 18 May 2020 15:40:15 +0200 Subject: [PATCH] [API] refactoring / split API with Routes. --- src/Gargantext/API.hs | 347 +++++++---------------------------- src/Gargantext/API/Routes.hs | 286 +++++++++++++++++++++++++++++ 2 files changed, 351 insertions(+), 282 deletions(-) create mode 100644 src/Gargantext/API/Routes.hs diff --git a/src/Gargantext/API.hs b/src/Gargantext/API.hs index 29f6f11c..6a07f4d8 100644 --- a/src/Gargantext/API.hs +++ b/src/Gargantext/API.hs @@ -47,7 +47,6 @@ Pouillard (who mainly made it). module Gargantext.API where --------------------------------------------------------------------- -import Control.Concurrent (threadDelay) import Control.Exception (finally) import Control.Lens import Control.Monad.Except (withExceptT) @@ -62,20 +61,13 @@ import Data.Version (showVersion) import GHC.Base (Applicative) import GHC.Generics (D1, Meta (..), Rep) import GHC.TypeLits (AppendSymbol, Symbol) -import Gargantext.API.Admin.Auth (AuthRequest, AuthResponse, AuthenticatedUser(..), AuthContext, auth, withAccess, PathId(..)) -import Gargantext.API.Admin.FrontEnd (FrontEndAPI, frontEndServer) +import Gargantext.API.Admin.Auth (AuthContext, auth) +import Gargantext.API.Admin.FrontEnd (frontEndServer) import Gargantext.API.Admin.Settings +import Gargantext.API.Ngrams (HasRepoSaver(..), saveRepo) import Gargantext.API.Prelude -import Gargantext.API.Count ( CountAPI, count, Query) -import Gargantext.API.Ngrams (HasRepoSaver(..), saveRepo, TableNgramsApi, apiNgramsTableDoc) -import Gargantext.API.Node -import Gargantext.API.Search (SearchPairsAPI, searchPairs) -import Gargantext.Core.Types.Individu (User(..)) -import Gargantext.Database.Query.Table.Node.Contact (HyperdataContact) -import Gargantext.Database.Admin.Types.Node -import Gargantext.Database.Admin.Types.Node (NodeId, CorpusId, AnnuaireId) +import Gargantext.API.Routes import Gargantext.Prelude -import Gargantext.Viz.Graph.API import Network.HTTP.Types hiding (Query) import Network.Wai import Network.Wai (Request, requestHeaders) @@ -83,24 +75,65 @@ import Network.Wai.Handler.Warp hiding (defaultSettings) import Network.Wai.Middleware.Cors import Network.Wai.Middleware.RequestLogger import Servant -import Servant.Auth as SA import Servant.Auth.Server (AuthResult(..)) import Servant.Auth.Swagger () -import Servant.Job.Async import Servant.Swagger import Servant.Swagger.UI import System.IO (FilePath) import qualified Data.ByteString.Lazy.Char8 as BL8 import qualified Data.Text.IO as T -import qualified Gargantext.API.Node.Corpus.Annuaire as Annuaire -import qualified Gargantext.API.Node.Corpus.Export as Export -import qualified Gargantext.API.Node.Corpus.New as New -import qualified Gargantext.API.Ngrams.List as List -import qualified Paths_gargantext as PG -- cabal magic build module +import qualified Paths_gargantext as PG -- cabal magic build module -showAsServantErr :: GargError -> ServerError -showAsServantErr (GargServerError err) = err -showAsServantErr a = err500 { errBody = BL8.pack $ show a } + +-- | startGargantext takes as parameters port number and Ini file. +startGargantext :: PortNumber -> FilePath -> IO () +startGargantext port file = do + env <- newEnv port file + portRouteInfo port + app <- makeApp env + mid <- makeDevMiddleware + run port (mid app) `finally` stopGargantext env + +portRouteInfo :: PortNumber -> IO () +portRouteInfo port = do + T.putStrLn " ----Main Routes----- " + T.putStrLn $ "http://localhost:" <> toUrlPiece port <> "/index.html" + T.putStrLn $ "http://localhost:" <> toUrlPiece port <> "/swagger-ui" + +-- TODO clean this Monad condition (more generic) ? +stopGargantext :: HasRepoSaver env => env -> IO () +stopGargantext env = do + T.putStrLn "----- Stopping gargantext -----" + runReaderT saveRepo env + + +-- | Output generated @swagger.json@ file for the @'TodoAPI'@. +swaggerWriteJSON :: IO () +swaggerWriteJSON = BL8.writeFile "swagger.json" (encodePretty swaggerDoc) + +-- | Swagger Specifications +swaggerDoc :: Swagger +swaggerDoc = toSwagger (Proxy :: Proxy GargAPI) + & info.title .~ "Gargantext" + & info.version .~ (cs $ showVersion PG.version) + -- & info.base_url ?~ (URL "http://gargantext.org/") + & info.description ?~ "REST API specifications" + -- & tags .~ Set.fromList [Tag "Garg" (Just "Main perations") Nothing] + & applyTagsFor (subOperations (Proxy :: Proxy GargAPI)(Proxy :: Proxy GargAPI)) + ["Gargantext" & description ?~ "Main operations"] + & info.license ?~ ("AGPLV3 (English) and CECILL (French)" & url ?~ URL urlLicence ) + where + urlLicence = "https://gitlab.iscpif.fr/gargantext/haskell-gargantext/blob/master/LICENSE" + +{- +startGargantextMock :: PortNumber -> IO () +startGargantextMock port = do + portRouteInfo port + application <- makeMockApp . MockEnv $ FireWall False + run port application +-} + +---------------------------------------------------------------------- fireWall :: Applicative f => Request -> FireWall -> f Bool fireWall req fw = do @@ -183,150 +216,8 @@ makeDevMiddleware = do --------------------------------------------------------------------- -- | API Global - --- | API for serving @swagger.json@ -type SwaggerAPI = SwaggerSchemaUI "swagger-ui" "swagger.json" - --- | API for serving main operational routes of @gargantext.org@ - - -type GargAPI = "api" :> Summary "API " :> GargAPIVersion --- | TODO :<|> Summary "Latest API" :> GargAPI' - - -type GargAPIVersion = "v1.0" - :> Summary "Garg API Version " - :> GargAPI' - -type GargVersion = "version" - :> Summary "Backend version" - :> Get '[JSON] Text - -type GargAPI' = - -- Auth endpoint - "auth" :> Summary "AUTH API" - :> ReqBody '[JSON] AuthRequest - :> Post '[JSON] AuthResponse - :<|> GargVersion - -- TODO-ACCESS here we want to request a particular header for - -- auth and capabilities. - :<|> GargPrivateAPI - - -type GargPrivateAPI = SA.Auth '[SA.JWT, SA.Cookie] AuthenticatedUser :> GargPrivateAPI' - -type GargAdminAPI - -- Roots endpoint - = "user" :> Summary "First user endpoint" - :> Roots - :<|> "nodes" :> Summary "Nodes endpoint" - :> ReqBody '[JSON] [NodeId] :> NodesAPI - ----------------------------------------- --- For Tests -type WaitAPI = Get '[JSON] Text - -waitAPI :: Int -> GargServer WaitAPI -waitAPI n = do - let - m = (10 :: Int) ^ (6 :: Int) - _ <- liftBase $ threadDelay ( m * n) - pure $ "Waited: " <> (cs $ show n) ----------------------------------------- - - -type GargPrivateAPI' = - GargAdminAPI - - -- Node endpoint - :<|> "node" :> Summary "Node endpoint" - :> Capture "node_id" NodeId - :> NodeAPI HyperdataAny - - -- Corpus endpoints - :<|> "corpus" :> Summary "Corpus endpoint" - :> Capture "corpus_id" CorpusId - :> NodeAPI HyperdataCorpus - - :<|> "corpus" :> Summary "Corpus endpoint" - :> Capture "node1_id" NodeId - :> "document" - :> Capture "node2_id" NodeId - :> NodeNodeAPI HyperdataAny - - :<|> "corpus" :> Capture "node_id" CorpusId - :> Export.API - - -- Annuaire endpoint - :<|> "annuaire" :> Summary "Annuaire endpoint" - :> Capture "annuaire_id" AnnuaireId - :> NodeAPI HyperdataAnnuaire - - :<|> "annuaire" :> Summary "Contact endpoint" - :> Capture "annuaire_id" NodeId - :> "contact" - :> Capture "contact_id" NodeId - :> NodeNodeAPI HyperdataContact - - -- Document endpoint - :<|> "document" :> Summary "Document endpoint" - :> Capture "doc_id" DocId - :> "ngrams" :> TableNgramsApi - - -- :<|> "counts" :> Stream GET NewLineFraming '[JSON] Count :> CountAPI - -- TODO-SECURITY - :<|> "count" :> Summary "Count endpoint" - :> ReqBody '[JSON] Query - :> CountAPI - - -- Corpus endpoint --> TODO rename s/search/filter/g - :<|> "search" :> Capture "corpus" NodeId - :> SearchPairsAPI - - -- TODO move to NodeAPI? - :<|> "graph" :> Summary "Graph endpoint" - :> Capture "graph_id" NodeId - :> GraphAPI - - -- TODO move to NodeAPI? - -- Tree endpoint - :<|> "tree" :> Summary "Tree endpoint" - :> Capture "tree_id" NodeId - :> TreeAPI - - -- :<|> New.Upload - :<|> New.AddWithForm - :<|> New.AddWithQuery - - -- :<|> "annuaire" :> Annuaire.AddWithForm - -- :<|> New.AddWithFile - -- :<|> "scraper" :> WithCallbacks ScraperAPI - -- :<|> "new" :> New.Api - - :<|> "lists" :> Summary "List export API" - :> Capture "listId" ListId - :> List.API - - :<|> "wait" :> Summary "Wait test" - :> Capture "x" Int - :> WaitAPI -- Get '[JSON] Int - --- /mv/<id>/<id> --- /merge/<id>/<id> --- /rename/<id> - -- :<|> "static" - -- :<|> "list" :> Capture "node_id" Int :> NodeAPI - -- :<|> "ngrams" :> Capture "node_id" Int :> NodeAPI - -- :<|> "auth" :> Capture "node_id" Int :> NodeAPI ---------------------------------------------------------------------- - -type API = SwaggerAPI - :<|> GargAPI - :<|> FrontEndAPI - --------------------------------------------------------------------- -- | Server declarations - server :: forall env. EnvC env => env -> IO (Server API) server env = do -- orchestrator <- scrapyOrchestrator env @@ -341,6 +232,12 @@ server env = do transform :: forall a. GargServerM env GargError a -> Handler a transform = Handler . withExceptT showAsServantErr . (`runReaderT` env) +showAsServantErr :: GargError -> ServerError +showAsServantErr (GargServerError err) = err +showAsServantErr a = err500 { errBody = BL8.pack $ show a } + +--------------------------- + serverGargAPI :: GargServerT env err (GargServerM env err) GargAPI serverGargAPI -- orchestrator = auth @@ -357,46 +254,14 @@ serverGargAPI -- orchestrator serverPrivateGargAPI _ = throwAll' (_ServerError # err401) -- Here throwAll' requires a concrete type for the monad. + -- TODO-SECURITY admin only: withAdmin -- Question: How do we mark admins? +{- serverGargAdminAPI :: GargServer GargAdminAPI serverGargAdminAPI = roots :<|> nodesAPI - - -serverPrivateGargAPI' :: AuthenticatedUser -> GargServer GargPrivateAPI' -serverPrivateGargAPI' (AuthenticatedUser (NodeId uid)) - = serverGargAdminAPI - :<|> nodeAPI (Proxy :: Proxy HyperdataAny) uid - :<|> nodeAPI (Proxy :: Proxy HyperdataCorpus) uid - :<|> nodeNodeAPI (Proxy :: Proxy HyperdataAny) uid - :<|> Export.getCorpus -- uid - :<|> nodeAPI (Proxy :: Proxy HyperdataAnnuaire) uid - :<|> nodeNodeAPI (Proxy :: Proxy HyperdataContact) uid - - :<|> withAccess (Proxy :: Proxy TableNgramsApi) Proxy uid - <$> PathNode <*> apiNgramsTableDoc - - :<|> count -- TODO: undefined - - :<|> withAccess (Proxy :: Proxy SearchPairsAPI) Proxy uid - <$> PathNode <*> searchPairs -- TODO: move elsewhere - - :<|> withAccess (Proxy :: Proxy GraphAPI) Proxy uid - <$> PathNode <*> graphAPI uid -- TODO: mock - - :<|> withAccess (Proxy :: Proxy TreeAPI) Proxy uid - <$> PathNode <*> treeAPI - -- TODO access - :<|> addCorpusWithForm (UserDBId uid) - :<|> addCorpusWithQuery (RootId (NodeId uid)) - - -- :<|> addAnnuaireWithForm - -- :<|> New.api uid -- TODO-SECURITY - -- :<|> New.info uid -- TODO-SECURITY - :<|> List.api - :<|> waitAPI - +-} --------------------------------------------------------------------- --gargMock :: Server GargAPI @@ -424,6 +289,7 @@ schemaUiServer :: (Server api ~ Handler Swagger) => Swagger -> Server (SwaggerSchemaUI' dir api) schemaUiServer = swaggerSchemaUIServer +--------------------------------------------------------------------- -- Type Family for the Documentation type family TypeName (x :: *) :: Symbol where TypeName Int = "Int" @@ -436,86 +302,3 @@ type family GenericTypeName t (r :: *) :: Symbol where type Desc t n = Description (AppendSymbol (TypeName t) (AppendSymbol " | " n)) --- | Swagger Specifications -swaggerDoc :: Swagger -swaggerDoc = toSwagger (Proxy :: Proxy GargAPI) - & info.title .~ "Gargantext" - & info.version .~ (cs $ showVersion PG.version) - -- & info.base_url ?~ (URL "http://gargantext.org/") - & info.description ?~ "REST API specifications" - -- & tags .~ Set.fromList [Tag "Garg" (Just "Main perations") Nothing] - & applyTagsFor (subOperations (Proxy :: Proxy GargAPI)(Proxy :: Proxy GargAPI)) - ["Gargantext" & description ?~ "Main operations"] - & info.license ?~ ("AGPLV3 (English) and CECILL (French)" & url ?~ URL urlLicence ) - where - urlLicence = "https://gitlab.iscpif.fr/gargantext/haskell-gargantext/blob/master/LICENSE" - --- | Output generated @swagger.json@ file for the @'TodoAPI'@. -swaggerWriteJSON :: IO () -swaggerWriteJSON = BL8.writeFile "swagger.json" (encodePretty swaggerDoc) - -portRouteInfo :: PortNumber -> IO () -portRouteInfo port = do - T.putStrLn " ----Main Routes----- " - T.putStrLn $ "http://localhost:" <> toUrlPiece port <> "/index.html" - T.putStrLn $ "http://localhost:" <> toUrlPiece port <> "/swagger-ui" - --- TODO clean this Monad condition (more generic) ? -stopGargantext :: HasRepoSaver env => env -> IO () -stopGargantext env = do - T.putStrLn "----- Stopping gargantext -----" - runReaderT saveRepo env - --- | startGargantext takes as parameters port number and Ini file. -startGargantext :: PortNumber -> FilePath -> IO () -startGargantext port file = do - env <- newEnv port file - portRouteInfo port - app <- makeApp env - mid <- makeDevMiddleware - run port (mid app) `finally` stopGargantext env - -{- -startGargantextMock :: PortNumber -> IO () -startGargantextMock port = do - portRouteInfo port - application <- makeMockApp . MockEnv $ FireWall False - run port application --} - ----------------------------------------------------------------------- - -addCorpusWithQuery :: User -> GargServer New.AddWithQuery -addCorpusWithQuery user cid = - serveJobsAPI $ - JobFunction (\q log -> - let - log' x = do - printDebug "addToCorpusWithQuery" x - liftBase $ log x - in New.addToCorpusWithQuery user cid q log' - ) - -{- -addWithFile :: GargServer New.AddWithFile -addWithFile cid i f = - serveJobsAPI $ - JobFunction (\_i log -> New.addToCorpusWithFile cid i f (liftBase . log)) --} - -addCorpusWithForm :: User -> GargServer New.AddWithForm -addCorpusWithForm user cid = - serveJobsAPI $ - JobFunction (\i log -> - let - log' x = do - printDebug "addToCorpusWithForm" x - liftBase $ log x - in New.addToCorpusWithForm user cid i log') - -addAnnuaireWithForm :: GargServer Annuaire.AddWithForm -addAnnuaireWithForm cid = - serveJobsAPI $ - JobFunction (\i log -> Annuaire.addToAnnuaireWithForm cid i (liftBase . log)) - - diff --git a/src/Gargantext/API/Routes.hs b/src/Gargantext/API/Routes.hs new file mode 100644 index 00000000..11de305d --- /dev/null +++ b/src/Gargantext/API/Routes.hs @@ -0,0 +1,286 @@ +{-| +Module : Gargantext.API.Routes +Description : +Copyright : (c) CNRS, 2017-Present +License : AGPL + CECILL v3 +Maintainer : team@gargantext.org +Stability : experimental +Portability : POSIX + + +-} + +{-# OPTIONS_GHC -fno-warn-name-shadowing #-} + +{-# LANGUAGE ConstraintKinds #-} +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableInstances #-} + +--------------------------------------------------------------------- +module Gargantext.API.Routes + where +--------------------------------------------------------------------- +import Control.Concurrent (threadDelay) +import Data.Text (Text) +import Data.Validity +import Gargantext.API.Admin.Auth (AuthRequest, AuthResponse, AuthenticatedUser(..), withAccess, PathId(..)) +import Gargantext.API.Admin.FrontEnd (FrontEndAPI) +import Gargantext.API.Prelude +import Gargantext.API.Count (CountAPI, count, Query) +import Gargantext.API.Ngrams (TableNgramsApi, apiNgramsTableDoc) +import Gargantext.API.Node +import Gargantext.API.Search (SearchPairsAPI, searchPairs) +import Gargantext.Core.Types.Individu (User(..)) +import Gargantext.Database.Query.Table.Node.Contact (HyperdataContact) +import Gargantext.Database.Admin.Types.Node +import Gargantext.Database.Admin.Types.Node (NodeId, CorpusId, AnnuaireId) +import Gargantext.Prelude +import Gargantext.Viz.Graph.API +import Servant +import Servant.Auth as SA +import Servant.Auth.Swagger () +import Servant.Job.Async +import Servant.Swagger.UI +import qualified Gargantext.API.Node.Corpus.Annuaire as Annuaire +import qualified Gargantext.API.Node.Corpus.Export as Export +import qualified Gargantext.API.Node.Corpus.New as New +import qualified Gargantext.API.Ngrams.List as List + + + +type GargAPI = "api" :> Summary "API " :> GargAPIVersion +-- | TODO :<|> Summary "Latest API" :> GargAPI' + + +type GargAPIVersion = "v1.0" + :> Summary "Garg API Version " + :> GargAPI' + +type GargVersion = "version" + :> Summary "Backend version" + :> Get '[JSON] Text + +type GargAPI' = + -- Auth endpoint + "auth" :> Summary "AUTH API" + :> ReqBody '[JSON] AuthRequest + :> Post '[JSON] AuthResponse + :<|> GargVersion + -- TODO-ACCESS here we want to request a particular header for + -- auth and capabilities. + :<|> GargPrivateAPI + + +type GargPrivateAPI = SA.Auth '[SA.JWT, SA.Cookie] AuthenticatedUser :> GargPrivateAPI' + +type GargAdminAPI + -- Roots endpoint + = "user" :> Summary "First user endpoint" + :> Roots + :<|> "nodes" :> Summary "Nodes endpoint" + :> ReqBody '[JSON] [NodeId] :> NodesAPI + +type GargPrivateAPI' = + GargAdminAPI + + -- Node endpoint + :<|> "node" :> Summary "Node endpoint" + :> Capture "node_id" NodeId + :> NodeAPI HyperdataAny + + -- Corpus endpoints + :<|> "corpus" :> Summary "Corpus endpoint" + :> Capture "corpus_id" CorpusId + :> NodeAPI HyperdataCorpus + + :<|> "corpus" :> Summary "Corpus endpoint" + :> Capture "node1_id" NodeId + :> "document" + :> Capture "node2_id" NodeId + :> NodeNodeAPI HyperdataAny + + :<|> "corpus" :> Capture "node_id" CorpusId + :> Export.API + + -- Annuaire endpoint + :<|> "annuaire" :> Summary "Annuaire endpoint" + :> Capture "annuaire_id" AnnuaireId + :> NodeAPI HyperdataAnnuaire + + :<|> "annuaire" :> Summary "Contact endpoint" + :> Capture "annuaire_id" NodeId + :> "contact" + :> Capture "contact_id" NodeId + :> NodeNodeAPI HyperdataContact + + -- Document endpoint + :<|> "document" :> Summary "Document endpoint" + :> Capture "doc_id" DocId + :> "ngrams" :> TableNgramsApi + + -- :<|> "counts" :> Stream GET NewLineFraming '[JSON] Count :> CountAPI + -- TODO-SECURITY + :<|> "count" :> Summary "Count endpoint" + :> ReqBody '[JSON] Query + :> CountAPI + + -- Corpus endpoint --> TODO rename s/search/filter/g + :<|> "search" :> Capture "corpus" NodeId + :> SearchPairsAPI + + -- TODO move to NodeAPI? + :<|> "graph" :> Summary "Graph endpoint" + :> Capture "graph_id" NodeId + :> GraphAPI + + -- TODO move to NodeAPI? + -- Tree endpoint + :<|> "tree" :> Summary "Tree endpoint" + :> Capture "tree_id" NodeId + :> TreeAPI + + -- :<|> New.Upload + :<|> New.AddWithForm + :<|> New.AddWithQuery + + -- :<|> "annuaire" :> Annuaire.AddWithForm + -- :<|> New.AddWithFile + -- :<|> "scraper" :> WithCallbacks ScraperAPI + -- :<|> "new" :> New.Api + + :<|> "lists" :> Summary "List export API" + :> Capture "listId" ListId + :> List.API + + :<|> "wait" :> Summary "Wait test" + :> Capture "x" Int + :> WaitAPI -- Get '[JSON] Int + +-- /mv/<id>/<id> +-- /merge/<id>/<id> +-- /rename/<id> + -- :<|> "static" + -- :<|> "list" :> Capture "node_id" Int :> NodeAPI + -- :<|> "ngrams" :> Capture "node_id" Int :> NodeAPI + -- :<|> "auth" :> Capture "node_id" Int :> NodeAPI +--------------------------------------------------------------------- + +type API = SwaggerAPI + :<|> GargAPI + :<|> FrontEndAPI + +-- | API for serving @swagger.json@ +type SwaggerAPI = SwaggerSchemaUI "swagger-ui" "swagger.json" + +-- | API for serving main operational routes of @gargantext.org@ +-- TODO +-- /mv/<id>/<id> +-- /merge/<id>/<id> +-- /rename/<id> + -- :<|> "static" + -- :<|> "list" :> Capture "node_id" Int :> NodeAPI + -- :<|> "ngrams" :> Capture "node_id" Int :> NodeAPI + -- :<|> "auth" :> Capture "node_id" Int :> NodeAPI +--------------------------------------------------------------------- + +--------------------------------------------------------------------- +-- | Server declarations + +-- TODO-SECURITY admin only: withAdmin +-- Question: How do we mark admins? +serverGargAdminAPI :: GargServer GargAdminAPI +serverGargAdminAPI = roots + :<|> nodesAPI + + +serverPrivateGargAPI' :: AuthenticatedUser -> GargServer GargPrivateAPI' +serverPrivateGargAPI' (AuthenticatedUser (NodeId uid)) + = serverGargAdminAPI + :<|> nodeAPI (Proxy :: Proxy HyperdataAny) uid + :<|> nodeAPI (Proxy :: Proxy HyperdataCorpus) uid + :<|> nodeNodeAPI (Proxy :: Proxy HyperdataAny) uid + :<|> Export.getCorpus -- uid + :<|> nodeAPI (Proxy :: Proxy HyperdataAnnuaire) uid + :<|> nodeNodeAPI (Proxy :: Proxy HyperdataContact) uid + + :<|> withAccess (Proxy :: Proxy TableNgramsApi) Proxy uid + <$> PathNode <*> apiNgramsTableDoc + + :<|> count -- TODO: undefined + + :<|> withAccess (Proxy :: Proxy SearchPairsAPI) Proxy uid + <$> PathNode <*> searchPairs -- TODO: move elsewhere + + :<|> withAccess (Proxy :: Proxy GraphAPI) Proxy uid + <$> PathNode <*> graphAPI uid -- TODO: mock + + :<|> withAccess (Proxy :: Proxy TreeAPI) Proxy uid + <$> PathNode <*> treeAPI + -- TODO access + :<|> addCorpusWithForm (UserDBId uid) + :<|> addCorpusWithQuery (RootId (NodeId uid)) + + -- :<|> addAnnuaireWithForm + -- :<|> New.api uid -- TODO-SECURITY + -- :<|> New.info uid -- TODO-SECURITY + :<|> List.api + :<|> waitAPI + + +---------------------------------------------------------------------- +-- For Tests +type WaitAPI = Get '[JSON] Text + +waitAPI :: Int -> GargServer WaitAPI +waitAPI n = do + let + m = (10 :: Int) ^ (6 :: Int) + _ <- liftBase $ threadDelay ( m * n) + pure $ "Waited: " <> (cs $ show n) +---------------------------------------- + + +addCorpusWithQuery :: User -> GargServer New.AddWithQuery +addCorpusWithQuery user cid = + serveJobsAPI $ + JobFunction (\q log -> + let + log' x = do + printDebug "addToCorpusWithQuery" x + liftBase $ log x + in New.addToCorpusWithQuery user cid q log' + ) + +{- +addWithFile :: GargServer New.AddWithFile +addWithFile cid i f = + serveJobsAPI $ + JobFunction (\_i log -> New.addToCorpusWithFile cid i f (liftBase . log)) +-} + +addCorpusWithForm :: User -> GargServer New.AddWithForm +addCorpusWithForm user cid = + serveJobsAPI $ + JobFunction (\i log -> + let + log' x = do + printDebug "addToCorpusWithForm" x + liftBase $ log x + in New.addToCorpusWithForm user cid i log') + +addAnnuaireWithForm :: GargServer Annuaire.AddWithForm +addAnnuaireWithForm cid = + serveJobsAPI $ + JobFunction (\i log -> Annuaire.addToAnnuaireWithForm cid i (liftBase . log)) + -- 2.21.0