{-# LANGUAGE FlexibleContexts #-}

module Network.OAuth2.Experiment.Flows.RefreshTokenRequest where

import Control.Monad.IO.Class (MonadIO (..))
import Control.Monad.Trans.Except (ExceptT (..))
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Set (Set)
import Data.Text.Lazy (Text)
import Network.HTTP.Conduit
import Network.OAuth.OAuth2 hiding (RefreshToken)
import Network.OAuth.OAuth2 qualified as OAuth2
import Network.OAuth2.Experiment.Flows.TokenRequest
import Network.OAuth2.Experiment.Types
import Network.OAuth2.Experiment.Utils

-------------------------------------------------------------------------------
--                            RefreshToken Requset                           --
-------------------------------------------------------------------------------

data RefreshTokenRequest = RefreshTokenRequest
  { RefreshTokenRequest -> RefreshToken
rrRefreshToken :: OAuth2.RefreshToken
  , RefreshTokenRequest -> GrantTypeValue
rrGrantType :: GrantTypeValue
  , RefreshTokenRequest -> Set Scope
rrScope :: Set Scope
  }

instance ToQueryParam RefreshTokenRequest where
  toQueryParam :: RefreshTokenRequest -> Map Text Text
  toQueryParam :: RefreshTokenRequest -> Map Text Text
toQueryParam RefreshTokenRequest {Set Scope
RefreshToken
GrantTypeValue
rrScope :: Set Scope
rrGrantType :: GrantTypeValue
rrRefreshToken :: RefreshToken
rrScope :: RefreshTokenRequest -> Set Scope
rrGrantType :: RefreshTokenRequest -> GrantTypeValue
rrRefreshToken :: RefreshTokenRequest -> RefreshToken
..} =
    forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
f (Map k a) -> Map k a
Map.unions
      [ forall a. ToQueryParam a => a -> Map Text Text
toQueryParam GrantTypeValue
rrGrantType
      , forall a. ToQueryParam a => a -> Map Text Text
toQueryParam Set Scope
rrScope
      , forall a. ToQueryParam a => a -> Map Text Text
toQueryParam RefreshToken
rrRefreshToken
      ]

class (HasOAuth2Key a, HasTokenRequestClientAuthenticationMethod a) => HasRefreshTokenRequest a where
  -- | Make Refresh Token Request parameters
  -- | https://www.rfc-editor.org/rfc/rfc6749#section-6
  mkRefreshTokenRequestParam :: a -> OAuth2.RefreshToken -> RefreshTokenRequest

-- | Make Refresh Token Request
-- https://www.rfc-editor.org/rfc/rfc6749#section-6
conduitRefreshTokenRequest ::
  (MonadIO m, HasRefreshTokenRequest a) =>
  IdpApplication i a ->
  Manager ->
  OAuth2.RefreshToken ->
  ExceptT TokenResponseError m OAuth2Token
conduitRefreshTokenRequest :: forall {k} (m :: * -> *) a (i :: k).
(MonadIO m, HasRefreshTokenRequest a) =>
IdpApplication i a
-> Manager
-> RefreshToken
-> ExceptT TokenResponseError m OAuth2Token
conduitRefreshTokenRequest IdpApplication {a
Idp i
application :: forall k (i :: k) a. IdpApplication i a -> a
idp :: forall k (i :: k) a. IdpApplication i a -> Idp i
application :: a
idp :: Idp i
..} Manager
mgr RefreshToken
rt =
  let tokenReq :: RefreshTokenRequest
tokenReq = forall a.
HasRefreshTokenRequest a =>
a -> RefreshToken -> RefreshTokenRequest
mkRefreshTokenRequestParam a
application RefreshToken
rt
      body :: [(ByteString, ByteString)]
body = [Map Text Text] -> [(ByteString, ByteString)]
unionMapsToQueryParams [forall a. ToQueryParam a => a -> Map Text Text
toQueryParam RefreshTokenRequest
tokenReq]
   in forall (m :: * -> *) a.
(MonadIO m, FromJSON a) =>
Manager
-> OAuth2
-> URI
-> [(ByteString, ByteString)]
-> ExceptT TokenResponseError m a
doJSONPostRequest Manager
mgr (forall a. HasOAuth2Key a => a -> OAuth2
mkOAuth2Key a
application) (forall k (i :: k). Idp i -> URI
idpTokenEndpoint Idp i
idp) [(ByteString, ByteString)]
body