Initial commit

This commit is contained in:
Steve Oswald 2022-11-24 21:25:05 +01:00 committed by GitHub
parent c34b586ab2
commit 29cd1889ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1480 additions and 0 deletions

8
composer.json Normal file
View file

@ -0,0 +1,8 @@
{
"require": {
"leafs/leaf": "^3.2",
"leafs/cookie": "^1.1",
"leafs/db": "^2.0",
"leafs/fetch": "^0.1.0"
}
}

583
composer.lock generated Normal file
View file

@ -0,0 +1,583 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c6806b7a50e2b140be99811858e03b55",
"packages": [
{
"name": "leafs/anchor",
"version": "v1.4.0",
"source": {
"type": "git",
"url": "https://github.com/leafsphp/anchor.git",
"reference": "83b2ae93f5796c255cb34b4b2633730ac0e24be0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/leafsphp/anchor/zipball/83b2ae93f5796c255cb34b4b2633730ac0e24be0",
"reference": "83b2ae93f5796c255cb34b4b2633730ac0e24be0",
"shasum": ""
},
"require-dev": {
"pestphp/pest": "^1.21"
},
"type": "library",
"autoload": {
"psr-4": {
"Leaf\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Darko",
"email": "mickdd22@gmail.com",
"homepage": "https://mychi.netlify.app",
"role": "Developer"
}
],
"description": "Leaf PHP util module",
"homepage": "https://leafphp.netlify.app/#/",
"keywords": [
"framework",
"leaf",
"php",
"util"
],
"support": {
"issues": "https://github.com/leafsphp/anchor/issues",
"source": "https://github.com/leafsphp/anchor/tree/v1.4.0"
},
"funding": [
{
"url": "https://github.com/leafsphp",
"type": "github"
},
{
"url": "https://opencollective.com/leaf",
"type": "open_collective"
}
],
"time": "2022-10-03T21:05:28+00:00"
},
{
"name": "leafs/cookie",
"version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/leafsphp/cookie.git",
"reference": "ff286903558975fcf737aa989c9defa57873a18e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/leafsphp/cookie/zipball/ff286903558975fcf737aa989c9defa57873a18e",
"reference": "ff286903558975fcf737aa989c9defa57873a18e",
"shasum": ""
},
"type": "library",
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Leaf\\Http\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Darko",
"email": "mickdd22@gmail.com",
"homepage": "https://mychi.netlify.app",
"role": "Developer"
}
],
"description": "Leaf PHP cookie module",
"homepage": "https://leafphp.netlify.app/#/",
"keywords": [
"cookies",
"framework",
"http",
"leaf",
"php"
],
"support": {
"issues": "https://github.com/leafsphp/cookie/issues",
"source": "https://github.com/leafsphp/cookie/tree/v1.1.1"
},
"funding": [
{
"url": "https://github.com/leafsphp",
"type": "github"
},
{
"url": "https://opencollective.com/leaf",
"type": "open_collective"
}
],
"time": "2022-10-16T21:00:05+00:00"
},
{
"name": "leafs/db",
"version": "v2.0.2",
"source": {
"type": "git",
"url": "https://github.com/leafsphp/db.git",
"reference": "7fb2aa179c7021be47e60201ad06d70608a04761"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/leafsphp/db/zipball/7fb2aa179c7021be47e60201ad06d70608a04761",
"reference": "7fb2aa179c7021be47e60201ad06d70608a04761",
"shasum": ""
},
"require": {
"ext-mysqli": "*"
},
"require-dev": {
"pestphp/pest": "^1.21"
},
"type": "library",
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Leaf\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Darko",
"email": "mickdd22@gmail.com",
"homepage": "https://mychi.netlify.app",
"role": "Developer"
}
],
"description": "Leaf PHP db module.",
"homepage": "https://leafphp.netlify.app/#/",
"keywords": [
"database",
"framework",
"leaf",
"orm",
"php"
],
"support": {
"issues": "https://github.com/leafsphp/db/issues",
"source": "https://github.com/leafsphp/db/tree/v2.0.2"
},
"funding": [
{
"url": "https://github.com/leafsphp",
"type": "github"
},
{
"url": "https://opencollective.com/leaf",
"type": "open_collective"
}
],
"time": "2022-05-29T23:01:32+00:00"
},
{
"name": "leafs/exception",
"version": "v3.1.1",
"source": {
"type": "git",
"url": "https://github.com/leafsphp/exceptions.git",
"reference": "3429469a55aad78e8b43b584dca8f7d8ea287635"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/leafsphp/exceptions/zipball/3429469a55aad78e8b43b584dca8f7d8ea287635",
"reference": "3429469a55aad78e8b43b584dca8f7d8ea287635",
"shasum": ""
},
"require": {
"php": "^5.5.9 || ^7.0 || ^8.0",
"psr/log": "^1.0.1 || ^2.0 || ^3.0"
},
"require-dev": {
"mockery/mockery": "^0.9 || ^1.0",
"phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3",
"symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0"
},
"suggest": {
"symfony/var-dumper": "Pretty print complex values better with var-dumper available",
"whoops/soap": "Formats errors as SOAP responses"
},
"type": "library",
"autoload": {
"psr-4": {
"Leaf\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Filipe Dobreira",
"homepage": "https://github.com/filp",
"role": "Developer"
},
{
"name": "Michael Darko",
"email": "mickdd22@gmail.com",
"homepage": "https://mychi.netlify.app",
"role": "Developer"
}
],
"description": "Error handler for leaf (fork of whoops)",
"homepage": "https://github.com/leafsphp/exception",
"keywords": [
"error",
"exception",
"handling",
"library",
"throwable",
"whoops"
],
"support": {
"source": "https://github.com/leafsphp/exceptions/tree/v3.1.1"
},
"funding": [
{
"url": "https://github.com/denis-sokolov",
"type": "github"
}
],
"time": "2022-09-18T00:29:18+00:00"
},
{
"name": "leafs/fetch",
"version": "v0.1",
"source": {
"type": "git",
"url": "https://github.com/leafsphp/fetch.git",
"reference": "f214dda6131c830ed19310dfdfd57a244f5bbd08"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/leafsphp/fetch/zipball/f214dda6131c830ed19310dfdfd57a244f5bbd08",
"reference": "f214dda6131c830ed19310dfdfd57a244f5bbd08",
"shasum": ""
},
"require": {
"ext-curl": "*"
},
"type": "library",
"autoload": {
"psr-4": {
"Leaf\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Darko",
"email": "mickdd22@gmail.com",
"homepage": "https://mychi.netlify.app",
"role": "Developer"
}
],
"description": "Plain simple PHP http client",
"homepage": "https://github.com/leafsphp/redis",
"keywords": [
"client",
"fetch",
"http",
"leaf",
"network",
"php",
"xhr"
],
"support": {
"issues": "https://github.com/leafsphp/fetch/issues",
"source": "https://github.com/leafsphp/fetch/tree/v0.1"
},
"funding": [
{
"url": "https://opencollective.com/leaf",
"type": "open_collective"
}
],
"time": "2021-06-04T17:47:10+00:00"
},
{
"name": "leafs/http",
"version": "v2.2.0",
"source": {
"type": "git",
"url": "https://github.com/leafsphp/http.git",
"reference": "593dc1befd6eb00ead6a84298a6f9f600458faa2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/leafsphp/http/zipball/593dc1befd6eb00ead6a84298a6f9f600458faa2",
"reference": "593dc1befd6eb00ead6a84298a6f9f600458faa2",
"shasum": ""
},
"require": {
"leafs/anchor": "*"
},
"type": "library",
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Leaf\\Http\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Darko",
"email": "mickdd22@gmail.com",
"homepage": "https://mychi.netlify.app",
"role": "Developer"
}
],
"description": "Leaf PHP HTTP module.",
"homepage": "https://leafphp.netlify.app/#/",
"keywords": [
"framework",
"headers",
"http",
"leaf",
"php",
"request",
"response"
],
"support": {
"issues": "https://github.com/leafsphp/http/issues",
"source": "https://github.com/leafsphp/http/tree/v2.2.0"
},
"funding": [
{
"url": "https://github.com/leafsphp",
"type": "github"
},
{
"url": "https://opencollective.com/leaf",
"type": "open_collective"
}
],
"time": "2022-10-23T13:43:58+00:00"
},
{
"name": "leafs/leaf",
"version": "v3.2.1",
"source": {
"type": "git",
"url": "https://github.com/leafsphp/leaf.git",
"reference": "573dca9a4caed6412544ceaf913d72afb58fcaee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/leafsphp/leaf/zipball/573dca9a4caed6412544ceaf913d72afb58fcaee",
"reference": "573dca9a4caed6412544ceaf913d72afb58fcaee",
"shasum": ""
},
"require": {
"leafs/anchor": "*",
"leafs/exception": "*",
"leafs/http": "*",
"leafs/router": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"pestphp/pest": "^1.21"
},
"type": "library",
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Leaf\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Darko",
"email": "mickdd22@gmail.com",
"homepage": "https://mychi.netlify.app",
"role": "Developer"
}
],
"description": "Simple, performant and powerful PHP micro-framework for rapid web app & API development",
"homepage": "https://leafphp.dev",
"keywords": [
"framework",
"leaf",
"microframework",
"php",
"rest",
"router"
],
"support": {
"issues": "https://github.com/leafsphp/leaf/issues",
"source": "https://github.com/leafsphp/leaf/tree/v3.2.1"
},
"funding": [
{
"url": "https://github.com/leafsphp",
"type": "github"
},
{
"url": "https://opencollective.com/leaf",
"type": "open_collective"
}
],
"time": "2022-10-23T16:50:47+00:00"
},
{
"name": "leafs/router",
"version": "v0.1.10",
"source": {
"type": "git",
"url": "https://github.com/leafsphp/router.git",
"reference": "a18b707e96b8e8e610dce8eb9aa6fabf3d0c5301"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/leafsphp/router/zipball/a18b707e96b8e8e610dce8eb9aa6fabf3d0c5301",
"reference": "a18b707e96b8e8e610dce8eb9aa6fabf3d0c5301",
"shasum": ""
},
"require": {
"leafs/anchor": "*",
"leafs/http": "*"
},
"require-dev": {
"pestphp/pest": "^1.21"
},
"type": "library",
"autoload": {
"psr-4": {
"Leaf\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Darko",
"email": "mickdd22@gmail.com",
"homepage": "https://mychi.netlify.app",
"role": "Developer"
}
],
"description": "Leaf router module for Leaf PHP.",
"homepage": "https://leafphp.netlify.app/#/modules/router",
"keywords": [
"framework",
"leaf",
"php",
"rest",
"router"
],
"support": {
"issues": "https://github.com/leafsphp/router/issues",
"source": "https://github.com/leafsphp/router/tree/v0.1.10"
},
"funding": [
{
"url": "https://github.com/leafsphp",
"type": "github"
},
{
"url": "https://opencollective.com/leaf",
"type": "open_collective"
}
],
"time": "2022-10-03T22:45:46+00:00"
},
{
"name": "psr/log",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
"shasum": ""
},
"require": {
"php": ">=8.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"support": {
"source": "https://github.com/php-fig/log/tree/3.0.0"
},
"time": "2021-07-14T16:46:02+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.3.0"
}

