-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Authentication plugin for Yesod.
--   
--   This package is the Yesod.Auth.HashDB plugin, originally included in
--   yesod-auth, but now modified to be more secure and placed in a
--   separate package.
@package yesod-auth-hashdb
@version 1.3.2


-- | A yesod-auth AuthPlugin designed to look users up in Persist where
--   their user id's and a hash of their password is stored.
--   
--   This module was removed from <tt>yesod-auth-1.3.0.0</tt> and is now
--   maintained separately. Versions of this module prior to
--   <tt>yesod-auth-1.3</tt> used a relatively weak hashing algorithm (a
--   single round of SHA1) which does not provide adequate protection
--   against an attacker who discovers the hashed passwords. See:
--   <a>https://github.com/yesodweb/yesod/issues/668</a>.
--   
--   It has now been rewritten to use <a>Crypto.PasswordStore</a>, but this
--   has been done in a way which preserves compatibility both with the API
--   and with databases which have been set up using older versions of this
--   module. There are two levels of database compatibility:
--   
--   <ul>
--   <li>The verification code recognises both the old and new hash
--   formats, so passwords can be verified against database entries which
--   still contain old-style hashes.</li>
--   <li>The function <a>upgradePasswordHash</a> can be used to migrate
--   existing user records to use the new format hash. Unlike freshly
--   created password hashes, entries converted this way must still have
--   the old salt field, since the old hash function remains part of the
--   algorithm needed for verification. (The new hash is layered on top of
--   the old one.)</li>
--   </ul>
--   
--   On the other hand, new passwords set up by <a>setPassword</a> or
--   <a>setPasswordStrength</a> no longer use a separate salt field, so new
--   users of this module need only provide a single password field in the
--   user data, and can ignore the salt.
--   
--   In a system which has been migrated from the old format, passwords
--   which are reset using the new format will have an empty salt field.
--   Once all the entries are of this form, it is safe to change the model
--   to remove the salt, and change the <a>HashDBUser</a> instance
--   accordingly.
--   
--   To use this in a Yesod application, it must be an instance of
--   YesodPersist, and the username and hashed-passwords should be added to
--   the database. The followng steps give an outline of what is required.
--   
--   You need a database table to store user records: in a scaffolded site
--   it might look like:
--   
--   <pre>
--   User
--       name Text             -- user name used by HashDB
--       password Text Maybe   -- password hash for HashDB
--       UniqueUser name
--   </pre>
--   
--   Create an instance of <a>HashDBUser</a> for this data type:
--   
--   <pre>
--   instance HashDBUser User where
--       userPasswordHash = userPassword
--       setPasswordHash h p = p { userPassword = Just h }
--   </pre>
--   
--   In the YesodAuth instance declaration for your app, include
--   <a>authHashDB</a> like so:
--   
--   <pre>
--   instance YesodAuth App where
--       ....
--       authPlugins _ = [ authHashDB (Just . UniqueUser), .... ]
--       getAuthId = getAuthIdHashDB AuthR (Just . UniqueUser)
--   </pre>
--   
--   <tt>AuthR</tt> should be your authentication route, and the function
--   <tt>(Just . UniqueUser)</tt> supplied to both <a>authHashDB</a> and
--   <a>getAuthIdHashDB</a> takes a <a>Text</a> and produces a
--   <a>Unique</a> value to look up in the User table.
--   <a>getAuthIdHashDB</a> is just a convenience for the case when
--   <tt>HashDB</tt> is the only plugin, and something else would be needed
--   when other plugins are used as well.
--   
--   You can create password hashes manually as follows, if you need to
--   initialise the database:
--   
--   <pre>
--   ghci -XOverloadedStrings
--   &gt; import Crypto.PasswordStore
--   &gt; makePassword "MyPassword" 14
--   </pre>
--   
--   where "14" is the default strength parameter used in this module.
--   
--   == Custom Login Form
--   
--   Instead of using the built-in HTML form, a custom one can be supplied
--   by using <a>authHashDBWithForm</a> instead of <a>authHashDB</a>.
--   
--   The custom form needs to be given as a function returning a Widget,
--   since it has to build in the supplied <a>action</a> URL, and it must
--   provide two text fields called <a>username</a> and <a>password</a>.
--   For example, the following modification of the outline code given
--   above would replace the default form with a very minimal one which has
--   no labels and a simple layout.
--   
--   <pre>
--   instance YesodAuth App where
--       ....
--       authPlugins _ = [ authHashDBWithForm myform (Just . UniqueUser), .... ]
--   
--   myform :: Route App -&gt; Widget
--   myform action = $(whamletFile "templates/loginform.hamlet")
--   </pre>
--   
--   where templates/loginform.hamlet contains
--   
--   <pre>
--   &lt;form method="post" action="@{action}"&gt;
--       &lt;input name="username"&gt;
--       &lt;input type="password" name="password"&gt;
--       &lt;input type="submit" value="Login"&gt;
--   </pre>
module Yesod.Auth.HashDB

