I've am trying to implement basic account management system (register/login/logout/etc) using happstack. This experience is challenging my understanding of monads and monad transformers. Below is a simple function that checks if a given session is valid.
Session stores user's id (email), client IP/port. 'checkSession' verifies if this information is valid. What I can't figure out how to make this code cleaner. It seems like this is a classic example for Maybe monad, but because of 'getSession' (~StateT) and 'query' (MonadIO) I can't seem to figure out a way to clean this up. [ I've been thinking that I should put 'acid' into a ReaderT, but that's only going to make this more complicated here]
Any ideas on how I can clean this up?
[ P.S. I know this check is not secure from replay attacks from the same IP; but that's another story ]
-- this code is ugly, I wonder if I could use a Maybe monad here
checkSession acid = do
session <- getSession
let uMail=userEmail session
if uMail == ""
then return (Nothing)
else do
req <- askRq
let peer=rqPeer req
if peer /= (userIPPort session)
then return (Nothing)
else do
u <- query' acid (FindUser uMail)
case u of
Nothing -> return (Nothing)
Just user -> return (Just session)
homePage :: DB -> App Response
homePage acid = do
res <- checkSession acid
case res of
Nothing -> loginPage
Just session -> userPage session