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


-- | A library simplifying user management for web applications
--   
--   Scrap the boilerplate for managing user accounts in web applications
--   
--   Features:
--   
--   <ul>
--   <li>Easy to understand API</li>
--   <li>CRUD for Users</li>
--   <li>Session Management</li>
--   <li>Password reset functionality</li>
--   <li>Activation functionality</li>
--   </ul>
--   
--   Current Backends:
--   
--   <ul>
--   <li><a>PostgreSQL-Simple Backend</a></li>
--   <li><a>Persistent Backend</a></li>
--   </ul>
@package users
@version 0.5.0.0

module Web.Users.Types

-- | An abstract backend for managing users. A backend library should
--   implement the interface and an end user should build applications on
--   top of this interface.
class IsUserBackend b => UserStorageBackend b where type UserId b :: * where {
    type family UserId b :: *;
}

-- | Initialise the backend. Call once on application launch to for example
--   create missing database tables
initUserBackend :: UserStorageBackend b => b -> IO ()

-- | Destory the backend. WARNING: This is only for testing! It deletes all
--   tables and data.
destroyUserBackend :: UserStorageBackend b => b -> IO ()

-- | This cleans up invalid sessions and other tokens. Call periodically as
--   needed.
housekeepBackend :: UserStorageBackend b => b -> IO ()

-- | Retrieve a user id from the database
getUserIdByName :: UserStorageBackend b => b -> Text -> IO (Maybe (UserId b))

-- | Retrieve a user from the database
getUserById :: UserStorageBackend b => b -> UserId b -> IO (Maybe User)

-- | List all users unlimited, or limited, sorted by a <a>UserField</a>
listUsers :: UserStorageBackend b => b -> Maybe (Int64, Int64) -> SortBy UserField -> IO [(UserId b, User)]

-- | Count all users
countUsers :: UserStorageBackend b => b -> IO Int64

-- | Create a user
createUser :: UserStorageBackend b => b -> User -> IO (Either CreateUserError (UserId b))

-- | Modify a user
updateUser :: UserStorageBackend b => b -> UserId b -> (User -> User) -> IO (Either UpdateUserError ())

-- | Delete a user
deleteUser :: UserStorageBackend b => b -> UserId b -> IO ()

-- | Authentificate a user using username/email and password. The
--   <a>NominalDiffTime</a> describes the session duration
authUser :: UserStorageBackend b => b -> Text -> PasswordPlain -> NominalDiffTime -> IO (Maybe SessionId)

-- | Authentificate a user and execute a single action.
withAuthUser :: UserStorageBackend b => b -> Text -> (User -> Bool) -> (UserId b -> IO r) -> IO (Maybe r)

-- | Verify a <a>SessionId</a>. The session duration can be extended by
--   <a>NominalDiffTime</a>
verifySession :: UserStorageBackend b => b -> SessionId -> NominalDiffTime -> IO (Maybe (UserId b))

-- | Force create a session for a user. This is useful for support/admin
--   login. If the user does not exist, this will fail.
createSession :: UserStorageBackend b => b -> UserId b -> NominalDiffTime -> IO (Maybe SessionId)

-- | Destroy a session
destroySession :: UserStorageBackend b => b -> SessionId -> IO ()

-- | Request a <a>PasswordResetToken</a> for a given user, valid for
--   <a>NominalDiffTime</a>
requestPasswordReset :: UserStorageBackend b => b -> UserId b -> NominalDiffTime -> IO PasswordResetToken

-- | Check if a <a>PasswordResetToken</a> is still valid and retrieve the
--   owner of it
verifyPasswordResetToken :: UserStorageBackend b => b -> PasswordResetToken -> IO (Maybe User)

-- | Apply a new password to the owner of <a>PasswordResetToken</a> iff the
--   token is still valid
applyNewPassword :: UserStorageBackend b => b -> PasswordResetToken -> Password -> IO (Either TokenError ())

-- | Request an <a>ActivationToken</a> for a given user, valid for
--   <a>NominalDiffTime</a>
requestActivationToken :: UserStorageBackend b => b -> UserId b -> NominalDiffTime -> IO ActivationToken

-- | Activate the owner of <a>ActivationToken</a> iff the token is still
--   valid
activateUser :: UserStorageBackend b => b -> ActivationToken -> IO (Either TokenError ())

-- | Core user datatype
data User
User :: !Text -> !Text -> !Password -> !Bool -> User
[u_name] :: User -> !Text
[u_email] :: User -> !Text
[u_password] :: User -> !Password
[u_active] :: User -> !Bool

