Cleaned up helpers + docs
This commit is contained in:
parent
e062033942
commit
d385fc48d1
@ -13,6 +13,8 @@
|
|||||||
--
|
--
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
-- | Generation of Atom newsfeeds. See
|
||||||
|
-- <http://en.wikipedia.org/wiki/Atom_(standard)>.
|
||||||
module Yesod.Helpers.AtomFeed
|
module Yesod.Helpers.AtomFeed
|
||||||
( AtomFeed (..)
|
( AtomFeed (..)
|
||||||
, AtomFeedEntry (..)
|
, AtomFeedEntry (..)
|
||||||
|
|||||||
@ -20,18 +20,19 @@
|
|||||||
--
|
--
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
module Yesod.Helpers.Auth
|
module Yesod.Helpers.Auth
|
||||||
( redirectLogin
|
( -- * Subsite
|
||||||
, Auth (..)
|
Auth (..)
|
||||||
, AuthRoutes (..)
|
, AuthRoutes (..)
|
||||||
, siteAuth
|
, siteAuth
|
||||||
|
-- * Settings
|
||||||
, YesodAuth (..)
|
, YesodAuth (..)
|
||||||
, identKey
|
|
||||||
, displayNameKey
|
|
||||||
, Creds (..)
|
, Creds (..)
|
||||||
, maybeCreds
|
, AuthType (..)
|
||||||
, requireCreds
|
|
||||||
, AuthEmailSettings (..)
|
, AuthEmailSettings (..)
|
||||||
, inMemoryEmailSettings
|
, inMemoryEmailSettings
|
||||||
|
-- * Functions
|
||||||
|
, maybeCreds
|
||||||
|
, requireCreds
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import qualified Web.Authenticate.Rpxnow as Rpxnow
|
import qualified Web.Authenticate.Rpxnow as Rpxnow
|
||||||
@ -71,12 +72,16 @@ class Yesod master => YesodAuth master where
|
|||||||
stdgen <- newStdGen
|
stdgen <- newStdGen
|
||||||
return $ take 10 $ randomRs ('A', 'Z') stdgen
|
return $ take 10 $ randomRs ('A', 'Z') stdgen
|
||||||
|
|
||||||
|
-- | Each authentication subsystem (OpenId, Rpxnow, Email) has its own
|
||||||
|
-- settings. If those settings are not present, then relevant handlers will
|
||||||
|
-- simply return a 404.
|
||||||
data Auth = Auth
|
data Auth = Auth
|
||||||
{ authIsOpenIdEnabled :: Bool
|
{ authIsOpenIdEnabled :: Bool
|
||||||
, authRpxnowApiKey :: Maybe String
|
, authRpxnowApiKey :: Maybe String
|
||||||
, authEmailSettings :: Maybe AuthEmailSettings
|
, authEmailSettings :: Maybe AuthEmailSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- | Which subsystem authenticated the user.
|
||||||
data AuthType = AuthOpenId | AuthRpxnow | AuthEmail
|
data AuthType = AuthOpenId | AuthRpxnow | AuthEmail
|
||||||
deriving (Show, Read, Eq)
|
deriving (Show, Read, Eq)
|
||||||
|
|
||||||
@ -86,7 +91,12 @@ type VerUrl = String
|
|||||||
type EmailId = Integer
|
type EmailId = Integer
|
||||||
type SaltedPass = String
|
type SaltedPass = String
|
||||||
type VerStatus = Bool
|
type VerStatus = Bool
|
||||||
|
|
||||||
|
-- | Data stored in a database for each e-mail address.
|
||||||
data EmailCreds = EmailCreds EmailId (Maybe SaltedPass) VerStatus VerKey
|
data EmailCreds = EmailCreds EmailId (Maybe SaltedPass) VerStatus VerKey
|
||||||
|
|
||||||
|
-- | For a sample set of settings for a trivial in-memory database, see
|
||||||
|
-- 'inMemoryEmailSettings'.
|
||||||
data AuthEmailSettings = AuthEmailSettings
|
data AuthEmailSettings = AuthEmailSettings
|
||||||
{ addUnverified :: Email -> VerKey -> IO EmailId
|
{ addUnverified :: Email -> VerKey -> IO EmailId
|
||||||
, sendVerifyEmail :: Email -> VerKey -> VerUrl -> IO ()
|
, sendVerifyEmail :: Email -> VerKey -> VerUrl -> IO ()
|
||||||
@ -116,6 +126,7 @@ setCreds creds extra = do
|
|||||||
setSession credsKey $ show creds
|
setSession credsKey $ show creds
|
||||||
onLogin creds extra
|
onLogin creds extra
|
||||||
|
|
||||||
|
-- | Retrieves user credentials, if user is authenticated.
|
||||||
maybeCreds :: GHandler sub master (Maybe Creds)
|
maybeCreds :: GHandler sub master (Maybe Creds)
|
||||||
maybeCreds = do
|
maybeCreds = do
|
||||||
mcs <- lookupSession credsKey
|
mcs <- lookupSession credsKey
|
||||||
@ -258,22 +269,17 @@ getLogout = do
|
|||||||
clearSession credsKey
|
clearSession credsKey
|
||||||
redirectUltDest RedirectTemporary $ defaultDest y
|
redirectUltDest RedirectTemporary $ defaultDest y
|
||||||
|
|
||||||
-- | Redirect the user to the 'defaultLoginPath', setting the DEST cookie
|
-- | Retrieve user credentials. If user is not logged in, redirects to the
|
||||||
-- appropriately.
|
-- 'defaultLoginRoute'. Sets ultimate destination to current route, so user
|
||||||
redirectLogin :: YesodAuth master => GHandler sub master a
|
-- should be sent back here after authenticating.
|
||||||
redirectLogin = do
|
|
||||||
y <- getYesod
|
|
||||||
setUltDest'
|
|
||||||
redirect RedirectTemporary $ defaultLoginRoute y
|
|
||||||
|
|
||||||
requireCreds :: YesodAuth master => GHandler sub master Creds
|
requireCreds :: YesodAuth master => GHandler sub master Creds
|
||||||
requireCreds = maybeCreds >>= maybe redirectLogin return
|
requireCreds =
|
||||||
|
maybeCreds >>= maybe redirectLogin return
|
||||||
identKey :: String
|
where
|
||||||
identKey = "IDENTIFIER"
|
redirectLogin = do
|
||||||
|
y <- getYesod
|
||||||
displayNameKey :: String
|
setUltDest'
|
||||||
displayNameKey = "DISPLAY_NAME"
|
redirect RedirectTemporary $ defaultLoginRoute y
|
||||||
|
|
||||||
getAuthEmailSettings :: GHandler Auth master AuthEmailSettings
|
getAuthEmailSettings :: GHandler Auth master AuthEmailSettings
|
||||||
getAuthEmailSettings = getYesodSub >>= maybe notFound return . authEmailSettings
|
getAuthEmailSettings = getYesodSub >>= maybe notFound return . authEmailSettings
|
||||||
|
|||||||
@ -13,6 +13,9 @@
|
|||||||
--
|
--
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
-- | Generates XML sitemap files.
|
||||||
|
--
|
||||||
|
-- See <http://www.sitemaps.org/>.
|
||||||
module Yesod.Helpers.Sitemap
|
module Yesod.Helpers.Sitemap
|
||||||
( sitemap
|
( sitemap
|
||||||
, robots
|
, robots
|
||||||
@ -31,6 +34,7 @@ data SitemapChangeFreq = Always
|
|||||||
| Monthly
|
| Monthly
|
||||||
| Yearly
|
| Yearly
|
||||||
| Never
|
| Never
|
||||||
|
|
||||||
showFreq :: SitemapChangeFreq -> String
|
showFreq :: SitemapChangeFreq -> String
|
||||||
showFreq Always = "always"
|
showFreq Always = "always"
|
||||||
showFreq Hourly = "hourly"
|
showFreq Hourly = "hourly"
|
||||||
@ -64,6 +68,7 @@ template urls = [$hamlet|
|
|||||||
sitemap :: [SitemapUrl (Routes master)] -> GHandler sub master RepXml
|
sitemap :: [SitemapUrl (Routes master)] -> GHandler sub master RepXml
|
||||||
sitemap = fmap RepXml . hamletToContent . template
|
sitemap = fmap RepXml . hamletToContent . template
|
||||||
|
|
||||||
|
-- | A basic robots file which just lists the "Sitemap: " line.
|
||||||
robots :: Routes sub -- ^ sitemap url
|
robots :: Routes sub -- ^ sitemap url
|
||||||
-> GHandler sub master RepPlain
|
-> GHandler sub master RepPlain
|
||||||
robots smurl = do
|
robots smurl = do
|
||||||
|
|||||||
@ -11,20 +11,23 @@
|
|||||||
-- Stability : Unstable
|
-- Stability : Unstable
|
||||||
-- Portability : portable
|
-- Portability : portable
|
||||||
--
|
--
|
||||||
-- Serve static files from a Yesod app.
|
|
||||||
|
-- | Serve static files from a Yesod app.
|
||||||
--
|
--
|
||||||
-- This is most useful for standalone testing. When running on a production
|
-- This is most useful for standalone testing. When running on a production
|
||||||
-- server (like Apache), just let the server do the static serving.
|
-- server (like Apache), just let the server do the static serving.
|
||||||
--
|
--
|
||||||
---------------------------------------------------------
|
-- In fact, in an ideal setup you'll serve your static files from a separate
|
||||||
|
-- domain name to save time on transmitting cookies. In that case, you may wish
|
||||||
|
-- to use 'urlRenderOverride' to redirect requests to this subsite to a
|
||||||
|
-- separate domain name.
|
||||||
module Yesod.Helpers.Static
|
module Yesod.Helpers.Static
|
||||||
( FileLookup
|
( -- * Subsite
|
||||||
, fileLookupDir
|
Static (..)
|
||||||
|
, StaticRoutes (..)
|
||||||
, siteStatic
|
, siteStatic
|
||||||
, StaticRoutes
|
-- * Lookup files in filesystem
|
||||||
, toStaticRoute
|
, fileLookupDir
|
||||||
, staticArgs
|
|
||||||
, Static
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import System.Directory (doesFileExist)
|
import System.Directory (doesFileExist)
|
||||||
@ -32,25 +35,21 @@ import Control.Monad
|
|||||||
|
|
||||||
import Yesod
|
import Yesod
|
||||||
import Data.List (intercalate)
|
import Data.List (intercalate)
|
||||||
import Network.Wai
|
|
||||||
|
|
||||||
type FileLookup = FilePath -> IO (Maybe (Either FilePath Content))
|
-- | A function for looking up file contents. For serving from the file system,
|
||||||
|
-- see 'fileLookupDir'.
|
||||||
data Static = Static FileLookup
|
data Static = Static (FilePath -> IO (Maybe (Either FilePath Content)))
|
||||||
|
|
||||||
staticArgs :: FileLookup -> Static
|
|
||||||
staticArgs = Static
|
|
||||||
|
|
||||||
$(mkYesodSub "Static" [] [$parseRoutes|
|
$(mkYesodSub "Static" [] [$parseRoutes|
|
||||||
/* StaticRoute GET
|
/* StaticRoute GET
|
||||||
|])
|
|])
|
||||||
|
|
||||||
-- | A 'FileLookup' for files in a directory. Note that this function does not
|
-- | Lookup files in a specific directory.
|
||||||
-- check if the requested path does unsafe things, eg expose hidden files. You
|
|
||||||
-- should provide this checking elsewhere.
|
|
||||||
--
|
--
|
||||||
-- If you are just using this in combination with serveStatic, serveStatic
|
-- If you are just using this in combination with the static subsite (you
|
||||||
-- provides this checking.
|
-- probably are), the handler itself checks that no unsafe paths are being
|
||||||
|
-- requested. In particular, no path segments may begin with a single period,
|
||||||
|
-- so hidden files and parent directories are safe.
|
||||||
fileLookupDir :: FilePath -> Static
|
fileLookupDir :: FilePath -> Static
|
||||||
fileLookupDir dir = Static $ \fp -> do
|
fileLookupDir dir = Static $ \fp -> do
|
||||||
let fp' = dir ++ '/' : fp
|
let fp' = dir ++ '/' : fp
|
||||||
@ -59,11 +58,11 @@ fileLookupDir dir = Static $ \fp -> do
|
|||||||
then return $ Just $ Left fp'
|
then return $ Just $ Left fp'
|
||||||
else return Nothing
|
else return Nothing
|
||||||
|
|
||||||
getStatic :: FileLookup -> [String] -> GHandler sub master [(ContentType, Content)]
|
getStaticRoute :: [String]
|
||||||
getStatic fl fp' = do
|
-> GHandler Static master [(ContentType, Content)]
|
||||||
|
getStaticRoute fp' = do
|
||||||
|
Static fl <- getYesodSub
|
||||||
when (any isUnsafe fp') notFound
|
when (any isUnsafe fp') notFound
|
||||||
wai <- waiRequest
|
|
||||||
when (requestMethod wai /= GET) badMethod
|
|
||||||
let fp = intercalate "/" fp'
|
let fp = intercalate "/" fp'
|
||||||
content <- liftIO $ fl fp
|
content <- liftIO $ fl fp
|
||||||
case content of
|
case content of
|
||||||
@ -74,11 +73,3 @@ getStatic fl fp' = do
|
|||||||
isUnsafe [] = True
|
isUnsafe [] = True
|
||||||
isUnsafe ('.':_) = True
|
isUnsafe ('.':_) = True
|
||||||
isUnsafe _ = False
|
isUnsafe _ = False
|
||||||
|
|
||||||
getStaticRoute :: [String] -> GHandler Static master [(ContentType, Content)]
|
|
||||||
getStaticRoute fp = do
|
|
||||||
Static fl <- getYesodSub
|
|
||||||
getStatic fl fp
|
|
||||||
|
|
||||||
toStaticRoute :: [String] -> StaticRoutes
|
|
||||||
toStaticRoute = StaticRoute
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user