    {-# LANGUAGE FlexibleContexts #-}

    module Network.OAuth2.Experiment.Flows.UserInfoRequest where

    import Control.Monad.IO.Class (MonadIO (..))
    import Control.Monad.Trans.Except (ExceptT (..))
    import Data.Aeson (FromJSON)
    import Data.ByteString.Lazy.Char8 qualified as BSL
    import Network.HTTP.Conduit
    import Network.OAuth.OAuth2
    import Network.OAuth2.Experiment.Types
    import URI.ByteString (URI)

    -------------------------------------------------------------------------------
    --                             User Info Request                             --
    -------------------------------------------------------------------------------

    class HasUserInfoRequest a

    -- | Standard approach of fetching /userinfo
    conduitUserInfoRequest ::
      (MonadIO m, HasUserInfoRequest a, FromJSON b) =>
      IdpApplication i a ->
      Manager ->
      AccessToken ->
      ExceptT BSL.ByteString m b
    conduitUserInfoRequest :: forall {k} (m :: * -> *) a b (i :: k).
    (MonadIO m, HasUserInfoRequest a, FromJSON b) =>
    IdpApplication i a
    -> Manager -> AccessToken -> ExceptT ByteString m b
    conduitUserInfoRequest = (Manager -> AccessToken -> URI -> ExceptT ByteString m b)
    -> IdpApplication i a
    -> Manager
    -> AccessToken
    -> ExceptT ByteString m b
    forall {k} (m :: * -> *) a b (i :: k).
    (MonadIO m, HasUserInfoRequest a, FromJSON b) =>
    (Manager -> AccessToken -> URI -> ExceptT ByteString m b)
    -> IdpApplication i a
    -> Manager
    -> AccessToken
    -> ExceptT ByteString m b
    conduitUserInfoRequestWithCustomMethod Manager -> AccessToken -> URI -> ExceptT ByteString m b
    forall (m :: * -> *) a.
    (MonadIO m, FromJSON a) =>
    Manager -> AccessToken -> URI -> ExceptT ByteString m a
    authGetJSON

    -- | Usually 'conduitUserInfoRequest' is good enough.
    -- But some IdP has different approach to fetch user information rather than GET.
    -- This method gives the flexiblity.
    conduitUserInfoRequestWithCustomMethod ::
      (MonadIO m, HasUserInfoRequest a, FromJSON b) =>
      ( Manager ->
        AccessToken ->
        URI ->
        ExceptT BSL.ByteString m b
      ) ->
      IdpApplication i a ->
      Manager ->
      AccessToken ->
      ExceptT BSL.ByteString m b
    conduitUserInfoRequestWithCustomMethod :: forall {k} (m :: * -> *) a b (i :: k).
    (MonadIO m, HasUserInfoRequest a, FromJSON b) =>
    (Manager -> AccessToken -> URI -> ExceptT ByteString m b)
    -> IdpApplication i a
    -> Manager
    -> AccessToken
    -> ExceptT ByteString m b
    conduitUserInfoRequestWithCustomMethod Manager -> AccessToken -> URI -> ExceptT ByteString m b
    fetchMethod IdpApplication {a
    Idp i
    idp :: Idp i
    application :: a
    application :: forall k (i :: k) a. IdpApplication i a -> a
    idp :: forall k (i :: k) a. IdpApplication i a -> Idp i
    ..} Manager
    mgr AccessToken
    at =
      Manager -> AccessToken -> URI -> ExceptT ByteString m b
    fetchMethod Manager
    mgr AccessToken
    at (Idp i -> URI
    forall k (i :: k). Idp i -> URI
    idpUserInfoEndpoint Idp i
    idp)