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
195
Issues
195
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
d0c5fec3
Commit
d0c5fec3
authored
Nov 06, 2023
by
Alfredo Di Napoli
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support InternalAuthenticationError
parent
988c0f97
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
88 additions
and
31 deletions
+88
-31
Auth.hs
src/Gargantext/API/Admin/Auth.hs
+8
-7
Types.hs
src/Gargantext/API/Admin/Auth/Types.hs
+5
-0
Errors.hs
src/Gargantext/API/Errors.hs
+12
-2
Class.hs
src/Gargantext/API/Errors/Class.hs
+3
-3
Types.hs
src/Gargantext/API/Errors/Types.hs
+45
-9
Backend.hs
src/Gargantext/API/Errors/Types/Backend.hs
+2
-0
Prelude.hs
src/Gargantext/API/Prelude.hs
+10
-10
Node.hs
src/Gargantext/Database/Admin/Types/Node.hs
+3
-0
No files found.
src/Gargantext/API/Admin/Auth.hs
View file @
d0c5fec3
...
@@ -53,7 +53,7 @@ import Gargantext.API.Admin.EnvTypes (GargJob(..), Env)
...
@@ -53,7 +53,7 @@ import Gargantext.API.Admin.EnvTypes (GargJob(..), Env)
import
Gargantext.API.Admin.Orchestrator.Types
(
JobLog
(
..
),
AsyncJobs
)
import
Gargantext.API.Admin.Orchestrator.Types
(
JobLog
(
..
),
AsyncJobs
)
import
Gargantext.API.Admin.Types
import
Gargantext.API.Admin.Types
import
Gargantext.API.Auth.PolicyCheck
import
Gargantext.API.Auth.PolicyCheck
import
Gargantext.API.Prelude
(
jose
Error
,
HasServerError
,
GargServerC
,
GargServer
,
_ServerError
,
GargM
)
import
Gargantext.API.Prelude
(
authentication
Error
,
HasServerError
,
GargServerC
,
GargServer
,
_ServerError
,
GargM
)
import
Gargantext.Core.Mail
(
MailModel
(
..
),
mail
)
import
Gargantext.Core.Mail
(
MailModel
(
..
),
mail
)
import
Gargantext.Core.Mail.Types
(
mailSettings
)
import
Gargantext.Core.Mail.Types
(
mailSettings
)
import
Gargantext.Core.Types.Individu
(
User
(
..
),
Username
,
GargPassword
(
..
))
import
Gargantext.Core.Types.Individu
(
User
(
..
),
Username
,
GargPassword
(
..
))
...
@@ -78,7 +78,7 @@ import Gargantext.API.Errors
...
@@ -78,7 +78,7 @@ import Gargantext.API.Errors
-- | Main functions of authorization
-- | Main functions of authorization
makeTokenForUser
::
(
HasSettings
env
,
Has
Jose
Error
err
)
makeTokenForUser
::
(
HasSettings
env
,
Has
Authentication
Error
err
)
=>
NodeId
=>
NodeId
->
UserId
->
UserId
->
Cmd'
env
err
Token
->
Cmd'
env
err
Token
...
@@ -86,10 +86,10 @@ makeTokenForUser nodeId userId = do
...
@@ -86,10 +86,10 @@ makeTokenForUser nodeId userId = do
jwtS
<-
view
$
settings
.
jwtSettings
jwtS
<-
view
$
settings
.
jwtSettings
e
<-
liftBase
$
makeJWT
(
AuthenticatedUser
nodeId
userId
)
jwtS
Nothing
e
<-
liftBase
$
makeJWT
(
AuthenticatedUser
nodeId
userId
)
jwtS
Nothing
-- TODO-SECURITY here we can implement token expiration ^^.
-- TODO-SECURITY here we can implement token expiration ^^.
either
joseError
(
pure
.
toStrict
.
LE
.
decodeUtf8
)
e
either
(
authenticationError
.
LoginFailed
nodeId
userId
)
(
pure
.
toStrict
.
LE
.
decodeUtf8
)
e
-- TODO not sure about the encoding...
-- TODO not sure about the encoding...
checkAuthRequest
::
(
HasSettings
env
,
Has
Jose
Error
err
,
DbCmd'
env
err
m
)
checkAuthRequest
::
(
HasSettings
env
,
Has
Authentication
Error
err
,
DbCmd'
env
err
m
)
=>
Username
=>
Username
->
GargPassword
->
GargPassword
->
m
CheckAuth
->
m
CheckAuth
...
@@ -114,7 +114,7 @@ checkAuthRequest couldBeEmail (GargPassword p) = do
...
@@ -114,7 +114,7 @@ checkAuthRequest couldBeEmail (GargPassword p) = do
token
<-
makeTokenForUser
nodeId
userLight_id
token
<-
makeTokenForUser
nodeId
userLight_id
pure
$
Valid
token
nodeId
userLight_id
pure
$
Valid
token
nodeId
userLight_id
auth
::
(
HasSettings
env
,
Has
Jose
Error
err
,
DbCmd'
env
err
m
)
auth
::
(
HasSettings
env
,
Has
Authentication
Error
err
,
DbCmd'
env
err
m
)
=>
AuthRequest
->
m
AuthResponse
=>
AuthRequest
->
m
AuthResponse
auth
(
AuthRequest
u
p
)
=
do
auth
(
AuthRequest
u
p
)
=
do
checkAuthRequest'
<-
checkAuthRequest
u
p
checkAuthRequest'
<-
checkAuthRequest
u
p
...
@@ -233,11 +233,12 @@ forgotPasswordPost (ForgotPasswordRequest email) = do
...
@@ -233,11 +233,12 @@ forgotPasswordPost (ForgotPasswordRequest email) = do
-- users' emails
-- users' emails
pure
$
ForgotPasswordResponse
"ok"
pure
$
ForgotPasswordResponse
"ok"
forgotPasswordGet
::
(
HasSettings
env
,
CmdCommon
env
,
Has
Jose
Error
err
,
HasServerError
err
)
forgotPasswordGet
::
(
HasSettings
env
,
CmdCommon
env
,
Has
Authentication
Error
err
,
HasServerError
err
)
=>
Maybe
Text
->
Cmd'
env
err
ForgotPasswordGet
=>
Maybe
Text
->
Cmd'
env
err
ForgotPasswordGet
forgotPasswordGet
Nothing
=
pure
$
ForgotPasswordGet
""
forgotPasswordGet
Nothing
=
pure
$
ForgotPasswordGet
""
forgotPasswordGet
(
Just
uuid
)
=
do
forgotPasswordGet
(
Just
uuid
)
=
do
let
mUuid
=
fromText
uuid
let
mUuid
=
fromText
uuid
-- FIXME(adn) Sending out \"not found\" is leaking information here, we ought to fix it.
case
mUuid
of
case
mUuid
of
Nothing
->
throwError
$
_ServerError
#
err404
{
errBody
=
"Not found"
}
Nothing
->
throwError
$
_ServerError
#
err404
{
errBody
=
"Not found"
}
Just
uuid'
->
do
Just
uuid'
->
do
...
@@ -249,7 +250,7 @@ forgotPasswordGet (Just uuid) = do
...
@@ -249,7 +250,7 @@ forgotPasswordGet (Just uuid) = do
---------------------
---------------------
forgotPasswordGetUser
::
(
HasSettings
env
,
CmdCommon
env
,
Has
Jose
Error
err
,
HasServerError
err
)
forgotPasswordGetUser
::
(
HasSettings
env
,
CmdCommon
env
,
Has
Authentication
Error
err
,
HasServerError
err
)
=>
UserLight
->
Cmd'
env
err
ForgotPasswordGet
=>
UserLight
->
Cmd'
env
err
ForgotPasswordGet
forgotPasswordGetUser
(
UserLight
{
..
})
=
do
forgotPasswordGetUser
(
UserLight
{
..
})
=
do
-- pick some random password
-- pick some random password
...
...
src/Gargantext/API/Admin/Auth/Types.hs
View file @
d0c5fec3
...
@@ -25,6 +25,7 @@ import Gargantext.Prelude hiding (reverse)
...
@@ -25,6 +25,7 @@ import Gargantext.Prelude hiding (reverse)
import
Servant.Auth.Server
import
Servant.Auth.Server
import
Test.QuickCheck
(
elements
,
oneof
)
import
Test.QuickCheck
(
elements
,
oneof
)
import
Test.QuickCheck.Arbitrary
(
Arbitrary
,
arbitrary
)
import
Test.QuickCheck.Arbitrary
(
Arbitrary
,
arbitrary
)
import
qualified
Crypto.JWT
as
Jose
---------------------------------------------------
---------------------------------------------------
...
@@ -70,6 +71,10 @@ instance ToSchema AuthenticatedUser where
...
@@ -70,6 +71,10 @@ instance ToSchema AuthenticatedUser where
instance
ToJWT
AuthenticatedUser
instance
ToJWT
AuthenticatedUser
instance
FromJWT
AuthenticatedUser
instance
FromJWT
AuthenticatedUser
data
AuthenticationError
=
LoginFailed
NodeId
UserId
Jose
.
Error
deriving
(
Show
,
Eq
)
-- TODO-SECURITY why is the CookieSettings necessary?
-- TODO-SECURITY why is the CookieSettings necessary?
type
AuthContext
=
'[
J
WTSettings
,
CookieSettings
]
-- , BasicAuthCfg
type
AuthContext
=
'[
J
WTSettings
,
CookieSettings
]
-- , BasicAuthCfg
...
...
src/Gargantext/API/Errors.hs
View file @
d0c5fec3
...
@@ -26,6 +26,7 @@ import qualified Network.HTTP.Types.Status as HTTP
...
@@ -26,6 +26,7 @@ import qualified Network.HTTP.Types.Status as HTTP
import
qualified
Data.Text
as
T
import
qualified
Data.Text
as
T
import
Gargantext.Database.Query.Tree
hiding
(
treeError
)
import
Gargantext.Database.Query.Tree
hiding
(
treeError
)
import
Data.Validity
(
prettyValidation
)
import
Data.Validity
(
prettyValidation
)
import
Gargantext.API.Admin.Auth.Types
$
(
deriveHttpStatusCode
''
B
ackendErrorCode
)
$
(
deriveHttpStatusCode
''
B
ackendErrorCode
)
...
@@ -43,13 +44,22 @@ backendErrorToFrontendError = \case
...
@@ -43,13 +44,22 @@ backendErrorToFrontendError = \case
$
FE_validation_error
$
case
prettyValidation
validationError
of
$
FE_validation_error
$
case
prettyValidation
validationError
of
Nothing
->
"unknown_validation_error"
Nothing
->
"unknown_validation_error"
Just
v
->
T
.
pack
v
Just
v
->
T
.
pack
v
Internal
JoseError
_jose
Error
Internal
AuthenticationError
auth
Error
->
undefined
->
authErrorToFrontendError
authError
InternalServerError
_internalServerError
InternalServerError
_internalServerError
->
undefined
->
undefined
InternalJobError
_jobError
InternalJobError
_jobError
->
undefined
->
undefined
authErrorToFrontendError
::
AuthenticationError
->
FrontendError
authErrorToFrontendError
=
\
case
-- For now, we ignore the Jose error, as they are too specific
-- (i.e. they should be logged internally to Sentry rather than shared
-- externall).
LoginFailed
nid
uid
_
->
mkFrontendErr'
"Invalid username/password, or invalid session token."
$
FE_login_failed_error
nid
uid
nodeErrorToFrontendError
::
NodeError
->
FrontendError
nodeErrorToFrontendError
::
NodeError
->
FrontendError
nodeErrorToFrontendError
ne
=
case
ne
of
nodeErrorToFrontendError
ne
=
case
ne
of
NoListFound
lid
NoListFound
lid
...
...
src/Gargantext/API/Errors/Class.hs
View file @
d0c5fec3
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
module
Gargantext.API.Errors.Class
where
module
Gargantext.API.Errors.Class
where
import
Control.Lens
import
Control.Lens
import
Crypto.JOSE.Error
as
Jose
import
Gargantext.API.Admin.Auth.Types
(
AuthenticationError
)
class
Has
Jose
Error
e
where
class
Has
Authentication
Error
e
where
_
JoseError
::
Prism'
e
Jose
.
Error
_
AuthenticationError
::
Prism'
e
Authentication
Error
src/Gargantext/API/Errors/Types.hs
View file @
d0c5fec3
...
@@ -61,13 +61,13 @@ import Servant (ServerError)
...
@@ -61,13 +61,13 @@ import Servant (ServerError)
import
Servant.Job.Core
import
Servant.Job.Core
import
Test.QuickCheck
import
Test.QuickCheck
import
Test.QuickCheck.Instances.Text
()
import
Test.QuickCheck.Instances.Text
()
import
qualified
Crypto.JWT
as
Jose
import
qualified
Data.Text
as
T
import
qualified
Data.Text
as
T
import
qualified
Gargantext.Utils.Jobs.Monad
as
Jobs
import
qualified
Gargantext.Utils.Jobs.Monad
as
Jobs
import
qualified
Servant.Job.Types
as
SJ
import
qualified
Servant.Job.Types
as
SJ
import
Text.Read
(
readMaybe
)
import
Text.Read
(
readMaybe
)
import
qualified
Data.List.NonEmpty
as
NE
import
qualified
Data.List.NonEmpty
as
NE
import
Data.Maybe
import
Data.Maybe
import
Gargantext.API.Admin.Auth.Types
(
AuthenticationError
)
-- | A 'WithStacktrace' carries an error alongside its
-- | A 'WithStacktrace' carries an error alongside its
-- 'CallStack', to be able to print the correct source location
-- 'CallStack', to be able to print the correct source location
...
@@ -89,7 +89,7 @@ data BackendInternalError
...
@@ -89,7 +89,7 @@ data BackendInternalError
=
InternalNodeError
!
NodeError
=
InternalNodeError
!
NodeError
|
InternalTreeError
!
TreeError
|
InternalTreeError
!
TreeError
|
InternalValidationError
!
Validation
|
InternalValidationError
!
Validation
|
Internal
JoseError
!
Jose
.
Error
|
Internal
AuthenticationError
!
Authentication
Error
|
InternalServerError
!
ServerError
|
InternalServerError
!
ServerError
|
InternalJobError
!
Jobs
.
JobError
|
InternalJobError
!
Jobs
.
JobError
deriving
(
Show
,
Typeable
)
deriving
(
Show
,
Typeable
)
...
@@ -122,8 +122,8 @@ instance HasTreeError BackendInternalError where
...
@@ -122,8 +122,8 @@ instance HasTreeError BackendInternalError where
instance
HasServerError
BackendInternalError
where
instance
HasServerError
BackendInternalError
where
_ServerError
=
_InternalServerError
_ServerError
=
_InternalServerError
instance
Has
Jose
Error
BackendInternalError
where
instance
Has
Authentication
Error
BackendInternalError
where
_
JoseError
=
_InternalJose
Error
_
AuthenticationError
=
_InternalAuthentication
Error
-- | An error that can be returned to the frontend. It carries a human-friendly
-- | An error that can be returned to the frontend. It carries a human-friendly
-- diagnostic, the 'type' of the error as well as some context-specific data.
-- diagnostic, the 'type' of the error as well as some context-specific data.
...
@@ -199,6 +199,17 @@ data instance ToFrontendErrorData 'EC_400__validation_error =
...
@@ -199,6 +199,17 @@ data instance ToFrontendErrorData 'EC_400__validation_error =
FE_validation_error
{
validation_error
::
T
.
Text
}
FE_validation_error
{
validation_error
::
T
.
Text
}
deriving
(
Show
,
Eq
,
Generic
)
deriving
(
Show
,
Eq
,
Generic
)
--
-- authentication errors
--
data
instance
ToFrontendErrorData
'E
C
_403__login_failed_error
=
FE_login_failed_error
{
lfe_node_id
::
NodeId
,
lfe_user_id
::
UserId
}
deriving
(
Show
,
Eq
,
Generic
)
--
--
-- Tree errors
-- Tree errors
--
--
...
@@ -267,6 +278,19 @@ instance FromJSON (ToFrontendErrorData 'EC_400__validation_error) where
...
@@ -267,6 +278,19 @@ instance FromJSON (ToFrontendErrorData 'EC_400__validation_error) where
parseJSON
(
String
txt
)
=
pure
$
FE_validation_error
txt
parseJSON
(
String
txt
)
=
pure
$
FE_validation_error
txt
parseJSON
ty
=
typeMismatch
"FE_validation_error"
ty
parseJSON
ty
=
typeMismatch
"FE_validation_error"
ty
--
-- authentication errors
--
instance
ToJSON
(
ToFrontendErrorData
'E
C
_403__login_failed_error
)
where
toJSON
FE_login_failed_error
{
..
}
=
object
[
"user_id"
.=
toJSON
lfe_user_id
,
"node_id"
.=
toJSON
lfe_node_id
]
instance
FromJSON
(
ToFrontendErrorData
'E
C
_403__login_failed_error
)
where
parseJSON
=
withObject
"FE_login_failed_error"
$
\
o
->
do
lfe_user_id
<-
o
.:
"user_id"
lfe_node_id
<-
o
.:
"node_id"
pure
FE_login_failed_error
{
..
}
--
--
-- tree errors
-- tree errors
...
@@ -317,12 +341,19 @@ genFrontendErr be = do
...
@@ -317,12 +341,19 @@ genFrontendErr be = do
EC_404__node_error_not_found
EC_404__node_error_not_found
->
do
nodeId
<-
arbitrary
->
do
nodeId
<-
arbitrary
pure
$
mkFrontendErr'
txt
(
FE_node_error_not_found
nodeId
)
pure
$
mkFrontendErr'
txt
(
FE_node_error_not_found
nodeId
)
-- validation error
-- validation error
EC_400__validation_error
EC_400__validation_error
->
do
let
genValChain
=
oneof
[
Violated
<$>
arbitrary
,
Location
<$>
arbitrary
<*>
genValChain
]
->
do
let
genValChain
=
oneof
[
Violated
<$>
arbitrary
,
Location
<$>
arbitrary
<*>
genValChain
]
chain
<-
listOf1
genValChain
chain
<-
listOf1
genValChain
pure
$
mkFrontendErr'
txt
$
FE_validation_error
(
T
.
pack
$
fromMaybe
"unknown_validation_error"
$
prettyValidation
$
Validation
chain
)
pure
$
mkFrontendErr'
txt
$
FE_validation_error
(
T
.
pack
$
fromMaybe
"unknown_validation_error"
$
prettyValidation
$
Validation
chain
)
-- authentication error
EC_403__login_failed_error
->
do
nid
<-
arbitrary
uid
<-
arbitrary
pure
$
mkFrontendErr'
txt
$
FE_login_failed_error
nid
uid
-- tree errors
-- tree errors
EC_404__tree_error_root_not_found
EC_404__tree_error_root_not_found
->
pure
$
mkFrontendErr'
txt
$
FE_tree_error_root_not_found
->
pure
$
mkFrontendErr'
txt
$
FE_tree_error_root_not_found
...
@@ -374,6 +405,11 @@ instance FromJSON FrontendError where
...
@@ -374,6 +405,11 @@ instance FromJSON FrontendError where
(
fe_data
::
ToFrontendErrorData
'E
C
_400__validation_error
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_400__validation_error
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
pure
FrontendError
{
..
}
-- authentication errors
EC_403__login_failed_error
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_403__login_failed_error
)
<-
o
.:
"data"
pure
FrontendError
{
..
}
-- tree errors
-- tree errors
EC_404__tree_error_root_not_found
->
do
EC_404__tree_error_root_not_found
->
do
(
fe_data
::
ToFrontendErrorData
'E
C
_404__tree_error_root_not_found
)
<-
o
.:
"data"
(
fe_data
::
ToFrontendErrorData
'E
C
_404__tree_error_root_not_found
)
<-
o
.:
"data"
...
...
src/Gargantext/API/Errors/Types/Backend.hs
View file @
d0c5fec3
...
@@ -23,6 +23,8 @@ data BackendErrorCode
...
@@ -23,6 +23,8 @@ data BackendErrorCode
|
EC_500__node_error_not_implemented_yet
|
EC_500__node_error_not_implemented_yet
-- validation errors
-- validation errors
|
EC_400__validation_error
|
EC_400__validation_error
-- authentication errors
|
EC_403__login_failed_error
-- tree errors
-- tree errors
|
EC_404__tree_error_root_not_found
|
EC_404__tree_error_root_not_found
|
EC_404__tree_error_empty_root
|
EC_404__tree_error_empty_root
...
...
src/Gargantext/API/Prelude.hs
View file @
d0c5fec3
...
@@ -21,8 +21,8 @@ module Gargantext.API.Prelude
...
@@ -21,8 +21,8 @@ module Gargantext.API.Prelude
where
where
import
Control.Lens
((
#
))
import
Control.Lens
((
#
))
import
Crypto.JOSE.Error
as
Jose
import
Data.Aeson.Types
import
Data.Aeson.Types
import
Gargantext.API.Admin.Auth.Types
(
AuthenticationError
)
import
Gargantext.API.Admin.Orchestrator.Types
import
Gargantext.API.Admin.Orchestrator.Types
import
Gargantext.API.Admin.Types
import
Gargantext.API.Admin.Types
import
Gargantext.API.Errors.Class
import
Gargantext.API.Errors.Class
...
@@ -40,8 +40,8 @@ import Servant
...
@@ -40,8 +40,8 @@ import Servant
import
Servant.Job.Async
import
Servant.Job.Async
import
Servant.Job.Core
(
HasServerError
(
..
),
serverError
)
import
Servant.Job.Core
(
HasServerError
(
..
),
serverError
)
joseError
::
(
MonadError
e
m
,
HasJoseError
e
)
=>
Jose
.
Error
->
m
a
authenticationError
::
(
MonadError
e
m
,
HasAuthenticationError
e
)
=>
Authentication
Error
->
m
a
joseError
=
throwError
.
(
_Jose
Error
#
)
authenticationError
=
throwError
.
(
_Authentication
Error
#
)
type
HasJobEnv'
env
=
HasJobEnv
env
JobLog
JobLog
type
HasJobEnv'
env
=
HasJobEnv
env
JobLog
JobLog
...
@@ -60,7 +60,7 @@ type ErrC err =
...
@@ -60,7 +60,7 @@ type ErrC err =
,
HasValidationError
err
,
HasValidationError
err
,
HasTreeError
err
,
HasTreeError
err
,
HasServerError
err
,
HasServerError
err
,
Has
JoseError
err
,
Has
AuthenticationError
err
-- , ToJSON err -- TODO this is arguable
-- , ToJSON err -- TODO this is arguable
,
Exception
err
,
Exception
err
)
)
...
...
src/Gargantext/Database/Admin/Types/Node.hs
View file @
d0c5fec3
...
@@ -74,6 +74,9 @@ instance DecodeScalar UserId where
...
@@ -74,6 +74,9 @@ instance DecodeScalar UserId where
instance
ResourceId
UserId
where
instance
ResourceId
UserId
where
isPositive
=
(
>
0
)
.
_UserId
isPositive
=
(
>
0
)
.
_UserId
instance
Arbitrary
UserId
where
arbitrary
=
UnsafeMkUserId
.
getPositive
<$>
arbitrary
instance
DefaultFromField
SqlInt4
UserId
instance
DefaultFromField
SqlInt4
UserId
where
where
defaultFromField
=
fromPGSFromField
defaultFromField
=
fromPGSFromField
...
...
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