broken attempts to work on concurrency
This commit is contained in:
+10
-12
@@ -11,29 +11,26 @@ cabal-version: >=1.10
|
|||||||
|
|
||||||
executable dbapi
|
executable dbapi
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
ghc-options: -Wall -W -Werror
|
ghc-options: -Wall -W -threaded
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
build-depends: base >=4.6 && <5
|
build-depends: base >=4.6 && <5
|
||||||
, HDBC, HDBC-postgresql
|
, HDBC, HDBC-postgresql
|
||||||
, warp, wai >= 3.0.1 && < 3.0.2
|
, warp, wai >= 3.0.1 && < 3.0.2
|
||||||
, wai-extra, wai-cors
|
, wai-extra, wai-cors
|
||||||
, wai-middleware-static >= 0.6.0
|
, wai-middleware-static >= 0.6.0
|
||||||
, HTTP, convertible
|
, HTTP, convertible, http-types
|
||||||
, case-insensitive
|
, case-insensitive
|
||||||
, http-types, scientific, time
|
, scientific, time
|
||||||
, bytestring, aeson, network >= 2.6
|
, aeson, network >= 2.6
|
||||||
, text , containers
|
, bytestring, text, split, string-conversions
|
||||||
|
, containers, unordered-containers
|
||||||
, optparse-applicative >= 0.9.1 && < 0.10
|
, optparse-applicative >= 0.9.1 && < 0.10
|
||||||
, unordered-containers
|
, regex-base, regex-tdfa
|
||||||
, regex-base
|
|
||||||
, string-conversions
|
|
||||||
, http-media, regex-tdfa
|
|
||||||
, Ranged-sets
|
, Ranged-sets
|
||||||
, transformers
|
, transformers
|
||||||
, bcrypt
|
, bcrypt, base64-string
|
||||||
, base64-string
|
|
||||||
, split
|
|
||||||
, network-uri >= 2.6
|
, network-uri >= 2.6
|
||||||
|
, resource-pool, process
|
||||||
Other-Modules: Dbapi
|
Other-Modules: Dbapi
|
||||||
, PgStructure
|
, PgStructure
|
||||||
, PgQuery
|
, PgQuery
|
||||||
@@ -69,3 +66,4 @@ Test-Suite spec
|
|||||||
, base64-string
|
, base64-string
|
||||||
, split
|
, split
|
||||||
, network-uri >= 2.6
|
, network-uri >= 2.6
|
||||||
|
, resource-pool
|
||||||
|
|||||||
+12
-3
@@ -3,9 +3,8 @@
|
|||||||
module Main where
|
module Main where
|
||||||
import Dbapi
|
import Dbapi
|
||||||
import Middleware (inTransaction, authenticated, withSavepoint, clientErrors,
|
import Middleware (inTransaction, authenticated, withSavepoint, clientErrors,
|
||||||
redirectInsecure)
|
redirectInsecure, withDBConnection)
|
||||||
import Network.Wai.Handler.Warp hiding (Connection)
|
import Network.Wai.Handler.Warp hiding (Connection)
|
||||||
import Database.HDBC.PostgreSQL (connectPostgreSQL')
|
|
||||||
import Data.String.Conversions (cs)
|
import Data.String.Conversions (cs)
|
||||||
|
|
||||||
import Control.Monad (unless)
|
import Control.Monad (unless)
|
||||||
@@ -14,6 +13,15 @@ import Options.Applicative hiding (columns)
|
|||||||
import Network.Wai.Middleware.Gzip (gzip, def)
|
import Network.Wai.Middleware.Gzip (gzip, def)
|
||||||
import Network.Wai.Middleware.Cors (cors)
|
import Network.Wai.Middleware.Cors (cors)
|
||||||
import Network.Wai.Middleware.Static (staticPolicy, only)
|
import Network.Wai.Middleware.Static (staticPolicy, only)
|
||||||
|
import Database.HDBC (disconnect)
|
||||||
|
import Database.HDBC.PostgreSQL(connectPostgreSQL')
|
||||||
|
import Data.Pool(createPool)
|
||||||
|
import System.Process
|
||||||
|
|
||||||
|
import Control.Concurrent(threadDelay)
|
||||||
|
|
||||||
|
import Network.HTTP.Types.Status
|
||||||
|
import Network.Wai
|
||||||
|
|
||||||
argParser :: Parser AppConfig
|
argParser :: Parser AppConfig
|
||||||
argParser = AppConfig
|
argParser = AppConfig
|
||||||
@@ -29,8 +37,9 @@ argParser = AppConfig
|
|||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
conf <- execParser (info (helper <*> argParser) describe)
|
conf <- execParser (info (helper <*> argParser) describe)
|
||||||
let port = configPort conf
|
|
||||||
let dburi = configDbUri conf
|
let dburi = configDbUri conf
|
||||||
|
pool <- createPool (putStrLn "creating connection" >> connectPostgreSQL' (configDbUri conf)) (\c-> putStrLn "destroying connection" >> disconnect c) 1 600 10
|
||||||
|
let port = configPort conf
|
||||||
|
|
||||||
unless (configSecure conf) $
|
unless (configSecure conf) $
|
||||||
putStrLn "WARNING, running in insecure mode, auth will be in plaintext"
|
putStrLn "WARNING, running in insecure mode, auth will be in plaintext"
|
||||||
|
|||||||
+12
-5
@@ -6,6 +6,7 @@ module Middleware where
|
|||||||
import Data.Aeson ((.=), toJSON, ToJSON, object, encode)
|
import Data.Aeson ((.=), toJSON, ToJSON, object, encode)
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
import Data.Monoid (mconcat)
|
import Data.Monoid (mconcat)
|
||||||
|
import Data.Pool(withResource, Pool)
|
||||||
|
|
||||||
import Database.HDBC (runRaw)
|
import Database.HDBC (runRaw)
|
||||||
import Database.HDBC.PostgreSQL (Connection)
|
import Database.HDBC.PostgreSQL (Connection)
|
||||||
@@ -15,6 +16,7 @@ import Data.String.Conversions(cs)
|
|||||||
import qualified Data.ByteString.Char8 as BS
|
import qualified Data.ByteString.Char8 as BS
|
||||||
import Control.Exception (finally, throw, catchJust, catch, SomeException,
|
import Control.Exception (finally, throw, catchJust, catch, SomeException,
|
||||||
bracket_)
|
bracket_)
|
||||||
|
import Control.Concurrent(threadDelay)
|
||||||
|
|
||||||
import Network.HTTP.Types.Header (RequestHeaders, hContentType, hAuthorization,
|
import Network.HTTP.Types.Header (RequestHeaders, hContentType, hAuthorization,
|
||||||
hLocation)
|
hLocation)
|
||||||
@@ -26,18 +28,23 @@ import Network.URI (URI(..), parseURI)
|
|||||||
import PgQuery(LoginAttempt(..), signInRole, setRole, resetRole)
|
import PgQuery(LoginAttempt(..), signInRole, setRole, resetRole)
|
||||||
import Codec.Binary.Base64.String (decode)
|
import Codec.Binary.Base64.String (decode)
|
||||||
|
|
||||||
inTransaction :: (Connection -> Application) -> Connection -> Application
|
|
||||||
|
withDBConnection :: Pool Connection -> (Connection -> Application) -> Application
|
||||||
|
withDBConnection pool app req respond =
|
||||||
|
withResource pool (\c -> app c req respond)
|
||||||
|
|
||||||
|
inTransaction :: (Connection -> Application) -> (Connection -> Application)
|
||||||
inTransaction app conn req respond =
|
inTransaction app conn req respond =
|
||||||
finally (runRaw conn "begin" >> app conn req respond) (runRaw conn "commit")
|
finally (runRaw conn "begin" >> app conn req respond) (runRaw conn "commit")
|
||||||
|
|
||||||
withSavepoint :: (Connection -> Application) -> Connection -> Application
|
withSavepoint :: (Connection -> Application) -> (Connection -> Application)
|
||||||
withSavepoint app conn req respond = do
|
withSavepoint app conn req respond = do
|
||||||
runRaw conn "savepoint req_sp"
|
runRaw conn "savepoint req_sp"
|
||||||
catch (app conn req respond) (\e -> let _ = (e::SomeException) in
|
catch (app conn req respond) (\e -> let _ = (e::SomeException) in
|
||||||
runRaw conn "rollback to savepoint req_sp" >> throw e)
|
runRaw conn "rollback to savepoint req_sp" >> throw e)
|
||||||
|
|
||||||
authenticated :: BS.ByteString -> (Connection -> Application) ->
|
authenticated :: BS.ByteString -> (Connection -> Application) ->
|
||||||
Connection -> Application
|
(Connection -> Application)
|
||||||
authenticated anon app conn req respond = do
|
authenticated anon app conn req respond = do
|
||||||
attempt <- httpRequesterRole (requestHeaders req)
|
attempt <- httpRequesterRole (requestHeaders req)
|
||||||
case attempt of
|
case attempt of
|
||||||
@@ -46,9 +53,9 @@ authenticated anon app conn req respond = do
|
|||||||
LoginFailed ->
|
LoginFailed ->
|
||||||
respond $ responseLBS status401 [] "Invalid username or password"
|
respond $ responseLBS status401 [] "Invalid username or password"
|
||||||
LoginSuccess role ->
|
LoginSuccess role ->
|
||||||
bracket_ (setRole conn role) (resetRole conn) $ app conn req respond
|
bracket_ (setRole conn role >> threadDelay 10000000) (resetRole conn) $ app conn req respond
|
||||||
NoCredentials ->
|
NoCredentials ->
|
||||||
bracket_ (setRole conn anon) (resetRole conn) $ app conn req respond
|
bracket_ (setRole conn anon >> threadDelay 10000000) (resetRole conn) $ app conn req respond
|
||||||
|
|
||||||
where
|
where
|
||||||
httpRequesterRole :: RequestHeaders -> IO LoginAttempt
|
httpRequesterRole :: RequestHeaders -> IO LoginAttempt
|
||||||
|
|||||||
Reference in New Issue
Block a user