Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
haskell-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
148
Issues
148
List
Board
Labels
Milestones
Merge Requests
7
Merge Requests
7
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
haskell-gargantext
Commits
4a46abad
Commit
4a46abad
authored
Nov 14, 2023
by
Alexandre Delanoë
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/adinapoli/issue-267-part-2' into dev-new
parents
5bdb077b
6a60ac39
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
78 additions
and
16 deletions
+78
-16
gargantext.cabal
gargantext.cabal
+1
-0
Errors.hs
src/Gargantext/API/Errors.hs
+10
-0
Types.hs
src/Gargantext/API/Errors/Types.hs
+2
-2
Routes.hs
src/Gargantext/API/Routes.hs
+31
-5
Server.hs
src/Gargantext/API/Server.hs
+6
-5
Errors.hs
test/Test/API/Errors.hs
+12
-1
Private.hs
test/Test/API/Private.hs
+16
-3
No files found.
gargantext.cabal
View file @
4a46abad
...
...
@@ -1049,6 +1049,7 @@ test-suite garg-test-hspec
, base ^>= 4.14.3.0
, boolexpr ^>= 0.2
, bytestring ^>= 0.10.12.0
, case-insensitive
, conduit ^>= 1.3.4.2
, containers ^>= 0.6.5.1
, crawlerArxiv
...
...
src/Gargantext/API/Errors.hs
View file @
4a46abad
...
...
@@ -6,6 +6,9 @@ module Gargantext.API.Errors (
module
Types
,
module
Class
-- * Types
,
GargErrorScheme
(
..
)
-- * Conversion functions
,
backendErrorToFrontendError
,
frontendErrorToServerError
...
...
@@ -34,6 +37,13 @@ import qualified Data.Text.Lazy as TL
$
(
deriveHttpStatusCode
''
B
ackendErrorCode
)
data
GargErrorScheme
=
-- | The old error scheme.
GES_old
-- | The new error scheme, that returns a 'FrontendError'.
|
GES_new
deriving
(
Show
,
Eq
)
-- | Transforms a backend internal error into something that the frontend
-- can consume. This is the only representation we offer to the outside world,
-- as we later encode this into a 'ServerError' in the main server handler.
...
...
src/Gargantext/API/Errors/Types.hs
View file @
4a46abad
...
...
@@ -640,10 +640,10 @@ genFrontendErr be = do
pure
$
mkFrontendErr'
txt
$
FE_job_generic_exception
err
instance
ToJSON
BackendErrorCode
where
toJSON
=
JSON
.
String
.
T
.
pack
.
drop
3
.
show
toJSON
=
JSON
.
String
.
T
.
pack
.
show
instance
FromJSON
BackendErrorCode
where
parseJSON
(
String
s
)
=
case
readMaybe
(
T
.
unpack
$
"EC_"
<>
s
)
of
parseJSON
(
String
s
)
=
case
readMaybe
(
T
.
unpack
s
)
of
Just
v
->
pure
v
Nothing
->
fail
$
"FromJSON BackendErrorCode unexpected value: "
<>
T
.
unpack
s
parseJSON
ty
=
typeMismatch
"BackendErrorCode"
ty
...
...
src/Gargantext/API/Routes.hs
View file @
4a46abad
...
...
@@ -15,6 +15,7 @@ Portability : POSIX
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UndecidableInstances #-}
module
Gargantext.API.Routes
where
...
...
@@ -28,6 +29,7 @@ import Gargantext.API.Admin.FrontEnd (FrontEndAPI)
import
Gargantext.API.Auth.PolicyCheck
import
Gargantext.API.Context
import
Gargantext.API.Count
(
CountAPI
,
count
,
Query
)
import
Gargantext.API.Errors
(
GargErrorScheme
(
..
))
import
Gargantext.API.Errors.Types
import
Gargantext.API.GraphQL
qualified
as
GraphQL
import
Gargantext.API.Members
(
MembersAPI
,
members
)
...
...
@@ -51,11 +53,38 @@ import Gargantext.Database.Prelude (HasConfig(..))
import
Gargantext.Prelude
import
Gargantext.Prelude.Config
(
gc_max_docs_scrapers
)
import
Gargantext.Utils.Jobs
(
serveJobsAPI
,
MonadJobStatus
(
..
))
import
Network.Wai
(
requestHeaders
)
import
Servant
import
Servant.Auth
as
SA
import
Servant.Auth.Swagger
()
import
Servant.Ekg
import
Servant.Server.Internal.Delayed
import
Servant.Server.Internal.DelayedIO
import
Servant.Swagger
import
Servant.Swagger.UI
import
qualified
Data.List
as
L
data
WithCustomErrorScheme
a
instance
(
HasServer
subApi
ctx
)
=>
HasServer
(
WithCustomErrorScheme
subApi
)
ctx
where
type
ServerT
(
WithCustomErrorScheme
subApi
)
m
=
GargErrorScheme
->
ServerT
subApi
m
hoistServerWithContext
_
pc
nt
s
=
hoistServerWithContext
(
Proxy
::
Proxy
subApi
)
pc
nt
.
s
route
Proxy
ctx
d
=
route
(
Proxy
::
Proxy
subApi
)
ctx
(
d
`
addHeaderCheck
`
getErrorScheme
)
where
getErrorScheme
::
DelayedIO
GargErrorScheme
getErrorScheme
=
withRequest
$
\
rq
->
do
let
hdrs
=
requestHeaders
rq
in
case
L
.
lookup
"X-Garg-Error-Scheme"
hdrs
of
Nothing
->
pure
GES_old
Just
"new"
->
pure
GES_new
Just
_
->
pure
GES_old
instance
HasSwagger
(
WithCustomErrorScheme
GargAPI
)
where
toSwagger
_
=
toSwagger
(
Proxy
::
Proxy
GargAPI
)
instance
HasEndpoint
sub
=>
HasEndpoint
(
WithCustomErrorScheme
sub
)
where
getEndpoint
_
=
getEndpoint
(
Proxy
::
Proxy
sub
)
enumerateEndpoints
_
=
enumerateEndpoints
(
Proxy
::
Proxy
sub
)
type
GargAPI
=
MkGargAPI
(
GargAPIVersion
GargAPI'
)
...
...
@@ -207,10 +236,7 @@ type GargPrivateAPI' =
-- :<|> "auth" :> Capture "node_id" Int :> NodeAPI
---------------------------------------------------------------------
type
API
=
SwaggerAPI
:<|>
GargAPI
:<|>
GraphQL
.
API
:<|>
FrontEndAPI
type
API
=
WithCustomErrorScheme
(
SwaggerAPI
:<|>
GargAPI
:<|>
GraphQL
.
API
:<|>
FrontEndAPI
)
-- | API for serving @swagger.json@
type
SwaggerAPI
=
SwaggerSchemaUI
"swagger-ui"
"swagger.json"
...
...
src/Gargantext/API/Server.hs
View file @
4a46abad
...
...
@@ -53,18 +53,19 @@ serverGargAPI baseUrl -- orchestrator
server
::
Env
->
IO
(
Server
API
)
server
env
=
do
-- orchestrator <- scrapyOrchestrator env
pure
$
swaggerSchemaUIServer
swaggerDoc
pure
$
\
errScheme
->
swaggerSchemaUIServer
swaggerDoc
:<|>
hoistServerWithContext
(
Proxy
::
Proxy
GargAPI
)
(
Proxy
::
Proxy
AuthContext
)
transformJSON
(
transformJSON
errScheme
)
(
serverGargAPI
(
env
^.
hasConfig
.
gc_url_backend_api
))
:<|>
hoistServerWithContext
(
Proxy
::
Proxy
GraphQL
.
API
)
(
Proxy
::
Proxy
AuthContext
)
transformJSON
(
transformJSON
errScheme
)
GraphQL
.
api
:<|>
frontEndServer
where
transformJSON
::
forall
a
.
GargM
Env
BackendInternalError
a
->
Handler
a
transformJSON
=
Handler
.
withExceptT
showAsServantJSONErr
.
(`
runReaderT
`
env
)
transformJSON
::
forall
a
.
GargErrorScheme
->
GargM
Env
BackendInternalError
a
->
Handler
a
transformJSON
GES_old
=
Handler
.
withExceptT
showAsServantJSONErr
.
(`
runReaderT
`
env
)
transformJSON
GES_new
=
Handler
.
withExceptT
(
frontendErrorToServerError
.
backendErrorToFrontendError
)
.
(`
runReaderT
`
env
)
test/Test/API/Errors.hs
View file @
4a46abad
...
...
@@ -10,7 +10,7 @@ import Network.Wai.Test
import
Servant
import
Servant.Auth.Client
()
import
Servant.Client
import
Test.API.Private
(
protected
,
withValidLogin
)
import
Test.API.Private
(
protected
,
withValidLogin
,
protectedNewError
)
import
Test.API.Setup
(
withTestDBAndPort
,
setupEnvironment
,
mkUrl
,
createAliceAndBob
)
import
Test.Hspec
import
Test.Hspec.Wai.Internal
(
withApplication
)
...
...
@@ -48,3 +48,14 @@ tests = sequential $ aroundAll withTestDBAndPort $ do
->
liftIO
$
do
statusCode
`
shouldBe
`
404
simpleBody
`
shouldBe
`
[
r
|
{"error":"Node does not exist (nodeId-99)"}
|]
it
"returns the new error if header X-Garg-Error-Scheme: new is passed"
$
\
((
_testEnv
,
port
),
app
)
->
do
withApplication
app
$
do
withValidLogin
port
"gargantua"
(
GargPassword
"secret_key"
)
$
\
token
->
do
res
<-
protectedNewError
token
"GET"
(
mkUrl
port
"/node/99"
)
""
case
res
of
SResponse
{
..
}
|
Status
{
..
}
<-
simpleStatus
->
liftIO
$
do
statusCode
`
shouldBe
`
404
simpleBody
`
shouldBe
`
[
r
|
{"data":{"node_id":99},"diagnostic":"FE_node_lookup_failed_not_found {nenf_node_id = nodeId-99}","type":"EC_404__node_lookup_failed_not_found"}
|]
test/Test/API/Private.hs
View file @
4a46abad
...
...
@@ -10,9 +10,12 @@ module Test.API.Private (
,
withValidLogin
,
getJSON
,
protected
,
protectedWith
,
protectedNewError
)
where
import
Data.ByteString.Lazy
qualified
as
L
import
Data.CaseInsensitive
qualified
as
CI
import
Data.Text.Encoding
qualified
as
TE
import
Gargantext.API.Admin.Auth.Types
import
Gargantext.API.Routes
...
...
@@ -36,11 +39,21 @@ import Test.Utils (jsonFragment, shouldRespondWith')
-- | Issue a request with a valid 'Authorization: Bearer' inside.
protected
::
Token
->
Method
->
ByteString
->
L
.
ByteString
->
WaiSession
()
SResponse
protected
tkn
mth
url
payload
=
request
mth
url
[
(
hAccept
,
"application/json;charset=utf-8"
)
protected
tkn
mth
url
=
protectedWith
mempty
tkn
mth
url
protectedWith
::
[
Network
.
HTTP
.
Types
.
Header
]
->
Token
->
Method
->
ByteString
->
L
.
ByteString
->
WaiSession
()
SResponse
protectedWith
extraHeaders
tkn
mth
url
payload
=
request
mth
url
([
(
hAccept
,
"application/json;charset=utf-8"
)
,
(
hContentType
,
"application/json"
)
,
(
hAuthorization
,
"Bearer "
<>
TE
.
encodeUtf8
tkn
)
]
payload
]
<>
extraHeaders
)
payload
protectedNewError
::
Token
->
Method
->
ByteString
->
L
.
ByteString
->
WaiSession
()
SResponse
protectedNewError
tkn
mth
url
=
protectedWith
newErrorFormat
tkn
mth
url
where
newErrorFormat
=
[(
CI
.
mk
"X-Garg-Error-Scheme"
,
"new"
)]
getJSON
::
ByteString
->
WaiSession
()
SResponse
getJSON
url
=
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment