{-# LANGUAGE AllowAmbiguousTypes #-}

module IHP.LoginSupport.Middleware (initAuthentication) where

import IHP.Prelude
import IHP.LoginSupport.Helper.Controller
import IHP.Controller.Session
import IHP.QueryBuilder
import IHP.Fetch
import IHP.ControllerSupport
import IHP.ModelSupport
import IHP.Controller.Context

{-# INLINE initAuthentication #-}
initAuthentication :: forall user normalizedModel.
        ( ?context :: ControllerContext
        , ?modelContext :: ModelContext
        , normalizedModel ~ NormalizeModel user
        , Typeable normalizedModel
        , Table normalizedModel
        , FromRow normalizedModel
        , PrimaryKey (GetTableName normalizedModel) ~ UUID
        , GetTableName normalizedModel ~ GetTableName user
        , FilterPrimaryKey (GetTableName normalizedModel)
        , KnownSymbol (GetModelName user)
    ) => IO ()
initAuthentication :: forall user normalizedModel.
(?context::ControllerContext, ?modelContext::ModelContext,
 normalizedModel ~ NormalizeModel user, Typeable normalizedModel,
 Table normalizedModel, FromRow normalizedModel,
 PrimaryKey (GetTableName normalizedModel) ~ UUID,
 GetTableName normalizedModel ~ GetTableName user,
 FilterPrimaryKey (GetTableName normalizedModel),
 KnownSymbol (GetModelName user)) =>
IO ()
initAuthentication = do
    Maybe normalizedModel
user <- forall value.
(?context::ControllerContext, Serialize value) =>
ByteString -> IO (Maybe value)
getSession @(Id user) (forall user. KnownSymbol (GetModelName user) => ByteString
sessionKey @user)
            IO (Maybe (Id' (GetTableName user)))
-> (Maybe (Id' (GetTableName user)) -> IO (Maybe normalizedModel))
-> IO (Maybe normalizedModel)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe (Id' (GetTableName user)) -> IO (Maybe normalizedModel)
forall fetchable model.
(Fetchable fetchable model, Table model, FromRow model,
 ?modelContext::ModelContext) =>
fetchable -> IO (Maybe model)
fetchOneOrNothing
    Maybe normalizedModel -> IO ()
forall value.
(?context::ControllerContext, Typeable value) =>
value -> IO ()
putContext Maybe normalizedModel
user