-- 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:
--   
--   <ul>
--   <li>The Snaplets API</li>
--   <li>Snaplets for sessions, authentication, and templates</li>
--   </ul>
--   
--   To get started, issue the following sequence of commands:
--   
--   <pre>
--   $ cabal install snap snap-templates
--   $ mkdir myproject
--   $ cd myproject
--   $ snap-framework init
--   </pre>
--   
--   If you have trouble or any questions, see our FAQ page
--   (<a>http://snapframework.com/faq</a>) or the documentation
--   (<a>http://snapframework.com/docs</a>).
--   
--   Note: since version 1.0, the "snap" executable program for generating
--   starter projects is provided by the <tt>snap-templates</tt> package.
@package snap
@version 1.1.3.3

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

-- | 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 GHC.Base.Semigroup Snap.Snaplet.Config.AppConfig
instance GHC.Base.Monoid Snap.Snaplet.Config.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:
--   
--   <ul>
--   <li>each snaplet has its own configuration given to it at
--   startup.</li>
--   <li>each snaplet is given its own directory on the filesystem, from
--   which it reads its configuration and in which it can store files.</li>
--   <li>each snaplet comes with an <a>Initializer</a> which defines how to
--   create an instance of the Snaplet at startup. The initializer decides
--   how to interpret the snaplet configuration, which URLs to handle (and
--   how), sets up the initial snaplet state, tells the snaplet runtime
--   system how to clean the snaplet up, etc.</li>
--   <li>each snaplet contains some user-defined in-memory state; for
--   instance, a snaplet that talks to a database might contain a reference
--   to a connection pool. The snaplet state is an ordinary Haskell record,
--   with a datatype defined by the snaplet author. The initial state
--   record is created during initialization and is available to snaplet
--   <a>Handler</a>s when serving HTTP requests.</li>
--   </ul>
--   
--   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 <tt>s</tt> here is user-defined and can be
--   any Haskell type. A value of type <tt>Snaplet s</tt> countains a
--   couple of things:
--   
--   <ul>
--   <li>a value of type <tt>s</tt>, called the "user state".</li>
--   <li>some bookkeeping data the framework uses to plug things together,
--   like the snaplet's configuration, the snaplet's root directory on the
--   filesystem, the snaplet's root URL, and so on.</li>
--   </ul>
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 :: forall s_ao99. Lens' (Snaplet s_ao99) SnapletConfig
snapletValue :: forall s_ao99. Lens' (Snaplet s_ao99) s_ao99

-- | 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:
--   
--   <ul>
--   <li><a>withTop'</a>, <a>with'</a>, <a>getLens</a>, and
--   <a>getOpaqueConfig</a>.</li>
--   </ul>
class MonadSnaplet m

-- | Runs a child snaplet action in the current snaplet's context. If you
--   think about snaplet lenses using a filesystem path metaphor, the lens
--   supplied to this snaplet must be a relative path. In other words, the
--   lens's base state must be the same as the current snaplet.
with :: MonadSnaplet m => SnapletLens v v' -> m b v' a -> m b v a

-- | Like <a>with</a> but doesn't impose the requirement that the action
--   being run be a descendant of the current snaplet. Using our filesystem
--   metaphor again, the lens for this function must be an absolute
--   path--it's base must be the same as the current base.
withTop :: MonadSnaplet m => SnapletLens b v' -> m b v' a -> m b v a

-- | A variant of <a>with</a> accepting a lens from snaplet to snaplet.
--   Unlike the lens used in the above <a>with</a> function, this lens
--   formulation has an identity, which makes it useful in certain
--   circumstances. The lenses generated by <a>makeLenses</a> will not work
--   with this function, however the lens returned by <a>getLens</a> will.
--   
--   <pre>
--   with = with' . subSnaplet
--   </pre>
with' :: MonadSnaplet m => SnapletLens (Snaplet v) v' -> m b v' a -> m b v a

-- | The absolute version of <a>with'</a>
withTop' :: MonadSnaplet m => SnapletLens (Snaplet b) v' -> m b v' a -> m b v a

-- | Gets the lens for the current snaplet.
getLens :: MonadSnaplet m => m b v (SnapletLens (Snaplet b) v)

-- | Gets the current snaplet's opaque config data type. You'll only use
--   this function when writing MonadSnaplet instances.
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 <tt>nestSnaplet</tt>.
getSnapletRootURL :: (Monad (m b v), MonadSnaplet m) => m b v ByteString

-- | Constructs a url relative to the current snaplet.
snapletURL :: (Monad (m b v), MonadSnaplet m) => ByteString -> 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 <tt>Snaplet v</tt> from the current snaplet's state.
getSnapletState :: Handler b v (Snaplet v)

-- | Puts a new <tt>Snaplet v</tt> in the current snaplet's state.
putSnapletState :: Snaplet v -> Handler b v ()

-- | Modifies the <tt>Snaplet v</tt> in the current snaplet's state.
modifySnapletState :: (Snaplet v -> Snaplet v) -> Handler b v ()

-- | Gets the <tt>Snaplet v</tt> 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
--   <tt>makeSnaplet</tt>, which handles standardized housekeeping common
--   to all snaplets. Common usage will look something like this:
--   
--   <pre>
--   fooInit :: SnapletInit b Foo
--   fooInit = makeSnaplet "foo" "An example snaplet" Nothing $ do
--       -- Your initializer code here
--       return $ Foo 42
--   </pre>
--   
--   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 <a>nestSnaplet</a> is the first
--   type parameter in the third argument. The "v1 v1" makes the child
--   snaplet think that it is the top-level state, 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.
--   
--   Note that this function does not change where this snaplet is located
--   in the filesystem. The snaplet directory structure convention stays
--   the same. Also, embedSnaplet limits the ways that snaplets can
--   interact, so we usually recommend using nestSnaplet instead. However,
--   we provide this function because sometimes reduced flexibility is
--   useful. In short, if you don't understand what this function does for
--   you from looking at its type, you probably don't want to use it.
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:
--   
--   <pre>
--   fooState &lt;- nestSnaplet "fooA" $ nameSnaplet "myFoo" $ fooInit
--   </pre>
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
--   <tt>addTemplates</tt> function which allows other snaplets to set up
--   their own templates. <tt>addTemplates</tt> is implemented using this
--   function.
addPostInitHook :: (v -> IO (Either Text v)) -> Initializer b v ()

-- | Variant of addPostInitHook for when you have things wrapped in a
--   Snaplet.
addPostInitHookBase :: (Snaplet b -> IO (Either Text (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]

-- | Return the current environment string. This will be the environment
--   given to <a>runSnaplet</a> or from the command line when using
--   <a>serveSnaplet</a>. Useful for changing behavior during development
--   and testing.
getEnvironment :: Initializer b v String

-- | Adds routing to the current <a>Handler</a>. 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 <i>base</i> 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:
--   
--   <pre>
--   wrapSite (\site -&gt; logHandlerStart &gt;&gt; site &gt;&gt; logHandlerFinished)
--   wrapSite (\site -&gt; ensureAdminUser &gt;&gt; site)
--   </pre>
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 <a>MonadSnap</a>, which
--   means it is the monad you will use to write all your application
--   routes. It also has a <a>MonadSnaplet</a> instance, which gives you
--   all the functionality described above.
data Handler b v a

-- | Pass if the request is not coming from localhost.
failIfNotLocal :: MonadSnap m => m b -> m b

-- | Handler that reloads the site.
reloadSite :: Handler b v ()

-- | Lets you change a snaplet's initial state. It's almost like a reload,
--   except that it doesn't run the initializer. It just modifies the
--   result of the initializer. This can be used to let you define actions
--   for reloading individual snaplets.
modifyMaster :: v -> Handler b v ()

-- | This function brackets a Handler action in resource acquisition and
--   release. Like <a>bracketSnap</a>, this is provided because
--   MonadCatchIO's <tt>bracket</tt> 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.
--   
--   <ol>
--   <li>Normal completion</li>
--   <li>Short-circuit completion, either from calling <a>fail</a> or
--   <tt>finishWith</tt></li>
--   <li>An exception being thrown.</li>
--   </ol>
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 <a>Handler</a>.
serveSnaplet :: Config Snap AppConfig -> SnapletInit b b -> IO ()

-- | Like <a>serveSnaplet</a>, but don't try to parse command-line
--   arguments.
serveSnapletNoArgParsing :: 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 <tt>heistInit</tt> to
--   initialize it. The type parameter b will typically be the base state
--   type for your application.
data Heist b
data DefaultMode
Compiled :: DefaultMode
Interpreted :: DefaultMode

-- | The <a>Initializer</a> for <a>Heist</a>. This function is a
--   convenience wrapper around <a>heistInit'</a> that uses
--   defaultHeistState and sets up routes for all the templates. It sets up
--   a "heistReload" route that reloads the heist templates when you
--   request it from localhost.
heistInit :: FilePath -> SnapletInit b (Heist b)

-- | A lower level <a>Initializer</a> for <a>Heist</a>. 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)

-- | Handler that triggers a template reload. For large sites, this can be
--   desireable because it may be much quicker than the full site reload
--   provided at the <i>admin</i>reload route. This allows you to reload
--   only the heist templates This handler is automatically set up by
--   heistInit, but if you use heistInit', then you can create your own
--   route with it.
heistReloader :: Handler b (Heist b) ()

-- | Sets the snaplet to default to interpreted mode. Initially, the
--   initializer sets the value to compiled mode. This function allows you
--   to override that setting. Note that this is just a default. It only
--   has an effect if you use one of the generic functions: <a>gRender</a>,
--   <a>gRenderAs</a>, <a>gHeistServe</a>, or <a>gHeistServeSingle</a>. If
--   you call the non-generic versions directly, then this value will not
--   be checked and you will get the mode implemented by the function you
--   called.
setInterpreted :: Snaplet (Heist b) -> Initializer b v ()
getCurHeistConfig :: Snaplet (Heist b) -> Initializer b v (HeistConfig (Handler b 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) ()
getHeistState :: SnapletLens (Snaplet b) (Heist b) -> Handler b v (HeistState (Handler b 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

-- | Like render/cRender, but chooses between the two appropriately based
--   on the default mode.
gRender :: ByteString -> Handler b (Heist b) ()

-- | Like renderAs/cRenderAs, but chooses between the two appropriately
--   based on the default mode.
gRenderAs :: ByteString -> ByteString -> Handler b (Heist b) ()

-- | Like heistServe/cHeistServe, but chooses between the two appropriately
--   based on the default mode.
gHeistServe :: Handler b (Heist b) ()

-- | Like heistServeSingle/cHeistServeSingle, but chooses between the two
--   appropriately based on the default mode.
gHeistServeSingle :: ByteString -> Handler b (Heist b) ()

-- | Chooses between a compiled action and an interpreted action based on
--   the configured default.
chooseMode :: MonadState (Heist b1) m => m b -> m b -> m b

-- | 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) -> SpliceConfig (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) -> Splices (SnapletISplice b) -> Handler b v a -> Handler b v a
renderWithSplices :: SnapletLens b (Heist b) -> ByteString -> Splices (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) -> Splices (SnapletISplice b) -> Handler b v a -> Handler b v a
renderWithSplices' :: SnapletLens (Snaplet b) (Heist b) -> ByteString -> Splices (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 Snap.Internal.Core.MonadSnap m => Snap.Internal.Core.MonadSnap (Heist.Internal.Types.HeistState.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 <tt>heistInit</tt> 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:
--   
--   <pre>
--   data App = App { _heist :: Snaplet (Heist App) }
--   makeLenses ''App
--   
--   instance HasHeist App where heistLens = subSnaplet heist
--   
--   appInit = makeSnaplet "app" "" Nothing $ do
--       h &lt;- nestSnaplet "heist" heist $ heistInit "templates"
--       addConfig h heistConfigWithMyAppSplices
--       return $ App h
--   </pre>
class HasHeist b

-- | A lens to the Heist snaplet. The b parameter to Heist will typically
--   be the base state of your application.
heistLens :: HasHeist b => SnapletLens (Snaplet b) (Heist b)

-- | The <a>Initializer</a> for <a>Heist</a>. This function is a
--   convenience wrapper around <a>heistInit'</a> that uses
--   defaultHeistState and sets up routes for all the templates. It sets up
--   a "heistReload" route that reloads the heist templates when you
--   request it from localhost.
heistInit :: FilePath -> SnapletInit b (Heist b)

-- | A lower level <a>Initializer</a> for <a>Heist</a>. 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)

-- | Handler that triggers a template reload. For large sites, this can be
--   desireable because it may be much quicker than the full site reload
--   provided at the <i>admin</i>reload route. This allows you to reload
--   only the heist templates This handler is automatically set up by
--   heistInit, but if you use heistInit', then you can create your own
--   route with it.
heistReloader :: Handler b (Heist b) ()

-- | Sets the snaplet to default to interpreted mode. Initially, the
--   initializer sets the value to compiled mode. This function allows you
--   to override that setting. Note that this is just a default. It only
--   has an effect if you use one of the generic functions: <a>gRender</a>,
--   <a>gRenderAs</a>, <a>gHeistServe</a>, or <a>gHeistServeSingle</a>. If
--   you call the non-generic versions directly, then this value will not
--   be checked and you will get the mode implemented by the function you
--   called.
setInterpreted :: Snaplet (Heist b) -> Initializer b v ()
getCurHeistConfig :: Snaplet (Heist b) -> Initializer b v (HeistConfig (Handler b 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) -> SpliceConfig (Handler b b) -> Initializer b v ()

-- | More general function allowing arbitrary HeistState modification.
getHeistState :: HasHeist b => Handler b v (HeistState (Handler b b))

-- | 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 <a>HeistState</a>.
withHeistState :: HasHeist b => (HeistState (Handler b b) -> a) -> Handler b v a

-- | Generic version of <a>render</a>/<a>cRender</a>.
gRender :: HasHeist b => ByteString -> Handler b v ()

-- | Generic version of <a>renderAs</a>/<a>cRenderAs</a>.
gRenderAs :: HasHeist b => ByteString -> ByteString -> Handler b v ()

-- | Generic version of <a>heistServe</a>/<a>cHeistServe</a>.
gHeistServe :: HasHeist b => Handler b v ()

-- | Generic version of <a>heistServeSingle</a>/<a>cHeistServeSingle</a>.
gHeistServeSingle :: HasHeist b => ByteString -> Handler b v ()

-- | Chooses between a compiled action and an interpreted action based on
--   the configured default.
chooseMode :: HasHeist b => Handler b v a -> Handler b v a -> Handler b v a

-- | Renders a compiled template as text/html. If the given template is not
--   found, this returns <tt>empty</tt>.
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 <tt>empty</tt>.
cRenderAs :: HasHeist b => ByteString -> ByteString -> Handler b v ()

-- | A compiled version of <a>heistServe</a>.
cHeistServe :: HasHeist b => Handler b v ()

-- | Analogous to <tt>fileServeSingle</tt>. 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 <tt>empty</tt>.
render :: HasHeist b => ByteString -> Handler b v ()

-- | Renders a template as the given content type. If the given template is
--   not found, this returns <tt>empty</tt>.
renderAs :: HasHeist b => ByteString -> ByteString -> Handler b v ()

-- | A handler that serves all the templates (similar to
--   <tt>serveDirectory</tt>). If the template specified in the request
--   path is not found, it returns <tt>empty</tt>. 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
--   <tt>fileServeSingle</tt>). If the given template is not found, this
--   throws an error.
heistServeSingle :: HasHeist b => ByteString -> Handler b v ()

-- | Runs a handler with a modified <a>HeistState</a>. 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:
--   
--   <pre>
--   heistLocal (bindSplices mySplices) handlerThatNeedsSplices
--   </pre>
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
--   <a>HeistState</a>.
withSplices :: HasHeist b => Splices (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 -> Splices (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 <tt>heistInit</tt> 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:
--   
--   <pre>
--   data App = App { _heist :: Snaplet (Heist App) }
--   makeLenses ''App
--   
--   instance HasHeist App where heistLens = subSnaplet heist
--   
--   appInit = makeSnaplet "app" "" Nothing $ do
--       h &lt;- nestSnaplet "heist" heist $ heistInit "templates"
--       addConfig h heistConfigWithMyAppSplices
--       return $ App h
--   </pre>
class HasHeist b

-- | A lens to the Heist snaplet. The b parameter to Heist will typically
--   be the base state of your application.
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 <a>Initializer</a> for <a>Heist</a>. This function is a
--   convenience wrapper around <a>heistInit'</a> that uses
--   defaultHeistState and sets up routes for all the templates. It sets up
--   a "heistReload" route that reloads the heist templates when you
--   request it from localhost.
heistInit :: FilePath -> SnapletInit b (Heist b)

-- | A lower level <a>Initializer</a> for <a>Heist</a>. 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) -> SpliceConfig (Handler b b) -> Initializer b v ()

-- | More general function allowing arbitrary HeistState modification.
getHeistState :: HasHeist b => Handler b v (HeistState (Handler b b))

-- | 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 <a>HeistState</a>.
withHeistState :: HasHeist b => (HeistState (Handler b b) -> a) -> Handler b v a

-- | Renders a template as text/html. If the given template is not found,
--   this returns <tt>empty</tt>.
render :: HasHeist b => ByteString -> Handler b v ()

-- | Renders a template as the given content type. If the given template is
--   not found, this returns <tt>empty</tt>.
renderAs :: HasHeist b => ByteString -> ByteString -> Handler b v ()

-- | A handler that serves all the templates (similar to
--   <tt>serveDirectory</tt>). If the template specified in the request
--   path is not found, it returns <tt>empty</tt>. 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
--   <tt>fileServeSingle</tt>). If the given template is not found, this
--   throws an error.
heistServeSingle :: HasHeist b => ByteString -> Handler b v ()

-- | Runs a handler with a modified <a>HeistState</a>. 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:
--   
--   <pre>
--   heistLocal (bindSplices mySplices) handlerThatNeedsSplices
--   </pre>
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
--   <a>HeistState</a>.
withSplices :: HasHeist b => Splices (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 -> Splices (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 generic functions that choose between compiled
--   and interpreted mode based on the setting specified in the
--   initializer. This module is most useful for writitng general snaplets
--   that use Heist and are meant to be used in applications that might use
--   either interpreted or compiled templates.
module Snap.Snaplet.Heist.Generic

-- | The state for the Heist snaplet. To use the Heist snaplet in your app
--   include this in your application state and use <tt>heistInit</tt> 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:
--   
--   <pre>
--   data App = App { _heist :: Snaplet (Heist App) }
--   makeLenses ''App
--   
--   instance HasHeist App where heistLens = subSnaplet heist
--   
--   appInit = makeSnaplet "app" "" Nothing $ do
--       h &lt;- nestSnaplet "heist" heist $ heistInit "templates"
--       addConfig h heistConfigWithMyAppSplices
--       return $ App h
--   </pre>
class HasHeist b

-- | A lens to the Heist snaplet. The b parameter to Heist will typically
--   be the base state of your application.
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)))

-- | 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) -> SpliceConfig (Handler b b) -> Initializer b v ()

-- | More general function allowing arbitrary HeistState modification.
getHeistState :: HasHeist b => Handler b v (HeistState (Handler b b))

-- | 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 <a>HeistState</a>.
withHeistState :: HasHeist b => (HeistState (Handler b b) -> a) -> Handler b v a

-- | Generic version of <a>render</a>/<a>cRender</a>.
gRender :: HasHeist b => ByteString -> Handler b v ()

-- | Generic version of <a>renderAs</a>/<a>cRenderAs</a>.
gRenderAs :: HasHeist b => ByteString -> ByteString -> Handler b v ()

-- | Generic version of <a>heistServe</a>/<a>cHeistServe</a>.
gHeistServe :: HasHeist b => Handler b v ()

-- | Generic version of <a>heistServeSingle</a>/<a>cHeistServeSingle</a>.
gHeistServeSingle :: HasHeist b => ByteString -> Handler b v ()

-- | Chooses between a compiled action and an interpreted action based on
--   the configured default.
chooseMode :: HasHeist b => Handler b v a -> Handler b v a -> Handler b v a

-- | 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 <tt>heistInit</tt> 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:
--   
--   <pre>
--   data App = App { _heist :: Snaplet (Heist App) }
--   makeLenses ''App
--   
--   instance HasHeist App where heistLens = subSnaplet heist
--   
--   appInit = makeSnaplet "app" "" Nothing $ do
--       h &lt;- nestSnaplet "heist" heist $ heistInit "templates"
--       addConfig h heistConfigWithMyAppSplices
--       return $ App h
--   </pre>
class HasHeist b

-- | A lens to the Heist snaplet. The b parameter to Heist will typically
--   be the base state of your application.
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 <a>Initializer</a> for <a>Heist</a>. This function is a
--   convenience wrapper around <tt>heistInit'</tt> that uses
--   defaultHeistState and sets up routes for all the templates. It sets up
--   a "heistReload" route that reloads the heist templates when you
--   request it from localhost.
heistInit :: FilePath -> SnapletInit b (Heist b)

-- | A lower level <a>Initializer</a> for <a>Heist</a>. 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)

-- | Handler that triggers a template reload. For large sites, this can be
--   desireable because it may be much quicker than the full site reload
--   provided at the <i>admin</i>reload route. This allows you to reload
--   only the heist templates This handler is automatically set up by
--   heistInit, but if you use heistInit', then you can create your own
--   route with it.
heistReloader :: Handler 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) -> SpliceConfig (Handler b b) -> Initializer b v ()

