packages feed

yesod-session-persist-0.0.0.0: internal/Yesod/Session/Cookie/SetCookie.hs

module Yesod.Session.Cookie.SetCookie
  ( makeSetCookieHeaders
  ) where

import Internal.Prelude

import Data.Text.Encoding (encodeUtf8)
import Session.Key
import Session.Timing.Math
import Session.Timing.Options
import Session.Timing.Time
import Session.Timing.Timeout
import Session.TransportSecurity qualified as TransportSecurity
import Time
import Web.Cookie qualified as C
import Yesod.Core.Types (Header (AddCookie))
import Yesod.Session.Options

makeSetCookieHeaders
  :: Options tx m -> Maybe (SessionKey, Time UTCTime) -> [Header]
makeSetCookieHeaders options =
  (: []) <$> maybe (deleteCookie options) (createCookie options)

cookieNameBS :: Options tx m -> ByteString
cookieNameBS options = encodeUtf8 options.cookieName

-- | Create a cookie for the given session
createCookie :: Options tx m -> (SessionKey, Time UTCTime) -> Header
createCookie options (key, time) =
  AddCookie
    C.def
      { C.setCookieName = cookieNameBS options
      , C.setCookieValue = sessionKeyToCookieValue key
      , C.setCookiePath = Just "/"
      , C.setCookieExpires = Just $ cookieExpires options.timing.timeout time
      , C.setCookieDomain = Nothing
      , C.setCookieHttpOnly = True
      , C.setCookieSecure = TransportSecurity.cookieSecure options.transportSecurity
      }

-- | Remove the session cookie from the client
deleteCookie :: Options tx m -> Header
deleteCookie options =
  AddCookie
    C.def
      { C.setCookieName = cookieNameBS options
      , C.setCookieValue = ""
      , C.setCookiePath = Just "/"
      , C.setCookieExpires = Just $ UTCTime systemEpochDay 1
      , C.setCookieMaxAge = Just 0
      , C.setCookieDomain = Nothing
      , C.setCookieHttpOnly = True
      , C.setCookieSecure = TransportSecurity.cookieSecure options.transportSecurity
      }

-- | Calculate the date that should be used for the cookie's "expires" field
cookieExpires :: Timeout NominalDiffTime -> Time UTCTime -> UTCTime
cookieExpires timeout time =
  fromMaybe (addUTCTime (years 10) time.accessed)
    $ nextExpires timeout time