Skip to content

Commit

Permalink
Added validation of configuration file
Browse files Browse the repository at this point in the history
  • Loading branch information
ruff committed Sep 30, 2024
1 parent 4d4c540 commit 394d1e5
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 8 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,5 @@ _backup*
/composer.lock

/examples/Example1.php
!/src/bin
/examples/config.json
!/src/bin
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"php": "^7.3|^7.4|^8",
"horstoeko/zugferd": "^1",
"horstoeko/zugferdublbridge": "^1",
"swaggest/json-schema": "^0.12.42",
"symfony/console": "^5|^6|^7",
"webklex/php-imap": "^4|^5"
},
Expand Down
57 changes: 50 additions & 7 deletions src/config/ZugferdMailConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@

namespace horstoeko\zugferdmail\config;

use stdClass;
use RuntimeException;
use InvalidArgumentException;
use ReflectionException;
use RuntimeException;
use stdClass;
use Swaggest\JsonSchema\Schema;
use Throwable;
use Webklex\PHPIMAP\ClientManager;

/**
Expand Down Expand Up @@ -221,11 +224,13 @@ public function makeClientManager(): ClientManager
}

/**
* Loads a configuration from a file.
* The file must exist.
* Loads a configuration from a file. The file must exist.
*
* @param string $filename
* @param string $filename
* @return ZugferdMailConfig
* @throws InvalidArgumentException
* @throws RuntimeException
* @throws ReflectionException
*/
public static function loadFromFile(string $filename): ZugferdMailConfig
{
Expand All @@ -236,11 +241,19 @@ public static function loadFromFile(string $filename): ZugferdMailConfig
$jsonString = file_get_contents($filename);

if ($jsonString === false) {
throw new RuntimeException(sprintf("Cannot read the file %s.", $filename));
throw new RuntimeException(sprintf("Cannot read the configuration file %s.", $filename));
}

$jsonObject = json_decode($jsonString);

if (is_null($jsonObject)) {
throw new RuntimeException(sprintf("The file %s does not seem to be a valid json.", $filename));
}

if (!static::validateConfig($jsonObject)) {
throw new RuntimeException(sprintf("The file %s does not seem to be a valid json.", $filename));
}

$config = new ZugferdMailConfig;
$config->setDateFormat($jsonObject->dateFormat);
$config->setUblSupportEnabled($jsonObject->ublSupportEnabled);
Expand Down Expand Up @@ -274,8 +287,9 @@ public static function loadFromFile(string $filename): ZugferdMailConfig
/**
* Save the configuration to a file
*
* @param string $filename
* @param string $filename
* @return ZugferdMailConfig
* @throws RuntimeException
*/
public function saveToFile(string $filename): ZugferdMailConfig
{
Expand Down Expand Up @@ -327,10 +341,39 @@ public function saveToFile(string $filename): ZugferdMailConfig
$jsonObject->accounts[] = $jsonAccountObject;
}

if (!static::validateConfig($jsonObject)) {
throw new RuntimeException(sprintf("The content of file %s is not valid.", $filename));
}

if (file_put_contents($filename, json_encode($jsonObject, JSON_PRETTY_PRINT)) === false) {
throw new RuntimeException(sprintf("Cannot save to file %s.", $filename));
}

return $this;
}

/**
* Validates a config file
*
* @param object $jsonObject
* @return bool
*/
protected static function validateConfig($jsonObject): bool
{
$result = true;

$schemaJson = file_get_contents(dirname(__FILE__) . "/schema.json");

try {
Schema::import(
json_decode($schemaJson),
)->in(
$jsonObject,
);
} catch (Throwable $e) {
$result = false;
}

return $result;
}
}
128 changes: 128 additions & 0 deletions src/config/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"dateFormat",
"ublSupportEnabled",
"accounts"
],
"properties": {
"dateFormat": {
"type": "string"
},
"ublSupportEnabled": {
"type": "boolean"
},
"accounts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"identifier": {
"type": "string"
},
"host": {
"type": "string"
},
"port": {
"type": "integer",
"minimum": 0,
"maximu,": 65535
},
"protocol": {
"type": "string",
"oneOf": [
{
"const": "imap"
},
{
"const": "legacy-imap"
},
{
"const": "pop3"
},
{
"const": "nntp"
}
]
},
"encryption": {
"type": [
"string",
"boolean"
],
"oneOf": [
{
"const": false
},
{
"const": "ssl"
},
{
"const": "tls"
},
{
"const": "starttls"
},
{
"const": "notls"
}
]
},
"validateCert": {
"type": "boolean"
},
"username": {
"type": "string"
},
"password": {
"type": "string"
},
"authentication": {
"type": [
"string",
"null"
],
"oneOf": [
{
"const": null
},
{
"const": "oauth"
}
]
},
"timeout": {
"type": "integer"
},
"foldersToWatch": {
"type": "array",
"items": {
"type": "string"
}
},
"mimeTypesToWatch": {
"type": "array",
"items": {
"type": "string"
}
},
"handlers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"classname": {
"type": "string"
},
"properties": {
"type": "object"
}
}
}
}
}
}
}
}
}

0 comments on commit 394d1e5

Please sign in to comment.