{-# LANGUAGE DataKinds #-} {-# LANGUAGE DoAndIfThenElse #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} module Web.Spock.SessionActions ( SessionId , sessionRegenerateId, getSessionId, readSession, writeSession , modifySession, modifySession', modifyReadSession, mapAllSessions, clearAllSessions ) where import Web.Spock.Action import Web.Spock.Internal.Monad () import Web.Spock.Internal.SessionManager import Web.Spock.Internal.Types -- | Regenerate the users sessionId. This preserves all stored data. Call this prior -- to logging in a user to prevent session fixation attacks. sessionRegenerateId :: SpockActionCtx ctx conn sess st () sessionRegenerateId = runInContext () $ getSessMgr >>= sm_regenerateSessionId -- | Get the current users sessionId. Note that this ID should only be -- shown to it's owner as otherwise sessions can be hijacked. getSessionId :: SpockActionCtx ctx conn sess st SessionId getSessionId = runInContext () $ getSessMgr >>= sm_getSessionId -- | Write to the current session. Note that all data is stored on the server. -- The user only reciedes a sessionId to be identified. writeSession :: forall sess ctx conn st. sess -> SpockActionCtx ctx conn sess st () writeSession d = do mgr <- getSessMgr runInContext () $ sm_writeSession mgr d -- | Modify the stored session modifySession :: (sess -> sess) -> SpockActionCtx ctx conn sess st () modifySession f = modifySession' $ \sess -> (f sess, ()) -- | Modify the stored session and return a value modifySession' :: (sess -> (sess, a)) -> SpockActionCtx ctx conn sess st a modifySession' f = do mgr <- getSessMgr runInContext () $ sm_modifySession mgr f -- | Modify the stored session and return the new value after modification modifyReadSession :: (sess -> sess) -> SpockActionCtx ctx conn sess st sess modifyReadSession f = modifySession' $ \sess -> let x = f sess in (x, x) -- | Read the stored session readSession :: SpockActionCtx ctx conn sess st sess readSession = runInContext () $ do mgr <- getSessMgr sm_readSession mgr -- | Globally delete all existing sessions. This is useful for example if you want -- to require all users to relogin clearAllSessions :: SpockActionCtx ctx conn sess st () clearAllSessions = do mgr <- getSessMgr runInContext () $ sm_clearAllSessions mgr -- | Apply a transformation to all sessions. Be careful with this, as this -- may cause many STM transaction retries. mapAllSessions :: (forall m. Monad m => sess -> m sess) -> SpockActionCtx ctx conn sess st () mapAllSessions f = do mgr <- getSessMgr runInContext () $ sm_mapSessions mgr f