module Network.Wai.Session.ClientSession (clientsessionStore) where
import Control.Monad
import Data.ByteString (ByteString)
import Control.Monad.IO.Class (liftIO, MonadIO)
import Network.Wai.Session (Session, SessionStore)
import Data.IORef
import Control.Error (hush)
import Web.ClientSession (Key, encryptIO, decrypt)
import Data.Serialize (encode, decode, Serialize)
clientsessionStore :: (Serialize k, Serialize v, Eq k, MonadIO m) => Key -> SessionStore m k v
clientsessionStore cryptKey (Just encoded) =
case hush . decode =<< decrypt cryptKey encoded of
Just sessionData -> backend cryptKey sessionData
Nothing -> clientsessionStore cryptKey Nothing
clientsessionStore cryptKey Nothing = backend cryptKey []
backend :: (Serialize k, Serialize v, Eq k, MonadIO m) => Key -> [(k, v)] -> IO (Session m k v, IO ByteString)
backend cryptKey sessionData = do
ref <- newIORef sessionData
return ((
(\k -> lookup k `liftM` liftIO (readIORef ref)),
(\k v -> liftIO (modifyIORef ref (((k,v):) . filter ((/=k) . fst))))
), encryptIO cryptKey =<< encode `fmap` readIORef ref)