{-# LANGUAGE ConstraintKinds, ConstrainedClassMethods, AllowAmbiguousTypes #-}

module IHP.LoginSupport.Types
( HasNewSessionUrl (newSessionUrl)
, CurrentUserRecord
, CurrentAdminRecord
, currentUserVaultKey
, currentAdminVaultKey
, currentUserIdVaultKey
, currentAdminIdVaultKey
, lookupAuthVault
) where

import IHP.Prelude
import qualified Data.Vault.Lazy as Vault
import qualified Network.Wai as Wai
import System.IO.Unsafe (unsafePerformIO)

class HasNewSessionUrl user where
    newSessionUrl :: Proxy user -> Text

type family CurrentUserRecord
type family CurrentAdminRecord

-- | Vault key for the current user record.
-- Used by 'authMiddleware' to store the authenticated user in the WAI request vault.
currentUserVaultKey :: Vault.Key (Maybe CurrentUserRecord)
currentUserVaultKey :: Key (Maybe CurrentUserRecord)
currentUserVaultKey = IO (Key (Maybe CurrentUserRecord)) -> Key (Maybe CurrentUserRecord)
forall a. IO a -> a
unsafePerformIO IO (Key (Maybe CurrentUserRecord))
forall a. IO (Key a)
Vault.newKey
{-# NOINLINE currentUserVaultKey #-}

-- | Vault key for the current admin record.
-- Used by 'adminAuthMiddleware' to store the authenticated admin in the WAI request vault.
currentAdminVaultKey :: Vault.Key (Maybe CurrentAdminRecord)
currentAdminVaultKey :: Key (Maybe CurrentAdminRecord)
currentAdminVaultKey = IO (Key (Maybe CurrentAdminRecord))
-> Key (Maybe CurrentAdminRecord)
forall a. IO a -> a
unsafePerformIO IO (Key (Maybe CurrentAdminRecord))
forall a. IO (Key a)
Vault.newKey
{-# NOINLINE currentAdminVaultKey #-}

-- | Vault key for the current user's UUID.
-- Used by 'userIdMiddleware' to store just the user ID (no DB fetch).
currentUserIdVaultKey :: Vault.Key (Maybe UUID)
currentUserIdVaultKey :: Key (Maybe UUID)
currentUserIdVaultKey = IO (Key (Maybe UUID)) -> Key (Maybe UUID)
forall a. IO a -> a
unsafePerformIO IO (Key (Maybe UUID))
forall a. IO (Key a)
Vault.newKey
{-# NOINLINE currentUserIdVaultKey #-}

-- | Vault key for the current admin's UUID.
-- Used by 'adminIdMiddleware' to store just the admin ID (no DB fetch).
currentAdminIdVaultKey :: Vault.Key (Maybe UUID)
currentAdminIdVaultKey :: Key (Maybe UUID)
currentAdminIdVaultKey = IO (Key (Maybe UUID)) -> Key (Maybe UUID)
forall a. IO a -> a
unsafePerformIO IO (Key (Maybe UUID))
forall a. IO (Key a)
Vault.newKey
{-# NOINLINE currentAdminIdVaultKey #-}

-- | Pure lookup of an auth record from the WAI request vault.
lookupAuthVault :: Vault.Key (Maybe user) -> Wai.Request -> Maybe user
lookupAuthVault :: forall user. Key (Maybe user) -> Request -> Maybe user
lookupAuthVault Key (Maybe user)
key Request
req = Maybe (Maybe user) -> Maybe user
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Key (Maybe user) -> Vault -> Maybe (Maybe user)
forall a. Key a -> Vault -> Maybe a
Vault.lookup Key (Maybe user)
key (Request -> Vault
Wai.vault Request
req))
{-# INLINE lookupAuthVault #-}