packages feed

yesod-session-persist-0.0.0.2: internal/Yesod/Session/Persist/Storage.hs

module Yesod.Session.Persist.Storage
  ( persistentStorage
  , SessionPersistence (..)

    -- * Persistent reëxports
  , PersistEntity
  , PersistEntityBackend
  , SafeToInsert
  , ConnectionPool
  ) where

import Internal.Prelude

import Database.Persist (Key, PersistRecordBackend)
import Database.Persist qualified as Persist
import Database.Persist.Class
  ( PersistEntity
  , PersistEntityBackend
  , SafeToInsert
  )
import Database.Persist.Sql (ConnectionPool)
import Session.Key
import Yesod.Session.SessionType
import Yesod.Session.Storage.Exceptions
import Yesod.Session.Storage.Operation

-- | Mapping between 'Yesod.Session.Persist.Session' and
--   a Persistent entity of your choice
data SessionPersistence backend record m = ( PersistRecordBackend record backend
                                           , Persist.PersistStoreWrite backend
                                           , SafeToInsert record
                                           ) =>
  SessionPersistence
  { databaseKey :: SessionKey -> Key record
  , toDatabase :: Session -> record
  , fromDatabase :: record -> Session
  , runDB :: forall a. ReaderT backend IO a -> m a
  }

persistentStorage
  :: forall record backend result m
   . (PersistRecordBackend record backend, Persist.PersistStoreWrite backend)
  => SessionPersistence backend record m
  -> StorageOperation result
  -> ReaderT backend IO result
persistentStorage sp@SessionPersistence {} = \case
  GetSession sessionKey ->
    fmap sp.fromDatabase <$> Persist.get (sp.databaseKey sessionKey)
  DeleteSession sessionKey ->
    Persist.delete $ sp.databaseKey sessionKey
  InsertSession session ->
    persistentStorage sp (GetSession session.key) >>= \case
      Nothing -> void $ Persist.insert $ sp.toDatabase session
      Just _ -> throwWithCallStack SessionAlreadyExists
  ReplaceSession session ->
    let key = sp.databaseKey session.key
    in  Persist.get key >>= \case
          Nothing -> throwWithCallStack SessionDoesNotExist
          Just _old -> void $ Persist.replace key $ sp.toDatabase session