Use postgres connection string
This commit is contained in:
@@ -57,8 +57,8 @@ import PostgREST.Types
|
|||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
app :: DbStructure -> AppConfig -> BL.ByteString -> DbRole -> Request -> H.Tx P.Postgres s Response
|
app :: DbStructure -> AppConfig -> Text -> BL.ByteString -> DbRole -> Request -> H.Tx P.Postgres s Response
|
||||||
app dbstructure conf reqBody dbrole req =
|
app dbstructure conf authenticator reqBody dbrole req =
|
||||||
case (path, verb) of
|
case (path, verb) of
|
||||||
|
|
||||||
([], _) -> do
|
([], _) -> do
|
||||||
@@ -295,7 +295,6 @@ app dbstructure conf reqBody dbrole req =
|
|||||||
hasPrefer val = any (\(h,v) -> h == "Prefer" && v == val) hdrs
|
hasPrefer val = any (\(h,v) -> h == "Prefer" && v == val) hdrs
|
||||||
accept = lookupHeader hAccept
|
accept = lookupHeader hAccept
|
||||||
schema = cs $ configSchema conf
|
schema = cs $ configSchema conf
|
||||||
authenticator = cs $ configDbUser conf
|
|
||||||
jwtSecret = cs $ configJwtSecret conf
|
jwtSecret = cs $ configJwtSecret conf
|
||||||
range = rangeRequested hdrs
|
range = rangeRequested hdrs
|
||||||
allOrigins = ("Access-Control-Allow-Origin", "*") :: Header
|
allOrigins = ("Access-Control-Allow-Origin", "*") :: Header
|
||||||
|
|||||||
+10
-19
@@ -34,34 +34,25 @@ import Prelude
|
|||||||
|
|
||||||
-- | Data type to store all command line options
|
-- | Data type to store all command line options
|
||||||
data AppConfig = AppConfig {
|
data AppConfig = AppConfig {
|
||||||
configDbName :: String
|
configDatabase :: String
|
||||||
, configDbPort :: Int
|
|
||||||
, configDbUser :: String
|
|
||||||
, configDbPass :: String
|
|
||||||
, configDbHost :: String
|
|
||||||
|
|
||||||
, configPort :: Int
|
, configPort :: Int
|
||||||
, configAnonRole :: String
|
, configAnonRole :: String
|
||||||
, configSecure :: Bool
|
|
||||||
, configPool :: Int
|
|
||||||
, configSchema :: String
|
, configSchema :: String
|
||||||
|
, configSecure :: Bool
|
||||||
, configJwtSecret :: String
|
, configJwtSecret :: String
|
||||||
|
, configPool :: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
argParser :: Parser AppConfig
|
argParser :: Parser AppConfig
|
||||||
argParser = AppConfig
|
argParser = AppConfig
|
||||||
<$> strOption (long "db-name" <> short 'd' <> metavar "NAME" <> help "name of database")
|
<$> argument str (help "database connection string" <> metavar "URL")
|
||||||
<*> option auto (long "db-port" <> short 'P' <> metavar "PORT" <> value 5432 <> help "postgres server port" <> showDefault)
|
|
||||||
<*> strOption (long "db-user" <> short 'U' <> metavar "ROLE" <> help "postgres authenticator role")
|
|
||||||
<*> strOption (long "db-pass" <> metavar "PASS" <> value "" <> help "password for authenticator role")
|
|
||||||
<*> strOption (long "db-host" <> metavar "HOST" <> value "localhost" <> help "postgres server hostname" <> showDefault)
|
|
||||||
|
|
||||||
<*> option auto (long "port" <> short 'p' <> metavar "PORT" <> value 3000 <> help "port number on which to run HTTP server" <> showDefault)
|
<*> option auto (long "port" <> short 'p' <> help "port number on which to run HTTP server" <> metavar "PORT" <> value 3000 <> showDefault)
|
||||||
<*> strOption (long "anonymous" <> short 'a' <> metavar "ROLE" <> help "postgres role to use for non-authenticated requests")
|
<*> strOption (long "anonymous" <> short 'a' <> help "postgres role to use for non-authenticated requests" <> metavar "ROLE")
|
||||||
<*> switch (long "secure" <> short 's' <> help "Redirect all requests to HTTPS")
|
<*> strOption (long "schema" <> short 'S' <> help "schema to use for API routes" <> metavar "NAME" <> value "1" <> showDefault)
|
||||||
<*> option auto (long "db-pool" <> metavar "COUNT" <> value 10 <> help "Max connections in database pool" <> showDefault)
|
<*> switch (long "secure" <> short 's' <> help "redirect all requests to HTTPS")
|
||||||
<*> strOption (long "schema" <> short 'S' <> metavar "NAME" <> value "public" <> help "Schema to use for API routes" <> showDefault)
|
<*> strOption (long "jwt-secret" <> short 'j' <> help "secret used to encrypt and decrypt JWT tokens" <> metavar "SECRET" <> value "secret" <> showDefault)
|
||||||
<*> strOption (long "jwt-secret" <> metavar "SECRET" <> value "secret" <> help "Secret used to encrypt and decrypt JWT tokens)" <> showDefault)
|
<*> option auto (long "pool" <> short 'o' <> help "max connections in database pool" <> metavar "COUNT" <> value 10 <> showDefault)
|
||||||
|
|
||||||
defaultCorsPolicy :: CorsResourcePolicy
|
defaultCorsPolicy :: CorsResourcePolicy
|
||||||
defaultCorsPolicy = CorsResourcePolicy Nothing
|
defaultCorsPolicy = CorsResourcePolicy Nothing
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import PostgREST.Config (AppConfig (..),
|
|||||||
|
|
||||||
isServerVersionSupported :: H.Session P.Postgres IO Bool
|
isServerVersionSupported :: H.Session P.Postgres IO Bool
|
||||||
isServerVersionSupported = do
|
isServerVersionSupported = do
|
||||||
Identity (row :: Text) <- H.tx Nothing $ H.singleEx $ [H.stmt|SHOW server_version_num|]
|
Identity (row :: Text) <- H.tx Nothing $ H.singleEx [H.stmt|SHOW server_version_num|]
|
||||||
return $ read (cs row) >= minimumPgVersion
|
return $ read (cs row) >= minimumPgVersion
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
@@ -50,11 +50,7 @@ main = do
|
|||||||
Prelude.putStrLn $ "Listening on port " ++
|
Prelude.putStrLn $ "Listening on port " ++
|
||||||
(show $ configPort conf :: String)
|
(show $ configPort conf :: String)
|
||||||
|
|
||||||
let pgSettings = P.ParamSettings (cs $ configDbHost conf)
|
let pgSettings = P.StringSettings $ cs (configDatabase conf)
|
||||||
(fromIntegral $ configDbPort conf)
|
|
||||||
(cs $ configDbUser conf)
|
|
||||||
(cs $ configDbPass conf)
|
|
||||||
(cs $ configDbName conf)
|
|
||||||
appSettings = setPort port
|
appSettings = setPort port
|
||||||
. setServerName (cs $ "postgrest/" <> prettyVersion)
|
. setServerName (cs $ "postgrest/" <> prettyVersion)
|
||||||
$ defaultSettings
|
$ defaultSettings
|
||||||
@@ -71,6 +67,10 @@ main = do
|
|||||||
fail "Cannot run in this PostgreSQL version, PostgREST needs at least 9.2.0"
|
fail "Cannot run in this PostgreSQL version, PostgREST needs at least 9.2.0"
|
||||||
) supportedOrError
|
) supportedOrError
|
||||||
|
|
||||||
|
Right authenticator <- H.session pool $ do
|
||||||
|
Identity (role :: Text) <- H.tx Nothing $ H.singleEx [H.stmt|SELECT SESSION_USER|]
|
||||||
|
return role
|
||||||
|
|
||||||
let txSettings = Just (H.ReadCommitted, Just True)
|
let txSettings = Just (H.ReadCommitted, Just True)
|
||||||
metadata <- H.session pool $ H.tx txSettings $ do
|
metadata <- H.session pool $ H.tx txSettings $ do
|
||||||
tabs <- allTables
|
tabs <- allTables
|
||||||
@@ -89,9 +89,8 @@ main = do
|
|||||||
, primaryKeys=keys
|
, primaryKeys=keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
runSettings appSettings $ middle $ \ req respond -> do
|
runSettings appSettings $ middle $ \ req respond -> do
|
||||||
body <- strictRequestBody req
|
body <- strictRequestBody req
|
||||||
resOrError <- liftIO $ H.session pool $ H.tx txSettings $
|
resOrError <- liftIO $ H.session pool $ H.tx txSettings $
|
||||||
authenticated conf (app dbstructure conf body) req
|
authenticated conf authenticator (app dbstructure conf authenticator body) req
|
||||||
either (respond . errResponse) respond resOrError
|
either (respond . errResponse) respond resOrError
|
||||||
|
|||||||
@@ -33,22 +33,21 @@ import PostgREST.Config (AppConfig (..), corsPolicy)
|
|||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
authenticated :: forall s. AppConfig ->
|
authenticated :: forall s. AppConfig -> Text ->
|
||||||
(DbRole -> Request -> H.Tx P.Postgres s Response) ->
|
(DbRole -> Request -> H.Tx P.Postgres s Response) ->
|
||||||
Request -> H.Tx P.Postgres s Response
|
Request -> H.Tx P.Postgres s Response
|
||||||
authenticated conf app req = do
|
authenticated conf authenticator app req = do
|
||||||
attempt <- httpRequesterRole (requestHeaders req)
|
attempt <- httpRequesterRole (requestHeaders req)
|
||||||
case attempt of
|
case attempt of
|
||||||
MalformedAuth ->
|
MalformedAuth ->
|
||||||
return $ responseLBS status400 [] "Malformed basic auth header"
|
return $ responseLBS status400 [] "Malformed basic auth header"
|
||||||
LoginFailed ->
|
LoginFailed ->
|
||||||
return $ responseLBS status401 [] "Invalid username or password"
|
return $ responseLBS status401 [] "Invalid username or password"
|
||||||
LoginSuccess role uid -> if role /= currentRole then runInRole role uid else app currentRole req
|
LoginSuccess role uid -> if role /= authenticator then runInRole role uid else app authenticator req
|
||||||
NoCredentials -> if anon /= currentRole then runInRole anon "" else app currentRole req
|
NoCredentials -> if anon /= authenticator then runInRole anon "" else app authenticator req
|
||||||
|
|
||||||
where
|
where
|
||||||
jwtSecret = cs $ configJwtSecret conf
|
jwtSecret = cs $ configJwtSecret conf
|
||||||
currentRole = cs $ configDbUser conf
|
|
||||||
anon = cs $ configAnonRole conf
|
anon = cs $ configAnonRole conf
|
||||||
httpRequesterRole :: RequestHeaders -> H.Tx P.Postgres s LoginAttempt
|
httpRequesterRole :: RequestHeaders -> H.Tx P.Postgres s LoginAttempt
|
||||||
httpRequesterRole hdrs = do
|
httpRequesterRole hdrs = do
|
||||||
|
|||||||
+11
-7
@@ -20,6 +20,7 @@ import Network.HTTP.Types.Header (Header, ByteRange, renderByteRange,
|
|||||||
import Codec.Binary.Base64.String (encode)
|
import Codec.Binary.Base64.String (encode)
|
||||||
import Data.CaseInsensitive (CI(..))
|
import Data.CaseInsensitive (CI(..))
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
|
import Data.Functor.Identity
|
||||||
import Text.Regex.TDFA ((=~))
|
import Text.Regex.TDFA ((=~))
|
||||||
import qualified Data.ByteString.Char8 as BS
|
import qualified Data.ByteString.Char8 as BS
|
||||||
import System.Process (readProcess)
|
import System.Process (readProcess)
|
||||||
@@ -33,28 +34,31 @@ import PostgREST.Error(errResponse)
|
|||||||
import PostgREST.PgStructure
|
import PostgREST.PgStructure
|
||||||
import PostgREST.Types
|
import PostgREST.Types
|
||||||
|
|
||||||
|
dbString :: String
|
||||||
|
dbString = "postgres://postgrest_test@localhost:5432/postgrest_test"
|
||||||
|
|
||||||
isLeft :: Either a b -> Bool
|
isLeft :: Either a b -> Bool
|
||||||
isLeft (Left _ ) = True
|
isLeft (Left _ ) = True
|
||||||
isLeft _ = False
|
isLeft _ = False
|
||||||
|
|
||||||
cfg :: AppConfig
|
cfg :: AppConfig
|
||||||
cfg = AppConfig "postgrest_test" 5432 "postgrest_test" "" "localhost" 3000 "postgrest_anonymous" False 10 "test" "safe"
|
cfg = AppConfig dbString 3000 "postgrest_anonymous" "test" False "safe" 10
|
||||||
|
|
||||||
testPoolOpts :: PoolSettings
|
testPoolOpts :: PoolSettings
|
||||||
testPoolOpts = fromMaybe (error "bad settings") $ H.poolSettings 1 30
|
testPoolOpts = fromMaybe (error "bad settings") $ H.poolSettings 1 30
|
||||||
|
|
||||||
pgSettings :: P.Settings
|
pgSettings :: P.Settings
|
||||||
pgSettings = P.ParamSettings (cs $ configDbHost cfg)
|
pgSettings = P.StringSettings $ cs dbString
|
||||||
(fromIntegral $ configDbPort cfg)
|
|
||||||
(cs $ configDbUser cfg)
|
|
||||||
(cs $ configDbPass cfg)
|
|
||||||
(cs $ configDbName cfg)
|
|
||||||
|
|
||||||
withApp :: ActionWith Application -> IO ()
|
withApp :: ActionWith Application -> IO ()
|
||||||
withApp perform = do
|
withApp perform = do
|
||||||
pool :: H.Pool P.Postgres
|
pool :: H.Pool P.Postgres
|
||||||
<- H.acquirePool pgSettings testPoolOpts
|
<- H.acquirePool pgSettings testPoolOpts
|
||||||
|
|
||||||
|
Right authenticator <- H.session pool $ do
|
||||||
|
Identity (role :: Text) <- H.tx Nothing $ H.singleEx [H.stmt|SELECT SESSION_USER|]
|
||||||
|
return role
|
||||||
|
|
||||||
let txSettings = Just (H.ReadCommitted, Just True)
|
let txSettings = Just (H.ReadCommitted, Just True)
|
||||||
metadata <- H.session pool $ H.tx txSettings $ do
|
metadata <- H.session pool $ H.tx txSettings $ do
|
||||||
tabs <- allTables
|
tabs <- allTables
|
||||||
@@ -76,7 +80,7 @@ withApp perform = do
|
|||||||
perform $ middle $ \req resp -> do
|
perform $ middle $ \req resp -> do
|
||||||
body <- strictRequestBody req
|
body <- strictRequestBody req
|
||||||
result <- liftIO $ H.session pool $ H.tx txSettings
|
result <- liftIO $ H.session pool $ H.tx txSettings
|
||||||
$ authenticated cfg (app dbstructure cfg body) req
|
$ authenticated cfg authenticator (app dbstructure cfg authenticator body) req
|
||||||
either (resp . errResponse) resp result
|
either (resp . errResponse) resp result
|
||||||
|
|
||||||
where middle = defaultMiddle False
|
where middle = defaultMiddle False
|
||||||
|
|||||||
Reference in New Issue
Block a user