-- This Source Code Form is subject to the terms of the Mozilla Public -- License, v. 2.0. If a copy of the MPL was not distributed with this -- file, You can obtain one at http://mozilla.org/MPL/2.0/. {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} module Database.CQL.IO.Connection.Settings ( ConnectionSettings , defSettings , connectTimeout , sendTimeout , responseTimeout , maxStreams , compression , defKeyspace , maxRecvBuffer , tlsContext , authenticators -- * Authentication , AuthMechanism (..) , Authenticator (..) , AuthContext (..) , authConnId , authHost , passwordAuthenticator , AuthUser (..) , AuthPass (..) ) where import Control.Lens (makeLenses) import Control.Monad import Data.HashMap.Strict (HashMap) import Data.Int import Database.CQL.Protocol import Database.CQL.IO.Types import OpenSSL.Session (SSLContext) import Prelude import qualified Data.ByteString.Lazy.Char8 as Char8 import qualified Data.HashMap.Strict as HashMap import qualified Data.Text.Lazy as Lazy import qualified Data.Text.Lazy.Encoding as Lazy data ConnectionSettings = ConnectionSettings { _connectTimeout :: !Milliseconds , _sendTimeout :: !Milliseconds , _responseTimeout :: !Milliseconds , _maxStreams :: !Int , _compression :: !Compression , _defKeyspace :: !(Maybe Keyspace) , _maxRecvBuffer :: !Int , _tlsContext :: !(Maybe SSLContext) , _authenticators :: !(HashMap AuthMechanism Authenticator) } -- | Context information given to 'Authenticator's when -- the server requests authentication on a connection. -- See 'authOnRequest'. data AuthContext = AuthContext { _authConnId :: !ConnId , _authHost :: !InetAddr } -- | A client authentication handler. -- -- The fields of an 'Authenticator' must implement the client-side -- of an (SASL) authentication mechanism as follows: -- -- * When a Cassandra server requests authentication on a new connection, -- 'authOnRequest' is called with the 'AuthContext' of the -- connection. -- -- * If additional challenges are posed by the server, -- 'authOnChallenge' is called, if available, otherwise an -- 'AuthenticationError' is thrown, i.e. every challenge must be -- answered. -- -- * Upon successful authentication 'authOnSuccess' is called. -- -- The existential type @s@ is chosen by an implementation and can -- be used to thread arbitrary state through the sequence of callback -- invocations during an authentication exchange. -- -- See also: -- -- data Authenticator = forall s. Authenticator { authMechanism :: !AuthMechanism -- ^ The (unique) name of the (SASL) mechanism that the callbacks -- implement. , authOnRequest :: AuthContext -> IO (AuthResponse, s) -- ^ Callback for initiating an authentication exchange. , authOnChallenge :: Maybe (s -> AuthChallenge -> IO (AuthResponse, s)) -- ^ Optional callback for additional challenges posed by the server. -- If the authentication mechanism does not require additional -- challenges, it should be set to 'Nothing'. Otherwise every -- challenge must be answered with a response. , authOnSuccess :: s -> AuthSuccess -> IO () -- ^ Callback for successful completion of an authentication exchange. } makeLenses ''AuthContext makeLenses ''ConnectionSettings newtype AuthUser = AuthUser Lazy.Text newtype AuthPass = AuthPass Lazy.Text -- | A password authentication handler for use with Cassandra's -- @PasswordAuthenticator@. -- -- See: passwordAuthenticator :: AuthUser -> AuthPass -> Authenticator passwordAuthenticator (AuthUser u) (AuthPass p) = Authenticator { authMechanism = "org.apache.cassandra.auth.PasswordAuthenticator" , authOnChallenge = Nothing , authOnSuccess = \() _ -> return () , authOnRequest = \_ctx -> let user = Lazy.encodeUtf8 u pass = Lazy.encodeUtf8 p resp = AuthResponse (Char8.concat ["\0", user, "\0", pass]) in return (resp, ()) } defSettings :: ConnectionSettings defSettings = ConnectionSettings 5000 -- connect timeout 3000 -- send timeout 10000 -- response timeout 128 -- max streams per connection noCompression -- compression Nothing -- keyspace 16384 -- receive buffer size Nothing -- no tls by default HashMap.empty -- no authentication