Make new session code optional, keep old API
This commit is contained in:
parent
f4674f9465
commit
bf293e6a1f
@ -35,6 +35,8 @@ module Yesod.Core
|
|||||||
, SessionBackend (..)
|
, SessionBackend (..)
|
||||||
, defaultClientSessionBackend
|
, defaultClientSessionBackend
|
||||||
, clientSessionBackend
|
, clientSessionBackend
|
||||||
|
, clientSessionBackend2
|
||||||
|
, clientSessionDateCacher
|
||||||
, loadClientSession
|
, loadClientSession
|
||||||
, Header(..)
|
, Header(..)
|
||||||
, BackendSession
|
, BackendSession
|
||||||
|
|||||||
@ -25,6 +25,9 @@ module Yesod.Internal.Core
|
|||||||
, defaultClientSessionBackend
|
, defaultClientSessionBackend
|
||||||
, clientSessionBackend
|
, clientSessionBackend
|
||||||
, loadClientSession
|
, loadClientSession
|
||||||
|
, clientSessionBackend2
|
||||||
|
, loadClientSession2
|
||||||
|
, clientSessionDateCacher
|
||||||
, BackendSession
|
, BackendSession
|
||||||
-- * jsLoader
|
-- * jsLoader
|
||||||
, ScriptLoadPosition (..)
|
, ScriptLoadPosition (..)
|
||||||
@ -44,6 +47,7 @@ import Yesod.Handler hiding (lift, getExpires)
|
|||||||
import Control.Monad.Logger (logErrorS)
|
import Control.Monad.Logger (logErrorS)
|
||||||
|
|
||||||
import Yesod.Routes.Class
|
import Yesod.Routes.Class
|
||||||
|
import Data.Time (UTCTime, addUTCTime, getCurrentTime)
|
||||||
|
|
||||||
import Data.Word (Word64)
|
import Data.Word (Word64)
|
||||||
import Control.Arrow ((***))
|
import Control.Arrow ((***))
|
||||||
@ -435,9 +439,10 @@ defaultYesodRunner logger handler' master sub murl toMasterRoute msb req
|
|||||||
[("Content-Type", "text/plain")]
|
[("Content-Type", "text/plain")]
|
||||||
"Request body too large to be processed."
|
"Request body too large to be processed."
|
||||||
| otherwise = do
|
| otherwise = do
|
||||||
let dontSaveSession _ = return []
|
let dontSaveSession _ _ = return []
|
||||||
(session, saveSession) <- liftIO $
|
now <- liftIO getCurrentTime -- FIXME remove in next major version bump
|
||||||
maybe (return ([], dontSaveSession)) (\sb -> sbLoadSession sb master req) msb
|
(session, saveSession) <- liftIO $ do
|
||||||
|
maybe (return ([], dontSaveSession)) (\sb -> sbLoadSession sb master req now) msb
|
||||||
rr <- liftIO $ parseWaiRequest req session (isJust msb) len
|
rr <- liftIO $ parseWaiRequest req session (isJust msb) len
|
||||||
let h = {-# SCC "h" #-} do
|
let h = {-# SCC "h" #-} do
|
||||||
case murl of
|
case murl of
|
||||||
@ -467,7 +472,7 @@ defaultYesodRunner logger handler' master sub murl toMasterRoute msb req
|
|||||||
newSess
|
newSess
|
||||||
(\n -> Map.insert tokenKey (TE.encodeUtf8 n) newSess)
|
(\n -> Map.insert tokenKey (TE.encodeUtf8 n) newSess)
|
||||||
(reqToken rr)
|
(reqToken rr)
|
||||||
sessionHeaders <- liftIO (saveSession nsToken)
|
sessionHeaders <- liftIO (saveSession nsToken now)
|
||||||
return $ ("Content-Type", ct) : map headerToPair sessionHeaders
|
return $ ("Content-Type", ct) : map headerToPair sessionHeaders
|
||||||
_ -> return []
|
_ -> return []
|
||||||
return $ yarToResponse yar extraHeaders
|
return $ yarToResponse yar extraHeaders
|
||||||
@ -758,25 +763,67 @@ defaultClientSessionBackend = do
|
|||||||
key <- CS.getKey CS.defaultKeyFile
|
key <- CS.getKey CS.defaultKeyFile
|
||||||
let timeout = fromIntegral (120 * 60 :: Int) -- 120 minutes
|
let timeout = fromIntegral (120 * 60 :: Int) -- 120 minutes
|
||||||
(getCachedDate, _closeDateCacher) <- clientSessionDateCacher timeout
|
(getCachedDate, _closeDateCacher) <- clientSessionDateCacher timeout
|
||||||
return $ clientSessionBackend key getCachedDate
|
return $ clientSessionBackend2 key getCachedDate
|
||||||
|
|
||||||
|
|
||||||
clientSessionBackend :: Yesod master
|
clientSessionBackend :: Yesod master
|
||||||
=> CS.Key -- ^ The encryption key
|
=> CS.Key -- ^ The encryption key
|
||||||
-> IO ClientSessionDateCache -- ^ See 'clientSessionDateCacher'
|
-> Int -- ^ Inactive session valitity in minutes
|
||||||
-> SessionBackend master
|
-> SessionBackend master
|
||||||
clientSessionBackend key getCachedDate =
|
clientSessionBackend key timeout = SessionBackend
|
||||||
SessionBackend {
|
{ sbLoadSession = loadClientSession key timeout "_SESSION"
|
||||||
sbLoadSession = loadClientSession key getCachedDate "_SESSION"
|
}
|
||||||
}
|
{-# DEPRECATED clientSessionBackend "Please use clientSessionBackend2, which is more efficient." #-}
|
||||||
|
|
||||||
loadClientSession :: Yesod master
|
loadClientSession :: Yesod master
|
||||||
|
=> CS.Key
|
||||||
|
-> Int -- ^ timeout
|
||||||
|
-> S8.ByteString -- ^ session name
|
||||||
|
-> master
|
||||||
|
-> W.Request
|
||||||
|
-> UTCTime
|
||||||
|
-> IO (BackendSession, SaveSession)
|
||||||
|
loadClientSession key timeout sessionName master req now = return (sess, save)
|
||||||
|
where
|
||||||
|
sess = fromMaybe [] $ do
|
||||||
|
raw <- lookup "Cookie" $ W.requestHeaders req
|
||||||
|
val <- lookup sessionName $ parseCookies raw
|
||||||
|
let host = "" -- fixme, properly lock sessions to client address
|
||||||
|
decodeClientSessionOld key now host val
|
||||||
|
save sess' now' = do
|
||||||
|
-- We should never cache the IV! Be careful!
|
||||||
|
iv <- liftIO CS.randomIV
|
||||||
|
return [AddCookie def
|
||||||
|
{ setCookieName = sessionName
|
||||||
|
, setCookieValue = sessionVal iv
|
||||||
|
, setCookiePath = Just (cookiePath master)
|
||||||
|
, setCookieExpires = Just expires
|
||||||
|
, setCookieDomain = cookieDomain master
|
||||||
|
, setCookieHttpOnly = True
|
||||||
|
}]
|
||||||
|
where
|
||||||
|
host = "" -- fixme, properly lock sessions to client address
|
||||||
|
expires = fromIntegral (timeout * 60) `addUTCTime` now'
|
||||||
|
sessionVal iv = encodeClientSessionOld key iv expires host sess'
|
||||||
|
{-# DEPRECATED loadClientSession "Please use loadClientSession2, which is more efficient." #-}
|
||||||
|
|
||||||
|
clientSessionBackend2 :: Yesod master
|
||||||
|
=> CS.Key -- ^ The encryption key
|
||||||
|
-> IO ClientSessionDateCache -- ^ See 'clientSessionDateCacher'
|
||||||
|
-> SessionBackend master
|
||||||
|
clientSessionBackend2 key getCachedDate =
|
||||||
|
SessionBackend {
|
||||||
|
sbLoadSession = \master req -> const $ loadClientSession2 key getCachedDate "_SESSION" master req
|
||||||
|
}
|
||||||
|
|
||||||
|
loadClientSession2 :: Yesod master
|
||||||
=> CS.Key
|
=> CS.Key
|
||||||
-> IO ClientSessionDateCache -- ^ See 'clientSessionDateCacher'
|
-> IO ClientSessionDateCache -- ^ See 'clientSessionDateCacher'
|
||||||
-> S8.ByteString -- ^ session name
|
-> S8.ByteString -- ^ session name
|
||||||
-> master
|
-> master
|
||||||
-> W.Request
|
-> W.Request
|
||||||
-> IO (BackendSession, SaveSession)
|
-> IO (BackendSession, SaveSession)
|
||||||
loadClientSession key getCachedDate sessionName master req = load
|
loadClientSession2 key getCachedDate sessionName master req = load
|
||||||
where
|
where
|
||||||
load = do
|
load = do
|
||||||
date <- getCachedDate
|
date <- getCachedDate
|
||||||
@ -786,7 +833,7 @@ loadClientSession key getCachedDate sessionName master req = load
|
|||||||
val <- lookup sessionName $ parseCookies raw
|
val <- lookup sessionName $ parseCookies raw
|
||||||
let host = "" -- fixme, properly lock sessions to client address
|
let host = "" -- fixme, properly lock sessions to client address
|
||||||
decodeClientSession key date host val
|
decodeClientSession key date host val
|
||||||
save date sess' = do
|
save date sess' _ = do
|
||||||
-- We should never cache the IV! Be careful!
|
-- We should never cache the IV! Be careful!
|
||||||
iv <- liftIO CS.randomIV
|
iv <- liftIO CS.randomIV
|
||||||
return [AddCookie def
|
return [AddCookie def
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
module Yesod.Internal.Session
|
module Yesod.Internal.Session
|
||||||
( encodeClientSession
|
( encodeClientSession
|
||||||
|
, encodeClientSessionOld
|
||||||
, decodeClientSession
|
, decodeClientSession
|
||||||
|
, decodeClientSessionOld
|
||||||
, clientSessionDateCacher
|
, clientSessionDateCacher
|
||||||
, ClientSessionDateCache(..)
|
, ClientSessionDateCache(..)
|
||||||
, BackendSession
|
, BackendSession
|
||||||
, SaveSession
|
, SaveSession
|
||||||
|
, SaveSessionOld
|
||||||
, SessionBackend(..)
|
, SessionBackend(..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
@ -27,11 +30,17 @@ import qualified Network.Wai as W
|
|||||||
type BackendSession = [(Text, S8.ByteString)]
|
type BackendSession = [(Text, S8.ByteString)]
|
||||||
|
|
||||||
type SaveSession = BackendSession -- ^ The session contents after running the handler
|
type SaveSession = BackendSession -- ^ The session contents after running the handler
|
||||||
|
-> UTCTime -- FIXME remove this in the next major version bump
|
||||||
|
-> IO [Header]
|
||||||
|
|
||||||
|
type SaveSessionOld = BackendSession -- ^ The session contents after running the handler
|
||||||
|
-> UTCTime
|
||||||
-> IO [Header]
|
-> IO [Header]
|
||||||
|
|
||||||
newtype SessionBackend master = SessionBackend
|
newtype SessionBackend master = SessionBackend
|
||||||
{ sbLoadSession :: master
|
{ sbLoadSession :: master
|
||||||
-> W.Request
|
-> W.Request
|
||||||
|
-> UTCTime -- FIXME remove this in the next major version bump
|
||||||
-> IO (BackendSession, SaveSession) -- ^ Return the session data and a function to save the session
|
-> IO (BackendSession, SaveSession) -- ^ Return the session data and a function to save the session
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,3 +137,25 @@ posixDayLength_int64 = 86400
|
|||||||
|
|
||||||
diffTimeScale :: DiffTime
|
diffTimeScale :: DiffTime
|
||||||
diffTimeScale = 1e12
|
diffTimeScale = 1e12
|
||||||
|
|
||||||
|
encodeClientSessionOld :: CS.Key
|
||||||
|
-> CS.IV
|
||||||
|
-> UTCTime -- ^ expire time
|
||||||
|
-> ByteString -- ^ remote host
|
||||||
|
-> [(Text, ByteString)] -- ^ session
|
||||||
|
-> ByteString -- ^ cookie value
|
||||||
|
encodeClientSessionOld key iv expire rhost session' =
|
||||||
|
CS.encrypt key iv $ encode $ SessionCookie (Left expire) rhost session'
|
||||||
|
|
||||||
|
decodeClientSessionOld :: CS.Key
|
||||||
|
-> UTCTime -- ^ current time
|
||||||
|
-> ByteString -- ^ remote host field
|
||||||
|
-> ByteString -- ^ cookie value
|
||||||
|
-> Maybe [(Text, ByteString)]
|
||||||
|
decodeClientSessionOld key now rhost encrypted = do
|
||||||
|
decrypted <- CS.decrypt key encrypted
|
||||||
|
SessionCookie (Left expire) rhost' session' <-
|
||||||
|
either (const Nothing) Just $ decode decrypted
|
||||||
|
guard $ expire > now
|
||||||
|
guard $ rhost' == rhost
|
||||||
|
return session'
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod-core
|
name: yesod-core
|
||||||
version: 1.1.6.1
|
version: 1.1.7
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman <michael@snoyman.com>
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user