packages feed

snaplet-oauth-0.0.5: src/Snap/Snaplet/OAuth/Internal/Handlers.hs

{-# LANGUAGE OverloadedStrings #-}

module Snap.Snaplet.OAuth.Internal.Handlers
       ( loginWithOauthH
       , oauthCallbackH ) where

import           Control.Monad.CatchIO             (throw)
import qualified Data.ByteString                   as BS
import           Data.Maybe
import           Network.OAuth2.HTTP.HttpClient
import           Network.OAuth2.OAuth2
import           Prelude                           hiding ((.))
import           Snap

import           Snap.Snaplet.OAuth.Internal.Types
import           Snap.Snaplet.OAuth.Internal.Utils

----------------------------------------------------------------------

-- | Login via OAuth. Redirect user for authorization.
--
loginWithOauthH :: HasOAuth b
               => OAuthKey
               -> Maybe BS.ByteString
               -- ^ Maybe extra query parameters,e.g., 'scope' param for google oauth.
               -> Handler b v ()
loginWithOauthH key param = withOAuthH key fn
    where extraP (Just x) = "&" `BS.append` x
          extraP Nothing  = ""
          fn oauth = redirect $ authorizationUrl oauth `BS.append` extraP param

----------------------------------------------------------------------

-- | Callback for oauth provider.
--
oauthCallbackH :: HasOAuth b
                  => OAuthKey
                  -> Handler b v OAuth2
oauthCallbackH key = withOAuthH key fn
    where fn oauth = do
                     codeParam  <- decodedParam accessTokenKey
                     maybeToken <- liftIO $ requestAccessToken oauth codeParam
                     case maybeToken of
                         Just token -> liftIO $ modifyAccessToken token oauth
                         _ -> throw (OAuthException $ "Failed to request Access Token." ++ show key)
                              >> return oauth


modifyAccessToken :: AccessToken -> OAuth2 -> IO OAuth2
modifyAccessToken (AccessToken at _) origin = return $ origin { oauthAccessToken = Just at }


accessTokenKey :: BS.ByteString
accessTokenKey = "code"

----------------------------------------------------------------------

withOAuthH :: HasOAuth b
              => OAuthKey
              -> (OAuthValue -> Handler b v a)
              -> Handler b v a
withOAuthH key fn = do
    value <- lookupOAuth key
    case value of
      Nothing -> failure
      Just oauth -> fn oauth
    where failure = throw $ OAuthException $ "oauth data has not been init of: " ++ show key


-- checkLogin :: HasOAuth b => OAuth2 -> Handler b v ()
-- checkLogin oa = when (isNothing $ oauthAccessToken oa) $ redirect "weibo"