mirror of
https://github.com/zhigang1992/graphql-engine.git
synced 2026-05-21 06:38:35 +08:00
committed by
Shahidh K Muhammed
parent
097bfb6bfa
commit
1fa66dc622
@@ -66,6 +66,12 @@ combine_hpc_reports() {
|
||||
rm graphql-engine.tix || true
|
||||
}
|
||||
|
||||
kill_hge_and_combine_hpc_reports() {
|
||||
kill -INT $PID
|
||||
wait $PID || true
|
||||
combine_hpc_reports
|
||||
}
|
||||
|
||||
if [ -z "${HASURA_GRAPHQL_DATABASE_URL:-}" ] ; then
|
||||
echo "Env var HASURA_GRAPHQL_DATABASE_URL is not set"
|
||||
exit 1
|
||||
@@ -147,9 +153,7 @@ wait_for_port 8080
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET"
|
||||
|
||||
kill -INT $PID
|
||||
sleep 4
|
||||
combine_hpc_reports
|
||||
kill_hge_and_combine_hpc_reports
|
||||
|
||||
##########
|
||||
echo -e "\n<########## TEST GRAPHQL-ENGINE WITH ADMIN SECRET AND JWT #####################################>\n"
|
||||
@@ -162,9 +166,7 @@ export HASURA_GRAPHQL_JWT_SECRET="$(jq -n --arg key "$(cat $OUTPUT_FOLDER/ssl/jw
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-jwt-key-file="$OUTPUT_FOLDER/ssl/jwt_private.key" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET"
|
||||
|
||||
kill -INT $PID
|
||||
sleep 4
|
||||
combine_hpc_reports
|
||||
kill_hge_and_combine_hpc_reports
|
||||
|
||||
unset HASURA_GRAPHQL_JWT_SECRET
|
||||
|
||||
@@ -176,9 +178,7 @@ export HASURA_GRAPHQL_JWT_SECRET="$(jq -n --arg key "$(cat $OUTPUT_FOLDER/ssl/jw
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-jwt-key-file="$OUTPUT_FOLDER/ssl/jwt_private.key" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET" test_jwt.py
|
||||
|
||||
kill -INT $PID
|
||||
sleep 4
|
||||
combine_hpc_reports
|
||||
kill_hge_and_combine_hpc_reports
|
||||
|
||||
unset HASURA_GRAPHQL_JWT_SECRET
|
||||
|
||||
@@ -193,11 +193,52 @@ wait_for_port 8080
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --test-cors test_cors.py
|
||||
|
||||
kill -INT $PID
|
||||
sleep 4
|
||||
combine_hpc_reports
|
||||
kill_hge_and_combine_hpc_reports
|
||||
|
||||
unset HASURA_GRAPHQL_CORS_DOMAIN
|
||||
|
||||
echo -e "\n<########## TEST GRAPHQL-ENGINE WITH GRAPHQL DISABLED ########>\n"
|
||||
|
||||
export HASURA_GRAPHQL_ENABLED_APIS="metadata"
|
||||
|
||||
"$GRAPHQL_ENGINE" serve >> "$OUTPUT_FOLDER/graphql-engine.log" 2>&1 & PID=$!
|
||||
|
||||
wait_for_port 8080
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --test-graphql-disabled test_apis_disabled.py
|
||||
|
||||
kill_hge_and_combine_hpc_reports
|
||||
|
||||
unset HASURA_GRAPHQL_ENABLED_APIS
|
||||
|
||||
"$GRAPHQL_ENGINE" serve --enabled-apis metadata >> "$OUTPUT_FOLDER/graphql-engine.log" 2>&1 & PID=$!
|
||||
|
||||
wait_for_port 8080
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --test-graphql-disabled test_apis_disabled.py
|
||||
|
||||
kill_hge_and_combine_hpc_reports
|
||||
|
||||
echo -e "\n<########## TEST GRAPHQL-ENGINE WITH METADATA DISABLED ########>\n"
|
||||
|
||||
export HASURA_GRAPHQL_ENABLED_APIS="graphql"
|
||||
|
||||
"$GRAPHQL_ENGINE" serve >> "$OUTPUT_FOLDER/graphql-engine.log" 2>&1 & PID=$!
|
||||
|
||||
wait_for_port 8080
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --test-metadata-disabled test_apis_disabled.py
|
||||
|
||||
kill_hge_and_combine_hpc_reports
|
||||
unset HASURA_GRAPHQL_ENABLED_APIS
|
||||
|
||||
"$GRAPHQL_ENGINE" serve --enabled-apis graphql >> "$OUTPUT_FOLDER/graphql-engine.log" 2>&1 & PID=$!
|
||||
|
||||
wait_for_port 8080
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --test-metadata-disabled test_apis_disabled.py
|
||||
|
||||
kill_hge_and_combine_hpc_reports
|
||||
|
||||
# webhook tests
|
||||
|
||||
@@ -223,25 +264,21 @@ if [ "$RUN_WEBHOOK_TESTS" == "true" ] ; then
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK"
|
||||
|
||||
kill -INT $PID
|
||||
sleep 4
|
||||
combine_hpc_reports
|
||||
kill_hge_and_combine_hpc_reports
|
||||
|
||||
echo -e "\n<########## TEST GRAPHQL-ENGINE WITH ADMIN SECRET & WEBHOOK (POST) #########################>\n"
|
||||
export HASURA_GRAPHQL_AUTH_HOOK_MODE="POST"
|
||||
|
||||
"$GRAPHQL_ENGINE" serve >> "$OUTPUT_FOLDER/graphql-engine.log" 2>&1 & PID=$!
|
||||
|
||||
wait_for_port 8080
|
||||
wait_for_port 8080
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK"
|
||||
|
||||
rm /etc/ssl/certs/webhook.crt
|
||||
update-ca-certificates
|
||||
|
||||
kill -INT $PID
|
||||
sleep 4
|
||||
combine_hpc_reports
|
||||
kill_hge_and_combine_hpc_reports
|
||||
|
||||
echo -e "\n<########## TEST GRAPHQL-ENGINE WITH ADMIN SECRET & HTTPS INSECURE WEBHOOK (GET) ########>\n"
|
||||
export HASURA_GRAPHQL_AUTH_HOOK_MODE="GET"
|
||||
@@ -252,9 +289,7 @@ if [ "$RUN_WEBHOOK_TESTS" == "true" ] ; then
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK" --test-webhook-insecure test_webhook_insecure.py
|
||||
|
||||
kill -INT $PID
|
||||
sleep 4
|
||||
combine_hpc_reports
|
||||
kill_hge_and_combine_hpc_reports
|
||||
|
||||
echo -e "\n<########## TEST GRAPHQL-ENGINE WITH ADMIN_SECRET & HTTPS INSECURE WEBHOOK (POST) ########>\n"
|
||||
export HASURA_GRAPHQL_AUTH_HOOK_MODE="POST"
|
||||
@@ -265,9 +300,7 @@ if [ "$RUN_WEBHOOK_TESTS" == "true" ] ; then
|
||||
|
||||
pytest -vv --hge-url="$HGE_URL" --pg-url="$HASURA_GRAPHQL_DATABASE_URL" --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK" --test-webhook-insecure test_webhook_insecure.py
|
||||
|
||||
kill -INT $PID
|
||||
sleep 4
|
||||
combine_hpc_reports
|
||||
kill_hge_and_combine_hpc_reports
|
||||
|
||||
kill $WH_PID
|
||||
|
||||
|
||||
@@ -139,6 +139,9 @@ For ``serve`` sub-command these are the flags and ENV variables available:
|
||||
- ``HASURA_GRAPHQL_TX_ISOLATION``
|
||||
- transaction isolation. read-committed / repeatable-read / serializable (default: read-commited)
|
||||
|
||||
* - ``--enabled-apis <APIS>``
|
||||
- ``HASURA_GRAPHQL_ENABLED_APIS``
|
||||
- Comma separated list of APIs (metadata & graphql) to be enabled. (default: ``metadata,graphql``)
|
||||
|
||||
.. note::
|
||||
When the equivalent flags for environment variables are used, the flags will take precedence.
|
||||
|
||||
@@ -71,6 +71,7 @@ parseHGECommand =
|
||||
<*> parseCorsConfig
|
||||
<*> parseEnableConsole
|
||||
<*> parseEnableTelemetry
|
||||
<*> parseEnabledAPIs
|
||||
|
||||
parseArgs :: IO HGEOptions
|
||||
parseArgs = do
|
||||
@@ -101,7 +102,7 @@ main = do
|
||||
let logger = mkLogger loggerCtx
|
||||
case hgeCmd of
|
||||
HCServe so@(ServeOptions port host cp isoL mAdminSecret mAuthHook mJwtSecret
|
||||
mUnAuthRole corsCfg enableConsole enableTelemetry) -> do
|
||||
mUnAuthRole corsCfg enableConsole enableTelemetry enabledAPIs) -> do
|
||||
-- log serve options
|
||||
unLogger logger $ serveOptsToLog so
|
||||
hloggerCtx <- mkLoggerCtx $ defaultLoggerSettings False
|
||||
@@ -123,7 +124,7 @@ main = do
|
||||
|
||||
pool <- Q.initPGPool ci cp
|
||||
(app, cacheRef) <- mkWaiApp isoL loggerCtx pool httpManager
|
||||
am corsCfg enableConsole enableTelemetry
|
||||
am corsCfg enableConsole enableTelemetry enabledAPIs
|
||||
|
||||
let warpSettings = Warp.setPort port $ Warp.setHost host Warp.defaultSettings
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import qualified Data.ByteString.Lazy as BL
|
||||
import qualified Data.FileEmbed as FE
|
||||
#endif
|
||||
import qualified Data.HashMap.Strict as M
|
||||
import qualified Data.HashSet as S
|
||||
import qualified Data.Text as T
|
||||
import qualified Network.HTTP.Client as HTTP
|
||||
import qualified Network.HTTP.Types as N
|
||||
@@ -89,13 +90,14 @@ mkConsoleHTML path authMode enableTelemetry =
|
||||
|
||||
data ServerCtx
|
||||
= ServerCtx
|
||||
{ scIsolation :: Q.TxIsolation
|
||||
, scPGPool :: Q.PGPool
|
||||
, scLogger :: L.Logger
|
||||
, scCacheRef :: IORef SchemaCache
|
||||
, scCacheLock :: MVar ()
|
||||
, scAuthMode :: AuthMode
|
||||
, scManager :: HTTP.Manager
|
||||
{ scIsolation :: Q.TxIsolation
|
||||
, scPGPool :: Q.PGPool
|
||||
, scLogger :: L.Logger
|
||||
, scCacheRef :: IORef SchemaCache
|
||||
, scCacheLock :: MVar ()
|
||||
, scAuthMode :: AuthMode
|
||||
, scManager :: HTTP.Manager
|
||||
, scEnabledAPIs :: S.HashSet API
|
||||
}
|
||||
|
||||
data HandlerCtx
|
||||
@@ -108,6 +110,12 @@ data HandlerCtx
|
||||
|
||||
type Handler = ExceptT QErr (ReaderT HandlerCtx IO)
|
||||
|
||||
isMetadataEnabled :: ServerCtx -> Bool
|
||||
isMetadataEnabled sc = S.member METADATA $ scEnabledAPIs sc
|
||||
|
||||
isGraphQLEnabled :: ServerCtx -> Bool
|
||||
isGraphQLEnabled sc = S.member GRAPHQL $ scEnabledAPIs sc
|
||||
|
||||
-- {-# SCC parseBody #-}
|
||||
parseBody :: (FromJSON a) => Handler a
|
||||
parseBody = do
|
||||
@@ -289,8 +297,9 @@ mkWaiApp
|
||||
-> CorsConfig
|
||||
-> Bool
|
||||
-> Bool
|
||||
-> S.HashSet API
|
||||
-> IO (Wai.Application, IORef SchemaCache)
|
||||
mkWaiApp isoLevel loggerCtx pool httpManager mode corsCfg enableConsole enableTelemetry = do
|
||||
mkWaiApp isoLevel loggerCtx pool httpManager mode corsCfg enableConsole enableTelemetry apis = do
|
||||
cacheRef <- do
|
||||
pgResp <- runExceptT $ peelRun emptySchemaCache adminUserInfo
|
||||
httpManager pool Q.Serializable buildSchemaCache
|
||||
@@ -300,7 +309,7 @@ mkWaiApp isoLevel loggerCtx pool httpManager mode corsCfg enableConsole enableTe
|
||||
|
||||
let serverCtx =
|
||||
ServerCtx isoLevel pool (L.mkLogger loggerCtx) cacheRef
|
||||
cacheLock mode httpManager
|
||||
cacheLock mode httpManager apis
|
||||
|
||||
spockApp <- spockAsApp $ spockT id $
|
||||
httpApp corsCfg serverCtx enableConsole enableTelemetry
|
||||
@@ -318,41 +327,45 @@ httpApp corsCfg serverCtx enableConsole enableTelemetry = do
|
||||
middleware $ corsMiddleware (mkDefaultCorsPolicy corsCfg)
|
||||
|
||||
-- API Console and Root Dir
|
||||
when enableConsole serveApiConsole
|
||||
when (enableConsole && enableMetadata) serveApiConsole
|
||||
|
||||
get "v1/version" $ do
|
||||
uncurry setHeader jsonHeader
|
||||
lazyBytes $ encode $ object [ "version" .= currentVersion ]
|
||||
|
||||
get ("v1/template" <//> var) tmpltGetOrDeleteH
|
||||
post ("v1/template" <//> var) tmpltPutOrPostH
|
||||
put ("v1/template" <//> var) tmpltPutOrPostH
|
||||
delete ("v1/template" <//> var) tmpltGetOrDeleteH
|
||||
when enableMetadata $ do
|
||||
get ("v1/template" <//> var) tmpltGetOrDeleteH
|
||||
post ("v1/template" <//> var) tmpltPutOrPostH
|
||||
put ("v1/template" <//> var) tmpltPutOrPostH
|
||||
delete ("v1/template" <//> var) tmpltGetOrDeleteH
|
||||
|
||||
post "v1/query" $ mkSpockAction encodeQErr serverCtx $ do
|
||||
query <- parseBody
|
||||
v1QueryHandler query
|
||||
post "v1/query" $ mkSpockAction encodeQErr serverCtx $ do
|
||||
query <- parseBody
|
||||
v1QueryHandler query
|
||||
|
||||
post "v1alpha1/graphql/explain" $ mkSpockAction encodeQErr serverCtx $ do
|
||||
expQuery <- parseBody
|
||||
gqlExplainHandler expQuery
|
||||
post ("api/1/table" <//> var <//> var) $ \tableName queryType ->
|
||||
mkSpockAction encodeQErr serverCtx $
|
||||
legacyQueryHandler (TableName tableName) queryType
|
||||
|
||||
post "v1alpha1/graphql" $ mkSpockAction GH.encodeGQErr serverCtx $ do
|
||||
query <- parseBody
|
||||
v1Alpha1GQHandler query
|
||||
when enableGraphQL $ do
|
||||
post "v1alpha1/graphql/explain" $ mkSpockAction encodeQErr serverCtx $ do
|
||||
expQuery <- parseBody
|
||||
gqlExplainHandler expQuery
|
||||
|
||||
-- get "v1alpha1/graphql/schema" $
|
||||
-- mkSpockAction encodeQErr serverCtx v1Alpha1GQSchemaHandler
|
||||
post "v1alpha1/graphql" $ mkSpockAction GH.encodeGQErr serverCtx $ do
|
||||
query <- parseBody
|
||||
v1Alpha1GQHandler query
|
||||
|
||||
post ("api/1/table" <//> var <//> var) $ \tableName queryType ->
|
||||
mkSpockAction encodeQErr serverCtx $
|
||||
legacyQueryHandler (TableName tableName) queryType
|
||||
-- get "v1alpha1/graphql/schema" $
|
||||
-- mkSpockAction encodeQErr serverCtx v1Alpha1GQSchemaHandler
|
||||
|
||||
hookAny GET $ \_ -> do
|
||||
forM_ [GET,POST] $ \m -> hookAny m $ \_ -> do
|
||||
let qErr = err404 NotFound "resource does not exist"
|
||||
raiseGenericApiError qErr
|
||||
|
||||
where
|
||||
enableGraphQL = isGraphQLEnabled serverCtx
|
||||
enableMetadata = isMetadataEnabled serverCtx
|
||||
tmpltGetOrDeleteH tmpltName = do
|
||||
tmpltArgs <- tmpltArgsFromQueryParams
|
||||
mkSpockAction encodeQErr serverCtx $ mkQTemplateAction tmpltName tmpltArgs
|
||||
|
||||
@@ -7,6 +7,7 @@ import System.Exit (exitFailure)
|
||||
|
||||
import qualified Data.Aeson as J
|
||||
import qualified Data.String as DataString
|
||||
import qualified Data.HashSet as Set
|
||||
import qualified Data.Text as T
|
||||
import qualified Text.PrettyPrint.ANSI.Leijen as PP
|
||||
|
||||
@@ -47,6 +48,7 @@ data RawServeOptions
|
||||
, rsoCorsConfig :: !(Maybe CorsConfig)
|
||||
, rsoEnableConsole :: !Bool
|
||||
, rsoEnableTelemetry :: !(Maybe Bool)
|
||||
, rsoEnabledAPIs :: !(Maybe [API])
|
||||
} deriving (Show, Eq)
|
||||
|
||||
data ServeOptions
|
||||
@@ -62,6 +64,7 @@ data ServeOptions
|
||||
, soCorsConfig :: !CorsConfig
|
||||
, soEnableConsole :: !Bool
|
||||
, soEnableTelemetry :: !Bool
|
||||
, soEnabledAPIs :: !(Set.HashSet API)
|
||||
} deriving (Show, Eq)
|
||||
|
||||
data RawConnInfo =
|
||||
@@ -83,6 +86,13 @@ data HGECommandG a
|
||||
| HCVersion
|
||||
deriving (Show, Eq)
|
||||
|
||||
data API
|
||||
= METADATA
|
||||
| GRAPHQL
|
||||
deriving (Show, Eq, Read, Generic)
|
||||
|
||||
instance Hashable API
|
||||
|
||||
type HGECommand = HGECommandG ServeOptions
|
||||
type RawHGECommand = HGECommandG RawServeOptions
|
||||
|
||||
@@ -130,6 +140,9 @@ instance FromEnv Q.TxIsolation where
|
||||
instance FromEnv CorsConfig where
|
||||
fromEnv = readCorsDomains
|
||||
|
||||
instance FromEnv [API] where
|
||||
fromEnv = readAPIs
|
||||
|
||||
parseStrAsBool :: String -> Either String Bool
|
||||
parseStrAsBool t
|
||||
| t `elem` truthVals = Right True
|
||||
@@ -226,9 +239,11 @@ mkServeOptions rso = do
|
||||
fst enableConsoleEnv
|
||||
enableTelemetry <- fromMaybe True <$>
|
||||
withEnv (rsoEnableTelemetry rso) (fst enableTelemetryEnv)
|
||||
enabledAPIs <- Set.fromList . fromMaybe [METADATA,GRAPHQL] <$>
|
||||
withEnv (rsoEnabledAPIs rso) (fst enabledAPIsEnv)
|
||||
|
||||
return $ ServeOptions port host connParams txIso adminScrt authHook jwtSecret
|
||||
unAuthRole corsCfg enableConsole enableTelemetry
|
||||
unAuthRole corsCfg enableConsole enableTelemetry enabledAPIs
|
||||
where
|
||||
mkConnParams (RawConnParams s c i p) = do
|
||||
stripes <- fromMaybe 1 <$> withEnv s (fst pgStripesEnv)
|
||||
@@ -442,6 +457,12 @@ enableTelemetryEnv =
|
||||
, "Enable anonymous telemetry (default: true)"
|
||||
)
|
||||
|
||||
enabledAPIsEnv :: (String,String)
|
||||
enabledAPIsEnv =
|
||||
( "HASURA_GRAPHQL_ENABLED_APIS"
|
||||
, "List of comma separated list of allowed APIs. (default: metadata,graphql)"
|
||||
)
|
||||
|
||||
parseRawConnInfo :: Parser RawConnInfo
|
||||
parseRawConnInfo =
|
||||
RawConnInfo <$> host <*> port <*> user <*> password
|
||||
@@ -584,6 +605,13 @@ readHookType tyS =
|
||||
"POST" -> Right AHTPost
|
||||
_ -> Left "Only expecting GET / POST"
|
||||
|
||||
readAPIs :: String -> Either String [API]
|
||||
readAPIs = mapM readAPI . T.splitOn "," . T.pack
|
||||
where readAPI si = case T.toUpper $ T.strip si of
|
||||
"METADATA" -> Right METADATA
|
||||
"GRAPHQL" -> Right GRAPHQL
|
||||
_ -> Left "Only expecting list of comma separated API types metadata / graphql"
|
||||
|
||||
parseWebHook :: Parser RawAuthHook
|
||||
parseWebHook =
|
||||
AuthHookG <$> url <*> urlType
|
||||
@@ -652,6 +680,13 @@ parseEnableTelemetry = optional $
|
||||
help (snd enableTelemetryEnv)
|
||||
)
|
||||
|
||||
parseEnabledAPIs :: Parser (Maybe [API])
|
||||
parseEnabledAPIs = optional $
|
||||
option (eitherReader readAPIs)
|
||||
( long "enabled-apis" <>
|
||||
help (snd enabledAPIsEnv)
|
||||
)
|
||||
|
||||
-- Init logging related
|
||||
connInfoToLog :: Q.ConnInfo -> StartupLog
|
||||
connInfoToLog (Q.ConnInfo host port user _ db _) =
|
||||
|
||||
@@ -33,6 +33,16 @@ def pytest_addoption(parser):
|
||||
help="Run testcases for CORS configuration"
|
||||
)
|
||||
|
||||
parser.addoption(
|
||||
"--test-metadata-disabled", action="store_true",
|
||||
help="Run Test cases with metadata queries being disabled"
|
||||
)
|
||||
|
||||
parser.addoption(
|
||||
"--test-graphql-disabled", action="store_true",
|
||||
help="Run Test cases with GraphQL queries being disabled"
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def hge_ctx(request):
|
||||
@@ -45,6 +55,7 @@ def hge_ctx(request):
|
||||
hge_jwt_key_file = request.config.getoption('--hge-jwt-key-file')
|
||||
hge_jwt_conf = request.config.getoption('--hge-jwt-conf')
|
||||
test_cors = request.config.getoption('--test-cors')
|
||||
metadata_disabled = request.config.getoption('--test-metadata-disabled')
|
||||
try:
|
||||
hge_ctx = HGECtx(
|
||||
hge_url=hge_url,
|
||||
@@ -53,7 +64,8 @@ def hge_ctx(request):
|
||||
hge_webhook=hge_webhook,
|
||||
webhook_insecure=webhook_insecure,
|
||||
hge_jwt_key_file=hge_jwt_key_file,
|
||||
hge_jwt_conf=hge_jwt_conf
|
||||
hge_jwt_conf=hge_jwt_conf,
|
||||
metadata_disabled=metadata_disabled
|
||||
)
|
||||
except HGECtxError as e:
|
||||
pytest.exit(str(e))
|
||||
|
||||
@@ -74,7 +74,7 @@ class WebhookServer(http.server.HTTPServer):
|
||||
|
||||
|
||||
class HGECtx:
|
||||
def __init__(self, hge_url, pg_url, hge_key, hge_webhook, webhook_insecure, hge_jwt_key_file, hge_jwt_conf):
|
||||
def __init__(self, hge_url, pg_url, hge_key, hge_webhook, webhook_insecure, hge_jwt_key_file, hge_jwt_conf, metadata_disabled):
|
||||
server_address = ('0.0.0.0', 5592)
|
||||
|
||||
self.resp_queue = queue.Queue(maxsize=1)
|
||||
@@ -99,6 +99,7 @@ class HGECtx:
|
||||
self.hge_jwt_key = f.read()
|
||||
self.hge_jwt_conf = hge_jwt_conf
|
||||
self.webhook_insecure = webhook_insecure
|
||||
self.metadata_disabled = metadata_disabled
|
||||
self.may_skip_test_teardown = False
|
||||
|
||||
self.ws_url = urlparse(hge_url)
|
||||
@@ -116,12 +117,13 @@ class HGECtx:
|
||||
|
||||
result = subprocess.run(['../../scripts/get-version.sh'], shell=False, stdout=subprocess.PIPE, check=True)
|
||||
self.version = result.stdout.decode('utf-8').strip()
|
||||
try:
|
||||
st_code, resp = self.v1q_f('queries/clear_db.yaml')
|
||||
except requests.exceptions.RequestException as e:
|
||||
self.teardown()
|
||||
raise HGECtxError(repr(e))
|
||||
assert st_code == 200, resp
|
||||
if not self.metadata_disabled:
|
||||
try:
|
||||
st_code, resp = self.v1q_f('queries/clear_db.yaml')
|
||||
except requests.exceptions.RequestException as e:
|
||||
self.teardown()
|
||||
raise HGECtxError(repr(e))
|
||||
assert st_code == 200, resp
|
||||
|
||||
def _on_message(self, message):
|
||||
my_json = json.loads(message)
|
||||
@@ -152,6 +154,12 @@ class HGECtx:
|
||||
)
|
||||
return resp.status_code, resp.json()
|
||||
|
||||
def sql(self, q):
|
||||
conn = self.engine.connect()
|
||||
res = conn.execute(q)
|
||||
conn.close()
|
||||
return res
|
||||
|
||||
def v1q(self, q, headers = {}):
|
||||
h = headers.copy()
|
||||
if self.hge_key is not None:
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
description: GraphQL introspection query which returns the kind of queryType. This output should be the same across any GraphQL implementation
|
||||
url: /v1alpha1/graphql
|
||||
status: 200
|
||||
response:
|
||||
data:
|
||||
__schema:
|
||||
queryType:
|
||||
kind: OBJECT
|
||||
query:
|
||||
query: |
|
||||
query foo {
|
||||
__schema {
|
||||
queryType {
|
||||
kind
|
||||
}
|
||||
}
|
||||
}
|
||||
57
server/tests-py/test_apis_disabled.py
Normal file
57
server/tests-py/test_apis_disabled.py
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/usrbin/env python3
|
||||
|
||||
import pytest
|
||||
from validate import check_query, check_query_f
|
||||
|
||||
def check_post_404(hge_ctx,url):
|
||||
return check_query(hge_ctx, {
|
||||
'url': url,
|
||||
'status': 404,
|
||||
'query': {}
|
||||
})
|
||||
|
||||
|
||||
@pytest.mark.skipif(not pytest.config.getoption("--test-metadata-disabled"),
|
||||
reason="flag --test-metadata-disabled is not set. Cannot run tests for metadata disabled")
|
||||
class TestMetadataDisabled:
|
||||
|
||||
def test_metadata_v1_query_disabled(self, hge_ctx):
|
||||
check_post_404(hge_ctx,'/v1/query')
|
||||
|
||||
def test_metadata_v1_template_disabled(self, hge_ctx):
|
||||
check_post_404(hge_ctx,'/v1/template/foo')
|
||||
|
||||
def test_metadata_api_1_disabled(self, hge_ctx):
|
||||
check_post_404(hge_ctx,'/api/1/table/foo/select')
|
||||
|
||||
|
||||
@pytest.mark.skipif(not pytest.config.getoption("--test-graphql-disabled"),
|
||||
reason="--test-graphql-disabled is not set. Cannot run GraphQL disabled tests")
|
||||
class TestGraphQLDisabled:
|
||||
|
||||
def test_graphql_endpoint_disabled(self, hge_ctx):
|
||||
check_post_404(hge_ctx,'/v1alpha1/graphql')
|
||||
|
||||
def test_graphql_explain_disabled(self, hge_ctx):
|
||||
check_post_404(hge_ctx,'/v1alpha1/graphql/explain')
|
||||
|
||||
|
||||
@pytest.mark.skipif(pytest.config.getoption("--test-graphql-disabled"),
|
||||
reason="--test-graphql-disabled is set. Cannot run GraphQL enabled tests")
|
||||
class TestGraphQLEnabled:
|
||||
|
||||
def test_graphql_introspection(self, hge_ctx):
|
||||
check_query_f(hge_ctx, "queries/graphql_introspection/introspection_only_kind_of_queryType.yaml")
|
||||
|
||||
|
||||
@pytest.mark.skipif(pytest.config.getoption("--test-metadata-disabled"),
|
||||
reason="--test-metadata-disabled is set. Cannot run metadata enabled tests")
|
||||
class TestMetadataEnabled:
|
||||
|
||||
def test_reload_metadata(self, hge_ctx):
|
||||
check_query_f(hge_ctx, "queries/v1/metadata/reload_metadata.yaml")
|
||||
|
||||
def test_run_sql(self, hge_ctx):
|
||||
check_query_f(hge_ctx, "queries/v1/run_sql/sql_set_timezone.yaml")
|
||||
|
||||
|
||||
@@ -166,11 +166,9 @@ class TestAddRemoteSchemaTbls:
|
||||
|
||||
def test_add_schema(self, hge_ctx):
|
||||
""" check if the remote schema is added in the db """
|
||||
conn = hge_ctx.engine.connect()
|
||||
res = conn.execute('select * from hdb_catalog.remote_schemas')
|
||||
res = hge_ctx.sql('select * from hdb_catalog.remote_schemas')
|
||||
row = res.fetchone()
|
||||
assert row['name'] == "simple2-graphql"
|
||||
conn.close()
|
||||
|
||||
def test_add_schema_conflicts_with_tables(self, hge_ctx):
|
||||
"""add remote schema which conflicts with hasura tables"""
|
||||
|
||||
@@ -62,7 +62,7 @@ def test_forbidden_when_admin_secret_reqd(hge_ctx, conf):
|
||||
|
||||
# Test without admin secret
|
||||
code, resp = hge_ctx.anyq(conf['url'], conf['query'], headers)
|
||||
assert code == 401, "\n" + yaml.dump({
|
||||
assert code in [401,404], "\n" + yaml.dump({
|
||||
"expected": "Should be access denied as admin secret is not provided",
|
||||
"actual": {
|
||||
"code": code,
|
||||
@@ -73,7 +73,7 @@ def test_forbidden_when_admin_secret_reqd(hge_ctx, conf):
|
||||
# Test with random admin secret
|
||||
headers['X-Hasura-Admin-Secret'] = base64.b64encode(os.urandom(30))
|
||||
code, resp = hge_ctx.anyq(conf['url'], conf['query'], headers)
|
||||
assert code == 401, "\n" + yaml.dump({
|
||||
assert code in [401,404], "\n" + yaml.dump({
|
||||
"expected": "Should be access denied as an incorrect admin secret is provided",
|
||||
"actual": {
|
||||
"code": code,
|
||||
@@ -85,7 +85,7 @@ def test_forbidden_when_admin_secret_reqd(hge_ctx, conf):
|
||||
def test_forbidden_webhook(hge_ctx, conf):
|
||||
h = {'Authorization': 'Bearer ' + base64.b64encode(base64.b64encode(os.urandom(30))).decode('utf-8')}
|
||||
code, resp = hge_ctx.anyq(conf['url'], conf['query'], h)
|
||||
assert code == 401, "\n" + yaml.dump({
|
||||
assert code in [401,404], "\n" + yaml.dump({
|
||||
"expected": "Should be access denied as it is denied from webhook",
|
||||
"actual": {
|
||||
"code": code,
|
||||
|
||||
Reference in New Issue
Block a user