mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-04 03:09:33 -06:00
[tests-only] check for invalid schema validators (#8533)
* test(api): check schema validators * test(api): check schema validators * test(api): check schema validators * test(api): fix schema * test(api): fix php code style * test(api): fix schema
This commit is contained in:
@@ -85,7 +85,7 @@ Feature: Notification
|
||||
},
|
||||
"id": {
|
||||
"type": "string",
|
||||
"enim": ["%user_id%"]
|
||||
"pattern": "^%user_id_pattern%$"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
|
||||
@@ -97,9 +97,7 @@ Feature: Notification
|
||||
},
|
||||
"id": {
|
||||
"type": "string",
|
||||
"enim": [
|
||||
"%user_id%"
|
||||
]
|
||||
"pattern": "^%user_id_pattern%$"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
@@ -232,9 +230,7 @@ Feature: Notification
|
||||
},
|
||||
"id": {
|
||||
"type": "string",
|
||||
"enim": [
|
||||
"%user_id%"
|
||||
]
|
||||
"pattern": "^%user_id_pattern%$"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
@@ -368,9 +364,7 @@ Feature: Notification
|
||||
},
|
||||
"id": {
|
||||
"type": "string",
|
||||
"enim": [
|
||||
"%user_id%"
|
||||
]
|
||||
"pattern": "^%user_id_pattern%$"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
|
||||
@@ -553,8 +553,6 @@ Feature: Create a share link for a resource
|
||||
},
|
||||
"link": {
|
||||
"type": "object",
|
||||
"minItems": 5,
|
||||
"maxItems": 5,
|
||||
"required": [
|
||||
"@libre.graph.displayName",
|
||||
"@libre.graph.quickLink",
|
||||
|
||||
@@ -102,8 +102,6 @@ Feature: Update permission of a share
|
||||
"""
|
||||
{
|
||||
"type": "object",
|
||||
"minItems": 3,
|
||||
"maxItems": 3,
|
||||
"required": [
|
||||
"grantedToV2",
|
||||
"id",
|
||||
|
||||
@@ -56,6 +56,12 @@ class FeatureContext extends BehatVariablesContext {
|
||||
use Sharing;
|
||||
use WebDav;
|
||||
|
||||
/**
|
||||
* json schema validator keywords
|
||||
* See: https://json-schema.org/draft-06/draft-wright-json-schema-validation-01#rfc.section.6
|
||||
*/
|
||||
private array $jsonSchemaValidators = [];
|
||||
|
||||
/**
|
||||
* Unix timestamp seconds
|
||||
*/
|
||||
@@ -572,6 +578,8 @@ class FeatureContext extends BehatVariablesContext {
|
||||
$this->publicLinkSharePassword = $publicLinkSharePasswordFromEnvironment;
|
||||
}
|
||||
$this->originalAdminPassword = $this->adminPassword;
|
||||
|
||||
$this->jsonSchemaValidators = \array_keys(JsonSchema::properties()->getDataKeyMap());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1206,6 +1214,56 @@ class FeatureContext extends BehatVariablesContext {
|
||||
return $a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JsonSchema $schemaObj
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function checkInvalidValidator(JsonSchema $schemaObj): void {
|
||||
$validators = \array_keys((array)$schemaObj->jsonSerialize());
|
||||
foreach ($validators as $validator) {
|
||||
Assert::assertContains(\ltrim($validator, "$"), $this->jsonSchemaValidators, "Invalid schema validator: '$validator'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates against the requirements that object schema should adhere to
|
||||
*
|
||||
* @param JsonSchema $schemaObj
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validateSchemaObject(JsonSchema $schemaObj): void {
|
||||
$this->checkInvalidValidator($schemaObj);
|
||||
|
||||
if ($schemaObj->type && $schemaObj->type !== "object") {
|
||||
return;
|
||||
}
|
||||
|
||||
$notAllowedValidators = ["items", "maxItems", "minItems", "uniqueItems"];
|
||||
|
||||
// check invalid validators
|
||||
foreach ($notAllowedValidators as $validator) {
|
||||
Assert::assertTrue(null === $schemaObj->$validator, "'$validator' should not be used with object type");
|
||||
}
|
||||
|
||||
$propNames = $schemaObj->getPropertyNames();
|
||||
$props = $schemaObj->getProperties();
|
||||
foreach ($propNames as $propName) {
|
||||
switch ($props->type) {
|
||||
case "array":
|
||||
$this->validateSchemaArray($props->$propName);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// traverse for nested properties
|
||||
$this->validateSchemaObject($props->$propName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates against the requirements that array schema should adhere to
|
||||
*
|
||||
@@ -1214,7 +1272,13 @@ class FeatureContext extends BehatVariablesContext {
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function validateSchemaArrayEntries(JsonSchema $schemaObj): void {
|
||||
private function validateSchemaArray(JsonSchema $schemaObj): void {
|
||||
$this->checkInvalidValidator($schemaObj);
|
||||
|
||||
if ($schemaObj->type && $schemaObj->type !== "array") {
|
||||
return;
|
||||
}
|
||||
|
||||
$hasTwoElementValidator = ($schemaObj->enum && $schemaObj->const) || ($schemaObj->enum && $schemaObj->items) || ($schemaObj->const && $schemaObj->items);
|
||||
Assert::assertFalse($hasTwoElementValidator, "'items', 'enum' and 'const' should not be used together");
|
||||
if ($schemaObj->enum || $schemaObj->const) {
|
||||
@@ -1224,20 +1288,26 @@ class FeatureContext extends BehatVariablesContext {
|
||||
|
||||
$requiredValidators = ["maxItems", "minItems"];
|
||||
$optionalValidators = ["items", "uniqueItems"];
|
||||
$notAllowedValidators = ["properties", "minProperties", "maxProperties", "required"];
|
||||
$errMsg = "'%s' is required for array assertion";
|
||||
|
||||
// validate required keywords
|
||||
// check invalid validators
|
||||
foreach ($notAllowedValidators as $validator) {
|
||||
Assert::assertTrue($schemaObj->$validator === null, "'$validator' should not be used with array type");
|
||||
}
|
||||
|
||||
// check required validators
|
||||
foreach ($requiredValidators as $validator) {
|
||||
Assert::assertNotNull($schemaObj->$validator, \sprintf($errMsg, $validator));
|
||||
}
|
||||
|
||||
Assert::assertEquals($schemaObj->minItems, $schemaObj->maxItems, "'minItems' and 'maxItems' should be equal for strict assertion");
|
||||
|
||||
// validate optional keywords
|
||||
// check optional validators
|
||||
foreach ($optionalValidators as $validator) {
|
||||
$value = $schemaObj->$validator;
|
||||
switch ($validator) {
|
||||
case 'items':
|
||||
case "items":
|
||||
if ($schemaObj->maxItems === 0) {
|
||||
break;
|
||||
}
|
||||
@@ -1267,6 +1337,15 @@ class FeatureContext extends BehatVariablesContext {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$items = $schemaObj->items;
|
||||
if ($items !== null && $items->oneOf !== null) {
|
||||
foreach ($items->oneOf as $oneOfItem) {
|
||||
$this->validateSchemaObject($oneOfItem);
|
||||
}
|
||||
} elseif ($items !== null) {
|
||||
$this->validateSchemaObject($items);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1278,29 +1357,17 @@ class FeatureContext extends BehatVariablesContext {
|
||||
* @throws Exception
|
||||
*/
|
||||
public function validateSchemaRequirements(JsonSchema $schema): void {
|
||||
$propNames = $schema->getPropertyNames();
|
||||
$props = $schema->getProperties();
|
||||
foreach ($propNames as $propName) {
|
||||
switch ($props->$propName->type) {
|
||||
case 'array':
|
||||
$this->validateSchemaArrayEntries($props->$propName);
|
||||
$items = $props->$propName->items;
|
||||
if ($items && $items->oneOf) {
|
||||
foreach ($items->oneOf as $oneOfItem) {
|
||||
$this->validateSchemaRequirements($oneOfItem);
|
||||
}
|
||||
break;
|
||||
} elseif ($items) {
|
||||
$this->validateSchemaRequirements($items);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// traverse for nested properties
|
||||
if ($props->$propName->getProperties()) {
|
||||
$this->validateSchemaRequirements($props->$propName);
|
||||
}
|
||||
Assert::assertNotNull($schema->type, "'type' is required for root level schema");
|
||||
|
||||
switch ($schema->type) {
|
||||
case "object":
|
||||
$this->validateSchemaObject($schema);
|
||||
break;
|
||||
case "array":
|
||||
$this->validateSchemaArray($schema);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user