{-# LANGUAGE CPP #-} ------------------------------------------------------------------------------ -- | This module contains functionality common among multiple back-ends. -- module Snap.Snaplet.Session.Common ( RNG , mkRNG , withRNG , randomToken , mkCSRFToken ) where ------------------------------------------------------------------------------ import Control.Concurrent import Control.Monad import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as B import qualified Data.Text.Encoding as T import Data.Text (Text) import Numeric import System.Random.MWC #if !MIN_VERSION_base(4,8,0) import Control.Applicative #endif ------------------------------------------------------------------------------ -- | High speed, mutable random number generator state newtype RNG = RNG (MVar GenIO) ------------------------------------------------------------------------------ -- | Perform given action, mutating the RNG state withRNG :: RNG -> (GenIO -> IO a) -> IO a withRNG (RNG rng) m = withMVar rng m ------------------------------------------------------------------------------ -- | Create a new RNG mkRNG :: IO RNG mkRNG = withSystemRandom (newMVar >=> return . RNG) ------------------------------------------------------------------------------ -- | Generates a random salt of given length randomToken :: Int -> RNG -> IO ByteString randomToken n rng = do is <- withRNG rng $ \gen -> sequence . take n . repeat $ mk gen return . B.pack . concat . map (flip showHex "") $ is where mk :: GenIO -> IO Int mk = uniformR (0,15) ------------------------------------------------------------------------------ -- | Generate a randomized CSRF token mkCSRFToken :: RNG -> IO Text mkCSRFToken rng = T.decodeUtf8 <$> randomToken 40 rng