{-| Module : Servant.Server.Auth.Token.Restore Description : Operations with restore codes Copyright : (c) Anton Gushcha, 2016 License : MIT Maintainer : ncrashed@gmail.com Stability : experimental Portability : Portable -} module Servant.Server.Auth.Token.Restore( getRestoreCode , guardRestoreCode , sendRestoreCode ) where import Control.Monad import Control.Monad.IO.Class import Data.Time.Clock import Database.Persist.Postgresql import Servant.API.Auth.Token import Servant.Server.Auth.Token.Config import Servant.Server.Auth.Token.Model import Servant.Server.Auth.Token.Monad -- | Get current restore code for user or generate new getRestoreCode :: IO RestoreCode -> UserImplId -> UTCTime -> SqlPersistT IO RestoreCode getRestoreCode generator uid expire = do t <- liftIO getCurrentTime mcode <- selectFirst [UserRestoreUser ==. uid, UserRestoreExpire >. t] [Desc UserRestoreExpire] case mcode of Nothing -> do code <- liftIO generator void $ insert UserRestore { userRestoreValue = code , userRestoreUser = uid , userRestoreExpire = expire } return code Just code -> return $ userRestoreValue . entityVal $ code -- | Throw if the restore code isn't valid for given user, if valid, invalidates the code guardRestoreCode :: UserImplId -> RestoreCode -> AuthHandler () guardRestoreCode uid code = do t <- liftIO getCurrentTime mcode <- runDB $ selectFirst [UserRestoreUser ==. uid, UserRestoreValue ==. code , UserRestoreExpire >. t] [Desc UserRestoreExpire] case mcode of Nothing -> throw400 "Invalid restore code" Just (Entity i rc) -> runDB $ replace i rc { userRestoreExpire = t } -- | Send restore code to the user' email sendRestoreCode :: RespUserInfo -> RestoreCode -> AuthHandler () sendRestoreCode user code = do AuthConfig{..} <- getConfig liftIO $ restoreCodeSender user code