15
config.php Normal file
View file

@ -0,0 +1,15 @@
<?php
$config = array();
$config["db_host"] = "127.0.0.1";
$config["db_port"] = "3306";
$config["db_username"] = "powerdnsapi";
$config["db_password"] = "powerdnsapi";
$config["db_database"] = "powerdnsapi";
$config["base_uri"] = "http://localhost/pdns-api"
$config["debug"] = false;
?>

180
endpoints/01_Zones.php Normal file
View file

@ -0,0 +1,180 @@
<?php
app()->get($API_PREFIX . "/servers/{server_id}/zones/{zone_id}/export", function ($serverId, $zoneId) {
$apiKey = getApiKeyFromHeader();
if (!checkAccess($apiKey, null)) {
response()->exit("Unauthorized", 401);
}
$server = getDatabaseServerForUserByHostnameAndApiKey($serverId, $apiKey);
if ($server == null) {
response()->exit("Not found", 404);
}
$domains = getDomainsForUserByApiKey($apiKey);
$keyHelpDomains = keyHelp_getDomains($server["hostname"], $server["api_key"]);
$userKeyHelpDomains = array();
for ($i = 0; $i < count($domains); $i++) {
$currentDomain = $domains[$i];
if (array_key_exists($currentDomain["name"], $keyHelpDomains)) {
if ($currentDomain["name"] == rtrim($zoneId, ".")) {
$userKeyHelpDomains[$currentDomain["name"]] = $keyHelpDomains[$currentDomain["name"]];
}
}
}
$output = null;
foreach ($userKeyHelpDomains as $domainName => $domainId) {
$keyHelpDnsEntry = keyHelp_getDns($server["hostname"], $server["api_key"], $domainId);
$output = Zone::getAxfrExport($server["hostname"], $domainName, $keyHelpDnsEntry);
}
if ($output == null) {
response()->exit("Not found", 404);
}
response()->plain(
$output
);
});
app()->patch($API_PREFIX . "/servers/{server_id}/zones/{zone_id}", function ($serverId, $zoneId) {
$apiKey = getApiKeyFromHeader();
if (!checkAccess($apiKey, null)) {
response()->exit("Unauthorized", 401);
}
$server = getDatabaseServerForUserByHostnameAndApiKey($serverId, $apiKey);
if ($server == null) {
response()->exit("Not found", 404);
}
$domains = getDomainsForUserByApiKey($apiKey);
$keyHelpDomains = keyHelp_getDomains($server["hostname"], $server["api_key"]);
$userKeyHelpDomains = array();
for ($i = 0; $i < count($domains); $i++) {
$currentDomain = $domains[$i];
if (array_key_exists($currentDomain["name"], $keyHelpDomains)) {
if ($currentDomain["name"] == rtrim($zoneId, ".")) {
$userKeyHelpDomains[$currentDomain["name"]] = $keyHelpDomains[$currentDomain["name"]];
}
}
}
$keyHelpDomainName = null;
$keyHelpDomainId = null;
$keyHelpDnsEntry = null;
foreach ($userKeyHelpDomains as $domainName => $domainId) {
$keyHelpDnsEntry = keyHelp_getDns($server["hostname"], $server["api_key"], $domainId);
$keyHelpDomainId = $domainId;
$keyHelpDomainName = $domainName;
}
if ($keyHelpDnsEntry == null) {
response()->exit("Not found", 404);
}
$input = file_get_contents('php://input');
$records = getRecordsFromDomainNameAndZoneRequestAndKeyHelpDnsEntry($keyHelpDomainName, json_decode($input), $keyHelpDnsEntry);
keyHelp_putDns($server["hostname"], $server["api_key"], $domainId, $records);
response()->plain("", 204);
});
app()->get($API_PREFIX . "/servers/{server_id}/zones/{zone_id}", function ($serverId, $zoneId) {
$apiKey = getApiKeyFromHeader();
if (!checkAccess($apiKey, null)) {
response()->exit("Unauthorized", 401);
}
$server = getDatabaseServerForUserByHostnameAndApiKey($serverId, $apiKey);
if ($server == null) {
response()->exit("Not found", 404);
}
$domains = getDomainsForUserByApiKey($apiKey);
$keyHelpDomains = keyHelp_getDomains($server["hostname"], $server["api_key"]);
$userKeyHelpDomains = array();
for ($i = 0; $i < count($domains); $i++) {
$currentDomain = $domains[$i];
if (array_key_exists($currentDomain["name"], $keyHelpDomains)) {
if ($currentDomain["name"] == rtrim($zoneId, ".")) {
$userKeyHelpDomains[$currentDomain["name"]] = $keyHelpDomains[$currentDomain["name"]];
}
}
}
$output = null;
foreach ($userKeyHelpDomains as $domainName => $domainId) {
$keyHelpDnsEntry = keyHelp_getDns($server["hostname"], $server["api_key"], $domainId);
$output = Zone::fromKeyHelpDnsEntry($server["hostname"], $domainName, $keyHelpDnsEntry);
}
if ($output == null) {
response()->exit("Not found", 404);
}
response()->json(
$output
);
});
app()->get($API_PREFIX . "/servers/{server_id}/zones", function ($serverId) {
$apiKey = getApiKeyFromHeader();
if (!checkAccess($apiKey, null)) {
response()->exit("Unauthorized", 401);
}
$server = getDatabaseServerForUserByHostnameAndApiKey($serverId, $apiKey);
if ($server == null) {
response()->exit("Not found", 404);
}
$domains = getDomainsForUserByApiKey($apiKey);
$keyHelpDomains = keyHelp_getDomains($server["hostname"], $server["api_key"]);
$userKeyHelpDomains = array();
for ($i = 0; $i < count($domains); $i++) {
$currentDomain = $domains[$i];
if (array_key_exists($currentDomain["name"], $keyHelpDomains)) {
$userKeyHelpDomains[$currentDomain["name"]] = $keyHelpDomains[$currentDomain["name"]];
}
}
$output = array();
foreach ($userKeyHelpDomains as $domainName => $domainId) {
$keyHelpDnsEntry = keyHelp_getDns($server["hostname"], $server["api_key"], $domainId);
$output[] = Zone::fromKeyHelpDnsEntry($server["hostname"], $domainName, $keyHelpDnsEntry);
}
response()->json(
$output
);
});
?>

