Add fromProfileResponse

Handles the common case of fetching profile information from a single
JSON endpoint. Throws InvalidProfileResponse if JSON parsing fails.
This commit is contained in:
patrick brisbin 2015-04-03 17:43:56 -04:00
parent 6d547b157c
commit 2d3d1d2a8e
No known key found for this signature in database
GPG Key ID: DB04E2CE780A17DE
4 changed files with 36 additions and 37 deletions

View File

@ -12,6 +12,7 @@
module Yesod.Auth.OAuth2 module Yesod.Auth.OAuth2
( authOAuth2 ( authOAuth2
, oauth2Url , oauth2Url
, fromProfileURL
, YesodOAuth2Exception(..) , YesodOAuth2Exception(..)
, module Network.OAuth.OAuth2 , module Network.OAuth.OAuth2
) where ) where
@ -54,6 +55,9 @@ authOAuth2 :: YesodAuth m
-- retrieve additional information about the user, to be -- retrieve additional information about the user, to be
-- set in the session as @'Creds'@. Usually this means a -- set in the session as @'Creds'@. Usually this means a
-- second authorized request to @api/me.json@. -- second authorized request to @api/me.json@.
--
-- See @'fromProfileURL'@ for an example.
--
-> AuthPlugin m -> AuthPlugin m
authOAuth2 name oauth getCreds = AuthPlugin name dispatch login authOAuth2 name oauth getCreds = AuthPlugin name dispatch login
@ -104,5 +108,21 @@ authOAuth2 name oauth getCreds = AuthPlugin name dispatch login
<a href=@{tm $ oauth2Url name}>Login via #{name} <a href=@{tm $ oauth2Url name}>Login via #{name}
|] |]
-- | Handle the common case of fetching Profile information a JSON endpoint
--
-- Throws @'InvalidProfileResponse'@ if JSON parsing fails
--
fromProfileURL :: FromJSON a
=> Text -- ^ Plugin name
-> URI -- ^ Profile URI
-> (a -> Creds m) -- ^ Conversion to Creds
-> Manager -> AccessToken -> IO (Creds m)
fromProfileURL name url toCreds manager token = do
result <- authGetJSON manager token url
case result of
Right profile -> return $ toCreds profile
Left err -> throwIO $ InvalidProfileResponse name err
bsToText :: ByteString -> Text bsToText :: ByteString -> Text
bsToText = decodeUtf8With lenientDecode bsToText = decodeUtf8With lenientDecode

View File

@ -15,7 +15,7 @@ module Yesod.Auth.OAuth2.Github
) where ) where
#if __GLASGOW_HASKELL__ < 710 #if __GLASGOW_HASKELL__ < 710
import Control.Applicative ((<$>), (<*>), pure) import Control.Applicative ((<$>), (<*>))
#endif #endif
import Control.Exception.Lifted import Control.Exception.Lifted

View File

@ -13,14 +13,12 @@ module Yesod.Auth.OAuth2.Spotify
import Control.Applicative ((<$>), (<*>), pure) import Control.Applicative ((<$>), (<*>), pure)
#endif #endif
import Control.Exception.Lifted
import Control.Monad (mzero) import Control.Monad (mzero)
import Data.Aeson import Data.Aeson
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Data.Maybe import Data.Maybe
import Data.Text (Text) import Data.Text (Text)
import Data.Text.Encoding (encodeUtf8) import Data.Text.Encoding (encodeUtf8)
import Network.HTTP.Conduit(Manager)
import Yesod.Auth import Yesod.Auth
import Yesod.Auth.OAuth2 import Yesod.Auth.OAuth2
@ -78,14 +76,7 @@ oauth2Spotify clientId clientSecret scope = authOAuth2 "spotify"
, oauthAccessTokenEndpoint = "https://accounts.spotify.com/api/token" , oauthAccessTokenEndpoint = "https://accounts.spotify.com/api/token"
, oauthCallback = Nothing , oauthCallback = Nothing
} }
fetchSpotifyProfile $ fromProfileURL "spotify" "https://api.spotify.com/v1/me" toCreds
fetchSpotifyProfile :: Manager -> AccessToken -> IO (Creds m)
fetchSpotifyProfile manager token = do
result <- authGetJSON manager token "https://api.spotify.com/v1/me"
case result of
Right user -> return $ toCreds user
Left err -> throwIO $ InvalidProfileResponse "spotify" err
toCreds :: SpotifyUser -> Creds m toCreds :: SpotifyUser -> Creds m
toCreds user = Creds toCreds user = Creds

View File

@ -14,17 +14,15 @@ module Yesod.Auth.OAuth2.Upcase
) where ) where
#if __GLASGOW_HASKELL__ < 710 #if __GLASGOW_HASKELL__ < 710
import Control.Applicative ((<$>), (<*>), pure) import Control.Applicative ((<$>), (<*>))
#endif #endif
import Control.Exception.Lifted
import Control.Monad (mzero) import Control.Monad (mzero)
import Data.Aeson import Data.Aeson
import Data.Text (Text) import Data.Text (Text)
import Data.Text.Encoding (encodeUtf8) import Data.Text.Encoding (encodeUtf8)
import Yesod.Auth import Yesod.Auth
import Yesod.Auth.OAuth2 import Yesod.Auth.OAuth2
import Network.HTTP.Conduit(Manager)
import qualified Data.Text as T import qualified Data.Text as T
data UpcaseUser = UpcaseUser data UpcaseUser = UpcaseUser
@ -52,9 +50,9 @@ instance FromJSON UpcaseResponse where
parseJSON _ = mzero parseJSON _ = mzero
oauth2Upcase :: YesodAuth m oauth2Upcase :: YesodAuth m
=> Text -- ^ Client ID => Text -- ^ Client ID
-> Text -- ^ Client Secret -> Text -- ^ Client Secret
-> AuthPlugin m -> AuthPlugin m
oauth2Upcase clientId clientSecret = authOAuth2 "upcase" oauth2Upcase clientId clientSecret = authOAuth2 "upcase"
OAuth2 OAuth2
{ oauthClientId = encodeUtf8 clientId { oauthClientId = encodeUtf8 clientId
@ -63,23 +61,13 @@ oauth2Upcase clientId clientSecret = authOAuth2 "upcase"
, oauthAccessTokenEndpoint = "http://upcase.com/oauth/token" , oauthAccessTokenEndpoint = "http://upcase.com/oauth/token"
, oauthCallback = Nothing , oauthCallback = Nothing
} }
fetchUpcaseProfile $ fromProfileURL "upcase" "http://upcase.com/api/v1/me.json"
$ \user -> Creds
fetchUpcaseProfile :: Manager -> AccessToken -> IO (Creds m) { credsPlugin = "upcase"
fetchUpcaseProfile manager token = do , credsIdent = T.pack $ show $ upcaseUserId user
result <- authGetJSON manager token "http://upcase.com/api/v1/me.json" , credsExtra =
[ ("first_name", upcaseUserFirstName user)
case result of , ("last_name", upcaseUserLastName user)
Right (UpcaseResponse user) -> return $ toCreds user , ("email", upcaseUserEmail user)
Left err -> throwIO $ InvalidProfileResponse "upcase" err ]
}
toCreds :: UpcaseUser -> Creds m
toCreds user = Creds
{ credsPlugin = "upcase"
, credsIdent = T.pack $ show $ upcaseUserId user
, credsExtra =
[ ("first_name", upcaseUserFirstName user)
, ("last_name" , upcaseUserLastName user)
, ("email" , upcaseUserEmail user)
]
}