From 17e3cf908d2a299c7476c81526bc5f4688745ada Mon Sep 17 00:00:00 2001 From: Lukas Metzger Date: Sat, 23 Jan 2016 17:05:13 +0100 Subject: [PATCH] Added working implementation for edit-master.php, validity checks are required --- api/edit-master.php | 129 +++++++++++++++++++++++- edit-master.php | 52 ++-------- js/edit-master.js | 229 ++++++++++++++++++++++++++++++++++++++++-- lib/update-serial.php | 59 +++++++++++ 4 files changed, 421 insertions(+), 48 deletions(-) create mode 100644 lib/update-serial.php diff --git a/api/edit-master.php b/api/edit-master.php index 2aa58ec..6859d4a 100644 --- a/api/edit-master.php +++ b/api/edit-master.php @@ -20,6 +20,7 @@ require_once '../config/config-default.php'; require_once '../lib/database.php'; require_once '../lib/session.php'; require_once '../lib/soa-mail.php'; +require_once '../lib/update-serial.php'; $input = json_decode(file_get_contents('php://input')); @@ -151,4 +152,130 @@ if(isset($input->action) && $input->action == "getSoa") { } -echo json_encode($retval); +//Action for getting SOA +if(isset($input->action) && $input->action == "getSerial") { + $domainId = (int)$input->domain; + + $stmt = $db->prepare("SELECT content FROM records WHERE type='SOA' AND domain_id=?"); + $stmt->bind_param("i", $domainId); + $stmt->execute(); + + $stmt->bind_result($content); + $stmt->fetch(); + + $content = explode(" ", $content); + + $retval = Array(); + + $retval['serial'] = $content[2]; +} + +//Action for saving SOA +if(isset($input->action) && $input->action == "saveSoa") { + $domainId = (int)$input->domain; + + $db->autocommit(false); + $db->begin_transaction(); + + $stmt = $db->prepare("SELECT content FROM records WHERE type='SOA' AND domain_id=?"); + $stmt->bind_param("i", $domainId); + $stmt->execute(); + $stmt->bind_result($content); + $stmt->fetch(); + $stmt->close(); + + $content = explode(" ", $content); + $serial = $content[2]; + + $newsoa = $input->primary . " "; + $newsoa .= mail_to_soa($input->email) . " "; + $newsoa .= $serial . " "; + $newsoa .= $input->refresh . " "; + $newsoa .= $input->retry . " "; + $newsoa .= $input->expire . " "; + $newsoa .= $input->ttl; + + $stmt = $db->prepare("UPDATE records SET content=? WHERE type='SOA' AND domain_id=?"); + $stmt->bind_param("si", $newsoa, $domainId); + $stmt->execute(); + + $db->commit(); + + $retval = Array(); + + update_serial($db, $domainId); +} + +//Action for saving Record +if(isset($input->action) && $input->action == "saveRecord") { + $domainId = $input->domain; + + $stmt = $db->prepare("UPDATE records SET name=?,type=?,content=?,ttl=?,prio=? WHERE id=? AND domain_id=?"); + $stmt->bind_param("sssiiii", + $input->name, $input->type, + $input->content, $input->ttl, + $input->prio, + $input->id, $domainId + ); + $stmt->execute(); + update_serial($db, $domainId); +} + +//Action for adding Record +if(isset($input->action) && $input->action == "addRecord") { + $domainId = $input->domain; + + $stmt = $db->prepare("INSERT INTO records (domain_id, name, type, content, prio, ttl) VALUES (?,?,?,?,?,?)"); + $stmt->bind_param("isssii", + $domainId, $input->name, + $input->type, $input->content, + $input->prio, $input->ttl + ); + $stmt->execute(); + $stmt->close(); + + $stmt = $db->prepare("SELECT LAST_INSERT_ID()"); + $stmt->execute(); + $stmt->bind_result($newId); + $stmt->fetch(); + $stmt->close(); + + $retval = Array(); + $retval['newId'] = $newId; + + update_serial($db, $domainId); +} + +//Action for removing Record +if(isset($input->action) && $input->action == "removeRecord") { + $domainId = $input->domain; + $recordId = $input->id; + + $stmt = $db->prepare("DELETE FROM records WHERE id=? AND domain_id=?"); + $stmt->bind_param("ii", $recordId, $domainId); + $stmt->execute(); + $stmt->close(); + + update_serial($db, $domainId); +} + +//Action for getting domain name +if(isset($input->action) && $input->action == "getDomainName") { + $domainId = $input->domain; + + $stmt = $db->prepare("SELECT name FROM domains WHERE id=?"); + $stmt->bind_param("i", $domainId); + $stmt->execute(); + $stmt->bind_result($domainName); + $stmt->fetch(); + $stmt->close(); + + $retval = Array(); + $retval['name'] = $domainName; +} + +if (isset($retval)) { + echo json_encode($retval); +} else { + echo "{}"; +} diff --git a/edit-master.php b/edit-master.php index efab7f1..f5a86b0 100644 --- a/edit-master.php +++ b/edit-master.php @@ -51,7 +51,7 @@ limitations under the License.
-

