ebook-manager/backend/src/Database/User.hs

62 lines
2.4 KiB
Haskell
Raw Normal View History

2018-08-03 23:36:38 +03:00
{-# Language LambdaCase #-}
{-# Language TypeApplications #-}
{-# Language DataKinds #-}
{-# Language TemplateHaskell #-}
module Database.User where
import ClassyPrelude
2018-08-05 21:39:38 +03:00
import Control.Lens (view, over, _Just)
2018-10-17 23:51:30 +03:00
import Control.Monad (mfilter)
import Control.Monad.Catch (MonadMask)
import Control.Monad.Logger
2018-08-03 23:36:38 +03:00
import Crypto.KDF.BCrypt
import Crypto.Random.Types (MonadRandom)
2018-10-17 23:51:30 +03:00
import Data.Generics.Product
import Database
import Database.Schema
import Database.Selda
2018-08-03 23:36:38 +03:00
data UserExistsError = UserExistsError
2018-10-17 23:51:30 +03:00
insertUser :: (MonadMask m, MonadLogger m, MonadIO m, MonadRandom m) => Username -> Email -> PlainPassword -> SeldaT m (Either UserExistsError (User NoPassword))
2018-08-03 23:36:38 +03:00
insertUser username email (PlainPassword password) =
getUser' username >>= maybe insert' (const (return $ Left UserExistsError))
where
insert' = adminExists >>= \e -> Right <$> if e then insertAs UserRole else insertAs AdminRole
insertAs role = do
lift $ $logInfo $ "Inserting new user as " <> pack (show role)
let bytePass = encodeUtf8 password
2018-08-04 21:30:08 +03:00
user <- User def email username role . HashedPassword <$> lift (hashPassword 12 bytePass)
2018-08-04 22:05:41 +03:00
insert_ (gen users) [toRel user] >> return (over (field @"password") (const NoPassword) user)
2018-08-03 23:36:38 +03:00
adminExists :: (MonadMask m, MonadLogger m, MonadIO m) => SeldaT m Bool
adminExists = do
r <- query q
lift $ $logInfo $ "Admin users: " <> (pack (show r))
return $ maybe False (> 0) . listToMaybe $ r
where
q = aggregate $ do
2018-08-04 21:30:08 +03:00
(_ :*: _ :*: _ :*: r :*: _) <- select (gen users)
2018-08-03 23:36:38 +03:00
restrict (r .== literal AdminRole)
return (count r)
2018-08-04 22:05:41 +03:00
getUser :: (MonadMask m, MonadIO m) => Username -> SeldaT m (Maybe (User NoPassword))
2018-08-03 23:36:38 +03:00
getUser name = over (_Just . field @"password") (const NoPassword) <$> getUser' name
2018-08-04 22:05:41 +03:00
validateUser :: (MonadMask m, MonadIO m) => Username -> PlainPassword -> SeldaT m (Maybe (User NoPassword))
2018-08-05 21:39:38 +03:00
validateUser name (PlainPassword password) =
asHidden . mfilter valid <$> getUser' name
where
valid = validatePassword password' . unHashed . view (field @"password")
password' = encodeUtf8 password
asHidden = over (_Just . field @"password") (const NoPassword)
2018-08-04 22:05:41 +03:00
getUser' :: (MonadMask m, MonadIO m) => Username -> SeldaT m (Maybe ( User HashedPassword ))
getUser' name = listToMaybe . fmap fromRel <$> query q
2018-08-03 23:36:38 +03:00
where
q = do
2018-08-04 22:05:41 +03:00
u@(_ :*: _ :*: username :*: _ ) <- select (gen users)
2018-08-03 23:36:38 +03:00
restrict (username .== literal name)
return u