Commit eed33b26 authored by Alexandre Delanoë's avatar Alexandre Delanoë

[SECURITY] password check implemented (needs tests).

parent 6c6371aa
Pipeline #853 failed with stage
...@@ -34,9 +34,8 @@ module Gargantext.API.Admin.Auth ...@@ -34,9 +34,8 @@ module Gargantext.API.Admin.Auth
import Control.Lens (view) import Control.Lens (view)
import Data.Aeson.TH (deriveJSON) import Data.Aeson.TH (deriveJSON)
import Data.List (elem)
import Data.Swagger import Data.Swagger
import Data.Text (Text, reverse) import Data.Text (Text)
import Data.Text.Lazy (toStrict) import Data.Text.Lazy (toStrict)
import Data.Text.Lazy.Encoding (decodeUtf8) import Data.Text.Lazy.Encoding (decodeUtf8)
import GHC.Generics (Generic) import GHC.Generics (Generic)
...@@ -50,10 +49,12 @@ import Gargantext.Database.Schema.Node (NodePoly(_node_id)) ...@@ -50,10 +49,12 @@ import Gargantext.Database.Schema.Node (NodePoly(_node_id))
import Gargantext.Database.Admin.Types.Node (NodeId(..), UserId, ListId, DocId) import Gargantext.Database.Admin.Types.Node (NodeId(..), UserId, ListId, DocId)
import Gargantext.Database.Prelude (Cmd', CmdM, HasConnectionPool) import Gargantext.Database.Prelude (Cmd', CmdM, HasConnectionPool)
import Gargantext.Prelude hiding (reverse) import Gargantext.Prelude hiding (reverse)
import Gargantext.Database.Query.Table.User
import Servant import Servant
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 Gargantext.Core.Auth as Auth
--------------------------------------------------- ---------------------------------------------------
...@@ -96,17 +97,23 @@ makeTokenForUser uid = do ...@@ -96,17 +97,23 @@ makeTokenForUser uid = do
-- TODO not sure about the encoding... -- TODO not sure about the encoding...
checkAuthRequest :: (HasSettings env, HasConnectionPool env, HasJoseError err) checkAuthRequest :: (HasSettings env, HasConnectionPool env, HasJoseError err)
=> Username -> Password -> Cmd' env err CheckAuth => Username
checkAuthRequest u p -> Password
| not (u `elem` arbitraryUsername) = pure InvalidUser -> Cmd' env err CheckAuth
| u /= reverse p = pure InvalidPassword checkAuthRequest u p = do
| otherwise = do candidate <- head <$> getUsersWith u
muId <- head <$> getRoot (UserName u) case candidate of
case _node_id <$> muId of Nothing -> pure InvalidUser
Nothing -> pure InvalidUser Just (UserLight _id _u _email h) ->
Just uid -> do case Auth.checkPassword (Auth.mkPassword p) (Auth.PasswordHash h) of
token <- makeTokenForUser uid Auth.PasswordCheckFail -> pure InvalidPassword
pure $ Valid token uid Auth.PasswordCheckSuccess -> do
muId <- head <$> getRoot (UserName u)
case _node_id <$> muId of
Nothing -> pure InvalidUser
Just uid -> do
token <- makeTokenForUser uid
pure $ Valid token uid
auth :: (HasSettings env, HasConnectionPool env, HasJoseError err) auth :: (HasSettings env, HasConnectionPool env, HasJoseError err)
=> AuthRequest -> Cmd' env err AuthResponse => AuthRequest -> Cmd' env err AuthResponse
......
...@@ -33,6 +33,7 @@ module Gargantext.Database.Query.Table.User ...@@ -33,6 +33,7 @@ module Gargantext.Database.Query.Table.User
, userWithUsername , userWithUsername
, userWithId , userWithId
, userLightWithId , userLightWithId
, getUsersWith
, module Gargantext.Database.Schema.User , module Gargantext.Database.Schema.User
) )
where where
...@@ -76,15 +77,18 @@ gargUserWith u m (Auth.PasswordHash p) = UserDB (Nothing) (pgStrictText p) ...@@ -76,15 +77,18 @@ gargUserWith u m (Auth.PasswordHash p) = UserDB (Nothing) (pgStrictText p)
(pgBool True) Nothing (pgBool True) Nothing
------------------------------------------------------------------ ------------------------------------------------------------------
getUsersWith :: Username -> Cmd err [UserLight]
getUsersWith u = map toUserLight <$> runOpaQuery (selectUsersLightWith u)
selectUsersLightWith :: Username -> Query UserRead
selectUsersLightWith u = proc () -> do
row <- queryUserTable -< ()
restrict -< user_username row .== pgStrictText u
returnA -< row
queryUserTable :: Query UserRead queryUserTable :: Query UserRead
queryUserTable = queryTable userTable queryUserTable = queryTable userTable
selectUsersLightWith :: Query UserRead
selectUsersLightWith = proc () -> do
row@(UserDB i _p _ll _is _un _fn _ln _m _iff _ive _dj) <- queryUserTable -< ()
restrict -< i .== 1
--returnA -< User i p ll is un fn ln m iff ive dj
returnA -< row
------------------------------------------------------------------ ------------------------------------------------------------------
-- | Select User with some parameters -- | Select User with some parameters
-- Not optimized version -- Not optimized version
......
...@@ -13,6 +13,7 @@ Functions to deal with users, database side. ...@@ -13,6 +13,7 @@ Functions to deal with users, database side.
{-# OPTIONS_GHC -fno-warn-name-shadowing #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleInstances #-}
...@@ -22,6 +23,7 @@ Functions to deal with users, database side. ...@@ -22,6 +23,7 @@ Functions to deal with users, database side.
{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-} {-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
module Gargantext.Database.Schema.User where module Gargantext.Database.Schema.User where
...@@ -30,6 +32,11 @@ import Data.Text (Text) ...@@ -30,6 +32,11 @@ import Data.Text (Text)
import Data.Time (UTCTime) import Data.Time (UTCTime)
import GHC.Show(Show(..)) import GHC.Show(Show(..))
import Gargantext.Prelude import Gargantext.Prelude
import GHC.Generics (Generic)
import Database.PostgreSQL.Simple.FromField (FromField, fromField)
import Data.Aeson.TH (deriveJSON)
import Gargantext.Database.Prelude (fromField')
import Gargantext.Core.Utils.Prefix (unPrefix)
-- FIXME PLZ : the import below leads to an error, why ? -- FIXME PLZ : the import below leads to an error, why ?
-- import Gargantext.Database.Schema.Prelude hiding (makeLensesWith, abbreviatedFields, makeAdaptorAndInstance) -- import Gargantext.Database.Schema.Prelude hiding (makeLensesWith, abbreviatedFields, makeAdaptorAndInstance)
...@@ -37,18 +44,19 @@ import Gargantext.Prelude ...@@ -37,18 +44,19 @@ import Gargantext.Prelude
-- When FIXED : Imports to remove: -- When FIXED : Imports to remove:
import Control.Lens.TH (makeLensesWith, abbreviatedFields) import Control.Lens.TH (makeLensesWith, abbreviatedFields)
import Data.Profunctor.Product.TH (makeAdaptorAndInstance) import Data.Profunctor.Product.TH (makeAdaptorAndInstance)
import Opaleye import Opaleye hiding (FromField)
------------------------------------------------------------------------ ------------------------------------------------------------------------
data UserLight = UserLight { userLight_id :: !Int data UserLight = UserLight { userLight_id :: !Int
, userLight_username :: !Text , userLight_username :: !Text
, userLight_email :: !Text , userLight_email :: !Text
, userLigth_password :: !Text , userLight_password :: !Text
} deriving (Show) } deriving (Show, Generic)
toUserLight :: UserDB -> UserLight toUserLight :: UserDB -> UserLight
toUserLight (UserDB id p _ _ u _ _ e _ _ _ ) = UserLight id u e p toUserLight (UserDB id p _ _ u _ _ e _ _ _ ) = UserLight id u e p
data UserPoly id pass llogin suser data UserPoly id pass llogin suser
uname fname lname uname fname lname
mail staff active djoined = mail staff active djoined =
...@@ -65,7 +73,8 @@ data UserPoly id pass llogin suser ...@@ -65,7 +73,8 @@ data UserPoly id pass llogin suser
, user_isStaff :: !staff , user_isStaff :: !staff
, user_isActive :: !active , user_isActive :: !active
, user_dateJoined :: !djoined , user_dateJoined :: !djoined
} deriving (Show) } deriving (Show, Generic)
type UserWrite = UserPoly (Maybe (Column PGInt4)) (Column PGText) type UserWrite = UserPoly (Maybe (Column PGInt4)) (Column PGText)
(Maybe (Column PGTimestamptz)) (Column PGBool) (Maybe (Column PGTimestamptz)) (Column PGBool)
...@@ -108,3 +117,12 @@ userTable = Table "auth_user" ...@@ -108,3 +117,12 @@ userTable = Table "auth_user"
, user_dateJoined = optional "date_joined" , user_dateJoined = optional "date_joined"
} }
) )
instance FromField UserLight where
fromField = fromField'
instance FromField UserDB where
fromField = fromField'
$(deriveJSON (unPrefix "userLight_") ''UserLight)
$(deriveJSON (unPrefix "user_") ''UserPoly)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment