From 83e98dc7067fa8c123a94b16b630f4bad85e3ee9 Mon Sep 17 00:00:00 2001 From: Ente Date: Wed, 6 Nov 2024 22:36:58 +0100 Subject: [PATCH] v1.1.2 - Quality --- README.md | 21 +++++++ composer.json | 2 +- src/API.dnsserver.ente.php | 84 +++++++++++++++++++++------- src/endpoints/admin/Groups.admin.php | 2 +- src/endpoints/allowed/Allowed.php | 2 +- src/endpoints/apps/Config.apps.php | 2 +- src/endpoints/dhcp/Scopes.dhcp.php | 10 ++++ 7 files changed, 100 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 94f1dd6..7d1d42b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # technitium-dnsserver-php-api This API client is intended to be used with Technitiums DNS Server +For the full Technitium API Documentation please visit [Technitium API Documentation](https://github.com/TechnitiumSoftware/DnsServer/blob/master/APIDOCS.md) ## Installation @@ -55,6 +56,20 @@ if($api->apps->downloadAndInstall($sampleApp["name"], $sampleApp["url"])) { ``` +### Send to custom endpoint + +```php +$bypass to true to use this feature +echo var_dump($api->sendCall(data: array("field" => "value"), endpoint: "admin/users/list", skip: false, bypass: true)) + +``` + ## DDNS You can use the `DDNS.Helper.API.dnsserver.ente.php` class to configure records to point to the current IP address. @@ -108,6 +123,12 @@ DDNS(new API(__DIR__ . "/configurations", ".env-custom"), file_get_contents("/my ## Changes +### v1.1.2: Quality + +- Added more documentation to the classes +- Small code changes + + ### v1.1.1: Fixes - Small changes to the `README.md` diff --git a/composer.json b/composer.json index d2e13d6..5a3b4b5 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "ente/technitium-dnsserver-php-api", "type": "library", "license": "GPL-3.0-only", - "version": "1.1.1", + "version": "1.1.2", "authors": [ { "name": "Ente", diff --git a/src/API.dnsserver.ente.php b/src/API.dnsserver.ente.php index 4ce3a4c..fb185b8 100644 --- a/src/API.dnsserver.ente.php +++ b/src/API.dnsserver.ente.php @@ -19,7 +19,6 @@ class API { private $protocol; - private $admin; private $allowed; private $apps; @@ -32,16 +31,13 @@ class API { private $users; private $zones; private $ddns; - private $log; - private $conf; - private $path; - private $fullPath; - private $env = []; + const PREFIX_GET = "&token="; + const PREFIX_POST = "?token="; public function __construct($confPath = null, $name = null){ $this->loader(); @@ -57,6 +53,12 @@ private function setProtocol(){ } } + /** + * `loadConf()` - Load the .env file and set the environment variables. + * @param mixed $path The full path to the directory containing the .env file. (optional) + * @param mixed $name The name of the .env file. (optional) + * @return void + */ private function loadConf($path = null, $name = null){ $this->conf = $name ?? ".env"; $this->path = $path ?? $_SERVER["DOCUMENT_ROOT"]; @@ -102,6 +104,15 @@ public function loader(){ require_once __DIR__ . "/helper/Log.Helper.API.dnsserver.ente.php"; } + /** + * `sendCall()` - Send a request to the Technitium API. + * @param array $data The data to send to the API + * @param string $endpoint The endpoint to send the data to, e.g. "admin/users/list" + * @param mixed $method The HTTP method to use. Default is "POST". + * @param mixed $skip Set to `true` to skip the authentication URI append. + * @param mixed $bypass Set to `true` to bypass the endpoint check allowing to access not (yet) implemented methods. + * @return array Returns the response from the API or an error (["status" => "error"]) as an array. + */ public function sendCall($data, $endpoint, $method = "POST", $skip = false, $bypass = false){ $c = curl_init(); $endpoint = $this->prepareEndpoint($endpoint, $bypass); @@ -126,50 +137,72 @@ public function sendCall($data, $endpoint, $method = "POST", $skip = false, $byp curl_setopt($c, CURLOPT_RETURNTRANSFER, true); break; } + $result = ["status" => "error", "error" => "Unknown error"]; try { $response = curl_exec($c); if(!$response){ Log::error_rep("Failed to send request: " . curl_error($c)); - return ["status" => "error", "error" => curl_error($c)]; + $result = ["status" => "error", "error" => curl_error($c)]; } } catch (\Throwable $e){ Log::error_rep("Failed to send request: " . $e->getMessage()); - return ["status" => "error", "error" => $e->getMessage()]; + $result = ["status" => "error", "error" => $e->getMessage()]; } curl_close($c); if($this->checkResponse($response)){ Log::error_rep("Successfully accessed endpoint: " . $endpoint); - return json_decode($response, true); + $result = json_decode($response, true); } - return [ - "error" => "An error occurred", - ]; + return $result; } + /** + * `appendAuth()` - Append the authentication token to the URI. + * @param mixed $m The HTTP method to use. Default is "POST". + * @param mixed $skip Set to `true` to skip the authentication URI append, allowing the use of `API::getPermanentToken()`. + * @return string Returns the authentication token URI string or an empty string. + */ private function appendAuth($m = "POST", $skip = false){ $this->loadConf($this->path, $this->conf); + $authAppend = null; if($skip){ return ""; } if(!empty($this->env["TOKEN"])){ switch($m){ case "POST": - return "?token=" . @$this->env["TOKEN"]; + $authAppend = $this::PREFIX_POST . @$this->env["TOKEN"]; + break; case "GET": - return "&token=" . @$this->env["TOKEN"]; + $authAppend = $this::PREFIX_GET . @$this->env["TOKEN"]; + break; + default: + $authAppend = $this::PREFIX_POST . @$this->env["TOKEN"]; + break; } } else { $this->getPermanentToken(); $this->loadConf($this->path, $this->conf); switch($m){ case "POST": - return "?token=" . @$this->env["TOKEN"]; + $authAppend = $this::PREFIX_POST . @$this->env["TOKEN"]; + break; case "GET": - return "&token=" . @$this->env["TOKEN"]; + $authAppend = $this::PREFIX_GET . @$this->env["TOKEN"]; + break; + default: + $authAppend = $this::PREFIX_POST . @$this->env["TOKEN"]; + break; } } + return $authAppend; } + /** + * `getPermanentToken()` - Get a permanent token from the Technitium API. + * This function is called when the token is not found in the .env file. + * @return bool Returns `true` if the token was successfully written to the .env file. + */ private function getPermanentToken(){ Log::error_rep("Getting permanent token... | .env: " . $this->fullPath); $response = $this->sendCall([ @@ -190,11 +223,18 @@ private function getPermanentToken(){ ->write(true); } catch(\Throwable $e){ - Log::error_rep("Unable to write to .env file: " . $this->fullPath); } + Log::error_rep("Unable to write to .env file: " . $this->fullPath); + } return true; } - private function checkResponse($response){ + /** + * `checkResponse()` - Check if the Technitium API response is valid. + * If the response status contains either "error" or "invalid-token" it is considered invalid. + * @param mixed $response The response returned by `API::sendCall()` function. + * @return bool Returns `true` if the response is valid, otherwise `false`. + */ + private function checkResponse(string $response){ if(is_null($response)){ return false; } else { @@ -203,6 +243,12 @@ private function checkResponse($response){ } } + /** + * `prepareEndpoint()` - Generates the API URI for the endpoint in question. + * @param mixed $endpoint The endpoint to generate the URI for. + * @param mixed $bypass Set to `true` to bypass the endpoint check allowing to access not (yet) implemented methods. + * @return bool|string Returns the URI as string or `false` if the endpoint is not implemented. + */ private function prepareEndpoint($endpoint, $bypass = false){ if($bypass){ return $this->protocol . "://" . $this->env["API_URL"] . "/api/" . $endpoint; @@ -280,7 +326,7 @@ public function ddns(): DDNS { } public function log(): Log { - if(!$this->log) $this->log = new Log($this); + if(!$this->log) $this->log = new Log(null); return $this->log; } } diff --git a/src/endpoints/admin/Groups.admin.php b/src/endpoints/admin/Groups.admin.php index e0ac0ca..4f07b98 100644 --- a/src/endpoints/admin/Groups.admin.php +++ b/src/endpoints/admin/Groups.admin.php @@ -3,7 +3,7 @@ /** * Groups class - * + * * This class is used to interact with the groups endpoint of the Technitium DNS Server API */ class groups { diff --git a/src/endpoints/allowed/Allowed.php b/src/endpoints/allowed/Allowed.php index a88e780..54c9e91 100644 --- a/src/endpoints/allowed/Allowed.php +++ b/src/endpoints/allowed/Allowed.php @@ -11,7 +11,7 @@ public function __construct($api){ * `list()` - Returns a list of all allowed domains. * @param string $domain The domain to list. * @param string $direction The direction to list the domains. Valid values are [`up`, `down`]. - * @return array|bool Returns the result array or `false` if the group was not found. + * @return array|bool Returns the result array or `false` if the group was not found. */ public function list(string $domain = "", string $direction = "up"){ $response = $this->API->sendCall(["domain" => $domain, "direction" => $direction], "allowed/list"); diff --git a/src/endpoints/apps/Config.apps.php b/src/endpoints/apps/Config.apps.php index 66b00a7..1b70cff 100644 --- a/src/endpoints/apps/Config.apps.php +++ b/src/endpoints/apps/Config.apps.php @@ -11,7 +11,7 @@ public function __construct($api){ /** * `get()` - Returns the configuration of an app. * @param string $name The name of the app. - * @return array|bool Returns the result array or `false` if the group was not found. + * @return array|bool Returns the result array or `false` if the group was not found. */ public function get(string $name){ $response = $this->API->sendCall(["name" => $name], "apps/config/get"); diff --git a/src/endpoints/dhcp/Scopes.dhcp.php b/src/endpoints/dhcp/Scopes.dhcp.php index 98e0696..644ec86 100644 --- a/src/endpoints/dhcp/Scopes.dhcp.php +++ b/src/endpoints/dhcp/Scopes.dhcp.php @@ -81,11 +81,21 @@ public function enable(string $name){ return $response["status"] == "ok"; } + /** + * `disable()` - Disables the DHCP scope. + * @param string $name The name of the scope. + * @return bool Returns `true` if the request was successful, `false` otherwise. + */ public function disable(string $name){ $response = $this->API->sendCall(["name" => $name], "dhcp/scopes/disable"); return $response["status"] == "ok"; } + /** + * `delete()` - Deletes the DHCP scope. + * @param string $name The name of the scope. + * @return bool Returns `true` if the request was successful, `false` otherwise. + */ public function delete(string $name){ $response = $this->API->sendCall(["name" => $name], "dhcp/scopes/delete"); return $response["status"] == "ok";