43
endpoints/02_Servers.php Normal file
View file

@ -0,0 +1,43 @@
<?php
app()->get($API_PREFIX . "/servers/{server_id}", function ($serverId) {
$apiKey = getApiKeyFromHeader();
if (!checkAccess($apiKey, null)) {
response()->exit("Unauthorized", 401);
}
$server = getServerForUserByHostnameAndApiKey($serverId, $apiKey);
if ($server == null) {
response()->exit("Not found", 404);
}
response()->json(
$server
);
});
app()->put($API_PREFIX . "/servers/{server_id}/cache/flush", function ($serverId) {
$output = new stdClass();
$output->count = 0;
$output->result = "Flushed cache";
response()->json(
$output
);
});
app()->get($API_PREFIX . "/servers", function () {
$apiKey = getApiKeyFromHeader();
if (!checkAccess($apiKey, null)) {
response()->exit("Unauthorized", 401);
}
response()->json(
getServersForUserByApiKey($apiKey)
);
});
?>

19
endpoints/autoload.php Normal file
View file

@ -0,0 +1,19 @@
<?php
$audoloadDir = opendir(__DIR__);
$filesToLoad = array();
while ($tmpFile = readdir($audoloadDir)) {
if ($tmpFile != "." && $tmpFile != ".." && $tmpFile != "autoload.php") {
$filesToLoad[] = $tmpFile;
}
}
sort($filesToLoad);
for ($i = 0; $i < count($filesToLoad); $i++) {
include_once(__DIR__ . "/" . $filesToLoad[$i]);
}
closedir($audoloadDir);
?>

