-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Top-level package for the Snap Web Framework -- -- This is the top-level package for the official Snap Framework -- libraries. It includes: -- -- -- -- To get started, issue the following sequence of commands: -- --
--   $ cabal install snap
--   $ mkdir myproject
--   $ cd myproject
--   $ snap init
--   
-- -- If you have trouble or any questions, see our FAQ page -- (http://snapframework.com/faq) or the documentation -- (http://snapframework.com/docs). @package snap @version 0.11.3 -- | This module is meant to be used mainly by Session backend developers, -- who would naturally need access to ISessionManager class internals. -- You can also use it if you need low-level access to the backend -- functionality. module Snap.Snaplet.Session.SessionManager -- | Any Haskell record that is a member of the ISessionManager -- typeclass can be stuffed inside a SessionManager to enable all -- session-related functionality. -- -- To use sessions in your application, just find a Backend that would -- produce one for you inside of your Initializer. See -- initCookieSessionManager in CookieSession for a -- built-in option that would get you started. data SessionManager SessionManager :: a -> SessionManager class ISessionManager r load :: ISessionManager r => r -> Snap r commit :: ISessionManager r => r -> Snap () reset :: ISessionManager r => r -> Snap r touch :: ISessionManager r => r -> r insert :: ISessionManager r => Text -> Text -> r -> r lookup :: ISessionManager r => Text -> r -> (Maybe Text) delete :: ISessionManager r => Text -> r -> r csrf :: ISessionManager r => r -> Text toList :: ISessionManager r => r -> [(Text, Text)] -- | This module contains functionality common among multiple back-ends. module Snap.Snaplet.Session.Common -- | High speed, mutable random number generator state data RNG -- | Create a new RNG mkRNG :: IO RNG -- | Perform given action, mutating the RNG state withRNG :: RNG -> (GenIO -> IO a) -> IO a -- | Generates a random salt of given length randomToken :: Int -> RNG -> IO ByteString -- | Generate a randomized CSRF token mkCSRFToken :: RNG -> IO Text instance Serialize Text module Snap.Snaplet.Config -- | AppConfig contains the config options for command line arguments in -- snaplet-based apps. newtype AppConfig AppConfig :: Maybe String -> AppConfig appEnvironment :: AppConfig -> Maybe String -- | AppConfig has a manual instance of Typeable due to limitations in the -- tools available before GHC 7.4, and the need to make dynamic loading -- tractable. When support for earlier versions of GHC is dropped, the -- dynamic loader package can be updated so that manual Typeable -- instances are no longer needed. appConfigTyCon :: TyCon -- | Command line options for snaplet applications. appOpts :: AppConfig -> [OptDescr (Maybe (Config m AppConfig))] -- | Calls snap-server's extendedCommandLineConfig to add snaplet options -- to the built-in server command line options. commandLineAppConfig :: MonadSnap m => Config m AppConfig -> IO (Config m AppConfig) instance Monoid AppConfig instance Typeable AppConfig -- | Snaplets allow you to build web applications out of composable parts. -- This allows you to build self-contained units and glue them together -- to make your overall application. -- -- A snaplet has a few moving parts, some user-defined and some provided -- by the snaplet API: -- -- -- -- NOTE: This documentation is written as a prose tutorial of the -- snaplets API. Don't be scared by the fact that it's auto-generated and -- is filled with type signatures. Just keep reading. module Snap.Snaplet -- | Snaplet's type parameter s here is user-defined and can be -- any Haskell type. A value of type Snaplet s countains a -- couple of things: -- -- data Snaplet s -- | An opaque data type holding internal snaplet configuration data. It is -- exported publicly because the getOpaqueConfig function in MonadSnaplet -- makes implementing new instances of MonadSnaplet more convenient. data SnapletConfig snapletConfig :: Lens' (Snaplet s_aBGz) SnapletConfig snapletValue :: Lens (Snaplet s_aBGz) (Snaplet s_aBHB) s_aBGz s_aBHB -- | Transforms a lens of the type you get from makeLenses to an similar -- lens that is more suitable for internal use. subSnaplet :: SnapletLens a b -> SnapletLens (Snaplet a) b -- | The m type parameter used in the MonadSnaplet type signatures will -- usually be either Initializer or Handler, but other monads may -- sometimes be useful. -- -- Minimal complete definition: -- -- class MonadSnaplet m where with l = with' (subSnaplet l) withTop l = withTop' (subSnaplet l) with :: MonadSnaplet m => SnapletLens v v' -> m b v' a -> m b v a withTop :: MonadSnaplet m => SnapletLens b v' -> m b v' a -> m b v a with' :: MonadSnaplet m => SnapletLens (Snaplet v) v' -> m b v' a -> m b v a withTop' :: MonadSnaplet m => SnapletLens (Snaplet b) v' -> m b v' a -> m b v a getLens :: MonadSnaplet m => m b v (SnapletLens (Snaplet b) v) getOpaqueConfig :: MonadSnaplet m => m b v SnapletConfig -- | Gets a list of the names of snaplets that are direct ancestors of the -- current snaplet. getSnapletAncestry :: (Monad (m b v), MonadSnaplet m) => m b v [Text] -- | Gets the snaplet's path on the filesystem. getSnapletFilePath :: (Monad (m b v), MonadSnaplet m) => m b v FilePath -- | Gets the current snaple's name. getSnapletName :: (Monad (m b v), MonadSnaplet m) => m b v (Maybe Text) -- | Gets a human readable description of the snaplet. getSnapletDescription :: (Monad (m b v), MonadSnaplet m) => m b v Text -- | Gets the config data structure for the current snaplet. getSnapletUserConfig :: (Monad (m b v), MonadSnaplet m) => m b v Config -- | Gets the base URL for the current snaplet. Directories get added to -- the current snaplet path by calls to nestSnaplet. getSnapletRootURL :: (Monad (m b v), MonadSnaplet m) => m b v ByteString -- | Gets the route pattern that matched for the handler. This lets you -- find out exactly which of the strings you used in addRoutes matched. getRoutePattern :: Handler b v (Maybe ByteString) -- | Sets the route pattern that matched for the handler. Use this when to -- override the default pattern which is the key to the alist passed to -- addRoutes. setRoutePattern :: ByteString -> Handler b v () -- | Gets the Snaplet v from the current snaplet's state. getSnapletState :: Handler b v (Snaplet v) -- | Puts a new Snaplet v in the current snaplet's state. putSnapletState :: Snaplet v -> Handler b v () -- | Modifies the Snaplet v in the current snaplet's state. modifySnapletState :: (Snaplet v -> Snaplet v) -> Handler b v () -- | Gets the Snaplet v from the current snaplet's state and -- applies a function to it. getsSnapletState :: (Snaplet v -> b) -> Handler b1 v b -- | Monad used for initializing snaplets. data Initializer b v a -- | Opaque newtype which gives us compile-time guarantees that the user is -- using makeSnaplet and either nestSnaplet or embedSnaplet correctly. data SnapletInit b v -- | All snaplet initializers must be wrapped in a call to -- makeSnaplet, which handles standardized housekeeping common -- to all snaplets. Common usage will look something like this: -- --
--   fooInit :: SnapletInit b Foo
--   fooInit = makeSnaplet "foo" "An example snaplet" Nothing $ do
--       -- Your initializer code here
--       return $ Foo 42
--   
-- -- Note that you're writing your initializer code in the Initializer -- monad, and makeSnaplet converts it into an opaque SnapletInit type. -- This allows us to use the type system to ensure that the API is used -- correctly. makeSnaplet :: Text -> Text -> Maybe (IO FilePath) -> Initializer b v v -> SnapletInit b v -- | Runs another snaplet's initializer and returns the initialized Snaplet -- value. Calling an initializer with nestSnaplet gives the nested -- snaplet access to the same base state that the current snaplet has. -- This makes it possible for the child snaplet to make use of -- functionality provided by sibling snaplets. nestSnaplet :: ByteString -> SnapletLens v v1 -> SnapletInit b v1 -> Initializer b v (Snaplet v1) -- | Runs another snaplet's initializer and returns the initialized Snaplet -- value. The difference between this and nestSnaplet is the first type -- parameter in the third argument. The "v1 v1" makes the child snaplet -- think that it is top-level, which means that it will not be able to -- use functionality provided by snaplets included above it in the -- snaplet tree. This strongly isolates the child snaplet, and allows you -- to eliminate the b type variable. The embedded snaplet can still get -- functionality from other snaplets, but only if it nests or embeds the -- snaplet itself. embedSnaplet :: ByteString -> SnapletLens v v1 -> SnapletInit v1 v1 -> Initializer b v (Snaplet v1) -- | Sets a snaplet's name. All snaplets have a default name set by the -- snaplet author. This function allows you to override that name. You -- will have to do this if you have more than one instance of the same -- kind of snaplet because snaplet names must be unique. This function -- must immediately surround the snaplet's initializer. For example: -- --
--   fooState <- nestSnaplet "fooA" $ nameSnaplet "myFoo" $ fooInit
--   
nameSnaplet :: Text -> SnapletInit b v -> SnapletInit b v -- | Attaches an unload handler to the snaplet. The unload handler will be -- called when the server shuts down, or is reloaded. onUnload :: IO () -> Initializer b v () -- | Adds an IO action that modifies the current snaplet state to be run at -- the end of initialization on the state that was created. This makes it -- easier to allow one snaplet's state to be modified by another -- snaplet's initializer. A good example of this is when a snaplet has -- templates that define its views. The Heist snaplet provides the -- addTemplates function which allows other snaplets to set up -- their own templates. addTemplates is implemented using this -- function. addPostInitHook :: (v -> EitherT Text IO v) -> Initializer b v () -- | Variant of addPostInitHook for when you have things wrapped in a -- Snaplet. addPostInitHookBase :: (Snaplet b -> EitherT Text IO (Snaplet b)) -> Initializer b v () -- | Initializers should use this function for all informational or error -- messages to be displayed to the user. On application startup they will -- be sent to the console. When executed from the reloader, they will be -- sent back to the user in the HTTP response. printInfo :: Text -> Initializer b v () -- | Lets you retrieve the list of routes currently set up by an -- Initializer. This can be useful in debugging. getRoutes :: Initializer b v [ByteString] -- | Adds routing to the current Handler. The new routes are merged -- with the main routing section and take precedence over existing -- routing that was previously defined. addRoutes :: [(ByteString, Handler b v ())] -> Initializer b v () -- | Wraps the base snaplet's routing in another handler, allowing -- you to run code before and after all routes in an application. -- -- Here are some examples of things you might do: -- --
--   wrapSite (\site -> logHandlerStart >> site >> logHandlerFinished)
--   wrapSite (\site -> ensureAdminUser >> site)
--   
wrapSite :: (Handler b v () -> Handler b v ()) -> Initializer b v () -- | Snaplet infrastructure is available during runtime request processing -- through the Handler monad. There aren't very many standalone functions -- to read about here, but this is deceptive. The key is in the type -- class instances. Handler is an instance of MonadSnap, which -- means it is the monad you will use to write all your application -- routes. It also has a MonadSnaplet instance, which gives you -- all the functionality described above. data Handler b v a -- | Handler that reloads the site. reloadSite :: Handler b v () -- | This function brackets a Handler action in resource acquisition and -- release. Like bracketSnap, this is provided because -- MonadCatchIO's bracket function doesn't work properly in the -- case of a short-circuit return from the action being bracketed. -- -- In order to prevent confusion regarding the effects of the aquisition -- and release actions on the Handler state, this function doesn't accept -- Handler actions for the acquire or release actions. -- -- This function will run the release action in all cases where the -- acquire action succeeded. This includes the following behaviors from -- the bracketed Snap action. -- --
    --
  1. Normal completion
  2. --
  3. Short-circuit completion, either from calling fail or -- finishWith
  4. --
  5. An exception being thrown.
  6. --
bracketHandler :: IO a -> (a -> IO x) -> (a -> Handler b v c) -> Handler b v c -- | Given an environment and a Snaplet initializer, produce a concatenated -- log of all messages generated during initialization, a snap handler, -- and a cleanup action. The environment is an arbitrary string such as -- "devel" or "production". This string is used to determine the name of -- the configuration files used by each snaplet. If an environment of -- Nothing is used, then runSnaplet defaults to "devel". runSnaplet :: Maybe String -> SnapletInit b b -> IO (Text, Snap (), IO ()) -- | Given a configuration and a snap handler, complete it and produce the -- completed configuration as well as a new toplevel handler with things -- like compression and a 500 handler set up. combineConfig :: Config Snap a -> Snap () -> IO (Config Snap a, Snap ()) -- | Initialize and run a Snaplet. This function parses command-line -- arguments, runs the given Snaplet initializer, and starts an HTTP -- server running the Snaplet's toplevel Handler. serveSnaplet :: Config Snap AppConfig -> SnapletInit b b -> IO () -- | Allows you to get all of your app's config data in the IO monad -- without the web server infrastructure. loadAppConfig :: FileName -> FilePath -> IO Config type SnapletLens s a = ALens' s (Snaplet a) -- | This module implements the Heist snaplet without using type classes. -- It is provided mainly as an example of how snaplets can be written -- with and without a type class for convenience. module Snap.Snaplet.HeistNoClass -- | The state for the Heist snaplet. To use the Heist snaplet in your app -- include this in your application state and use heistInit to -- initialize it. The type parameter b will typically be the base state -- type for your application. data Heist b -- | The Initializer for Heist. This function is a -- convenience wrapper around heistInit' that uses -- defaultHeistState and sets up routes for all the templates. heistInit :: FilePath -> SnapletInit b (Heist b) -- | A lower level Initializer for Heist. This initializer -- requires you to specify the initial HeistConfig. It also does not add -- any routes for templates, allowing you complete control over which -- templates get routed. heistInit' :: FilePath -> HeistConfig (Handler b b) -> SnapletInit b (Heist b) -- | Clears data stored by the cache tag. The cache tag automatically -- reloads its data when the specified TTL expires, but sometimes you may -- want to trigger a manual reload. This function lets you do that. clearHeistCache :: Heist b -> IO () -- | Adds templates to the Heist HeistConfig. Other snaplets should use -- this function to add their own templates. The templates are -- automatically read from the templates directory in the current -- snaplet's filesystem root. addTemplates :: Snaplet (Heist b) -> ByteString -> Initializer b (Heist b) () -- | Adds templates to the Heist HeistConfig, and lets you specify where -- they are found in the filesystem. Note that the path to the template -- directory is an absolute path. This allows you more flexibility in -- where your templates are located, but means that you have to -- explicitly call getSnapletFilePath if you want your snaplet to use -- templates within its normal directory structure. addTemplatesAt :: Snaplet (Heist b) -> ByteString -> FilePath -> Initializer b (Heist b) () modifyHeistState :: SnapletLens b (Heist b) -> (HeistState (Handler b b) -> HeistState (Handler b b)) -> Initializer b v () modifyHeistState' :: SnapletLens (Snaplet b) (Heist b) -> (HeistState (Handler b b) -> HeistState (Handler b b)) -> Initializer b v () withHeistState :: SnapletLens b (Heist b) -> (HeistState (Handler b b) -> a) -> Handler b v a withHeistState' :: SnapletLens (Snaplet b) (Heist b) -> (HeistState (Handler b b) -> a) -> Handler b v a addSplices :: SnapletLens b (Heist b) -> [(Text, SnapletISplice b)] -> Initializer b v () addSplices' :: SnapletLens (Snaplet b) (Heist b) -> [(Text, SnapletISplice b)] -> Initializer b v () -- | Adds more HeistConfig data using mappend with whatever is currently -- there. This is the preferred method for adding all four kinds of -- splices as well as new templates. addConfig :: Snaplet (Heist b) -> HeistConfig (Handler b b) -> Initializer b v () cRender :: ByteString -> Handler b (Heist b) () cRenderAs :: ByteString -> ByteString -> Handler b (Heist b) () cHeistServe :: Handler b (Heist b) () cHeistServeSingle :: ByteString -> Handler b (Heist b) () render :: ByteString -> Handler b (Heist b) () renderAs :: ByteString -> ByteString -> Handler b (Heist b) () heistServe :: Handler b (Heist b) () heistServeSingle :: ByteString -> Handler b (Heist b) () heistLocal :: SnapletLens b (Heist b) -> (HeistState (Handler b b) -> HeistState (Handler b b)) -> Handler b v a -> Handler b v a withSplices :: SnapletLens b (Heist b) -> [(Text, SnapletISplice b)] -> Handler b v a -> Handler b v a renderWithSplices :: SnapletLens b (Heist b) -> ByteString -> [(Text, SnapletISplice b)] -> Handler b v () heistLocal' :: SnapletLens (Snaplet b) (Heist b) -> (HeistState (Handler b b) -> HeistState (Handler b b)) -> Handler b v a -> Handler b v a withSplices' :: SnapletLens (Snaplet b) (Heist b) -> [(Text, SnapletISplice b)] -> Handler b v a -> Handler b v a renderWithSplices' :: SnapletLens (Snaplet b) (Heist b) -> ByteString -> [(Text, SnapletISplice b)] -> Handler b v () type SnapletHeist b m a = HeistT (Handler b b) m a type SnapletISplice b = SnapletHeist b (Handler b b) Template type SnapletCSplice b = SnapletHeist b IO (DList (Chunk (Handler b b))) instance MonadSnap m => MonadSnap (HeistT n m) -- | The Heist snaplet makes it easy to add Heist to your application and -- use it in other snaplets. module Snap.Snaplet.Heist -- | The state for the Heist snaplet. To use the Heist snaplet in your app -- include this in your application state and use heistInit to -- initialize it. The type parameter b will typically be the base state -- type for your application. data Heist b -- | A single snaplet should never need more than one instance of Heist as -- a subsnaplet. This type class allows you to make it easy for other -- snaplets to get the lens that identifies the heist snaplet. Here's an -- example of how the heist snaplet might be declared: -- --
--   data App = App { _heist :: Snaplet (Heist App) }
--   makeLenses ''App
--   
--   instance HasHeist App where heistLens = subSnaplet heist
--   
--   appInit = makeSnaplet "app" "" Nothing $ do
--       h <- nestSnaplet "heist" heist $ heistInit "templates"
--       addSplices myAppSplices
--       return $ App h
--   
class HasHeist b heistLens :: HasHeist b => SnapletLens (Snaplet b) (Heist b) -- | The Initializer for Heist. This function is a -- convenience wrapper around heistInit' that uses -- defaultHeistState and sets up routes for all the templates. heistInit :: FilePath -> SnapletInit b (Heist b) -- | A lower level Initializer for Heist. This initializer -- requires you to specify the initial HeistConfig. It also does not add -- any routes for templates, allowing you complete control over which -- templates get routed. heistInit' :: FilePath -> HeistConfig (Handler b b) -> SnapletInit b (Heist b) -- | Adds templates to the Heist HeistState. Other snaplets should use this -- function to add their own templates. The templates are automatically -- read from the templates directory in the current snaplet's filesystem -- root. addTemplates :: HasHeist b => Snaplet (Heist b) -> ByteString -> Initializer b v () -- | Adds templates to the Heist HeistState, and lets you specify where -- they are found in the filesystem. Note that the path to the template -- directory is an absolute path. This allows you more flexibility in -- where your templates are located, but means that you have to -- explicitly call getSnapletFilePath if you want your snaplet to use -- templates within its normal directory structure. addTemplatesAt :: HasHeist b => Snaplet (Heist b) -> ByteString -> FilePath -> Initializer b v () -- | Adds more HeistConfig data using mappend with whatever is currently -- there. This is the preferred method for adding all four kinds of -- splices as well as new templates. addConfig :: Snaplet (Heist b) -> HeistConfig (Handler b b) -> Initializer b v () -- | More general function allowing arbitrary HeistState modification. modifyHeistState :: HasHeist b => (HeistState (Handler b b) -> HeistState (Handler b b)) -> Initializer b v () -- | Runs a function on with the Heist snaplet's HeistState. withHeistState :: HasHeist b => (HeistState (Handler b b) -> a) -> Handler b v a -- | Allows snaplets to add interpreted splices. -- -- NOTE: The splices added with this function will not work if you render -- your templates with cRender. To add splices that work with cRender, -- you have to use the addConfig function to add compiled splices or load -- time splices. addSplices :: HasHeist b => [(Text, SnapletISplice b)] -> Initializer b v () -- | Renders a compiled template as text/html. If the given template is not -- found, this returns empty. cRender :: HasHeist b => ByteString -> Handler b v () -- | Renders a compiled template as the given content type. If the given -- template is not found, this returns empty. cRenderAs :: HasHeist b => ByteString -> ByteString -> Handler b v () -- | A compiled version of heistServe. cHeistServe :: HasHeist b => Handler b v () -- | Analogous to fileServeSingle. If the given template is not -- found, this throws an error. cHeistServeSingle :: HasHeist b => ByteString -> Handler b v () -- | Renders a template as text/html. If the given template is not found, -- this returns empty. render :: HasHeist b => ByteString -> Handler b v () -- | Renders a template as the given content type. If the given template is -- not found, this returns empty. renderAs :: HasHeist b => ByteString -> ByteString -> Handler b v () -- | A handler that serves all the templates (similar to -- serveDirectory). If the template specified in the request -- path is not found, it returns empty. Also, this function does -- not serve any templates beginning with an underscore. This gives you a -- way to prevent some templates from being served. For example, you -- might have a template that contains only the navbar of your pages, and -- you probably wouldn't want that template to be visible to the user as -- a standalone template. So if you put it in a file called "_nav.tpl", -- this function won't serve it. heistServe :: HasHeist b => Handler b v () -- | Handler for serving a single template (similar to -- fileServeSingle). If the given template is not found, this -- throws an error. heistServeSingle :: HasHeist b => ByteString -> Handler b v () -- | Runs a handler with a modified HeistState. You might want to -- use this if you had a set of splices which were customised for a -- specific action. To do that you would do: -- --
--   heistLocal (bindSplices mySplices) handlerThatNeedsSplices
--   
heistLocal :: HasHeist b => (HeistState (Handler b b) -> HeistState (Handler b b)) -> Handler b v a -> Handler b v a -- | Runs an action with additional splices bound into the Heist -- HeistState. withSplices :: HasHeist b => [(Text, SnapletISplice b)] -> Handler b v a -> Handler b v a -- | Renders a template with a given set of splices. This is syntax sugar -- for a common combination of heistLocal, bindSplices, and render. renderWithSplices :: HasHeist b => ByteString -> [(Text, SnapletISplice b)] -> Handler b v () type SnapletHeist b m a = HeistT (Handler b b) m a type SnapletCSplice b = SnapletHeist b IO (DList (Chunk (Handler b b))) type SnapletISplice b = SnapletHeist b (Handler b b) Template -- | Clears data stored by the cache tag. The cache tag automatically -- reloads its data when the specified TTL expires, but sometimes you may -- want to trigger a manual reload. This function lets you do that. clearHeistCache :: Heist b -> IO () -- | A module exporting only functions for using interpreted templates. If -- you import the main Snap.Snaplet.Heist module, it's easy to -- accidentally use the compiled render function even when you're using -- interpreted Heist. Importing only this module will make it harder to -- make mistakes like that. module Snap.Snaplet.Heist.Interpreted -- | The state for the Heist snaplet. To use the Heist snaplet in your app -- include this in your application state and use heistInit to -- initialize it. The type parameter b will typically be the base state -- type for your application. data Heist b -- | A single snaplet should never need more than one instance of Heist as -- a subsnaplet. This type class allows you to make it easy for other -- snaplets to get the lens that identifies the heist snaplet. Here's an -- example of how the heist snaplet might be declared: -- --
--   data App = App { _heist :: Snaplet (Heist App) }
--   makeLenses ''App
--   
--   instance HasHeist App where heistLens = subSnaplet heist
--   
--   appInit = makeSnaplet "app" "" Nothing $ do
--       h <- nestSnaplet "heist" heist $ heistInit "templates"
--       addSplices myAppSplices
--       return $ App h
--   
class HasHeist b heistLens :: HasHeist b => SnapletLens (Snaplet b) (Heist b) type SnapletHeist b m a = HeistT (Handler b b) m a type SnapletISplice b = SnapletHeist b (Handler b b) Template -- | The Initializer for Heist. This function is a -- convenience wrapper around heistInit' that uses -- defaultHeistState and sets up routes for all the templates. heistInit :: FilePath -> SnapletInit b (Heist b) -- | A lower level Initializer for Heist. This initializer -- requires you to specify the initial HeistConfig. It also does not add -- any routes for templates, allowing you complete control over which -- templates get routed. heistInit' :: FilePath -> HeistConfig (Handler b b) -> SnapletInit b (Heist b) -- | Adds templates to the Heist HeistState. Other snaplets should use this -- function to add their own templates. The templates are automatically -- read from the templates directory in the current snaplet's filesystem -- root. addTemplates :: HasHeist b => Snaplet (Heist b) -> ByteString -> Initializer b v () -- | Adds templates to the Heist HeistState, and lets you specify where -- they are found in the filesystem. Note that the path to the template -- directory is an absolute path. This allows you more flexibility in -- where your templates are located, but means that you have to -- explicitly call getSnapletFilePath if you want your snaplet to use -- templates within its normal directory structure. addTemplatesAt :: HasHeist b => Snaplet (Heist b) -> ByteString -> FilePath -> Initializer b v () -- | Adds more HeistConfig data using mappend with whatever is currently -- there. This is the preferred method for adding all four kinds of -- splices as well as new templates. addConfig :: Snaplet (Heist b) -> HeistConfig (Handler b b) -> Initializer b v () -- | More general function allowing arbitrary HeistState modification. modifyHeistState :: HasHeist b => (HeistState (Handler b b) -> HeistState (Handler b b)) -> Initializer b v () -- | Runs a function on with the Heist snaplet's HeistState. withHeistState :: HasHeist b => (HeistState (Handler b b) -> a) -> Handler b v a -- | Allows snaplets to add interpreted splices. -- -- NOTE: The splices added with this function will not work if you render -- your templates with cRender. To add splices that work with cRender, -- you have to use the addConfig function to add compiled splices or load -- time splices. addSplices :: HasHeist b => [(Text, SnapletISplice b)] -> Initializer b v () -- | Renders a template as text/html. If the given template is not found, -- this returns empty. render :: HasHeist b => ByteString -> Handler b v () -- | Renders a template as the given content type. If the given template is -- not found, this returns empty. renderAs :: HasHeist b => ByteString -> ByteString -> Handler b v () -- | A handler that serves all the templates (similar to -- serveDirectory). If the template specified in the request -- path is not found, it returns empty. Also, this function does -- not serve any templates beginning with an underscore. This gives you a -- way to prevent some templates from being served. For example, you -- might have a template that contains only the navbar of your pages, and -- you probably wouldn't want that template to be visible to the user as -- a standalone template. So if you put it in a file called "_nav.tpl", -- this function won't serve it. heistServe :: HasHeist b => Handler b v () -- | Handler for serving a single template (similar to -- fileServeSingle). If the given template is not found, this -- throws an error. heistServeSingle :: HasHeist b => ByteString -> Handler b v () -- | Runs a handler with a modified HeistState. You might want to -- use this if you had a set of splices which were customised for a -- specific action. To do that you would do: -- --
--   heistLocal (bindSplices mySplices) handlerThatNeedsSplices
--   
heistLocal :: HasHeist b => (HeistState (Handler b b) -> HeistState (Handler b b)) -> Handler b v a -> Handler b v a -- | Runs an action with additional splices bound into the Heist -- HeistState. withSplices :: HasHeist b => [(Text, SnapletISplice b)] -> Handler b v a -> Handler b v a -- | Renders a template with a given set of splices. This is syntax sugar -- for a common combination of heistLocal, bindSplices, and render. renderWithSplices :: HasHeist b => ByteString -> [(Text, SnapletISplice b)] -> Handler b v () -- | Clears data stored by the cache tag. The cache tag automatically -- reloads its data when the specified TTL expires, but sometimes you may -- want to trigger a manual reload. This function lets you do that. clearHeistCache :: Heist b -> IO () -- | A module exporting only functions for using compiled templates. If you -- import the main Snap.Snaplet.Heist module, it's easy to accidentally -- use the interpreted render function even when you're using compiled -- Heist. Importing only this module will make it harder to make mistakes -- like that. module Snap.Snaplet.Heist.Compiled -- | The state for the Heist snaplet. To use the Heist snaplet in your app -- include this in your application state and use heistInit to -- initialize it. The type parameter b will typically be the base state -- type for your application. data Heist b -- | A single snaplet should never need more than one instance of Heist as -- a subsnaplet. This type class allows you to make it easy for other -- snaplets to get the lens that identifies the heist snaplet. Here's an -- example of how the heist snaplet might be declared: -- --
--   data App = App { _heist :: Snaplet (Heist App) }
--   makeLenses ''App
--   
--   instance HasHeist App where heistLens = subSnaplet heist
--   
--   appInit = makeSnaplet "app" "" Nothing $ do
--       h <- nestSnaplet "heist" heist $ heistInit "templates"
--       addSplices myAppSplices
--       return $ App h
--   
class HasHeist b heistLens :: HasHeist b => SnapletLens (Snaplet b) (Heist b) type SnapletHeist b m a = HeistT (Handler b b) m a type SnapletCSplice b = SnapletHeist b IO (DList (Chunk (Handler b b))) -- | The Initializer for Heist. This function is a -- convenience wrapper around heistInit' that uses -- defaultHeistState and sets up routes for all the templates. heistInit :: FilePath -> SnapletInit b (Heist b) -- | A lower level Initializer for Heist. This initializer -- requires you to specify the initial HeistConfig. It also does not add -- any routes for templates, allowing you complete control over which -- templates get routed. heistInit' :: FilePath -> HeistConfig (Handler b b) -> SnapletInit b (Heist b) -- | Adds templates to the Heist HeistState. Other snaplets should use this -- function to add their own templates. The templates are automatically -- read from the templates directory in the current snaplet's filesystem -- root. addTemplates :: HasHeist b => Snaplet (Heist b) -> ByteString -> Initializer b v () -- | Adds templates to the Heist HeistState, and lets you specify where -- they are found in the filesystem. Note that the path to the template -- directory is an absolute path. This allows you more flexibility in -- where your templates are located, but means that you have to -- explicitly call getSnapletFilePath if you want your snaplet to use -- templates within its normal directory structure. addTemplatesAt :: HasHeist b => Snaplet (Heist b) -> ByteString -> FilePath -> Initializer b v () -- | Adds more HeistConfig data using mappend with whatever is currently -- there. This is the preferred method for adding all four kinds of -- splices as well as new templates. addConfig :: Snaplet (Heist b) -> HeistConfig (Handler b b) -> Initializer b v () -- | More general function allowing arbitrary HeistState modification. modifyHeistState :: HasHeist b => (HeistState (Handler b b) -> HeistState (Handler b b)) -> Initializer b v () -- | Runs a function on with the Heist snaplet's HeistState. withHeistState :: HasHeist b => (HeistState (Handler b b) -> a) -> Handler b v a -- | Renders a compiled template as text/html. If the given template is not -- found, this returns empty. render :: HasHeist b => ByteString -> Handler b v () -- | Renders a compiled template as the given content type. If the given -- template is not found, this returns empty. renderAs :: HasHeist b => ByteString -> ByteString -> Handler b v () -- | A handler that serves all the templates (similar to -- serveDirectory). If the template specified in the request -- path is not found, it returns empty. Also, this function does -- not serve any templates beginning with an underscore. This gives you a -- way to prevent some templates from being served. For example, you -- might have a template that contains only the navbar of your pages, and -- you probably wouldn't want that template to be visible to the user as -- a standalone template. So if you put it in a file called "_nav.tpl", -- this function won't serve it. heistServe :: HasHeist b => Handler b v () -- | Handler for serving a single template (similar to -- fileServeSingle). If the given template is not found, this -- throws an error. heistServeSingle :: HasHeist b => ByteString -> Handler b v () -- | Clears data stored by the cache tag. The cache tag automatically -- reloads its data when the specified TTL expires, but sometimes you may -- want to trigger a manual reload. This function lets you do that. clearHeistCache :: Heist b -> IO () module Snap.Snaplet.Session -- | Any Haskell record that is a member of the ISessionManager -- typeclass can be stuffed inside a SessionManager to enable all -- session-related functionality. -- -- To use sessions in your application, just find a Backend that would -- produce one for you inside of your Initializer. See -- initCookieSessionManager in CookieSession for a -- built-in option that would get you started. data SessionManager -- | Wrap around a handler, committing any changes in the session at the -- end withSession :: SnapletLens b SessionManager -> Handler b v a -> Handler b v a -- | Commit changes to session within the current request cycle commitSession :: Handler b SessionManager () -- | Set a key-value pair in the current session setInSession :: Text -> Text -> Handler b SessionManager () -- | Get a key from the current session getFromSession :: Text -> Handler b SessionManager (Maybe Text) -- | Remove a key from the current session deleteFromSession :: Text -> Handler b SessionManager () -- | Returns a CSRF Token unique to the current session csrfToken :: Handler b SessionManager Text -- | Return session contents as an association list sessionToList :: Handler b SessionManager [(Text, Text)] -- | Deletes the session cookie, effectively resetting the session resetSession :: Handler b SessionManager () -- | Touch the session so the timeout gets refreshed touchSession :: Handler b SessionManager () -- | Arbitrary payload with timestamp. type SecureCookie t = (UTCTime, t) getSecureCookie :: (MonadSnap m, Serialize t) => ByteString -> Key -> Maybe Int -> m (Maybe t) -- | Inject the payload setSecureCookie :: (MonadSnap m, Serialize t) => ByteString -> Key -> Maybe Int -> t -> m () -- | Validate session against timeout policy. -- -- checkTimeout :: MonadSnap m => Maybe Int -> UTCTime -> m Bool -- | This module contains all the central authentication functionality. -- -- It exports a number of high-level functions to be used directly in -- your application handlers. -- -- We also export a number of mid-level functions that should be helpful -- when you are integrating with another way of confirming the -- authentication of login requests. module Snap.Snaplet.Auth -- | Create a new user from just a username and password createUser :: Text -> ByteString -> Handler b (AuthManager b) (Either AuthFailure AuthUser) -- | Check whether a user with the given username exists. usernameExists :: Text -> Handler b (AuthManager b) Bool -- | Create or update a given user saveUser :: AuthUser -> Handler b (AuthManager b) (Either AuthFailure AuthUser) -- | Destroy the given user destroyUser :: AuthUser -> Handler b (AuthManager b) () -- | Lookup a user by her username, check given password and perform login loginByUsername :: ByteString -> Password -> Bool -> Handler b (AuthManager b) (Either AuthFailure AuthUser) -- | Remember user from the remember token if possible and perform login loginByRememberToken :: Handler b (AuthManager b) (Maybe AuthUser) -- | Login and persist the given AuthUser in the active session -- -- Meant to be used if you have other means of being sure that the person -- is who she says she is. forceLogin :: AuthUser -> Handler b (AuthManager b) (Either AuthFailure AuthUser) -- | Logout the active user logout :: Handler b (AuthManager b) () -- | Return the current user; trying to remember from cookie if possible. currentUser :: Handler b (AuthManager b) (Maybe AuthUser) -- | Convenience wrapper around rememberUser that returns a bool -- result isLoggedIn :: Handler b (AuthManager b) Bool -- | Mutate an AuthUser, marking successful authentication -- -- This will save the user to the backend. markAuthSuccess :: AuthUser -> Handler b (AuthManager b) (Either AuthFailure AuthUser) -- | Mutate an AuthUser, marking failed authentication -- -- This will save the user to the backend. markAuthFail :: AuthUser -> Handler b (AuthManager b) (Either AuthFailure AuthUser) -- | Authenticate and log the user into the current session if successful. -- -- This is a mid-level function exposed to allow roll-your-own ways of -- looking up a user from the database. -- -- This function will: -- --
    --
  1. Check the password
  2. --
  3. Login the user into the current session
  4. --
  5. Mark success/failure of the authentication trial on the user -- record
  6. --
checkPasswordAndLogin :: AuthUser -> Password -> Handler b (AuthManager b) (Either AuthFailure AuthUser) -- | Abstract data type holding all necessary information for auth -- operation data AuthManager b AuthManager :: r -> SnapletLens b SessionManager -> Maybe AuthUser -> Int -> ByteString -> Maybe Int -> Key -> Maybe (Int, NominalDiffTime) -> RNG -> AuthManager b -- | Storage back-end backend :: AuthManager b -> r -- | A lens pointer to a SessionManager session :: AuthManager b -> SnapletLens b SessionManager -- | A per-request logged-in user cache activeUser :: AuthManager b -> Maybe AuthUser -- | Password length range minPasswdLen :: AuthManager b -> Int -- | Cookie name for the remember token rememberCookieName :: AuthManager b -> ByteString -- | Remember period in seconds. Defaults to 2 weeks. rememberPeriod :: AuthManager b -> Maybe Int -- | A unique encryption key used to encrypt remember cookie siteKey :: AuthManager b -> Key -- | Lockout after x tries, re-allow entry after y seconds lockout :: AuthManager b -> Maybe (Int, NominalDiffTime) -- | Random number generator randomNumberGenerator :: AuthManager b -> RNG -- | All storage backends need to implement this typeclass class IAuthBackend r save :: IAuthBackend r => r -> AuthUser -> IO (Either AuthFailure AuthUser) lookupByUserId :: IAuthBackend r => r -> UserId -> IO (Maybe AuthUser) lookupByLogin :: IAuthBackend r => r -> Text -> IO (Maybe AuthUser) lookupByRememberToken :: IAuthBackend r => r -> Text -> IO (Maybe AuthUser) destroy :: IAuthBackend r => r -> AuthUser -> IO () -- | Authetication settings defined at initialization time data AuthSettings AuthSettings :: Int -> ByteString -> Maybe Int -> Maybe (Int, NominalDiffTime) -> FilePath -> AuthSettings -- | Currently not used/checked asMinPasswdLen :: AuthSettings -> Int -- | Name of the desired remember cookie asRememberCookieName :: AuthSettings -> ByteString -- | How long to remember when the option is used in rest of the API. -- Nothing means remember until end of session. asRememberPeriod :: AuthSettings -> Maybe Int -- | Lockout strategy: ([MaxAttempts], [LockoutDuration]) asLockout :: AuthSettings -> Maybe (Int, NominalDiffTime) -- | Location of app's encryption key asSiteKey :: AuthSettings -> FilePath -- | Default settings for Auth. -- --
--   asMinPasswdLen = 8
--   asRememberCookieName = "_remember"
--   asRememberPeriod = Just (2*7*24*60*60) = 2 weeks
--   asLockout = Nothing
--   asSiteKey = "site_key.txt"
--   
defAuthSettings :: AuthSettings -- | Type representing the concept of a User in your application. data AuthUser AuthUser :: Maybe UserId -> Text -> Maybe Text -> Maybe Password -> Maybe UTCTime -> Maybe UTCTime -> Maybe Text -> Int -> Int -> Maybe UTCTime -> Maybe UTCTime -> Maybe UTCTime -> Maybe ByteString -> Maybe ByteString -> Maybe UTCTime -> Maybe UTCTime -> Maybe Text -> Maybe UTCTime -> [Role] -> HashMap Text Value -> AuthUser userId :: AuthUser -> Maybe UserId userLogin :: AuthUser -> Text userEmail :: AuthUser -> Maybe Text userPassword :: AuthUser -> Maybe Password userActivatedAt :: AuthUser -> Maybe UTCTime userSuspendedAt :: AuthUser -> Maybe UTCTime userRememberToken :: AuthUser -> Maybe Text userLoginCount :: AuthUser -> Int userFailedLoginCount :: AuthUser -> Int userLockedOutUntil :: AuthUser -> Maybe UTCTime userCurrentLoginAt :: AuthUser -> Maybe UTCTime userLastLoginAt :: AuthUser -> Maybe UTCTime userCurrentLoginIp :: AuthUser -> Maybe ByteString userLastLoginIp :: AuthUser -> Maybe ByteString userCreatedAt :: AuthUser -> Maybe UTCTime userUpdatedAt :: AuthUser -> Maybe UTCTime userResetToken :: AuthUser -> Maybe Text userResetRequestedAt :: AuthUser -> Maybe UTCTime userRoles :: AuthUser -> [Role] userMeta :: AuthUser -> HashMap Text Value -- | Default AuthUser that has all empty values. defAuthUser :: AuthUser -- | Internal representation of a User. By convention, we demand -- that the application is able to directly fetch a User using -- this identifier. -- -- Think of this type as a secure, authenticated user. You should -- normally never see this type unless a user has been authenticated. newtype UserId UserId :: Text -> UserId unUid :: UserId -> Text -- | Password is clear when supplied by the user and encrypted later when -- returned from the db. data Password ClearText :: ByteString -> Password Encrypted :: ByteString -> Password -- | Authentication failures indicate what went wrong during -- authentication. They may provide useful information to the developer, -- although it is generally not advisable to show the user the exact -- details about why login failed. data AuthFailure AuthError :: String -> AuthFailure BackendError :: AuthFailure DuplicateLogin :: AuthFailure EncryptedPassword :: AuthFailure IncorrectPassword :: AuthFailure -- | Locked out until given time LockedOut :: UTCTime -> AuthFailure PasswordMissing :: AuthFailure UsernameMissing :: AuthFailure UserNotFound :: AuthFailure -- | This will be replaced by a role-based permission system. data Role Role :: ByteString -> Role -- | Function to get auth settings from a config file. This function can be -- used by the authors of auth snaplet backends in the initializer to let -- the user configure the auth snaplet from a config file. All options -- are optional and default to what's in defAuthSettings if not supplied. -- Here's what the default options would look like in the config file: -- --
--   minPasswordLen = 8
--   rememberCookie = "_remember"
--   rememberPeriod = 1209600 # 2 weeks
--   lockout = [5, 86400] # 5 attempts locks you out for 86400 seconds
--   siteKey = "site_key.txt"
--   
authSettingsFromConfig :: Initializer b v AuthSettings -- | Run a function on the backend, and return the result. -- -- This uses an existential type so that the backend type doesn't -- escape AuthManager. The reason that the type is Handler b -- (AuthManager v) a and not a is because anything that uses the backend -- will return an IO something, which you can liftIO, or a Handler b -- (AuthManager v) a if it uses other handler things. withBackend :: (forall r. IAuthBackend r => r -> Handler b (AuthManager v) a) -> Handler b (AuthManager v) a -- | Turn a ClearText password into an Encrypted password, -- ready to be stuffed into a database. encryptPassword :: Password -> IO Password checkPassword :: Password -> Password -> Bool -- | Check password for a given user. -- -- Returns Nothing if check is successful and an -- IncorrectPassword error otherwise authenticatePassword :: AuthUser -> Password -> Maybe AuthFailure -- | Set a new password for the given user. Given password should be -- clear-text; it will be encrypted into a Encrypted. setPassword :: AuthUser -> ByteString -> IO AuthUser -- | The underlying encryption function, in case you need it for external -- processing. encrypt :: ByteString -> IO ByteString -- | The underlying verify function, in case you need it for external -- processing. verify :: ByteString -> ByteString -> Bool -- | Register a new user by specifying login and password Param -- fields registerUser :: ByteString -> ByteString -> Handler b (AuthManager b) (Either AuthFailure AuthUser) -- | A MonadSnap handler that processes a login form. -- -- The request paremeters are passed to performLogin -- -- To make your users stay logged in for longer than the session replay -- prevention timeout, you must pass a field name as the third parameter -- and that field must be set to a value of "1" by the submitting form. -- This lets you use a user selectable check box. Or if you want user -- remembering always turned on, you can use a hidden form field. loginUser :: ByteString -> ByteString -> Maybe ByteString -> (AuthFailure -> Handler b (AuthManager b) ()) -> Handler b (AuthManager b) () -> Handler b (AuthManager b) () -- | Simple handler to log the user out. Deletes user from session. logoutUser :: Handler b (AuthManager b) () -> Handler b (AuthManager b) () -- | Require that an authenticated AuthUser is present in the -- current session. -- -- This function has no DB cost - only checks to see if a user_id is -- present in the current session. requireUser :: SnapletLens b (AuthManager b) -> Handler b v a -> Handler b v a -> Handler b v a -- | This function generates a random password reset token and stores it in -- the database for the user. Call this function when a user forgets -- their password. Then use the token to autogenerate a link that the -- user can visit to reset their password. This function also sets a -- timestamp so the reset token can be expired. setPasswordResetToken :: Text -> Handler b (AuthManager b) (Maybe Text) -- | Clears a user's password reset token. Call this when the user -- successfully changes their password to ensure that the password reset -- link cannot be used again. clearPasswordResetToken :: Text -> Handler b (AuthManager b) Bool -- | Add all standard auth splices to a Heist-enabled application. -- -- This adds the following splices: <ifLoggedIn> -- <ifLoggedOut> <loggedInUser> addAuthSplices :: HasHeist b => SnapletLens b (AuthManager b) -> Initializer b v () -- | List containing compiled splices for ifLoggedIn, ifLoggedOut, and -- loggedInUser. compiledAuthSplices :: SnapletLens b (AuthManager b) -> [(Text, SnapletCSplice b)] -- | Compiled splices for AuthUser. userCSplices :: Monad m => [(Text, Promise AuthUser -> Splice m)] -- | A splice that can be used to check for existence of a user. If a user -- is present, this will run the contents of the node. -- --
--   <ifLoggedIn> Show this when there is a logged in user </ifLoggedIn>
--   
ifLoggedIn :: SnapletLens b (AuthManager b) -> SnapletISplice b -- | A splice that can be used to check for absence of a user. If a user is -- not present, this will run the contents of the node. -- --
--   <ifLoggedOut> Show this when there is a logged in user </ifLoggedOut>
--   
ifLoggedOut :: SnapletLens b (AuthManager b) -> SnapletISplice b -- | A splice that will simply print the current user's login, if there is -- one. loggedInUser :: SnapletLens b (AuthManager b) -> SnapletISplice b module Snap.Snaplet.Auth.Backends.JsonFile -- | Initialize a JSON file backed AuthManager initJsonFileAuthManager :: AuthSettings -> SnapletLens b SessionManager -> FilePath -> SnapletInit b (AuthManager b) -- | Load/create a datafile into memory cache and return the manager. -- -- This data type can be used by itself for batch/non-handler processing. mkJsonAuthMgr :: FilePath -> IO JsonFileAuthManager instance FromJSON UserCache instance ToJSON UserCache instance IAuthBackend JsonFileAuthManager instance FromJSON UserIdCache instance ToJSON UserIdCache module Snap.Snaplet.Session.Backends.CookieSession -- | Initialize a cookie-backed session, returning a SessionManager -- to be stuffed inside your application's state. This -- SessionManager will enable the use of all session storage -- functionality defined in Session initCookieSessionManager :: FilePath -> ByteString -> Maybe Int -> SnapletInit b SessionManager instance Typeable CookieSessionManager instance Eq CookieSession instance Show CookieSession instance Eq Payload instance Show Payload instance Ord Payload instance Serialize Payload instance ISessionManager CookieSessionManager instance (Serialize k, Serialize v, Hashable k, Eq k) => Serialize (HashMap k v) instance Serialize CookieSession -- | The Snap.Snaplet.Test module contains primitives and combinators for -- testing Snaplets. module Snap.Snaplet.Test -- | Given a Snaplet Handler, a SnapletInit specifying the initial -- state, and a RequestBuilder defining a test request, runs the -- handler, returning the monadic value it produces. -- -- Throws an exception if the Snap handler early-terminates with -- finishWith or mzero. -- -- Note that the output of this function is slightly different from -- 'evalHandler defined in Snap.Test, because due to the fact running the -- initializer inside SnapletInit can throw an exception. evalHandler :: MonadIO m => RequestBuilder m () -> Handler b b a -> SnapletInit b b -> m (Either Text a) -- | Given a Snaplet Handler and a RequestBuilder defining a test -- request, runs the Handler, producing an HTTP Response. -- -- Note that the output of this function is slightly different from -- runHandler defined in Snap.Test, because due to the fact -- running the initializer inside SnapletInit can throw an -- exception. runHandler :: MonadIO m => RequestBuilder m () -> Handler b b a -> SnapletInit b b -> m (Either Text Response) -- | Remove the given file before running an IO computation. Obviously it -- can be used with Assertion. withTemporaryFile :: FilePath -> IO () -> IO () -- | This module provides convenience exports of the modules most commonly -- used when developing with the Snap Framework. For documentation about -- Snaplets, see Snap.Snaplet. For the core web server API, see -- Snap.Core. module Snap