-- | More general function allowing arbitrary HeistState modification.
getHeistState :: HasHeist b => Handler b v (HeistState (Handler b b))

-- | 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 <a>HeistState</a>.
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 <tt>empty</tt>.
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 <tt>empty</tt>.
renderAs :: HasHeist b => ByteString -> ByteString -> Handler b v ()

-- | A handler that serves all the templates (similar to
--   <tt>serveDirectory</tt>). If the template specified in the request
--   path is not found, it returns <tt>empty</tt>. 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
--   <tt>fileServeSingle</tt>). 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 ()


-- | This module provides convenience exports of the modules most commonly
--   used when developing with the Snap Framework. For documentation about
--   Snaplets, see <a>Snap.Snaplet</a>. For the core web server API, see
--   <a>Snap.Core</a>.
module Snap


-- | 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


-- | 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 <a>ISessionManager</a>
--   typeclass can be stuffed inside a <a>SessionManager</a> 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 <tt>Initializer</tt>. See
--   <tt>initCookieSessionManager</tt> in <a>CookieSession</a> for a
--   built-in option that would get you started.
data SessionManager
SessionManager :: a -> SessionManager
class ISessionManager r

-- | Load a session from given payload.
--   
--   Will always be called before any other operation. If possible, cache
--   and do nothing when called multiple times within the same request
--   cycle.
load :: ISessionManager r => r -> Snap r

