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
199
Issues
199
List
Board
Labels
Milestones
Merge Requests
12
Merge Requests
12
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
09de17bd
Unverified
Commit
09de17bd
authored
Sep 24, 2019
by
Nicolas Pouillard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Secure API with JWT auth. Part 1
parent
365c0e0d
Pipeline
#577
failed with stage
Changes
23
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
323 additions
and
111 deletions
+323
-111
Main.hs
bin/gargantext-import/Main.hs
+1
-1
Main.hs
bin/gargantext-init/Main.hs
+1
-1
Dockerfile
devops/docker/Dockerfile
+1
-1
docker-postgres
devops/docker/docker-postgres
+1
-1
package.yaml
package.yaml
+5
-1
API.hs
src/Gargantext/API.hs
+45
-39
Auth.hs
src/Gargantext/API/Auth.hs
+59
-10
New.hs
src/Gargantext/API/Corpus/New.hs
+2
-0
Ngrams.hs
src/Gargantext/API/Ngrams.hs
+49
-0
Tools.hs
src/Gargantext/API/Ngrams/Tools.hs
+4
-0
Node.hs
src/Gargantext/API/Node.hs
+2
-0
Settings.hs
src/Gargantext/API/Settings.hs
+20
-21
Types.hs
src/Gargantext/API/Types.hs
+75
-5
Database.hs
src/Gargantext/Database.hs
+2
-2
Access.hs
src/Gargantext/Database/Access.hs
+1
-0
Bashql.hs
src/Gargantext/Database/Bashql.hs
+5
-2
Facet.hs
src/Gargantext/Database/Facet.hs
+19
-5
Flow.hs
src/Gargantext/Database/Flow.hs
+22
-10
Pairing.hs
src/Gargantext/Database/Flow/Pairing.hs
+1
-0
Update.hs
src/Gargantext/Database/Node/Update.hs
+1
-0
TextSearch.hs
src/Gargantext/Database/TextSearch.hs
+2
-0
Node.hs
src/Gargantext/Database/Types/Node.hs
+4
-11
stack.yaml
stack.yaml
+1
-1
No files found.
bin/gargantext-import/Main.hs
View file @
09de17bd
...
@@ -30,7 +30,7 @@ import Gargantext.Database.Types.Node (CorpusId, toHyperdataDocument)
...
@@ -30,7 +30,7 @@ import Gargantext.Database.Types.Node (CorpusId, toHyperdataDocument)
import
Gargantext.Database.Schema.User
(
insertUsersDemo
)
import
Gargantext.Database.Schema.User
(
insertUsersDemo
)
import
Gargantext.Text.Terms
(
TermType
(
..
))
import
Gargantext.Text.Terms
(
TermType
(
..
))
import
Gargantext.Core
(
Lang
(
..
))
import
Gargantext.Core
(
Lang
(
..
))
import
Gargantext.API
--
(GargError)
import
Gargantext.API
.Types
(
GargError
)
import
Gargantext.API.Node
()
-- instances
import
Gargantext.API.Node
()
-- instances
import
Gargantext.API.Settings
(
withDevEnv
,
runCmdDev
,
DevEnv
)
import
Gargantext.API.Settings
(
withDevEnv
,
runCmdDev
,
DevEnv
)
import
System.Environment
(
getArgs
)
import
System.Environment
(
getArgs
)
...
...
bin/gargantext-init/Main.hs
View file @
09de17bd
...
@@ -28,7 +28,7 @@ import Gargantext.Database.Types.Node (CorpusId, toHyperdataDocument, RootId)
...
@@ -28,7 +28,7 @@ import Gargantext.Database.Types.Node (CorpusId, toHyperdataDocument, RootId)
import
Gargantext.Database.Schema.User
(
insertUsersDemo
,
UserId
)
import
Gargantext.Database.Schema.User
(
insertUsersDemo
,
UserId
)
import
Gargantext.Text.Terms
(
TermType
(
..
))
import
Gargantext.Text.Terms
(
TermType
(
..
))
import
Gargantext.Core
(
Lang
(
..
))
import
Gargantext.Core
(
Lang
(
..
))
import
Gargantext.API
--
(GargError)
import
Gargantext.API
.Types
(
GargError
)
import
Gargantext.API.Node
()
-- instances
import
Gargantext.API.Node
()
-- instances
import
Gargantext.API.Settings
(
withDevEnv
,
runCmdDev
,
DevEnv
)
import
Gargantext.API.Settings
(
withDevEnv
,
runCmdDev
,
DevEnv
)
--import Gargantext.Text.Corpus.Parsers.GrandDebat (readFile, GrandDebatReference(..))
--import Gargantext.Text.Corpus.Parsers.GrandDebat (readFile, GrandDebatReference(..))
...
...
devops/docker/Dockerfile
View file @
09de17bd
from
fpco/stack-build:lts-1
2.2
6
from
fpco/stack-build:lts-1
4.
6
RUN
apt-get update
&&
\
RUN
apt-get update
&&
\
apt-get
install
-y
git libigraph0-dev
&&
\
apt-get
install
-y
git libigraph0-dev
&&
\
...
...
devops/docker/docker-postgres
View file @
09de17bd
...
@@ -4,6 +4,6 @@ docker rm --volumes dbgarg || :
...
@@ -4,6 +4,6 @@ docker rm --volumes dbgarg || :
export PGPASSWORD="$(grep DB_PASS gargantext.ini | \awk '{print $3}')"
export PGPASSWORD="$(grep DB_PASS gargantext.ini | \awk '{print $3}')"
docker run --name dbgarg -e POSTGRES_USER=gargantua -e POSTGRES_DB=gargandbV5 -e POSTGRES_PASSWORD=${PGPASSWORD} -d postgres
docker run --name dbgarg -e POSTGRES_USER=gargantua -e POSTGRES_DB=gargandbV5 -e POSTGRES_PASSWORD=${PGPASSWORD} -d postgres
sleep 3
sleep 3
docker run -e PGPASSWORD -i --rm --link dbgarg:postgres postgres psql -h postgres -U gargantua -d gargandbV5 <
src/Gargantext/Database/Schema
/schema.sql
docker run -e PGPASSWORD -i --rm --link dbgarg:postgres postgres psql -h postgres -U gargantua -d gargandbV5 <
devops/postgres
/schema.sql
#docker run -e PGPASSWORD -i --rm --link dbgarg:postgres postgres psql -h postgres -U gargantua -d gargandbV5 < gargantext.dump
#docker run -e PGPASSWORD -i --rm --link dbgarg:postgres postgres psql -h postgres -U gargantua -d gargandbV5 < gargantext.dump
#docker run -e PGPASSWORD -i --rm --link dbgarg:postgres postgres dropdb -h postgres -U gargantua gargandbV5
#docker run -e PGPASSWORD -i --rm --link dbgarg:postgres postgres dropdb -h postgres -U gargantua gargandbV5
package.yaml
View file @
09de17bd
...
@@ -33,6 +33,7 @@ library:
...
@@ -33,6 +33,7 @@ library:
# - Gargantext.API.Orchestrator
# - Gargantext.API.Orchestrator
-
Gargantext.API.Search
-
Gargantext.API.Search
-
Gargantext.API.Settings
-
Gargantext.API.Settings
-
Gargantext.API.Types
-
Gargantext.Core
-
Gargantext.Core
-
Gargantext.Core.Types
-
Gargantext.Core.Types
-
Gargantext.Core.Types.Main
-
Gargantext.Core.Types.Main
...
@@ -130,7 +131,7 @@ library:
...
@@ -130,7 +131,7 @@ library:
-
hlcm
-
hlcm
-
ini
-
ini
-
insert-ordered-containers
-
insert-ordered-containers
-
jose
-jwt
-
jose
# - kmeans-vector
# - kmeans-vector
-
json-stream
-
json-stream
-
KMP
-
KMP
...
@@ -160,6 +161,7 @@ library:
...
@@ -160,6 +161,7 @@ library:
-
simple-reflect
-
simple-reflect
-
cereal
# (IGraph)
-
cereal
# (IGraph)
-
singletons
# (IGraph)
-
singletons
# (IGraph)
-
quickcheck-instances
-
random
-
random
-
rake
-
rake
-
regex-compat
-
regex-compat
...
@@ -169,6 +171,8 @@ library:
...
@@ -169,6 +171,8 @@ library:
-
semigroups
-
semigroups
-
servant
-
servant
-
servant-auth
-
servant-auth
-
servant-auth-server >= 0.4.4.0
-
servant-auth-swagger
-
servant-blaze
-
servant-blaze
-
servant-client
-
servant-client
# - servant-job
# - servant-job
...
...
src/Gargantext/API.hs
View file @
09de17bd
...
@@ -55,6 +55,9 @@ import Network.Wai
...
@@ -55,6 +55,9 @@ import Network.Wai
import
Network.Wai.Handler.Warp
hiding
(
defaultSettings
)
import
Network.Wai.Handler.Warp
hiding
(
defaultSettings
)
import
Servant
import
Servant
import
Servant.Auth
as
SA
import
Servant.Auth.Server
(
AuthResult
(
..
))
import
Servant.Auth.Swagger
()
import
Servant.HTML.Blaze
(
HTML
)
import
Servant.HTML.Blaze
(
HTML
)
--import Servant.Mock (mock)
--import Servant.Mock (mock)
--import Servant.Job.Server (WithCallbacks)
--import Servant.Job.Server (WithCallbacks)
...
@@ -68,7 +71,7 @@ import Text.Blaze.Html (Html)
...
@@ -68,7 +71,7 @@ import Text.Blaze.Html (Html)
--import Gargantext.API.Swagger
--import Gargantext.API.Swagger
--import Gargantext.Database.Node.Contact (HyperdataContact)
--import Gargantext.Database.Node.Contact (HyperdataContact)
import
Gargantext.API.Auth
(
AuthRequest
,
AuthResponse
,
auth
)
import
Gargantext.API.Auth
(
AuthRequest
,
AuthResponse
,
AuthenticatedUser
(
..
),
AuthContext
,
auth
)
import
Gargantext.API.Count
(
CountAPI
,
count
,
Query
)
import
Gargantext.API.Count
(
CountAPI
,
count
,
Query
)
import
Gargantext.API.FrontEnd
(
FrontEndAPI
,
frontEndServer
)
import
Gargantext.API.FrontEnd
(
FrontEndAPI
,
frontEndServer
)
import
Gargantext.API.Ngrams
(
HasRepo
(
..
),
HasRepoSaver
(
..
),
saveRepo
,
TableNgramsApi
,
apiNgramsTableDoc
)
import
Gargantext.API.Ngrams
(
HasRepo
(
..
),
HasRepoSaver
(
..
),
saveRepo
,
TableNgramsApi
,
apiNgramsTableDoc
)
...
@@ -76,9 +79,6 @@ import Gargantext.API.Node
...
@@ -76,9 +79,6 @@ import Gargantext.API.Node
import
Gargantext.API.Search
(
SearchPairsAPI
,
searchPairs
)
import
Gargantext.API.Search
(
SearchPairsAPI
,
searchPairs
)
import
Gargantext.API.Types
import
Gargantext.API.Types
import
qualified
Gargantext.API.Corpus.New
as
New
import
qualified
Gargantext.API.Corpus.New
as
New
import
Gargantext.Core.Types
(
HasInvalidError
(
..
))
import
Gargantext.Database.Schema.Node
(
HasNodeError
(
..
),
NodeError
)
import
Gargantext.Database.Tree
(
HasTreeError
(
..
),
TreeError
)
import
Gargantext.Database.Types.Node
import
Gargantext.Database.Types.Node
import
Gargantext.Database.Types.Node
(
NodeId
,
CorpusId
,
AnnuaireId
)
import
Gargantext.Database.Types.Node
(
NodeId
,
CorpusId
,
AnnuaireId
)
import
Gargantext.Database.Utils
(
HasConnection
)
import
Gargantext.Database.Utils
(
HasConnection
)
...
@@ -109,24 +109,8 @@ import Network.HTTP.Types hiding (Query)
...
@@ -109,24 +109,8 @@ import Network.HTTP.Types hiding (Query)
import
Gargantext.API.Settings
import
Gargantext.API.Settings
data
GargError
showAsServantErr
::
GargError
->
ServerError
=
GargNodeError
NodeError
showAsServantErr
(
GargServerError
err
)
=
err
|
GargTreeError
TreeError
|
GargInvalidError
Validation
deriving
(
Show
)
makePrisms
''
G
argError
instance
HasNodeError
GargError
where
_NodeError
=
_GargNodeError
instance
HasInvalidError
GargError
where
_InvalidError
=
_GargInvalidError
instance
HasTreeError
GargError
where
_TreeError
=
_GargTreeError
showAsServantErr
::
Show
a
=>
a
->
ServerError
showAsServantErr
a
=
err500
{
errBody
=
BL8
.
pack
$
show
a
}
showAsServantErr
a
=
err500
{
errBody
=
BL8
.
pack
$
show
a
}
fireWall
::
Applicative
f
=>
Request
->
FireWall
->
f
Bool
fireWall
::
Applicative
f
=>
Request
->
FireWall
->
f
Bool
...
@@ -231,15 +215,21 @@ type GargAPI' =
...
@@ -231,15 +215,21 @@ type GargAPI' =
"auth"
:>
Summary
"AUTH API"
"auth"
:>
Summary
"AUTH API"
:>
ReqBody
'[
J
SON
]
AuthRequest
:>
ReqBody
'[
J
SON
]
AuthRequest
:>
Post
'[
J
SON
]
AuthResponse
:>
Post
'[
J
SON
]
AuthResponse
-- TODO-ACCESS here we want to request a particular header for
-- auth and capabilities.
:<|>
GargPrivateAPI
type
GargPrivateAPI
=
SA
.
Auth
'[
S
A
.
JWT
]
AuthenticatedUser
:>
GargPrivateAPI'
type
GargPrivateAPI'
=
-- Roots endpoint
-- Roots endpoint
:<|>
"user"
:>
Summary
"First user endpoint"
"user"
:>
Summary
"First user endpoint"
:>
Roots
:>
Roots
-- Node endpoint
-- Node endpoint
:<|>
"node"
:>
Summary
"Node endpoint"
:<|>
"node"
:>
Summary
"Node endpoint"
:>
Capture
"id"
NodeId
:>
NodeAPI
HyperdataAny
:>
Capture
"id"
NodeId
:>
NodeAPI
HyperdataAny
-- Corpus endpoint
-- Corpus endpoint
:<|>
"corpus"
:>
Summary
"Corpus endpoint"
:<|>
"corpus"
:>
Summary
"Corpus endpoint"
:>
Capture
"id"
CorpusId
:>
NodeAPI
HyperdataCorpus
:>
Capture
"id"
CorpusId
:>
NodeAPI
HyperdataCorpus
...
@@ -290,6 +280,10 @@ type SwaggerFrontAPI = SwaggerAPI :<|> FrontEndAPI
...
@@ -290,6 +280,10 @@ type SwaggerFrontAPI = SwaggerAPI :<|> FrontEndAPI
type
API
=
SwaggerFrontAPI
:<|>
GargAPI
:<|>
Get
'[
H
TML
]
Html
type
API
=
SwaggerFrontAPI
:<|>
GargAPI
:<|>
Get
'[
H
TML
]
Html
-- This is the concrete monad. It needs to be used as little as possible,
-- instead, prefer GargServer, GargServerT, GargServerC.
type
GargServerM
env
err
=
ReaderT
env
(
ExceptT
err
IO
)
---------------------------------------------------------------------
---------------------------------------------------------------------
-- | Server declarations
-- | Server declarations
...
@@ -298,19 +292,28 @@ server :: forall env. (HasConnection env, HasRepo env, HasSettings env)
...
@@ -298,19 +292,28 @@ server :: forall env. (HasConnection env, HasRepo env, HasSettings env)
server
env
=
do
server
env
=
do
-- orchestrator <- scrapyOrchestrator env
-- orchestrator <- scrapyOrchestrator env
pure
$
swaggerFront
pure
$
swaggerFront
:<|>
hoistServer
(
Proxy
::
Proxy
GargAPI
)
transform
serverGargAPI
:<|>
hoistServer
WithContext
(
Proxy
::
Proxy
GargAPI
)
(
Proxy
::
Proxy
AuthContext
)
transform
serverGargAPI
:<|>
serverStatic
:<|>
serverStatic
where
where
transform
::
forall
a
.
ReaderT
env
(
ExceptT
GargError
IO
)
a
->
Handler
a
transform
::
forall
a
.
GargServerM
env
GargError
a
->
Handler
a
transform
=
Handler
.
withExceptT
showAsServantErr
.
(`
runReaderT
`
env
)
transform
=
Handler
.
withExceptT
showAsServantErr
.
(`
runReaderT
`
env
)
serverGargAPI
::
GargServer
GargAPI
serverGargAPI
::
GargServer
T
env
err
(
GargServerM
env
err
)
GargAPI
serverGargAPI
-- orchestrator
serverGargAPI
-- orchestrator
=
auth
=
auth
:<|>
serverPrivateGargAPI
:<|>
roots
-- :<|> orchestrator
:<|>
nodeAPI
(
Proxy
::
Proxy
HyperdataAny
)
fakeUserId
:<|>
nodeAPI
(
Proxy
::
Proxy
HyperdataCorpus
)
fakeUserId
serverPrivateGargAPI
::
GargServerT
env
err
(
GargServerM
env
err
)
GargPrivateAPI
:<|>
nodeAPI
(
Proxy
::
Proxy
HyperdataAnnuaire
)
fakeUserId
serverPrivateGargAPI
(
Authenticated
auser
)
=
serverPrivateGargAPI'
auser
serverPrivateGargAPI
_
=
throwAll'
(
_ServerError
#
err401
)
-- Here throwAll' requires a concrete type for the monad.
serverPrivateGargAPI'
::
AuthenticatedUser
->
GargServer
GargPrivateAPI'
serverPrivateGargAPI'
(
AuthenticatedUser
(
NodeId
uid
))
=
roots
:<|>
nodeAPI
(
Proxy
::
Proxy
HyperdataAny
)
uid
:<|>
nodeAPI
(
Proxy
::
Proxy
HyperdataCorpus
)
uid
:<|>
nodeAPI
(
Proxy
::
Proxy
HyperdataAnnuaire
)
uid
:<|>
apiNgramsTableDoc
:<|>
apiNgramsTableDoc
:<|>
nodesAPI
:<|>
nodesAPI
:<|>
count
-- TODO: undefined
:<|>
count
-- TODO: undefined
...
@@ -318,10 +321,7 @@ serverGargAPI -- orchestrator
...
@@ -318,10 +321,7 @@ serverGargAPI -- orchestrator
:<|>
graphAPI
-- TODO: mock
:<|>
graphAPI
-- TODO: mock
:<|>
treeAPI
:<|>
treeAPI
:<|>
New
.
api
:<|>
New
.
api
:<|>
New
.
info
fakeUserId
:<|>
New
.
info
uid
-- :<|> orchestrator
where
fakeUserId
=
2
-- TODO, byDefault user1 (if users automatically generated with inserUsersDemo)
serverStatic
::
Server
(
Get
'[
H
TML
]
Html
)
serverStatic
::
Server
(
Get
'[
H
TML
]
Html
)
serverStatic
=
$
(
do
serverStatic
=
$
(
do
...
@@ -341,7 +341,13 @@ swaggerFront = schemaUiServer swaggerDoc
...
@@ -341,7 +341,13 @@ swaggerFront = schemaUiServer swaggerDoc
---------------------------------------------------------------------
---------------------------------------------------------------------
makeApp
::
(
HasConnection
env
,
HasRepo
env
,
HasSettings
env
)
makeApp
::
(
HasConnection
env
,
HasRepo
env
,
HasSettings
env
)
=>
env
->
IO
Application
=>
env
->
IO
Application
makeApp
=
fmap
(
serve
api
)
.
server
makeApp
env
=
serveWithContext
api
cfg
<$>
server
env
where
cfg
::
Servant
.
Context
AuthContext
cfg
=
env
^.
settings
.
jwtSettings
:.
env
^.
settings
.
cookieSettings
-- :. authCheck env
:.
EmptyContext
--appMock :: Application
--appMock :: Application
--appMock = serve api (swaggerFront :<|> gargMock :<|> serverStatic)
--appMock = serve api (swaggerFront :<|> gargMock :<|> serverStatic)
...
...
src/Gargantext/API/Auth.hs
View file @
09de17bd
...
@@ -16,6 +16,8 @@ Main authorisation of Gargantext are managed in this module
...
@@ -16,6 +16,8 @@ Main authorisation of Gargantext are managed in this module
-- 2: Implement the Auth API backend
-- 2: Implement the Auth API backend
https://github.com/haskell-servant/servant-auth
https://github.com/haskell-servant/servant-auth
TODO-ACCESS Critical
-}
-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE NoImplicitPrelude #-}
...
@@ -28,15 +30,22 @@ Main authorisation of Gargantext are managed in this module
...
@@ -28,15 +30,22 @@ Main authorisation of Gargantext are managed in this module
module
Gargantext.API.Auth
module
Gargantext.API.Auth
where
where
import
Control.Lens
(
view
)
import
Control.Monad.IO.Class
(
liftIO
)
import
Data.Aeson.TH
(
deriveJSON
)
import
Data.Aeson.TH
(
deriveJSON
)
import
Data.List
(
elem
)
import
Data.List
(
elem
)
import
Data.Swagger
import
Data.Swagger
import
Data.Text
(
Text
,
reverse
)
import
Data.Text
(
Text
,
reverse
)
import
Data.Text.Lazy
(
toStrict
)
import
Data.Text.Lazy.Encoding
(
decodeUtf8
)
import
GHC.Generics
(
Generic
)
import
GHC.Generics
(
Generic
)
import
Servant.Auth.Server
import
Gargantext.Core.Utils.Prefix
(
unPrefix
)
import
Gargantext.Core.Utils.Prefix
(
unPrefix
)
import
Gargantext.API.Settings
import
Gargantext.API.Types
(
HasJoseError
(
..
),
joseError
)
import
Gargantext.Database.Root
(
getRoot
)
import
Gargantext.Database.Root
(
getRoot
)
import
Gargantext.Database.Types.Node
(
NodePoly
(
_node_id
),
NodeId
)
import
Gargantext.Database.Types.Node
(
NodePoly
(
_node_id
),
NodeId
)
import
Gargantext.Database.Utils
(
Cmd
)
import
Gargantext.Database.Utils
(
Cmd
'
,
HasConnection
)
import
Gargantext.Prelude
hiding
(
reverse
)
import
Gargantext.Prelude
hiding
(
reverse
)
import
Test.QuickCheck
(
elements
,
oneof
)
import
Test.QuickCheck
(
elements
,
oneof
)
import
Test.QuickCheck.Arbitrary
(
Arbitrary
,
arbitrary
)
import
Test.QuickCheck.Arbitrary
(
Arbitrary
,
arbitrary
)
...
@@ -74,15 +83,30 @@ type TreeId = NodeId
...
@@ -74,15 +83,30 @@ type TreeId = NodeId
data
CheckAuth
=
InvalidUser
|
InvalidPassword
|
Valid
Token
TreeId
data
CheckAuth
=
InvalidUser
|
InvalidPassword
|
Valid
Token
TreeId
deriving
(
Eq
)
deriving
(
Eq
)
checkAuthRequest
::
Username
->
Password
->
Cmd
err
CheckAuth
makeTokenForUser
::
(
HasSettings
env
,
HasJoseError
err
)
=>
NodeId
->
Cmd'
env
err
Token
makeTokenForUser
uid
=
do
jwtS
<-
view
$
settings
.
jwtSettings
e
<-
liftIO
$
makeJWT
(
AuthenticatedUser
uid
)
jwtS
Nothing
-- TODO-SECURITY here we can implement token expiration ^^.
either
joseError
(
pure
.
toStrict
.
decodeUtf8
)
e
-- TODO not sure about the encoding...
checkAuthRequest
::
(
HasSettings
env
,
HasConnection
env
,
HasJoseError
err
)
=>
Username
->
Password
->
Cmd'
env
err
CheckAuth
checkAuthRequest
u
p
checkAuthRequest
u
p
|
not
(
u
`
elem
`
arbitraryUsername
)
=
pure
InvalidUser
|
not
(
u
`
elem
`
arbitraryUsername
)
=
pure
InvalidUser
|
u
/=
reverse
p
=
pure
InvalidPassword
|
u
/=
reverse
p
=
pure
InvalidPassword
|
otherwise
=
do
|
otherwise
=
do
muId
<-
getRoot
"user1"
muId
<-
head
<$>
getRoot
"user1"
-- TODO user1 hard-coded
pure
$
maybe
InvalidUser
(
Valid
"token"
.
_node_id
)
$
head
muId
case
_node_id
<$>
muId
of
Nothing
->
pure
InvalidUser
auth
::
AuthRequest
->
Cmd
err
AuthResponse
Just
uid
->
do
token
<-
makeTokenForUser
uid
pure
$
Valid
token
uid
auth
::
(
HasSettings
env
,
HasConnection
env
,
HasJoseError
err
)
=>
AuthRequest
->
Cmd'
env
err
AuthResponse
auth
(
AuthRequest
u
p
)
=
do
auth
(
AuthRequest
u
p
)
=
do
checkAuthRequest'
<-
checkAuthRequest
u
p
checkAuthRequest'
<-
checkAuthRequest
u
p
case
checkAuthRequest'
of
case
checkAuthRequest'
of
...
@@ -90,9 +114,34 @@ auth (AuthRequest u p) = do
...
@@ -90,9 +114,34 @@ auth (AuthRequest u p) = do
InvalidPassword
->
pure
$
AuthResponse
Nothing
(
Just
$
AuthInvalid
"Invalid password"
)
InvalidPassword
->
pure
$
AuthResponse
Nothing
(
Just
$
AuthInvalid
"Invalid password"
)
Valid
to
trId
->
pure
$
AuthResponse
(
Just
$
AuthValid
to
trId
)
Nothing
Valid
to
trId
->
pure
$
AuthResponse
(
Just
$
AuthValid
to
trId
)
Nothing
newtype
AuthenticatedUser
=
AuthenticatedUser
{
_au_id
::
NodeId
}
deriving
(
Generic
)
$
(
deriveJSON
(
unPrefix
"_au_"
)
''
A
uthenticatedUser
)
instance
ToSchema
AuthenticatedUser
instance
ToJWT
AuthenticatedUser
instance
FromJWT
AuthenticatedUser
--type instance BasicAuthCfg = BasicAuthData -> IO (AuthResult AuthenticatedUser)
-- TODO-SECURITY why is the CookieSettings necessary?
type
AuthContext
=
'[
J
WTSettings
,
CookieSettings
]
-- , BasicAuthCfg
{-
instance FromBasicAuthData AuthenticatedUser where
fromBasicAuthData authData authCheckFunction = authCheckFunction authData
authCheck :: forall env. env
-> BasicAuthData
-> IO (AuthResult AuthenticatedUser)
authCheck _env (BasicAuthData login password) = pure $
maybe Indefinite Authenticated $ TODO
-}
-- | Instances
-- | Instances
$
(
deriveJSON
(
unPrefix
"_authReq_"
)
''
A
uthRequest
)
$
(
deriveJSON
(
unPrefix
"_authReq_"
)
''
A
uthRequest
)
instance
ToSchema
AuthRequest
instance
ToSchema
AuthRequest
-- TODO-SWAGGER unPrefix
instance
Arbitrary
AuthRequest
where
instance
Arbitrary
AuthRequest
where
arbitrary
=
elements
[
AuthRequest
u
p
arbitrary
=
elements
[
AuthRequest
u
p
...
@@ -101,20 +150,20 @@ instance Arbitrary AuthRequest where
...
@@ -101,20 +150,20 @@ instance Arbitrary AuthRequest where
]
]
$
(
deriveJSON
(
unPrefix
"_authRes_"
)
''
A
uthResponse
)
$
(
deriveJSON
(
unPrefix
"_authRes_"
)
''
A
uthResponse
)
instance
ToSchema
AuthResponse
instance
ToSchema
AuthResponse
-- TODO-SWAGGER unPrefix
instance
Arbitrary
AuthResponse
where
instance
Arbitrary
AuthResponse
where
arbitrary
=
oneof
[
AuthResponse
Nothing
.
Just
<$>
arbitrary
arbitrary
=
oneof
[
AuthResponse
Nothing
.
Just
<$>
arbitrary
,
flip
AuthResponse
Nothing
.
Just
<$>
arbitrary
]
,
flip
AuthResponse
Nothing
.
Just
<$>
arbitrary
]
$
(
deriveJSON
(
unPrefix
"_authInv_"
)
''
A
uthInvalid
)
$
(
deriveJSON
(
unPrefix
"_authInv_"
)
''
A
uthInvalid
)
instance
ToSchema
AuthInvalid
instance
ToSchema
AuthInvalid
-- TODO-SWAGGER unPrefix
instance
Arbitrary
AuthInvalid
where
instance
Arbitrary
AuthInvalid
where
arbitrary
=
elements
[
AuthInvalid
m
arbitrary
=
elements
[
AuthInvalid
m
|
m
<-
[
"Invalid user"
,
"Invalid password"
]
|
m
<-
[
"Invalid user"
,
"Invalid password"
]
]
]
$
(
deriveJSON
(
unPrefix
"_authVal_"
)
''
A
uthValid
)
$
(
deriveJSON
(
unPrefix
"_authVal_"
)
''
A
uthValid
)
instance
ToSchema
AuthValid
instance
ToSchema
AuthValid
-- TODO-SWAGGER unPrefix
instance
Arbitrary
AuthValid
where
instance
Arbitrary
AuthValid
where
arbitrary
=
elements
[
AuthValid
to
tr
arbitrary
=
elements
[
AuthValid
to
tr
|
to
<-
[
"token0"
,
"token1"
]
|
to
<-
[
"token0"
,
"token1"
]
...
...
src/Gargantext/API/Corpus/New.hs
View file @
09de17bd
...
@@ -70,6 +70,8 @@ type Api = Summary "New Corpus endpoint"
...
@@ -70,6 +70,8 @@ type Api = Summary "New Corpus endpoint"
:<|>
Get
'[
J
SON
]
ApiInfo
:<|>
Get
'[
J
SON
]
ApiInfo
-- | TODO manage several apis
-- | TODO manage several apis
-- TODO-ACCESS
-- TODO this is only the POST
api
::
(
FlowCmdM
env
err
m
)
=>
Query
->
m
CorpusId
api
::
(
FlowCmdM
env
err
m
)
=>
Query
->
m
CorpusId
api
(
Query
q
_
as
)
=
do
api
(
Query
q
_
as
)
=
do
cId
<-
case
head
as
of
cId
<-
case
head
as
of
...
...
src/Gargantext/API/Ngrams.hs
View file @
09de17bd
{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}
{-|
{-|
Module : Gargantext.API.Ngrams
Module : Gargantext.API.Ngrams
Description : Server API
Description : Server API
...
@@ -32,6 +33,52 @@ add get
...
@@ -32,6 +33,52 @@ add get
{-# OPTIONS -fno-warn-orphans #-}
{-# OPTIONS -fno-warn-orphans #-}
module
Gargantext.API.Ngrams
module
Gargantext.API.Ngrams
(
TableNgramsApi
,
TableNgramsApiGet
,
TableNgramsApiPut
,
TableNgramsApiPost
,
getTableNgrams
,
putListNgrams
,
tableNgramsPost
,
apiNgramsTableCorpus
,
apiNgramsTableDoc
,
NgramsStatePatch
,
NgramsTablePatch
,
NgramsElement
,
mkNgramsElement
,
mergeNgramsElement
,
RootParent
(
..
)
,
MSet
,
mSetFromList
,
mSetToList
,
Repo
(
..
)
,
r_version
,
r_state
,
NgramsRepo
,
NgramsRepoElement
(
..
)
,
saveRepo
,
initRepo
,
RepoEnv
(
..
)
,
renv_var
,
renv_lock
,
TabType
(
..
)
,
ngramsTypeFromTabType
,
HasRepoVar
(
..
)
,
HasRepoSaver
(
..
)
,
HasRepo
(
..
)
,
RepoCmdM
,
QueryParamR
,
TODO
(
..
)
)
where
where
-- import Debug.Trace (trace)
-- import Debug.Trace (trace)
...
@@ -798,12 +845,14 @@ putListNgrams listId ngramsType nes = do
...
@@ -798,12 +845,14 @@ putListNgrams listId ngramsType nes = do
where
where
m
=
Map
.
fromList
$
(
\
n
->
(
n
^.
ne_ngrams
,
ngramsElementToRepo
n
))
<$>
nes
m
=
Map
.
fromList
$
(
\
n
->
(
n
^.
ne_ngrams
,
ngramsElementToRepo
n
))
<$>
nes
-- TODO-ACCESS check
tableNgramsPost
::
RepoCmdM
env
err
m
=>
TabType
->
NodeId
->
Maybe
ListType
->
[
NgramsTerm
]
->
m
()
tableNgramsPost
::
RepoCmdM
env
err
m
=>
TabType
->
NodeId
->
Maybe
ListType
->
[
NgramsTerm
]
->
m
()
tableNgramsPost
tabType
listId
mayList
=
tableNgramsPost
tabType
listId
mayList
=
putListNgrams
listId
(
ngramsTypeFromTabType
tabType
)
.
fmap
(
newNgramsElement
mayList
)
putListNgrams
listId
(
ngramsTypeFromTabType
tabType
)
.
fmap
(
newNgramsElement
mayList
)
-- Apply the given patch to the DB and returns the patch to be applied on the
-- Apply the given patch to the DB and returns the patch to be applied on the
-- client.
-- client.
-- TODO-ACCESS check
tableNgramsPut
::
(
HasInvalidError
err
,
RepoCmdM
env
err
m
)
tableNgramsPut
::
(
HasInvalidError
err
,
RepoCmdM
env
err
m
)
=>
TabType
->
ListId
=>
TabType
->
ListId
->
Versioned
NgramsTablePatch
->
Versioned
NgramsTablePatch
...
...
src/Gargantext/API/Ngrams/Tools.hs
View file @
09de17bd
...
@@ -33,6 +33,10 @@ import qualified Data.Set as Set
...
@@ -33,6 +33,10 @@ import qualified Data.Set as Set
type
RootTerm
=
Text
type
RootTerm
=
Text
-- TODO-ACCESS: We want to do the security check before entering here.
-- Add a static capability parameter would be nice.
-- Ideally this is the access to `repoVar` which needs to
-- be properly guarded.
getListNgrams
::
RepoCmdM
env
err
m
getListNgrams
::
RepoCmdM
env
err
m
=>
[
ListId
]
->
NgramsType
=>
[
ListId
]
->
NgramsType
->
m
(
Map
Text
NgramsRepoElement
)
->
m
(
Map
Text
NgramsRepoElement
)
...
...
src/Gargantext/API/Node.hs
View file @
09de17bd
...
@@ -7,6 +7,8 @@ Maintainer : team@gargantext.org
...
@@ -7,6 +7,8 @@ Maintainer : team@gargantext.org
Stability : experimental
Stability : experimental
Portability : POSIX
Portability : POSIX
-- TODO-SECURITY: Critical
-- TODO-ACCESS: CanGetNode
-- TODO-ACCESS: CanGetNode
-- TODO-EVENTS: No events as this is a read only query.
-- TODO-EVENTS: No events as this is a read only query.
Node API
Node API
...
...
src/Gargantext/API/Settings.hs
View file @
09de17bd
...
@@ -6,6 +6,8 @@ License : AGPL + CECILL v3
...
@@ -6,6 +6,8 @@ License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Maintainer : team@gargantext.org
Stability : experimental
Stability : experimental
Portability : POSIX
Portability : POSIX
TODO-SECURITY: Critical
-}
-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
...
@@ -40,16 +42,15 @@ import Data.Aeson
...
@@ -40,16 +42,15 @@ import Data.Aeson
import
Data.Maybe
(
fromMaybe
)
import
Data.Maybe
(
fromMaybe
)
import
Data.Either
(
either
)
import
Data.Either
(
either
)
import
Data.Text
import
Data.Text
import
Data.Text.Encoding
(
encodeUtf8
)
--
import Data.Text.Encoding (encodeUtf8)
import
Data.ByteString
(
ByteString
)
import
Data.ByteString
(
ByteString
)
import
qualified
Data.ByteString.Lazy
as
L
import
qualified
Data.ByteString.Lazy
as
L
import
Servant
import
Servant
import
Servant.Auth.Server
(
defaultJWTSettings
,
JWTSettings
,
CookieSettings
,
defaultCookieSettings
,
readKey
,
writeKey
)
import
Servant.Client
(
BaseUrl
,
parseBaseUrl
)
import
Servant.Client
(
BaseUrl
,
parseBaseUrl
)
--import Servant.Job.Async (newJobEnv, defaultSettings)
--import Servant.Job.Async (newJobEnv, defaultSettings)
import
Web.HttpApiData
(
parseUrlPiece
)
import
Web.HttpApiData
(
parseUrlPiece
)
import
qualified
Jose.Jwk
as
Jose
import
qualified
Jose.Jwa
as
Jose
import
Control.Concurrent
import
Control.Concurrent
import
Control.Debounce
(
mkDebounce
,
defaultDebounceSettings
,
debounceFreq
,
debounceAction
)
import
Control.Debounce
(
mkDebounce
,
defaultDebounceSettings
,
debounceFreq
,
debounceAction
)
...
@@ -77,7 +78,8 @@ data Settings = Settings
...
@@ -77,7 +78,8 @@ data Settings = Settings
,
_logLevelLimit
::
LogLevel
-- log level from the monad-logger package
,
_logLevelLimit
::
LogLevel
-- log level from the monad-logger package
-- , _dbServer :: Text
-- , _dbServer :: Text
-- ^ this is not used yet
-- ^ this is not used yet
,
_jwtSecret
::
Jose
.
Jwk
-- key from the jose-jwt package
,
_jwtSettings
::
JWTSettings
,
_cookieSettings
::
CookieSettings
,
_sendLoginEmails
::
SendEmailType
,
_sendLoginEmails
::
SendEmailType
,
_scrapydUrl
::
BaseUrl
,
_scrapydUrl
::
BaseUrl
,
_fileFolder
::
FilePath
,
_fileFolder
::
FilePath
...
@@ -89,29 +91,22 @@ class HasSettings env where
...
@@ -89,29 +91,22 @@ class HasSettings env where
settings
::
Getter
env
Settings
settings
::
Getter
env
Settings
parseJwk
::
Text
->
Jose
.
Jwk
devSettings
::
FilePath
->
IO
Settings
parseJwk
secretStr
=
jwk
devSettings
jwkFile
=
do
where
jwkExists
<-
doesFileExist
jwkFile
secretBs
=
encodeUtf8
secretStr
when
(
not
jwkExists
)
$
writeKey
jwkFile
jwk
=
Jose
.
SymmetricJwk
secretBs
jwk
<-
readKey
jwkFile
Nothing
pure
$
Settings
Nothing
(
Just
$
Jose
.
Signed
Jose
.
HS256
)
devSettings
::
Settings
devSettings
=
Settings
{
_allowedOrigin
=
"http://localhost:8008"
{
_allowedOrigin
=
"http://localhost:8008"
,
_allowedHost
=
"localhost:3000"
,
_allowedHost
=
"localhost:3000"
,
_appPort
=
3000
,
_appPort
=
3000
,
_logLevelLimit
=
LevelDebug
,
_logLevelLimit
=
LevelDebug
-- , _dbServer = "localhost"
-- , _dbServer = "localhost"
-- generate with dd if=/dev/urandom bs=1 count=32 | base64
-- make sure jwtSecret differs between development and production, because you do not want
-- your production key inside source control.
,
_jwtSecret
=
parseJwk
"MVg0YAPVSPiYQc/qIs/rV/X32EFR0zOJWfHFgMbszMw="
,
_sendLoginEmails
=
LogEmailToConsole
,
_sendLoginEmails
=
LogEmailToConsole
,
_scrapydUrl
=
fromMaybe
(
panic
"Invalid scrapy URL"
)
$
parseBaseUrl
"http://localhost:6800"
,
_scrapydUrl
=
fromMaybe
(
panic
"Invalid scrapy URL"
)
$
parseBaseUrl
"http://localhost:6800"
,
_fileFolder
=
"data"
,
_fileFolder
=
"data"
,
_cookieSettings
=
defaultCookieSettings
-- TODO-SECURITY tune
,
_jwtSettings
=
defaultJWTSettings
jwk
-- TODO-SECURITY tune
}
}
...
@@ -232,10 +227,13 @@ readRepoEnv = do
...
@@ -232,10 +227,13 @@ readRepoEnv = do
saver
<-
mkRepoSaver
mvar
saver
<-
mkRepoSaver
mvar
pure
$
RepoEnv
{
_renv_var
=
mvar
,
_renv_saver
=
saver
,
_renv_lock
=
lock
}
pure
$
RepoEnv
{
_renv_var
=
mvar
,
_renv_saver
=
saver
,
_renv_lock
=
lock
}
devJwkFile
::
FilePath
devJwkFile
=
"dev.jwk"
newEnv
::
PortNumber
->
FilePath
->
IO
Env
newEnv
::
PortNumber
->
FilePath
->
IO
Env
newEnv
port
file
=
do
newEnv
port
file
=
do
manager
<-
newTlsManager
manager
<-
newTlsManager
settings
<-
pure
(
devSettings
&
appPort
.~
port
)
-- TODO read from 'file'
settings
<-
devSettings
devJwkFile
<&>
appPort
.~
port
-- TODO read from 'file'
when
(
port
/=
settings
^.
appPort
)
$
when
(
port
/=
settings
^.
appPort
)
$
panic
"TODO: conflicting settings of port"
panic
"TODO: conflicting settings of port"
...
@@ -295,10 +293,11 @@ withDevEnv iniPath k = do
...
@@ -295,10 +293,11 @@ withDevEnv iniPath k = do
param
<-
databaseParameters
iniPath
param
<-
databaseParameters
iniPath
conn
<-
connect
param
conn
<-
connect
param
repo
<-
readRepoEnv
repo
<-
readRepoEnv
setts
<-
devSettings
devJwkFile
pure
$
DevEnv
pure
$
DevEnv
{
_dev_env_conn
=
conn
{
_dev_env_conn
=
conn
,
_dev_env_repo
=
repo
,
_dev_env_repo
=
repo
,
_dev_env_settings
=
devSetting
s
,
_dev_env_settings
=
sett
s
}
}
-- | Run Cmd Sugar for the Repl (GHCI)
-- | Run Cmd Sugar for the Repl (GHCI)
...
...
src/Gargantext/API/Types.hs
View file @
09de17bd
...
@@ -10,13 +10,26 @@ Portability : POSIX
...
@@ -10,13 +10,26 @@ Portability : POSIX
-}
-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module
Gargantext.API.Types
module
Gargantext.API.Types
where
where
import
Control.Lens
(
Prism
'
,
(
#
))
import
Control.Lens.TH
(
makePrisms
)
import
Control.Monad.Error.Class
(
MonadError
(
throwError
))
import
Crypto.JOSE.Error
as
Jose
import
Data.Validity
import
Servant
import
Servant
import
Gargantext.Prelude
import
Gargantext.API.Settings
import
Gargantext.API.Settings
import
Gargantext.API.Ngrams
import
Gargantext.API.Ngrams
import
Gargantext.Database.Tree
import
Gargantext.Database.Tree
...
@@ -24,18 +37,75 @@ import Gargantext.Core.Types
...
@@ -24,18 +37,75 @@ import Gargantext.Core.Types
import
Gargantext.Database.Utils
import
Gargantext.Database.Utils
import
Gargantext.Database.Schema.Node
import
Gargantext.Database.Schema.Node
class
HasServerError
e
where
_ServerError
::
Prism'
e
ServerError
type
GargServer
api
=
serverError
::
(
MonadError
e
m
,
HasServerError
e
)
=>
ServerError
->
m
a
forall
env
err
m
.
serverError
e
=
throwError
$
_ServerError
#
e
class
HasJoseError
e
where
_JoseError
::
Prism'
e
Jose
.
Error
joseError
::
(
MonadError
e
m
,
HasJoseError
e
)
=>
Jose
.
Error
->
m
a
joseError
=
throwError
.
(
_JoseError
#
)
class
ThrowAll'
e
a
|
a
->
e
where
-- | 'throwAll' is a convenience function to throw errors across an entire
-- sub-API
--
--
-- > throwAll err400 :: Handler a :<|> Handler b :<|> Handler c
-- > == throwError err400 :<|> throwError err400 :<|> err400
throwAll'
::
e
->
a
instance
(
ThrowAll'
e
a
,
ThrowAll'
e
b
)
=>
ThrowAll'
e
(
a
:<|>
b
)
where
throwAll'
e
=
throwAll'
e
:<|>
throwAll'
e
-- Really this shouldn't be necessary - ((->) a) should be an instance of
-- MonadError, no?
instance
{-# OVERLAPPING #-}
ThrowAll'
e
b
=>
ThrowAll'
e
(
a
->
b
)
where
throwAll'
e
=
const
$
throwAll'
e
instance
{-# OVERLAPPABLE #-}
(
MonadError
e
m
)
=>
ThrowAll'
e
(
m
a
)
where
throwAll'
=
throwError
type
GargServerC
env
err
m
=
(
CmdM
env
err
m
(
CmdM
env
err
m
,
HasNodeError
err
,
HasNodeError
err
,
HasInvalidError
err
,
HasInvalidError
err
,
HasTreeError
err
,
HasTreeError
err
,
HasServerError
err
,
HasJoseError
err
,
HasRepo
env
,
HasRepo
env
,
HasSettings
env
,
HasSettings
env
)
)
=>
ServerT
api
m
type
GargServerT
env
err
m
api
=
GargServerC
env
err
m
=>
ServerT
api
m
type
GargServer
api
=
forall
env
err
m
.
GargServerT
env
err
m
api
data
GargError
=
GargNodeError
NodeError
|
GargTreeError
TreeError
|
GargInvalidError
Validation
|
GargJoseError
Jose
.
Error
|
GargServerError
ServerError
deriving
(
Show
)
makePrisms
''
G
argError
instance
HasNodeError
GargError
where
_NodeError
=
_GargNodeError
instance
HasInvalidError
GargError
where
_InvalidError
=
_GargInvalidError
instance
HasTreeError
GargError
where
_TreeError
=
_GargTreeError
instance
HasServerError
GargError
where
_ServerError
=
_GargServerError
instance
HasJoseError
GargError
where
_JoseError
=
_GargJoseError
src/Gargantext/Database.hs
View file @
09de17bd
...
@@ -17,9 +17,9 @@ Gargantext's database.
...
@@ -17,9 +17,9 @@ Gargantext's database.
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE NoImplicitPrelude #-}
module
Gargantext.Database
(
module
Gargantext
.
Database
.
Utils
module
Gargantext.Database
(
module
Gargantext
.
Database
.
Utils
,
module
Gargantext
.
Database
.
Bashql
--
, module Gargantext.Database.Bashql
)
)
where
where
import
Gargantext.Database.Utils
(
connectGargandb
)
import
Gargantext.Database.Utils
(
connectGargandb
)
import
Gargantext.Database.Bashql
--
import Gargantext.Database.Bashql
src/Gargantext/Database/Access.hs
View file @
09de17bd
...
@@ -7,6 +7,7 @@ Maintainer : team@gargantext.org
...
@@ -7,6 +7,7 @@ Maintainer : team@gargantext.org
Stability : experimental
Stability : experimental
Portability : POSIX
Portability : POSIX
TODO-SECURITY review purpose of this module
-}
-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE NoImplicitPrelude #-}
...
...
src/Gargantext/Database/Bashql.hs
View file @
09de17bd
{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}
{-|
{-|
Module : Gargantext.Database.Bashql
Module : Gargantext.Database.Bashql
Description : BASHQL to deal with Gargantext Database.
Description : BASHQL to deal with Gargantext Database.
...
@@ -55,13 +56,15 @@ AMS, and by SIAM.
...
@@ -55,13 +56,15 @@ AMS, and by SIAM.
[3] https://github.com/Gabriel439/Haskell-Turtle-Library
[3] https://github.com/Gabriel439/Haskell-Turtle-Library
TODO-ACCESS: should the checks be done here or before.
-}
-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RankNTypes #-}
module
Gargantext.Database.Bashql
(
get
module
Gargantext.Database.Bashql
(
)
{-(
get
,
ls
,
ls
,
home
,
home
,
post
,
post
...
@@ -71,7 +74,7 @@ module Gargantext.Database.Bashql ( get
...
@@ -71,7 +74,7 @@ module Gargantext.Database.Bashql ( get
,
rename
,
rename
,
tree
,
tree
--
,
mk
Corpus
,
mkAnnuaire
--
,
mk
Corpus
,
mkAnnuaire
)
)
-
}
where
where
import
Control.Monad.Reader
-- (Reader, ask)
import
Control.Monad.Reader
-- (Reader, ask)
...
...
src/Gargantext/Database/Facet.hs
View file @
09de17bd
...
@@ -26,10 +26,22 @@ Portability : POSIX
...
@@ -26,10 +26,22 @@ Portability : POSIX
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilies #-}
------------------------------------------------------------------------
------------------------------------------------------------------------
module
Gargantext.Database.Facet
module
Gargantext.Database.Facet
(
runViewAuthorsDoc
,
runViewDocuments
,
filterWith
,
Pair
(
..
)
,
Facet
(
..
)
,
FacetDoc
,
FacetDocRead
,
FacetPaired
(
..
)
,
FacetPairedRead
,
OrderBy
(
..
)
)
where
where
------------------------------------------------------------------------
------------------------------------------------------------------------
import
Control.Arrow
(
returnA
)
import
Control.Arrow
(
returnA
)
import
Control.Lens.TH
(
makeLensesWith
,
abbreviatedFields
)
--
import Control.Lens.TH (makeLensesWith, abbreviatedFields)
import
Data.Aeson
(
FromJSON
,
ToJSON
)
import
Data.Aeson
(
FromJSON
,
ToJSON
)
import
Data.Aeson.TH
(
deriveJSON
)
import
Data.Aeson.TH
(
deriveJSON
)
import
Data.Either
(
Either
(
Left
))
import
Data.Either
(
Either
(
Left
))
...
@@ -70,9 +82,9 @@ type Title = Text
...
@@ -70,9 +82,9 @@ type Title = Text
-- TODO remove Title
-- TODO remove Title
type
FacetDoc
=
Facet
NodeId
UTCTime
Title
HyperdataDocument
(
Maybe
Favorite
)
(
Maybe
Double
)
type
FacetDoc
=
Facet
NodeId
UTCTime
Title
HyperdataDocument
(
Maybe
Favorite
)
(
Maybe
Double
)
type
FacetSources
=
FacetDoc
--
type FacetSources = FacetDoc
type
FacetAuthors
=
FacetDoc
--
type FacetAuthors = FacetDoc
type
FacetTerms
=
FacetDoc
--
type FacetTerms = FacetDoc
data
Facet
id
created
title
hyperdata
favorite
ngramCount
=
data
Facet
id
created
title
hyperdata
favorite
ngramCount
=
...
@@ -158,7 +170,7 @@ instance Arbitrary FacetDoc where
...
@@ -158,7 +170,7 @@ instance Arbitrary FacetDoc where
-- Facets / Views for the Front End
-- Facets / Views for the Front End
-- | Database instances
-- | Database instances
$
(
makeAdaptorAndInstance
"pFacetDoc"
''
F
acet
)
$
(
makeAdaptorAndInstance
"pFacetDoc"
''
F
acet
)
$
(
makeLensesWith
abbreviatedFields
''
F
acet
)
--
$(makeLensesWith abbreviatedFields ''Facet)
type
FacetDocRead
=
Facet
(
Column
PGInt4
)
type
FacetDocRead
=
Facet
(
Column
PGInt4
)
(
Column
PGTimestamptz
)
(
Column
PGTimestamptz
)
...
@@ -196,6 +208,7 @@ instance Arbitrary OrderBy
...
@@ -196,6 +208,7 @@ instance Arbitrary OrderBy
arbitrary
=
elements
[
minBound
..
maxBound
]
arbitrary
=
elements
[
minBound
..
maxBound
]
-- TODO-SECURITY check
runViewAuthorsDoc
::
ContactId
->
IsTrash
->
Maybe
Offset
->
Maybe
Limit
->
Maybe
OrderBy
->
Cmd
err
[
FacetDoc
]
runViewAuthorsDoc
::
ContactId
->
IsTrash
->
Maybe
Offset
->
Maybe
Limit
->
Maybe
OrderBy
->
Cmd
err
[
FacetDoc
]
runViewAuthorsDoc
cId
t
o
l
order
=
runOpaQuery
$
filterWith
o
l
order
$
viewAuthorsDoc
cId
t
ntId
runViewAuthorsDoc
cId
t
o
l
order
=
runOpaQuery
$
filterWith
o
l
order
$
viewAuthorsDoc
cId
t
ntId
where
where
...
@@ -236,6 +249,7 @@ queryAuthorsDoc = leftJoin5 queryNodeTable queryNodeNgramTable queryNgramsTable
...
@@ -236,6 +249,7 @@ queryAuthorsDoc = leftJoin5 queryNodeTable queryNodeNgramTable queryNgramsTable
------------------------------------------------------------------------
------------------------------------------------------------------------
-- TODO-SECURITY check
runViewDocuments
::
CorpusId
->
IsTrash
->
Maybe
Offset
->
Maybe
Limit
->
Maybe
OrderBy
->
Cmd
err
[
FacetDoc
]
runViewDocuments
::
CorpusId
->
IsTrash
->
Maybe
Offset
->
Maybe
Limit
->
Maybe
OrderBy
->
Cmd
err
[
FacetDoc
]
runViewDocuments
cId
t
o
l
order
=
runViewDocuments
cId
t
o
l
order
=
runOpaQuery
$
filterWith
o
l
order
$
viewDocuments
cId
t
ntId
runOpaQuery
$
filterWith
o
l
order
$
viewDocuments
cId
t
ntId
...
...
src/Gargantext/Database/Flow.hs
View file @
09de17bd
...
@@ -31,6 +31,13 @@ Portability : POSIX
...
@@ -31,6 +31,13 @@ Portability : POSIX
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedStrings #-}
module
Gargantext.Database.Flow
-- (flowDatabase, ngrams2list)
module
Gargantext.Database.Flow
-- (flowDatabase, ngrams2list)
(
FlowCmdM
,
flowCorpusFile
,
flowCorpus
,
flowCorpusSearchInDatabase
,
getOrMkRoot
,
getOrMkRootWithCorpus
)
where
where
import
Prelude
(
String
)
import
Prelude
(
String
)
import
Data.Either
import
Data.Either
...
@@ -45,7 +52,7 @@ import Data.Monoid
...
@@ -45,7 +52,7 @@ import Data.Monoid
import
Data.Text
(
Text
,
splitOn
,
intercalate
)
import
Data.Text
(
Text
,
splitOn
,
intercalate
)
import
GHC.Show
(
Show
)
import
GHC.Show
(
Show
)
import
Gargantext.API.Ngrams
(
HasRepoVar
)
import
Gargantext.API.Ngrams
(
HasRepoVar
)
import
Gargantext.API.Ngrams
(
NgramsElement
(
..
)
,
putListNgrams
,
RepoCmdM
)
import
Gargantext.API.Ngrams
(
NgramsElement
,
putListNgrams
,
RepoCmdM
)
import
Gargantext.Core
(
Lang
(
..
))
import
Gargantext.Core
(
Lang
(
..
))
import
Gargantext.Core.Types
(
NodePoly
(
..
),
Terms
(
..
))
import
Gargantext.Core.Types
(
NodePoly
(
..
),
Terms
(
..
))
import
Gargantext.Core.Types.Individu
(
Username
)
import
Gargantext.Core.Types.Individu
(
Username
)
...
@@ -99,30 +106,32 @@ getDataApi lang limit (ApiIsidoreQuery q) = Isidore.get lang limit (Just q) Noth
...
@@ -99,30 +106,32 @@ getDataApi lang limit (ApiIsidoreQuery q) = Isidore.get lang limit (Just q) Noth
getDataApi
lang
limit
(
ApiIsidoreAuth
q
)
=
Isidore
.
get
lang
limit
Nothing
(
Just
q
)
getDataApi
lang
limit
(
ApiIsidoreAuth
q
)
=
Isidore
.
get
lang
limit
Nothing
(
Just
q
)
flowCorpusApi
::
(
FlowCmdM
env
err
m
)
-- UNUSED
_flowCorpusApi
::
(
FlowCmdM
env
err
m
)
=>
Username
->
Either
CorpusName
[
CorpusId
]
=>
Username
->
Either
CorpusName
[
CorpusId
]
->
TermType
Lang
->
TermType
Lang
->
Maybe
Limit
->
Maybe
Limit
->
ApiQuery
->
ApiQuery
->
m
CorpusId
->
m
CorpusId
flowCorpusApi
u
n
tt
l
q
=
do
_
flowCorpusApi
u
n
tt
l
q
=
do
docs
<-
liftIO
$
splitEvery
500
<$>
getDataApi
(
_tt_lang
tt
)
l
q
docs
<-
liftIO
$
splitEvery
500
<$>
getDataApi
(
_tt_lang
tt
)
l
q
flowCorpus
u
n
tt
docs
flowCorpus
u
n
tt
docs
------------------------------------------------------------------------
------------------------------------------------------------------------
flowAnnuaire
::
FlowCmdM
env
err
m
-- UNUSED
_flowAnnuaire
::
FlowCmdM
env
err
m
=>
Username
->
Either
CorpusName
[
CorpusId
]
->
(
TermType
Lang
)
->
FilePath
->
m
AnnuaireId
=>
Username
->
Either
CorpusName
[
CorpusId
]
->
(
TermType
Lang
)
->
FilePath
->
m
AnnuaireId
flowAnnuaire
u
n
l
filePath
=
do
_
flowAnnuaire
u
n
l
filePath
=
do
docs
<-
liftIO
$
((
splitEvery
500
<$>
deserialiseImtUsersFromFile
filePath
)
::
IO
[[
HyperdataContact
]])
docs
<-
liftIO
$
((
splitEvery
500
<$>
deserialiseImtUsersFromFile
filePath
)
::
IO
[[
HyperdataContact
]])
flow
(
Nothing
::
Maybe
HyperdataAnnuaire
)
u
n
l
docs
flow
(
Nothing
::
Maybe
HyperdataAnnuaire
)
u
n
l
docs
-- UNUSED
flowCorpusDebat
::
FlowCmdM
env
err
m
_
flowCorpusDebat
::
FlowCmdM
env
err
m
=>
Username
->
Either
CorpusName
[
CorpusId
]
=>
Username
->
Either
CorpusName
[
CorpusId
]
->
Limit
->
FilePath
->
Limit
->
FilePath
->
m
CorpusId
->
m
CorpusId
flowCorpusDebat
u
n
l
fp
=
do
_
flowCorpusDebat
u
n
l
fp
=
do
docs
<-
liftIO
(
splitEvery
500
docs
<-
liftIO
(
splitEvery
500
<$>
take
l
<$>
take
l
<$>
readFile'
fp
<$>
readFile'
fp
...
@@ -151,19 +160,22 @@ flowCorpusSearchInDatabase u la q = do
...
@@ -151,19 +160,22 @@ flowCorpusSearchInDatabase u la q = do
flowCorpusUser
la
u
(
Left
q
)
(
Nothing
::
Maybe
HyperdataCorpus
)
ids
flowCorpusUser
la
u
(
Left
q
)
(
Nothing
::
Maybe
HyperdataCorpus
)
ids
flowCorpusSearchInDatabaseApi
::
FlowCmdM
env
err
m
-- UNUSED
_flowCorpusSearchInDatabaseApi
::
FlowCmdM
env
err
m
=>
Username
->
Lang
->
Text
->
m
CorpusId
=>
Username
->
Lang
->
Text
->
m
CorpusId
flowCorpusSearchInDatabaseApi
u
la
q
=
do
_
flowCorpusSearchInDatabaseApi
u
la
q
=
do
(
_masterUserId
,
_masterRootId
,
cId
)
<-
getOrMkRootWithCorpus
userMaster
(
Left
""
)
(
Nothing
::
Maybe
HyperdataCorpus
)
(
_masterUserId
,
_masterRootId
,
cId
)
<-
getOrMkRootWithCorpus
userMaster
(
Left
""
)
(
Nothing
::
Maybe
HyperdataCorpus
)
ids
<-
map
fst
<$>
searchInDatabase
cId
(
stemIt
q
)
ids
<-
map
fst
<$>
searchInDatabase
cId
(
stemIt
q
)
flowCorpusUser
la
u
(
Left
q
)
(
Nothing
::
Maybe
HyperdataCorpus
)
ids
flowCorpusUser
la
u
(
Left
q
)
(
Nothing
::
Maybe
HyperdataCorpus
)
ids
------------------------------------------------------------------------
------------------------------------------------------------------------
-- | TODO improve the needed type to create/update a corpus
-- | TODO improve the needed type to create/update a corpus
{- UNUSED
data UserInfo = Username Text
data UserInfo = Username Text
| UserId NodeId
| UserId NodeId
data CorpusInfo = CorpusName Lang Text
data CorpusInfo = CorpusName Lang Text
| CorpusId Lang NodeId
| CorpusId Lang NodeId
-}
flow
::
(
FlowCmdM
env
err
m
,
FlowCorpus
a
,
MkCorpus
c
)
flow
::
(
FlowCmdM
env
err
m
,
FlowCorpus
a
,
MkCorpus
c
)
...
...
src/Gargantext/Database/Flow/Pairing.hs
View file @
09de17bd
...
@@ -16,6 +16,7 @@ Portability : POSIX
...
@@ -16,6 +16,7 @@ Portability : POSIX
-- {-# LANGUAGE Arrows #-}
-- {-# LANGUAGE Arrows #-}
module
Gargantext.Database.Flow.Pairing
module
Gargantext.Database.Flow.Pairing
(
pairing
)
where
where
--import Debug.Trace (trace)
--import Debug.Trace (trace)
...
...
src/Gargantext/Database/Node/Update.hs
View file @
09de17bd
...
@@ -41,6 +41,7 @@ data Update = Rename NodeId Name
...
@@ -41,6 +41,7 @@ data Update = Rename NodeId Name
unOnly
::
Only
a
->
a
unOnly
::
Only
a
->
a
unOnly
(
Only
a
)
=
a
unOnly
(
Only
a
)
=
a
-- TODO-ACCESS
update
::
Update
->
Cmd
err
[
Int
]
update
::
Update
->
Cmd
err
[
Int
]
update
(
Rename
nId
name
)
=
map
unOnly
<$>
runPGSQuery
"UPDATE nodes SET name=? where id=? returning id"
update
(
Rename
nId
name
)
=
map
unOnly
<$>
runPGSQuery
"UPDATE nodes SET name=? where id=? returning id"
(
DT
.
take
255
name
,
nId
)
(
DT
.
take
255
name
,
nId
)
...
...
src/Gargantext/Database/TextSearch.hs
View file @
09de17bd
...
@@ -82,6 +82,7 @@ joinInCorpus = leftJoin queryNodeSearchTable queryNodeNodeTable cond
...
@@ -82,6 +82,7 @@ joinInCorpus = leftJoin queryNodeSearchTable queryNodeNodeTable cond
type
AuthorName
=
Text
type
AuthorName
=
Text
-- | TODO Optim: Offset and Limit in the Query
-- | TODO Optim: Offset and Limit in the Query
-- TODO-SECURITY check
searchInCorpusWithContacts
::
CorpusId
->
[
Text
]
->
Maybe
Offset
->
Maybe
Limit
->
Maybe
OrderBy
->
Cmd
err
[
FacetPaired
Int
UTCTime
HyperdataDocument
Int
[
Pair
Int
Text
]]
searchInCorpusWithContacts
::
CorpusId
->
[
Text
]
->
Maybe
Offset
->
Maybe
Limit
->
Maybe
OrderBy
->
Cmd
err
[
FacetPaired
Int
UTCTime
HyperdataDocument
Int
[
Pair
Int
Text
]]
searchInCorpusWithContacts
cId
q
o
l
order
=
take
(
maybe
5
identity
l
)
<$>
drop
(
maybe
0
identity
o
)
searchInCorpusWithContacts
cId
q
o
l
order
=
take
(
maybe
5
identity
l
)
<$>
drop
(
maybe
0
identity
o
)
<$>
map
(
\
((
i
,
u
,
h
,
s
),
ps
)
->
FacetPaired
i
u
h
s
(
catMaybes
ps
))
<$>
map
(
\
((
i
,
u
,
h
,
s
),
ps
)
->
FacetPaired
i
u
h
s
(
catMaybes
ps
))
...
@@ -94,6 +95,7 @@ searchInCorpusWithContacts cId q o l order = take (maybe 5 identity l) <$> drop
...
@@ -94,6 +95,7 @@ searchInCorpusWithContacts cId q o l order = take (maybe 5 identity l) <$> drop
maybePair
(
Pair
Nothing
_
)
=
Nothing
maybePair
(
Pair
Nothing
_
)
=
Nothing
maybePair
(
Pair
(
Just
p_id
)
(
Just
p_label
))
=
Just
$
Pair
p_id
p_label
maybePair
(
Pair
(
Just
p_id
)
(
Just
p_label
))
=
Just
$
Pair
p_id
p_label
-- TODO-SECURITY check
searchInCorpusWithContacts'
::
CorpusId
->
[
Text
]
->
Maybe
Offset
->
Maybe
Limit
->
Maybe
OrderBy
->
Cmd
err
[(
FacetPaired
Int
UTCTime
HyperdataDocument
Int
(
Pair
(
Maybe
Int
)
(
Maybe
Text
)))]
searchInCorpusWithContacts'
::
CorpusId
->
[
Text
]
->
Maybe
Offset
->
Maybe
Limit
->
Maybe
OrderBy
->
Cmd
err
[(
FacetPaired
Int
UTCTime
HyperdataDocument
Int
(
Pair
(
Maybe
Int
)
(
Maybe
Text
)))]
searchInCorpusWithContacts'
cId
q
o
l
order
=
runOpaQuery
$
queryInCorpusWithContacts
cId
q'
o
l
order
searchInCorpusWithContacts'
cId
q
o
l
order
=
runOpaQuery
$
queryInCorpusWithContacts
cId
q'
o
l
order
where
where
...
...
src/Gargantext/Database/Types/Node.hs
View file @
09de17bd
...
@@ -41,9 +41,8 @@ import Data.ByteString.Lazy (ByteString)
...
@@ -41,9 +41,8 @@ import Data.ByteString.Lazy (ByteString)
import
Data.Either
import
Data.Either
import
Data.Eq
(
Eq
)
import
Data.Eq
(
Eq
)
import
Data.Monoid
(
mempty
)
import
Data.Monoid
(
mempty
)
import
Data.Text
(
Text
,
unpack
,
pack
)
import
Data.Text
(
Text
,
unpack
)
import
Data.Time
(
UTCTime
)
import
Data.Time
(
UTCTime
)
import
Data.Time.Segment
(
jour
,
timesAfter
,
Granularity
(
D
))
import
Data.Swagger
import
Data.Swagger
import
Text.Read
(
read
)
import
Text.Read
(
read
)
...
@@ -55,6 +54,8 @@ import Servant
...
@@ -55,6 +54,8 @@ import Servant
import
Test.QuickCheck.Arbitrary
import
Test.QuickCheck.Arbitrary
import
Test.QuickCheck
(
elements
)
import
Test.QuickCheck
(
elements
)
import
Test.QuickCheck.Instances.Time
()
import
Test.QuickCheck.Instances.Text
()
import
Gargantext.Prelude
import
Gargantext.Prelude
import
Gargantext.Core.Utils.Prefix
(
unPrefix
)
import
Gargantext.Core.Utils.Prefix
(
unPrefix
)
...
@@ -133,12 +134,6 @@ type MasterUserId = UserId
...
@@ -133,12 +134,6 @@ type MasterUserId = UserId
id2int
::
NodeId
->
Int
id2int
::
NodeId
->
Int
id2int
(
NodeId
n
)
=
n
id2int
(
NodeId
n
)
=
n
type
UTCTime'
=
UTCTime
instance
Arbitrary
UTCTime'
where
arbitrary
=
elements
$
timesAfter
100
D
(
jour
2000
01
01
)
------------------------------------------------------------------------
------------------------------------------------------------------------
data
Status
=
Status
{
status_failed
::
!
Int
data
Status
=
Status
{
status_failed
::
!
Int
,
status_succeeded
::
!
Int
,
status_succeeded
::
!
Int
...
@@ -276,15 +271,13 @@ instance ToSchema Event where
...
@@ -276,15 +271,13 @@ instance ToSchema Event where
declareNamedSchema
proxy
=
genericDeclareNamedSchema
defaultSchemaOptions
proxy
declareNamedSchema
proxy
=
genericDeclareNamedSchema
defaultSchemaOptions
proxy
------------------------------------------------------------------------
------------------------------------------------------------------------
instance
Arbitrary
Text
where
arbitrary
=
elements
$
map
(
\
c
->
pack
[
c
])
[
'a'
..
'z'
]
data
Resource
=
Resource
{
resource_path
::
!
(
Maybe
Text
)
data
Resource
=
Resource
{
resource_path
::
!
(
Maybe
Text
)
,
resource_scraper
::
!
(
Maybe
Text
)
,
resource_scraper
::
!
(
Maybe
Text
)
,
resource_query
::
!
(
Maybe
Text
)
,
resource_query
::
!
(
Maybe
Text
)
,
resource_events
::
!
([
Event
])
,
resource_events
::
!
([
Event
])
,
resource_status
::
!
Status
,
resource_status
::
!
Status
,
resource_date
::
!
UTCTime
'
,
resource_date
::
!
UTCTime
}
deriving
(
Show
,
Generic
)
}
deriving
(
Show
,
Generic
)
$
(
deriveJSON
(
unPrefix
"resource_"
)
''
R
esource
)
$
(
deriveJSON
(
unPrefix
"resource_"
)
''
R
esource
)
...
...
stack.yaml
View file @
09de17bd
...
@@ -6,7 +6,7 @@ packages:
...
@@ -6,7 +6,7 @@ packages:
docker
:
docker
:
enable
:
false
enable
:
false
repo
:
'
cgenie/stack-build:lts-12.26
'
repo
:
'
fpco/stack-build:lts-14.6-garg
'
allow-newer
:
true
allow-newer
:
true
extra-deps
:
extra-deps
:
...
...
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