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
bcd2edfd
Commit
bcd2edfd
authored
Jan 15, 2024
by
Alexandre Delanoë
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/600-dev-invite-and-errors-fixes' into dev
parents
555a1c96
ec271ca6
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
77 additions
and
61 deletions
+77
-61
Auth.hs
src/Gargantext/API/Admin/Auth.hs
+5
-3
Types.hs
src/Gargantext/API/Admin/Auth/Types.hs
+6
-30
Errors.hs
src/Gargantext/API/Errors.hs
+2
-0
Types.hs
src/Gargantext/API/Errors/Types.hs
+22
-0
Backend.hs
src/Gargantext/API/Errors/Types/Backend.hs
+1
-0
Share.hs
src/Gargantext/API/Node/Share.hs
+1
-1
Individu.hs
src/Gargantext/Core/Types/Individu.hs
+3
-1
Share.hs
src/Gargantext/Database/Action/Share.hs
+1
-1
Error.hs
src/Gargantext/Database/Query/Table/Node/Error.hs
+27
-5
Authentication.hs
test/Test/API/Authentication.hs
+7
-14
Errors.hs
test/Test/API/Errors.hs
+1
-1
Private.hs
test/Test/API/Private.hs
+1
-5
No files found.
src/Gargantext/API/Admin/Auth.hs
View file @
bcd2edfd
...
...
@@ -119,9 +119,11 @@ auth :: (HasSettings env, HasAuthenticationError err, DbCmd' env err m)
auth
(
AuthRequest
u
p
)
=
do
checkAuthRequest'
<-
checkAuthRequest
u
p
case
checkAuthRequest'
of
InvalidUser
->
pure
$
AuthResponse
Nothing
(
Just
$
AuthInvalid
"Invalid username or password"
)
InvalidPassword
->
pure
$
AuthResponse
Nothing
(
Just
$
AuthInvalid
"Invalid username or password"
)
Valid
to
trId
uId
->
pure
$
AuthResponse
(
Just
$
AuthValid
to
trId
uId
)
Nothing
InvalidUser
->
do
throwError
$
_AuthenticationError
#
InvalidUsernameOrPassword
InvalidPassword
->
do
throwError
$
_AuthenticationError
#
InvalidUsernameOrPassword
Valid
to
trId
uId
->
pure
$
AuthResponse
to
trId
uId
--type instance BasicAuthCfg = BasicAuthData -> IO (AuthResult AuthenticatedUser)
...
...
src/Gargantext/API/Admin/Auth/Types.hs
View file @
bcd2edfd
...
...
@@ -23,7 +23,7 @@ import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixSwagger)
import
Gargantext.Database.Admin.Types.Node
(
NodeId
(
..
),
ListId
,
DocId
,
UserId
(
..
))
import
Gargantext.Prelude
hiding
(
reverse
)
import
Servant.Auth.Server
import
Test.QuickCheck
(
elements
,
oneof
)
import
Test.QuickCheck
(
elements
)
import
Test.QuickCheck.Arbitrary
(
Arbitrary
,
arbitrary
)
import
qualified
Crypto.JWT
as
Jose
...
...
@@ -35,21 +35,12 @@ data AuthRequest = AuthRequest { _authReq_username :: Username
}
deriving
(
Generic
)
-- TODO: Use an HTTP error to wrap AuthInvalid
data
AuthResponse
=
AuthResponse
{
_authRes_valid
::
Maybe
AuthVali
d
,
_authRes_
inval
::
Maybe
AuthInvali
d
data
AuthResponse
=
AuthResponse
{
_authRes_token
::
Token
,
_authRes_tree_id
::
TreeI
d
,
_authRes_
user_id
::
UserI
d
}
deriving
(
Generic
,
Eq
,
Show
)
data
AuthInvalid
=
AuthInvalid
{
_authInv_message
::
Text
}
deriving
(
Generic
,
Eq
,
Show
)
data
AuthValid
=
AuthValid
{
_authVal_token
::
Token
,
_authVal_tree_id
::
TreeId
,
_authVal_user_id
::
UserId
}
deriving
(
Generic
,
Eq
,
Show
)
type
Token
=
Text
type
TreeId
=
NodeId
...
...
@@ -73,6 +64,7 @@ instance FromJWT AuthenticatedUser
data
AuthenticationError
=
LoginFailed
NodeId
UserId
Jose
.
Error
|
InvalidUsernameOrPassword
deriving
(
Show
,
Eq
)
-- TODO-SECURITY why is the CookieSettings necessary?
...
...
@@ -93,22 +85,7 @@ $(deriveJSON (unPrefix "_authRes_") ''AuthResponse)
instance
ToSchema
AuthResponse
where
declareNamedSchema
=
genericDeclareNamedSchema
(
unPrefixSwagger
"_authRes_"
)
instance
Arbitrary
AuthResponse
where
arbitrary
=
oneof
[
AuthResponse
Nothing
.
Just
<$>
arbitrary
,
flip
AuthResponse
Nothing
.
Just
<$>
arbitrary
]
$
(
deriveJSON
(
unPrefix
"_authInv_"
)
''
A
uthInvalid
)
instance
ToSchema
AuthInvalid
where
declareNamedSchema
=
genericDeclareNamedSchema
(
unPrefixSwagger
"_authInv_"
)
instance
Arbitrary
AuthInvalid
where
arbitrary
=
elements
[
AuthInvalid
m
|
m
<-
[
"Invalid user"
,
"Invalid password"
]
]
$
(
deriveJSON
(
unPrefix
"_authVal_"
)
''
A
uthValid
)
instance
ToSchema
AuthValid
where
declareNamedSchema
=
genericDeclareNamedSchema
(
unPrefixSwagger
"_authVal_"
)
instance
Arbitrary
AuthValid
where
arbitrary
=
elements
[
AuthValid
to'
tr
u
arbitrary
=
elements
[
AuthResponse
to'
tr
u
|
to'
<-
[
"token0"
,
"token1"
]
,
tr
<-
map
UnsafeMkNodeId
[
1
..
3
]
,
u
<-
map
UnsafeMkUserId
[
1
..
3
]
...
...
@@ -140,5 +117,4 @@ $(deriveJSON (unPrefix "_fpGet_") ''ForgotPasswordGet)
instance
ToSchema
ForgotPasswordGet
where
declareNamedSchema
=
genericDeclareNamedSchema
(
unPrefixSwagger
"_fpGet_"
)
makeLenses
''
A
uthValid
makeLenses
''
A
uthResponse
src/Gargantext/API/Errors.hs
View file @
bcd2edfd
...
...
@@ -93,6 +93,8 @@ authErrorToFrontendError = \case
-- externally).
LoginFailed
nid
uid
_
->
mkFrontendErr'
"Invalid username/password, or invalid session token."
$
FE_login_failed_error
nid
uid
InvalidUsernameOrPassword
->
mkFrontendErr'
"Invalid username or password."
$
FE_login_failed_invalid_username_or_password
nodeErrorToFrontendError
::
NodeError
->
FrontendError
nodeErrorToFrontendError
ne
=
case
ne
of
...
...
src/Gargantext/API/Errors/Types.hs
View file @
bcd2edfd
...
...
@@ -260,6 +260,11 @@ data instance ToFrontendErrorData 'EC_403__login_failed_error =
deriving
(
Show
,
Eq
,
Generic
)
data
instance
ToFrontendErrorData
'E
C
_403__login_failed_invalid_username_or_password
=
FE_login_failed_invalid_username_or_password
deriving
(
Show
,
Eq
,
Generic
)
--
-- Tree errors
--
...
...
@@ -472,6 +477,15 @@ instance FromJSON (ToFrontendErrorData 'EC_403__login_failed_error) where
lfe_node_id
<-
o
.:
"node_id"
pure
FE_login_failed_error
{
..
}
instance
ToJSON
(
ToFrontendErrorData
'E
C
_403__login_failed_invalid_username_or_password
)
where
toJSON
FE_login_failed_invalid_username_or_password
=
object
[]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_403__login_failed_invalid_username_or_password
)
where
parseJSON
=
withObject
"FE_login_failed_invalid_username_or_password"
$
\
_o
->
do
pure
FE_login_failed_invalid_username_or_password
--
-- internal server errors
--
...
...
@@ -638,6 +652,10 @@ genFrontendErr be = do
uid
<-
arbitrary
pure
$
mkFrontendErr'
txt
$
FE_login_failed_error
nid
uid
EC_403__login_failed_invalid_username_or_password
->
do
pure
$
mkFrontendErr'
txt
$
FE_login_failed_invalid_username_or_password
-- internal error
EC_500__internal_server_error
->
do
err
<-
arbitrary
...
...
@@ -753,6 +771,10 @@ instance FromJSON FrontendError where
(
fe_data
::
ToFrontendErrorData
'E
C
_403__login_failed_error
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
EC_403__login_failed_invalid_username_or_password
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_403__login_failed_invalid_username_or_password
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
-- internal server error
EC_500__internal_server_error
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_500__internal_server_error
)
<-
o
.:
"data"
...
...
src/Gargantext/API/Errors/Types/Backend.hs
View file @
bcd2edfd
...
...
@@ -36,6 +36,7 @@ data BackendErrorCode
|
EC_400__validation_error
-- authentication errors
|
EC_403__login_failed_error
|
EC_403__login_failed_invalid_username_or_password
-- tree errors
|
EC_404__tree_root_not_found
|
EC_404__tree_empty_root
...
...
src/Gargantext/API/Node/Share.hs
View file @
bcd2edfd
...
...
@@ -38,7 +38,7 @@ import Test.QuickCheck.Arbitrary
------------------------------------------------------------------------
data
ShareNodeParams
=
ShareTeamParams
{
username
::
Text
}
|
SharePublicParams
{
node_id
::
NodeId
}
|
SharePublicParams
{
node_id
::
NodeId
}
deriving
(
Generic
)
------------------------------------------------------------------------
-- TODO unPrefix "pn_" FromJSON, ToJSON, ToSchema, adapt frontend.
...
...
src/Gargantext/Core/Types/Individu.hs
View file @
bcd2edfd
...
...
@@ -29,7 +29,9 @@ import Prelude qualified
-- FIXME UserName used twice
data
User
=
UserDBId
UserId
|
UserName
Text
|
RootId
NodeId
deriving
(
Eq
)
deriving
(
Show
,
Eq
,
Generic
)
instance
ToJSON
User
renderUser
::
User
->
T
.
Text
renderUser
=
\
case
...
...
src/Gargantext/Database/Action/Share.hs
View file @
bcd2edfd
...
...
@@ -72,7 +72,7 @@ membersOfQuery (_NodeId -> teamId) = proc () -> do
(
nn
,
n
,
u
)
<-
nodeNode_node_User
-<
()
restrict
-<
(
nn
^.
nn_node2_id
)
.==
sqlInt4
teamId
returnA
-<
(
user_username
<$>
u
,
view
node_id
<$>
n
)
,
view
node_id
<$>
n
)
nodeNode_node_User
::
O
.
Select
(
NodeNodeRead
...
...
src/Gargantext/Database/Query/Table/Node/Error.hs
View file @
bcd2edfd
...
...
@@ -30,11 +30,9 @@ import Control.Lens (Prism', (#), (^?))
import
Data.Aeson
import
Data.Text
qualified
as
T
import
Gargantext.Core.Types.Individu
import
Prelude
hiding
(
null
,
id
,
map
,
sum
,
show
)
import
Gargantext.Database.Admin.Types.Node
(
ListId
,
NodeId
(
..
),
ContextId
,
UserId
,
ParentId
)
import
Gargantext.Prelude
hiding
(
sum
,
head
)
import
Prelude
hiding
(
null
,
id
,
map
,
sum
,
show
)
import
Prelude
qualified
data
NodeCreationError
...
...
@@ -42,6 +40,9 @@ data NodeCreationError
|
UserParentDoesNotExist
UserId
|
UserHasNegativeId
UserId
|
InsertNodeFailed
UserId
ParentId
deriving
(
Show
,
Eq
,
Generic
)
instance
ToJSON
NodeCreationError
renderNodeCreationFailed
::
NodeCreationError
->
T
.
Text
renderNodeCreationFailed
=
\
case
...
...
@@ -56,13 +57,16 @@ data NodeLookupError
|
UserDoesNotExist
UserId
|
UserNameDoesNotExist
Username
|
UserHasTooManyRoots
UserId
[
NodeId
]
deriving
(
Show
,
Eq
,
Generic
)
instance
ToJSON
NodeLookupError
renderNodeLookupFailed
::
NodeLookupError
->
T
.
Text
renderNodeLookupFailed
=
\
case
NodeDoesNotExist
nid
->
"node with id "
<>
T
.
pack
(
show
nid
)
<>
" couldn't be found."
NodeParentDoesNotExist
nid
->
"no parent for node with id "
<>
T
.
pack
(
show
nid
)
<>
"."
UserDoesNotExist
uid
->
"user with id "
<>
T
.
pack
(
show
uid
)
<>
" couldn't be found."
UserNameDoesNotExist
uname
->
"user with username '"
<>
uname
<>
" couldn't be found."
UserNameDoesNotExist
uname
->
"user with username '"
<>
uname
<>
"
'
couldn't be found."
UserHasTooManyRoots
uid
roots
->
"user with id "
<>
T
.
pack
(
show
uid
)
<>
" has too many roots: ["
<>
T
.
intercalate
","
(
map
(
T
.
pack
.
show
)
roots
)
------------------------------------------------------------------------
...
...
@@ -95,11 +99,29 @@ instance Prelude.Show NodeError
show
(
DoesNotExist
n
)
=
"Node does not exist ("
<>
show
n
<>
")"
instance
ToJSON
NodeError
where
toJSON
(
DoesNotExist
n
)
=
object
[
(
"error"
,
"Node does not exist"
)
,
(
"node"
,
toJSON
n
)
]
toJSON
(
NoListFound
listId
)
=
object
[
(
"error"
,
"No list found"
)
,
(
"listId"
,
toJSON
listId
)
]
toJSON
(
NodeError
e
)
=
object
[
(
"error"
,
"Node error"
)
,
(
"exception"
,
toJSON
$
T
.
pack
$
show
e
)
]
toJSON
(
NoUserFound
ur
)
=
object
[
(
"error"
,
"No user found"
)
,
(
"user"
,
toJSON
ur
)
]
toJSON
(
NodeCreationFailed
reason
)
=
object
[
(
"error"
,
"Node creation failed"
)
,
(
"reason"
,
toJSON
reason
)
]
toJSON
(
NodeLookupFailed
reason
)
=
object
[
(
"error"
,
"Node lookup failed"
)
,
(
"reason"
,
toJSON
reason
)
]
toJSON
(
NoContextFound
n
)
=
object
[
(
"error"
,
"No context found"
)
,
(
"node"
,
toJSON
n
)
]
toJSON
err
=
object
[
(
"error"
,
String
$
T
.
pack
$
show
err
)
]
object
[
(
"error"
,
toJSON
$
T
.
pack
$
show
err
)
]
class
HasNodeError
e
where
_NodeError
::
Prism'
e
NodeError
...
...
test/Test/API/Authentication.hs
View file @
bcd2edfd
...
...
@@ -59,24 +59,17 @@ tests = sequential $ aroundAll withTestDBAndPort $ do
let
authPayload
=
AuthRequest
"alice"
(
GargPassword
"alice"
)
result0
<-
runClientM
(
auth_api
authPayload
)
(
clientEnv
port
)
let
result
=
over
(
_Right
.
authRes_
valid
.
_Just
.
authVal_
token
)
(
const
cannedToken
)
result0
let
result
=
over
(
_Right
.
authRes_token
)
(
const
cannedToken
)
result0
let
expected
=
AuthResponse
{
_authRes_valid
=
Just
$
AuthValid
{
_authVal_token
=
cannedToken
,
_authVal_tree_id
=
fromMaybe
(
UnsafeMkNodeId
1
)
$
listToMaybe
$
result0
^..
_Right
.
authRes_valid
.
_Just
.
authVal_tree_id
,
_authVal_user_id
=
fromMaybe
(
UnsafeMkUserId
1
)
$
listToMaybe
$
result0
^..
_Right
.
authRes_valid
.
_Just
.
authVal_user_id
}
,
_authRes_inval
=
Nothing
}
_authRes_token
=
cannedToken
,
_authRes_tree_id
=
fromMaybe
(
UnsafeMkNodeId
1
)
$
listToMaybe
$
result0
^..
_Right
.
authRes_tree_id
,
_authRes_user_id
=
fromMaybe
(
UnsafeMkUserId
1
)
$
listToMaybe
$
result0
^..
_Right
.
authRes_user_id
}
result
`
shouldBe
`
(
Right
expected
)
it
"denies login for user 'alice' if password is invalid"
$
\
((
_testEnv
,
port
),
_
)
->
do
let
authPayload
=
AuthRequest
"alice"
(
GargPassword
"wrong"
)
result
<-
runClientM
(
auth_api
authPayload
)
(
clientEnv
port
)
let
expected
=
AuthResponse
{
_authRes_valid
=
Nothing
,
_authRes_inval
=
Just
$
AuthInvalid
"Invalid username or password"
}
result
`
shouldBe
`
(
Right
expected
)
putText
$
"result: "
<>
show
result
-- result `shouldBe` (Left $ InvalidUsernameOrPassword)
test/Test/API/Errors.hs
View file @
bcd2edfd
...
...
@@ -47,7 +47,7 @@ tests = sequential $ aroundAll withTestDBAndPort $ do
|
Status
{
..
}
<-
simpleStatus
->
liftIO
$
do
statusCode
`
shouldBe
`
404
simpleBody
`
shouldBe
`
[
r
|
{"
error":"Node does not exist (nodeId-99)
"}
|]
simpleBody
`
shouldBe
`
[
r
|
{"
node":99,"error":"Node does not exist
"}
|]
it
"returns the new error if header X-Garg-Error-Scheme: new is passed"
$
\
((
_testEnv
,
port
),
app
)
->
do
withApplication
app
$
do
...
...
test/Test/API/Private.hs
View file @
bcd2edfd
...
...
@@ -114,11 +114,7 @@ withValidLogin port ur pwd act = do
result
<-
liftIO
$
runClientM
(
auth_api
authPayload
)
clientEnv
case
result
of
Left
err
->
liftIO
$
throwIO
$
Prelude
.
userError
(
show
err
)
Right
res
|
Just
tkn
<-
_authRes_valid
res
->
act
(
_authVal_token
tkn
)
|
otherwise
->
Prelude
.
fail
$
"No token found in "
<>
show
res
Right
res
->
act
$
_authRes_token
res
tests
::
Spec
...
...
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