authIdentifier (automatic login redirection)

This commit is contained in:
Michael Snoyman 2009-12-31 02:41:20 +02:00
parent 13d3444881
commit 4087573088
3 changed files with 50 additions and 28 deletions

View File

@ -16,9 +16,9 @@
module Yesod.Helpers.Auth module Yesod.Helpers.Auth
( authHandler ( authHandler
, YesodAuth (..) , YesodAuth (..)
, authIdentifier
) where ) where
import qualified Hack
import Web.Encodings import Web.Encodings
import qualified Web.Authenticate.Rpxnow as Rpxnow import qualified Web.Authenticate.Rpxnow as Rpxnow
import qualified Web.Authenticate.OpenId as OpenId import qualified Web.Authenticate.OpenId as OpenId
@ -31,10 +31,27 @@ import Control.Monad.Attempt
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
class Yesod a => YesodAuth a where class YesodApproot a => YesodAuth a where
-- | The following breaks DRY, but I cannot think of a better solution
-- right now.
--
-- The root relative to the application root. Should not begin with a slash
-- and should end with one.
authRoot :: a -> String
authRoot _ = "auth/"
defaultLoginPath :: a -> String
defaultLoginPath a = authRoot a ++ "openid/"
rpxnowApiKey :: a -> Maybe String rpxnowApiKey :: a -> Maybe String
rpxnowApiKey _ = Nothing rpxnowApiKey _ = Nothing
getFullAuthRoot :: YesodAuth y => Handler y String
getFullAuthRoot = do
y <- getYesod
let (Approot ar) = approot y
return $ ar ++ authRoot y
data AuthResource = data AuthResource =
Check Check
| Logout | Logout
@ -85,13 +102,11 @@ authOpenidForm = do
Nothing -> return () Nothing -> return ()
return $ cs html return $ cs html
authOpenidForward :: Handler y HtmlObject authOpenidForward :: YesodAuth y => Handler y HtmlObject
authOpenidForward = do authOpenidForward = do
oid <- getParam "openid" oid <- getParam "openid"
env <- parseEnv authroot <- getFullAuthRoot
let complete = "http://" ++ Hack.serverName env ++ ":" ++ let complete = authroot ++ "/openid/complete/"
show (Hack.serverPort env) ++
"/auth/openid/complete/"
res <- runAttemptT $ OpenId.getForwardUrl oid complete res <- runAttemptT $ OpenId.getForwardUrl oid complete
attempt attempt
(\err -> redirect $ "/auth/openid/?message=" ++ encodeUrl (show err)) (\err -> redirect $ "/auth/openid/?message=" ++ encodeUrl (show err))
@ -145,15 +160,24 @@ rpxnowLogin = do
authCheck :: Handler y HtmlObject authCheck :: Handler y HtmlObject
authCheck = do authCheck = do
ident <- maybeIdentifier ident <- identifier
case ident of return $ toHtmlObject [("identifier", fromMaybe "" ident)]
Nothing -> return $ toHtmlObject [("status", "notloggedin")]
Just i -> return $ toHtmlObject
[ ("status", "loggedin")
, ("ident", i)
]
authLogout :: Handler y HtmlObject authLogout :: Handler y HtmlObject
authLogout = do authLogout = do
deleteCookie authCookieName deleteCookie authCookieName
return $ toHtmlObject [("status", "loggedout")] return $ toHtmlObject [("status", "loggedout")]
authIdentifier :: YesodAuth y => Handler y String
authIdentifier = do
mi <- identifier
Approot ar <- getApproot
case mi of
Nothing -> do
rp <- requestPath
let dest = ar ++ rp
liftIO $ print ("authIdentifier", dest, ar, rp)
lp <- defaultLoginPath `fmap` getYesod
addCookie 120 "DEST" dest
redirect $ ar ++ lp
Just x -> return x

View File

@ -36,7 +36,6 @@ module Yesod.Request
, anyParam , anyParam
, cookieParam , cookieParam
, identifier , identifier
, maybeIdentifier
, acceptedLanguages , acceptedLanguages
, requestPath , requestPath
, parseEnv , parseEnv
@ -164,19 +163,10 @@ anyParam = genParam anyParams PostParam -- FIXME
cookieParam :: (Parameter a, MonadRequestReader m) => ParamName -> m a cookieParam :: (Parameter a, MonadRequestReader m) => ParamName -> m a
cookieParam = genParam cookies CookieParam cookieParam = genParam cookies CookieParam
-- | Extract the cookie which specifies the identifier for a logged in
-- user.
identifier :: MonadRequestReader m => m String
identifier = do
mi <- maybeIdentifier
case mi of
Nothing -> authRequired
Just x -> return x
-- | Extract the cookie which specifies the identifier for a logged in -- | Extract the cookie which specifies the identifier for a logged in
-- user, if available. -- user, if available.
maybeIdentifier :: MonadRequestReader m => m (Maybe String) identifier :: MonadRequestReader m => m (Maybe String)
maybeIdentifier = do identifier = do
env <- parseEnv env <- parseEnv
case lookup authCookieName $ Hack.hackHeaders env of case lookup authCookieName $ Hack.hackHeaders env of
Nothing -> return Nothing Nothing -> return Nothing
@ -203,7 +193,10 @@ requestPath = do
"" -> "" "" -> ""
q'@('?':_) -> q' q'@('?':_) -> q'
q' -> q' q' -> q'
return $! Hack.pathInfo env ++ q return $! dropSlash (Hack.pathInfo env) ++ q
where
dropSlash ('/':x) = x
dropSlash x = x
type PathInfo = [String] type PathInfo = [String]
@ -285,9 +278,10 @@ instance Parameter Day where
then Right $ fromGregorian y m d then Right $ fromGregorian y m d
else Left $ "Invalid date: " ++ s else Left $ "Invalid date: " ++ s
-- for checkboxes; checks for presence -- for checkboxes; checks for presence or a "false" value
instance Parameter Bool where instance Parameter Bool where
readParams [] = Right False readParams [] = Right False
readParams [RawParam _ _ "false"] = Right False
readParams [_] = Right True readParams [_] = Right True
readParams x = Left $ "Invalid Bool parameter: " ++ show (map paramValue x) readParams x = Left $ "Invalid Bool parameter: " ++ show (map paramValue x)

View File

@ -2,6 +2,7 @@
module Yesod.Yesod module Yesod.Yesod
( Yesod (..) ( Yesod (..)
, YesodApproot (..) , YesodApproot (..)
, getApproot
, toHackApp , toHackApp
) where ) where
@ -50,6 +51,9 @@ class Yesod a => YesodApproot a where
-- | An absolute URL to the root of the application. -- | An absolute URL to the root of the application.
approot :: a -> Approot approot :: a -> Approot
getApproot :: YesodApproot y => Handler y Approot
getApproot = approot `fmap` getYesod
defaultErrorHandler :: Yesod y defaultErrorHandler :: Yesod y
=> ErrorResult => ErrorResult
-> Handler y RepChooser -> Handler y RepChooser