-- | Password representation. When updating or creating a user, use
--   <a>makePassword</a> to create one. The implementation details of this
--   type are ONLY for use in backend implementations.
data Password
PasswordHash :: !Text -> Password
PasswordHidden :: Password

-- | Construct a password from plaintext by hashing it
makePassword :: PasswordPlain -> Password

-- | Strip the password from the user type.
hidePassword :: User -> User

-- | Plaintext passsword. Used for authentification.
newtype PasswordPlain
PasswordPlain :: Text -> PasswordPlain
[unPasswordPlain] :: PasswordPlain -> Text

-- | Check a plaintext password against a password
verifyPassword :: PasswordPlain -> Password -> Bool

-- | Fields of user datatype
data UserField
UserFieldId :: UserField
UserFieldName :: UserField
UserFieldEmail :: UserField
UserFieldPassword :: UserField
UserFieldActive :: UserField

-- | A password reset token to send out to users via email or sms
newtype PasswordResetToken
PasswordResetToken :: Text -> PasswordResetToken
[unPasswordResetToken] :: PasswordResetToken -> Text

-- | An activation token to send out to users via email or sms
newtype ActivationToken
ActivationToken :: Text -> ActivationToken
[unActivationToken] :: ActivationToken -> Text

-- | A session id for identifying user sessions
newtype SessionId
SessionId :: Text -> SessionId
[unSessionId] :: SessionId -> Text

-- | Errors that happen on storage level during user creation
data CreateUserError
InvalidPassword :: CreateUserError
UsernameAlreadyTaken :: CreateUserError
EmailAlreadyTaken :: CreateUserError
UsernameAndEmailAlreadyTaken :: CreateUserError

-- | Errors that happen on storage level during user updating
data UpdateUserError
UsernameAlreadyExists :: UpdateUserError
EmailAlreadyExists :: UpdateUserError
UserDoesntExist :: UpdateUserError

-- | Errors that happen on storage level during token actions
data TokenError
TokenInvalid :: TokenError

-- | Sorting direction
data SortBy t
SortAsc :: t -> SortBy t
SortDesc :: t -> SortBy t
instance GHC.Classes.Eq Web.Users.Types.User
instance GHC.Show.Show Web.Users.Types.User
instance GHC.Classes.Eq Web.Users.Types.UserField
instance GHC.Show.Show Web.Users.Types.UserField
instance GHC.Classes.Eq Web.Users.Types.Password
instance GHC.Show.Show Web.Users.Types.Password
instance Data.String.IsString Web.Users.Types.PasswordPlain
instance GHC.Classes.Eq Web.Users.Types.PasswordPlain
instance GHC.Show.Show Web.Users.Types.PasswordPlain
instance Web.PathPieces.PathPiece Web.Users.Types.SessionId
instance Data.Aeson.Types.FromJSON.FromJSON Web.Users.Types.SessionId
instance Data.Aeson.Types.ToJSON.ToJSON Web.Users.Types.SessionId
instance GHC.Classes.Eq Web.Users.Types.SessionId
instance GHC.Show.Show Web.Users.Types.SessionId
instance Web.PathPieces.PathPiece Web.Users.Types.ActivationToken
instance Data.Aeson.Types.FromJSON.FromJSON Web.Users.Types.ActivationToken
instance Data.Aeson.Types.ToJSON.ToJSON Web.Users.Types.ActivationToken
instance GHC.Classes.Eq Web.Users.Types.ActivationToken
instance GHC.Show.Show Web.Users.Types.ActivationToken
instance Web.PathPieces.PathPiece Web.Users.Types.PasswordResetToken
instance Data.Aeson.Types.FromJSON.FromJSON Web.Users.Types.PasswordResetToken
instance Data.Aeson.Types.ToJSON.ToJSON Web.Users.Types.PasswordResetToken
instance GHC.Classes.Eq Web.Users.Types.PasswordResetToken
instance GHC.Show.Show Web.Users.Types.PasswordResetToken
instance GHC.Classes.Eq Web.Users.Types.TokenError
instance GHC.Show.Show Web.Users.Types.TokenError
instance GHC.Classes.Eq Web.Users.Types.UpdateUserError
instance GHC.Show.Show Web.Users.Types.UpdateUserError
instance GHC.Classes.Eq Web.Users.Types.CreateUserError
instance GHC.Show.Show Web.Users.Types.CreateUserError
instance Data.Aeson.Types.ToJSON.ToJSON Web.Users.Types.User
instance Data.Aeson.Types.FromJSON.FromJSON Web.Users.Types.User
