servant/config: use config in servant-example/auth-combinator
This commit is contained in:
parent
81f8c43531
commit
9079c55b00
1 changed files with 19 additions and 7 deletions
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
import Data.Aeson
|
import Data.Aeson
|
||||||
import Data.ByteString (ByteString)
|
import Data.ByteString (ByteString)
|
||||||
|
import Data.IORef
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import GHC.Generics
|
import GHC.Generics
|
||||||
import Network.Wai
|
import Network.Wai
|
||||||
|
@ -18,24 +19,32 @@ import Servant.Server.Internal
|
||||||
-- Pretty much stolen/adapted from
|
-- Pretty much stolen/adapted from
|
||||||
-- https://github.com/haskell-servant/HaskellSGMeetup2015/blob/master/examples/authentication-combinator/AuthenticationCombinator.hs
|
-- https://github.com/haskell-servant/HaskellSGMeetup2015/blob/master/examples/authentication-combinator/AuthenticationCombinator.hs
|
||||||
|
|
||||||
type DBLookup = ByteString -> IO Bool
|
type DBConnection = IORef [ByteString]
|
||||||
|
type DBLookup = DBConnection -> ByteString -> IO Bool
|
||||||
|
|
||||||
|
initDB :: IO DBConnection
|
||||||
|
initDB = newIORef ["good password"]
|
||||||
|
|
||||||
isGoodCookie :: DBLookup
|
isGoodCookie :: DBLookup
|
||||||
isGoodCookie = return . (== "good password")
|
isGoodCookie ref password = do
|
||||||
|
allowed <- readIORef ref
|
||||||
|
return (password `elem` allowed)
|
||||||
|
|
||||||
data AuthProtected
|
data AuthProtected
|
||||||
|
|
||||||
instance HasServer rest => HasServer (AuthProtected :> rest) where
|
instance HasServer rest => HasServer (AuthProtected :> rest) where
|
||||||
type ServerT (AuthProtected :> rest) m = ServerT rest m
|
type ServerT (AuthProtected :> rest) m = ServerT rest m
|
||||||
type HasCfg (AuthProtected :> rest) c = HasCfg rest c
|
type HasCfg (AuthProtected :> rest) config =
|
||||||
|
(HasConfigEntry config DBConnection, HasCfg rest config)
|
||||||
|
|
||||||
route Proxy p subserver = WithRequest $ \ request ->
|
route Proxy config subserver = WithRequest $ \ request ->
|
||||||
route (Proxy :: Proxy rest) p $ addAcceptCheck subserver $ cookieCheck request
|
route (Proxy :: Proxy rest) config $ addAcceptCheck subserver $ cookieCheck request
|
||||||
where
|
where
|
||||||
cookieCheck req = case lookup "Cookie" (requestHeaders req) of
|
cookieCheck req = case lookup "Cookie" (requestHeaders req) of
|
||||||
Nothing -> return $ FailFatal err401 { errBody = "Missing auth header" }
|
Nothing -> return $ FailFatal err401 { errBody = "Missing auth header" }
|
||||||
Just v -> do
|
Just v -> do
|
||||||
authGranted <- isGoodCookie v
|
let dbConnection = getConfigEntry config
|
||||||
|
authGranted <- isGoodCookie dbConnection v
|
||||||
if authGranted
|
if authGranted
|
||||||
then return $ Route ()
|
then return $ Route ()
|
||||||
else return $ FailFatal err403 { errBody = "Invalid cookie" }
|
else return $ FailFatal err403 { errBody = "Invalid cookie" }
|
||||||
|
@ -67,7 +76,10 @@ server = return prvdata :<|> return pubdata
|
||||||
pubdata = [PublicData "this is a public piece of data"]
|
pubdata = [PublicData "this is a public piece of data"]
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = run 8080 (serve api EmptyConfig server)
|
main = do
|
||||||
|
dbConnection <- initDB
|
||||||
|
let config = dbConnection :. EmptyConfig
|
||||||
|
run 8080 (serve api config server)
|
||||||
|
|
||||||
{- Sample session:
|
{- Sample session:
|
||||||
$ curl http://localhost:8080/
|
$ curl http://localhost:8080/
|
||||||
|
|
Loading…
Reference in a new issue