example.com

+

@@ -125,45 +125,7 @@ limitations under the License.
Type - +
@@ -182,7 +144,15 @@ limitations under the License. - + + + + + + + + +
diff --git a/js/edit-master.js b/js/edit-master.js index 99fda86..da0d661 100644 --- a/js/edit-master.js +++ b/js/edit-master.js @@ -17,7 +17,18 @@ var sort = { field: "", order: 1 -} +}; + +var domainName = ""; + +var recordTypes = [ + "A","AAAA","AFSDB","CERT","CNAME","DHCID", + "DLV","DNSKEY","DS","EUI48","EUI64","HINFO", + "IPSECKEY","KEY","KX","LOC","MINFO","MR", + "MX","NAPTR","NS","NSEC","NSEC3","NSEC3PARAM", + "OPT","PTR","RKEY","RP","RRSIG","SOA","SPF", + "SRV","SSHFP","TLSA","TSIG","TXT","WKS" +]; $(document).ready(function() { @@ -42,7 +53,12 @@ $(document).ready(function() { }); $('#searchType').select2({ - placeholder: "Filter..." + placeholder: "Filter...", + data: recordTypes + }); + + $('#addType').select2({ + data: recordTypes }); $('#table-records>thead>tr>td span.glyphicon').click(function() { @@ -70,10 +86,13 @@ $(document).ready(function() { $('#searchType').change(function() { requestRecordData(); }); - + + $('#addButton').click(addRecord); + requestRecordData(); requestSoaData(); - + requestSerial(); + requestDomainName(); }); function validateSoaData() { @@ -101,10 +120,13 @@ function recreateTable(data) { .append('' + item.content + '') .append('' + item.priority + '') .append('' + item.ttl + '') - .append('') - .append(''); + .append('') + .append(''); }); + + $('#table-records>tbody>tr>td>span.glyphicon-trash').click(trashClicked); + $('#table-records>tbody>tr>td>span.glyphicon-pencil').click(editClicked); } function requestRecordData() { @@ -158,6 +180,22 @@ function requestSoaData() { $('#soa-retry').val(data.retry); $('#soa-expire').val(data.expire); $('#soa-ttl').val(data.ttl); + }, + "json" + ); +} + +function requestSerial() { + var data = { + action: "getSerial" + }; + + data.domain = location.hash.substring(1); + + $.post( + "api/edit-master.php", + JSON.stringify(data), + function(data) { $('#soa-serial').val(data.serial); }, "json" @@ -165,5 +203,184 @@ function requestSoaData() { } function saveSoaData() { + var data = { + action: "saveSoa" + }; + data.domain = location.hash.substring(1); + + data.primary = $('#soa-primary').val(); + data.email = $('#soa-mail').val(); + data.refresh = $('#soa-refresh').val(); + data.retry = $('#soa-retry').val(); + data.expire = $('#soa-expire').val(); + data.ttl = $('#soa-ttl').val(); + + $.post( + "api/edit-master.php", + JSON.stringify(data), + function() { + requestSerial(); + }, + "json" + ); +} + +function editClicked() { + var tableCells = $(this).parent().parent().children('td'); + var tableRow = $(this).parent().parent(); + + var valueName = tableCells.eq(1).text(); + tableCells.eq(1).empty(); + $('').appendTo(tableCells.eq(1)).val(valueName); + + var valueType = tableCells.eq(2).text(); + tableCells.eq(2).empty(); + $('').appendTo(tableCells.eq(2)).select2({ + data: recordTypes + }).val(valueType).trigger("change"); + + var valueContent = tableCells.eq(3).text(); + tableCells.eq(3).empty(); + $('').appendTo(tableCells.eq(3)).val(valueContent); + + var valuePrio = tableCells.eq(4).text(); + tableCells.eq(4).empty(); + $('').appendTo(tableCells.eq(4)).val(valuePrio); + + var valueTtl = tableCells.eq(5).text(); + tableCells.eq(5).empty(); + $('').appendTo(tableCells.eq(5)).val(valueTtl); + + tableCells.eq(6).remove(); + tableCells.eq(7).remove(); + + $(tableRow).append(''); + + $(tableRow).find('button').click(saveRecord); + + enableFilter(false); +} + +function saveRecord() { + + var tableRow = $(this).parent().parent(); + + var data = { + id: tableRow.children('td').eq(0).text(), + name: tableRow.children('td').eq(1).children('input').val(), + type: tableRow.children('td').eq(2).children('select').val(), + content: tableRow.children('td').eq(3).children('input').val(), + prio: tableRow.children('td').eq(4).children('input').val(), + ttl: tableRow.children('td').eq(5).children('input').val(), + action: "saveRecord", + domain: location.hash.substring(1) + }; + + tableRow.children('td').eq(0).empty().text(data.id); + tableRow.children('td').eq(1).empty().text(data.name); + tableRow.children('td').eq(2).empty().text(data.type); + tableRow.children('td').eq(3).empty().text(data.content); + tableRow.children('td').eq(4).empty().text(data.prio); + tableRow.children('td').eq(5).empty().text(data.ttl); + + tableRow.children('td').eq(6).remove(); + + tableRow.append('') + .append(''); + tableRow.find('span.glyphicon-trash').click(trashClicked); + tableRow.find('span.glyphicon-pencil').click(editClicked); + + enableFilter(true); + + $.post( + "api/edit-master.php", + JSON.stringify(data), + function() { + requestSerial(); + }, + "json" + ); +} + +function addRecord() { + var data = { + name: $('#addName').val(), + type: $('#addType').val(), + content: $('#addContent').val(), + prio: $('#addPrio').val(), + ttl: $('#addTtl').val(), + action: "addRecord", + domain: location.hash.substring(1) + }; + + $.post( + "api/edit-master.php", + JSON.stringify(data), + function(dataRecv) { + $('').appendTo('#table-records>tbody') + .append('' + dataRecv.newId + '') + .append('' + data.name + '') + .append('' + data.type + '') + .append('' + data.content + '') + .append('' + data.prio + '') + .append('' + data.ttl + '') + .append('') + .append('') + .find('span.glyphicon-trash').click(trashClicked) + .find('span.glyphicon-pencil').click(editClicked); + + requestSerial(); + }, + "json" + ); +} + +function trashClicked() { + var data = { + id: $(this).parent().parent().children().eq(0).text(), + domain: location.hash.substring(1), + action: "removeRecord" + }; + + var lineAffected = $(this).parent().parent(); + + $.post( + "api/edit-master.php", + JSON.stringify(data), + function() { + lineAffected.remove(); + requestSerial(); + }, + "json" + ); +} + +function requestDomainName() { + var data = { + action: "getDomainName", + domain: location.hash.substring(1) + }; + + $.post( + "api/edit-master.php", + JSON.stringify(data), + function(data) { + $('#domain-name').text(data.name); + domainName = data.name; + }, + "json" + ); +} + +function enableFilter(enable) { + if(enable) { + $('#searchName').prop("disabled", false); + $('#searchType').prop("disabled", false); + $('#searchContent').prop("disabled", false); + } else { + $('#searchName').prop("disabled", true); + $('#searchType').prop("disabled", true); + $('#searchContent').prop("disabled", true); + } } \ No newline at end of file diff --git a/lib/update-serial.php b/lib/update-serial.php new file mode 100644 index 0000000..f1ee3fe --- /dev/null +++ b/lib/update-serial.php @@ -0,0 +1,59 @@ +. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function update_serial($db, $domainId) { + + $db->autocommit(false); + $db->begin_transaction(); + + $stmt = $db->prepare("SELECT content FROM records WHERE type='SOA' AND domain_id=?"); + $stmt->bind_param("i", $domainId); + $stmt->execute(); + $stmt->bind_result($content); + $stmt->fetch(); + $stmt->close(); + + $content = explode(" ", $content); + + $serial = $content[2]; + + $currentSerialDate = (int)($serial / 100); + $currentSerialSequence = $serial % 100; + + $currentDate = (int)date("Ymd"); + + if($currentDate != $currentSerialDate) { + $newSerial = $currentDate . "00"; + } else { + $newSerialSequence = ($currentSerialSequence+1)%100 . ""; + $newSerialSequence = str_pad($newSerialSequence, 2, "0", STR_PAD_LEFT); + $newSerial = $currentDate . "" . $newSerialSequence; + } + + $content[2] = $newSerial; + + + $newsoa = implode(" ", $content); + + $stmt = $db->prepare("UPDATE records SET content=? WHERE type='SOA' AND domain_id=?"); + $stmt->bind_param("si", $newsoa, $domainId); + $stmt->execute(); + + $db->commit(); + +} \ No newline at end of file