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
160
Issues
160
List
Board
Labels
Milestones
Merge Requests
14
Merge Requests
14
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
7337820e
Commit
7337820e
authored
Dec 16, 2024
by
Alfredo Di Napoli
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Basic Remote API testing
parent
1eb59c52
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
125 additions
and
16 deletions
+125
-16
gargantext.cabal
gargantext.cabal
+2
-0
Client.hs
src/Gargantext/API/Routes/Client.hs
+20
-1
Remote.hs
src/Gargantext/API/Routes/Named/Remote.hs
+2
-2
Remote.hs
src/Gargantext/API/Server/Named/Remote.hs
+14
-13
Private.hs
test/Test/API/Private.hs
+3
-0
Remote.hs
test/Test/API/Private/Remote.hs
+83
-0
Setup.hs
test/Test/API/Setup.hs
+1
-0
No files found.
gargantext.cabal
View file @
7337820e
...
@@ -796,6 +796,7 @@ test-suite garg-test-tasty
...
@@ -796,6 +796,7 @@ test-suite garg-test-tasty
CLI.Phylo.Common
CLI.Phylo.Common
Paths_gargantext
Paths_gargantext
Test.API.Private.Move
Test.API.Private.Move
Test.API.Private.Remote
Test.API.Private.Share
Test.API.Private.Share
Test.API.Private.Table
Test.API.Private.Table
Test.API.Authentication
Test.API.Authentication
...
@@ -865,6 +866,7 @@ test-suite garg-test-hspec
...
@@ -865,6 +866,7 @@ test-suite garg-test-hspec
Test.API.Notifications
Test.API.Notifications
Test.API.Private
Test.API.Private
Test.API.Private.Move
Test.API.Private.Move
Test.API.Private.Remote
Test.API.Private.Share
Test.API.Private.Share
Test.API.Private.Table
Test.API.Private.Table
Test.API.Routes
Test.API.Routes
...
...
src/Gargantext/API/Routes/Client.hs
View file @
7337820e
...
@@ -13,6 +13,7 @@ import Gargantext.API.Errors (GargErrorScheme(..))
...
@@ -13,6 +13,7 @@ import Gargantext.API.Errors (GargErrorScheme(..))
import
Gargantext.API.Routes.Named
import
Gargantext.API.Routes.Named
import
Gargantext.API.Routes.Named.Private
(
mkPrivateAPI
,
remoteAPI
)
import
Gargantext.API.Routes.Named.Private
(
mkPrivateAPI
,
remoteAPI
)
import
Gargantext.API.Routes.Named.Remote
qualified
as
Named
import
Gargantext.API.Routes.Named.Remote
qualified
as
Named
import
Gargantext.Database.Admin.Types.Node
import
Gargantext.Prelude
import
Gargantext.Prelude
import
Network.HTTP.Types
qualified
as
H
import
Network.HTTP.Types
qualified
as
H
import
Servant.API.WebSocket
qualified
as
WS
import
Servant.API.WebSocket
qualified
as
WS
...
@@ -38,7 +39,7 @@ clientRoutes = genericClient
...
@@ -38,7 +39,7 @@ clientRoutes = genericClient
remoteImportClient
::
Auth
.
Token
remoteImportClient
::
Auth
.
Token
->
C
.
ConduitT
()
Named
.
RemoteBinaryData
IO
()
->
C
.
ConduitT
()
Named
.
RemoteBinaryData
IO
()
->
ClientM
()
->
ClientM
[
NodeId
]
remoteImportClient
(
S
.
Token
.
TE
.
encodeUtf8
->
token
)
c
=
remoteImportClient
(
S
.
Token
.
TE
.
encodeUtf8
->
token
)
c
=
clientRoutes
&
apiWithCustomErrorScheme
clientRoutes
&
apiWithCustomErrorScheme
&
(
$
GES_new
)
&
(
$
GES_new
)
...
@@ -53,3 +54,21 @@ remoteImportClient (S.Token . TE.encodeUtf8 -> token) c =
...
@@ -53,3 +54,21 @@ remoteImportClient (S.Token . TE.encodeUtf8 -> token) c =
&
Named
.
remoteAPI
&
Named
.
remoteAPI
&
Named
.
remoteImportEp
&
Named
.
remoteImportEp
&
(
$
c
)
&
(
$
c
)
remoteExportClient
::
Auth
.
Token
->
Named
.
RemoteExportRequest
->
ClientM
[
NodeId
]
remoteExportClient
(
S
.
Token
.
TE
.
encodeUtf8
->
token
)
r
=
clientRoutes
&
apiWithCustomErrorScheme
&
(
$
GES_new
)
&
backendAPI
&
backendAPI'
&
mkBackEndAPI
&
gargAPIVersion
&
gargPrivateAPI
&
mkPrivateAPI
&
(
$
token
)
&
remoteAPI
&
Named
.
remoteAPI
&
Named
.
remoteExportEp
&
(
$
r
)
src/Gargantext/API/Routes/Named/Remote.hs
View file @
7337820e
...
@@ -77,7 +77,7 @@ instance ToSchema RemoteBinaryData where
...
@@ -77,7 +77,7 @@ instance ToSchema RemoteBinaryData where
declareNamedSchema
_
=
pure
$
NamedSchema
(
Just
"RemoteExportRequest"
)
binarySchema
declareNamedSchema
_
=
pure
$
NamedSchema
(
Just
"RemoteExportRequest"
)
binarySchema
data
RemoteAPI'
mode
=
RemoteAPI'
data
RemoteAPI'
mode
=
RemoteAPI'
{
remoteExportEp
::
mode
:-
"export"
:>
ReqBody
'[
J
SON
]
RemoteExportRequest
:>
PolicyChecked
(
Post
'[
J
SON
]
()
)
{
remoteExportEp
::
mode
:-
"export"
:>
ReqBody
'[
J
SON
]
RemoteExportRequest
:>
PolicyChecked
(
Post
'[
J
SON
]
[
NodeId
]
)
,
remoteImportEp
::
mode
:-
"import"
:>
StreamBody
NoFraming
OctetStream
(
C
.
ConduitT
()
RemoteBinaryData
IO
()
)
,
remoteImportEp
::
mode
:-
"import"
:>
StreamBody
NoFraming
OctetStream
(
C
.
ConduitT
()
RemoteBinaryData
IO
()
)
:>
Post
'[
J
SON
]
()
:>
Post
'[
J
SON
]
[
NodeId
]
}
deriving
Generic
}
deriving
Generic
src/Gargantext/API/Server/Named/Remote.hs
View file @
7337820e
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE BangPatterns #-}
module
Gargantext.API.Server.Named.Remote
(
module
Gargantext.API.Server.Named.Remote
(
remoteAPI
remoteAPI
...
@@ -13,7 +14,6 @@ import Conduit
...
@@ -13,7 +14,6 @@ import Conduit
import
Control.Exception.Safe
qualified
as
Safe
import
Control.Exception.Safe
qualified
as
Safe
import
Control.Exception
(
toException
)
import
Control.Exception
(
toException
)
import
Control.Lens
(
view
,
(
#
))
import
Control.Lens
(
view
,
(
#
))
import
Control.Monad
import
Control.Monad.Except
(
throwError
)
import
Control.Monad.Except
(
throwError
)
import
Data.Aeson
qualified
as
JSON
import
Data.Aeson
qualified
as
JSON
import
Data.ByteString.Builder
qualified
as
B
import
Data.ByteString.Builder
qualified
as
B
...
@@ -37,6 +37,7 @@ import Gargantext.Database.Query.Table.Node (getNode, insertNodeWithHyperdata)
...
@@ -37,6 +37,7 @@ import Gargantext.Database.Query.Table.Node (getNode, insertNodeWithHyperdata)
import
Gargantext.Database.Schema.Node
(
NodePoly
(
..
))
import
Gargantext.Database.Schema.Node
(
NodePoly
(
..
))
import
Gargantext.Orphans
()
import
Gargantext.Orphans
()
import
Prelude
import
Prelude
import
Protolude.Safe
(
headMay
)
import
Servant.Client.Streaming
(
mkClientEnv
,
withClientM
,
ClientError
)
import
Servant.Client.Streaming
(
mkClientEnv
,
withClientM
,
ClientError
)
import
Servant.Server.Generic
(
AsServerT
)
import
Servant.Server.Generic
(
AsServerT
)
...
@@ -56,7 +57,7 @@ remoteImportHandler :: forall err env m.
...
@@ -56,7 +57,7 @@ remoteImportHandler :: forall err env m.
(
HasNodeError
err
,
HasBackendInternalError
err
,
IsDBCmd
env
err
m
,
MonadIO
m
)
(
HasNodeError
err
,
HasBackendInternalError
err
,
IsDBCmd
env
err
m
,
MonadIO
m
)
=>
AuthenticatedUser
=>
AuthenticatedUser
->
ConduitT
()
Named
.
RemoteBinaryData
IO
()
->
ConduitT
()
Named
.
RemoteBinaryData
IO
()
->
m
()
->
m
[
NodeId
]
remoteImportHandler
loggedInUser
c
=
do
remoteImportHandler
loggedInUser
c
=
do
chunks
<-
liftIO
$
sourceToList
$
c
.|
C
.
map
(
B
.
byteString
.
Named
.
getRemoteBinaryData
)
chunks
<-
liftIO
$
sourceToList
$
c
.|
C
.
map
(
B
.
byteString
.
Named
.
getRemoteBinaryData
)
-- FIXME(adn): We have to find a way to deserialise this into a streaming fashion and
-- FIXME(adn): We have to find a way to deserialise this into a streaming fashion and
...
@@ -66,23 +67,23 @@ remoteImportHandler loggedInUser c = do
...
@@ -66,23 +67,23 @@ remoteImportHandler loggedInUser c = do
Right
[]
->
throwError
$
_BackendInternalError
#
InternalUnexpectedError
(
toException
$
userError
$
"Deserialization error: empty list"
)
Right
[]
->
throwError
$
_BackendInternalError
#
InternalUnexpectedError
(
toException
$
userError
$
"Deserialization error: empty list"
)
Right
(
x
:
xs
)
->
do
Right
(
x
:
xs
)
->
do
-- Attempts to insert nodes a we go along.
-- Attempts to insert nodes a we go along.
rootNode
<-
inserter
Nothing
x
rootNode
<-
inserter
[]
x
void
$
foldlM
insert_remote
rootNode
xs
foldlM
inserter
rootNode
xs
where
where
inserter
::
Maybe
ParentId
->
Node
JSON
.
Value
->
m
NodeId
inserter
::
[
NodeId
]
->
Node
JSON
.
Value
->
m
[
NodeId
]
inserter
p
x
=
case
lookupDBid
$
_node_typename
x
of
inserter
!
acc
x
=
case
lookupDBid
$
_node_typename
x
of
Nothing
->
error
"remoteImportHandler: impossible."
Nothing
->
throwError
$
_BackendInternalError
#
InternalUnexpectedError
(
toException
$
userError
$
"remoteImportHandler: impossible, node with invalid type."
)
Just
ty
->
insertNodeWithHyperdata
ty
(
_node_name
x
)
(
_node_hyperdata
x
)
p
(
_auth_user_id
loggedInUser
)
Just
ty
->
do
new_node
<-
insertNodeWithHyperdata
ty
(
_node_name
x
)
(
_node_hyperdata
x
)
(
headMay
acc
)
(
_auth_user_id
loggedInUser
)
pure
$
new_node
:
acc
insert_remote
::
NodeId
->
Node
JSON
.
Value
->
m
NodeId
insert_remote
previousNode
=
inserter
(
Just
previousNode
)
remoteExportHandler
::
(
MonadIO
m
,
Safe
.
MonadCatch
m
remoteExportHandler
::
(
MonadIO
m
,
Safe
.
MonadCatch
m
,
IsGargServer
err
env
m
,
IsGargServer
err
env
m
)
)
=>
Named
.
RemoteExportRequest
=>
Named
.
RemoteExportRequest
->
m
()
->
m
[
NodeId
]
remoteExportHandler
Named
.
RemoteExportRequest
{
..
}
=
do
remoteExportHandler
Named
.
RemoteExportRequest
{
..
}
=
do
mgr
<-
view
gargHttpManager
mgr
<-
view
gargHttpManager
-- FIXME(adn) Here I should somehow need to get all the children of the
-- FIXME(adn) Here I should somehow need to get all the children of the
...
@@ -95,7 +96,7 @@ streamEncoder :: (MonadIO m, Serialise a) => a -> ConduitT () Named.RemoteBinary
...
@@ -95,7 +96,7 @@ streamEncoder :: (MonadIO m, Serialise a) => a -> ConduitT () Named.RemoteBinary
streamEncoder
=
CL
.
sourceList
.
map
Named
.
RemoteBinaryData
.
BL
.
toChunks
.
serialise
streamEncoder
=
CL
.
sourceList
.
map
Named
.
RemoteBinaryData
.
BL
.
toChunks
.
serialise
-- | Returns a conduit which can be used to decode
-- | Returns a conduit which can be used to decode
streamDecode
::
Either
ClientError
()
->
IO
()
streamDecode
::
Either
ClientError
[
NodeId
]
->
IO
[
NodeId
]
streamDecode
=
\
case
streamDecode
=
\
case
Left
err
->
Safe
.
throwIO
$
InternalUnexpectedError
(
toException
$
userError
$
show
err
)
Left
err
->
Safe
.
throwIO
$
InternalUnexpectedError
(
toException
$
userError
$
show
err
)
Right
_
->
pure
()
Right
x
->
pure
x
test/Test/API/Private.hs
View file @
7337820e
...
@@ -20,6 +20,7 @@ import Servant.Client.Streaming
...
@@ -20,6 +20,7 @@ import Servant.Client.Streaming
import
Servant.Client.Generic
(
genericClient
)
import
Servant.Client.Generic
(
genericClient
)
import
Test.API.Prelude
import
Test.API.Prelude
import
Test.API.Private.Move
qualified
as
Move
import
Test.API.Private.Move
qualified
as
Move
import
Test.API.Private.Remote
qualified
as
Remote
import
Test.API.Private.Share
qualified
as
Share
import
Test.API.Private.Share
qualified
as
Share
import
Test.API.Private.Table
qualified
as
Table
import
Test.API.Private.Table
qualified
as
Table
import
Test.API.Routes
(
mkUrl
,
get_node
,
get_tree
)
import
Test.API.Routes
(
mkUrl
,
get_node
,
get_tree
)
...
@@ -111,3 +112,5 @@ tests = sequential $ do
...
@@ -111,3 +112,5 @@ tests = sequential $ do
Table
.
tests
Table
.
tests
describe
"Move API"
$
do
describe
"Move API"
$
do
Move
.
tests
Move
.
tests
describe
"Remote API"
$
do
Remote
.
tests
test/Test/API/Private/Remote.hs
0 → 100644
View file @
7337820e
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module
Test.API.Private.Remote
(
tests
)
where
import
Control.Lens
import
Gargantext.API.Admin.EnvTypes
(
Mode
(
..
))
import
Gargantext.API.Errors
import
Gargantext.API
(
makeApp
)
import
Gargantext.API.Routes.Client
(
remoteExportClient
)
import
Gargantext.API.Routes.Named.Remote
(
RemoteExportRequest
(
..
))
import
Gargantext.Core.Types.Individu
import
Gargantext.Core.Types
(
NodeId
(
UnsafeMkNodeId
))
import
Gargantext.Prelude
import
Gargantext.System.Logging
import
Network.Wai.Handler.Warp
qualified
as
Warp
import
Network.Wai
qualified
as
Wai
import
Servant.Client.Streaming
import
Test.API.Prelude
import
Test.API.Setup
import
Test.Database.Setup
import
Test.Database.Types
import
Test.Hspec
(
Spec
,
it
,
aroundAll
,
describe
,
sequential
,
shouldBe
)
import
Test.Hspec.Wai.Internal
(
withApplication
)
import
Test.Utils
-- | Helper to let us test transferring data between two instances.
withTwoServerInstances
::
(
SpecContext
(
TestEnv
,
Wai
.
Application
,
Warp
.
Port
)
->
IO
()
)
->
IO
()
withTwoServerInstances
action
=
withTestDB
$
\
testEnv1
->
do
withTestDB
$
\
testEnv2
->
do
garg1App
<-
withLoggerHoisted
Mock
$
\
ioLogger
->
do
env
<-
newTestEnv
testEnv1
ioLogger
server1Port
makeApp
env
garg2App
<-
withLoggerHoisted
Mock
$
\
ioLogger
->
do
env
<-
newTestEnv
testEnv2
ioLogger
server2Port
makeApp
env
testWithApplicationOnPort
(
pure
garg1App
)
server1Port
$
testWithApplicationOnPort
(
pure
garg2App
)
server2Port
$
action
(
SpecContext
testEnv1
server1Port
garg1App
(
testEnv2
,
garg2App
,
server2Port
))
where
server1Port
=
8008
server2Port
=
9008
tests
::
Spec
tests
=
sequential
$
aroundAll
withTwoServerInstances
$
do
describe
"Prelude"
$
do
it
"setup DB triggers"
$
\
SpecContext
{
..
}
->
do
forM_
[
_sctx_env
,
_sctx_data
^.
_1
]
$
\
e
->
do
setupEnvironment
e
void
$
createAliceAndBob
e
describe
"Copying nodes across instances"
$
do
it
"should forbid moving a node the user doesn't own"
$
\
(
SpecContext
testEnv1
server1Port
app1
(
_testEnv2
,
_app2
,
server2Port
))
->
do
withApplication
app1
$
do
withValidLogin
server1Port
"alice"
(
GargPassword
"alice"
)
$
\
aliceClientEnv
aliceToken
->
do
withValidLogin
server2Port
"bob"
(
GargPassword
"bob"
)
$
\
_bobClientEnv
bobToken
->
do
liftIO
$
do
bobPublicFolderId
<-
getRootPublicFolderIdForUser
testEnv1
(
UserName
"bob"
)
let
rq
=
RemoteExportRequest
{
_rer_node_id
=
bobPublicFolderId
,
_rer_instance_url
=
fromMaybe
(
panicTrace
"impossible"
)
$
parseBaseUrl
"http://localhost:9008"
,
_rer_instance_auth
=
bobToken
}
res
<-
runClientM
(
remoteExportClient
aliceToken
rq
)
aliceClientEnv
res
`
shouldFailWith
`
EC_403__policy_check_error
it
"supports trivial transfer between instances"
$
\
(
SpecContext
testEnv1
server1Port
app1
(
_testEnv2
,
_app2
,
server2Port
))
->
do
withApplication
app1
$
do
withValidLogin
server1Port
"alice"
(
GargPassword
"alice"
)
$
\
aliceClientEnv
aliceToken
->
do
folderId
<-
liftIO
$
getRootPublicFolderIdForUser
testEnv1
(
UserName
"alice"
)
withValidLogin
server2Port
"bob"
(
GargPassword
"bob"
)
$
\
_bobClientEnv
bobToken
->
do
liftIO
$
do
let
rq
=
RemoteExportRequest
{
_rer_node_id
=
folderId
,
_rer_instance_url
=
fromMaybe
(
panicTrace
"impossible"
)
$
parseBaseUrl
"http://localhost:9008"
,
_rer_instance_auth
=
bobToken
}
res
<-
checkEither
$
runClientM
(
remoteExportClient
aliceToken
rq
)
aliceClientEnv
res
`
shouldBe
`
[
UnsafeMkNodeId
16
]
test/Test/API/Setup.hs
View file @
7337820e
...
@@ -9,6 +9,7 @@ module Test.API.Setup (
...
@@ -9,6 +9,7 @@ module Test.API.Setup (
,
setupEnvironment
,
setupEnvironment
,
createAliceAndBob
,
createAliceAndBob
,
dbEnvSetup
,
dbEnvSetup
,
newTestEnv
)
where
)
where
import
Control.Concurrent.Async
qualified
as
Async
import
Control.Concurrent.Async
qualified
as
Async
...
...
Przemyslaw Kaminski
@cgenie
mentioned in commit
942e663f
·
Jan 29, 2025
mentioned in commit
942e663f
mentioned in commit 942e663f539b287b4cc0469fe2bcf735813b4ff2
Toggle commit list
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