packages feed

bein-0.3: Bein/Web/Authentication.hs

module Bein.Web.Authentication where

import Bein.Web.Types
import Bein.Web.Commands
import Database.HDBC
import Control.Monad.Reader
import Happstack.Server
import Happstack.Crypto.SHA1

sessionCookie :: String
sessionCookie = "beinsid"

sessionTimeout :: Int
sessionTimeout = 30*60 -- 30 minutes

getSession :: RqData (Maybe String)
getSession = liftM Just (lookCookieValue sessionCookie) `mplus` return Nothing

getRequestUser :: BeinServerPart (Maybe User)
getRequestUser = hostAuthentication `mmplus` cookieAuthentication

hostAuthentication :: BeinServerPart (Maybe User)
hostAuthentication = askRq >>= return . fst . rqPeer >>= \h -> lift $ getUser (WithHost h)

cookieAuthentication :: BeinServerPart (Maybe User)
cookieAuthentication = withDataFn getSession f
  where f Nothing    = return Nothing
        f (Just sid) = userOfSession sid

userOfSession :: String -> BeinServerPart (Maybe User)
userOfSession sid = do
  r <- lift $ query "select uid from sessions where key = ?" [toSql sid]
  case (fmap (fromSql.head) . safeHead) r of
    Nothing -> do addCookie 0 (mkCookie sessionCookie "0")
                  return Nothing
    Just thisUid -> do lift $ update "select touch_session(?)" [toSql sid]
                       addCookie sessionTimeout (mkCookie sessionCookie sid)
                       lift $ getUser (WithUid thisUid)

ensureSession :: BeinServerPart a -> BeinServerPart a -> (String,String) -> BeinServerPart a
ensureSession onFail onSucceed (givenUsername,givenPassword) = lift (getUser (WithUserName givenUsername)) >>= \u -> case u of 
  Nothing -> onFail
  Just user -> if authType user == Password (sha1 givenPassword)
                 then do sid <- liftM (fromSql.head.head) $ lift $ updateWithResponse "select new_session(?)" [toSql (uid user)]
                         addCookie sessionTimeout (mkCookie sessionCookie sid)
                         onSucceed `withUser` user
                 else do onFail



clearSession :: BeinServerPart ()
clearSession = withDataFn getSession logOut'
  where logOut' c = do addCookie 0 (mkCookie sessionCookie "0")
                       lift $ update "delete from sessions where key = ?" [toSql c]
                       setHeaderM "Content-Type" "text/html; charset=utf-8"