-- | Commit session, return a possibly updated paylaod
commit :: ISessionManager r => r -> Snap ()

-- | Reset session
reset :: ISessionManager r => r -> Snap r

-- | Touch session
touch :: ISessionManager r => r -> r

-- | Insert a key-value pair into session
insert :: ISessionManager r => Text -> Text -> r -> r

-- | Lookup a key in session
lookup :: ISessionManager r => Text -> r -> Maybe Text

-- | Delete a key in session
delete :: ISessionManager r => Text -> r -> r

-- | Return a session-specific CSRF protection token. See
--   <tt>mkCSRFToken</tt> for help in creating the value.
csrf :: ISessionManager r => r -> Text

-- | Return all key-value pairs as an association list
toList :: ISessionManager r => r -> [(Text, Text)]

module Snap.Snaplet.Session

-- | Any Haskell record that is a member of the <a>ISessionManager</a>
--   typeclass can be stuffed inside a <a>SessionManager</a> 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 <tt>Initializer</tt>. See
--   <tt>initCookieSessionManager</tt> in <a>CookieSession</a> 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)

-- | Get the cookie payload.
getSecureCookie :: (MonadSnap m, Serialize t) => ByteString -> Key -> Maybe Int -> m (Maybe t)

-- | Inject the payload.
setSecureCookie :: (MonadSnap m, Serialize t) => ByteString -> Maybe ByteString -> Key -> Maybe Int -> t -> m ()

