Continue Standardising Error Models

This commit is contained in:
Bradley Schofield
2023-03-14 09:31:10 +09:00
parent fbb489d7fe
commit 0798a577c1
8 changed files with 179 additions and 97 deletions
+51 -35
View File
@@ -23,7 +23,6 @@ use Utopia\Transfer\Sources\Appwrite as SourcesAppwrite;
use Utopia\Transfer\Sources\Firebase;
use Utopia\Transfer\Sources\NHost;
use Utopia\Transfer\Sources\Supabase;
use Utopia\Transfer\Transfer as TransferTransfer;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Integer;
use Utopia\Validator\JSON;
@@ -285,7 +284,7 @@ App::post('/v1/transfers/sources/:sourceId/validate')
->label('sdk.description', '/docs/references/transfers/validate-source.md')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ANY)
->label('sdk.response.model', Response::MODEL_SOURCE_VALIDATION)
->param('sourceId', '', new UID(), 'Source unique ID.')
->param('resources', TRANSFER_RESOURCES, new ArrayList(new WhiteList(TRANSFER_RESOURCES)), 'List of resources to test. If none are sent then all resources are tested. [A list of resources can be found here.](https://appwrite.io/docs/transfers#resources)', true)
->inject('response')
@@ -328,7 +327,13 @@ App::post('/v1/transfers/sources/:sourceId/validate')
return $response->json($result);
} catch (Throwable $e) {
throw new Exception(Exception::TRANSFER_SOURCE_FAILED, $e->getMessage(), 400);
return $response->setStatusCode(401)->dynamic(new Document([
'success' => false,
'message' => 'Missing Permissions',
'errors' => [
'Databases' => [$e->getMessage()],
],
]), Response::MODEL_DESTINATION_VALIDATION);
}
});
@@ -467,18 +472,17 @@ App::post('/v1/transfers/destinations/:destinationId/validate')
$result = $testAdapter->check($resources);
$result = array_filter($result, function ($value) {
return $value !== true;
return $value !== [];
});
if (count($result) == 0) {
return $response->dynamic(new Document([
'status' => 'success',
'message' => 'Destination is valid',
'errors' => $result
'success' => true,
'message' => 'Destination is valid'
]), Response::MODEL_DESTINATION_VALIDATION);
} else {
return $response->setStatusCode(401)->dynamic(new Document([
'status' => 'failed',
'success' => false,
'message' => 'Missing Permissions',
'errors' => $result
]), Response::MODEL_DESTINATION_VALIDATION);
@@ -567,8 +571,6 @@ App::post('/v1/transfers/sources/appwrite/validate')
->groups(['api', 'transfers'])
->desc('Validate Appwrite Source')
->label('scope', 'transfers.write')
->label('event', 'transfers.[sourceId].validateAppwriteSource')
->label('audits.event', 'transfers.validateAppwriteSource')
->label('audits.resource', 'sources/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'transfers')
@@ -586,9 +588,17 @@ App::post('/v1/transfers/sources/appwrite/validate')
try {
$testAdapter->check(); // Throws exception on failure
} catch (Exception $e) {
throw new Exception($e->getMessage(), 400);
return $response->setStatusCode(401)->dynamic(new Document([
'success' => false,
'message' => 'Missing Permissions',
'errors' => [
'Databases' => [$e->getMessage()],
],
]), Response::MODEL_DESTINATION_VALIDATION);
}
return $response->json(TRANSFER_RESOURCES);
});
@@ -641,8 +651,6 @@ App::post('/v1/transfers/sources/firebase/validate')
->groups(['api', 'transfers'])
->desc('Validate Firebase Source')
->label('scope', 'transfers.write')
->label('event', 'transfers.validateFirebaseSource')
->label('audits.event', 'transfers.validateFirebaseSource')
->label('audits.resource', 'sources/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'transfers')
@@ -722,8 +730,6 @@ App::post('/v1/transfers/sources/supabase/validate')
->groups(['api', 'transfers'])
->desc('Validate Supabase Source')
->label('scope', 'transfers.write')
->label('event', 'transfers.validateSupabaseSource')
->label('audits.event', 'transfers.validateSupabaseSource')
->label('audits.resource', 'sources/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'transfers')
@@ -744,21 +750,21 @@ App::post('/v1/transfers/sources/supabase/validate')
$result = $testAdapter->check();
$result = array_filter($result, function ($value) {
return $value !== true;
return $value !== [];
});
if (count($result) == 0) {
return $response->dynamic(new Document([
'status' => 'success',
'message' => 'Destination is valid',
'success' => true,
'message' => 'Source is valid',
'errors' => $result
]), Response::MODEL_DESTINATION_VALIDATION);
]), Response::MODEL_SOURCE_VALIDATION);
} else {
return $response->setStatusCode(401)->dynamic(new Document([
'status' => 'failed',
'success' => false,
'message' => 'Missing Permissions',
'errors' => $result
]), Response::MODEL_DESTINATION_VALIDATION);
]), Response::MODEL_SOURCE_VALIDATION);
}
});
@@ -819,8 +825,6 @@ App::post('/v1/transfers/sources/nhost/validate')
->groups(['api', 'transfers'])
->desc('Validate Nhost Source')
->label('scope', 'transfers.write')
->label('event', 'transfers.validateNhostSource')
->label('audits.event', 'transfers.validateNhostSource')
->label('audits.resource', 'sources/{response.$id}')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.namespace', 'transfers')
@@ -836,24 +840,36 @@ App::post('/v1/transfers/sources/nhost/validate')
->param('port', '5432', new Integer(true), 'Nhost Database Port. The port of the database to validate.', true)
->inject('response')
->action(function (string $url, string $database, string $username, string $password, string $port, Response $response) {
$testAdapter = new NHost($url, $database, $username, $password, $port);
try {
$testAdapter = new NHost($url, $database, $username, $password, $port);
} catch (Throwable $e) {
return $response->setStatusCode(401)->dynamic(new Document([
'success' => false,
'message' => 'Invalid Nhost Source',
'errors' => [
'Databases' => [$e->getMessage()],
]
]), Response::MODEL_SOURCE_VALIDATION);
};
$result = $testAdapter->check();
$result = array_filter($result, function ($value) {
return $value !== true;
return $value !== [];
});
if (count($result) == 0) {
return $response->dynamic(new Document([
'status' => 'success',
'message' => 'Destination is valid',
'success' => true,
'message' => 'Source is valid',
'errors' => $result
]), Response::MODEL_DESTINATION_VALIDATION);
]), Response::MODEL_SOURCE_VALIDATION);
} else {
return $response->setStatusCode(401)->dynamic(new Document([
'status' => 'failed',
'success' => false,
'message' => 'Missing Permissions',
'errors' => $result
]), Response::MODEL_DESTINATION_VALIDATION);
]), Response::MODEL_SOURCE_VALIDATION);
}
});
@@ -888,7 +904,7 @@ App::post('/v1/transfers/destinations/appwrite')
$result = $testAdapter->check();
$result = array_filter($result, function ($value) {
return $value !== true;
return $value !== [];
});
if (count($result) > 0) {
@@ -936,18 +952,18 @@ App::post('/v1/transfers/destinations/appwrite/validate')
$result = $testAdapter->check();
$result = array_filter($result, function ($value) {
return $value !== true;
return $value !== [];
});
if (count($result) == 0) {
return $response->dynamic(new Document([
'status' => 'success',
'success' => true,
'message' => 'Destination is valid',
'errors' => $result
]), Response::MODEL_DESTINATION_VALIDATION);
} else {
return $response->setStatusCode(401)->dynamic(new Document([
'status' => 'failed',
'success' => false,
'message' => 'Missing Permissions',
'errors' => $result
]), Response::MODEL_DESTINATION_VALIDATION);
Generated
+37 -37
View File
@@ -734,16 +734,16 @@
},
{
"name": "guzzlehttp/psr7",
"version": "2.4.3",
"version": "2.4.4",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "67c26b443f348a51926030c83481b85718457d3d"
"reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/67c26b443f348a51926030c83481b85718457d3d",
"reference": "67c26b443f348a51926030c83481b85718457d3d",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf",
"reference": "3cf1b6d4f0c820a2cf8bcaec39fc698f3443b5cf",
"shasum": ""
},
"require": {
@@ -833,7 +833,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.4.3"
"source": "https://github.com/guzzle/psr7/tree/2.4.4"
},
"funding": [
{
@@ -849,7 +849,7 @@
"type": "tidelift"
}
],
"time": "2022-10-26T14:07:24+00:00"
"time": "2023-03-09T13:19:02+00:00"
},
{
"name": "influxdb/influxdb-php",
@@ -1748,16 +1748,16 @@
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.2.0",
"version": "v3.2.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3"
"reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/1ee04c65529dea5d8744774d474e7cbd2f1206d3",
"reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e",
"reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e",
"shasum": ""
},
"require": {
@@ -1795,7 +1795,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0"
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1"
},
"funding": [
{
@@ -1811,7 +1811,7 @@
"type": "tidelift"
}
],
"time": "2022-11-25T10:21:52+00:00"
"time": "2023-03-01T10:25:55+00:00"
},
{
"name": "symfony/polyfill-php80",
@@ -2948,12 +2948,12 @@
"source": {
"type": "git",
"url": "https://github.com/utopia-php/transfer.git",
"reference": "84b543d9c9c344986930821be234adf9ee8adace"
"reference": "fae74e218c5deaa8ec13a7e85921791f8974948f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/transfer/zipball/84b543d9c9c344986930821be234adf9ee8adace",
"reference": "84b543d9c9c344986930821be234adf9ee8adace",
"url": "https://api.github.com/repos/utopia-php/transfer/zipball/fae74e218c5deaa8ec13a7e85921791f8974948f",
"reference": "fae74e218c5deaa8ec13a7e85921791f8974948f",
"shasum": ""
},
"require": {
@@ -2998,7 +2998,7 @@
"source": "https://github.com/utopia-php/transfer/tree/feat-database-and-documents",
"issues": "https://github.com/utopia-php/transfer/issues"
},
"time": "2023-02-24T06:12:39+00:00"
"time": "2023-02-24T16:24:24+00:00"
},
{
"name": "utopia-php/websocket",
@@ -3431,16 +3431,16 @@
},
{
"name": "myclabs/deep-copy",
"version": "1.11.0",
"version": "1.11.1",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
"reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
"reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
"reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
"shasum": ""
},
"require": {
@@ -3478,7 +3478,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
"source": "https://github.com/myclabs/DeepCopy/tree/1.11.1"
},
"funding": [
{
@@ -3486,20 +3486,20 @@
"type": "tidelift"
}
],
"time": "2022-03-03T13:19:32+00:00"
"time": "2023-03-08T13:26:56+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.15.3",
"version": "v4.15.4",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039"
"reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/570e980a201d8ed0236b0a62ddf2c9cbb2034039",
"reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
"reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
"shasum": ""
},
"require": {
@@ -3540,9 +3540,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.3"
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4"
},
"time": "2023-01-16T22:05:37+00:00"
"time": "2023-03-05T19:49:14+00:00"
},
{
"name": "phar-io/manifest",
@@ -3890,23 +3890,23 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.24",
"version": "9.2.26",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "2cf940ebc6355a9d430462811b5aaa308b174bed"
"reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2cf940ebc6355a9d430462811b5aaa308b174bed",
"reference": "2cf940ebc6355a9d430462811b5aaa308b174bed",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1",
"reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.14",
"nikic/php-parser": "^4.15",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
@@ -3921,8 +3921,8 @@
"phpunit/phpunit": "^9.3"
},
"suggest": {
"ext-pcov": "*",
"ext-xdebug": "*"
"ext-pcov": "PHP extension that provides line coverage",
"ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
},
"type": "library",
"extra": {
@@ -3955,7 +3955,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.24"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26"
},
"funding": [
{
@@ -3963,7 +3963,7 @@
"type": "github"
}
],
"time": "2023-01-26T08:26:55+00:00"
"time": "2023-03-06T12:58:08+00:00"
},
{
"name": "phpunit/php-file-iterator",
+20
View File
@@ -150,4 +150,24 @@ class Transfer extends Event
'payload' => $this->payload
]);
}
/**
* {@inheritdoc}
*/
public function setUser(Document $user): self
{
parent::setUser($user);
return $this;
}
/**
* {@inheritdoc}
*/
public function setProject(Document $project): self
{
parent::setProject($project);
return $this;
}
}
+3
View File
@@ -88,6 +88,7 @@ use Appwrite\Utopia\Response\Model\Source;
use Appwrite\Utopia\Response\Model\Destination;
use Appwrite\Utopia\Response\Model\DestinationValidation;
use Appwrite\Utopia\Response\Model\SourceValidation;
use Appwrite\Utopia\Response\Model\TransferValidationError;
/**
* @method int getStatusCode()
@@ -221,6 +222,7 @@ class Response extends SwooleResponse
// Transfers
public const MODEL_TRANSFER = 'transfer';
public const MODEL_TRANSFER_LIST = 'transferList';
public const MODEL_TRANSFER_VALIDATION_ERROR = 'transferValidationError';
public const MODEL_SOURCE = 'source';
public const MODEL_SOURCE_LIST = 'sourceList';
public const MODEL_SOURCE_VALIDATION = 'sourceValidation';
@@ -364,6 +366,7 @@ class Response extends SwooleResponse
->setModel(new DestinationValidation())
->setModel(new Source())
->setModel(new SourceValidation())
->setModel(new TransferValidationError())
// Verification
// Recovery
// Tests (keep last)
@@ -10,24 +10,27 @@ class DestinationValidation extends Model
public function __construct()
{
$this
->addRule('status', [
'type' => self::TYPE_STRING,
'description' => 'Success status. "success" or "failed".',
'default' => "failed",
'example' => "success",
->addRule('success', [
'type' => self::TYPE_BOOLEAN,
'description' => 'If the validation was successful or not.',
'default' => false,
'example' => true,
])
->addRule('message', [
'type' => self::TYPE_STRING,
'description' => 'Extra details about the status.',
'description' => 'Validation message.',
'default' => '',
'example' => 'Source is valid.',
'example' => 'Validation completed successfully',
])
->addRule('errors', [
'type' => self::TYPE_STRING,
'description' => 'Missing roles.',
'default' => '',
'example' => '[]',
'array' => true
'type' => Response::MODEL_TRANSFER_VALIDATION_ERROR,
'description' => 'A key-value array of all the validation errors.',
'default' => [],
'example' => [
'Users' => ['Access to table "public.users" is denied.'],
'Databases' => ['Failed to access database. Please check your connection.'],
],
'requried' => false
])
;
}
@@ -51,4 +54,4 @@ class DestinationValidation extends Model
{
return Response::MODEL_DESTINATION_VALIDATION;
}
}
}
@@ -40,6 +40,15 @@ class Source extends Model
'default' => '',
'example' => 'Appwrite',
])
->addRule('lastCheck', [
'type' => self::TYPE_JSON,
'description' => 'A JSON Object with the result of the last source check.',
'default' => '',
'example' => [
'success' => false,
'message' => 'Transfer completed successfully'
],
])
;
}
@@ -10,24 +10,27 @@ class SourceValidation extends Model
public function __construct()
{
$this
->addRule('status', [
'type' => self::TYPE_STRING,
'description' => 'Success status. "success" or "failed".',
'default' => "failed",
'example' => "success",
->addRule('success', [
'type' => self::TYPE_BOOLEAN,
'description' => 'If the validation was successful or not.',
'default' => false,
'example' => true,
])
->addRule('message', [
'type' => self::TYPE_STRING,
'description' => 'Extra details about the status.',
'description' => 'Validation message.',
'default' => '',
'example' => 'Source is valid.',
'example' => 'Validation completed successfully',
])
->addRule('errors', [
'type' => self::TYPE_STRING,
'description' => 'Missing roles.',
'default' => '',
'example' => '[]',
'array' => true
'type' => Response::MODEL_TRANSFER_VALIDATION_ERROR,
'description' => 'A key-value array of all the validation errors.',
'default' => [],
'example' => [
'Users' => ['Access to table "public.users" is denied.'],
'Documents' => ['Failed to access database. Please check your connection.'],
],
'requried' => false
])
;
}
@@ -0,0 +1,28 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
class TransferValidationError extends Any
{
/**
* Get Name
*
* @return string
*/
public function getName(): string
{
return 'Transfer Validiation Error';
}
/**
* Get Type
*
* @return string
*/
public function getType(): string
{
return Response::MODEL_TRANSFER_VALIDATION_ERROR;
}
}