View file

@ -0,0 +1,74 @@
<?php
use Leaf\Fetch;
function keyHelp_getDomains($hostname, $apiKey) {
$response = Fetch::request([
"method" => "GET",
"url" => "https://" . $hostname . "/api/v2/domains",
"headers" => ["X-API-Key: " . $apiKey]
]);
$output = array();
for ($i = 0; $i < count($response->data); $i++) {
$currentDomain = $response->data[$i];
if ($currentDomain->id_parent_domain == 0) {
$output[$currentDomain->domain] = $currentDomain->id;
}
}
return $output;
}
function keyHelp_getDns($hostname, $apiKey, $domainId) {
$response = Fetch::request([
"method" => "GET",
"url" => "https://" . $hostname . "/api/v2/dns/" . $domainId,
"headers" => ["X-API-Key: " . $apiKey]
]);
return $response->data;
}
function keyHelp_putDns($hostname, $apiKey, $domainId, $records) {
$response = Fetch::request([
"method" => "PUT",
"url" => "https://" . $hostname . "/api/v2/dns/" . $domainId,
"headers" => ["X-API-Key: " . $apiKey, "Content-Type: application/json"],
"data" => json_encode($records)
]);
//response()->exit(var_dump($response), 200);
return $response->data;
}
class KeyHelpDnsRequest {
public KeyHelpDnsRequestRecords $records;
}
class KeyHelpDnsRequestRecords {
public KeyHelpDnsRequestRecordsSoa $soa;
public array $other;
}
class KeyHelpDnsRequestRecordsSoa {
public int $ttl;
public string $primary_ns;
public string $rname;
public int $refresh;
public int $retry;
public int $expire;
public int $minimum;
}
class KeyHelpDnsRequestRecordsOther {
public string $host;
public int $ttl;
public string $type;
public string $value;
}
?>