-- | Expire secure cookie
expireSecureCookie :: MonadSnap m => ByteString -> Maybe ByteString -> m ()

-- | Encode SecureCookie with key into injectable payload
encodeSecureCookie :: (MonadIO m, Serialize t) => Key -> SecureCookie t -> m ByteString

-- | Decode secure cookie payload wih key.
decodeSecureCookie :: Serialize a => Key -> ByteString -> Maybe (SecureCookie a)

-- | Validate session against timeout policy.
--   
--   <ul>
--   <li>If timeout is set to <a>Nothing</a>, never trigger a
--   time-out.</li>
--   <li>Otherwise, do a regular time-out check based on current time and
--   given timestamp.</li>
--   </ul>
checkTimeout :: MonadSnap m => Maybe Int -> UTCTime -> m Bool

module Snap.Snaplet.Session.Backends.CookieSession

-- | Initialize a cookie-backed session, returning a <a>SessionManager</a>
--   to be stuffed inside your application's state. This
--   <a>SessionManager</a> will enable the use of all session storage
--   functionality defined in <a>Session</a>
initCookieSessionManager :: FilePath -> ByteString -> Maybe ByteString -> Maybe Int -> SnapletInit b SessionManager
instance GHC.Show.Show Snap.Snaplet.Session.Backends.CookieSession.CookieSession
instance GHC.Classes.Eq Snap.Snaplet.Session.Backends.CookieSession.CookieSession
instance Data.Serialize.Serialize Snap.Snaplet.Session.Backends.CookieSession.Payload
instance GHC.Classes.Ord Snap.Snaplet.Session.Backends.CookieSession.Payload
instance GHC.Show.Show Snap.Snaplet.Session.Backends.CookieSession.Payload
instance GHC.Classes.Eq Snap.Snaplet.Session.Backends.CookieSession.Payload
instance Snap.Snaplet.Session.SessionManager.ISessionManager Snap.Snaplet.Session.Backends.CookieSession.CookieSessionManager
instance Data.Serialize.Serialize Snap.Snaplet.Session.Backends.CookieSession.CookieSession

