Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
haskell-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
148
Issues
148
List
Board
Labels
Milestones
Merge Requests
7
Merge Requests
7
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
haskell-gargantext
Commits
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
Hide 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)
import
Gargantext.API.Admin.Orchestrator.Types
(
JobLog
(
..
),
AsyncJobs
)
import
Gargantext.API.Admin.Types
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.Types
(
mailSettings
)
import
Gargantext.Core.Types.Individu
(
User
(
..
),
Username
,
GargPassword
(
..
))
...
...
@@ -78,7 +78,7 @@ import Gargantext.API.Errors
-- | Main functions of authorization
makeTokenForUser
::
(
HasSettings
env
,
Has
Jose
Error
err
)
makeTokenForUser
::
(
HasSettings
env
,
Has
Authentication
Error
err
)
=>
NodeId
->
UserId
->
Cmd'
env
err
Token
...
...
@@ -86,10 +86,10 @@ makeTokenForUser nodeId userId = do
jwtS
<-
view
$
settings
.
jwtSettings
e
<-
liftBase
$
makeJWT
(
AuthenticatedUser
nodeId
userId
)
jwtS
Nothing
-- 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...
checkAuthRequest
::
(
HasSettings
env
,
Has
Jose
Error
err
,
DbCmd'
env
err
m
)
checkAuthRequest
::
(
HasSettings
env
,
Has
Authentication
Error
err
,
DbCmd'
env
err
m
)
=>
Username
->
GargPassword
->
m
CheckAuth
...
...
@@ -114,7 +114,7 @@ checkAuthRequest couldBeEmail (GargPassword p) = do
token
<-
makeTokenForUser
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
auth
(
AuthRequest
u
p
)
=
do
checkAuthRequest'
<-
checkAuthRequest
u
p
...
...
@@ -233,11 +233,12 @@ forgotPasswordPost (ForgotPasswordRequest email) = do
-- users' emails
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
forgotPasswordGet
Nothing
=
pure
$
ForgotPasswordGet
""
forgotPasswordGet
(
Just
uuid
)
=
do
let
mUuid
=
fromText
uuid
-- FIXME(adn) Sending out \"not found\" is leaking information here, we ought to fix it.
case
mUuid
of
Nothing
->
throwError
$
_ServerError
#
err404
{
errBody
=
"Not found"
}
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
forgotPasswordGetUser
(
UserLight
{
..
})
=
do
-- pick some random password
...
...
src/Gargantext/API/Admin/Auth/Types.hs
View file @
d0c5fec3
...
...
@@ -25,6 +25,7 @@ import Gargantext.Prelude hiding (reverse)
import
Servant.Auth.Server
import
Test.QuickCheck
(
elements
,
oneof
)
import
Test.QuickCheck.Arbitrary
(
Arbitrary
,
arbitrary
)
import
qualified
Crypto.JWT
as
Jose
---------------------------------------------------
...
...
@@ -70,6 +71,10 @@ instance ToSchema AuthenticatedUser where
instance
ToJWT
AuthenticatedUser
instance
FromJWT
AuthenticatedUser
data
AuthenticationError
=
LoginFailed
NodeId
UserId
Jose
.
Error
deriving
(
Show
,
Eq
)
-- TODO-SECURITY why is the CookieSettings necessary?
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
import
qualified
Data.Text
as
T
import
Gargantext.Database.Query.Tree
hiding
(
treeError
)
import
Data.Validity
(
prettyValidation
)
import
Gargantext.API.Admin.Auth.Types
$
(
deriveHttpStatusCode
''
B
ackendErrorCode
)
...
...
@@ -43,13 +44,22 @@ backendErrorToFrontendError = \case
$
FE_validation_error
$
case
prettyValidation
validationError
of
Nothing
->
"unknown_validation_error"
Just
v
->
T
.
pack
v
Internal
JoseError
_jose
Error
->
undefined
Internal
AuthenticationError
auth
Error
->
authErrorToFrontendError
authError
InternalServerError
_internalServerError
->
undefined
InternalJobError
_jobError
->
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
ne
=
case
ne
of
NoListFound
lid
...
...
src/Gargantext/API/Errors/Class.hs
View file @
d0c5fec3
...
...
@@ -2,7 +2,7 @@
module
Gargantext.API.Errors.Class
where
import
Control.Lens
import
Crypto.JOSE.Error
as
Jose
import
Gargantext.API.Admin.Auth.Types
(
AuthenticationError
)
class
Has
Jose
Error
e
where
_
JoseError
::
Prism'
e
Jose
.
Error
class
Has
Authentication
Error
e
where
_
AuthenticationError
::
Prism'
e
Authentication
Error
src/Gargantext/API/Errors/Types.hs
View file @
d0c5fec3
...
...
@@ -61,13 +61,13 @@ import Servant (ServerError)
import
Servant.Job.Core
import
Test.QuickCheck
import
Test.QuickCheck.Instances.Text
()
import
qualified
Crypto.JWT
as
Jose
import
qualified
Data.Text
as
T
import
qualified
Gargantext.Utils.Jobs.Monad
as
Jobs
import
qualified
Servant.Job.Types
as
SJ
import
Text.Read
(
readMaybe
)
import
qualified
Data.List.NonEmpty
as
NE
import
Data.Maybe
import
Gargantext.API.Admin.Auth.Types
(
AuthenticationError
)
-- | A 'WithStacktrace' carries an error alongside its
-- 'CallStack', to be able to print the correct source location
...
...
@@ -86,12 +86,12 @@ instance Exception e => Exception (WithStacktrace e) where
-- | An internal error which can be emitted from the backend and later
-- converted into a 'FrontendError', for later consumption.
data
BackendInternalError
=
InternalNodeError
!
NodeError
|
InternalTreeError
!
TreeError
|
InternalValidationError
!
Validation
|
Internal
JoseError
!
Jose
.
Error
|
InternalServerError
!
ServerError
|
InternalJobError
!
Jobs
.
JobError
=
InternalNodeError
!
NodeError
|
InternalTreeError
!
TreeError
|
InternalValidationError
!
Validation
|
Internal
AuthenticationError
!
Authentication
Error
|
InternalServerError
!
ServerError
|
InternalJobError
!
Jobs
.
JobError
deriving
(
Show
,
Typeable
)
makePrisms
''
B
ackendInternalError
...
...
@@ -122,8 +122,8 @@ instance HasTreeError BackendInternalError where
instance
HasServerError
BackendInternalError
where
_ServerError
=
_InternalServerError
instance
Has
Jose
Error
BackendInternalError
where
_
JoseError
=
_InternalJose
Error
instance
Has
Authentication
Error
BackendInternalError
where
_
AuthenticationError
=
_InternalAuthentication
Error
-- | 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.
...
...
@@ -199,6 +199,17 @@ data instance ToFrontendErrorData 'EC_400__validation_error =
FE_validation_error
{
validation_error
::
T
.
Text
}
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
--
...
...
@@ -267,6 +278,19 @@ instance FromJSON (ToFrontendErrorData 'EC_400__validation_error) where
parseJSON
(
String
txt
)
=
pure
$
FE_validation_error
txt
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
...
...
@@ -317,12 +341,19 @@ genFrontendErr be = do
EC_404__node_error_not_found
->
do
nodeId
<-
arbitrary
pure
$
mkFrontendErr'
txt
(
FE_node_error_not_found
nodeId
)
-- validation error
EC_400__validation_error
->
do
let
genValChain
=
oneof
[
Violated
<$>
arbitrary
,
Location
<$>
arbitrary
<*>
genValChain
]
chain
<-
listOf1
genValChain
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
EC_404__tree_error_root_not_found
->
pure
$
mkFrontendErr'
txt
$
FE_tree_error_root_not_found
...
...
@@ -374,6 +405,11 @@ instance FromJSON FrontendError where
(
fe_data
::
ToFrontendErrorData
'E
C
_400__validation_error
)
<-
o
.:
"data"
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
EC_404__tree_error_root_not_found
->
do
(
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
|
EC_500__node_error_not_implemented_yet
-- validation errors
|
EC_400__validation_error
-- authentication errors
|
EC_403__login_failed_error
-- tree errors
|
EC_404__tree_error_root_not_found
|
EC_404__tree_error_empty_root
...
...
src/Gargantext/API/Prelude.hs
View file @
d0c5fec3
...
...
@@ -21,8 +21,8 @@ module Gargantext.API.Prelude
where
import
Control.Lens
((
#
))
import
Crypto.JOSE.Error
as
Jose
import
Data.Aeson.Types
import
Gargantext.API.Admin.Auth.Types
(
AuthenticationError
)
import
Gargantext.API.Admin.Orchestrator.Types
import
Gargantext.API.Admin.Types
import
Gargantext.API.Errors.Class
...
...
@@ -40,8 +40,8 @@ import Servant
import
Servant.Job.Async
import
Servant.Job.Core
(
HasServerError
(
..
),
serverError
)
joseError
::
(
MonadError
e
m
,
HasJoseError
e
)
=>
Jose
.
Error
->
m
a
joseError
=
throwError
.
(
_Jose
Error
#
)
authenticationError
::
(
MonadError
e
m
,
HasAuthenticationError
e
)
=>
Authentication
Error
->
m
a
authenticationError
=
throwError
.
(
_Authentication
Error
#
)
type
HasJobEnv'
env
=
HasJobEnv
env
JobLog
JobLog
...
...
@@ -56,13 +56,13 @@ type EnvC env =
)
type
ErrC
err
=
(
HasNodeError
err
,
HasValidationError
err
,
HasTreeError
err
,
HasServerError
err
,
Has
JoseError
err
-- , ToJSON err -- TODO this is arguable
,
Exception
err
(
HasNodeError
err
,
HasValidationError
err
,
HasTreeError
err
,
HasServerError
err
,
Has
AuthenticationError
err
-- , ToJSON
err -- TODO this is arguable
,
Exception
err
)
type
GargServerC
env
err
m
=
...
...
src/Gargantext/Database/Admin/Types/Node.hs
View file @
d0c5fec3
...
...
@@ -74,6 +74,9 @@ instance DecodeScalar UserId where
instance
ResourceId
UserId
where
isPositive
=
(
>
0
)
.
_UserId
instance
Arbitrary
UserId
where
arbitrary
=
UnsafeMkUserId
.
getPositive
<$>
arbitrary
instance
DefaultFromField
SqlInt4
UserId
where
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