mirror of
https://github.com/VinylDNS/vinyldns
synced 2025-08-22 02:02:14 +00:00
- Simplify build config - Add TTY check to Makefiles for running Docker containers - Update `fs2` to latest patch - Update `sbt-assembly` plugin - Update portal to remove chatty console - Update portal scripts to add license header - Update prepare-portal/Gruntfile to combine js and css where applicable - Remove unused gentelella files from final portal artifact - Add support for shared zones to quickstart/docker images - Consolidate built artifacts in `artifacts/` to make eventual release easier
227 lines
11 KiB
JavaScript
227 lines
11 KiB
JavaScript
/*
|
||
* Copyright 2018 Comcast Cable Communications Management, LLC
|
||
*
|
||
* 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() {
|
||
'use strict';
|
||
|
||
angular.module('dns-change')
|
||
.controller('DnsChangeNewController', function($scope, $log, $location, $timeout, $q, dnsChangeService, utilityService, groupsService){
|
||
groupsService.getGroups()
|
||
.then(function (results) {
|
||
$scope.myGroups = results['data']['groups'];
|
||
if ($scope.myGroups.length == 1) {
|
||
$scope.newBatch.ownerGroupId = $scope.myGroups[0]['id']
|
||
}
|
||
})
|
||
.catch(function (error) {
|
||
handleError(error, 'groupsService::getGroups-failure');
|
||
});
|
||
|
||
$scope.batch = {};
|
||
var tomorrow = moment().startOf('hour').add(1, 'day');
|
||
$scope.newBatch = {comments: "", changes: [{changeType: "Add", type: "A+PTR"}], scheduledTime: tomorrow.format('LL hh:mm A')};
|
||
$scope.alerts = [];
|
||
$scope.batchChangeErrors = false;
|
||
$scope.ownerGroupError = false;
|
||
$scope.softErrors = false;
|
||
$scope.formStatus = "pendingSubmit";
|
||
$scope.scheduledOption = false;
|
||
$scope.allowManualReview = false;
|
||
$scope.confirmationPrompt = "Are you sure you want to submit this batch change request?";
|
||
$scope.manualReviewEnabled;
|
||
|
||
$scope.addSingleChange = function() {
|
||
$scope.newBatch.changes.push({changeType: "Add", type: "A+PTR"});
|
||
var changesLength = $scope.newBatch.changes.length;
|
||
$timeout(function() {document.getElementsByClassName("changeType")[changesLength - 1].focus()});
|
||
};
|
||
|
||
$scope.cancelSubmit = function() {
|
||
$scope.formStatus = "pendingSubmit";
|
||
$scope.allowManualReview = false;
|
||
$scope.confirmationPrompt = "Are you sure you want to submit this batch change request?";
|
||
};
|
||
|
||
$scope.confirmSubmit = function(form) {
|
||
if(form.$invalid){
|
||
form.$setSubmitted();
|
||
$scope.formStatus = "pendingSubmit";
|
||
}
|
||
};
|
||
|
||
$scope.clearRecordData = function(changeIndex) {
|
||
delete $scope.newBatch.changes[changeIndex].record;
|
||
};
|
||
|
||
$scope.createBatchChange = function() {
|
||
//flag to prevent multiple clicks until previous promise has resolved.
|
||
$scope.processing = true;
|
||
|
||
var payload = $scope.newBatch;
|
||
|
||
function formatData(payload) {
|
||
if (!$scope.newBatch.ownerGroupId) {
|
||
delete payload.ownerGroupId
|
||
}
|
||
|
||
if ($scope.scheduledOption && $scope.newBatch.scheduledTime) {
|
||
payload.scheduledTime = moment($scope.newBatch.scheduledTime, 'LL hh:mm A').utc().format();
|
||
} else {
|
||
delete payload.scheduledTime;
|
||
}
|
||
for (var i = 0; i < payload.changes.length; i++) {
|
||
var entry = payload.changes[i]
|
||
if(entry.type == 'A+PTR' || entry.type == 'AAAA+PTR') {
|
||
entry.type = entry.type.slice(0, -4);
|
||
var newEntry = {changeType: entry.changeType, type: "PTR", ttl: entry.ttl, inputName: entry.record.address, record: {ptrdname: entry.inputName}}
|
||
payload.changes.splice(i+1, 0, newEntry)
|
||
}
|
||
if(entry.changeType == 'DeleteRecordSet' && entry.record) {
|
||
var recordDataEmpty = true;
|
||
for (var attr in entry.record) {
|
||
if (entry.record[attr] != undefined && entry.record[attr].toString().length > 0) {
|
||
recordDataEmpty = false
|
||
}
|
||
}
|
||
if (recordDataEmpty) {
|
||
delete entry.record
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
function success(response) {
|
||
var alert = utilityService.success('Successfully created DNS Change', response, 'createBatchChange: createBatchChange successful');
|
||
$scope.alerts.push(alert);
|
||
$timeout(function(){
|
||
location.href = "/dnschanges/" + response.data.id;
|
||
}, 2000);
|
||
$scope.batch = response.data;
|
||
}
|
||
|
||
formatData(payload);
|
||
|
||
return dnsChangeService.createBatchChange(payload, true)
|
||
.then(success)
|
||
.catch(function (error){
|
||
if(payload.scheduledTime) {
|
||
$scope.newBatch.scheduledTime = moment(payload.scheduledTime).local().format('LL hh:mm A')
|
||
}
|
||
if(error.data.errors || error.status !== 400 || typeof error.data == "string"){
|
||
handleError(error, 'dnsChangesService::createBatchChange-failure');
|
||
} else {
|
||
$scope.newBatch.changes = error.data;
|
||
$scope.batchChangeErrors = true;
|
||
$scope.listOfErrors = error.data.flatMap(d => d.errors)
|
||
$scope.ownerGroupError = $scope.listOfErrors.some(e => e.includes('owner group ID must be specified for record'));
|
||
$scope.softErrors = false;
|
||
$scope.formStatus = "pendingSubmit";
|
||
$scope.alerts.push({type: 'danger', content: 'Errors found. Please correct and submit again.'});
|
||
}
|
||
});
|
||
};
|
||
|
||
$scope.deleteSingleChange = function(changeNumber) {
|
||
$('.batch-change-delete').blur();
|
||
$scope.newBatch.changes.splice(changeNumber, 1);
|
||
};
|
||
|
||
$scope.submitChange = function(manualReviewEnabled) {
|
||
$scope.formStatus = "pendingConfirm";
|
||
$scope.manualReviewEnabled = manualReviewEnabled;
|
||
}
|
||
|
||
$scope.getLocalTimeZone = function() {
|
||
return new Date().toLocaleString('en-us', {timeZoneName:'short'}).split(' ')[3];
|
||
}
|
||
|
||
function handleError(error, type) {
|
||
var alert = utilityService.failure(error, type);
|
||
$scope.alerts.push(alert);
|
||
}
|
||
|
||
$scope.uploadCSV = function(file) {
|
||
parseFile(file).then(function(dataLength){
|
||
$scope.alerts.push({type: 'success', content: 'Successfully imported ' + dataLength + ' changes.' });
|
||
}, function(error) {
|
||
$scope.alerts.push({type: 'danger', content: error});
|
||
});
|
||
|
||
function parseFile(file) {
|
||
return $q(function(resolve, reject) {
|
||
var reader = new FileReader();
|
||
reader.onload = function(e) {
|
||
var rows = e.target.result.split("\n");
|
||
if (rows[0].trim() == "Change Type,Record Type,Input Name,TTL,Record Data") {
|
||
$scope.newBatch.changes = [];
|
||
for(var i = 1; i < rows.length; i++) {
|
||
var lengthCheck = rows[i].replace(/,+/g, '').trim().length
|
||
if (lengthCheck == 0) { continue; }
|
||
parseRow(rows[i])
|
||
}
|
||
$scope.$apply()
|
||
resolve($scope.newBatch.changes.length);
|
||
} else {
|
||
reject("Import failed. Not a valid file. File should be of ‘.csv’ type.");
|
||
}
|
||
}
|
||
reader.readAsText(file);
|
||
});
|
||
}
|
||
|
||
function parseRow(row) {
|
||
var change = {};
|
||
var headers = ["changeType", "type", "inputName", "ttl", "record"];
|
||
var rowContent = row.split(",");
|
||
for (var j = 0; j < rowContent.length; j++) {
|
||
if (headers[j] == "changeType") {
|
||
if (rowContent[j].match(/add/i)) {
|
||
change[headers[j]] = "Add"
|
||
} else if (rowContent[j].match(/delete/i)) {
|
||
change[headers[j]] = "DeleteRecordSet"
|
||
}
|
||
} else if (headers[j] == "type") {
|
||
change[headers[j]] = rowContent[j].trim().toUpperCase()
|
||
} else if (headers[j] == "ttl") {
|
||
change[headers[j]] = parseInt(rowContent[j].trim())
|
||
} else if (headers[j] == "record"){
|
||
if (change["type"] == "A" || change["type"] == "AAAA" || change["type"] == "A+PTR" || change["type"] == "AAAA+PTR"){
|
||
change[headers[j]] = {"address": rowContent[j].trim()}
|
||
} else if (change["type"] == "CNAME") {
|
||
change[headers[j]] = {"cname": rowContent[j].trim()}
|
||
} else if (change["type"] == "PTR") {
|
||
change[headers[j]] = {"ptrdname": rowContent[j].trim()}
|
||
}
|
||
} else {
|
||
change[headers[j]] = rowContent[j].trim()
|
||
}
|
||
}
|
||
$scope.newBatch.changes.push(change);
|
||
}
|
||
}
|
||
|
||
$('input[name="scheduledTime"]').daterangepicker({
|
||
singleDatePicker: true,
|
||
timePicker: true,
|
||
startDate: tomorrow,
|
||
locale: {
|
||
format: 'LL hh:mm A'
|
||
}
|
||
});
|
||
|
||
});
|
||
})();
|