module Snap.Snaplet.Auth.Backends.JsonFile

-- | Initialize a JSON file backed <a>AuthManager</a>
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 Snap.Snaplet.Auth.AuthManager.IAuthBackend Snap.Snaplet.Auth.Backends.JsonFile.JsonFileAuthManager
instance Data.Aeson.Types.ToJSON.ToJSON Snap.Snaplet.Auth.Backends.JsonFile.UserCache
instance Data.Aeson.Types.FromJSON.FromJSON Snap.Snaplet.Auth.Backends.JsonFile.UserCache


-- | 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 :: Text -> 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) (Either AuthFailure AuthUser)

-- | Login and persist the given <a>AuthUser</a> 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 ())

-- | 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 <tt>rememberUser</tt> that returns a bool
--   result
isLoggedIn :: Handler b (AuthManager b) Bool

-- | Mutate an <a>AuthUser</a>, marking successful authentication
--   
--   This will save the user to the backend.
markAuthSuccess :: AuthUser -> Handler b (AuthManager b) (Either AuthFailure AuthUser)

-- | Mutate an <a>AuthUser</a>, 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:
--   
--   <ol>
--   <li>Check the password</li>
--   <li>Login the user into the current session</li>
--   <li>Mark success/failure of the authentication trial on the user
--   record</li>
--   </ol>
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 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

