From 144d8a23b3474d1f294ce29b01c89de80d4d0267 Mon Sep 17 00:00:00 2001
From: Matthew Saunders Brown
Date: Tue, 13 Feb 2024 14:41:15 -0800
Subject: [PATCH] add vdns code
---
panel/classes/Panel/Vdns.php | 106 +++++++++++++++++++++++
panel/classes/Panel/Vdns/Zones.php | 73 ++++++++++++++++
panel/classes/Panel/Vdns/ZonesAdd.php | 69 +++++++++++++++
panel/classes/Panel/Vdns/ZonesDelete.php | 46 ++++++++++
panel/config/config.ini | 66 +++++++-------
panel/config/maps-vdns.ini | 11 +++
panel/config/maps-vpanel.ini | 1 -
panel/index.php | 5 ++
panel/ui/header.html | 1 +
panel/ui/vdns/zones-add.html | 20 +++++
panel/ui/vdns/zones-delete.html | 17 ++++
panel/ui/vdns/zones-zone.html | 86 ++++++++++++++++++
panel/ui/vdns/zones.html | 47 ++++++++++
13 files changed, 517 insertions(+), 31 deletions(-)
create mode 100644 panel/classes/Panel/Vdns.php
create mode 100644 panel/classes/Panel/Vdns/Zones.php
create mode 100644 panel/classes/Panel/Vdns/ZonesAdd.php
create mode 100644 panel/classes/Panel/Vdns/ZonesDelete.php
create mode 100644 panel/config/maps-vdns.ini
create mode 100644 panel/ui/vdns/zones-add.html
create mode 100644 panel/ui/vdns/zones-delete.html
create mode 100644 panel/ui/vdns/zones-zone.html
create mode 100644 panel/ui/vdns/zones.html
diff --git a/panel/classes/Panel/Vdns.php b/panel/classes/Panel/Vdns.php
new file mode 100644
index 0000000..a644392
--- /dev/null
+++ b/panel/classes/Panel/Vdns.php
@@ -0,0 +1,106 @@
+
+ * GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+ */
+
+namespace Panel;
+
+class Vdns extends \Panel {
+
+ function beforeRoute($f3) {
+
+ parent::beforeRoute($f3);
+
+ if ($f3->get('PDNSADMIN') != '1') {
+ $f3->reroute('/');
+ }
+
+ }
+
+ public static function verifyZoneExists($zone) {
+
+ global $f3;
+
+ exec("/usr/local/bin/vdns-zone-ext.sh -z $zone", $output, $result_code);
+ if ($result_code == 0 && $output[0] == 'true') {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+
+ }
+
+ public static function returnZoneDefaultsArray($zone) {
+
+ global $f3;
+
+ if ($defaults_array = $f3->call('\Panel::vGet', array("vdns-zone-def.sh -z $zone -c", FALSE))) {
+ return $defaults_array;
+ } else {
+ return FALSE;
+ }
+
+ }
+
+ public static function returnZoneDefaultsNameserverArray($zone) {
+
+ global $f3;
+
+ if ($defaults_array = $f3->call('\Panel\Vdns::returnZoneDefaultsArray', $zone)) {
+ $defaults_ns_array = array();
+ foreach($defaults_array as $record_array) {
+ if ($record_array['type'] == "NS") {
+ $defaults_ns_array[] = $record_array['content'];
+ }
+ }
+ sort($defaults_ns_array);
+ return $defaults_ns_array;
+ } else {
+ return FALSE;
+ }
+
+ }
+
+ public static function returnNameserverArray($zone) {
+
+ global $f3;
+
+ $ns_array = array();
+ if ($dns_ns_array = dns_get_record("$zone", DNS_NS)) {
+ foreach ($dns_ns_array as $record_array) {
+ $ns_array[] = $record_array['target'];
+ }
+ sort($ns_array);
+ return $ns_array;
+ } else {
+ return FALSE;
+ }
+
+
+ }
+
+ public static function returnNameserverStatus($zone) {
+
+ global $f3;
+
+ if ($defaults_ns_array = $f3->call('\Panel\Vdns::returnZoneDefaultsNameserverArray', $zone)) {
+ if ($ns_array = $f3->call('\Panel\Vdns::returnNameserverArray', $zone)) {
+ if ($defaults_ns_array === $ns_array) {
+ return "Verified";
+ } else {
+ return "Pending";
+ }
+ } else {
+ return "Unknown";
+ }
+ } else {
+ return "Error";
+ }
+
+ }
+
+}
diff --git a/panel/classes/Panel/Vdns/Zones.php b/panel/classes/Panel/Vdns/Zones.php
new file mode 100644
index 0000000..39509b0
--- /dev/null
+++ b/panel/classes/Panel/Vdns/Zones.php
@@ -0,0 +1,73 @@
+
+ * GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+ */
+
+namespace Panel\Vdns;
+
+class Zones extends \Panel\Vdns {
+
+ /* use this to make query */
+ function beforeRoute($f3) {
+
+ parent::beforeRoute($f3);
+
+ if ($f3->exists('PARAMS.zone')) {
+ $zone = $f3->get('PARAMS.zone');
+ if ($f3->call('\Panel\Vdns::verifyZoneExists', $zone)) {
+ if ($zone_array = $f3->call('\Panel::vGet', array("vdns-zone-exp.sh -z $zone -c", FALSE))) {
+ $f3->set('zone_array', $zone_array);
+ }
+ $ns_info_array = array();
+ $ns_info_array['zone'] = $zone;
+ $ns_info_array['status'] = $f3->call('\Panel\Vdns::returnNameserverStatus', $zone);
+ if ($ns_info_array['status'] != "Verified") {
+ $ns_info_array['defaults_ns_array'] = $f3->call('\Panel\Vdns::returnZoneDefaultsNameserverArray', $zone);
+ $ns_info_array['ns_array'] = $f3->call('\Panel\Vdns::returnNameserverArray', $zone);
+ }
+ $f3->set('ns_info_array', $ns_info_array);
+ }
+ } else {
+ if ($zones_array = $f3->call('\Panel::vGet', array("vdns-zone-lst.sh", FALSE))) {
+ foreach ($zones_array as $k=>$zone_array) {
+ $zones_array[$k]['ns_status'] = $f3->call('\Panel\Vdns::returnNameserverStatus', $zone_array['zone']);
+ }
+ $f3->set('zones_array', $zones_array);
+ }
+ }
+
+ }
+
+ static function get($f3) {
+
+ if ($f3->exists('PARAMS.zone')) {
+
+ $zone = $f3->get('PARAMS.zone');
+
+ if (is_array($f3->get('zone_array'))) {
+
+ $f3->set('page_header', "DNS Zone records for $zone");
+ echo \Template::instance()->render('vdns/zones-zone.html');
+
+ } else {
+
+ $messages[] = "Zone $zone not found.";
+ $f3->set('SESSION.messages', $messages);
+ $f3->reroute("/DNS");
+
+ }
+
+ } else {
+
+ $f3->set('page_header', "DNS Zones");
+ echo \Template::instance()->render('vdns/zones.html');
+
+ }
+
+ }
+
+}
diff --git a/panel/classes/Panel/Vdns/ZonesAdd.php b/panel/classes/Panel/Vdns/ZonesAdd.php
new file mode 100644
index 0000000..271db32
--- /dev/null
+++ b/panel/classes/Panel/Vdns/ZonesAdd.php
@@ -0,0 +1,69 @@
+
+ * GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+ */
+
+namespace Panel\Vdns;
+
+class ZonesAdd extends \Panel\Vdns {
+
+ function beforeRoute($f3) {
+
+ parent::beforeRoute($f3);
+
+ }
+
+ static function get($f3) {
+
+ echo \Template::instance()->render('vdns/zones-add.html');
+
+ }
+
+ function post($f3) {
+
+ // print_r($_POST);
+
+ /* force zone to be all lower case */
+ $zone = strtolower($_POST['zone']);
+ /* strip spaces */
+ $zone = trim($zone);
+ /* remove leading www. */
+ $zone = preg_replace('/^www\./', '', $zone);
+ /* remove trailing . (dot) */
+ $zone = rtrim($zone, '.');
+ if ($f3->call('\Panel::validateDomain', $zone)) {
+ /* check if zone exists */
+ if ($f3->call('\Panel\Vdns::verifyZoneExists', $zone)) {
+ $messages[] = "Zone $zone already exists in DNS.";
+ $messages[] = "Note if $zone should be associated with this server but it's now showing up in the list below please contact support.";
+ $f3->set('SESSION.messages', $messages);
+ $f3->call('\Panel\Vdns\ZonesAdd::get', $f3);
+ } else {
+ $hostname = $f3->get('NAV.hostname');
+ exec("/usr/local/bin/vdns-zone-add.sh -z $zone -w hostname=$hostname/$zone", $output, $result_code);
+ if ($result_code == 0) {
+ $messages[] = "Zone (Domain Name) $zone has been added to DNS.";
+ $f3->set('SESSION.messages', $messages);
+ $f3->reroute("/DNS");
+ } else {
+ if (count($output) > 0) {
+ foreach ($output as $k=>$output_message) {
+ $messages[] = "$output_message";
+ }
+ } else {
+ $messages[] = "Unknown error adding Zone $zone to DNS.";
+ }
+ $f3->set('SESSION.messages', $messages);
+ $f3->call('\Panel\Vdns\ZonesAdd::get', $f3);
+ }
+ }
+ } else {
+ $f3->call('\Panel\Vdns\ZonesAdd::get', $f3);
+ }
+ }
+
+}
diff --git a/panel/classes/Panel/Vdns/ZonesDelete.php b/panel/classes/Panel/Vdns/ZonesDelete.php
new file mode 100644
index 0000000..6aa74d7
--- /dev/null
+++ b/panel/classes/Panel/Vdns/ZonesDelete.php
@@ -0,0 +1,46 @@
+
+ * GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+ */
+
+namespace Panel\Vdns;
+
+class ZonesDelete extends \Panel\Vdns {
+
+ function beforeRoute($f3) {
+
+ parent::beforeRoute($f3);
+
+ /* verify zone exists */
+ $zone = $f3->get('PARAMS.zone');
+ if (!$f3->call('\Panel\Vdns::verifyZoneExists', $zone)) {
+ $messages[] = "Zone '$zone' does not exist.";
+ $f3->set('SESSION.messages', $messages);
+ $f3->reroute("/DNS");
+ }
+
+ }
+
+ static function get($f3) {
+
+ $f3->set('confirm', 'true');
+ echo \Template::instance()->render('vdns/zones-delete.html');
+
+ }
+
+ function post($f3) {
+
+ /* run delete command here */
+ $zone = $f3->get('PARAMS.zone');
+ exec("/usr/local/bin/vdns-zone-del.sh -z $zone -x", $output, $result_code);
+ $messages[] = "Zone '$zone' has been deleted from DNS.";
+ $f3->set('SESSION.messages', $messages);
+ $f3->reroute("/DNS");
+
+ }
+
+}
diff --git a/panel/config/config.ini b/panel/config/config.ini
index 7ccd7ad..989f3b8 100644
--- a/panel/config/config.ini
+++ b/panel/config/config.ini
@@ -1,30 +1,36 @@
-; vpanel-stack
-; https://git.stack-source.com/msb/vpanel-stack
-; Copyright (c) 2022 Matthew Saunders Brown
-; GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-[globals]
-DEBUG=0
-UI=ui/
-AUTOLOAD=classes/
-TEMP=tmp/
-LOGS=tmp/logs/
-UPLOADS=tmp/uploads/
-PACKAGE=Stack-Panel
-AUTHOR=Matthew Saunders Brown
-LICENSE=GPL-3.0
-LICENSEURL=https://www.gnu.org/licenses/gpl-3.0.txt
-CASELESS=FALSE
-CACHE=TRUE
-; Session lifetime in seconds
-TIMEOUT=900
-; Remote IP address that is automatically logged in without auth
-ADMINIP=
-; Jail new users by default. 1 = Yes, blank or 0 = No
-JAILUSER=1
-; PHP-FPM pm.max_children. Recommended range 2-12 on Shared Server
-FPMMAX=4
-; Write user info to /home/username/.passwd. 1 = Yes, blank or 0 = No
-WRITEUSERINFO=1
-; Show "Write User Info" & "Write DB Info" options. If no then just use defaults above without giving users the option to change. 1 = Yes, blank or 0 = No
-SHOWWRITEINFO=0
+; vpanel-stack
+; https://git.stack-source.com/msb/vpanel-stack
+; Copyright (c) 2022 Matthew Saunders Brown
+; GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+[globals]
+DEBUG=0
+UI=ui/
+AUTOLOAD=classes/
+TEMP=tmp/
+LOGS=tmp/logs/
+UPLOADS=tmp/uploads/
+PACKAGE=Stack-Panel
+AUTHOR=Matthew Saunders Brown
+LICENSE=GPL-3.0
+LICENSEURL=https://www.gnu.org/licenses/gpl-3.0.txt
+CASELESS=FALSE
+CACHE=TRUE
+; Session lifetime in seconds
+TIMEOUT=900
+; Remote IP address that is automatically logged in without auth
+ADMINIP=
+; Jail new users by default. 1 = Yes, blank or 0 = No
+JAILUSER=1
+; PHP-FPM pm.max_children. Recommended range 2-12 on Shared Server
+FPMMAX=4
+; Write user info to /home/username/.passwd. 1 = Yes, blank or 0 = No
+WRITEUSERINFO=1
+; Show "Write User Info" & "Write DB Info" options. If no then just use defaults above without giving users the option to change. 1 = Yes, blank or 0 = No
+SHOWWRITEINFO=0
+; DNS admin. 1 = Yes, blank or 0 = No
+PDNSADMIN=0
+; Maximum number of results returned for DNS listings. Defaults to 100 if unspecified.
+;PDNSMAX=100
+; URL to phpMyPDNS. If this is set, and PDNSADMIN is enabled, show link to phpMyPDNS
+PHPMYPDNSURL=
diff --git a/panel/config/maps-vdns.ini b/panel/config/maps-vdns.ini
new file mode 100644
index 0000000..7a8e5ec
--- /dev/null
+++ b/panel/config/maps-vdns.ini
@@ -0,0 +1,11 @@
+; vpanel-stack
+; https://git.stack-source.com/msb/vpanel-stack
+; Copyright (c) 2024 Matthew Saunders Brown
+; GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+[maps]
+; Vdns
+/DNS [sync] = Panel\Vdns\Zones
+/DNS/@zone [sync] = Panel\Vdns\Zones
+/DNS/Add [sync] = Panel\Vdns\ZonesAdd
+/DNS/@zone/Delete [sync] = Panel\Vdns\ZonesDelete
diff --git a/panel/config/maps-vpanel.ini b/panel/config/maps-vpanel.ini
index bebb7cb..f1578bd 100644
--- a/panel/config/maps-vpanel.ini
+++ b/panel/config/maps-vpanel.ini
@@ -84,4 +84,3 @@
/Certs/@cert/Delete [sync] = Panel\Cert\CertsDelete
/Databases [sync] = Panel\MySQL\Databases
-
diff --git a/panel/index.php b/panel/index.php
index 13b092f..5542533 100644
--- a/panel/index.php
+++ b/panel/index.php
@@ -38,6 +38,11 @@ if ($f3->get('HOST') == $f3->get('NAV.hostname')) {
$f3->set('NAV.mapping', $mapping);
$f3->config("config/maps-$mapping.ini");
+/* load DNS mapping, if enabled */
+if ($f3->get('PDNSADMIN') == '1') {
+ $f3->config("config/maps-vdns.ini");
+}
+
/* custom error page */
$f3->set('ONERROR',function($f3){
echo \Template::instance()->render('error.html');
diff --git a/panel/ui/header.html b/panel/ui/header.html
index 74e9ce0..04f23b1 100644
--- a/panel/ui/header.html
+++ b/panel/ui/header.html
@@ -33,6 +33,7 @@
Databases |
Certificates |
Users |
+ DNS |
Logout
diff --git a/panel/ui/vdns/zones-add.html b/panel/ui/vdns/zones-add.html
new file mode 100644
index 0000000..36add0d
--- /dev/null
+++ b/panel/ui/vdns/zones-add.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+Zone Enter the Domain Name that will be added to DNS.
+
+
+
diff --git a/panel/ui/vdns/zones-delete.html b/panel/ui/vdns/zones-delete.html
new file mode 100644
index 0000000..85afa9e
--- /dev/null
+++ b/panel/ui/vdns/zones-delete.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/panel/ui/vdns/zones-zone.html b/panel/ui/vdns/zones-zone.html
new file mode 100644
index 0000000..fa993bc
--- /dev/null
+++ b/panel/ui/vdns/zones-zone.html
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+ Nameservers for {{ @ns_info_array.zone }} verified. The DNS records below are active.
+
+ You can manage these DNS entries here: {{ @PHPMYPDNSURL }}
+
+
+
+
+
+
+
+ The Nameservers for {{ @ns_info_array.zone }} are not pointing to this DNS system.
+ To make this DNS active update the Nameservers at your current Domain Name Registrar to:
+
+ {{ @nameserver }}
+
+ Note that after making this change it can take up to 24 hours for the changes to go through.
+
+ If you are intentionally using another provider for DNS you can reference the records below for what should be added to your DNS (excluding the NS & SOA records).
+
+
+ The Nameserver verification system could not find nameserver information for {{ @ns_info_array.zone }}.
+ Make sure the domain name is registered and has the folowing nameservers set:
+
+ {{ @nameserver }}
+
+
+
+ There was an error verifying the Namservers for {{ @ns_info_array.zone }}.
+ If this persists please contact tech support.
+
+
+
+
+
+
+
+ Name |
+ TTL |
+ Class |
+ Type |
+ Value |
+
+
+
+
+
+ {{ @record_array.name }} |
+ {{ @record_array.ttl }} |
+ {{ @record_array.class }} |
+ {{ @record_array.type }} |
+
+ "{{ @record_array.value }}" |
+ {{ @record_array.value }} |
+
+
+
+
+
+
+
+ Notes:
+
+ - Zone info is displayed in BIND format.
You should be able to cut-and-past above records directly into a BIND file, if desired.
+ - MX & SRV records will show the Priority as part of the record.
e.g. "10 mail.example.com" indicates a Priority of "10" for "mail.example.com".
Only MX & SRV records use Priority, all other records have an unused priority of "0".
+
+
+
+
+ phpMyPDNS can be used to manage DNS entries here: {{ @PHPMYPDNSURL }}
+
+
+
+
+ No Zone info.
+
+
+
+
diff --git a/panel/ui/vdns/zones.html b/panel/ui/vdns/zones.html
new file mode 100644
index 0000000..f9cc369
--- /dev/null
+++ b/panel/ui/vdns/zones.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+ Zone |
+ Nameservers |
+ Action |
+
+
+
+
+
+ {{ @zone.zone }} |
+
+ ✓ {{ @zone.ns_status }} |
+ {{ @zone.ns_status }} - click view for details → |
+
+ View Delete |
+
+
+
+
+
+
+
+ There are no DNS Zones on this server.
+
+
+
+
+Zone is what a Domain Name is called in DNS.
+View zone to see list of all DNS entries.
+Delete will remove the zone from DNS entirely.
+
+
+
+ phpMyPDNS can be used to manage DNS entries here: {{ @PHPMYPDNSURL }}
+
+
+
+Add new DNS Zone
+
+
+