obviate need for data families

This commit is contained in:
aaron levin 2016-01-09 17:54:09 +01:00
parent ffeeffe745
commit f9dcbdd7d4
2 changed files with 23 additions and 13 deletions

View file

@ -415,13 +415,12 @@ instance HasClient api => HasClient (BasicAuth tag realm usr :> api) where
clientWithRoute (Proxy :: Proxy api) (basicAuthReq val req) baseurl manager
instance ( HasClient api
, AuthenticateClientRequest (AuthProtect tag)
) => HasClient (AuthProtect tag :> api) where
type Client (AuthProtect tag :> api)
= ClientAuthType (AuthProtect tag) -> Client api
= AuthenticateReq (AuthProtect tag) -> Client api
clientWithRoute Proxy req baseurl manager val =
clientWithRoute (Proxy :: Proxy api) (authReq val req) baseurl manager
clientWithRoute Proxy req baseurl manager (AuthenticateReq (val,func)) =
clientWithRoute (Proxy :: Proxy api) (func val req) baseurl manager
{- Note [Non-Empty Content Types]

View file

@ -1,6 +1,3 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeFamilies #-}
@ -8,9 +5,11 @@
-- | Authentication for clients
module Servant.Common.Auth (
AuthenticateClientRequest ( ClientAuthType, authReq )
AuthenticateReq(AuthenticateReq, unAuthReq)
, AuthClientData
, BasicAuthData (BasicAuthData, username, password)
, basicAuthReq
, mkAuthenticateReq
) where
import Data.ByteString (ByteString)
@ -31,8 +30,20 @@ basicAuthReq (BasicAuthData user pass) req =
let authText = decodeUtf8 ("Basic " <> encode (user <> ":" <> pass))
in addHeader "Authorization" authText req
-- | Class to represent the ability to authenticate a 'Request'
-- object. For example, we may add special headers to the 'Request'.
class AuthenticateClientRequest a where
data ClientAuthType a :: *
authReq :: ClientAuthType a -> Req -> Req
-- | For a resource protected by authentication (e.g. AuthProtect), we need
-- to provide the client with some data used to add authentication data
-- to a request
type family AuthClientData a :: *
-- | For better type inference and to avoid usage of a data family, we newtype
-- wrap the combination of some 'AuthClientData' and a function to add authentication
-- data to a request
newtype AuthenticateReq a =
AuthenticateReq { unAuthReq :: (AuthClientData a, AuthClientData a -> Req -> Req) }
-- | Handy helper to avoid wrapping datatypes in tuples everywhere.
mkAuthenticateReq :: AuthClientData a
-> (AuthClientData a -> Req -> Req)
-> AuthenticateReq a
mkAuthenticateReq val func = AuthenticateReq (val, func)