ebook-manager/backend/src/Server/Auth.hs

60 lines
2.0 KiB
Haskell
Raw Normal View History

2018-08-04 23:53:40 +03:00
{-# Language DataKinds #-}
{-# Language TypeFamilies #-}
{-# Language OverloadedStrings #-}
{-# Language NoImplicitPrelude #-}
{-# Language TypeOperators #-}
{-# Language DuplicateRecordFields #-}
{-# Language TypeApplications #-}
2018-08-05 23:13:49 +03:00
{-# Language TemplateHaskell #-}
module Server.Auth
( SafeUser(..)
, authCheck
, AuthResult(..)
, requireLoggedIn)
where
2018-08-04 23:53:40 +03:00
import ClassyPrelude
2018-10-17 23:51:30 +03:00
import Control.Lens (view)
import Control.Monad.Logger
import Control.Monad.Catch (throwM, MonadThrow)
2018-08-04 23:53:40 +03:00
import Data.Aeson
2018-10-17 23:51:30 +03:00
import Data.Generics.Product
import Database
2018-08-04 23:53:40 +03:00
import Database.Schema
import Database.User
2018-08-05 23:13:49 +03:00
import Servant (err401)
2018-10-17 23:51:30 +03:00
import Servant.Auth.Server as SAS
import Types
2018-08-04 23:53:40 +03:00
-- generic-lens can convert similar types to this
-- I'm trying out servant-auth-server which uses a jwt style login. IIRC anyone
-- can open the jwt token and view what's inside, you just can't modify it.
--
-- Is it a problem that a human readable username and email are visible?
data SafeUser = SafeUser { email :: Email
, username :: Username
, role :: Role }
deriving (Show, Generic)
instance ToJSON SafeUser where
instance FromJSON SafeUser where
instance ToJWT SafeUser where
instance FromJWT SafeUser where
type instance BasicAuthCfg = BasicAuthData -> IO (AuthResult SafeUser)
instance FromBasicAuthData SafeUser where
fromBasicAuthData authData authCheckFunction = authCheckFunction authData
authCheck :: App -> BasicAuthData -> IO (AuthResult SafeUser)
authCheck app (BasicAuthData username password) = flip runReaderT app $
maybe SAS.Indefinite authenticated <$> runDB (validateUser username' password')
where
username' = Username $ decodeUtf8 username
password' = PlainPassword $ decodeUtf8 password
authenticated = SAS.Authenticated . view (super @SafeUser)
2018-08-05 23:13:49 +03:00
2018-10-17 23:51:30 +03:00
requireLoggedIn :: (MonadThrow m, MonadLogger m, Monad m) => (SafeUser -> m a) -> AuthResult SafeUser -> m a
2018-08-05 23:13:49 +03:00
requireLoggedIn f (Authenticated user) = f user
requireLoggedIn _ u = $logError (pack (show u)) >> throwM err401