Add abuse test
This commit is contained in:
parent
13ff5ca45e
commit
221e7b59c4
|
@ -34,7 +34,7 @@ App::get('/v1/graphql')
|
|||
->inject('register')
|
||||
->inject('dbForProject')
|
||||
->inject('promiseAdapter')
|
||||
->inject('gqlSchema')
|
||||
->inject('schema')
|
||||
->action(Closure::fromCallable('graphqlRequest'));
|
||||
|
||||
App::post('/v1/graphql')
|
||||
|
@ -54,7 +54,7 @@ App::post('/v1/graphql')
|
|||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('promiseAdapter')
|
||||
->inject('gqlSchema')
|
||||
->inject('schema')
|
||||
->action(Closure::fromCallable('graphqlRequest'));
|
||||
|
||||
/**
|
||||
|
@ -66,7 +66,7 @@ function graphqlRequest(
|
|||
Appwrite\Utopia\Request $request,
|
||||
Appwrite\Utopia\Response $response,
|
||||
CoroutinePromiseAdapter $promiseAdapter,
|
||||
Type\Schema $gqlSchema
|
||||
Type\Schema $schema
|
||||
): void {
|
||||
$contentType = $request->getHeader('content-type');
|
||||
$maxBatchSize = App::getEnv('_APP_GRAPHQL_MAX_BATCH_SIZE', 50);
|
||||
|
@ -108,7 +108,7 @@ function graphqlRequest(
|
|||
foreach ($query as $indexed) {
|
||||
$promises[] = GraphQL::promiseToExecute(
|
||||
$promiseAdapter,
|
||||
$gqlSchema,
|
||||
$schema,
|
||||
$indexed['query'],
|
||||
variableValues: $indexed['variables'] ?? null,
|
||||
operationName: $indexed['operationName'] ?? null,
|
||||
|
@ -121,12 +121,11 @@ function graphqlRequest(
|
|||
$wg->add();
|
||||
$promiseAdapter->all($promises)->then(
|
||||
function (array $results) use (&$output, &$wg, $debugFlags) {
|
||||
processResult($results, $output, $debugFlags);
|
||||
$wg->done();
|
||||
},
|
||||
function ($error) use (&$output, $wg) {
|
||||
$output = ['errors' => [$error]];
|
||||
$wg->done();
|
||||
try {
|
||||
processResult($results, $output, $debugFlags);
|
||||
} finally {
|
||||
$wg->done();
|
||||
}
|
||||
}
|
||||
);
|
||||
$wg->wait();
|
||||
|
|
|
@ -1006,6 +1006,6 @@ App::setResource('promiseAdapter', function ($register) {
|
|||
return $register->get('promiseAdapter');
|
||||
}, ['register']);
|
||||
|
||||
App::setResource('gqlSchema', function ($utopia, $dbForProject) {
|
||||
App::setResource('schema', function ($utopia, $dbForProject) {
|
||||
return SchemaBuilder::buildSchema($utopia, $dbForProject);
|
||||
}, ['utopia', 'dbForProject']);
|
||||
|
|
68
tests/e2e/Services/GraphQL/GraphQLAbuseTest.php
Normal file
68
tests/e2e/Services/GraphQL/GraphQLAbuseTest.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\E2E\Services\GraphQL;
|
||||
|
||||
use Tests\E2E\Client;
|
||||
use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\Scope;
|
||||
use Tests\E2E\Scopes\SideServer;
|
||||
use Utopia\App;
|
||||
|
||||
class GraphQLAbuseTest extends Scope
|
||||
{
|
||||
use ProjectCustom;
|
||||
use SideServer;
|
||||
use GraphQLBase;
|
||||
|
||||
public function testComplexQueryBlocked()
|
||||
{
|
||||
$projectId = $this->getProject()['$id'];
|
||||
$query = $this->getQuery(self::$COMPLEX_QUERY);
|
||||
$graphQLPayload = [
|
||||
'query' => $query,
|
||||
'variables' => [
|
||||
'userId' => 'user',
|
||||
'email' => 'user@appwrite.io',
|
||||
'password' => 'password',
|
||||
'databaseId' => 'database',
|
||||
'databaseName' => 'database',
|
||||
'collectionId' => 'collection',
|
||||
'collectionName' => 'collection',
|
||||
'collectionPermission' => 'collection',
|
||||
'collectionRead' => ['role:member'],
|
||||
'collectionWrite' => ['role:member'],
|
||||
'documentId' => 'document',
|
||||
'documentData' => ['name' => 'foobar'],
|
||||
'documentRead' => ['role:member'],
|
||||
'documentWrite' => ['role:member'],
|
||||
],
|
||||
];
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
], $this->getHeaders()), $graphQLPayload);
|
||||
|
||||
\var_dump($response);
|
||||
|
||||
$this->assertEquals('Too many queries.', $response['body']['message']);
|
||||
}
|
||||
|
||||
public function testTooManyQueriesBlocked()
|
||||
{
|
||||
$projectId = $this->getProject()['$id'];
|
||||
$maxQueries = App::getEnv('_APP_GRAPHQL_MAX_QUERIES', 50);
|
||||
|
||||
$query = [];
|
||||
for ($i = 0; $i <= $maxQueries + 1; $i++) {
|
||||
$query[] = ['query' => $this->getQuery(self::$LIST_COUNTRIES)];
|
||||
}
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
], $this->getHeaders()), $query);
|
||||
|
||||
$this->assertEquals('Too many queries.', $response['body']['message']);
|
||||
}
|
||||
}
|
|
@ -174,6 +174,8 @@ trait GraphQLBase
|
|||
public static string $GET_QRCODE = 'get_qrcode';
|
||||
public static string $GET_USER_INITIALS = 'get_user_initials';
|
||||
|
||||
public static string $COMPLEX_QUERY = 'complex_query';
|
||||
|
||||
public function getQuery(string $name): string
|
||||
{
|
||||
switch ($name) {
|
||||
|
@ -1346,6 +1348,18 @@ trait GraphQLBase
|
|||
status
|
||||
}
|
||||
}';
|
||||
case self::$COMPLEX_QUERY:
|
||||
return 'mutation complex($databaseId: String!, $databaseName: String!, $collectionId: String!, $collectionName: String!, $collectionPermission: String!, $collectionRead: [String!]!, $collectionWrite: [String!]!) {
|
||||
databasesCreate(databaseId: $databaseId, name: $databaseName) {
|
||||
_id
|
||||
name
|
||||
}
|
||||
databasesCreateCollection(databaseId: $databaseId, collectionId: $collectionId, name: $collectionName, permission: $collectionPermission, read: $collectionRead, write: $collectionWrite) {
|
||||
_id
|
||||
name
|
||||
permission
|
||||
}
|
||||
}';
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Invalid query type');
|
||||
|
|
|
@ -46,7 +46,7 @@ class GraphQLContentTypeTest extends Scope
|
|||
$this->assertEquals(194, $response['total']);
|
||||
}
|
||||
|
||||
public function testBatchedJSONContentType()
|
||||
public function testArrayBatchedJSONContentType()
|
||||
{
|
||||
$projectId = $this->getProject()['$id'];
|
||||
$query1 = 'query { localeGetCountries { total countries { code } } }';
|
||||
|
@ -68,6 +68,31 @@ class GraphQLContentTypeTest extends Scope
|
|||
$this->assertEquals(7, $response['body']['data']['localeGetContinents']['total']);
|
||||
}
|
||||
|
||||
public function testQueryBatchedJSONContentType()
|
||||
{
|
||||
$projectId = $this->getProject()['$id'];
|
||||
$query = '
|
||||
query {
|
||||
localeGetCountries { total countries { code } }
|
||||
localeGetContinents { total continents { code } }
|
||||
}
|
||||
';
|
||||
$graphQLPayload = [
|
||||
['query' => $query],
|
||||
];
|
||||
$response = $this->client->call(Client::METHOD_POST, '/graphql', \array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
], $this->getHeaders()), $graphQLPayload);
|
||||
|
||||
$this->assertIsArray($response['body']['data']);
|
||||
$this->assertArrayNotHasKey('errors', $response['body']);
|
||||
$this->assertArrayHasKey('localeGetCountries', $response['body']['data']);
|
||||
$this->assertArrayHasKey('localeGetContinents', $response['body']['data']);
|
||||
$this->assertEquals(194, $response['body']['data']['localeGetCountries']['total']);
|
||||
$this->assertEquals(7, $response['body']['data']['localeGetContinents']['total']);
|
||||
}
|
||||
|
||||
public function testMultipartFormDataContentType()
|
||||
{
|
||||
$projectId = $this->getProject()['$id'];
|
||||
|
|
Loading…
Reference in a new issue