module Web.Wheb.Plugins.Session
( SessionContainer (..)
, SessionApp (..)
, SessionBackend (..)
, setSessionValue
, getSessionValue
, getSessionValue'
, deleteSessionValue
, generateSessionKey
, getCurrentSessionKey
, clearSessionKey
) where
import Control.Monad (liftM)
import Control.Monad.IO.Class (MonadIO(..))
import Data.Maybe (fromMaybe)
import Data.Text.Lazy (pack, Text)
import Data.Text.Lazy.Encoding as T (decodeUtf8)
import Data.UUID (toLazyASCIIBytes)
import Data.UUID.V4 (nextRandom)
import Web.Wheb (getWithApp, WhebT)
import Web.Wheb.Cookie (getCookie, setCookie)
session_cookie_key :: Text
session_cookie_key = pack "-session-"
data SessionContainer = forall r. SessionBackend r => SessionContainer r
class SessionApp a where
getSessionContainer :: a -> SessionContainer
class SessionBackend c where
backendSessionPut :: (SessionApp a, MonadIO m) => Text -> Text -> Text -> c -> WhebT a b m ()
backendSessionGet :: (SessionApp a, MonadIO m) => Text -> Text -> c -> WhebT a b m (Maybe Text)
backendSessionDelete :: (SessionApp a, MonadIO m) => Text -> Text -> c -> WhebT a b m ()
backendSessionClear :: (SessionApp a, MonadIO m) => Text -> c -> WhebT a b m ()
runWithContainer :: (SessionApp a, MonadIO m) => (forall r. SessionBackend r => r -> WhebT a s m b) -> WhebT a s m b
runWithContainer f = do
SessionContainer sessStore <- getWithApp getSessionContainer
f sessStore
deleteSessionValue :: (SessionApp a, MonadIO m) => Text -> WhebT a b m ()
deleteSessionValue key= do
sessId <- getCurrentSessionKey
runWithContainer $ backendSessionDelete sessId key
setSessionValue :: (SessionApp a, MonadIO m) => Text -> Text -> WhebT a b m ()
setSessionValue key content = do
sessId <- getCurrentSessionKey
runWithContainer $ backendSessionPut sessId key content
getSessionValue :: (SessionApp a, MonadIO m) => Text -> WhebT a b m (Maybe Text)
getSessionValue key = do
sessId <- getCurrentSessionKey
runWithContainer $ backendSessionGet sessId key
getSessionValue' :: (SessionApp a, MonadIO m) => Text -> Text -> WhebT a b m Text
getSessionValue' def key = liftM (fromMaybe def) (getSessionValue key)
getSessionCookie :: (SessionApp a, MonadIO m) => WhebT a b m (Maybe Text)
getSessionCookie = getCookie session_cookie_key
generateSessionKey :: (SessionApp a, MonadIO m) => WhebT a b m Text
generateSessionKey = do
newKey <- liftM (T.decodeUtf8 . toLazyASCIIBytes) (liftIO nextRandom)
setCookie session_cookie_key newKey
return newKey
getCurrentSessionKey :: (SessionApp a, MonadIO m) => WhebT a b m Text
getCurrentSessionKey = do
curKey <- getSessionCookie
case curKey of
Just key -> return key
Nothing -> generateSessionKey
clearSessionKey :: (SessionApp a, MonadIO m) => WhebT a b m Text
clearSessionKey = do
curKey <- getSessionCookie
newKey <- generateSessionKey
case curKey of
Nothing -> return newKey
Just oldKey -> do
runWithContainer $ backendSessionClear oldKey
return newKey