2014-05-22 03:23:57 +05:30
|
|
|
{-# LANGUAGE TemplateHaskell #-}
|
|
|
|
{-# LANGUAGE TypeFamilies #-}
|
|
|
|
|
2014-06-07 00:50:27 +05:30
|
|
|
module Network.IRC.Handlers.Auth (authMsgHandlerMaker) where
|
2014-05-22 03:23:57 +05:30
|
|
|
|
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
|
2014-10-13 11:21:08 +05:30
|
|
|
import Control.Monad.Reader (asks)
|
|
|
|
import Control.Monad.State.Strict (get, put)
|
|
|
|
import Data.Acid (AcidState, Query, Update, makeAcidic, query, update,
|
|
|
|
openLocalState, createArchive)
|
|
|
|
import Data.Acid.Local (createCheckpointAndClose)
|
2014-05-22 03:23:57 +05:30
|
|
|
|
2014-10-04 21:22:24 +05:30
|
|
|
import Network.IRC
|
2014-05-22 03:23:57 +05:30
|
|
|
import Network.IRC.Handlers.Auth.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-10-04 21:22:24 +05:30
|
|
|
authMessage :: MonadMsgHandler m => IORef (AcidState Auth) -> Message -> m [Message]
|
|
|
|
authMessage state Message { .. }
|
2014-06-08 04:26:50 +05:30
|
|
|
| Just (PrivMsg user msg) <- fromMessage message
|
2014-10-04 21:22:24 +05:30
|
|
|
, "token" `isPrefixOf` msg = do
|
|
|
|
token <- io $ readIORef state >>= flip issueToken (userNick user)
|
|
|
|
map singleton . newMessage $ PrivMsgReply user token
|
|
|
|
| Just (AuthRequest user token reply) <- fromMessage message = io $ do
|
|
|
|
acid <- readIORef state
|
|
|
|
mt <- query acid (GetToken user)
|
|
|
|
case mt of
|
|
|
|
Just t -> putMVar reply (t == token)
|
|
|
|
Nothing -> putMVar reply False
|
|
|
|
return []
|
|
|
|
| otherwise = return []
|
2014-05-22 03:23:57 +05:30
|
|
|
|
|
|
|
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
|
|
|
|
2014-06-07 00:50:27 +05:30
|
|
|
authMsgHandlerMaker :: MsgHandlerMaker
|
|
|
|
authMsgHandlerMaker = MsgHandlerMaker "auth" go
|
2014-05-22 20:59:02 +05:30
|
|
|
where
|
2014-06-02 00:26:41 +05:30
|
|
|
helpMsg botNick = "Send a PM to get a new auth token. /msg " ++ nickToText botNick ++ " token"
|
|
|
|
|
2014-10-04 21:22:24 +05:30
|
|
|
go BotConfig { .. } _ = do
|
2014-06-02 00:26:41 +05:30
|
|
|
state <- io $ openLocalState emptyAuth >>= newIORef
|
2014-10-04 21:22:24 +05:30
|
|
|
return $ newMsgHandler { onMessage = authMessage state
|
|
|
|
, onStop = stopAuth state
|
|
|
|
, handlerHelp = return $ singletonMap "token" (helpMsg botNick) }
|