module Happstack.Server.Auth where
import Control.Monad                             (MonadPlus(mzero, mplus))
import Data.ByteString.Base64                    as Base64
import qualified Data.ByteString.Char8           as B
import qualified Data.Map                        as M
import Happstack.Server.Monads                   (Happstack, escape, getHeaderM, setHeaderM)
import Happstack.Server.Response                 (unauthorized, toResponse)
basicAuth :: (Happstack m) =>
   String 
   -> M.Map String String 
   -> m a 
   -> m a
basicAuth realmName authMap xs = basicAuthImpl `mplus` xs
  where
    basicAuthImpl = do
        aHeader <- getHeaderM "authorization"
        case aHeader of
            Nothing -> err
            Just x -> 
                do r <- parseHeader x 
                   case r of
                     (name, ':':password) | validLogin name password -> mzero
                                          | otherwise -> err
                     _  -> err
    validLogin name password = M.lookup name authMap == Just password
    parseHeader h = 
      case Base64.decode . B.drop 6 $ h of
        (Left _)   -> err
        (Right bs) -> return (break (':'==) (B.unpack bs))
    headerName  = "WWW-Authenticate"
    headerValue = "Basic realm=\"" ++ realmName ++ "\""
    err :: (Happstack m) => m a
    err = escape $ do
            setHeaderM headerName headerValue
            unauthorized $ toResponse "Not authorized"