-- | Interface for data type which holds user info. It's just a collection
--   of getters and setters
class HashDBUser user where userPasswordSalt _ = Just "" setPasswordHash = setSaltAndPasswordHash "" setUserHashAndSalt = error "Define setSaltAndPasswordHash to get old-database compatibility" setSaltAndPasswordHash = setUserHashAndSalt
userPasswordHash :: HashDBUser user => user -> Maybe Text
userPasswordSalt :: HashDBUser user => user -> Maybe Text
setPasswordHash :: HashDBUser user => Text -> user -> user
setUserHashAndSalt :: HashDBUser user => Text -> Text -> user -> user
setSaltAndPasswordHash :: HashDBUser user => Text -> Text -> user -> user

-- | Unique keys besided the Key

-- | Default strength used for passwords (see <a>Crypto.PasswordStore</a>
--   for details).
defaultStrength :: Int

-- | Set password for user, using the given strength setting. Use this
--   function, or <a>setPassword</a>, to produce a user record containing
--   the hashed password. Unlike previous versions of this module, no
--   separate salt field is required for new passwords (but it may still be
--   required for compatibility while old password hashes remain in the
--   database).
--   
--   This function does not change the database; the calling application is
--   responsible for saving the data which is returned.
setPasswordStrength :: (MonadIO m, HashDBUser user) => Int -> Text -> user -> m user

-- | As <a>setPasswordStrength</a>, but using the <a>defaultStrength</a>
setPassword :: (MonadIO m, HashDBUser user) => Text -> user -> m user

-- | Upgrade existing user credentials to a stronger hash. The existing
--   hash may have been produced either by previous versions of this
--   module, which used a weak algorithm, or from a weaker setting in the
--   current algorithm. Use this function to produce an updated user record
--   to store in the database.
--   
--   To allow transitional use, starting from hashes produced by older
--   versions of this module, and upgrading them to the new format, we have
--   to use the hash alone, without knowledge of the user's plaintext
--   password. In this case, we apply the new algorithm to the old hash,
--   resulting in both hash functions, old and new, being used one on top
--   of the other; this situation is recognised by the hash having the new
--   format while the separate salt field is non-empty.
--   
--   Returns Nothing if the user has no password (ie if
--   <a>userPasswordHash</a> u is <a>Nothing</a> and/or
--   <a>userPasswordSalt</a> u is <a>Nothing</a>).
upgradePasswordHash :: (MonadIO m, HashDBUser user) => Int -> user -> m (Maybe user)

-- | Given a user ID and password in plaintext, validate them against the
--   database values. This function retains compatibility with databases
--   containing hashes produced by previous versions of this module,
--   although they are less secure and should be upgraded as soon as
--   possible. They can be upgraded using <a>upgradePasswordHash</a>, or by
--   insisting that users set new passwords.
validateUser :: HashDBPersist site user => Unique user -> Text -> HandlerT site IO Bool

-- | Prompt for username and password, validate that against a database
--   which holds the username and a hash of the password
authHashDB :: HashDBPersist site user => (Text -> Maybe (Unique user)) -> AuthPlugin site

-- | Like <a>authHashDB</a>, but with an extra parameter to supply a custom
--   HTML form.
--   
--   The custom form should be specified as a function which takes a route
--   to use as the form action, and returns a Widget containing the form.
--   The form must use the supplied route as its action URL, and, when
--   submitted, it must send two text fields called <a>username</a> and
--   <a>password</a>.
--   
--   Please see the example in the documentation at the head of this
--   module.
--   
--   Since 1.3.2
authHashDBWithForm :: HashDBPersist site user => (Route site -> WidgetT site IO ()) -> (Text -> Maybe (Unique user)) -> AuthPlugin site

-- | A drop in for the getAuthId method of your YesodAuth instance which
--   can be used if authHashDB is the only plugin in use.
getAuthIdHashDB :: HashDBPersist site user => (AuthRoute -> Route site) -> (Text -> Maybe (Unique user)) -> Creds site -> HandlerT site IO (Maybe (AuthId site))

-- | <i>Deprecated: The predefined User data type will be removed soon -
--   please define your own database table and accompanying instance of
--   HashDBUser </i>
type User = UserGeneric SqlBackend

-- | Generate data base instances for a valid user
data UserGeneric backend

-- | <i>Deprecated: The predefined User data type will be removed soon -
--   please define your own database table and accompanying instance of
--   HashDBUser </i>
User :: !Text -> !Text -> !Text -> UserGeneric backend
userUsername :: UserGeneric backend -> !Text
userPassword :: UserGeneric backend -> !Text
userSalt :: UserGeneric backend -> !Text
type UserId = KeyBackend SqlBackend User

-- | An <a>EntityField</a> is parameterised by the Haskell record it
--   belongs to and the additional type of that field

-- | <i>Deprecated: The predefined User data type will be removed soon -
--   please define your own database table and accompanying instance of
--   HashDBUser </i>
migrateUsers :: (MonadBaseControl IO m, MonadIO m, MonadLogger m) => Migration (SqlPersistT m)
instance Typeable1 UserGeneric
instance HashDBUser (UserGeneric backend)
instance PersistEntity (UserGeneric backend)
instance PersistFieldSql (UserGeneric backend)
instance PersistField (UserGeneric backend)
