Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
02dcb99cad
@ -1,4 +1,4 @@
|
|||||||
resolver: lts-3.7
|
resolver: lts-5.6
|
||||||
packages:
|
packages:
|
||||||
- ./yesod-core
|
- ./yesod-core
|
||||||
- ./yesod-static
|
- ./yesod-static
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
## 1.4.1
|
||||||
|
|
||||||
|
* change OAuth Twitter ID, screen_name → user_id [#1168](https://github.com/yesodweb/yesod/pull/1168)
|
||||||
|
|
||||||
## 1.4.0.2
|
## 1.4.0.2
|
||||||
|
|
||||||
* Compile with GHC 7.10
|
* Compile with GHC 7.10
|
||||||
|
|||||||
@ -4,6 +4,7 @@ module Yesod.Auth.OAuth
|
|||||||
( authOAuth
|
( authOAuth
|
||||||
, oauthUrl
|
, oauthUrl
|
||||||
, authTwitter
|
, authTwitter
|
||||||
|
, authTwitterUsingUserId
|
||||||
, twitterUrl
|
, twitterUrl
|
||||||
, authTumblr
|
, authTumblr
|
||||||
, tumblrUrl
|
, tumblrUrl
|
||||||
@ -89,11 +90,12 @@ mkExtractCreds name idName (Credential dic) = do
|
|||||||
Just crId -> return $ Creds name crId $ map (bsToText *** bsToText) dic
|
Just crId -> return $ Creds name crId $ map (bsToText *** bsToText) dic
|
||||||
Nothing -> throwIO $ CredentialError ("key not found: " ++ idName) (Credential dic)
|
Nothing -> throwIO $ CredentialError ("key not found: " ++ idName) (Credential dic)
|
||||||
|
|
||||||
authTwitter :: YesodAuth m
|
authTwitter' :: YesodAuth m
|
||||||
=> ByteString -- ^ Consumer Key
|
=> ByteString -- ^ Consumer Key
|
||||||
-> ByteString -- ^ Consumer Secret
|
-> ByteString -- ^ Consumer Secret
|
||||||
-> AuthPlugin m
|
-> String
|
||||||
authTwitter key secret = authOAuth
|
-> AuthPlugin m
|
||||||
|
authTwitter' key secret idName = authOAuth
|
||||||
(newOAuth { oauthServerName = "twitter"
|
(newOAuth { oauthServerName = "twitter"
|
||||||
, oauthRequestUri = "https://api.twitter.com/oauth/request_token"
|
, oauthRequestUri = "https://api.twitter.com/oauth/request_token"
|
||||||
, oauthAccessTokenUri = "https://api.twitter.com/oauth/access_token"
|
, oauthAccessTokenUri = "https://api.twitter.com/oauth/access_token"
|
||||||
@ -103,7 +105,26 @@ authTwitter key secret = authOAuth
|
|||||||
, oauthConsumerSecret = secret
|
, oauthConsumerSecret = secret
|
||||||
, oauthVersion = OAuth10a
|
, oauthVersion = OAuth10a
|
||||||
})
|
})
|
||||||
(mkExtractCreds "twitter" "screen_name")
|
(mkExtractCreds "twitter" idName)
|
||||||
|
|
||||||
|
-- | This plugin uses Twitter's /screen_name/ as ID, which shouldn't be used for authentication because it is mutable.
|
||||||
|
authTwitter :: YesodAuth m
|
||||||
|
=> ByteString -- ^ Consumer Key
|
||||||
|
-> ByteString -- ^ Consumer Secret
|
||||||
|
-> AuthPlugin m
|
||||||
|
authTwitter key secret = authTwitter' key secret "screen_name"
|
||||||
|
{-# DEPRECATED authTwitter "Use authTwitterUsingUserID instead" #-}
|
||||||
|
|
||||||
|
-- | Twitter plugin which uses Twitter's /user_id/ as ID.
|
||||||
|
--
|
||||||
|
-- For more information, see: https://github.com/yesodweb/yesod/pull/1168
|
||||||
|
--
|
||||||
|
-- @since 1.4.1
|
||||||
|
authTwitterUsingUserId :: YesodAuth m
|
||||||
|
=> ByteString -- ^ Consumer Key
|
||||||
|
-> ByteString -- ^ Consumer Secret
|
||||||
|
-> AuthPlugin m
|
||||||
|
authTwitterUsingUserId key secret = authTwitter' key secret "user_id"
|
||||||
|
|
||||||
twitterUrl :: AuthRoute
|
twitterUrl :: AuthRoute
|
||||||
twitterUrl = oauthUrl "twitter"
|
twitterUrl = oauthUrl "twitter"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod-auth-oauth
|
name: yesod-auth-oauth
|
||||||
version: 1.4.0.2
|
version: 1.4.1
|
||||||
license: BSD3
|
license: BSD3
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Hiromi Ishii
|
author: Hiromi Ishii
|
||||||
|
|||||||
@ -1,3 +1,8 @@
|
|||||||
|
## 1.4.13
|
||||||
|
|
||||||
|
* Add a CSRF token to the login form from `Yesod.Auth.Hardcoded`, making it compatible with the CSRF middleware [#1161](https://github.com/yesodweb/yesod/pull/1161)
|
||||||
|
* Multiple session messages. [#1187](https://github.com/yesodweb/yesod/pull/1187)
|
||||||
|
|
||||||
## 1.4.12
|
## 1.4.12
|
||||||
|
|
||||||
* Deprecated Yesod.Auth.GoogleEmail
|
* Deprecated Yesod.Auth.GoogleEmail
|
||||||
|
|||||||
@ -189,9 +189,9 @@ class (Yesod master, PathPiece (AuthId master), RenderMessage master FormMessage
|
|||||||
authHttpManager :: master -> Manager
|
authHttpManager :: master -> Manager
|
||||||
|
|
||||||
-- | Called on a successful login. By default, calls
|
-- | Called on a successful login. By default, calls
|
||||||
-- @setMessageI NowLoggedIn@.
|
-- @addMessageI "success" NowLoggedIn@.
|
||||||
onLogin :: HandlerT master IO ()
|
onLogin :: HandlerT master IO ()
|
||||||
onLogin = setMessageI Msg.NowLoggedIn
|
onLogin = addMessageI "success" Msg.NowLoggedIn
|
||||||
|
|
||||||
-- | Called on logout. By default, does nothing
|
-- | Called on logout. By default, does nothing
|
||||||
onLogout :: HandlerT master IO ()
|
onLogout :: HandlerT master IO ()
|
||||||
@ -214,10 +214,10 @@ class (Yesod master, PathPiece (AuthId master), RenderMessage master FormMessage
|
|||||||
maybeAuthId = defaultMaybeAuthId
|
maybeAuthId = defaultMaybeAuthId
|
||||||
|
|
||||||
-- | Called on login error for HTTP requests. By default, calls
|
-- | Called on login error for HTTP requests. By default, calls
|
||||||
-- @setMessage@ and redirects to @dest@.
|
-- @addMessage@ with "error" as status and redirects to @dest@.
|
||||||
onErrorHtml :: (MonadResourceBase m) => Route master -> Text -> HandlerT master m Html
|
onErrorHtml :: (MonadResourceBase m) => Route master -> Text -> HandlerT master m Html
|
||||||
onErrorHtml dest msg = do
|
onErrorHtml dest msg = do
|
||||||
setMessage $ toHtml msg
|
addMessage "error" $ toHtml msg
|
||||||
fmap asHtml $ redirect dest
|
fmap asHtml $ redirect dest
|
||||||
|
|
||||||
-- | runHttpRequest gives you a chance to handle an HttpException and retry
|
-- | runHttpRequest gives you a chance to handle an HttpException and retry
|
||||||
|
|||||||
@ -2,7 +2,10 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
-- | NOTE: Mozilla Persona will be shut down by the end of 2016, therefore this
|
||||||
|
-- module is no longer recommended for use.
|
||||||
module Yesod.Auth.BrowserId
|
module Yesod.Auth.BrowserId
|
||||||
|
{-# DEPRECATED "Mozilla Persona will be shut down by the end of 2016" #-}
|
||||||
( authBrowserId
|
( authBrowserId
|
||||||
, createOnClick, createOnClickOverride
|
, createOnClick, createOnClickOverride
|
||||||
, def
|
, def
|
||||||
|
|||||||
@ -107,6 +107,11 @@ data EmailCreds site = EmailCreds
|
|||||||
, emailCredsEmail :: Email
|
, emailCredsEmail :: Email
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data ForgotPasswordForm = ForgotPasswordForm { forgotEmail :: Text }
|
||||||
|
data PasswordForm = PasswordForm { passwordCurrent :: Text, passwordNew :: Text, passwordConfirm :: Text }
|
||||||
|
data UserForm = UserForm { email :: Text }
|
||||||
|
data UserLoginForm = UserLoginForm { loginEmail :: Text, loginPassword :: Text }
|
||||||
|
|
||||||
class ( YesodAuth site
|
class ( YesodAuth site
|
||||||
, PathPiece (AuthEmailId site)
|
, PathPiece (AuthEmailId site)
|
||||||
, (RenderMessage site Msg.AuthMessage)
|
, (RenderMessage site Msg.AuthMessage)
|
||||||
@ -253,30 +258,9 @@ class ( YesodAuth site
|
|||||||
-> AuthHandler site TypedContent
|
-> AuthHandler site TypedContent
|
||||||
setPasswordHandler = defaultSetPasswordHandler
|
setPasswordHandler = defaultSetPasswordHandler
|
||||||
|
|
||||||
|
authEmail :: (YesodAuthEmail m) => AuthPlugin m
|
||||||
authEmail :: YesodAuthEmail m => AuthPlugin m
|
|
||||||
authEmail =
|
authEmail =
|
||||||
AuthPlugin "email" dispatch $ \tm ->
|
AuthPlugin "email" dispatch emailLoginHandler
|
||||||
[whamlet|
|
|
||||||
$newline never
|
|
||||||
<form method="post" action="@{tm loginR}">
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>_{Msg.Email}
|
|
||||||
<td>
|
|
||||||
<input type="email" name="email" required>
|
|
||||||
<tr>
|
|
||||||
<th>_{Msg.Password}
|
|
||||||
<td>
|
|
||||||
<input type="password" name="password" required>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<button type=submit .btn .btn-success>
|
|
||||||
_{Msg.LoginViaEmail}
|
|
||||||
|
|
||||||
<a href="@{tm registerR}" .btn .btn-default>
|
|
||||||
_{Msg.RegisterLong}
|
|
||||||
|]
|
|
||||||
where
|
where
|
||||||
dispatch "GET" ["register"] = getRegisterR >>= sendResponse
|
dispatch "GET" ["register"] = getRegisterR >>= sendResponse
|
||||||
dispatch "POST" ["register"] = postRegisterR >>= sendResponse
|
dispatch "POST" ["register"] = postRegisterR >>= sendResponse
|
||||||
@ -294,23 +278,98 @@ $newline never
|
|||||||
getRegisterR :: YesodAuthEmail master => HandlerT Auth (HandlerT master IO) Html
|
getRegisterR :: YesodAuthEmail master => HandlerT Auth (HandlerT master IO) Html
|
||||||
getRegisterR = registerHandler
|
getRegisterR = registerHandler
|
||||||
|
|
||||||
|
emailLoginHandler :: YesodAuthEmail master => (Route Auth -> Route master) -> WidgetT master IO ()
|
||||||
|
emailLoginHandler toParent = do
|
||||||
|
(widget, enctype) <- liftWidgetT $ generateFormPost loginForm
|
||||||
|
|
||||||
|
[whamlet|
|
||||||
|
<form method="post" action="@{toParent loginR}">
|
||||||
|
<div id="emailLoginForm">
|
||||||
|
^{widget}
|
||||||
|
<div>
|
||||||
|
<button type=submit .btn .btn-success>
|
||||||
|
_{Msg.LoginViaEmail}
|
||||||
|
|
||||||
|
<a href="@{toParent registerR}" .btn .btn-default>
|
||||||
|
_{Msg.RegisterLong}
|
||||||
|
|]
|
||||||
|
where
|
||||||
|
loginForm extra = do
|
||||||
|
|
||||||
|
emailMsg <- renderMessage' Msg.Email
|
||||||
|
(emailRes, emailView) <- mreq emailField (emailSettings emailMsg) Nothing
|
||||||
|
|
||||||
|
passwordMsg <- renderMessage' Msg.Password
|
||||||
|
(passwordRes, passwordView) <- mreq passwordField (passwordSettings passwordMsg) Nothing
|
||||||
|
|
||||||
|
let userRes = UserLoginForm <$> emailRes <*> passwordRes
|
||||||
|
let widget = do
|
||||||
|
[whamlet|
|
||||||
|
#{extra}
|
||||||
|
<div>
|
||||||
|
^{fvInput emailView}
|
||||||
|
<div>
|
||||||
|
^{fvInput passwordView}
|
||||||
|
|]
|
||||||
|
|
||||||
|
return (userRes, widget)
|
||||||
|
emailSettings emailMsg = do
|
||||||
|
FieldSettings {
|
||||||
|
fsLabel = SomeMessage Msg.Email,
|
||||||
|
fsTooltip = Nothing,
|
||||||
|
fsId = Just "email",
|
||||||
|
fsName = Just "email",
|
||||||
|
fsAttrs = [("autofocus", ""), ("placeholder", emailMsg)]
|
||||||
|
}
|
||||||
|
passwordSettings passwordMsg =
|
||||||
|
FieldSettings {
|
||||||
|
fsLabel = SomeMessage Msg.Password,
|
||||||
|
fsTooltip = Nothing,
|
||||||
|
fsId = Just "password",
|
||||||
|
fsName = Just "password",
|
||||||
|
fsAttrs = [("placeholder", passwordMsg)]
|
||||||
|
}
|
||||||
|
renderMessage' msg = do
|
||||||
|
langs <- languages
|
||||||
|
master <- getYesod
|
||||||
|
return $ renderAuthMessage master langs msg
|
||||||
-- | Default implementation of 'registerHandler'.
|
-- | Default implementation of 'registerHandler'.
|
||||||
--
|
--
|
||||||
-- Since: 1.2.6
|
-- Since: 1.2.6
|
||||||
defaultRegisterHandler :: YesodAuthEmail master => AuthHandler master Html
|
defaultRegisterHandler :: YesodAuthEmail master => AuthHandler master Html
|
||||||
defaultRegisterHandler = do
|
defaultRegisterHandler = do
|
||||||
email <- newIdent
|
(widget, enctype) <- lift $ generateFormPost registrationForm
|
||||||
tp <- getRouteToParent
|
toParentRoute <- getRouteToParent
|
||||||
lift $ authLayout $ do
|
lift $ authLayout $ do
|
||||||
setTitleI Msg.RegisterLong
|
setTitleI Msg.RegisterLong
|
||||||
[whamlet|
|
[whamlet|
|
||||||
<p>_{Msg.EnterEmail}
|
<p>_{Msg.EnterEmail}
|
||||||
<form method="post" action="@{tp registerR}">
|
<form method="post" action="@{toParentRoute registerR}" enctype=#{enctype}>
|
||||||
<div id="registerForm">
|
<div id="registerForm">
|
||||||
<label for=#{email}>_{Msg.Email}:
|
^{widget}
|
||||||
<input ##{email} type="email" name="email" width="150" autofocus>
|
|
||||||
<button .btn>_{Msg.Register}
|
<button .btn>_{Msg.Register}
|
||||||
|]
|
|]
|
||||||
|
where
|
||||||
|
registrationForm extra = do
|
||||||
|
let emailSettings = FieldSettings {
|
||||||
|
fsLabel = SomeMessage Msg.Email,
|
||||||
|
fsTooltip = Nothing,
|
||||||
|
fsId = Just "email",
|
||||||
|
fsName = Just "email",
|
||||||
|
fsAttrs = [("autofocus", "")]
|
||||||
|
}
|
||||||
|
|
||||||
|
(emailRes, emailView) <- mreq emailField emailSettings Nothing
|
||||||
|
|
||||||
|
let userRes = UserForm <$> emailRes
|
||||||
|
let widget = do
|
||||||
|
[whamlet|
|
||||||
|
#{extra}
|
||||||
|
^{fvLabel emailView}
|
||||||
|
^{fvInput emailView}
|
||||||
|
|]
|
||||||
|
|
||||||
|
return (userRes, widget)
|
||||||
|
|
||||||
registerHelper :: YesodAuthEmail master
|
registerHelper :: YesodAuthEmail master
|
||||||
=> Bool -- ^ allow usernames?
|
=> Bool -- ^ allow usernames?
|
||||||
@ -365,18 +424,38 @@ getForgotPasswordR = forgotPasswordHandler
|
|||||||
-- Since: 1.2.6
|
-- Since: 1.2.6
|
||||||
defaultForgotPasswordHandler :: YesodAuthEmail master => AuthHandler master Html
|
defaultForgotPasswordHandler :: YesodAuthEmail master => AuthHandler master Html
|
||||||
defaultForgotPasswordHandler = do
|
defaultForgotPasswordHandler = do
|
||||||
tp <- getRouteToParent
|
(widget, enctype) <- lift $ generateFormPost forgotPasswordForm
|
||||||
email <- newIdent
|
toParent <- getRouteToParent
|
||||||
lift $ authLayout $ do
|
lift $ authLayout $ do
|
||||||
setTitleI Msg.PasswordResetTitle
|
setTitleI Msg.PasswordResetTitle
|
||||||
[whamlet|
|
[whamlet|
|
||||||
<p>_{Msg.PasswordResetPrompt}
|
<p>_{Msg.PasswordResetPrompt}
|
||||||
<form method="post" action="@{tp forgotPasswordR}">
|
<form method=post action=@{toParent forgotPasswordR} enctype=#{enctype}>
|
||||||
<div id="registerForm">
|
<div id="forgotPasswordForm">
|
||||||
<label for=#{email}>_{Msg.ProvideIdentifier}
|
^{widget}
|
||||||
<input ##{email} type=text name="email" width="150" autofocus>
|
<button .btn>_{Msg.SendPasswordResetEmail}
|
||||||
<button .btn>_{Msg.SendPasswordResetEmail}
|
|
||||||
|]
|
|]
|
||||||
|
where
|
||||||
|
forgotPasswordForm extra = do
|
||||||
|
(emailRes, emailView) <- mreq emailField emailSettings Nothing
|
||||||
|
|
||||||
|
let forgotPasswordRes = ForgotPasswordForm <$> emailRes
|
||||||
|
let widget = do
|
||||||
|
[whamlet|
|
||||||
|
#{extra}
|
||||||
|
^{fvLabel emailView}
|
||||||
|
^{fvInput emailView}
|
||||||
|
|]
|
||||||
|
return (forgotPasswordRes, widget)
|
||||||
|
|
||||||
|
emailSettings =
|
||||||
|
FieldSettings {
|
||||||
|
fsLabel = SomeMessage Msg.ProvideIdentifier,
|
||||||
|
fsTooltip = Nothing,
|
||||||
|
fsId = Just "forgotPassword",
|
||||||
|
fsName = Just "email",
|
||||||
|
fsAttrs = [("autofocus", "")]
|
||||||
|
}
|
||||||
|
|
||||||
postForgotPasswordR :: YesodAuthEmail master => HandlerT Auth (HandlerT master IO) TypedContent
|
postForgotPasswordR :: YesodAuthEmail master => HandlerT Auth (HandlerT master IO) TypedContent
|
||||||
postForgotPasswordR = registerHelper True forgotPasswordR
|
postForgotPasswordR = registerHelper True forgotPasswordR
|
||||||
@ -400,7 +479,7 @@ getVerifyR lid key = do
|
|||||||
let msgAv = Msg.AddressVerified
|
let msgAv = Msg.AddressVerified
|
||||||
selectRep $ do
|
selectRep $ do
|
||||||
provideRep $ do
|
provideRep $ do
|
||||||
lift $ setMessageI msgAv
|
lift $ addMessageI "success" msgAv
|
||||||
fmap asHtml $ redirect setpassR
|
fmap asHtml $ redirect setpassR
|
||||||
provideJsonMessage $ mr msgAv
|
provideJsonMessage $ mr msgAv
|
||||||
_ -> invalidKey mr
|
_ -> invalidKey mr
|
||||||
@ -461,40 +540,77 @@ getPasswordR = do
|
|||||||
-- Since: 1.2.6
|
-- Since: 1.2.6
|
||||||
defaultSetPasswordHandler :: YesodAuthEmail master => Bool -> AuthHandler master TypedContent
|
defaultSetPasswordHandler :: YesodAuthEmail master => Bool -> AuthHandler master TypedContent
|
||||||
defaultSetPasswordHandler needOld = do
|
defaultSetPasswordHandler needOld = do
|
||||||
tp <- getRouteToParent
|
messageRender <- lift getMessageRender
|
||||||
pass0 <- newIdent
|
toParent <- getRouteToParent
|
||||||
pass1 <- newIdent
|
|
||||||
pass2 <- newIdent
|
|
||||||
mr <- lift getMessageRender
|
|
||||||
selectRep $ do
|
selectRep $ do
|
||||||
provideJsonMessage $ mr Msg.SetPass
|
provideJsonMessage $ messageRender Msg.SetPass
|
||||||
provideRep $ lift $ authLayout $ do
|
provideRep $ lift $ authLayout $ do
|
||||||
setTitleI Msg.SetPassTitle
|
(widget, enctype) <- liftWidgetT $ generateFormPost $ setPasswordForm needOld
|
||||||
[whamlet|
|
setTitleI Msg.SetPassTitle
|
||||||
$newline never
|
[whamlet|
|
||||||
<h3>_{Msg.SetPass}
|
<h3>_{Msg.SetPass}
|
||||||
<form method="post" action="@{tp setpassR}">
|
<form method="post" action="@{toParent setpassR}">
|
||||||
<table>
|
^{widget}
|
||||||
$if needOld
|
|]
|
||||||
<tr>
|
where
|
||||||
<th>
|
setPasswordForm needOld extra = do
|
||||||
<label for=#{pass0}>Current Password
|
(currentPasswordRes, currentPasswordView) <- mreq passwordField currentPasswordSettings Nothing
|
||||||
<td>
|
(newPasswordRes, newPasswordView) <- mreq passwordField newPasswordSettings Nothing
|
||||||
<input ##{pass0} type="password" name="current" autofocus>
|
(confirmPasswordRes, confirmPasswordView) <- mreq passwordField confirmPasswordSettings Nothing
|
||||||
<tr>
|
|
||||||
<th>
|
let passwordFormRes = PasswordForm <$> currentPasswordRes <*> newPasswordRes <*> confirmPasswordRes
|
||||||
<label for=#{pass1}>_{Msg.NewPass}
|
let widget = do
|
||||||
<td>
|
[whamlet|
|
||||||
<input ##{pass1} type="password" name="new" :not needOld:autofocus>
|
#{extra}
|
||||||
<tr>
|
<table>
|
||||||
<th>
|
$if needOld
|
||||||
<label for=#{pass2}>_{Msg.ConfirmPass}
|
<tr>
|
||||||
<td>
|
<th>
|
||||||
<input ##{pass2} type="password" name="confirm">
|
^{fvLabel currentPasswordView}
|
||||||
<tr>
|
<td>
|
||||||
<td colspan="2">
|
^{fvInput currentPasswordView}
|
||||||
<input type="submit" value=_{Msg.SetPassTitle}>
|
<tr>
|
||||||
|]
|
<th>
|
||||||
|
^{fvLabel newPasswordView}
|
||||||
|
<td>
|
||||||
|
^{fvInput newPasswordView}
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
^{fvLabel confirmPasswordView}
|
||||||
|
<td>
|
||||||
|
^{fvInput confirmPasswordView}
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<input type=submit value=_{Msg.SetPassTitle}>
|
||||||
|
|]
|
||||||
|
|
||||||
|
return (passwordFormRes, widget)
|
||||||
|
currentPasswordSettings =
|
||||||
|
FieldSettings {
|
||||||
|
fsLabel = SomeMessage Msg.CurrentPassword,
|
||||||
|
fsTooltip = Nothing,
|
||||||
|
fsId = Just "currentPassword",
|
||||||
|
fsName = Just "current",
|
||||||
|
fsAttrs = [("autofocus", "")]
|
||||||
|
}
|
||||||
|
newPasswordSettings =
|
||||||
|
FieldSettings {
|
||||||
|
fsLabel = SomeMessage Msg.NewPass,
|
||||||
|
fsTooltip = Nothing,
|
||||||
|
fsId = Just "newPassword",
|
||||||
|
fsName = Just "new",
|
||||||
|
fsAttrs = [("autofocus", ""), (":not", ""), ("needOld:autofocus", "")]
|
||||||
|
}
|
||||||
|
confirmPasswordSettings =
|
||||||
|
FieldSettings {
|
||||||
|
fsLabel = SomeMessage Msg.ConfirmPass,
|
||||||
|
fsTooltip = Nothing,
|
||||||
|
fsId = Just "confirmPassword",
|
||||||
|
fsName = Just "confirm",
|
||||||
|
fsAttrs = [("autofocus", "")]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
postPasswordR :: YesodAuthEmail master => HandlerT Auth (HandlerT master IO) TypedContent
|
postPasswordR :: YesodAuthEmail master => HandlerT Auth (HandlerT master IO) TypedContent
|
||||||
postPasswordR = do
|
postPasswordR = do
|
||||||
@ -534,7 +650,7 @@ postPasswordR = do
|
|||||||
y <- lift $ do
|
y <- lift $ do
|
||||||
setPassword aid salted
|
setPassword aid salted
|
||||||
deleteSession loginLinkKey
|
deleteSession loginLinkKey
|
||||||
setMessageI msgOk
|
addMessageI "success" msgOk
|
||||||
getYesod
|
getYesod
|
||||||
|
|
||||||
mr <- lift getMessageRender
|
mr <- lift getMessageRender
|
||||||
|
|||||||
@ -59,7 +59,7 @@ import Yesod.Core (HandlerSite, HandlerT, MonadHandler,
|
|||||||
lift, liftIO, lookupGetParam,
|
lift, liftIO, lookupGetParam,
|
||||||
lookupSession, notFound, redirect,
|
lookupSession, notFound, redirect,
|
||||||
setSession, whamlet, (.:),
|
setSession, whamlet, (.:),
|
||||||
setMessage, getYesod, authRoute,
|
addMessage, getYesod, authRoute,
|
||||||
toHtml)
|
toHtml)
|
||||||
|
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ authPlugin storeToken clientID clientSecret =
|
|||||||
case err of
|
case err of
|
||||||
"access_denied" -> "Access denied"
|
"access_denied" -> "Access denied"
|
||||||
_ -> "Unknown error occurred: " `T.append` err
|
_ -> "Unknown error occurred: " `T.append` err
|
||||||
setMessage $ toHtml msg
|
addMessage "error" $ toHtml msg
|
||||||
lift $ redirect $ logoutDest master
|
lift $ redirect $ logoutDest master
|
||||||
Just c -> return c
|
Just c -> return c
|
||||||
|
|
||||||
|
|||||||
@ -160,10 +160,13 @@ authHardcoded =
|
|||||||
where
|
where
|
||||||
dispatch "POST" ["login"] = postLoginR >>= sendResponse
|
dispatch "POST" ["login"] = postLoginR >>= sendResponse
|
||||||
dispatch _ _ = notFound
|
dispatch _ _ = notFound
|
||||||
loginWidget toMaster =
|
loginWidget toMaster = do
|
||||||
|
request <- getRequest
|
||||||
[whamlet|
|
[whamlet|
|
||||||
$newline never
|
$newline never
|
||||||
<form method="post" action="@{toMaster loginR}">
|
<form method="post" action="@{toMaster loginR}">
|
||||||
|
$maybe t <- reqToken request
|
||||||
|
<input type=hidden name=#{defaultCsrfParamName} value=#{t}>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>_{Msg.UserName}
|
<th>_{Msg.UserName}
|
||||||
|
|||||||
@ -17,9 +17,10 @@ module Yesod.Auth.Message
|
|||||||
, czechMessage
|
, czechMessage
|
||||||
, russianMessage
|
, russianMessage
|
||||||
, dutchMessage
|
, dutchMessage
|
||||||
|
, danishMessage
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.Monoid (mappend,(<>))
|
import Data.Monoid (mappend, (<>))
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
|
|
||||||
data AuthMessage =
|
data AuthMessage =
|
||||||
@ -60,6 +61,7 @@ data AuthMessage =
|
|||||||
| ProvideIdentifier
|
| ProvideIdentifier
|
||||||
| SendPasswordResetEmail
|
| SendPasswordResetEmail
|
||||||
| PasswordResetPrompt
|
| PasswordResetPrompt
|
||||||
|
| CurrentPassword
|
||||||
| InvalidUsernamePass
|
| InvalidUsernamePass
|
||||||
| Logout
|
| Logout
|
||||||
| LogoutTitle
|
| LogoutTitle
|
||||||
@ -78,6 +80,7 @@ englishMessage LoginYahoo = "Login via Yahoo"
|
|||||||
englishMessage Email = "Email"
|
englishMessage Email = "Email"
|
||||||
englishMessage UserName = "User name"
|
englishMessage UserName = "User name"
|
||||||
englishMessage Password = "Password"
|
englishMessage Password = "Password"
|
||||||
|
englishMessage CurrentPassword = "Current Password"
|
||||||
englishMessage Register = "Register"
|
englishMessage Register = "Register"
|
||||||
englishMessage RegisterLong = "Register a new account"
|
englishMessage RegisterLong = "Register a new account"
|
||||||
englishMessage EnterEmail = "Enter your e-mail address below, and a confirmation e-mail will be sent to you."
|
englishMessage EnterEmail = "Enter your e-mail address below, and a confirmation e-mail will be sent to you."
|
||||||
@ -124,6 +127,7 @@ portugueseMessage LoginYahoo = "Entrar via Yahoo"
|
|||||||
portugueseMessage Email = "E-mail"
|
portugueseMessage Email = "E-mail"
|
||||||
portugueseMessage UserName = "Nome de usuário" -- FIXME by Google Translate "user name"
|
portugueseMessage UserName = "Nome de usuário" -- FIXME by Google Translate "user name"
|
||||||
portugueseMessage Password = "Senha"
|
portugueseMessage Password = "Senha"
|
||||||
|
portugueseMessage CurrentPassword = "Palavra de passe"
|
||||||
portugueseMessage Register = "Registrar"
|
portugueseMessage Register = "Registrar"
|
||||||
portugueseMessage RegisterLong = "Registrar uma nova conta"
|
portugueseMessage RegisterLong = "Registrar uma nova conta"
|
||||||
portugueseMessage EnterEmail = "Por favor digite seu endereço de e-mail abaixo e um e-mail de confirmação será enviado para você."
|
portugueseMessage EnterEmail = "Por favor digite seu endereço de e-mail abaixo e um e-mail de confirmação será enviado para você."
|
||||||
@ -171,6 +175,7 @@ spanishMessage LoginYahoo = "Entrar utilizando Yahoo"
|
|||||||
spanishMessage Email = "Correo electrónico"
|
spanishMessage Email = "Correo electrónico"
|
||||||
spanishMessage UserName = "Nombre de Usuario" -- FIXME by Google Translate "user name"
|
spanishMessage UserName = "Nombre de Usuario" -- FIXME by Google Translate "user name"
|
||||||
spanishMessage Password = "Contraseña"
|
spanishMessage Password = "Contraseña"
|
||||||
|
spanishMessage CurrentPassword = "Contraseña actual"
|
||||||
spanishMessage Register = "Registrarse"
|
spanishMessage Register = "Registrarse"
|
||||||
spanishMessage RegisterLong = "Registrar una nueva cuenta"
|
spanishMessage RegisterLong = "Registrar una nueva cuenta"
|
||||||
spanishMessage EnterEmail = "Coloque su dirección de correo electrónico, y un correo de confirmación le será enviado a su cuenta."
|
spanishMessage EnterEmail = "Coloque su dirección de correo electrónico, y un correo de confirmación le será enviado a su cuenta."
|
||||||
@ -218,6 +223,7 @@ swedishMessage LoginYahoo = "Logga in via Yahoo"
|
|||||||
swedishMessage Email = "Epost"
|
swedishMessage Email = "Epost"
|
||||||
swedishMessage UserName = "Användarnamn" -- FIXME by Google Translate "user name"
|
swedishMessage UserName = "Användarnamn" -- FIXME by Google Translate "user name"
|
||||||
swedishMessage Password = "Lösenord"
|
swedishMessage Password = "Lösenord"
|
||||||
|
swedishMessage CurrentPassword = "Current password"
|
||||||
swedishMessage Register = "Registrera"
|
swedishMessage Register = "Registrera"
|
||||||
swedishMessage RegisterLong = "Registrera ett nytt konto"
|
swedishMessage RegisterLong = "Registrera ett nytt konto"
|
||||||
swedishMessage EnterEmail = "Skriv in din epost nedan så kommer ett konfirmationsmail skickas till adressen."
|
swedishMessage EnterEmail = "Skriv in din epost nedan så kommer ett konfirmationsmail skickas till adressen."
|
||||||
@ -266,6 +272,7 @@ germanMessage LoginYahoo = "Login via Yahoo"
|
|||||||
germanMessage Email = "Email"
|
germanMessage Email = "Email"
|
||||||
germanMessage UserName = "Benutzername" -- FIXME by Google Translate "user name"
|
germanMessage UserName = "Benutzername" -- FIXME by Google Translate "user name"
|
||||||
germanMessage Password = "Passwort"
|
germanMessage Password = "Passwort"
|
||||||
|
germanMessage CurrentPassword = "Aktuelles Passwort"
|
||||||
germanMessage Register = "Registrieren"
|
germanMessage Register = "Registrieren"
|
||||||
germanMessage RegisterLong = "Neuen Account registrieren"
|
germanMessage RegisterLong = "Neuen Account registrieren"
|
||||||
germanMessage EnterEmail = "Bitte die e-Mail Adresse angeben, eine Bestätigungsmail wird verschickt."
|
germanMessage EnterEmail = "Bitte die e-Mail Adresse angeben, eine Bestätigungsmail wird verschickt."
|
||||||
@ -313,6 +320,7 @@ frenchMessage LoginYahoo = "Se connecter avec Yahoo"
|
|||||||
frenchMessage Email = "Adresse électronique"
|
frenchMessage Email = "Adresse électronique"
|
||||||
frenchMessage UserName = "Nom d'utilisateur" -- FIXME by Google Translate "user name"
|
frenchMessage UserName = "Nom d'utilisateur" -- FIXME by Google Translate "user name"
|
||||||
frenchMessage Password = "Mot de passe"
|
frenchMessage Password = "Mot de passe"
|
||||||
|
frenchMessage CurrentPassword = "Mot de passe actuel"
|
||||||
frenchMessage Register = "S'inscrire"
|
frenchMessage Register = "S'inscrire"
|
||||||
frenchMessage RegisterLong = "Créer un compte"
|
frenchMessage RegisterLong = "Créer un compte"
|
||||||
frenchMessage EnterEmail = "Entrez ci-dessous votre adresse électronique, et un message de confirmation vous sera envoyé"
|
frenchMessage EnterEmail = "Entrez ci-dessous votre adresse électronique, et un message de confirmation vous sera envoyé"
|
||||||
@ -359,6 +367,7 @@ norwegianBokmålMessage LoginYahoo = "Logg inn med Yahoo"
|
|||||||
norwegianBokmålMessage Email = "E-post"
|
norwegianBokmålMessage Email = "E-post"
|
||||||
norwegianBokmålMessage UserName = "Brukernavn" -- FIXME by Google Translate "user name"
|
norwegianBokmålMessage UserName = "Brukernavn" -- FIXME by Google Translate "user name"
|
||||||
norwegianBokmålMessage Password = "Passord"
|
norwegianBokmålMessage Password = "Passord"
|
||||||
|
norwegianBokmålMessage CurrentPassword = "Current password"
|
||||||
norwegianBokmålMessage Register = "Registrer"
|
norwegianBokmålMessage Register = "Registrer"
|
||||||
norwegianBokmålMessage RegisterLong = "Registrer en ny konto"
|
norwegianBokmålMessage RegisterLong = "Registrer en ny konto"
|
||||||
norwegianBokmålMessage EnterEmail = "Skriv inn e-postadressen din nedenfor og en e-postkonfirmasjon vil bli sendt."
|
norwegianBokmålMessage EnterEmail = "Skriv inn e-postadressen din nedenfor og en e-postkonfirmasjon vil bli sendt."
|
||||||
@ -406,6 +415,7 @@ japaneseMessage LoginYahoo = "Yahooでログイン"
|
|||||||
japaneseMessage Email = "Eメール"
|
japaneseMessage Email = "Eメール"
|
||||||
japaneseMessage UserName = "ユーザー名" -- FIXME by Google Translate "user name"
|
japaneseMessage UserName = "ユーザー名" -- FIXME by Google Translate "user name"
|
||||||
japaneseMessage Password = "パスワード"
|
japaneseMessage Password = "パスワード"
|
||||||
|
japaneseMessage CurrentPassword = "Current password"
|
||||||
japaneseMessage Register = "登録"
|
japaneseMessage Register = "登録"
|
||||||
japaneseMessage RegisterLong = "新規アカウント登録"
|
japaneseMessage RegisterLong = "新規アカウント登録"
|
||||||
japaneseMessage EnterEmail = "メールアドレスを入力してください。確認メールが送られます"
|
japaneseMessage EnterEmail = "メールアドレスを入力してください。確認メールが送られます"
|
||||||
@ -453,6 +463,7 @@ finnishMessage LoginYahoo = "Kirjaudu Yahoo-tilillä"
|
|||||||
finnishMessage Email = "Sähköposti"
|
finnishMessage Email = "Sähköposti"
|
||||||
finnishMessage UserName = "Käyttäjätunnus" -- FIXME by Google Translate "user name"
|
finnishMessage UserName = "Käyttäjätunnus" -- FIXME by Google Translate "user name"
|
||||||
finnishMessage Password = "Salasana"
|
finnishMessage Password = "Salasana"
|
||||||
|
finnishMessage Password = "Current password"
|
||||||
finnishMessage Register = "Luo uusi"
|
finnishMessage Register = "Luo uusi"
|
||||||
finnishMessage RegisterLong = "Luo uusi tili"
|
finnishMessage RegisterLong = "Luo uusi tili"
|
||||||
finnishMessage EnterEmail = "Kirjoita alle sähköpostiosoitteesi, johon vahvistussähköposti lähetetään."
|
finnishMessage EnterEmail = "Kirjoita alle sähköpostiosoitteesi, johon vahvistussähköposti lähetetään."
|
||||||
@ -501,6 +512,7 @@ chineseMessage LoginYahoo = "用Yahoo帐户登录"
|
|||||||
chineseMessage Email = "邮箱"
|
chineseMessage Email = "邮箱"
|
||||||
chineseMessage UserName = "用户名" -- FIXME by Google Translate "user name"
|
chineseMessage UserName = "用户名" -- FIXME by Google Translate "user name"
|
||||||
chineseMessage Password = "密码"
|
chineseMessage Password = "密码"
|
||||||
|
chineseMessage CurrentPassword = "Current password"
|
||||||
chineseMessage Register = "注册"
|
chineseMessage Register = "注册"
|
||||||
chineseMessage RegisterLong = "注册新帐户"
|
chineseMessage RegisterLong = "注册新帐户"
|
||||||
chineseMessage EnterEmail = "输入你的邮箱地址,你将收到一封确认邮件。"
|
chineseMessage EnterEmail = "输入你的邮箱地址,你将收到一封确认邮件。"
|
||||||
@ -548,6 +560,7 @@ czechMessage LoginYahoo = "Přihlásit přes Yahoo"
|
|||||||
czechMessage Email = "E-mail"
|
czechMessage Email = "E-mail"
|
||||||
czechMessage UserName = "Uživatelské jméno"
|
czechMessage UserName = "Uživatelské jméno"
|
||||||
czechMessage Password = "Heslo"
|
czechMessage Password = "Heslo"
|
||||||
|
czechMessage CurrentPassword = "Current password"
|
||||||
czechMessage Register = "Registrovat"
|
czechMessage Register = "Registrovat"
|
||||||
czechMessage RegisterLong = "Zaregistrovat nový účet"
|
czechMessage RegisterLong = "Zaregistrovat nový účet"
|
||||||
czechMessage EnterEmail = "Níže zadejte svou e-mailovou adresu a bude vám poslán potvrzovací e-mail."
|
czechMessage EnterEmail = "Níže zadejte svou e-mailovou adresu a bude vám poslán potvrzovací e-mail."
|
||||||
@ -595,6 +608,7 @@ russianMessage LoginYahoo = "Вход с помощью Yahoo"
|
|||||||
russianMessage Email = "Эл.почта"
|
russianMessage Email = "Эл.почта"
|
||||||
russianMessage UserName = "Имя пользователя"
|
russianMessage UserName = "Имя пользователя"
|
||||||
russianMessage Password = "Пароль"
|
russianMessage Password = "Пароль"
|
||||||
|
russianMessage CurrentPassword = "Current password"
|
||||||
russianMessage Register = "Регистрация"
|
russianMessage Register = "Регистрация"
|
||||||
russianMessage RegisterLong = "Создать учётную запись"
|
russianMessage RegisterLong = "Создать учётную запись"
|
||||||
russianMessage EnterEmail = "Введите свой адрес эл.почты ниже, вам будет отправлено письмо для подтверждения."
|
russianMessage EnterEmail = "Введите свой адрес эл.почты ниже, вам будет отправлено письмо для подтверждения."
|
||||||
@ -611,7 +625,7 @@ russianMessage BadSetPass = "Чтобы изменить пароль, необ
|
|||||||
russianMessage SetPassTitle = "Установить пароль"
|
russianMessage SetPassTitle = "Установить пароль"
|
||||||
russianMessage SetPass = "Установить новый пароль"
|
russianMessage SetPass = "Установить новый пароль"
|
||||||
russianMessage NewPass = "Новый пароль"
|
russianMessage NewPass = "Новый пароль"
|
||||||
russianMessage ConfirmPass = "Подтверждение"
|
russianMessage ConfirmPass = "Подтверждение пароля"
|
||||||
russianMessage PassMismatch = "Пароли не совпадают, повторите снова"
|
russianMessage PassMismatch = "Пароли не совпадают, повторите снова"
|
||||||
russianMessage PassUpdated = "Пароль обновлён"
|
russianMessage PassUpdated = "Пароль обновлён"
|
||||||
russianMessage Facebook = "Войти с помощью Facebook"
|
russianMessage Facebook = "Войти с помощью Facebook"
|
||||||
@ -641,6 +655,7 @@ dutchMessage LoginYahoo = "Inloggen via Yahoo"
|
|||||||
dutchMessage Email = "E-mail"
|
dutchMessage Email = "E-mail"
|
||||||
dutchMessage UserName = "Gebruikersnaam" -- FIXME by Google Translate "user name"
|
dutchMessage UserName = "Gebruikersnaam" -- FIXME by Google Translate "user name"
|
||||||
dutchMessage Password = "Wachtwoord"
|
dutchMessage Password = "Wachtwoord"
|
||||||
|
dutchMessage CurrentPassword = "Current password"
|
||||||
dutchMessage Register = "Registreren"
|
dutchMessage Register = "Registreren"
|
||||||
dutchMessage RegisterLong = "Registreer een nieuw account"
|
dutchMessage RegisterLong = "Registreer een nieuw account"
|
||||||
dutchMessage EnterEmail = "Voer uw e-mailadres hieronder in, er zal een bevestigings-e-mail naar u worden verzonden."
|
dutchMessage EnterEmail = "Voer uw e-mailadres hieronder in, er zal een bevestigings-e-mail naar u worden verzonden."
|
||||||
@ -680,44 +695,92 @@ dutchMessage LogoutTitle = "Log Out" -- FIXME NOT TRANSLATED
|
|||||||
dutchMessage AuthError = "Verificatiefout" -- FIXME by Google Translate
|
dutchMessage AuthError = "Verificatiefout" -- FIXME by Google Translate
|
||||||
|
|
||||||
croatianMessage :: AuthMessage -> Text
|
croatianMessage :: AuthMessage -> Text
|
||||||
croatianMessage NoOpenID = "Nije pronađen OpenID identifikator"
|
croatianMessage NoOpenID = "Nije pronađen OpenID identifikator"
|
||||||
croatianMessage LoginOpenID = "Prijava uz OpenID"
|
croatianMessage LoginOpenID = "Prijava uz OpenID"
|
||||||
croatianMessage LoginGoogle = "Prijava uz Google"
|
croatianMessage LoginGoogle = "Prijava uz Google"
|
||||||
croatianMessage LoginYahoo = "Prijava uz Yahoo"
|
croatianMessage LoginYahoo = "Prijava uz Yahoo"
|
||||||
croatianMessage Facebook = "Prijava uz Facebook"
|
croatianMessage Facebook = "Prijava uz Facebook"
|
||||||
croatianMessage LoginViaEmail = "Prijava putem e-pošte"
|
croatianMessage LoginViaEmail = "Prijava putem e-pošte"
|
||||||
croatianMessage Email = "E-pošta"
|
croatianMessage Email = "E-pošta"
|
||||||
croatianMessage UserName = "Korisničko ime"
|
croatianMessage UserName = "Korisničko ime"
|
||||||
croatianMessage Password = "Lozinka"
|
croatianMessage Password = "Lozinka"
|
||||||
croatianMessage Register = "Registracija"
|
croatianMessage CurrentPassword = "Current Password"
|
||||||
croatianMessage RegisterLong = "Registracija novog računa"
|
croatianMessage Register = "Registracija"
|
||||||
croatianMessage EnterEmail = "Dolje unesite adresu e-pošte, pa ćemo vam poslati e-poruku za potvrdu."
|
croatianMessage RegisterLong = "Registracija novog računa"
|
||||||
|
croatianMessage EnterEmail = "Dolje unesite adresu e-pošte, pa ćemo vam poslati e-poruku za potvrdu."
|
||||||
croatianMessage PasswordResetPrompt = "Dolje unesite adresu e-pošte ili korisničko ime, pa ćemo vam poslati e-poruku za potvrdu."
|
croatianMessage PasswordResetPrompt = "Dolje unesite adresu e-pošte ili korisničko ime, pa ćemo vam poslati e-poruku za potvrdu."
|
||||||
croatianMessage ConfirmationEmailSentTitle = "E-poruka za potvrdu"
|
croatianMessage ConfirmationEmailSentTitle = "E-poruka za potvrdu"
|
||||||
croatianMessage (ConfirmationEmailSent email) = "E-poruka za potvrdu poslana je na adresu " <> email <> "."
|
croatianMessage (ConfirmationEmailSent email) = "E-poruka za potvrdu poslana je na adresu " <> email <> "."
|
||||||
croatianMessage AddressVerified = "Adresa ovjerena, postavite novu lozinku"
|
croatianMessage AddressVerified = "Adresa ovjerena, postavite novu lozinku"
|
||||||
croatianMessage InvalidKeyTitle = "Ključ za ovjeru nije valjan"
|
croatianMessage InvalidKeyTitle = "Ključ za ovjeru nije valjan"
|
||||||
croatianMessage InvalidKey = "Nažalost, taj ključ za ovjeru nije valjan."
|
croatianMessage InvalidKey = "Nažalost, taj ključ za ovjeru nije valjan."
|
||||||
croatianMessage InvalidEmailPass = "Kombinacija e-pošte i lozinke nije valjana"
|
croatianMessage InvalidEmailPass = "Kombinacija e-pošte i lozinke nije valjana"
|
||||||
croatianMessage InvalidUsernamePass = "Kombinacija korisničkog imena i lozinke nije valjana"
|
croatianMessage InvalidUsernamePass = "Kombinacija korisničkog imena i lozinke nije valjana"
|
||||||
croatianMessage BadSetPass = "Za postavljanje lozinke morate biti prijavljeni"
|
croatianMessage BadSetPass = "Za postavljanje lozinke morate biti prijavljeni"
|
||||||
croatianMessage SetPassTitle = "Postavi lozinku"
|
croatianMessage SetPassTitle = "Postavi lozinku"
|
||||||
croatianMessage SetPass = "Postavite novu lozinku"
|
croatianMessage SetPass = "Postavite novu lozinku"
|
||||||
croatianMessage NewPass = "Nova lozinka"
|
croatianMessage NewPass = "Nova lozinka"
|
||||||
croatianMessage ConfirmPass = "Potvrda lozinke"
|
croatianMessage ConfirmPass = "Potvrda lozinke"
|
||||||
croatianMessage PassMismatch = "Lozinke se ne podudaraju, pokušajte ponovo"
|
croatianMessage PassMismatch = "Lozinke se ne podudaraju, pokušajte ponovo"
|
||||||
croatianMessage PassUpdated = "Lozinka ažurirana"
|
croatianMessage PassUpdated = "Lozinka ažurirana"
|
||||||
croatianMessage InvalidLogin = "Prijava nije valjana"
|
croatianMessage InvalidLogin = "Prijava nije valjana"
|
||||||
croatianMessage NowLoggedIn = "Sada ste prijavljeni u"
|
croatianMessage NowLoggedIn = "Sada ste prijavljeni u"
|
||||||
croatianMessage LoginTitle = "Prijava"
|
croatianMessage LoginTitle = "Prijava"
|
||||||
croatianMessage PleaseProvideUsername = "Unesite korisničko ime"
|
croatianMessage PleaseProvideUsername = "Unesite korisničko ime"
|
||||||
croatianMessage PleaseProvidePassword = "Unesite lozinku"
|
croatianMessage PleaseProvidePassword = "Unesite lozinku"
|
||||||
croatianMessage NoIdentifierProvided = "Nisu dani e-pošta/korisničko ime"
|
croatianMessage NoIdentifierProvided = "Nisu dani e-pošta/korisničko ime"
|
||||||
croatianMessage InvalidEmailAddress = "Dana adresa e-pošte nije valjana"
|
croatianMessage InvalidEmailAddress = "Dana adresa e-pošte nije valjana"
|
||||||
croatianMessage PasswordResetTitle = "Poništavanje lozinke"
|
croatianMessage PasswordResetTitle = "Poništavanje lozinke"
|
||||||
croatianMessage ProvideIdentifier = "E-pošta ili korisničko ime"
|
croatianMessage ProvideIdentifier = "E-pošta ili korisničko ime"
|
||||||
croatianMessage SendPasswordResetEmail = "Pošalji e-poruku za poništavanje lozinke"
|
croatianMessage SendPasswordResetEmail = "Pošalji e-poruku za poništavanje lozinke"
|
||||||
croatianMessage (IdentifierNotFound ident) = "Korisničko ime/e-pošta nisu pronađeni: " <> ident
|
croatianMessage (IdentifierNotFound ident) = "Korisničko ime/e-pošta nisu pronađeni: " <> ident
|
||||||
croatianMessage Logout = "Odjava"
|
croatianMessage Logout = "Odjava"
|
||||||
croatianMessage LogoutTitle = "Odjava"
|
croatianMessage LogoutTitle = "Odjava"
|
||||||
croatianMessage AuthError = "Pogreška provjere autentičnosti"
|
croatianMessage AuthError = "Pogreška provjere autentičnosti"
|
||||||
|
|
||||||
|
danishMessage :: AuthMessage -> Text
|
||||||
|
danishMessage NoOpenID = "Mangler OpenID identifier"
|
||||||
|
danishMessage LoginOpenID = "Login med OpenID"
|
||||||
|
danishMessage LoginGoogle = "Login med Google"
|
||||||
|
danishMessage LoginYahoo = "Login med Yahoo"
|
||||||
|
danishMessage Email = "E-mail"
|
||||||
|
danishMessage UserName = "Brugernavn"
|
||||||
|
danishMessage Password = "Kodeord"
|
||||||
|
danishMessage CurrentPassword = "Nuværende kodeord"
|
||||||
|
danishMessage Register = "Opret"
|
||||||
|
danishMessage RegisterLong = "Opret en ny konto"
|
||||||
|
danishMessage EnterEmail = "Indtast din e-mailadresse nedenfor og en bekræftelsesmail vil blive sendt til dig."
|
||||||
|
danishMessage ConfirmationEmailSentTitle = "Bekræftelsesmail sendt"
|
||||||
|
danishMessage (ConfirmationEmailSent email) =
|
||||||
|
"En bekræftelsesmail er sendt til " `mappend`
|
||||||
|
email `mappend`
|
||||||
|
"."
|
||||||
|
danishMessage AddressVerified = "Adresse bekræftet, sæt venligst et nyt kodeord"
|
||||||
|
danishMessage InvalidKeyTitle = "Ugyldig verifikationsnøgle"
|
||||||
|
danishMessage InvalidKey = "Beklager, det var en ugyldigt verifikationsnøgle."
|
||||||
|
danishMessage InvalidEmailPass = "Ugyldigt e-mail/kodeord"
|
||||||
|
danishMessage BadSetPass = "Du skal være logget ind for at sætte et kodeord"
|
||||||
|
danishMessage SetPassTitle = "Sæt kodeord"
|
||||||
|
danishMessage SetPass = "Sæt et nyt kodeord"
|
||||||
|
danishMessage NewPass = "Nyt kodeord"
|
||||||
|
danishMessage ConfirmPass = "Bekræft"
|
||||||
|
danishMessage PassMismatch = "Kodeordne var forskellige, prøv venligst igen"
|
||||||
|
danishMessage PassUpdated = "Kodeord opdateret"
|
||||||
|
danishMessage Facebook = "Login med Facebook"
|
||||||
|
danishMessage LoginViaEmail = "Login med e-mail"
|
||||||
|
danishMessage InvalidLogin = "Ugyldigt login"
|
||||||
|
danishMessage NowLoggedIn = "Du er nu logget ind"
|
||||||
|
danishMessage LoginTitle = "Log ind"
|
||||||
|
danishMessage PleaseProvideUsername = "Indtast venligst dit brugernavn"
|
||||||
|
danishMessage PleaseProvidePassword = "Indtasy venligst dit kodeord"
|
||||||
|
danishMessage NoIdentifierProvided = "Mangler e-mail/username"
|
||||||
|
danishMessage InvalidEmailAddress = "Ugyldig e-mailadresse indtastet"
|
||||||
|
danishMessage PasswordResetTitle = "Nulstilning af kodeord"
|
||||||
|
danishMessage ProvideIdentifier = "E-mail eller brugernavn"
|
||||||
|
danishMessage SendPasswordResetEmail = "Send kodeordsnulstillingsmail"
|
||||||
|
danishMessage PasswordResetPrompt = "Indtast din e-mailadresse eller dit brugernavn nedenfor, så bliver en kodeordsnulstilningsmail sendt til dig."
|
||||||
|
danishMessage InvalidUsernamePass = "Ugyldigt brugernavn/kodeord"
|
||||||
|
danishMessage (IdentifierNotFound ident) = "Brugernavn findes ikke: " `mappend` ident
|
||||||
|
danishMessage Logout = "Log ud"
|
||||||
|
danishMessage LogoutTitle = "Log ud"
|
||||||
|
danishMessage AuthError = "Fejl ved bekræftelse af identitet"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod-auth
|
name: yesod-auth
|
||||||
version: 1.4.12
|
version: 1.4.13
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman, Patrick Brisbin
|
author: Michael Snoyman, Patrick Brisbin
|
||||||
@ -23,7 +23,7 @@ library
|
|||||||
build-depends: base >= 4 && < 5
|
build-depends: base >= 4 && < 5
|
||||||
, authenticate >= 1.3
|
, authenticate >= 1.3
|
||||||
, bytestring >= 0.9.1.4
|
, bytestring >= 0.9.1.4
|
||||||
, yesod-core >= 1.4 && < 1.5
|
, yesod-core >= 1.4.20 && < 1.5
|
||||||
, wai >= 1.4
|
, wai >= 1.4
|
||||||
, template-haskell
|
, template-haskell
|
||||||
, base16-bytestring
|
, base16-bytestring
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
## 1.4.18
|
||||||
|
|
||||||
|
* Disable `yesod test` when using Stack [#1198](https://github.com/yesodweb/yesod/issues/1198)
|
||||||
|
|
||||||
## 1.4.17
|
## 1.4.17
|
||||||
|
|
||||||
* Fully remove the `yesod init` command
|
* Fully remove the `yesod init` command
|
||||||
|
|||||||
@ -6,11 +6,12 @@ module Keter
|
|||||||
import Data.Yaml
|
import Data.Yaml
|
||||||
import qualified Data.HashMap.Strict as Map
|
import qualified Data.HashMap.Strict as Map
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
import System.Environment (getEnvironment)
|
||||||
import System.Exit
|
import System.Exit
|
||||||
import System.Process
|
import System.Process
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import System.Directory hiding (findFiles)
|
import System.Directory hiding (findFiles)
|
||||||
import Data.Maybe (mapMaybe)
|
import Data.Maybe (mapMaybe,isJust,maybeToList)
|
||||||
import Data.Monoid
|
import Data.Monoid
|
||||||
import System.FilePath ((</>))
|
import System.FilePath ((</>))
|
||||||
import qualified Codec.Archive.Tar as Tar
|
import qualified Codec.Archive.Tar as Tar
|
||||||
@ -48,6 +49,8 @@ keter cabal noBuild noCopyTo buildArgs = do
|
|||||||
_ -> return value
|
_ -> return value
|
||||||
Just _ -> error $ ketercfg ++ " is not an object"
|
Just _ -> error $ ketercfg ++ " is not an object"
|
||||||
|
|
||||||
|
env' <- getEnvironment
|
||||||
|
cwd' <- getCurrentDirectory
|
||||||
files <- getDirectoryContents "."
|
files <- getDirectoryContents "."
|
||||||
project <-
|
project <-
|
||||||
case mapMaybe (T.stripSuffix ".cabal" . T.pack) files of
|
case mapMaybe (T.stripSuffix ".cabal" . T.pack) files of
|
||||||
@ -74,15 +77,27 @@ keter cabal noBuild noCopyTo buildArgs = do
|
|||||||
collapse' (x:xs) = x : collapse' xs
|
collapse' (x:xs) = x : collapse' xs
|
||||||
collapse' [] = []
|
collapse' [] = []
|
||||||
|
|
||||||
unless noBuild $ if elem "stack.yaml" files
|
unless noBuild $ do
|
||||||
then do run "stack" ["clean"]
|
stackQueryRunSuccess <- do
|
||||||
createDirectoryIfMissing True "./dist/bin"
|
(ec,_,_) <- readProcessWithExitCode "stack" ["query"] ""
|
||||||
run "stack"
|
return (ec == ExitSuccess)
|
||||||
((words "--local-bin-path ./dist/bin build --copy-bins")
|
|
||||||
<> buildArgs)
|
let inStackExec = isJust $ lookup "STACK_EXE" env'
|
||||||
else do run cabal ["clean"]
|
mStackYaml = lookup "STACK_YAML" env'
|
||||||
run cabal ["configure"]
|
useStack = inStackExec || isJust mStackYaml || stackQueryRunSuccess
|
||||||
run cabal ("build" : buildArgs)
|
|
||||||
|
if useStack
|
||||||
|
then do let stackYaml = maybeToList $ fmap ("--stack-yaml="<>) mStackYaml
|
||||||
|
localBinPath = cwd' </> "dist/bin"
|
||||||
|
run "stack" $ stackYaml <> ["clean"]
|
||||||
|
createDirectoryIfMissing True localBinPath
|
||||||
|
run "stack"
|
||||||
|
(stackYaml
|
||||||
|
<> ["--local-bin-path",localBinPath,"build","--copy-bins"]
|
||||||
|
<> buildArgs)
|
||||||
|
else do run cabal ["clean"]
|
||||||
|
run cabal ["configure"]
|
||||||
|
run cabal ("build" : buildArgs)
|
||||||
|
|
||||||
_ <- try' $ removeDirectoryRecursive "static/tmp"
|
_ <- try' $ removeDirectoryRecursive "static/tmp"
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import Data.Monoid
|
|||||||
import Data.Version (showVersion)
|
import Data.Version (showVersion)
|
||||||
import Options.Applicative
|
import Options.Applicative
|
||||||
import System.Environment (getEnvironment)
|
import System.Environment (getEnvironment)
|
||||||
import System.Exit (ExitCode (ExitSuccess), exitWith)
|
import System.Exit (ExitCode (ExitSuccess), exitWith, exitFailure)
|
||||||
import System.FilePath (splitSearchPath)
|
import System.FilePath (splitSearchPath)
|
||||||
import System.Process (rawSystem)
|
import System.Process (rawSystem)
|
||||||
|
|
||||||
@ -15,6 +15,7 @@ import Devel (DevelOpts (..), devel, DevelTermOpt(..)
|
|||||||
import Keter (keter)
|
import Keter (keter)
|
||||||
import Options (injectDefaults)
|
import Options (injectDefaults)
|
||||||
import qualified Paths_yesod_bin
|
import qualified Paths_yesod_bin
|
||||||
|
import System.IO (hPutStrLn, stderr)
|
||||||
|
|
||||||
import HsFile (mkHsFile)
|
import HsFile (mkHsFile)
|
||||||
#ifndef WINDOWS
|
#ifndef WINDOWS
|
||||||
@ -130,10 +131,18 @@ main = do
|
|||||||
}
|
}
|
||||||
devel develOpts develExtraArgs
|
devel develOpts develExtraArgs
|
||||||
where
|
where
|
||||||
cabalTest cabal = do touch'
|
cabalTest cabal = do
|
||||||
_ <- cabal ["configure", "--enable-tests", "-flibrary-only"]
|
env <- getEnvironment
|
||||||
_ <- cabal ["build"]
|
case lookup "STACK_EXE" env of
|
||||||
cabal ["test"]
|
Nothing -> do
|
||||||
|
touch'
|
||||||
|
_ <- cabal ["configure", "--enable-tests", "-flibrary-only"]
|
||||||
|
_ <- cabal ["build"]
|
||||||
|
cabal ["test"]
|
||||||
|
Just _ -> do
|
||||||
|
hPutStrLn stderr "'yesod test' is no longer needed with Stack"
|
||||||
|
hPutStrLn stderr "Instead, please just run 'stack test'"
|
||||||
|
exitFailure
|
||||||
|
|
||||||
handleGhcPackagePath :: IO ([String], Maybe [(String, String)])
|
handleGhcPackagePath :: IO ([String], Maybe [(String, String)])
|
||||||
handleGhcPackagePath = do
|
handleGhcPackagePath = do
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod-bin
|
name: yesod-bin
|
||||||
version: 1.4.17.1
|
version: 1.4.18
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman <michael@snoyman.com>
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
|
|||||||
@ -1,3 +1,15 @@
|
|||||||
|
## 1.4.20.1
|
||||||
|
|
||||||
|
* Log a warning when a CSRF error occurs [#1200](https://github.com/yesodweb/yesod/pull/1200)
|
||||||
|
|
||||||
|
## 1.4.20
|
||||||
|
|
||||||
|
* `addMessage`, `addMessageI`, and `getMessages` functions
|
||||||
|
|
||||||
|
## 1.4.19.1
|
||||||
|
|
||||||
|
* Allow lines of dashes in route files [#1182](https://github.com/yesodweb/yesod/pull/1182)
|
||||||
|
|
||||||
## 1.4.19
|
## 1.4.19
|
||||||
|
|
||||||
* Auth logout not working with defaultCsrfMiddleware [#1151](https://github.com/yesodweb/yesod/issues/1151)
|
* Auth logout not working with defaultCsrfMiddleware [#1151](https://github.com/yesodweb/yesod/issues/1151)
|
||||||
|
|||||||
@ -87,7 +87,7 @@ class RenderRoute site => Yesod site where
|
|||||||
defaultLayout :: WidgetT site IO () -> HandlerT site IO Html
|
defaultLayout :: WidgetT site IO () -> HandlerT site IO Html
|
||||||
defaultLayout w = do
|
defaultLayout w = do
|
||||||
p <- widgetToPageContent w
|
p <- widgetToPageContent w
|
||||||
mmsg <- getMessage
|
msgs <- getMessages
|
||||||
withUrlRenderer [hamlet|
|
withUrlRenderer [hamlet|
|
||||||
$newline never
|
$newline never
|
||||||
$doctype 5
|
$doctype 5
|
||||||
@ -96,8 +96,8 @@ class RenderRoute site => Yesod site where
|
|||||||
<title>#{pageTitle p}
|
<title>#{pageTitle p}
|
||||||
^{pageHead p}
|
^{pageHead p}
|
||||||
<body>
|
<body>
|
||||||
$maybe msg <- mmsg
|
$forall (status, msg) <- msgs
|
||||||
<p .message>#{msg}
|
<p class="message #{status}">#{msg}
|
||||||
^{pageBody p}
|
^{pageBody p}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
|||||||
@ -136,6 +136,9 @@ module Yesod.Core.Handler
|
|||||||
, redirectUltDest
|
, redirectUltDest
|
||||||
, clearUltDest
|
, clearUltDest
|
||||||
-- ** Messages
|
-- ** Messages
|
||||||
|
, addMessage
|
||||||
|
, addMessageI
|
||||||
|
, getMessages
|
||||||
, setMessage
|
, setMessage
|
||||||
, setMessageI
|
, setMessageI
|
||||||
, getMessage
|
, getMessage
|
||||||
@ -205,7 +208,7 @@ import qualified Data.Text as T
|
|||||||
import Data.Text.Encoding (decodeUtf8With, encodeUtf8)
|
import Data.Text.Encoding (decodeUtf8With, encodeUtf8)
|
||||||
import Data.Text.Encoding.Error (lenientDecode)
|
import Data.Text.Encoding.Error (lenientDecode)
|
||||||
import qualified Data.Text.Lazy as TL
|
import qualified Data.Text.Lazy as TL
|
||||||
import qualified Text.Blaze.Html.Renderer.Text as RenderText
|
import Text.Blaze.Html.Renderer.Utf8 (renderHtml)
|
||||||
import Text.Hamlet (Html, HtmlUrl, hamlet)
|
import Text.Hamlet (Html, HtmlUrl, hamlet)
|
||||||
|
|
||||||
import qualified Data.ByteString as S
|
import qualified Data.ByteString as S
|
||||||
@ -223,7 +226,7 @@ import Text.Shakespeare.I18N (RenderMessage (..))
|
|||||||
import Web.Cookie (SetCookie (..))
|
import Web.Cookie (SetCookie (..))
|
||||||
import Yesod.Core.Content (ToTypedContent (..), simpleContentType, contentTypeTypes, HasContentType (..), ToContent (..), ToFlushBuilder (..))
|
import Yesod.Core.Content (ToTypedContent (..), simpleContentType, contentTypeTypes, HasContentType (..), ToContent (..), ToFlushBuilder (..))
|
||||||
import Yesod.Core.Internal.Util (formatRFC1123)
|
import Yesod.Core.Internal.Util (formatRFC1123)
|
||||||
import Text.Blaze.Html (preEscapedToMarkup, toHtml)
|
import Text.Blaze.Html (preEscapedToHtml, toHtml)
|
||||||
|
|
||||||
import qualified Data.IORef.Lifted as I
|
import qualified Data.IORef.Lifted as I
|
||||||
import Data.Maybe (listToMaybe, mapMaybe)
|
import Data.Maybe (listToMaybe, mapMaybe)
|
||||||
@ -249,6 +252,7 @@ import qualified Yesod.Core.TypeCache as Cache
|
|||||||
import qualified Data.Word8 as W8
|
import qualified Data.Word8 as W8
|
||||||
import qualified Data.Foldable as Fold
|
import qualified Data.Foldable as Fold
|
||||||
import Data.Default
|
import Data.Default
|
||||||
|
import Control.Monad.Logger (MonadLogger, logWarnS)
|
||||||
|
|
||||||
get :: MonadHandler m => m GHState
|
get :: MonadHandler m => m GHState
|
||||||
get = liftHandlerT $ HandlerT $ I.readIORef . handlerState
|
get = liftHandlerT $ HandlerT $ I.readIORef . handlerState
|
||||||
@ -521,30 +525,66 @@ clearUltDest = deleteSession ultDestKey
|
|||||||
msgKey :: Text
|
msgKey :: Text
|
||||||
msgKey = "_MSG"
|
msgKey = "_MSG"
|
||||||
|
|
||||||
-- | Sets a message in the user's session.
|
-- | Adds a status and message in the user's session.
|
||||||
--
|
--
|
||||||
-- See 'getMessage'.
|
-- See 'getMessages'.
|
||||||
setMessage :: MonadHandler m => Html -> m ()
|
--
|
||||||
setMessage = setSession msgKey . T.concat . TL.toChunks . RenderText.renderHtml
|
-- @since 1.4.20
|
||||||
|
addMessage :: MonadHandler m
|
||||||
|
=> Text -- ^ status
|
||||||
|
-> Html -- ^ message
|
||||||
|
-> m ()
|
||||||
|
addMessage status msg = do
|
||||||
|
val <- lookupSessionBS msgKey
|
||||||
|
setSessionBS msgKey $ addMsg val
|
||||||
|
where
|
||||||
|
addMsg = maybe msg' (S.append msg' . S.cons W8._nul)
|
||||||
|
msg' = S.append
|
||||||
|
(encodeUtf8 status)
|
||||||
|
(W8._nul `S.cons` (L.toStrict $ renderHtml msg))
|
||||||
|
|
||||||
-- | Sets a message in the user's session.
|
-- | Adds a message in the user's session but uses RenderMessage to allow for i18n
|
||||||
--
|
--
|
||||||
-- See 'getMessage'.
|
-- See 'getMessages'.
|
||||||
|
--
|
||||||
|
-- @since 1.4.20
|
||||||
|
addMessageI :: (MonadHandler m, RenderMessage (HandlerSite m) msg)
|
||||||
|
=> Text -> msg -> m ()
|
||||||
|
addMessageI status msg = do
|
||||||
|
mr <- getMessageRender
|
||||||
|
addMessage status $ toHtml $ mr msg
|
||||||
|
|
||||||
|
-- | Gets all messages in the user's session, and then clears the variable.
|
||||||
|
--
|
||||||
|
-- See 'addMessage'.
|
||||||
|
--
|
||||||
|
-- @since 1.4.20
|
||||||
|
getMessages :: MonadHandler m => m [(Text, Html)]
|
||||||
|
getMessages = do
|
||||||
|
bs <- lookupSessionBS msgKey
|
||||||
|
let ms = maybe [] enlist bs
|
||||||
|
deleteSession msgKey
|
||||||
|
return ms
|
||||||
|
where
|
||||||
|
enlist = pairup . S.split W8._nul
|
||||||
|
pairup [] = []
|
||||||
|
pairup [x] = []
|
||||||
|
pairup (s:v:xs) = (decode s, preEscapedToHtml (decode v)) : pairup xs
|
||||||
|
decode = decodeUtf8With lenientDecode
|
||||||
|
|
||||||
|
-- | Calls 'addMessage' with an empty status
|
||||||
|
setMessage :: MonadHandler m => Html -> m ()
|
||||||
|
setMessage = addMessage ""
|
||||||
|
|
||||||
|
-- | Calls 'addMessageI' with an empty status
|
||||||
setMessageI :: (MonadHandler m, RenderMessage (HandlerSite m) msg)
|
setMessageI :: (MonadHandler m, RenderMessage (HandlerSite m) msg)
|
||||||
=> msg -> m ()
|
=> msg -> m ()
|
||||||
setMessageI msg = do
|
setMessageI = addMessageI ""
|
||||||
mr <- getMessageRender
|
|
||||||
setMessage $ toHtml $ mr msg
|
|
||||||
|
|
||||||
-- | Gets the message in the user's session, if available, and then clears the
|
-- | Gets just the last message in the user's session,
|
||||||
-- variable.
|
-- discards the rest and the status
|
||||||
--
|
|
||||||
-- See 'setMessage'.
|
|
||||||
getMessage :: MonadHandler m => m (Maybe Html)
|
getMessage :: MonadHandler m => m (Maybe Html)
|
||||||
getMessage = do
|
getMessage = (return . fmap snd . headMay) =<< getMessages
|
||||||
mmsg <- liftM (fmap preEscapedToMarkup) $ lookupSession msgKey
|
|
||||||
deleteSession msgKey
|
|
||||||
return mmsg
|
|
||||||
|
|
||||||
-- | Bypass remaining handler code and output the given file.
|
-- | Bypass remaining handler code and output the given file.
|
||||||
--
|
--
|
||||||
@ -580,6 +620,8 @@ sendResponseStatus s = handlerError . HCContent s . toTypedContent
|
|||||||
|
|
||||||
-- | Bypass remaining handler code and output the given JSON with the given
|
-- | Bypass remaining handler code and output the given JSON with the given
|
||||||
-- status code.
|
-- status code.
|
||||||
|
--
|
||||||
|
-- Since 1.4.18
|
||||||
sendStatusJSON :: (MonadHandler m, ToJSON c) => H.Status -> c -> m a
|
sendStatusJSON :: (MonadHandler m, ToJSON c) => H.Status -> c -> m a
|
||||||
sendStatusJSON s v = sendResponseStatus s (toJSON v)
|
sendStatusJSON s v = sendResponseStatus s (toJSON v)
|
||||||
|
|
||||||
@ -1398,14 +1440,16 @@ hasValidCsrfParamNamed paramName = do
|
|||||||
-- If the value doesn't match the token stored in the session, this function throws a 'PermissionDenied' error.
|
-- If the value doesn't match the token stored in the session, this function throws a 'PermissionDenied' error.
|
||||||
--
|
--
|
||||||
-- Since 1.4.14
|
-- Since 1.4.14
|
||||||
checkCsrfHeaderOrParam :: MonadHandler m
|
checkCsrfHeaderOrParam :: (MonadHandler m, MonadLogger m)
|
||||||
=> CI S8.ByteString -- ^ The header name to lookup the CSRF token
|
=> CI S8.ByteString -- ^ The header name to lookup the CSRF token
|
||||||
-> Text -- ^ The POST parameter name to lookup the CSRF token
|
-> Text -- ^ The POST parameter name to lookup the CSRF token
|
||||||
-> m ()
|
-> m ()
|
||||||
checkCsrfHeaderOrParam headerName paramName = do
|
checkCsrfHeaderOrParam headerName paramName = do
|
||||||
validHeader <- hasValidCsrfHeaderNamed headerName
|
validHeader <- hasValidCsrfHeaderNamed headerName
|
||||||
validParam <- hasValidCsrfParamNamed paramName
|
validParam <- hasValidCsrfParamNamed paramName
|
||||||
unless (validHeader || validParam) (permissionDenied csrfErrorMessage)
|
unless (validHeader || validParam) $ do
|
||||||
|
$logWarnS "yesod-core" csrfErrorMessage
|
||||||
|
permissionDenied csrfErrorMessage
|
||||||
|
|
||||||
validCsrf :: Maybe Text -> Maybe S.ByteString -> Bool
|
validCsrf :: Maybe Text -> Maybe S.ByteString -> Bool
|
||||||
-- It's important to use constant-time comparison (constEqBytes) in order to avoid timing attacks.
|
-- It's important to use constant-time comparison (constEqBytes) in order to avoid timing attacks.
|
||||||
@ -1414,4 +1458,4 @@ validCsrf Nothing _param = True
|
|||||||
validCsrf (Just _token) Nothing = False
|
validCsrf (Just _token) Nothing = False
|
||||||
|
|
||||||
csrfErrorMessage :: Text
|
csrfErrorMessage :: Text
|
||||||
csrfErrorMessage = "A valid CSRF token wasn't present in HTTP headers or POST parameters. Check the Yesod.Core.Handler docs of the yesod-core package for details on CSRF protection."
|
csrfErrorMessage = "A valid CSRF token wasn't present in HTTP headers or POST parameters. Because the request could have been forged, it's been rejected altogether. Check the Yesod.Core.Handler docs of the yesod-core package for details on CSRF protection."
|
||||||
|
|||||||
@ -55,7 +55,7 @@ decodeClientSession key date rhost encrypted = do
|
|||||||
-- to preserve the type.
|
-- to preserve the type.
|
||||||
|
|
||||||
clientSessionDateCacher ::
|
clientSessionDateCacher ::
|
||||||
NominalDiffTime -- ^ Inactive session valitity.
|
NominalDiffTime -- ^ Inactive session validity.
|
||||||
-> IO (IO ClientSessionDateCache, IO ())
|
-> IO (IO ClientSessionDateCache, IO ())
|
||||||
clientSessionDateCacher validity = do
|
clientSessionDateCacher validity = do
|
||||||
getClientSessionDateCache <- mkAutoUpdate defaultUpdateSettings
|
getClientSessionDateCache <- mkAutoUpdate defaultUpdateSettings
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import Language.Haskell.TH.Quote
|
|||||||
import qualified System.IO as SIO
|
import qualified System.IO as SIO
|
||||||
import Yesod.Routes.TH
|
import Yesod.Routes.TH
|
||||||
import Yesod.Routes.Overlap (findOverlapNames)
|
import Yesod.Routes.Overlap (findOverlapNames)
|
||||||
import Data.List (foldl')
|
import Data.List (foldl', isPrefixOf)
|
||||||
import Data.Maybe (mapMaybe)
|
import Data.Maybe (mapMaybe)
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ resourcesFromString =
|
|||||||
spaces = takeWhile (== ' ') thisLine
|
spaces = takeWhile (== ' ') thisLine
|
||||||
(others, remainder) = parse indent otherLines'
|
(others, remainder) = parse indent otherLines'
|
||||||
(this, otherLines') =
|
(this, otherLines') =
|
||||||
case takeWhile (/= "--") $ words thisLine of
|
case takeWhile (not . isPrefixOf "--") $ words thisLine of
|
||||||
(pattern:rest0)
|
(pattern:rest0)
|
||||||
| Just (constr:rest) <- stripColonLast rest0
|
| Just (constr:rest) <- stripColonLast rest0
|
||||||
, Just attrs <- mapM parseAttr rest ->
|
, Just attrs <- mapM parseAttr rest ->
|
||||||
|
|||||||
@ -78,6 +78,8 @@ do
|
|||||||
let resources = [parseRoutes|
|
let resources = [parseRoutes|
|
||||||
/ HomeR GET
|
/ HomeR GET
|
||||||
|
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
/!#Int BackwardsR GET
|
/!#Int BackwardsR GET
|
||||||
|
|
||||||
/admin/#Int AdminR:
|
/admin/#Int AdminR:
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod-core
|
name: yesod-core
|
||||||
version: 1.4.19
|
version: 1.4.20.1
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman <michael@snoyman.com>
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
|
|||||||
@ -2,3 +2,14 @@
|
|||||||
|
|
||||||
Form handling for Yesod, in the same style as formlets. See [the forms
|
Form handling for Yesod, in the same style as formlets. See [the forms
|
||||||
chapter](http://www.yesodweb.com/book/forms) of the Yesod book.
|
chapter](http://www.yesodweb.com/book/forms) of the Yesod book.
|
||||||
|
|
||||||
|
This package provies a set of basic form inputs such as text, number, time,
|
||||||
|
checkbox, select, textarea, and etc. via `Yesod.Form.Fields` module. Also,
|
||||||
|
there is `Yesod.Form.Nic` module providing richtext field using Nic editor.
|
||||||
|
However, this module is grandfathered now and Nic editor is not actively
|
||||||
|
maintained since June 2012. You can find additional richtext editor fields in
|
||||||
|
[`yesod-form-richtext`][yesod-form-richtext] package (currently in provides
|
||||||
|
support of [Summernote][summernote] editor only).
|
||||||
|
|
||||||
|
[yesod-form-richtext]:http://hackage.haskell.org/package/yesod-form-richtext
|
||||||
|
[summernote]:http://summernote.org/
|
||||||
|
|||||||
@ -349,7 +349,7 @@ $newline never
|
|||||||
, fieldEnctype = UrlEncoded
|
, fieldEnctype = UrlEncoded
|
||||||
}
|
}
|
||||||
|
|
||||||
-- | Creates an input with @type="email"@ with the <http://www.w3.org/html/wg/drafts/html/master/forms.html#the-multiple-attribute multiple> attribute; browsers might implement this as taking a comma separated list of emails. Each email address is validated as described in 'emailField'.
|
-- | Creates an input with @type="email"@ with the <http://w3c.github.io/html/sec-forms.html#the-multiple-attribute multiple> attribute; browsers might implement this as taking a comma separated list of emails. Each email address is validated as described in 'emailField'.
|
||||||
--
|
--
|
||||||
-- Since 1.3.7
|
-- Since 1.3.7
|
||||||
multiEmailField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m [Text]
|
multiEmailField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m [Text]
|
||||||
|
|||||||
@ -59,6 +59,7 @@ import Text.Blaze (Markup, toMarkup)
|
|||||||
#define Html Markup
|
#define Html Markup
|
||||||
#define toHtml toMarkup
|
#define toHtml toMarkup
|
||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
|
import Yesod.Core.Handler (defaultCsrfParamName)
|
||||||
import Network.Wai (requestMethod)
|
import Network.Wai (requestMethod)
|
||||||
import Text.Hamlet (shamlet)
|
import Text.Hamlet (shamlet)
|
||||||
import Data.Monoid (mempty)
|
import Data.Monoid (mempty)
|
||||||
@ -213,7 +214,7 @@ postHelper :: (MonadHandler m, RenderMessage (HandlerSite m) FormMessage)
|
|||||||
-> m ((FormResult a, xml), Enctype)
|
-> m ((FormResult a, xml), Enctype)
|
||||||
postHelper form env = do
|
postHelper form env = do
|
||||||
req <- getRequest
|
req <- getRequest
|
||||||
let tokenKey = "_token"
|
let tokenKey = defaultCsrfParamName
|
||||||
let token =
|
let token =
|
||||||
case reqToken req of
|
case reqToken req of
|
||||||
Nothing -> mempty
|
Nothing -> mempty
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE CPP#-}
|
{-# LANGUAGE CPP#-}
|
||||||
|
-- | A module providing a means of creating multiple input forms, such as a
|
||||||
|
-- list of 0 or more recipients.
|
||||||
module Yesod.Form.MassInput
|
module Yesod.Form.MassInput
|
||||||
( inputList
|
( inputList
|
||||||
, massDivs
|
, massDivs
|
||||||
@ -40,11 +42,19 @@ up i = do
|
|||||||
IntCons _ is' -> put is' >> newFormIdent >> return ()
|
IntCons _ is' -> put is' >> newFormIdent >> return ()
|
||||||
up $ i - 1
|
up $ i - 1
|
||||||
|
|
||||||
|
-- | Generate a form that accepts 0 or more values from the user, allowing the
|
||||||
|
-- user to specify that a new row is necessary.
|
||||||
inputList :: (m ~ HandlerT site IO, xml ~ WidgetT site IO (), RenderMessage site FormMessage)
|
inputList :: (m ~ HandlerT site IO, xml ~ WidgetT site IO (), RenderMessage site FormMessage)
|
||||||
=> Html
|
=> Html
|
||||||
|
-- ^ label for the form
|
||||||
-> ([[FieldView site]] -> xml)
|
-> ([[FieldView site]] -> xml)
|
||||||
|
-- ^ how to display the rows, usually either 'massDivs' or 'massTable'
|
||||||
-> (Maybe a -> AForm (HandlerT site IO) a)
|
-> (Maybe a -> AForm (HandlerT site IO) a)
|
||||||
-> (Maybe [a] -> AForm (HandlerT site IO) [a])
|
-- ^ display a single row of the form, where @Maybe a@ gives the
|
||||||
|
-- previously submitted value
|
||||||
|
-> Maybe [a]
|
||||||
|
-- ^ default initial values for the form
|
||||||
|
-> AForm (HandlerT site IO) [a]
|
||||||
inputList label fixXml single mdef = formToAForm $ do
|
inputList label fixXml single mdef = formToAForm $ do
|
||||||
theId <- lift newIdent
|
theId <- lift newIdent
|
||||||
down 1
|
down 1
|
||||||
|
|||||||
@ -4,6 +4,13 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
-- | Provide the user with a rich text editor.
|
-- | Provide the user with a rich text editor.
|
||||||
|
--
|
||||||
|
-- According to NIC editor homepage it is not actively maintained since June
|
||||||
|
-- 2012. There is another better alternative — open sourced Summernote editor
|
||||||
|
-- released under MIT licence. You can use Summernote in your Yesod forms via
|
||||||
|
-- separately distributed
|
||||||
|
-- <http://hackage.haskell.org/package/yesod-form-richtext yesod-form-richtext>
|
||||||
|
-- package.
|
||||||
module Yesod.Form.Nic
|
module Yesod.Form.Nic
|
||||||
( YesodNic (..)
|
( YesodNic (..)
|
||||||
, nicHtmlField
|
, nicHtmlField
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod-form
|
name: yesod-form
|
||||||
version: 1.4.6
|
version: 1.4.7
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman <michael@snoyman.com>
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
@ -10,7 +10,7 @@ stability: Stable
|
|||||||
cabal-version: >= 1.8
|
cabal-version: >= 1.8
|
||||||
build-type: Simple
|
build-type: Simple
|
||||||
homepage: http://www.yesodweb.com/
|
homepage: http://www.yesodweb.com/
|
||||||
description: API docs and the README are available at <http://www.stackage.org/package/yesod-form>
|
description: API docs and the README are available at <http://www.stackage.org/package/yesod-form>. Third-party packages which you can find useful: <http://hackage.haskell.org/package/yesod-form-richtext yesod-form-richtext> - richtext form fields (currntly it provides only Summernote support).
|
||||||
extra-source-files: ChangeLog.md
|
extra-source-files: ChangeLog.md
|
||||||
README.md
|
README.md
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ flag network-uri
|
|||||||
|
|
||||||
library
|
library
|
||||||
build-depends: base >= 4 && < 5
|
build-depends: base >= 4 && < 5
|
||||||
, yesod-core >= 1.4 && < 1.5
|
, yesod-core >= 1.4.14 && < 1.5
|
||||||
, yesod-persistent >= 1.4 && < 1.5
|
, yesod-persistent >= 1.4 && < 1.5
|
||||||
, time >= 1.1.4
|
, time >= 1.1.4
|
||||||
, shakespeare >= 2.0
|
, shakespeare >= 2.0
|
||||||
@ -63,7 +63,7 @@ library
|
|||||||
Yesod.Form.I18n.German
|
Yesod.Form.I18n.German
|
||||||
Yesod.Form.I18n.French
|
Yesod.Form.I18n.French
|
||||||
Yesod.Form.I18n.Norwegian
|
Yesod.Form.I18n.Norwegian
|
||||||
Yesod.Form.I18n.Japanese
|
Yesod.Form.I18n.Japanese
|
||||||
Yesod.Form.I18n.Czech
|
Yesod.Form.I18n.Czech
|
||||||
Yesod.Form.I18n.Russian
|
Yesod.Form.I18n.Russian
|
||||||
Yesod.Form.I18n.Dutch
|
Yesod.Form.I18n.Dutch
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod-persistent
|
name: yesod-persistent
|
||||||
version: 1.4.0.3
|
version: 1.4.0.4
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman <michael@snoyman.com>
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
## 1.5.1.0
|
||||||
|
|
||||||
|
* Better error provenance for stuff invoking withResponse' [#1191](https://github.com/yesodweb/yesod/pull/1191)
|
||||||
|
|
||||||
## 1.5.0.1
|
## 1.5.0.1
|
||||||
|
|
||||||
* Fixed the `application/x-www-form-urlencoded` header being added to all requests, even those sending a binary POST body [#1064](https://github.com/yesodweb/yesod/pull/1064/files)
|
* Fixed the `application/x-www-form-urlencoded` header being added to all requests, even those sending a binary POST body [#1064](https://github.com/yesodweb/yesod/pull/1064/files)
|
||||||
|
|||||||
@ -50,6 +50,7 @@ module Yesod.Test
|
|||||||
, get
|
, get
|
||||||
, post
|
, post
|
||||||
, postBody
|
, postBody
|
||||||
|
, followRedirect
|
||||||
, request
|
, request
|
||||||
, addRequestHeader
|
, addRequestHeader
|
||||||
, setMethod
|
, setMethod
|
||||||
@ -277,15 +278,21 @@ yit label example = tell [YesodSpecItem label example]
|
|||||||
-- response-level assertions
|
-- response-level assertions
|
||||||
withResponse' :: MonadIO m
|
withResponse' :: MonadIO m
|
||||||
=> (state -> Maybe SResponse)
|
=> (state -> Maybe SResponse)
|
||||||
|
-> [T.Text]
|
||||||
-> (SResponse -> ST.StateT state m a)
|
-> (SResponse -> ST.StateT state m a)
|
||||||
-> ST.StateT state m a
|
-> ST.StateT state m a
|
||||||
withResponse' getter f = maybe err f . getter =<< ST.get
|
withResponse' getter errTrace f = maybe err f . getter =<< ST.get
|
||||||
where err = failure "There was no response, you should make a request"
|
where err = failure msg
|
||||||
|
msg = if null errTrace
|
||||||
|
then "There was no response, you should make a request."
|
||||||
|
else
|
||||||
|
"There was no response, you should make a request. A response was needed because: \n - "
|
||||||
|
<> T.intercalate "\n - " errTrace
|
||||||
|
|
||||||
-- | Performs a given action using the last response. Use this to create
|
-- | Performs a given action using the last response. Use this to create
|
||||||
-- response-level assertions
|
-- response-level assertions
|
||||||
withResponse :: (SResponse -> YesodExample site a) -> YesodExample site a
|
withResponse :: (SResponse -> YesodExample site a) -> YesodExample site a
|
||||||
withResponse = withResponse' yedResponse
|
withResponse = withResponse' yedResponse []
|
||||||
|
|
||||||
-- | Use HXT to parse a value from an HTML tag.
|
-- | Use HXT to parse a value from an HTML tag.
|
||||||
-- Check for usage examples in this module's source.
|
-- Check for usage examples in this module's source.
|
||||||
@ -295,16 +302,17 @@ parseHTML html = fromDocument $ HD.parseLBS html
|
|||||||
-- | Query the last response using CSS selectors, returns a list of matched fragments
|
-- | Query the last response using CSS selectors, returns a list of matched fragments
|
||||||
htmlQuery' :: MonadIO m
|
htmlQuery' :: MonadIO m
|
||||||
=> (state -> Maybe SResponse)
|
=> (state -> Maybe SResponse)
|
||||||
|
-> [T.Text]
|
||||||
-> Query
|
-> Query
|
||||||
-> ST.StateT state m [HtmlLBS]
|
-> ST.StateT state m [HtmlLBS]
|
||||||
htmlQuery' getter query = withResponse' getter $ \ res ->
|
htmlQuery' getter errTrace query = withResponse' getter ("Tried to invoke htmlQuery' in order to read HTML of a previous response." : errTrace) $ \ res ->
|
||||||
case findBySelector (simpleBody res) query of
|
case findBySelector (simpleBody res) query of
|
||||||
Left err -> failure $ query <> " did not parse: " <> T.pack (show err)
|
Left err -> failure $ query <> " did not parse: " <> T.pack (show err)
|
||||||
Right matches -> return $ map (encodeUtf8 . TL.pack) matches
|
Right matches -> return $ map (encodeUtf8 . TL.pack) matches
|
||||||
|
|
||||||
-- | Query the last response using CSS selectors, returns a list of matched fragments
|
-- | Query the last response using CSS selectors, returns a list of matched fragments
|
||||||
htmlQuery :: Query -> YesodExample site [HtmlLBS]
|
htmlQuery :: Query -> YesodExample site [HtmlLBS]
|
||||||
htmlQuery = htmlQuery' yedResponse
|
htmlQuery = htmlQuery' yedResponse []
|
||||||
|
|
||||||
-- | Asserts that the two given values are equal.
|
-- | Asserts that the two given values are equal.
|
||||||
assertEqual :: (Eq a) => String -> a -> a -> YesodExample site ()
|
assertEqual :: (Eq a) => String -> a -> a -> YesodExample site ()
|
||||||
@ -569,7 +577,7 @@ fileByLabel label path mime = do
|
|||||||
-- > addToken_ "#formID"
|
-- > addToken_ "#formID"
|
||||||
addToken_ :: Query -> RequestBuilder site ()
|
addToken_ :: Query -> RequestBuilder site ()
|
||||||
addToken_ scope = do
|
addToken_ scope = do
|
||||||
matches <- htmlQuery' rbdResponse $ scope <> "input[name=_token][type=hidden][value]"
|
matches <- htmlQuery' rbdResponse ["Tried to get CSRF token with addToken'"] $ scope <> "input[name=_token][type=hidden][value]"
|
||||||
case matches of
|
case matches of
|
||||||
[] -> failure $ "No CSRF token found in the current page"
|
[] -> failure $ "No CSRF token found in the current page"
|
||||||
element:[] -> addPostParam "_token" $ head $ attribute "value" $ parseHTML element
|
element:[] -> addPostParam "_token" $ head $ attribute "value" $ parseHTML element
|
||||||
@ -686,6 +694,29 @@ get url = request $ do
|
|||||||
setMethod "GET"
|
setMethod "GET"
|
||||||
setUrl url
|
setUrl url
|
||||||
|
|
||||||
|
-- | Follow a redirect, if the last response was a redirect.
|
||||||
|
-- (We consider a request a redirect if the status is
|
||||||
|
-- 301, 302, 303, 307 or 308, and the Location header is set.)
|
||||||
|
--
|
||||||
|
-- ==== __Examples__
|
||||||
|
--
|
||||||
|
-- > get HomeR
|
||||||
|
-- > followRedirect
|
||||||
|
followRedirect :: Yesod site
|
||||||
|
=> YesodExample site (Either T.Text T.Text) -- ^ 'Left' with an error message if not a redirect, 'Right' with the redirected URL if it was
|
||||||
|
followRedirect = do
|
||||||
|
mr <- getResponse
|
||||||
|
case mr of
|
||||||
|
Nothing -> return $ Left "followRedirect called, but there was no previous response, so no redirect to follow"
|
||||||
|
Just r -> do
|
||||||
|
if not ((H.statusCode $ simpleStatus r) `elem` [301, 302, 303, 307, 308])
|
||||||
|
then return $ Left "followRedirect called, but previous request was not a redirect"
|
||||||
|
else do
|
||||||
|
case lookup "Location" (simpleHeaders r) of
|
||||||
|
Nothing -> return $ Left "followRedirect called, but no location header set"
|
||||||
|
Just h -> let url = TE.decodeUtf8 h in
|
||||||
|
get url >> return (Right url)
|
||||||
|
|
||||||
-- | Sets the HTTP method used by the request.
|
-- | Sets the HTTP method used by the request.
|
||||||
--
|
--
|
||||||
-- ==== __Examples__
|
-- ==== __Examples__
|
||||||
|
|||||||
@ -20,11 +20,13 @@ import Data.Monoid ((<>))
|
|||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import Network.Wai (pathInfo, requestHeaders)
|
import Network.Wai (pathInfo, requestHeaders)
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
|
import Data.Either (isLeft, isRight)
|
||||||
|
import Control.Exception.Lifted(try, SomeException)
|
||||||
|
|
||||||
import Data.ByteString.Lazy.Char8 ()
|
import Data.ByteString.Lazy.Char8 ()
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import qualified Text.HTML.DOM as HD
|
import qualified Text.HTML.DOM as HD
|
||||||
import Network.HTTP.Types.Status (unsupportedMediaType415)
|
import Network.HTTP.Types.Status (status301, status303, unsupportedMediaType415)
|
||||||
|
|
||||||
parseQuery_ = either error id . parseQuery
|
parseQuery_ = either error id . parseQuery
|
||||||
findBySelector_ x = either error id . findBySelector x
|
findBySelector_ x = either error id . findBySelector x
|
||||||
@ -213,8 +215,29 @@ main = hspec $ do
|
|||||||
setMethod "POST"
|
setMethod "POST"
|
||||||
setUrl ("/" :: Text)
|
setUrl ("/" :: Text)
|
||||||
statusIs 403
|
statusIs 403
|
||||||
|
describe "test redirects" $ yesodSpec app $ do
|
||||||
|
yit "follows 303 redirects when requested" $ do
|
||||||
|
get ("/redirect303" :: Text)
|
||||||
|
statusIs 303
|
||||||
|
r <- followRedirect
|
||||||
|
liftIO $ assertBool "expected a Right from a 303 redirect" $ isRight r
|
||||||
|
statusIs 200
|
||||||
|
bodyContains "we have been successfully redirected"
|
||||||
|
|
||||||
|
yit "follows 301 redirects when requested" $ do
|
||||||
|
get ("/redirect301" :: Text)
|
||||||
|
statusIs 301
|
||||||
|
r <- followRedirect
|
||||||
|
liftIO $ assertBool "expected a Right from a 301 redirect" $ isRight r
|
||||||
|
statusIs 200
|
||||||
|
bodyContains "we have been successfully redirected"
|
||||||
|
|
||||||
|
|
||||||
|
yit "returns a Left when no redirect was returned" $ do
|
||||||
|
get ("/" :: Text)
|
||||||
|
statusIs 200
|
||||||
|
r <- followRedirect
|
||||||
|
liftIO $ assertBool "expected a Left when not a redirect" $ isLeft r
|
||||||
|
|
||||||
instance RenderMessage LiteApp FormMessage where
|
instance RenderMessage LiteApp FormMessage where
|
||||||
renderMessage _ _ = defaultFormMessage
|
renderMessage _ _ = defaultFormMessage
|
||||||
@ -235,6 +258,9 @@ app = liteApp $ do
|
|||||||
case mfoo of
|
case mfoo of
|
||||||
Nothing -> error "No foo"
|
Nothing -> error "No foo"
|
||||||
Just foo -> return foo
|
Just foo -> return foo
|
||||||
|
onStatic "redirect301" $ dispatchTo $ redirectWith status301 ("/redirectTarget" :: Text) >> return ()
|
||||||
|
onStatic "redirect303" $ dispatchTo $ redirectWith status303 ("/redirectTarget" :: Text) >> return ()
|
||||||
|
onStatic "redirectTarget" $ dispatchTo $ return ("we have been successfully redirected" :: Text)
|
||||||
onStatic "form" $ dispatchTo $ do
|
onStatic "form" $ dispatchTo $ do
|
||||||
((mfoo, widget), _) <- runFormPost
|
((mfoo, widget), _) <- runFormPost
|
||||||
$ renderDivs
|
$ renderDivs
|
||||||
@ -290,4 +316,4 @@ postHomeR = defaultLayout
|
|||||||
[whamlet|
|
[whamlet|
|
||||||
<p>
|
<p>
|
||||||
Welcome to my test application.
|
Welcome to my test application.
|
||||||
|]
|
|]
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
name: yesod-test
|
name: yesod-test
|
||||||
version: 1.5.0.1
|
version: 1.5.1.0
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Nubis <nubis@woobiz.com.ar>
|
author: Nubis <nubis@woobiz.com.ar>
|
||||||
maintainer: Michael Snoyman, Greg Weber, Nubis <nubis@woobiz.com.ar>
|
maintainer: Michael Snoyman, Greg Weber, Nubis <nubis@woobiz.com.ar>
|
||||||
synopsis: integration testing for WAI/Yesod Applications
|
synopsis: integration testing for WAI/Yesod Applications
|
||||||
category: Web, Yesod, Testing
|
category: Web, Yesod, Testing
|
||||||
stability: Experimental
|
stability: Experimental
|
||||||
cabal-version: >= 1.8
|
cabal-version: >= 1.8
|
||||||
@ -60,6 +60,7 @@ test-suite test
|
|||||||
, yesod-form
|
, yesod-form
|
||||||
, text
|
, text
|
||||||
, wai
|
, wai
|
||||||
|
, lifted-base
|
||||||
, http-types
|
, http-types
|
||||||
|
|
||||||
source-repository head
|
source-repository head
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod
|
name: yesod
|
||||||
version: 1.4.2
|
version: 1.4.2.1
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman <michael@snoyman.com>
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user