Cleanup, use SinglePiece
This commit is contained in:
parent
eb94784201
commit
52bb6fdc50
@ -22,20 +22,13 @@ module Yesod.Helpers.Auth
|
|||||||
, requireAuth
|
, requireAuth
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Yesod.Handler
|
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Yesod.Widget
|
|
||||||
import Yesod.Content
|
|
||||||
import Yesod.Dispatch
|
|
||||||
import Yesod.Persist
|
import Yesod.Persist
|
||||||
import Yesod.Request
|
|
||||||
import Yesod.Json
|
import Yesod.Json
|
||||||
import Text.Blaze
|
import Text.Blaze
|
||||||
import Language.Haskell.TH.Syntax hiding (lift)
|
import Language.Haskell.TH.Syntax hiding (lift)
|
||||||
import qualified Data.ByteString.Char8 as S8
|
|
||||||
import qualified Network.Wai as W
|
import qualified Network.Wai as W
|
||||||
import Text.Hamlet (hamlet)
|
import Text.Hamlet (hamlet)
|
||||||
import Data.Text.Lazy (pack)
|
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
import Data.Aeson
|
import Data.Aeson
|
||||||
@ -66,7 +59,7 @@ data Creds m = Creds
|
|||||||
, credsExtra :: [(Text, Text)]
|
, credsExtra :: [(Text, Text)]
|
||||||
}
|
}
|
||||||
|
|
||||||
class Yesod m => YesodAuth m where
|
class (Yesod m, SinglePiece (AuthId m)) => YesodAuth m where
|
||||||
type AuthId m
|
type AuthId m
|
||||||
|
|
||||||
-- | Default destination on successful login, if no other
|
-- | Default destination on successful login, if no other
|
||||||
@ -79,65 +72,62 @@ class Yesod m => YesodAuth m where
|
|||||||
|
|
||||||
getAuthId :: Creds m -> GHandler s m (Maybe (AuthId m))
|
getAuthId :: Creds m -> GHandler s m (Maybe (AuthId m))
|
||||||
|
|
||||||
showAuthId :: m -> AuthId m -> Text
|
|
||||||
readAuthId :: m -> Text -> Maybe (AuthId m)
|
|
||||||
|
|
||||||
authPlugins :: [AuthPlugin m]
|
authPlugins :: [AuthPlugin m]
|
||||||
|
|
||||||
-- | What to show on the login page.
|
-- | What to show on the login page.
|
||||||
loginHandler :: GHandler Auth m RepHtml
|
loginHandler :: GHandler Auth m RepHtml
|
||||||
loginHandler = defaultLayout $ do
|
loginHandler = defaultLayout $ do
|
||||||
setTitle $ string "Login"
|
setTitle "Login"
|
||||||
tm <- lift getRouteToMaster
|
tm <- lift getRouteToMaster
|
||||||
mapM_ (flip apLogin tm) authPlugins
|
mapM_ (flip apLogin tm) authPlugins
|
||||||
|
|
||||||
----- Message strings. In theory in the future make this localizable
|
----- Message strings. In theory in the future make this localizable
|
||||||
----- See gist: https://gist.github.com/778712
|
----- See gist: https://gist.github.com/778712
|
||||||
messageNoOpenID :: m -> Html
|
messageNoOpenID :: m -> Html
|
||||||
messageNoOpenID _ = string "No OpenID identifier found"
|
messageNoOpenID _ = "No OpenID identifier found"
|
||||||
messageLoginOpenID :: m -> Html
|
messageLoginOpenID :: m -> Html
|
||||||
messageLoginOpenID _ = string "Login via OpenID"
|
messageLoginOpenID _ = "Login via OpenID"
|
||||||
|
|
||||||
messageEmail :: m -> Html
|
messageEmail :: m -> Html
|
||||||
messageEmail _ = string "Email"
|
messageEmail _ = "Email"
|
||||||
messagePassword :: m -> Html
|
messagePassword :: m -> Html
|
||||||
messagePassword _ = string "Password"
|
messagePassword _ = "Password"
|
||||||
messageRegister :: m -> Html
|
messageRegister :: m -> Html
|
||||||
messageRegister _ = string "Register"
|
messageRegister _ = "Register"
|
||||||
messageRegisterLong :: m -> Html
|
messageRegisterLong :: m -> Html
|
||||||
messageRegisterLong _ = string "Register a new account"
|
messageRegisterLong _ = "Register a new account"
|
||||||
messageEnterEmail :: m -> Html
|
messageEnterEmail :: m -> Html
|
||||||
messageEnterEmail _ = string "Enter your e-mail address below, and a confirmation e-mail will be sent to you."
|
messageEnterEmail _ = "Enter your e-mail address below, and a confirmation e-mail will be sent to you."
|
||||||
messageConfirmationEmailSentTitle :: m -> Html
|
messageConfirmationEmailSentTitle :: m -> Html
|
||||||
messageConfirmationEmailSentTitle _ = string "Confirmation e-mail sent"
|
messageConfirmationEmailSentTitle _ = "Confirmation e-mail sent"
|
||||||
messageConfirmationEmailSent :: m -> Text -> Html
|
messageConfirmationEmailSent :: m -> Text -> Html
|
||||||
messageConfirmationEmailSent _ email = toHtml $ mconcat
|
messageConfirmationEmailSent _ email = toHtml $ mconcat
|
||||||
["A confirmation e-mail has been sent to ", email, "."]
|
["A confirmation e-mail has been sent to ", email, "."]
|
||||||
messageAddressVerified :: m -> Html
|
messageAddressVerified :: m -> Html
|
||||||
messageAddressVerified _ = string "Address verified, please set a new password"
|
messageAddressVerified _ = "Address verified, please set a new password"
|
||||||
messageInvalidKeyTitle :: m -> Html
|
messageInvalidKeyTitle :: m -> Html
|
||||||
messageInvalidKeyTitle _ = string "Invalid verification key"
|
messageInvalidKeyTitle _ = "Invalid verification key"
|
||||||
messageInvalidKey :: m -> Html
|
messageInvalidKey :: m -> Html
|
||||||
messageInvalidKey _ = string "I'm sorry, but that was an invalid verification key."
|
messageInvalidKey _ = "I'm sorry, but that was an invalid verification key."
|
||||||
messageInvalidEmailPass :: m -> Html
|
messageInvalidEmailPass :: m -> Html
|
||||||
messageInvalidEmailPass _ = string "Invalid email/password combination"
|
messageInvalidEmailPass _ = "Invalid email/password combination"
|
||||||
messageBadSetPass :: m -> Html
|
messageBadSetPass :: m -> Html
|
||||||
messageBadSetPass _ = string "You must be logged in to set a password"
|
messageBadSetPass _ = "You must be logged in to set a password"
|
||||||
messageSetPassTitle :: m -> Html
|
messageSetPassTitle :: m -> Html
|
||||||
messageSetPassTitle _ = string "Set password"
|
messageSetPassTitle _ = "Set password"
|
||||||
messageSetPass :: m -> Html
|
messageSetPass :: m -> Html
|
||||||
messageSetPass _ = string "Set a new password"
|
messageSetPass _ = "Set a new password"
|
||||||
messageNewPass :: m -> Html
|
messageNewPass :: m -> Html
|
||||||
messageNewPass _ = string "New password"
|
messageNewPass _ = "New password"
|
||||||
messageConfirmPass :: m -> Html
|
messageConfirmPass :: m -> Html
|
||||||
messageConfirmPass _ = string "Confirm"
|
messageConfirmPass _ = "Confirm"
|
||||||
messagePassMismatch :: m -> Html
|
messagePassMismatch :: m -> Html
|
||||||
messagePassMismatch _ = string "Passwords did not match, please try again"
|
messagePassMismatch _ = "Passwords did not match, please try again"
|
||||||
messagePassUpdated :: m -> Html
|
messagePassUpdated :: m -> Html
|
||||||
messagePassUpdated _ = string "Password updated"
|
messagePassUpdated _ = "Password updated"
|
||||||
|
|
||||||
messageFacebook :: m -> Html
|
messageFacebook :: m -> Html
|
||||||
messageFacebook _ = string "Login with Facebook"
|
messageFacebook _ = "Login with Facebook"
|
||||||
|
|
||||||
type Texts = [Text]
|
type Texts = [Text]
|
||||||
|
|
||||||
@ -180,14 +170,14 @@ setCreds doRedirects creds = do
|
|||||||
|]
|
|]
|
||||||
sendResponse rh
|
sendResponse rh
|
||||||
Just ar -> do
|
Just ar -> do
|
||||||
setMessage $ string "Invalid login"
|
setMessage "Invalid login"
|
||||||
redirect RedirectTemporary ar
|
redirect RedirectTemporary ar
|
||||||
else return ()
|
else return ()
|
||||||
Just aid -> do
|
Just aid -> do
|
||||||
setSession credsKey $ showAuthId y aid
|
setSession credsKey $ toSinglePiece aid
|
||||||
if doRedirects
|
if doRedirects
|
||||||
then do
|
then do
|
||||||
setMessage $ string "You are now logged in"
|
setMessage "You are now logged in"
|
||||||
redirectUltDest RedirectTemporary $ loginDest y
|
redirectUltDest RedirectTemporary $ loginDest y
|
||||||
else return ()
|
else return ()
|
||||||
|
|
||||||
@ -195,8 +185,8 @@ getCheckR :: YesodAuth m => GHandler Auth m RepHtmlJson
|
|||||||
getCheckR = do
|
getCheckR = do
|
||||||
creds <- maybeAuthId
|
creds <- maybeAuthId
|
||||||
defaultLayoutJson (do
|
defaultLayoutJson (do
|
||||||
setTitle $ string "Authentication Status"
|
setTitle "Authentication Status"
|
||||||
addHtml $ html creds) (json creds)
|
addHtml $ html creds) (json' creds)
|
||||||
where
|
where
|
||||||
html creds =
|
html creds =
|
||||||
#if GHC7
|
#if GHC7
|
||||||
@ -210,7 +200,7 @@ $maybe _ <- creds
|
|||||||
$nothing
|
$nothing
|
||||||
<p>Not logged in.
|
<p>Not logged in.
|
||||||
|]
|
|]
|
||||||
json creds =
|
json' creds =
|
||||||
Object $ Map.fromList
|
Object $ Map.fromList
|
||||||
[ (T.pack "logged_in", Bool $ maybe False (const True) creds)
|
[ (T.pack "logged_in", Bool $ maybe False (const True) creds)
|
||||||
]
|
]
|
||||||
@ -239,10 +229,9 @@ handlePluginR plugin pieces = do
|
|||||||
maybeAuthId :: YesodAuth m => GHandler s m (Maybe (AuthId m))
|
maybeAuthId :: YesodAuth m => GHandler s m (Maybe (AuthId m))
|
||||||
maybeAuthId = do
|
maybeAuthId = do
|
||||||
ms <- lookupSession credsKey
|
ms <- lookupSession credsKey
|
||||||
y <- getYesod
|
|
||||||
case ms of
|
case ms of
|
||||||
Nothing -> return Nothing
|
Nothing -> return Nothing
|
||||||
Just s -> return $ readAuthId y s
|
Just s -> return $ fromSinglePiece s
|
||||||
|
|
||||||
maybeAuth :: ( YesodAuth m
|
maybeAuth :: ( YesodAuth m
|
||||||
, Key val ~ AuthId m
|
, Key val ~ AuthId m
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{-# LANGUAGE QuasiQuotes, TypeFamilies #-}
|
{-# LANGUAGE QuasiQuotes, TypeFamilies #-}
|
||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
module Yesod.Helpers.Auth.Email
|
module Yesod.Helpers.Auth.Email
|
||||||
( -- * Plugin
|
( -- * Plugin
|
||||||
authEmail
|
authEmail
|
||||||
@ -55,12 +56,9 @@ data EmailCreds m = EmailCreds
|
|||||||
, emailCredsVerkey :: Maybe VerKey
|
, emailCredsVerkey :: Maybe VerKey
|
||||||
}
|
}
|
||||||
|
|
||||||
class YesodAuth m => YesodAuthEmail m where
|
class (YesodAuth m, SinglePiece (AuthEmailId m)) => YesodAuthEmail m where
|
||||||
type AuthEmailId m
|
type AuthEmailId m
|
||||||
|
|
||||||
showAuthEmailId :: m -> AuthEmailId m -> Text
|
|
||||||
readAuthEmailId :: m -> Text -> Maybe (AuthEmailId m)
|
|
||||||
|
|
||||||
addUnverified :: Email -> VerKey -> GHandler Auth m (AuthEmailId m)
|
addUnverified :: Email -> VerKey -> GHandler Auth m (AuthEmailId m)
|
||||||
sendVerifyEmail :: Email -> VerKey -> VerUrl -> GHandler Auth m ()
|
sendVerifyEmail :: Email -> VerKey -> VerUrl -> GHandler Auth m ()
|
||||||
getVerifyKey :: AuthEmailId m -> GHandler Auth m (Maybe VerKey)
|
getVerifyKey :: AuthEmailId m -> GHandler Auth m (Maybe VerKey)
|
||||||
@ -104,9 +102,8 @@ authEmail =
|
|||||||
where
|
where
|
||||||
dispatch "GET" ["register"] = getRegisterR >>= sendResponse
|
dispatch "GET" ["register"] = getRegisterR >>= sendResponse
|
||||||
dispatch "POST" ["register"] = postRegisterR >>= sendResponse
|
dispatch "POST" ["register"] = postRegisterR >>= sendResponse
|
||||||
dispatch "GET" ["verify", eid, verkey] = do
|
dispatch "GET" ["verify", eid, verkey] =
|
||||||
y <- getYesod
|
case fromSinglePiece eid of
|
||||||
case readAuthEmailId y eid of
|
|
||||||
Nothing -> notFound
|
Nothing -> notFound
|
||||||
Just eid' -> getVerifyR eid' verkey >>= sendResponse
|
Just eid' -> getVerifyR eid' verkey >>= sendResponse
|
||||||
dispatch "POST" ["login"] = postLoginR >>= sendResponse
|
dispatch "POST" ["login"] = postLoginR >>= sendResponse
|
||||||
@ -151,7 +148,7 @@ postRegisterR = do
|
|||||||
return (lid, key)
|
return (lid, key)
|
||||||
render <- getUrlRender
|
render <- getUrlRender
|
||||||
tm <- getRouteToMaster
|
tm <- getRouteToMaster
|
||||||
let verUrl = render $ tm $ verify (showAuthEmailId y lid) verKey
|
let verUrl = render $ tm $ verify (toSinglePiece lid) verKey
|
||||||
sendVerifyEmail email verKey verUrl
|
sendVerifyEmail email verKey verUrl
|
||||||
defaultLayout $ do
|
defaultLayout $ do
|
||||||
setTitle $ messageConfirmationEmailSentTitle y
|
setTitle $ messageConfirmationEmailSentTitle y
|
||||||
|
|||||||
@ -17,11 +17,11 @@ import Yesod.Handler
|
|||||||
import Yesod.Widget
|
import Yesod.Widget
|
||||||
import Text.Hamlet (hamlet)
|
import Text.Hamlet (hamlet)
|
||||||
import Control.Monad.IO.Class (liftIO)
|
import Control.Monad.IO.Class (liftIO)
|
||||||
import qualified Data.ByteString.Char8 as S8
|
|
||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Control.Monad (mzero)
|
import Control.Monad (mzero)
|
||||||
import Data.Monoid (mappend)
|
import Data.Monoid (mappend)
|
||||||
|
import qualified Data.Aeson.Types
|
||||||
|
|
||||||
facebookUrl :: AuthRoute
|
facebookUrl :: AuthRoute
|
||||||
facebookUrl = PluginR "facebook" ["forward"]
|
facebookUrl = PluginR "facebook" ["forward"]
|
||||||
@ -39,7 +39,7 @@ authFacebook cid secret perms =
|
|||||||
tm <- getRouteToMaster
|
tm <- getRouteToMaster
|
||||||
render <- getUrlRender
|
render <- getUrlRender
|
||||||
let fb = Facebook.Facebook cid secret $ render $ tm url
|
let fb = Facebook.Facebook cid secret $ render $ tm url
|
||||||
redirectString RedirectTemporary $ Facebook.getForwardUrl fb perms
|
redirectText RedirectTemporary $ Facebook.getForwardUrl fb perms
|
||||||
dispatch "GET" [] = do
|
dispatch "GET" [] = do
|
||||||
render <- getUrlRender
|
render <- getUrlRender
|
||||||
tm <- getRouteToMaster
|
tm <- getRouteToMaster
|
||||||
@ -67,6 +67,7 @@ authFacebook cid secret perms =
|
|||||||
<a href="#{furl}">#{messageFacebook y}
|
<a href="#{furl}">#{messageFacebook y}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
parseCreds :: Text -> Value -> Data.Aeson.Types.Parser (Creds m)
|
||||||
parseCreds at' (Object m) = do
|
parseCreds at' (Object m) = do
|
||||||
id' <- m .: "id"
|
id' <- m .: "id"
|
||||||
let id'' = "http://graph.facebook.com/" `mappend` id'
|
let id'' = "http://graph.facebook.com/" `mappend` id'
|
||||||
|
|||||||
@ -73,7 +73,6 @@ import Text.Hamlet (hamlet)
|
|||||||
import Control.Applicative ((<$>), (<*>))
|
import Control.Applicative ((<$>), (<*>))
|
||||||
import Data.ByteString.Lazy.Char8 (pack)
|
import Data.ByteString.Lazy.Char8 (pack)
|
||||||
import Data.Digest.Pure.SHA (sha1, showDigest)
|
import Data.Digest.Pure.SHA (sha1, showDigest)
|
||||||
import Database.Persist.TH (share2, mkMigrate, persist, mkPersist)
|
|
||||||
import Data.Text (Text, unpack)
|
import Data.Text (Text, unpack)
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
|
|
||||||
|
|||||||
@ -14,15 +14,14 @@ import Text.Hamlet (hamlet)
|
|||||||
import Web.Authenticate.OAuth
|
import Web.Authenticate.OAuth
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.String
|
import Data.String
|
||||||
import Network.HTTP.Enumerator
|
|
||||||
import Data.ByteString.Char8 (pack)
|
import Data.ByteString.Char8 (pack)
|
||||||
import Control.Arrow ((***))
|
import Control.Arrow ((***))
|
||||||
import Control.Monad
|
|
||||||
import Control.Monad.IO.Class (liftIO)
|
import Control.Monad.IO.Class (liftIO)
|
||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
import Data.Text (Text, unpack)
|
import Data.Text (Text, unpack)
|
||||||
import Data.Text.Encoding (encodeUtf8, decodeUtf8With)
|
import Data.Text.Encoding (encodeUtf8, decodeUtf8With)
|
||||||
import Data.Text.Encoding.Error (lenientDecode)
|
import Data.Text.Encoding.Error (lenientDecode)
|
||||||
|
import Data.ByteString (ByteString)
|
||||||
|
|
||||||
oauthUrl :: Text -> AuthRoute
|
oauthUrl :: Text -> AuthRoute
|
||||||
oauthUrl name = PluginR name ["forward"]
|
oauthUrl name = PluginR name ["forward"]
|
||||||
@ -50,11 +49,8 @@ authOAuth name ident reqUrl accUrl authUrl key sec = AuthPlugin name dispatch lo
|
|||||||
tm <- getRouteToMaster
|
tm <- getRouteToMaster
|
||||||
let oauth' = oauth { oauthCallback = Just $ encodeUtf8 $ render $ tm url }
|
let oauth' = oauth { oauthCallback = Just $ encodeUtf8 $ render $ tm url }
|
||||||
tok <- liftIO $ getTemporaryCredential oauth'
|
tok <- liftIO $ getTemporaryCredential oauth'
|
||||||
redirectString RedirectTemporary (fromString $ authorizeUrl oauth' tok)
|
redirectText RedirectTemporary (fromString $ authorizeUrl oauth' tok)
|
||||||
dispatch "GET" [] = do
|
dispatch "GET" [] = do
|
||||||
render <- getUrlRender
|
|
||||||
tm <- getRouteToMaster
|
|
||||||
let callback = render $ tm url
|
|
||||||
verifier <- runFormGet' $ stringInput "oauth_verifier"
|
verifier <- runFormGet' $ stringInput "oauth_verifier"
|
||||||
oaTok <- runFormGet' $ stringInput "oauth_token"
|
oaTok <- runFormGet' $ stringInput "oauth_token"
|
||||||
let reqTok = Credential [ ("oauth_verifier", encodeUtf8 verifier), ("oauth_token", encodeUtf8 oaTok)
|
let reqTok = Credential [ ("oauth_verifier", encodeUtf8 verifier), ("oauth_token", encodeUtf8 oaTok)
|
||||||
@ -89,4 +85,5 @@ authTwitter = authOAuth "twitter"
|
|||||||
twitterUrl :: AuthRoute
|
twitterUrl :: AuthRoute
|
||||||
twitterUrl = oauthUrl "twitter"
|
twitterUrl = oauthUrl "twitter"
|
||||||
|
|
||||||
|
bsToText :: ByteString -> Text
|
||||||
bsToText = decodeUtf8With lenientDecode
|
bsToText = decodeUtf8With lenientDecode
|
||||||
|
|||||||
@ -16,9 +16,8 @@ import Yesod.Widget
|
|||||||
import Yesod.Request
|
import Yesod.Request
|
||||||
import Text.Hamlet (hamlet)
|
import Text.Hamlet (hamlet)
|
||||||
import Text.Cassius (cassius)
|
import Text.Cassius (cassius)
|
||||||
import Text.Blaze (string)
|
import Text.Blaze (toHtml)
|
||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
import qualified Data.ByteString.Char8 as S8
|
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
|
|
||||||
forwardUrl :: AuthRoute
|
forwardUrl :: AuthRoute
|
||||||
@ -64,10 +63,10 @@ authOpenId =
|
|||||||
res <- runAttemptT $ OpenId.getForwardUrl oid complete' Nothing []
|
res <- runAttemptT $ OpenId.getForwardUrl oid complete' Nothing []
|
||||||
attempt
|
attempt
|
||||||
(\err -> do
|
(\err -> do
|
||||||
setMessage $ string $ show err
|
setMessage $ toHtml $ show err
|
||||||
redirect RedirectTemporary $ toMaster LoginR
|
redirect RedirectTemporary $ toMaster LoginR
|
||||||
)
|
)
|
||||||
(redirectString RedirectTemporary)
|
(redirectText RedirectTemporary)
|
||||||
res
|
res
|
||||||
_ -> do
|
_ -> do
|
||||||
toMaster <- getRouteToMaster
|
toMaster <- getRouteToMaster
|
||||||
@ -88,7 +87,7 @@ completeHelper gets' = do
|
|||||||
res <- runAttemptT $ OpenId.authenticate gets'
|
res <- runAttemptT $ OpenId.authenticate gets'
|
||||||
toMaster <- getRouteToMaster
|
toMaster <- getRouteToMaster
|
||||||
let onFailure err = do
|
let onFailure err = do
|
||||||
setMessage $ string $ show err
|
setMessage $ toHtml $ show err
|
||||||
redirect RedirectTemporary $ toMaster LoginR
|
redirect RedirectTemporary $ toMaster LoginR
|
||||||
let onSuccess (OpenId.Identifier ident, _) =
|
let onSuccess (OpenId.Identifier ident, _) =
|
||||||
setCreds True $ Creds "openid" ident []
|
setCreds True $ Creds "openid" ident []
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import Yesod.Widget
|
|||||||
import Yesod.Request
|
import Yesod.Request
|
||||||
import Text.Hamlet (hamlet)
|
import Text.Hamlet (hamlet)
|
||||||
import Control.Monad.IO.Class (liftIO)
|
import Control.Monad.IO.Class (liftIO)
|
||||||
import Data.Text (Text, pack, unpack)
|
import Data.Text (pack, unpack)
|
||||||
import Control.Arrow ((***))
|
import Control.Arrow ((***))
|
||||||
|
|
||||||
authRpxnow :: YesodAuth m
|
authRpxnow :: YesodAuth m
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user