-- | Domain for which remember cookie will be created.
[rememberCookieDomain] :: AuthManager b -> Maybe 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

-- | Create or update the given <a>AuthUser</a> record. A <a>userId</a> of
--   Nothing indicates that a new user should be created, otherwise the
--   user information for that userId should be updated.
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)
lookupByEmail :: IAuthBackend r => r -> Text -> IO (Maybe AuthUser)
lookupByRememberToken :: IAuthBackend r => r -> Text -> IO (Maybe AuthUser)
destroy :: IAuthBackend r => r -> AuthUser -> IO ()

-- | Authentication 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.
--   <a>Nothing</a> 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.
--   
--   <pre>
--   asMinPasswdLen = 8
--   asRememberCookieName = "_remember"
--   asRememberPeriod = Just (2*7*24*60*60) = 2 weeks
--   asLockout = Nothing
--   asSiteKey = "site_key.txt"
--   </pre>
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 <tt>User</tt>. By convention, we demand
--   that the application is able to directly fetch a <tt>User</tt> 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:
--   
--   <pre>
--   minPasswordLen = 8
--   rememberCookie = "_remember"
--   rememberPeriod = 1209600 # 2 weeks
--   lockout = [5, 86400] # 5 attempts locks you out for 86400 seconds
--   siteKey = "site_key.txt"
--   </pre>
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
--   <tt>escape</tt> 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 <a>ClearText</a> password into an <a>Encrypted</a> password,
--   ready to be stuffed into a database.
encryptPassword :: Password -> IO Password
checkPassword :: Password -> Password -> Bool

