packages feed

servant-auth-hmac-0.1.0.0: example/server/Example.hs

{-# LANGUAGE DataKinds                  #-}
{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE TypeOperators              #-}
{-# LANGUAGE RecordWildCards            #-}

import AuthAPI
import Data.Default
import Data.IORef (newIORef, readIORef)
import Network.Wai (Application)
import Network.Wai.Handler.Warp (run)
import Servant (Proxy(..), Server, (:>), (:<|>)(..), Raw, Get, Capture)
import Servant.API.ContentTypes (JSON)
import Servant.HTML.Blaze
import Servant.Server (Context ((:.), EmptyContext), serveWithContext)
import Servant.Server.Experimental.Auth.HMAC
import Servant.Utils.StaticFiles (serveDirectory)
import System.Posix.Directory (getWorkingDirectory)
import Text.Blaze.Html5 ((!))
import Text.Blaze.Html5 (Markup)
import qualified Data.Map as Map
import qualified Text.Blaze.Html5 as H
import qualified Text.Blaze.Html5.Attributes as A


type ExampleAPI = Get '[HTML] Markup
             :<|> "static" :> Raw
             :<|> "api" :> "templates" :> Get '[JSON] [String]
             :<|> "api" :> "templates" :> Capture "name" String :> Get '[HTML] Markup
             :<|> "api" :> AuthAPI


server :: FilePath -> Storage -> Server ExampleAPI
server root storage = serveIndex
                 :<|> serveStatic
                 :<|> serveTemplates
                 :<|> serveTemplate
                 :<|> serveAuth storage where

  serveIndex = return indexPage
  serveStatic = serveDirectory root
  serveTemplates = return $ map fst templates
  serveTemplate name = return $ (maybe defaultPage id) (lookup name templates)

  templates = [
      ("home"   , homePage)
    , ("login"  , loginPage)
    , ("private", privatePage)
    ]


app :: FilePath -> Storage -> AuthTokenProvider -> AuthHmacSettings -> Application
app root storage tokenProvider settings = serveWithContext
  (Proxy :: Proxy ExampleAPI)
  ((defaultAuthHandler tokenProvider settings) :. EmptyContext)
  (server root storage)

main :: IO ()
main = do
  root <- (++ "/example/client/result/static") <$> getWorkingDirectory
  storage <- newIORef $ Map.empty
  let tokenProvider username = (Map.lookup username) <$> (readIORef storage)
  run 8080 (app root storage tokenProvider (def::AuthHmacSettings))


indexPage :: H.Html
indexPage = H.docTypeHtml $ do
  H.head $ do
    H.script ! A.src "static/app.js" ! A.type_ "application/javascript;version=1.8" $ ""
  H.body $ do
    H.div ! A.class_ "app" $ "Loading..."

homePage :: H.Html
homePage = do
  H.p "This is an example of using servant-auth-hmac library."
  H.p "Use login page to get access to the private page."

loginPage :: H.Html
loginPage = do
  H.form ! A.method "post" ! A.action "/api/login" $ do
    H.table $ do
      H.tr $ do
       H.td $ "username:"
       H.td $ H.input ! A.type_ "text" ! A.name "username"
      H.tr $ do
       H.td $ "password:"
       H.td $ H.input ! A.type_ "password" ! A.name "password"
    H.input ! A.type_ "submit"
  H.p ! A.class_ "feedback" $ ""

privatePage :: H.Html
privatePage = do
  H.p $ H.b "username: " >> "{{username}}"
  H.p $ H.b "token: "    >> "{{token}}"
  H.p $ H.b "secret: "   >> "{{secret}}"

defaultPage :: H.Html
defaultPage = H.p "not found"