76
helpers/ServerHelper.php Normal file
View file

@ -0,0 +1,76 @@
<?php
function getServersForUserByApiKey($apiKey) : array {
$output = array();
$query = <<<EOT
SELECT
server.*
FROM
user_domain,
domain,
user,
server
WHERE
user.api_key = '$apiKey' AND
user_domain.user_id = user.id AND
user_domain.domain_id = domain.id AND
server.id = domain.server_id
GROUP BY
server.id
EOT;
$databaseServers = db()->query($query)->fetchAll();
for ($i = 0; $i < count($databaseServers); $i++) {
$output[] = Server::fromDatabaseServer($databaseServers[$i]);
}
return $output;
}
function getServerForUserByHostnameAndApiKey($hostname, $apiKey) : ?Server {
$databaseServer = getDatabaseServerForUserByHostnameAndApiKey($hostname, $apiKey);
if ($databaseServer == null) {
return null;
}
return Server::fromDatabaseServer($databaseServer);
}
function getDatabaseServerForUserByHostnameAndApiKey($hostname, $apiKey) {
$output = null;
$query = <<<EOT
SELECT
server.*
FROM
user_domain,
domain,
user,
server
WHERE
user.api_key = '$apiKey' AND
user_domain.user_id = user.id AND
user_domain.domain_id = domain.id AND
server.id = domain.server_id
GROUP BY
server.id
EOT;
$databaseServers = db()->query($query)->fetchAll();
for ($i = 0; $i < count($databaseServers); $i++) {
$currentServer = $databaseServers[$i];
if ($currentServer["hostname"] == $hostname || ($hostname == "localhost" && $currentServer["localhost"] == 1)) {
$output = $currentServer;
break;
}
}
return $output;
}
?>

60
helpers/UserHelper.php Normal file
View file

@ -0,0 +1,60 @@
<?php
function getApiKeyFromHeader() : ?string {
$headers = Leaf\Http\Headers::all();
if (array_key_exists("X-API-Key", $headers)) {
return $headers["X-API-Key"];
}
if (array_key_exists("X-Api-Key", $headers)) {
return $headers["X-Api-Key"];
}
if (array_key_exists("x-api-key", $headers)) {
return $headers["x-api-key"];
}
return null;
}
function checkAccess($apiKey, $domain) : bool {
if (empty($apiKey)) {
return false;
}
if (count(db()->select("user")->where("api_key", $apiKey)->fetchAll()) != 1) {
return false;
}
if (!empty($domain)) {
}
return true;
}
function getUserIdByApiKey($apiKey) {
return db()->select("user")->where("api_key", $apiKey)->limit(1)->fetchObj()["id"];
}
function getDomainsForUserByApiKey($apiKey) {
$query = <<<EOT
SELECT
domain.*
FROM
user_domain,
domain,
user
WHERE
user.api_key = '$apiKey' AND
user_domain.user_id = user.id AND
user_domain.domain_id = domain.id
EOT;
$databaseDomains = db()->query($query)->fetchAll();
return $databaseDomains;
}
?>

119
helpers/ZoneHelper.php Normal file
View file

