yesod-auth: add a runHttpRequest typeclass method
This commit is contained in:
parent
bb7f0afe34
commit
3f96cae289
@ -1,3 +1,7 @@
|
|||||||
|
## 1.4.7
|
||||||
|
|
||||||
|
* add a runHttpRequest function for handling HTTP errors
|
||||||
|
|
||||||
## 1.4.6
|
## 1.4.6
|
||||||
|
|
||||||
* Use nonce package to generate verification keys and CSRF tokens [#1011](https://github.com/yesodweb/yesod/pull/1011)
|
* Use nonce package to generate verification keys and CSRF tokens [#1011](https://github.com/yesodweb/yesod/pull/1011)
|
||||||
|
|||||||
@ -46,6 +46,7 @@ module Yesod.Auth
|
|||||||
, asHtml
|
, asHtml
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Control.Applicative ((<$>))
|
||||||
import Control.Monad (when)
|
import Control.Monad (when)
|
||||||
import Control.Monad.Trans.Maybe
|
import Control.Monad.Trans.Maybe
|
||||||
|
|
||||||
@ -57,11 +58,12 @@ import Data.Text (Text)
|
|||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.HashMap.Lazy as Map
|
import qualified Data.HashMap.Lazy as Map
|
||||||
import Data.Monoid (Endo)
|
import Data.Monoid (Endo)
|
||||||
import Network.HTTP.Conduit (Manager)
|
import Network.HTTP.Client (Manager, Request, withResponse, Response, BodyReader)
|
||||||
|
|
||||||
import qualified Network.Wai as W
|
import qualified Network.Wai as W
|
||||||
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Core.Types (HandlerT(..), unHandlerT)
|
||||||
import Yesod.Persist
|
import Yesod.Persist
|
||||||
import Yesod.Auth.Message (AuthMessage, defaultMessage)
|
import Yesod.Auth.Message (AuthMessage, defaultMessage)
|
||||||
import qualified Yesod.Auth.Message as Msg
|
import qualified Yesod.Auth.Message as Msg
|
||||||
@ -208,6 +210,16 @@ class (Yesod master, PathPiece (AuthId master), RenderMessage master FormMessage
|
|||||||
setMessage $ toHtml msg
|
setMessage $ toHtml msg
|
||||||
fmap asHtml $ redirect dest
|
fmap asHtml $ redirect dest
|
||||||
|
|
||||||
|
-- | runHttpRequest gives you a chance to handle an HttpException and retry
|
||||||
|
-- The default behavior is to simply execute the request which will throw an exception on failure
|
||||||
|
--
|
||||||
|
-- The HTTP 'Request' is given in case it is useful to change behavior based on inspecting the request.
|
||||||
|
-- This is an experimental API that is not broadly used throughout the yesod-auth code base
|
||||||
|
runHttpRequest :: Request -> (Response BodyReader -> HandlerT master IO a) -> HandlerT master IO a
|
||||||
|
runHttpRequest req inner = do
|
||||||
|
man <- authHttpManager <$> getYesod
|
||||||
|
HandlerT $ \t -> withResponse req man $ \res -> unHandlerT (inner res) t
|
||||||
|
|
||||||
{-# MINIMAL loginDest, logoutDest, (authenticate | getAuthId), authPlugins, authHttpManager #-}
|
{-# MINIMAL loginDest, logoutDest, (authenticate | getAuthId), authPlugins, authHttpManager #-}
|
||||||
|
|
||||||
{-# DEPRECATED getAuthId "Define 'authenticate' instead; 'getAuthId' will be removed in the next major version" #-}
|
{-# DEPRECATED getAuthId "Define 'authenticate' instead; 'getAuthId' will be removed in the next major version" #-}
|
||||||
|
|||||||
@ -50,11 +50,11 @@ module Yesod.Auth.GoogleEmail2
|
|||||||
import Yesod.Auth (Auth, AuthPlugin (AuthPlugin),
|
import Yesod.Auth (Auth, AuthPlugin (AuthPlugin),
|
||||||
AuthRoute, Creds (Creds),
|
AuthRoute, Creds (Creds),
|
||||||
Route (PluginR), YesodAuth,
|
Route (PluginR), YesodAuth,
|
||||||
authHttpManager, setCredsRedirect)
|
runHttpRequest, setCredsRedirect)
|
||||||
import qualified Yesod.Auth.Message as Msg
|
import qualified Yesod.Auth.Message as Msg
|
||||||
import Yesod.Core (HandlerSite, HandlerT, MonadHandler,
|
import Yesod.Core (HandlerSite, HandlerT, MonadHandler,
|
||||||
TypedContent, getRouteToParent,
|
TypedContent, getRouteToParent,
|
||||||
getUrlRender, getYesod, invalidArgs,
|
getUrlRender, invalidArgs,
|
||||||
lift, liftIO, lookupGetParam,
|
lift, liftIO, lookupGetParam,
|
||||||
lookupSession, notFound, redirect,
|
lookupSession, notFound, redirect,
|
||||||
setSession, whamlet, (.:))
|
setSession, whamlet, (.:))
|
||||||
@ -63,7 +63,8 @@ import Yesod.Core (HandlerSite, HandlerT, MonadHandler,
|
|||||||
import Blaze.ByteString.Builder (fromByteString, toByteString)
|
import Blaze.ByteString.Builder (fromByteString, toByteString)
|
||||||
import Control.Applicative ((<$>), (<*>))
|
import Control.Applicative ((<$>), (<*>))
|
||||||
import Control.Arrow (second)
|
import Control.Arrow (second)
|
||||||
import Control.Monad (liftM, unless, when)
|
import Control.Monad (unless, when)
|
||||||
|
import Control.Monad.IO.Class (MonadIO)
|
||||||
import qualified Crypto.Nonce as Nonce
|
import qualified Crypto.Nonce as Nonce
|
||||||
import Data.Aeson ((.:?))
|
import Data.Aeson ((.:?))
|
||||||
import qualified Data.Aeson as A
|
import qualified Data.Aeson as A
|
||||||
@ -71,7 +72,7 @@ import qualified Data.Aeson.Encode as A
|
|||||||
import Data.Aeson.Parser (json')
|
import Data.Aeson.Parser (json')
|
||||||
import Data.Aeson.Types (FromJSON (parseJSON), parseEither,
|
import Data.Aeson.Types (FromJSON (parseJSON), parseEither,
|
||||||
parseMaybe, withObject, withText)
|
parseMaybe, withObject, withText)
|
||||||
import Data.Conduit (($$+-))
|
import Data.Conduit (($$+-), ($$))
|
||||||
import Data.Conduit.Attoparsec (sinkParser)
|
import Data.Conduit.Attoparsec (sinkParser)
|
||||||
import qualified Data.HashMap.Strict as M
|
import qualified Data.HashMap.Strict as M
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
@ -83,7 +84,8 @@ import qualified Data.Text.Lazy as TL
|
|||||||
import qualified Data.Text.Lazy.Builder as TL
|
import qualified Data.Text.Lazy.Builder as TL
|
||||||
import Network.HTTP.Client (Manager, parseUrl, requestHeaders,
|
import Network.HTTP.Client (Manager, parseUrl, requestHeaders,
|
||||||
responseBody, urlEncodedBody)
|
responseBody, urlEncodedBody)
|
||||||
import Network.HTTP.Conduit (http)
|
import Network.HTTP.Client.Conduit (Request, bodyReaderSource)
|
||||||
|
import Network.HTTP.Conduit (http)
|
||||||
import Network.HTTP.Types (renderQueryText)
|
import Network.HTTP.Types (renderQueryText)
|
||||||
import System.IO.Unsafe (unsafePerformIO)
|
import System.IO.Unsafe (unsafePerformIO)
|
||||||
|
|
||||||
@ -202,9 +204,7 @@ authPlugin storeToken clientID clientSecret =
|
|||||||
req'
|
req'
|
||||||
{ requestHeaders = []
|
{ requestHeaders = []
|
||||||
}
|
}
|
||||||
manager <- liftM authHttpManager $ lift getYesod
|
value <- makeHttpRequest req
|
||||||
res <- http req manager
|
|
||||||
value <- responseBody res $$+- sinkParser json'
|
|
||||||
token@(Token accessToken' tokenType') <-
|
token@(Token accessToken' tokenType') <-
|
||||||
case parseEither parseJSON value of
|
case parseEither parseJSON value of
|
||||||
Left e -> error e
|
Left e -> error e
|
||||||
@ -215,7 +215,7 @@ authPlugin storeToken clientID clientSecret =
|
|||||||
-- User's access token is saved for further access to API
|
-- User's access token is saved for further access to API
|
||||||
when storeToken $ setSession accessTokenKey accessToken'
|
when storeToken $ setSession accessTokenKey accessToken'
|
||||||
|
|
||||||
personValue <- lift $ getPersonValue manager token
|
personValue <- makeHttpRequest =<< personValueRequest token
|
||||||
person <- case parseEither parseJSON personValue of
|
person <- case parseEither parseJSON personValue of
|
||||||
Left e -> error e
|
Left e -> error e
|
||||||
Right x -> return x
|
Right x -> return x
|
||||||
@ -229,25 +229,33 @@ authPlugin storeToken clientID clientSecret =
|
|||||||
|
|
||||||
dispatch _ _ = notFound
|
dispatch _ _ = notFound
|
||||||
|
|
||||||
|
makeHttpRequest
|
||||||
|
:: (YesodAuth site)
|
||||||
|
=> Request
|
||||||
|
-> HandlerT Auth (HandlerT site IO) A.Value
|
||||||
|
makeHttpRequest req = lift $
|
||||||
|
runHttpRequest req $ \res -> bodyReaderSource (responseBody res) $$ sinkParser json'
|
||||||
|
|
||||||
-- | Allows to fetch information about a user from Google's API.
|
-- | Allows to fetch information about a user from Google's API.
|
||||||
-- In case of parsing error returns 'Nothing'.
|
-- In case of parsing error returns 'Nothing'.
|
||||||
-- Will throw 'HttpException' in case of network problems or error response code.
|
-- Will throw 'HttpException' in case of network problems or error response code.
|
||||||
--
|
--
|
||||||
-- Since 1.4.3
|
-- Since 1.4.3
|
||||||
getPerson :: Manager -> Token -> HandlerT site IO (Maybe Person)
|
getPerson :: Manager -> Token -> HandlerT site IO (Maybe Person)
|
||||||
getPerson manager token = parseMaybe parseJSON <$> getPersonValue manager token
|
getPerson manager token = parseMaybe parseJSON <$> (do
|
||||||
|
req <- personValueRequest token
|
||||||
|
res <- http req manager
|
||||||
|
responseBody res $$+- sinkParser json'
|
||||||
|
)
|
||||||
|
|
||||||
getPersonValue :: Manager -> Token -> HandlerT site IO A.Value
|
personValueRequest :: MonadIO m => Token -> m Request
|
||||||
getPersonValue manager token = do
|
personValueRequest token = do
|
||||||
req2' <- liftIO $ parseUrl "https://www.googleapis.com/plus/v1/people/me"
|
req2' <- liftIO $ parseUrl "https://www.googleapis.com/plus/v1/people/me"
|
||||||
let req2 = req2'
|
return req2'
|
||||||
{ requestHeaders =
|
{ requestHeaders =
|
||||||
[ ("Authorization", encodeUtf8 $ "Bearer " `mappend` accessToken token)
|
[ ("Authorization", encodeUtf8 $ "Bearer " `mappend` accessToken token)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
res2 <- http req2 manager
|
|
||||||
val <- responseBody res2 $$+- sinkParser json'
|
|
||||||
return val
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- | An authentication token which was acquired from OAuth callback.
|
-- | An authentication token which was acquired from OAuth callback.
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod-auth
|
name: yesod-auth
|
||||||
version: 1.4.6.1
|
version: 1.4.7
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman, Patrick Brisbin
|
author: Michael Snoyman, Patrick Brisbin
|
||||||
@ -39,7 +39,8 @@ library
|
|||||||
, transformers >= 0.2.2
|
, transformers >= 0.2.2
|
||||||
, persistent >= 2.1 && < 2.3
|
, persistent >= 2.1 && < 2.3
|
||||||
, persistent-template >= 2.1 && < 2.2
|
, persistent-template >= 2.1 && < 2.2
|
||||||
, http-conduit >= 1.5
|
, http-client
|
||||||
|
, http-conduit >= 2.1
|
||||||
, aeson >= 0.7
|
, aeson >= 0.7
|
||||||
, lifted-base >= 0.1
|
, lifted-base >= 0.1
|
||||||
, blaze-html >= 0.5
|
, blaze-html >= 0.5
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user