BrowserID lazy load
This commit is contained in:
parent
ba9e40c177
commit
4cde171285
@ -1,10 +1,14 @@
|
|||||||
{-# LANGUAGE QuasiQuotes #-}
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
module Yesod.Auth.BrowserId
|
module Yesod.Auth.BrowserId
|
||||||
( authBrowserId
|
( authBrowserId
|
||||||
, authBrowserIdAudience
|
|
||||||
, createOnClick
|
, createOnClick
|
||||||
|
, def
|
||||||
|
, BrowserIdSettings
|
||||||
|
, bisAudience
|
||||||
|
, bisLazyLoad
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Yesod.Auth
|
import Yesod.Auth
|
||||||
@ -14,12 +18,13 @@ import Yesod.Core
|
|||||||
import Text.Hamlet (hamlet)
|
import Text.Hamlet (hamlet)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
import Control.Monad (when)
|
import Control.Monad (when, unless)
|
||||||
import Control.Exception (throwIO)
|
import Control.Exception (throwIO)
|
||||||
import Text.Julius (julius, rawJS)
|
import Text.Julius (julius, rawJS)
|
||||||
import Network.URI (uriPath, parseURI)
|
import Network.URI (uriPath, parseURI)
|
||||||
import Data.FileEmbed (embedFile)
|
import Data.FileEmbed (embedFile)
|
||||||
import Data.ByteString (ByteString)
|
import Data.ByteString (ByteString)
|
||||||
|
import Data.Default
|
||||||
|
|
||||||
pid :: Text
|
pid :: Text
|
||||||
pid = "browserid"
|
pid = "browserid"
|
||||||
@ -27,29 +32,42 @@ pid = "browserid"
|
|||||||
complete :: Route Auth
|
complete :: Route Auth
|
||||||
complete = PluginR pid []
|
complete = PluginR pid []
|
||||||
|
|
||||||
-- | Log into browser ID with an audience value determined from the 'approot'.
|
-- | A settings type for various configuration options relevant to BrowserID.
|
||||||
authBrowserId :: YesodAuth m => AuthPlugin m
|
--
|
||||||
authBrowserId = helper Nothing
|
-- See: <http://www.yesodweb.com/book/settings-types>
|
||||||
|
--
|
||||||
|
-- Since 1.2.0
|
||||||
|
data BrowserIdSettings = BrowserIdSettings
|
||||||
|
{ bisAudience :: Maybe Text
|
||||||
|
-- ^ BrowserID audience value. If @Nothing@, will be extracted based on the
|
||||||
|
-- approot.
|
||||||
|
--
|
||||||
|
-- Default: @Nothing@
|
||||||
|
--
|
||||||
|
-- Since 1.2.0
|
||||||
|
, bisLazyLoad :: Bool
|
||||||
|
-- ^ Use asynchronous Javascript loading for the BrowserID JS file.
|
||||||
|
--
|
||||||
|
-- Default: @True@.
|
||||||
|
--
|
||||||
|
-- Since 1.2.0
|
||||||
|
}
|
||||||
|
|
||||||
-- | Log into browser ID with the given audience value. Note that this must be
|
instance Default BrowserIdSettings where
|
||||||
-- your actual hostname, or login will fail.
|
def = BrowserIdSettings
|
||||||
authBrowserIdAudience
|
{ bisAudience = Nothing
|
||||||
:: YesodAuth m
|
, bisLazyLoad = True
|
||||||
=> Text -- ^ audience
|
}
|
||||||
-> AuthPlugin m
|
|
||||||
authBrowserIdAudience = helper . Just
|
|
||||||
|
|
||||||
helper :: YesodAuth m
|
authBrowserId :: YesodAuth m => BrowserIdSettings -> AuthPlugin m
|
||||||
=> Maybe Text -- ^ audience
|
authBrowserId bis@BrowserIdSettings {..} = AuthPlugin
|
||||||
-> AuthPlugin m
|
|
||||||
helper maudience = AuthPlugin
|
|
||||||
{ apName = pid
|
{ apName = pid
|
||||||
, apDispatch = \m ps ->
|
, apDispatch = \m ps ->
|
||||||
case (m, ps) of
|
case (m, ps) of
|
||||||
("GET", [assertion]) -> do
|
("GET", [assertion]) -> do
|
||||||
master <- lift getYesod
|
master <- lift getYesod
|
||||||
audience <-
|
audience <-
|
||||||
case maudience of
|
case bisAudience of
|
||||||
Just a -> return a
|
Just a -> return a
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
r <- getUrlRender
|
r <- getUrlRender
|
||||||
@ -69,12 +87,10 @@ helper maudience = AuthPlugin
|
|||||||
(_, []) -> badMethod
|
(_, []) -> badMethod
|
||||||
_ -> notFound
|
_ -> notFound
|
||||||
, apLogin = \toMaster -> do
|
, apLogin = \toMaster -> do
|
||||||
onclick <- createOnClick toMaster
|
onclick <- createOnClick bis toMaster
|
||||||
|
|
||||||
autologin <- fmap (== Just "true") $ lookupGetParam "autologin"
|
autologin <- fmap (== Just "true") $ lookupGetParam "autologin"
|
||||||
when autologin $ toWidget [julius|
|
when autologin $ toWidget [julius|#{rawJS onclick}();|]
|
||||||
#{rawJS onclick}();
|
|
||||||
|]
|
|
||||||
|
|
||||||
toWidget [hamlet|
|
toWidget [hamlet|
|
||||||
$newline never
|
$newline never
|
||||||
@ -89,27 +105,43 @@ $newline never
|
|||||||
|
|
||||||
-- | Generates a function to handle on-click events, and returns that function
|
-- | Generates a function to handle on-click events, and returns that function
|
||||||
-- name.
|
-- name.
|
||||||
createOnClick :: (Route Auth -> Route master) -> WidgetT master IO Text
|
createOnClick :: BrowserIdSettings
|
||||||
createOnClick toMaster = do
|
-> (Route Auth -> Route master)
|
||||||
addScriptRemote browserIdJs
|
-> WidgetT master IO Text
|
||||||
|
createOnClick BrowserIdSettings {..} toMaster = do
|
||||||
|
unless bisLazyLoad $ addScriptRemote browserIdJs
|
||||||
onclick <- newIdent
|
onclick <- newIdent
|
||||||
render <- getUrlRender
|
render <- getUrlRender
|
||||||
let login = toJSON $ getPath $ render $ toMaster LoginR
|
let login = toJSON $ getPath $ render (toMaster LoginR)
|
||||||
toWidget [julius|
|
toWidget [julius|
|
||||||
function #{rawJS onclick}() {
|
function #{rawJS onclick}() {
|
||||||
navigator.id.watch({
|
if (navigator.id) {
|
||||||
onlogin: function (assertion) {
|
navigator.id.watch({
|
||||||
if (assertion) {
|
onlogin: function (assertion) {
|
||||||
document.location = "@{toMaster complete}" + "/" + assertion;
|
if (assertion) {
|
||||||
}
|
document.location = "@{toMaster complete}/" + assertion;
|
||||||
},
|
}
|
||||||
onlogout: function () {}
|
},
|
||||||
});
|
onlogout: function () {}
|
||||||
navigator.id.request({
|
});
|
||||||
returnTo: #{login} + "?autologin=true"
|
navigator.id.request({
|
||||||
});
|
returnTo: #{login} + "?autologin=true"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
alert("Loading, please try again");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|]
|
|]
|
||||||
|
when bisLazyLoad $ toWidget [julius|
|
||||||
|
(function(){
|
||||||
|
var bid = document.createElement("script");
|
||||||
|
bid.async = true;
|
||||||
|
bid.src = #{toJSON browserIdJs};
|
||||||
|
var s = document.getElementsByTagName('script')[0];
|
||||||
|
s.parentNode.insertBefore(bid, s);
|
||||||
|
})();
|
||||||
|
|]
|
||||||
|
|
||||||
autologin <- fmap (== Just "true") $ lookupGetParam "autologin"
|
autologin <- fmap (== Just "true") $ lookupGetParam "autologin"
|
||||||
when autologin $ toWidget [julius|#{rawJS onclick}();|]
|
when autologin $ toWidget [julius|#{rawJS onclick}();|]
|
||||||
|
|||||||
@ -45,6 +45,7 @@ library
|
|||||||
, http-types
|
, http-types
|
||||||
, file-embed
|
, file-embed
|
||||||
, email-validate >= 1.0
|
, email-validate >= 1.0
|
||||||
|
, data-default
|
||||||
|
|
||||||
exposed-modules: Yesod.Auth
|
exposed-modules: Yesod.Auth
|
||||||
Yesod.Auth.BrowserId
|
Yesod.Auth.BrowserId
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user