@ -0,0 +1,119 @@
<?php
function getRecordsFromDomainNameAndZoneRequestAndKeyHelpDnsEntry($domainName, $zoneRequest, $keyHelpDnsEntry) : KeyHelpDnsRequest {
$changedRecords = array();
for ($i = 0; $i < count($zoneRequest->rrsets); $i++) {
$currentRRSet = $zoneRequest->rrsets[$i];
if (property_exists($currentRRSet, "changetype")) {
$changedRecords[] = RRSet::fromZoneRequestRRSet($currentRRSet);
}
}
$keyHelpRecords = RRSet::arrayFromKeyHelpDnsEntry($domainName, $keyHelpDnsEntry);
$output = new KeyHelpDnsRequest();
$output->records = new KeyHelpDnsRequestRecords();
$changedSoaRecordIndex = getRecordIndexForNameAndType($changedRecords, $domainName . ".", "SOA");
if ($changedSoaRecordIndex != -1) {
$changedSoaRecord = $changedRecords[$changedSoaRecordIndex];
$soaRecord = new KeyHelpDnsRequestRecordsSoa();
$soaRecord->ttl = $changedSoaRecord->ttl;
$changedSoaRecordContent = $changedSoaRecord->records[0]->content;
$splittedChangedSoaRecordContent = explode(" ", $changedSoaRecordContent);
$soaRecord->primary_ns = $splittedChangedSoaRecordContent[0];
$soaRecord->rname = $splittedChangedSoaRecordContent[1];
$soaRecord->refresh = intval($splittedChangedSoaRecordContent[3]);
$soaRecord->retry = intval($splittedChangedSoaRecordContent[4]);
$soaRecord->expire = intval($splittedChangedSoaRecordContent[5]);
$soaRecord->minimum = intval($splittedChangedSoaRecordContent[6]);
$output->records->soa = $soaRecord;
unset($changedRecords[$changedSoaRecordIndex]);
} else {
$soaRecord = new KeyHelpDnsRequestRecordsSoa();
$soaRecord->ttl = $keyHelpDnsEntry->records->soa->ttl;
$soaRecord->primary_ns = $keyHelpDnsEntry->records->soa->primary_ns;
$soaRecord->rname = $keyHelpDnsEntry->records->soa->rname;
$soaRecord->refresh = $keyHelpDnsEntry->records->soa->refresh;
$soaRecord->retry = $keyHelpDnsEntry->records->soa->retry;
$soaRecord->expire = $keyHelpDnsEntry->records->soa->expire;
$soaRecord->minimum = $keyHelpDnsEntry->records->soa->minimum;
$output->records->soa = $soaRecord;
}
$output->records->other = array();
if(count($keyHelpRecords) > 0) {
for ($i = 0; $i < count($keyHelpRecords); $i++) {
$currentKeyHelpRecord = $keyHelpRecords[$i];
$changedRecordIndex = getRecordIndexForNameAndType($changedRecords, $currentKeyHelpRecord->name, $currentKeyHelpRecord->type);
if ($changedRecordIndex != -1) {
$changedRecord = $changedRecords[$changedRecordIndex];
if ($changedRecord->changetype == "REPLACE") {
for ($x = 0; $x < count($changedRecord->records); $x++) {
$newRecord = new KeyHelpDnsRequestRecordsOther();
$newRecord->host = trim(preg_replace("/" . str_replace(".", "\\.", $domainName) . "\\.?$/", "", $changedRecord->name), ".");
$newRecord->ttl = $changedRecord->ttl;
$newRecord->type = $changedRecord->type;
$newRecord->value = $changedRecord->records[$x]->content;
$output->records->other[] = $newRecord;
}
}
unset($changedRecords[$changedRecordIndex]);
} else {
for ($x = 0; $x < count($currentKeyHelpRecord->records); $x++) {
$newRecord = new KeyHelpDnsRequestRecordsOther();
$newRecord->host = trim(preg_replace("/" . str_replace(".", "\\.", $domainName) . "\\.?$/", "", $currentKeyHelpRecord->name), ".");
$newRecord->ttl = $currentKeyHelpRecord->ttl;
$newRecord->type = $currentKeyHelpRecord->type;
$newRecord->value = $currentKeyHelpRecord->records[$x]->content;
$output->records->other[] = $newRecord;
}
}
}
}
foreach ($changedRecords as $index => $changedRecord) {
if ($changedRecord->changetype == "REPLACE") {
for ($x = 0; $x < count($changedRecord->records); $x++) {
$newRecord = new KeyHelpDnsRequestRecordsOther();
$newRecord->host = trim(preg_replace("/" . str_replace(".", "\\.", $domainName) . "\\.?$/", "", $changedRecord->name), ".");
$newRecord->ttl = $changedRecord->ttl;
$newRecord->type = $changedRecord->type;
$newRecord->value = $changedRecord->records[$x]->content;
$output->records->other[] = $newRecord;
}
}
}
return $output;
}
function getRecordIndexForNameAndType($records, $name, $type) : int {
foreach ($records as $index => $record) {
if ($record->name == $name && $record->type == $type) {
return $index;
}
}
return -1;
}
?>