-- | Check password for a given user.
--   
--   Returns <a>Nothing</a> if check is successful and an
--   <a>IncorrectPassword</a> 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 <a>Encrypted</a>.
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 <tt>Param</tt>
--   fields
registerUser :: ByteString -> ByteString -> Handler b (AuthManager b) (Either AuthFailure AuthUser)

-- | A <a>MonadSnap</a> handler that processes a login form.
--   
--   The request paremeters are passed to <tt>performLogin</tt>
--   
--   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 <a>AuthUser</a> 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: &lt;ifLoggedIn&gt;
--   &lt;ifLoggedOut&gt; &lt;loggedInUser&gt;
addAuthSplices :: HasHeist b => Snaplet (Heist b) -> SnapletLens b (AuthManager b) -> Initializer b v ()

-- | List containing compiled splices for ifLoggedIn, ifLoggedOut, and
--   loggedInUser.
compiledAuthSplices :: SnapletLens b (AuthManager b) -> Splices (SnapletCSplice b)

-- | Compiled splices for AuthUser.
userCSplices :: Monad m => Splices (RuntimeSplice m AuthUser -> Splice m)

-- | Function to generate interpreted splices from an AuthUser.
userISplices :: Monad m => AuthUser -> Splices (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.
--   
--   <pre>
--   &lt;ifLoggedIn&gt; Show this when there is a logged in user &lt;/ifLoggedIn&gt;
--   </pre>
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.
--   
--   <pre>
--   &lt;ifLoggedOut&gt; Show this when there is a logged in user &lt;/ifLoggedOut&gt;
--   </pre>
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


-- | The Snap.Snaplet.Test module contains primitives and combinators for
--   testing Snaplets.
module Snap.Snaplet.Test

-- | Given a Snaplet Handler, a <a>SnapletInit</a> specifying the initial
--   state, and a <a>RequestBuilder</a> defining a test request, runs the
--   handler, returning the monadic value it produces.
--   
--   Throws an exception if the <a>Snap</a> handler early-terminates with
--   <a>finishWith</a> or <tt>mzero</tt>.
--   
--   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 <a>SnapletInit</a> can throw an exception.
evalHandler :: MonadIO m => Maybe String -> RequestBuilder m () -> Handler b b a -> SnapletInit b b -> m (Either Text a)

-- | A variant of evalHandler that takes the Snaplet and InitializerState
--   as produced by getSnaplet, so those can be re-used across requests. It
--   does not run cleanup actions, so closeSnaplet should be used when
--   finished.
evalHandler' :: MonadIO m => Snaplet b -> InitializerState b -> RequestBuilder m () -> Handler b b a -> m (Either Text a)

-- | Given a Snaplet Handler and a <a>RequestBuilder</a> defining a test
--   request, runs the Handler, producing an HTTP <a>Response</a>.
--   
--   Note that the output of this function is slightly different from
--   <a>runHandler</a> defined in Snap.Test, because due to the fact
--   running the initializer inside <a>SnapletInit</a> can throw an
--   exception.
runHandler :: MonadIO m => Maybe String -> RequestBuilder m () -> Handler b b v -> SnapletInit b b -> m (Either Text Response)

-- | A variant of runHandler that takes the Snaplet and InitializerState as
--   produced by getSnaplet, so those can be re-used across requests. It
--   does not run cleanup actions, so closeSnaplet should be used when
--   finished.
runHandler' :: MonadIO m => Snaplet b -> InitializerState b -> RequestBuilder m () -> Handler b b v -> m (Either Text Response)

-- | Run the given initializer, yielding a tuple where the first element is
--   a <tt>Snaplet b</tt>, or an error message whether the initializer
--   threw an exception. This is only needed for runHandler'/evalHandler'.
getSnaplet :: MonadIO m => Maybe String -> SnapletInit b b -> m (Either Text (Snaplet b, InitializerState b))

-- | Run cleanup for an initializer. Should be run after finished using the
--   state that getSnaplet returned. Only needed if using getSnaplet and
--   evalHandler'/runHandler'.
closeSnaplet :: MonadIO m => InitializerState b -> m ()

-- | Information about a partially constructed initializer. Used to
--   automatically aggregate handlers and cleanup actions.
data InitializerState b

-- | Remove the given file after running an IO computation. Obviously it
--   can be used with <tt>Assertion</tt>.
withTemporaryFile :: FilePath -> IO () -> IO ()
