module Servant.Server.Auth.Token.SingleUse(
makeSingleUseExpire
, registerSingleUseCode
, invalideSingleUseCode
, validateSingleUseCode
, generateSingleUsedCodes
) where
import Control.Monad
import Control.Monad.IO.Class
import Data.Time
import Database.Persist.Sql
import Servant.API.Auth.Token
import Servant.Server.Auth.Token.Common
import Servant.Server.Auth.Token.Model
makeSingleUseExpire :: MonadIO m => NominalDiffTime
-> m UTCTime
makeSingleUseExpire dt = do
t <- liftIO getCurrentTime
return $ dt `addUTCTime` t
registerSingleUseCode :: MonadIO m => UserImplId
-> SingleUseCode
-> Maybe UTCTime
-> SqlPersistT m ()
registerSingleUseCode uid code expire = void $ insert
$ UserSingleUseCode code uid expire Nothing
invalideSingleUseCode :: MonadIO m => UserSingleUseCodeId
-> SqlPersistT m ()
invalideSingleUseCode i = do
t <- liftIO getCurrentTime
update i [UserSingleUseCodeUsed =. Just t]
validateSingleUseCode :: MonadIO m => UserImplId
-> SingleUseCode
-> SqlPersistT m Bool
validateSingleUseCode uid code = do
t <- liftIO getCurrentTime
mcode <- selectFirst ([
UserSingleUseCodeValue ==. code
, UserSingleUseCodeUser ==. uid
, UserSingleUseCodeUsed ==. Nothing
] ++ (
[UserSingleUseCodeExpire ==. Nothing]
||. [UserSingleUseCodeExpire >=. Just t]
)) [Desc UserSingleUseCodeExpire]
whenJust mcode $ invalideSingleUseCode . entityKey
return $ maybe False (const True) mcode
generateSingleUsedCodes :: MonadIO m => UserImplId
-> IO SingleUseCode
-> Word
-> SqlPersistT m [SingleUseCode]
generateSingleUsedCodes uid gen n = do
t <- liftIO getCurrentTime
updateWhere [
UserSingleUseCodeUser ==. uid
, UserSingleUseCodeUsed ==. Nothing
, UserSingleUseCodeExpire ==. Nothing
]
[UserSingleUseCodeUsed =. Just t]
replicateM (fromIntegral n) $ do
code <- liftIO gen
_ <- insert $ UserSingleUseCode code uid Nothing Nothing
return code