19
helpers/autoload.php Normal file
View file

@ -0,0 +1,19 @@
<?php
$audoloadDir = opendir(__DIR__);
$filesToLoad = array();
while ($tmpFile = readdir($audoloadDir)) {
if ($tmpFile != "." && $tmpFile != ".." && $tmpFile != "autoload.php") {
$filesToLoad[] = $tmpFile;
}
}
sort($filesToLoad);
for ($i = 0; $i < count($filesToLoad); $i++) {
include_once(__DIR__ . "/" . $filesToLoad[$i]);
}
closedir($audoloadDir);
?>

33
index.php Normal file
View file

@ -0,0 +1,33 @@
<?php
$API_VERSION = "0.1";
$API_PREFIX = "/api/v1";
require __DIR__ . "/config.php";
require __DIR__ . "/vendor/autoload.php";
require __DIR__ . "/helpers/autoload.php";
require __DIR__ . "/models/autoload.php";
require __DIR__ . "/endpoints/autoload.php";
db()->connect($config["db_host"] . ":" . $config["db_port"], $config["db_database"], $config["db_username"], $config["db_password"]);
if ($config["debug"]) {
app()->get($API_PREFIX . "/debug", function () {
response()->json(
dns_get_record("oswald-cloud.de", DNS_SOA)
//keyHelp_getDomains("lithium.server.ossinet.de", "L9r9MbEN.eswinlGhxQILroLhYkwWWdLKfKZ1cMSjHIGnOycN9yBDm9sf8PehutkHKVYj4W591Kqoli2Q4V0tI1wkLYvn1PRDONgmv4rINsI9FJucZtOeOEDlVmxiaqAU")
);
});
app()->patch($API_PREFIX . "/debug", function () {
response()->json(
Leaf\Http\Headers::all()
//keyHelp_getDomains("lithium.server.ossinet.de", "L9r9MbEN.eswinlGhxQILroLhYkwWWdLKfKZ1cMSjHIGnOycN9yBDm9sf8PehutkHKVYj4W591Kqoli2Q4V0tI1wkLYvn1PRDONgmv4rINsI9FJucZtOeOEDlVmxiaqAU")
);
});
}
app()->run();
?>

8
models/Error.php Normal file
View file

@ -0,0 +1,8 @@
<?php
// class Error {
// public string $error;
// public array $errors;
// }
?>

126
models/RRSet.php Normal file
View file

@ -0,0 +1,126 @@
<?php
class RRSet {
public static function arrayFromKeyHelpDnsEntry($domainName, $keyHelpDnsEntry) : array {
$output = array();
$keyHelpRecords = $keyHelpDnsEntry->records;
$output[] = RRSet::getSoaRecord($domainName, $keyHelpRecords->soa);
$otherKeyHelpRecords = $keyHelpRecords->other;
for ($i = 0; $i < count($otherKeyHelpRecords); $i++) {
$currentKeyHelpRecord = $otherKeyHelpRecords[$i];
$currentRecordName = null;
if ($currentKeyHelpRecord->host == "@") {
$currentRecordName = $domainName . ".";
} else {
$currentRecordName = $currentKeyHelpRecord->host . "." . $domainName . ".";
}
$currentRecordIndex = getRecordIndexForNameAndType($output, $currentRecordName, $currentKeyHelpRecord->type);
if ($currentRecordIndex != -1) {
$tmpRRSet = $output[$currentRecordIndex];
$tmpRecord = new Record();
$tmpRecord->disabled = false;
$tmpRecord->content = $currentKeyHelpRecord->value;
$tmpRRSet->records[] = $tmpRecord;
} else {
$tmpRRSet = new RRSet();
$tmpRRSet->name = $currentRecordName;
$tmpRRSet->type = $currentKeyHelpRecord->type;
$tmpRRSet->ttl = $currentKeyHelpRecord->ttl;
$tmpRRSet->records = array();
$tmpRecord = new Record();
$tmpRecord->disabled = false;
$tmpRecord->content = $currentKeyHelpRecord->value;
$tmpRRSet->records[] = $tmpRecord;
$output[] = $tmpRRSet;
}
}
return $output;
}
public static function fromZoneRequestRRSet($zoneRequestRRSet) : RRSet {
$output = new RRSet();
$output->name = $zoneRequestRRSet->name;
$output->type = $zoneRequestRRSet->type;
$output->ttl = $zoneRequestRRSet->ttl;
if (property_exists($zoneRequestRRSet, "changetype")) {
$output->changetype = $zoneRequestRRSet->changetype;
}
if (property_exists($zoneRequestRRSet, "records")) {
if ($zoneRequestRRSet->records != null && count($zoneRequestRRSet->records) > 0) {
$output->records = array();
for ($i = 0; $i < count($zoneRequestRRSet->records); $i++) {
$currentRecord = $zoneRequestRRSet->records[$i];
if (!$currentRecord->disabled) {
$record = new Record();
$record->disabled = false;
$record->content = $currentRecord->content;
$output->records[] = $record;
}
}
}
}
return $output;
}
private static function getSoaRecord($domainName, $soaRecord) : RRSet {
$output = new RRSet();
$output->name = $domainName . ".";
$output->type = "SOA";
$output->ttl = $soaRecord->ttl;
$dnsRecord = dns_get_record($domainName, DNS_SOA);
$output->serial = $dnsRecord[0]["serial"];
$recordString = $soaRecord->primary_ns . " " .
$soaRecord->rname . " " .
$dnsRecord[0]["serial"] . " " .
$soaRecord->refresh . " " .
$soaRecord->retry . " " .
$soaRecord->expire . " " .
$soaRecord->minimum;
$output->records = array();
$record = new Record();
$record->disabled = false;
$record->content = $recordString;
$output->records[] = $record;
return $output;
}
public string $name;
public string $type;
public int $ttl;
public string $changetype;
public array $records;
public array $comments;
}
?>

