hask-irc/src/Network/IRC/Handlers/Auth.hs

79 lines
2.8 KiB
Haskell
Raw Normal View History

2014-05-22 03:23:57 +05:30
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module Network.IRC.Handlers.Auth (mkMsgHandler) where
2014-05-25 01:09:31 +05:30
import qualified Data.UUID as U
2014-05-22 03:23:57 +05:30
import qualified Data.UUID.V4 as U
import ClassyPrelude
import Control.Concurrent.Lifted (Chan)
import Control.Monad.Reader (asks)
import Control.Monad.State (get, put)
2014-05-22 20:59:02 +05:30
import Data.Acid (AcidState, Query, Update, makeAcidic, query, update,
openLocalState, createArchive)
2014-05-22 03:23:57 +05:30
import Data.Acid.Local (createCheckpointAndClose)
import Network.IRC.Handlers.Auth.Types
import Network.IRC.Types
2014-05-23 12:21:38 +05:30
import Network.IRC.Util
2014-05-22 03:23:57 +05:30
2014-05-22 20:59:02 +05:30
-- database
2014-05-22 03:23:57 +05:30
getToken :: Nick -> Query Auth (Maybe Token)
getToken user = lookup user <$> asks auth
saveToken :: Nick -> Token -> Update Auth ()
saveToken user token = get >>= put . Auth . insertMap user token . auth
deleteToken :: Nick -> Update Auth ()
deleteToken user = get >>= put . Auth . deleteMap user . auth
$(makeAcidic ''Auth ['getToken, 'saveToken, 'deleteToken])
issueToken :: AcidState Auth -> Nick -> IO Token
issueToken acid user = do
2014-05-22 20:59:02 +05:30
mt <- query acid (GetToken user)
2014-05-22 03:23:57 +05:30
case mt of
Just t -> return t
Nothing -> do
token <- map (pack . U.toString) U.nextRandom
2014-05-22 20:59:02 +05:30
update acid (SaveToken user token)
2014-05-22 03:23:57 +05:30
return token
2014-05-22 20:59:02 +05:30
-- handler
2014-05-22 03:23:57 +05:30
authMessage :: MonadMsgHandler m => IORef (AcidState Auth) -> Message -> m (Maybe Command)
2014-05-25 01:09:31 +05:30
authMessage state Message { msgDetails = PrivMsg { .. }, .. }
2014-05-23 12:21:38 +05:30
| "token" `isPrefixOf` msg = map (Just . PrivMsgReply user) . io $
2014-05-22 20:59:02 +05:30
readIORef state >>= flip issueToken (userNick user)
2014-05-22 03:23:57 +05:30
authMessage _ _ = return Nothing
stopAuth :: MonadMsgHandler m => IORef (AcidState Auth) -> m ()
2014-05-23 12:21:38 +05:30
stopAuth state = io $ do
2014-05-22 20:59:02 +05:30
acid <- readIORef state
createArchive acid
createCheckpointAndClose acid
2014-05-22 03:23:57 +05:30
authEvent :: MonadMsgHandler m => IORef (AcidState Auth) -> SomeEvent -> m EventResponse
authEvent state event = case fromEvent event of
2014-05-23 12:21:38 +05:30
Just (AuthEvent user token reply, _) -> io $ do
2014-05-22 03:23:57 +05:30
acid <- readIORef state
2014-05-22 20:59:02 +05:30
mt <- query acid (GetToken user)
2014-05-22 03:23:57 +05:30
case mt of
Just t -> putMVar reply (t == token)
Nothing -> putMVar reply False
return RespNothing
2014-05-22 20:59:02 +05:30
_ -> return RespNothing
2014-05-22 03:23:57 +05:30
mkMsgHandler :: BotConfig -> Chan SomeEvent -> MsgHandlerName -> IO (Maybe MsgHandler)
2014-05-22 20:59:02 +05:30
mkMsgHandler BotConfig { .. } _ "auth" = do
2014-05-25 01:09:31 +05:30
state <- io $ openLocalState emptyAuth >>= newIORef
2014-05-22 03:23:57 +05:30
return . Just $ newMsgHandler { onMessage = authMessage state
, onEvent = authEvent state
2014-05-22 20:59:02 +05:30
, onStop = stopAuth state
, onHelp = return $ singletonMap "token" helpMsg }
where
helpMsg = "Send a PM to get a new auth token. /msg " ++ botNick ++ " token"
mkMsgHandler _ _ _ = return Nothing