feat: add openapi-mode config (#1881)

* openapi-mode="follow-acl"(default): follows access control for the
JWT role.
* openapi-mode="ignore-acl": ignores access control for the JWT role.
* openapi-mode="disabled": disables OpenAPI output, the root endpoint
replies with 404 Not Found.
This commit is contained in:
Steve Chavez
2021-06-25 19:20:04 -05:00
committed by GitHub
parent 214a92f207
commit 41d119b19f
20 changed files with 144 additions and 12 deletions
+15 -6
View File
@@ -53,7 +53,8 @@ import qualified PostgREST.Request.DbRequestBuilder as ReqBuilder
import PostgREST.AppState (AppState)
import PostgREST.Config (AppConfig (..),
LogLevel (..))
LogLevel (..),
OpenAPIMode (..))
import PostgREST.Config.PgVersion (PgVersion (..))
import PostgREST.ContentType (ContentType (..))
import PostgREST.DbStructure (DbStructure (..),
@@ -463,11 +464,19 @@ handleInvoke invMethod proc context@RequestContext{..} = do
handleOpenApi :: Bool -> Schema -> RequestContext -> DbHandler Wai.Response
handleOpenApi headersOnly tSchema (RequestContext conf@AppConfig{..} dbStructure apiRequest _) = do
body <-
lift $
OpenAPI.encode conf dbStructure
<$> SQL.statement tSchema (DbStructure.accessibleTables configDbPreparedStatements)
<*> SQL.statement tSchema (DbStructure.schemaDescription configDbPreparedStatements)
<*> SQL.statement tSchema (DbStructure.accessibleProcs configDbPreparedStatements)
lift $ case configOpenApiMode of
OAFollowACL ->
OpenAPI.encode conf dbStructure
<$> SQL.statement tSchema (DbStructure.accessibleTables configDbPreparedStatements)
<*> SQL.statement tSchema (DbStructure.accessibleProcs configDbPreparedStatements)
<*> SQL.statement tSchema (DbStructure.schemaDescription configDbPreparedStatements)
OAIgnoreACL ->
OpenAPI.encode conf dbStructure
(DbStructure.dbTables dbStructure)
(DbStructure.dbProcs dbStructure)
<$> SQL.statement tSchema (DbStructure.schemaDescription configDbPreparedStatements)
OADisabled ->
pure mempty
return $
Wai.responseLBS HTTP.status200
+4
View File
@@ -192,6 +192,10 @@ exampleConfigFile =
|## when none is provided, 660 is applied by default
|# server-unix-socket-mode = "660"
|
|## determine if swagger output should follow or ignore ACL constraints or be disabled entirely
|## admitted values: follow-acl, ignore-acl, disabled
|openapi-mode = "follow-acl"
|
|## base url for swagger output
|openapi-server-proxy-uri = ""
|
+21
View File
@@ -16,6 +16,7 @@ module PostgREST.Config
, JSPath
, JSPathExp(..)
, LogLevel(..)
, OpenAPIMode(..)
, Proxy(..)
, toText
, isMalformedProxyUri
@@ -85,6 +86,7 @@ data AppConfig = AppConfig
, configJwtSecret :: Maybe B.ByteString
, configJwtSecretIsBase64 :: Bool
, configLogLevel :: LogLevel
, configOpenApiMode :: OpenAPIMode
, configOpenApiServerProxyUri :: Maybe Text
, configRawMediaTypes :: [B.ByteString]
, configServerHost :: Text
@@ -101,6 +103,14 @@ instance Show LogLevel where
show LogWarn = "warn"
show LogInfo = "info"
data OpenAPIMode = OAFollowACL | OAIgnoreACL | OADisabled
deriving Eq
instance Show OpenAPIMode where
show OAFollowACL = "follow-acl"
show OAIgnoreACL = "ignore-acl"
show OADisabled = "disabled"
-- | Dump the config
toText :: AppConfig -> Text
toText conf =
@@ -127,6 +137,7 @@ toText conf =
,("jwt-secret", q . toS . showJwtSecret)
,("jwt-secret-is-base64", T.toLower . show . configJwtSecretIsBase64)
,("log-level", q . show . configLogLevel)
,("openapi-mode", q . show . configOpenApiMode)
,("openapi-server-proxy-uri", q . fromMaybe mempty . configOpenApiServerProxyUri)
,("raw-media-types", q . toS . B.intercalate "," . configRawMediaTypes)
,("server-host", q . configServerHost)
@@ -220,6 +231,7 @@ parser optPath env dbSettings =
(optBool "jwt-secret-is-base64")
(optBool "secret-is-base64"))
<*> parseLogLevel "log-level"
<*> parseOpenAPIMode "openapi-mode"
<*> parseOpenAPIServerProxyURI "openapi-server-proxy-uri"
<*> (maybe [] (fmap encodeUtf8 . splitOnCommas) <$> optValue "raw-media-types")
<*> (fromMaybe "!4" <$> optString "server-host")
@@ -247,6 +259,15 @@ parser optPath env dbSettings =
then fail "Invalid server-unix-socket-mode: needs to be between 600 and 777"
else pure fileMode
parseOpenAPIMode :: C.Key -> C.Parser C.Config OpenAPIMode
parseOpenAPIMode k =
optString k >>= \case
Nothing -> pure OAFollowACL
Just "follow-acl" -> pure OAFollowACL
Just "ignore-acl" -> pure OAIgnoreACL
Just "disabled" -> pure OADisabled
Just _ -> fail "Invalid openapi-mode. Check your configuration."
parseOpenAPIServerProxyURI :: C.Key -> C.Parser C.Config (Maybe Text)
parseOpenAPIServerProxyURI k =
optString k >>= \case
+2 -2
View File
@@ -40,8 +40,8 @@ import PostgREST.ContentType
import Protolude hiding (Proxy, get, toS)
import Protolude.Conv (toS)
encode :: AppConfig -> DbStructure -> [Table] -> Maybe Text -> HashMap.HashMap k [ProcDescription] -> LBS.ByteString
encode conf dbStructure tables schemaDescription procs =
encode :: AppConfig -> DbStructure -> [Table] -> HashMap.HashMap k [ProcDescription] -> Maybe Text -> LBS.ByteString
encode conf dbStructure tables procs schemaDescription =
JSON.encode $
postgrestSpec
(dbRelationships dbStructure)
+5 -3
View File
@@ -44,7 +44,8 @@ import Network.Wai (Request (..))
import Network.Wai.Parse (parseHttpAccept)
import Web.Cookie (parseCookies)
import PostgREST.Config (AppConfig (..))
import PostgREST.Config (AppConfig (..),
OpenAPIMode (..))
import PostgREST.ContentType (ContentType (..))
import PostgREST.DbStructure (DbStructure (..))
import PostgREST.DbStructure.Identifiers (FieldName,
@@ -313,8 +314,9 @@ userApiRequest conf@AppConfig{..} dbStructure req reqBody
in
case path of
[] -> case configDbRootSpec of
Just (QualifiedIdentifier pSch pName) -> TargetProc (callFindProc (if pSch == mempty then schema else pSch) pName) True
Nothing -> TargetDefaultSpec schema
Just (QualifiedIdentifier pSch pName) -> TargetProc (callFindProc (if pSch == mempty then schema else pSch) pName) True
Nothing | configOpenApiMode == OADisabled -> TargetUnknown
| otherwise -> TargetDefaultSpec schema
[table] -> TargetIdent $ QualifiedIdentifier schema table
["rpc", pName] -> TargetProc (callFindProc schema pName) False
_ -> TargetUnknown