8
models/Record.php Normal file
View file

@ -0,0 +1,8 @@
<?php
class Record {
public bool $disabled;
public string $content;
}
?>

24
models/Server.php Normal file
View file

@ -0,0 +1,24 @@
<?php
class Server {
public static function fromDatabaseServer($datbaseServer) : Server {
$output = new Server();
$output->id = $datbaseServer["hostname"];
$output->daemon_type = "authoritative";
$output->version = $GLOBALS["API_VERSION"];
$output->url = $GLOBALS["config"]["base_uri"] . $GLOBALS["API_PREFIX"] . "/servers/" . $datbaseServer["hostname"];
$output->zones_url = $output->url . "/zones";
return $output;
}
public string $type = "Server";
public string $id;
public string $daemon_type;
public string $version;
public string $url;
public string $config_url;
public string $zones_url;
}
?>

66
models/Zone.php Normal file
View file

@ -0,0 +1,66 @@
<?php
class Zone {
public static function fromKeyHelpDnsEntry($serverHostname, $domainName, $keyHelpDnsEntry) : Zone {
$output = new Zone();
$output->id = $domainName . ".";
$output->name = $domainName;
$output->url = $GLOBALS["config"]["base_uri"] . $GLOBALS["API_PREFIX"] . "/servers/" . $serverHostname . "/zones/" . $domainName;
$output->kind = "Master";
$output->rrsets = RRSet::arrayFromKeyHelpDnsEntry($domainName, $keyHelpDnsEntry);
$dnsRecord = dns_get_record($domainName, DNS_SOA);
$output->serial = $dnsRecord[0]["serial"];
$output->notified_serial = $dnsRecord[0]["serial"];
$output->edited_serial = $dnsRecord[0]["serial"];
$output->dnssec = false;
return $output;
}
public static function getAxfrExport($serverHostname, $domainName, $keyHelpDnsEntry) : string {
$zone = Zone::fromKeyHelpDnsEntry($serverHostname, $domainName, $keyHelpDnsEntry);
$output = "";
for ($i = 0; $i < count($zone->rrsets); $i++) {
if ($i > 0) {
$output = $output . "\r\n";
}
$RRSet = $zone->rrsets[$i];
$output = $output . $RRSet->name . "\t" . $RRSet->ttl . "\t" . $RRSet->type . "\t" . $RRSet->records[0]->content;
}
return $output;
}
public string $id;
public string $name;
public string $type = "Zone";
public string $url;
public string $kind;
public array $rrsets;
public int $serial;
public int $notified_serial;
public int $edited_serial;
public array $masters;
public bool $dnssec;
public string $nsec3param;
public bool $nsec3narrow;
public bool $presigned;
public string $soa_edit;
public string $soa_edit_api;
public bool $api_rectify;
public string $zone;
public string $catalog;
public string $account;
public array $nameservers;
public array $master_tsig_key_ids;
public array $slave_tsig_key_ids;
}
?>

19
models/autoload.php Normal file
View file

@ -0,0 +1,19 @@
<?php
$audoloadDir = opendir(__DIR__);
$filesToLoad = array();
while ($tmpFile = readdir($audoloadDir)) {
if ($tmpFile != "." && $tmpFile != ".." && $tmpFile != "autoload.php") {
$filesToLoad[] = $tmpFile;
}
}
sort($filesToLoad);
for ($i = 0; $i < count($filesToLoad); $i++) {
include_once(__DIR__ . "/" . $filesToLoad[$i]);
}
closedir($audoloadDir);
?>