module Data.SensitiveBytes.IO
( withUserPassword
) where
import Prelude hiding (length)
import Control.Exception.Safe (MonadMask)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import System.IO (stdin, stdout)
import Data.SensitiveBytes (WithSecureMemory)
import Data.SensitiveBytes.Internal (SensitiveBytes (..), resized, withSensitiveBytes)
import Data.SensitiveBytes.IO.Internal.Password (readPassword)
withUserPassword
:: forall m s r. (MonadIO m, MonadMask m, WithSecureMemory)
=> Int
-> Maybe Text
-> (SensitiveBytes s -> m r)
-> m r
withUserPassword :: Int -> Maybe Text -> (SensitiveBytes s -> m r) -> m r
withUserPassword Int
maxLength Maybe Text
mprompt SensitiveBytes s -> m r
act =
Int -> (SensitiveBytes s -> m r) -> m r
forall k (s :: k) (m :: * -> *) r.
(MonadIO m, MonadMask m, WithSecureMemory) =>
Int -> (SensitiveBytes s -> m r) -> m r
withSensitiveBytes Int
allocSize ((SensitiveBytes s -> m r) -> m r)
-> (SensitiveBytes s -> m r) -> m r
forall a b. (a -> b) -> a -> b
$ \sb :: SensitiveBytes s
sb@SensitiveBytes{ Ptr ()
bufPtr :: forall k (s :: k). SensitiveBytes s -> Ptr ()
bufPtr :: Ptr ()
bufPtr } -> do
Int
size <- IO Int -> m Int
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Int -> m Int) -> IO Int -> m Int
forall a b. (a -> b) -> a -> b
$ Handle -> Handle -> Text -> Ptr () -> Int -> IO Int
readPassword Handle
stdin Handle
stdout Text
prompt Ptr ()
bufPtr Int
allocSize
SensitiveBytes s -> m r
act (Int -> SensitiveBytes s -> SensitiveBytes s
forall k (s :: k). Int -> SensitiveBytes s -> SensitiveBytes s
resized Int
size SensitiveBytes s
sb)
where
defaultPrompt :: Text
defaultPrompt = Text
"Password: "
prompt :: Text
prompt = Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
defaultPrompt Maybe Text
mprompt
allocSize :: Int
allocSize = Int
maxLength