packages feed

shomei-core-0.2.0.0: src/Shomei/Session/Store.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}

-- | The session-store port: persisting, looking up, and revoking sessions.
module Shomei.Session.Store
  ( SessionStore (..),
    createSession,
    findSessionById,
    revokeSession,
    revokeAllUserSessions,
    listSessionsForUser,
  )
where

import Effectful (Dispatch (..), DispatchOf, Eff, Effect, (:>))
import Effectful.Dispatch.Dynamic (send)
import Shomei.Id (SessionId, UserId)
import Shomei.Prelude
import Shomei.Session.Domain (NewSession, Session)

data SessionStore :: Effect where
  CreateSession :: NewSession -> SessionStore m Session
  FindSessionById :: SessionId -> SessionStore m (Maybe Session)
  RevokeSession :: SessionId -> UTCTime -> SessionStore m ()
  RevokeAllUserSessions :: UserId -> UTCTime -> SessionStore m ()
  -- | Every session ever created for a user, newest first, in every status. Unpaginated:
  -- sessions per user are bounded small in practice (roughly one per device), unlike users
  -- per deployment.
  ListSessionsForUser :: UserId -> SessionStore m [Session]

type instance DispatchOf SessionStore = Dynamic

createSession :: (SessionStore :> es) => NewSession -> Eff es Session
createSession = send . CreateSession

findSessionById :: (SessionStore :> es) => SessionId -> Eff es (Maybe Session)
findSessionById = send . FindSessionById

revokeSession :: (SessionStore :> es) => SessionId -> UTCTime -> Eff es ()
revokeSession sid t = send (RevokeSession sid t)

revokeAllUserSessions :: (SessionStore :> es) => UserId -> UTCTime -> Eff es ()
revokeAllUserSessions uid t = send (RevokeAllUserSessions uid t)

listSessionsForUser :: (SessionStore :> es) => UserId -> Eff es [Session]
listSessionsForUser = send . ListSessionsForUser