mirror of
https://github.com/cwinfo/powerdns-admin.git
synced 2024-12-04 19:15:30 +00:00
Adjustment in domain template feature to work with python3
This commit is contained in:
commit
29d1cf4117
104
app/models.py
104
app/models.py
@ -18,6 +18,8 @@ from flask_login import AnonymousUserMixin
|
||||
from app import app, db
|
||||
from app.lib import utils
|
||||
from app.lib.log import logger
|
||||
|
||||
# LOG CONFIGS
|
||||
logging = logger('MODEL', app.config['LOG_LEVEL'], app.config['LOG_FILE']).config()
|
||||
|
||||
if 'LDAP_TYPE' in app.config.keys():
|
||||
@ -894,7 +896,7 @@ class Record(object):
|
||||
list_deleted_records = [x for x in list_current_records if x not in list_new_records]
|
||||
|
||||
# convert back to list of hash
|
||||
deleted_records = [x for x in current_records if [x['name'],x['type']] in list_deleted_records and x['type'] in app.config['RECORDS_ALLOW_EDIT']]
|
||||
deleted_records = [x for x in current_records if [x['name'],x['type']] in list_deleted_records and (x['type'] in app.config['RECORDS_ALLOW_EDIT'] and x['type'] != 'SOA')]
|
||||
|
||||
# return a tuple
|
||||
return deleted_records, new_records
|
||||
@ -1042,12 +1044,14 @@ class Record(object):
|
||||
})
|
||||
|
||||
postdata_for_new = {"rrsets": final_records}
|
||||
|
||||
logging.info(postdata_for_new)
|
||||
logging.info(postdata_for_delete)
|
||||
logging.info(urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)))
|
||||
try:
|
||||
headers = {}
|
||||
headers['X-API-Key'] = PDNS_API_KEY
|
||||
jdata1 = utils.fetch_json(urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=postdata_for_delete)
|
||||
jdata2 = utils.fetch_json(urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain), headers=headers, method='PATCH', data=postdata_for_new)
|
||||
jdata1 = utils.fetch_json(urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)), headers=headers, method='PATCH', data=postdata_for_delete)
|
||||
jdata2 = utils.fetch_json(urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)), headers=headers, method='PATCH', data=postdata_for_new)
|
||||
|
||||
if 'error' in jdata2.keys():
|
||||
logging.error('Cannot apply record changes.')
|
||||
@ -1058,7 +1062,7 @@ class Record(object):
|
||||
logging.info('Record was applied successfully.')
|
||||
return {'status': 'ok', 'msg': 'Record was applied successfully'}
|
||||
except Exception as e:
|
||||
logging.error("Cannot apply record changes to domain %s. DETAIL: %s" % (e, domain))
|
||||
logging.error("Cannot apply record changes to domain {0}. DETAIL: {1}".format(e, domain))
|
||||
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
|
||||
|
||||
def auto_ptr(self, domain, new_records, deleted_records):
|
||||
@ -1127,12 +1131,18 @@ class Record(object):
|
||||
logging.error("Cannot remove record %s/%s/%s from domain %s" % (self.name, self.type, self.data, domain))
|
||||
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
|
||||
|
||||
def is_allowed(self):
|
||||
def is_allowed_edit(self):
|
||||
"""
|
||||
Check if record is allowed to edit/removed
|
||||
Check if record is allowed to edit
|
||||
"""
|
||||
return self.type in app.config['RECORDS_ALLOW_EDIT']
|
||||
|
||||
def is_allowed_delete(self):
|
||||
"""
|
||||
Check if record is allowed to removed
|
||||
"""
|
||||
return (self.type in app.config['RECORDS_ALLOW_EDIT'] and self.type != 'SOA')
|
||||
|
||||
def exists(self, domain):
|
||||
"""
|
||||
Check if record is present within domain records, and if it's present set self to found record
|
||||
@ -1361,3 +1371,83 @@ class Setting(db.Model):
|
||||
logging.debug(traceback.format_exec())
|
||||
db.session.rollback()
|
||||
return False
|
||||
|
||||
|
||||
class DomainTemplate(db.Model):
|
||||
__tablename__ = "domain_template"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(255), index=True, unique=True)
|
||||
description = db.Column(db.String(255))
|
||||
records = db.relationship('DomainTemplateRecord', back_populates='template', cascade="all, delete-orphan")
|
||||
|
||||
def __repr__(self):
|
||||
return '<DomainTemplate %s>' % self.name
|
||||
|
||||
def __init__(self, name=None, description=None):
|
||||
self.id = None
|
||||
self.name = name
|
||||
self.description = description
|
||||
|
||||
def replace_records(self, records):
|
||||
try:
|
||||
self.records = []
|
||||
for record in records:
|
||||
self.records.append(record)
|
||||
db.session.commit()
|
||||
return {'status': 'ok', 'msg': 'Template records have been modified'}
|
||||
except Exception as e:
|
||||
logging.error('Cannot create template records Error: {0}'.format(e))
|
||||
db.session.rollback()
|
||||
return {'status': 'error', 'msg': 'Can not create template records'}
|
||||
|
||||
def create(self):
|
||||
try:
|
||||
db.session.add(self)
|
||||
db.session.commit()
|
||||
return {'status': 'ok', 'msg': 'Template has been created'}
|
||||
except Exception as e:
|
||||
logging.error('Can not update domain template table. Error: {0}'.format(e))
|
||||
db.session.rollback()
|
||||
return {'status': 'error', 'msg': 'Can not update domain template table'}
|
||||
|
||||
def delete_template(self):
|
||||
try:
|
||||
self.records = []
|
||||
db.session.delete(self)
|
||||
db.session.commit()
|
||||
return {'status': 'ok', 'msg': 'Template has been deleted'}
|
||||
except Exception as e:
|
||||
logging.error('Can not delete domain template. Error: {0}'.format(e))
|
||||
db.session.rollback()
|
||||
return {'status': 'error', 'msg': 'Can not delete domain template'}
|
||||
|
||||
|
||||
class DomainTemplateRecord(db.Model):
|
||||
__tablename__ = "domain_template_record"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(255))
|
||||
type = db.Column(db.String(64))
|
||||
ttl = db.Column(db.Integer)
|
||||
data = db.Column(db.String(255))
|
||||
status = db.Column(db.Boolean)
|
||||
template_id = db.Column(db.Integer, db.ForeignKey('domain_template.id'))
|
||||
template = db.relationship('DomainTemplate', back_populates='records')
|
||||
|
||||
def __repr__(self):
|
||||
return '<DomainTemplateRecord %i>' % self.id
|
||||
|
||||
def __init__(self, id=None, name=None, type=None, ttl=None, data=None, status=None):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.ttl = ttl
|
||||
self.data = data
|
||||
self.status = status
|
||||
|
||||
def apply(self):
|
||||
try:
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
logging.error('Can not update domain template table. Error: {0}'.format(e))
|
||||
db.session.rollback()
|
||||
return {'status': 'error', 'msg': 'Can not update domain template table'}
|
||||
|
@ -127,6 +127,7 @@
|
||||
<li><a href="{{ url_for('domain_add') }}"><i class="fa fa-plus"></i> <span>New Domain</span></a></li>
|
||||
<li class="header">ADMINISTRATION</li>
|
||||
<li><a href="{{ url_for('admin') }}"><i class="fa fa-wrench"></i> <span>Admin Console</span></a></li>
|
||||
<li><a href="{{ url_for('templates') }}"><i class="fa fa-clone"></i> <span>Domain Templates</span></a></li>
|
||||
<li><a href="{{ url_for('admin_manageuser') }}"><i class="fa fa-users"></i> <span>Users</span></a></li>
|
||||
<li><a href="{{ url_for('admin_history') }}"><i class="fa fa-calendar"></i> <span>History</span></a></li>
|
||||
<li><a href="{{ url_for('admin_settings') }}"><i class="fa fa-cog"></i> <span>Settings</span></a></li>
|
||||
|
@ -203,6 +203,31 @@
|
||||
var domain = $(this).prop('id');
|
||||
getdnssec($SCRIPT_ROOT + '/domain/' + domain + '/dnssec');
|
||||
});
|
||||
|
||||
$(document.body).on("click", ".button_template", function (e) {
|
||||
var modal = $("#modal_template");
|
||||
var domain = $(this).prop('id');
|
||||
var form = " <label for=\"template_name\">Template name</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"template_name\" id=\"template_name\" placeholder=\"Enter a valid template name (required)\"> \
|
||||
<label for=\"template_description\">Template description</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"template_description\" id=\"template_description\" placeholder=\"Enter a template description (optional)\"> \
|
||||
<input id=\"domain\" name=\"domain\" type=\"hidden\" value=\""+domain+"\"> \
|
||||
";
|
||||
modal.find('.modal-body p').html(form);
|
||||
modal.find('#button_save').click(function() {
|
||||
var data = {};
|
||||
data['name'] = modal.find('#template_name').val();
|
||||
data['description'] = modal.find('#template_description').val();
|
||||
data['domain'] = modal.find('#domain').val();
|
||||
applyChanges(data, $SCRIPT_ROOT + "{{ url_for('create_template_from_zone') }}", true);
|
||||
modal.modal('hide');
|
||||
})
|
||||
modal.find('#button_close').click(function() {
|
||||
modal.modal('hide');
|
||||
})
|
||||
|
||||
modal.modal('show');
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% block modals %}
|
||||
@ -252,4 +277,27 @@
|
||||
<!-- /.modal-dialog -->
|
||||
</div>
|
||||
<!-- /.modal -->
|
||||
<div class="modal fade modal-primary" id="modal_template">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"
|
||||
aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Clone to template</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-flat btn-default pull-left"
|
||||
id="button_close" data-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-flat btn-primary" id="button_save">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.modal-content -->
|
||||
</div>
|
||||
<!-- /.modal-dialog -->
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -27,14 +27,11 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro actions(domain) %}
|
||||
{% if current_user.role.name !='Administrator' %}
|
||||
<td width="6%">
|
||||
<button type="button" class="btn btn-flat btn-success" onclick="window.location.href='{{ url_for('domain', domain_name=domain.name) }}'">
|
||||
Manage <i class="fa fa-cog"></i>
|
||||
{% if current_user.role.name =='Administrator' %}
|
||||
<td width="25%">
|
||||
<button type="button" class="btn btn-flat btn-success button_template" id="{{ domain.name }}">
|
||||
Template <i class="fa fa-clone"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% else %}
|
||||
<td width="20%">
|
||||
<button type="button" class="btn btn-flat btn-success" onclick="window.location.href='{{ url_for('domain', domain_name=domain.name) }}'">
|
||||
Manage <i class="fa fa-cog"></i>
|
||||
</button>
|
||||
@ -42,5 +39,11 @@
|
||||
Admin <i class="fa fa-cog"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% else %}
|
||||
<td width="6%">
|
||||
<button type="button" class="btn btn-flat btn-success" onclick="window.location.href='{{ url_for('domain', domain_name=domain.name) }}'">
|
||||
Manage <i class="fa fa-cog"></i>
|
||||
</button>
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
@ -70,25 +70,23 @@
|
||||
</td>
|
||||
{% if domain.type != 'Slave' %}
|
||||
<td width="6%">
|
||||
{% if record.is_allowed() %}
|
||||
{% if record.is_allowed_edit() %}
|
||||
<button type="button" class="btn btn-flat btn-warning button_edit" id="{{ (record.name,domain.name)|display_record_name }}">Edit <i class="fa fa-edit"></i></button>
|
||||
{% else %}
|
||||
<button type="button" class="btn btn-flat btn-warning""> <i class="fa fa-exclamation-circle"></i> </button>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td width="6%">
|
||||
{% if record.is_allowed() %}
|
||||
{% if record.is_allowed_delete() %}
|
||||
<button type="button" class="btn btn-flat btn-danger button_delete" id="{{ (record.name,domain.name)|display_record_name }}">Delete <i class="fa fa-trash"></i></button>
|
||||
{% else %}
|
||||
<button type="button" class="btn btn-flat btn-warning""> <i class="fa fa-exclamation-circle"></i> </button>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<td width="6%">
|
||||
<button type="button" class="btn btn-flat btn-warning""> <i class="fa fa-exclamation-circle"></i> </button>
|
||||
<button type="button" class="btn btn-flat btn-warning"> <i class="fa fa-exclamation-circle"></i> </button>
|
||||
</td>
|
||||
<td width="6%">
|
||||
<button type="button" class="btn btn-flat btn-warning""> <i class="fa fa-exclamation-circle"></i> </button>
|
||||
</td>
|
||||
<button type="button" class="btn btn-flat btn-warning"> <i class="fa fa-exclamation-circle"></i> </button>
|
||||
</td>
|
||||
{% endif %}
|
||||
</td>
|
||||
<!-- hidden column that we can sort on -->
|
||||
|
@ -47,6 +47,15 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Select a template</label>
|
||||
<select class="form-control" id="domain_template" name="domain_template">
|
||||
<option value="0">No template</option>
|
||||
{% for template in templates %}
|
||||
<option value="{{ template.id }}">{{ template.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" style="display: none;" id="domain_master_address_div">
|
||||
<input type="text" class="form-control" name="domain_master_address" id="domain_master_address" placeholder="Enter valid master ip addresses (separated by commas)">
|
||||
</div>
|
||||
|
116
app/templates/template.html
Normal file
116
app/templates/template.html
Normal file
@ -0,0 +1,116 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}<title>DNS Control Panel - Templates</title>{% endblock %}
|
||||
|
||||
{% block dashboard_stat %}
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
Templates
|
||||
<small>List</small>
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{{ url_for('templates') }}"><i class="fa fa-dashboard"></i> Templates</a></li>
|
||||
<li class="active">List</li>
|
||||
</ol>
|
||||
</section>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<!-- Main content -->
|
||||
<section class="content">
|
||||
{% with errors = get_flashed_messages(category_filter=["error"]) %} {% if errors %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-danger alert-dismissible">
|
||||
<button type="button" class="close" data-dismiss="alert"
|
||||
aria-hidden="true">×</button>
|
||||
<h4>
|
||||
<i class="icon fa fa-ban"></i> Error!
|
||||
</h4>
|
||||
<div class="alert-message block-message error">
|
||||
<a class="close" href="#">x</a>
|
||||
<ul>
|
||||
{%- for msg in errors %}
|
||||
<li>{{ msg }}</li> {% endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %} {% endwith %}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title">Templates</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<a href="{{ url_for('create_template') }}">
|
||||
<button type="button" class="btn btn-flat btn-primary pull-left">
|
||||
Create Template <i class="fa fa-plus"></i>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<table id="tbl_template_list" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Number of Records</th>
|
||||
<th width="20%">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for template in templates %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ url_for('edit_template', template=template.name) }}"><strong>{{ template.name }}</strong></a>
|
||||
</td>
|
||||
<td>
|
||||
{{ template.description }}
|
||||
</td>
|
||||
<td>
|
||||
{{ template.records|count }}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ url_for('edit_template', template=template.name) }}">
|
||||
<button type="button" class="btn btn-flat btn-warning button_edit" id="">
|
||||
Edit <i class="fa fa-edit"></i>
|
||||
</button>
|
||||
</a>
|
||||
<a href="{{ url_for('delete_template', template=template.name) }}">
|
||||
<button type="button" class="btn btn-flat btn-danger button_delete" id="">
|
||||
Delete <i class="fa fa-trash"></i>
|
||||
</button>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
</section>
|
||||
<!-- /.content -->
|
||||
{% endblock %}
|
||||
{% block extrascripts %}
|
||||
<script>
|
||||
// set up history data table
|
||||
$("#tbl_template_list").DataTable({
|
||||
"paging" : true,
|
||||
"lengthChange" : true,
|
||||
"searching" : true,
|
||||
"ordering" : true,
|
||||
"info" : false,
|
||||
"autoWidth" : false
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% block modals %}
|
||||
{% endblock %}
|
104
app/templates/template_add.html
Normal file
104
app/templates/template_add.html
Normal file
@ -0,0 +1,104 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}<title>DNS Control Panel - Create Template</title>{% endblock %}
|
||||
|
||||
{% block dashboard_stat %}
|
||||
<!-- Content Header (Page header) -->
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
Template
|
||||
<small>Create</small>
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{{ url_for('templates') }}"><i class="fa fa-dashboard"></i> Templates</a></li>
|
||||
<li class="active">Create</li>
|
||||
</ol>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="content">
|
||||
{% with errors = get_flashed_messages(category_filter=["error"]) %} {%
|
||||
if errors %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-danger alert-dismissible">
|
||||
<button type="button" class="close" data-dismiss="alert"
|
||||
aria-hidden="true">×</button>
|
||||
<h4>
|
||||
<i class="icon fa fa-ban"></i> Error!
|
||||
</h4>
|
||||
<div class="alert-message block-message error">
|
||||
<a class="close" href="#">x</a>
|
||||
<ul>
|
||||
{%- for msg in errors %}
|
||||
<li>{{ msg }}</li> {% endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %} {% endwith %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Create new template</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<!-- form start -->
|
||||
<form role="form" method="post"
|
||||
action="{{ url_for('create_template') }}">
|
||||
<div class="box-body">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="name" id="name"
|
||||
placeholder="Enter a valid template name (required)">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="description"
|
||||
id="description"
|
||||
placeholder="Enter a template description (optional)">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<button type="submit" class="btn btn-flat btn-primary">Submit</button>
|
||||
<button type="button" class="btn btn-flat btn-default"
|
||||
onclick="window.location.href='{{ url_for('templates') }}'">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Help with creating a new template</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Template name</dt>
|
||||
<dd>Enter your template name, this is the name of the template that
|
||||
will be shown to users. The name should not have any spaces but
|
||||
can have symbols.</dd>
|
||||
<dt>Template description</dt>
|
||||
<dd>Enter your template description, this is to help better
|
||||
identify the template.</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
{% block extrascripts %}
|
||||
<script>
|
||||
$("input[name=radio_type]").change(function() {
|
||||
var type = $(this).val();
|
||||
if (type == "slave") {
|
||||
$("#domain_master_address_div").show();
|
||||
} else {
|
||||
$("#domain_master_address_div").hide();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
415
app/templates/template_edit.html
Normal file
415
app/templates/template_edit.html
Normal file
@ -0,0 +1,415 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}<title>DNS Control Panel - Edit Template</title>{% endblock %}
|
||||
|
||||
{% block dashboard_stat %}
|
||||
<section class="content-header">
|
||||
<h1>
|
||||
Edit template <small>{{ template }}</small>
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{{ url_for('dashboard') }}"><i
|
||||
class="fa fa-dashboard"></i> Home</a></li>
|
||||
<li>Templates</li>
|
||||
<li class="active">{{ template }}</li>
|
||||
</ol>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="content">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title">Manage Template Records for {{ template }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<button type="button" class="btn btn-flat btn-primary pull-left button_add_record" id="{{ template }}">
|
||||
Add Record <i class="fa fa-plus"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-flat btn-primary pull-right button_apply_changes" id="{{ template }}">
|
||||
Apply Changes <i class="fa fa-floppy-o"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<table id="tbl_records" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Status</th>
|
||||
<th>TTL</th>
|
||||
<th>Data</th>
|
||||
<th>Edit</th>
|
||||
<th>Delete</th>
|
||||
<th>ID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for record in records %}
|
||||
<tr class="odd row_record" id="{{ record.name }}">
|
||||
<td>
|
||||
{{ record.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ record.type }}
|
||||
</td>
|
||||
<td>
|
||||
{{ record.status }}
|
||||
</td>
|
||||
<td>
|
||||
{{ record.ttl }}
|
||||
</td>
|
||||
<td class="length-break">
|
||||
{{ record.data }}
|
||||
</td>
|
||||
<td width="6%">
|
||||
<button type="button" class="btn btn-flat btn-warning button_edit" id="{{ record.name }}">
|
||||
Edit <i class="fa fa-edit"></i>
|
||||
</button>
|
||||
</td>
|
||||
<td width="6%">
|
||||
<button type="button" class="btn btn-flat btn-danger button_delete" id="{{ record.name }}">
|
||||
Delete <i class="fa fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
{{ record.id }}
|
||||
</td>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
{% block extrascripts %}
|
||||
<script>
|
||||
// superglobals
|
||||
window.records_allow_edit = {{ editable_records|tojson }};
|
||||
window.nEditing = null;
|
||||
window.nNew = false;
|
||||
|
||||
// set up user data table
|
||||
$("#tbl_records").DataTable({
|
||||
"paging" : true,
|
||||
"lengthChange" : true,
|
||||
"searching" : true,
|
||||
"ordering" : true,
|
||||
"info" : true,
|
||||
"autoWidth" : false,
|
||||
{% if default_record_table_size_setting in ['5','15','20'] %}
|
||||
"lengthMenu": [ [5, 15, 20, -1],
|
||||
[5, 15, 20, "All"]],
|
||||
{% else %}
|
||||
"lengthMenu": [ [5, 15, 20, {{ default_record_table_size_setting }}, -1],
|
||||
[5, 15, 20, {{ default_record_table_size_setting }}, "All"]],
|
||||
{% endif %}
|
||||
"pageLength": {{ default_record_table_size_setting }},
|
||||
"language": {
|
||||
"lengthMenu": " _MENU_ records"
|
||||
},
|
||||
"retrieve" : true,
|
||||
"columnDefs": [{
|
||||
"targets": [ 7 ],
|
||||
"visible": false,
|
||||
"searchable": false
|
||||
}]
|
||||
|
||||
});
|
||||
|
||||
// handle delete button
|
||||
$(document.body).on("click", ".button_delete", function(e) {
|
||||
e.stopPropagation();
|
||||
var modal = $("#modal_delete");
|
||||
var table = $("#tbl_records").DataTable();
|
||||
var record = $(this).prop('id');
|
||||
var nRow = $(this).parents('tr')[0];
|
||||
var info = "Are you sure you want to delete " + record + "?";
|
||||
modal.find('.modal-body p').text(info);
|
||||
modal.find('#button_delete_confirm').click(function() {
|
||||
table.row(nRow).remove().draw();
|
||||
modal.modal('hide');
|
||||
})
|
||||
modal.modal('show');
|
||||
|
||||
});
|
||||
// handle edit button
|
||||
$(document.body).on("click", ".button_edit, .row_record", function(e) {
|
||||
e.stopPropagation();
|
||||
if ($(this).is('tr')) {
|
||||
var nRow = $(this)[0];
|
||||
} else {
|
||||
var nRow = $(this).parents('tr')[0];
|
||||
}
|
||||
var table = $("#tbl_records").DataTable();
|
||||
|
||||
if (nEditing == nRow) {
|
||||
/* click on row already being edited, do nothing */
|
||||
} else if (nEditing !== null && nEditing != nRow && nNew == false) {
|
||||
/* Currently editing - but not this row - restore the old before continuing to edit mode */
|
||||
restoreRow(table, nEditing);
|
||||
editRow(table, nRow);
|
||||
nEditing = nRow;
|
||||
} else if (nNew == true) {
|
||||
/* adding a new row, delete it and start editing */
|
||||
table.row(nEditing).remove().draw();
|
||||
nNew = false;
|
||||
editRow(table, nRow);
|
||||
nEditing = nRow;
|
||||
} else {
|
||||
/* No edit in progress - let's start one */
|
||||
editRow(table, nRow);
|
||||
nEditing = nRow;
|
||||
}
|
||||
});
|
||||
|
||||
// handle apply changes button
|
||||
$(document.body).on("click",".button_apply_changes", function() {
|
||||
var modal = $("#modal_apply_changes");
|
||||
var table = $("#tbl_records").DataTable();
|
||||
var template = $(this).prop('id');
|
||||
var info = "Are you sure you want to apply your changes?";
|
||||
modal.find('.modal-body p').text(info);
|
||||
modal.find('#button_apply_confirm').click(function() {
|
||||
var data = getTableData(table);
|
||||
applyChanges(data, '/template/' + template + '/apply', true);
|
||||
modal.modal('hide');
|
||||
})
|
||||
modal.modal('show');
|
||||
|
||||
});
|
||||
|
||||
// handle add record button
|
||||
$(document.body).on("click", ".button_add_record", function (e) {
|
||||
if (nNew || nEditing) {
|
||||
// TODO: replace this alert with modal
|
||||
alert("Previous record not saved. Please save it before adding more record.")
|
||||
return;
|
||||
}
|
||||
var table = $("#tbl_records").DataTable();
|
||||
|
||||
var aiNew = table.row.add(['', 'A', 'Active', 3600, '', '', '', '']).draw();
|
||||
var nRow = aiNew.index();
|
||||
editRow(table, nRow);
|
||||
nEditing = nRow;
|
||||
nNew = true;
|
||||
});
|
||||
|
||||
//handle cancel button
|
||||
$(document.body).on("click", ".button_cancel", function (e) {
|
||||
e.stopPropagation();
|
||||
var oTable = $("#tbl_records").DataTable();
|
||||
if (nNew) {
|
||||
oTable.row(nEditing).remove().draw();
|
||||
nEditing = null;
|
||||
nNew = false;
|
||||
} else {
|
||||
restoreRow(oTable, nEditing);
|
||||
nEditing = null;
|
||||
}
|
||||
});
|
||||
|
||||
//handle save button
|
||||
$(document.body).on("click", ".button_save", function (e) {
|
||||
e.stopPropagation();
|
||||
var table = $("#tbl_records").DataTable();
|
||||
saveRow(table, nEditing);
|
||||
nEditing = null;
|
||||
nNew = false;
|
||||
});
|
||||
|
||||
{% if record_helper_setting %}
|
||||
//handle wacky record types
|
||||
$(document.body).on("focus", "#current_edit_record_data", function (e) {
|
||||
var record_type = $(this).parents("tr").find('#record_type').val();
|
||||
var record_data = $(this);
|
||||
if (record_type == "MX") {
|
||||
var modal = $("#modal_custom_record");
|
||||
if (record_data.val() == "") {
|
||||
var form = " <label for=\"mx_priority\">MX Priority</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"mx_priority\" id=\"mx_priority\" placeholder=\"10\"> \
|
||||
<label for=\"mx_server\">MX Server</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"mx_server\" id=\"mx_server\" placeholder=\"postfix.example.com\"> \
|
||||
";
|
||||
} else {
|
||||
var parts = record_data.val().split(" ");
|
||||
var form = " <label for=\"mx_priority\">MX Priority</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"mx_priority\" id=\"mx_priority\" placeholder=\"10\" value=\"" + parts[0] + "\"> \
|
||||
<label for=\"mx_server\">MX Server</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"mx_server\" id=\"mx_server\" placeholder=\"postfix.example.com\" value=\"" + parts[1] + "\"> \
|
||||
";
|
||||
}
|
||||
modal.find('.modal-body p').html(form);
|
||||
modal.find('#button_save').click(function() {
|
||||
mx_server = modal.find('#mx_server').val();
|
||||
mx_priority = modal.find('#mx_priority').val();
|
||||
data = mx_priority + " " + mx_server;
|
||||
record_data.val(data);
|
||||
modal.modal('hide');
|
||||
})
|
||||
modal.modal('show');
|
||||
} else if (record_type == "SRV") {
|
||||
var modal = $("#modal_custom_record");
|
||||
if (record_data.val() == "") {
|
||||
var form = " <label for=\"srv_priority\">SRV Priority</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"srv_priority\" id=\"srv_priority\" placeholder=\"0\"> \
|
||||
<label for=\"srv_weight\">SRV Weight</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"srv_weight\" id=\"srv_weight\" placeholder=\"10\"> \
|
||||
<label for=\"srv_port\">SRV Port</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"srv_port\" id=\"srv_port\" placeholder=\"5060\"> \
|
||||
<label for=\"srv_target\">SRV Target</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"srv_target\" id=\"srv_target\" placeholder=\"sip.example.com\"> \
|
||||
";
|
||||
} else {
|
||||
var parts = record_data.val().split(" ");
|
||||
var form = " <label for=\"srv_priority\">SRV Priority</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"srv_priority\" id=\"srv_priority\" placeholder=\"0\" value=\"" + parts[0] + "\"> \
|
||||
<label for=\"srv_weight\">SRV Weight</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"srv_weight\" id=\"srv_weight\" placeholder=\"10\" value=\"" + parts[1] + "\"> \
|
||||
<label for=\"srv_port\">SRV Port</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"srv_port\" id=\"srv_port\" placeholder=\"5060\" value=\"" + parts[2] + "\"> \
|
||||
<label for=\"srv_target\">SRV Target</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"srv_target\" id=\"srv_target\" placeholder=\"sip.example.com\" value=\"" + parts[3] + "\"> \
|
||||
";
|
||||
}
|
||||
modal.find('.modal-body p').html(form);
|
||||
modal.find('#button_save').click(function() {
|
||||
srv_priority = modal.find('#srv_priority').val();
|
||||
srv_weight = modal.find('#srv_weight').val();
|
||||
srv_port = modal.find('#srv_port').val();
|
||||
srv_target = modal.find('#srv_target').val();
|
||||
data = srv_priority + " " + srv_weight + " " + srv_port + " " + srv_target;
|
||||
record_data.val(data);
|
||||
modal.modal('hide');
|
||||
})
|
||||
modal.modal('show');
|
||||
} else if (record_type == "SOA") {
|
||||
var modal = $("#modal_custom_record");
|
||||
if (record_data.val() == "") {
|
||||
var form = " <label for=\"soa_primaryns\">Primary Name Server</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_primaryns\" id=\"soa_primaryns\" placeholder=\"ns1.example.com\"> \
|
||||
<label for=\"soa_adminemail\">Primary Contact</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_adminemail\" id=\"soa_adminemail\" placeholder=\"admin.example.com\"> \
|
||||
<label for=\"soa_serial\">Serial</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_serial\" id=\"soa_serial\" placeholder=\"2016010101\"> \
|
||||
<label for=\"soa_zonerefresh\">Zone refresh timer</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_zonerefresh\" id=\"soa_zonerefresh\" placeholder=\"86400\"> \
|
||||
<label for=\"soa_failedzonerefresh\">Failed refresh retry timer</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_failedzonerefresh\" id=\"soa_failedzonerefresh\" placeholder=\"7200\"> \
|
||||
<label for=\"soa_zoneexpiry\">Zone expiry timer</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_zoneexpiry\" id=\"soa_zoneexpiry\" placeholder=\"604800\"> \
|
||||
<label for=\"soa_minimumttl\">Minimum TTL</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_minimumttl\" id=\"soa_minimumttl\" placeholder=\"300\"> \
|
||||
";
|
||||
} else {
|
||||
var parts = record_data.val().split(" ");
|
||||
var form = " <label for=\"soa_primaryns\">Primary Name Server</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_primaryns\" id=\"soa_primaryns\" value=\"" + parts[0] + "\"> \
|
||||
<label for=\"soa_adminemail\">Primary Contact</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_adminemail\" id=\"soa_adminemail\" value=\"" + parts[1] + "\"> \
|
||||
<label for=\"soa_serial\">Serial</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_serial\" id=\"soa_serial\" value=\"" + parts[2] + "\"> \
|
||||
<label for=\"soa_zonerefresh\">Zone refresh timer</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_zonerefresh\" id=\"soa_zonerefresh\" value=\"" + parts[3] + "\"> \
|
||||
<label for=\"soa_failedzonerefresh\">Failed refresh retry timer</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_failedzonerefresh\" id=\"soa_failedzonerefresh\" value=\"" + parts[4] + "\"> \
|
||||
<label for=\"soa_zoneexpiry\">Zone expiry timer</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_zoneexpiry\" id=\"soa_zoneexpiry\" value=\"" + parts[5] + "\"> \
|
||||
<label for=\"soa_minimumttl\">Minimum TTL</label> \
|
||||
<input type=\"text\" class=\"form-control\" name=\"soa_minimumttl\" id=\"soa_minimumttl\" value=\"" + parts[6] + "\"> \
|
||||
";
|
||||
}
|
||||
modal.find('.modal-body p').html(form);
|
||||
modal.find('#button_save').click(function() {
|
||||
soa_primaryns = modal.find('#soa_primaryns').val();
|
||||
soa_adminemail = modal.find('#soa_adminemail').val();
|
||||
soa_serial = modal.find('#soa_serial').val();
|
||||
soa_zonerefresh = modal.find('#soa_zonerefresh').val();
|
||||
soa_failedzonerefresh = modal.find('#soa_failedzonerefresh').val();
|
||||
soa_zoneexpiry = modal.find('#soa_zoneexpiry').val();
|
||||
soa_minimumttl = modal.find('#soa_minimumttl').val();
|
||||
|
||||
data = soa_primaryns + " " + soa_adminemail + " " + soa_serial + " " + soa_zonerefresh + " " + soa_failedzonerefresh + " " + soa_zoneexpiry + " " + soa_minimumttl;
|
||||
record_data.val(data);
|
||||
modal.modal('hide');
|
||||
})
|
||||
modal.modal('show');
|
||||
}
|
||||
});
|
||||
{% endif %}
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% block modals %}
|
||||
<div class="modal fade modal-warning" id="modal_delete">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"
|
||||
aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Confirmation</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-flat btn-default pull-left"
|
||||
data-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-flat btn-danger" id="button_delete_confirm">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.modal-content -->
|
||||
</div>
|
||||
<!-- /.modal-dialog -->
|
||||
</div>
|
||||
<div class="modal fade modal-primary" id="modal_apply_changes">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"
|
||||
aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Confirmation</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-flat btn-default pull-left"
|
||||
data-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-flat btn-primary" id="button_apply_confirm">Apply</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.modal-content -->
|
||||
</div>
|
||||
<!-- /.modal-dialog -->
|
||||
</div>
|
||||
<div class="modal fade modal-primary" id="modal_custom_record">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"
|
||||
aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">Custom Record</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-flat btn-primary" id="button_save">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.modal-content -->
|
||||
</div>
|
||||
<!-- /.modal-dialog -->
|
||||
</div>
|
||||
{% endblock %}
|
215
app/views.py
215
app/views.py
@ -11,17 +11,21 @@ from io import BytesIO
|
||||
import jinja2
|
||||
import qrcode as qrc
|
||||
import qrcode.image.svg as qrc_svg
|
||||
from flask import g, request, make_response, jsonify, render_template, session, redirect, url_for, send_from_directory, abort
|
||||
from flask import g, request, make_response, jsonify, render_template, session, redirect, url_for, send_from_directory, abort, flash
|
||||
from flask_login import login_user, logout_user, current_user, login_required
|
||||
from werkzeug import secure_filename
|
||||
from werkzeug.security import gen_salt
|
||||
|
||||
from .models import User, Domain, Record, Server, History, Anonymous, Setting, DomainSetting
|
||||
from .models import User, Domain, Record, Server, History, Anonymous, Setting, DomainSetting, DomainTemplate, DomainTemplateRecord
|
||||
from app import app, login_manager, github, google
|
||||
from app.lib import utils
|
||||
from app.lib.log import logger
|
||||
from app.decorators import admin_role_required, can_access_domain
|
||||
|
||||
# LOG CONFIG
|
||||
logging = logger('MODEL', app.config['LOG_LEVEL'], app.config['LOG_FILE']).config()
|
||||
|
||||
# FILTERS
|
||||
jinja2.filters.FILTERS['display_record_name'] = utils.display_record_name
|
||||
jinja2.filters.FILTERS['display_master_name'] = utils.display_master_name
|
||||
jinja2.filters.FILTERS['display_second_to_time'] = utils.display_time
|
||||
@ -436,10 +440,13 @@ def domain(domain_name):
|
||||
@login_required
|
||||
@admin_role_required
|
||||
def domain_add():
|
||||
templates = DomainTemplate.query.all()
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
domain_name = request.form.getlist('domain_name')[0]
|
||||
domain_type = request.form.getlist('radio_type')[0]
|
||||
domain_template = request.form.getlist('domain_template')[0]
|
||||
logging.info("Selected template ==== {0}".format(domain_template))
|
||||
soa_edit_api = request.form.getlist('radio_type_soa_edit_api')[0]
|
||||
|
||||
if ' ' in domain_name or not domain_name or not domain_type:
|
||||
@ -457,12 +464,28 @@ def domain_add():
|
||||
if result['status'] == 'ok':
|
||||
history = History(msg='Add domain %s' % domain_name, detail=str({'domain_type': domain_type, 'domain_master_ips': domain_master_ips}), created_by=current_user.username)
|
||||
history.add()
|
||||
if domain_template != '0':
|
||||
template = DomainTemplate.query.filter(DomainTemplate.id == domain_template).first()
|
||||
template_records = DomainTemplateRecord.query.filter(DomainTemplateRecord.template_id == domain_template).all()
|
||||
record_data = []
|
||||
for template_record in template_records:
|
||||
record_row = {'record_data': template_record.data, 'record_name': template_record.name, 'record_status': template_record.status, 'record_ttl': template_record.ttl, 'record_type': template_record.type}
|
||||
record_data.append(record_row)
|
||||
r = Record()
|
||||
result = r.apply(domain_name, record_data)
|
||||
if result['status'] == 'ok':
|
||||
history = History(msg='Applying template %s to %s, created records successfully.' % (template.name, domain_name), detail=str(result), created_by=current_user.username)
|
||||
history.add()
|
||||
else:
|
||||
history = History(msg='Applying template %s to %s, FAILED to created records.' % (template.name, domain_name), detail=str(result), created_by=current_user.username)
|
||||
history.add()
|
||||
return redirect(url_for('dashboard'))
|
||||
else:
|
||||
return render_template('errors/400.html', msg=result['msg']), 400
|
||||
except:
|
||||
logging.error(traceback.print_exc())
|
||||
return redirect(url_for('error', code=500))
|
||||
return render_template('domain_add.html')
|
||||
return render_template('domain_add.html', templates=templates)
|
||||
|
||||
|
||||
@app.route('/admin/domain/<path:domain_name>/delete', methods=['GET'])
|
||||
@ -534,7 +557,7 @@ def record_apply(domain_name):
|
||||
else:
|
||||
return make_response(jsonify( result ), 400)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
logging.error(traceback.print_exc())
|
||||
return make_response(jsonify( {'status': 'error', 'msg': 'Error when applying new changes'} ), 500)
|
||||
|
||||
|
||||
@ -557,7 +580,7 @@ def record_update(domain_name):
|
||||
else:
|
||||
return make_response(jsonify( {'status': 'error', 'msg': result['msg']} ), 500)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
logging.error(traceback.print_exc())
|
||||
return make_response(jsonify( {'status': 'error', 'msg': 'Error when applying new changes'} ), 500)
|
||||
|
||||
|
||||
@ -571,7 +594,7 @@ def record_delete(domain_name, record_name, record_type):
|
||||
if result['status'] == 'error':
|
||||
print(result['msg'])
|
||||
except:
|
||||
traceback.print_exc()
|
||||
logging.error(traceback.print_exc())
|
||||
return redirect(url_for('error', code=500)), 500
|
||||
return redirect(url_for('domain', domain_name=domain_name))
|
||||
|
||||
@ -621,10 +644,182 @@ def admin_setdomainsetting(domain_name):
|
||||
else:
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'Action not supported.' } ), 400)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
logging.error(traceback.print_exc())
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'There is something wrong, please contact Administrator.' } ), 400)
|
||||
|
||||
|
||||
@app.route('/templates', methods=['GET', 'POST'])
|
||||
@app.route('/templates/list', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
def templates():
|
||||
templates = DomainTemplate.query.all()
|
||||
return render_template('template.html', templates=templates)
|
||||
|
||||
|
||||
@app.route('/template/create', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
def create_template():
|
||||
if request.method == 'GET':
|
||||
return render_template('template_add.html')
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
name = request.form.getlist('name')[0]
|
||||
description = request.form.getlist('description')[0]
|
||||
|
||||
if ' ' in name or not name or not type:
|
||||
flash("Please correct your input", 'error')
|
||||
return redirect(url_for('create_template'))
|
||||
|
||||
if DomainTemplate.query.filter(DomainTemplate.name == name).first():
|
||||
flash("A template with the name %s already exists!" % name, 'error')
|
||||
return redirect(url_for('create_template'))
|
||||
t = DomainTemplate(name=name, description=description)
|
||||
result = t.create()
|
||||
if result['status'] == 'ok':
|
||||
history = History(msg='Add domain template %s' % name, detail=str({'name': name, 'description': description}), created_by=current_user.username)
|
||||
history.add()
|
||||
return redirect(url_for('templates'))
|
||||
else:
|
||||
flash(result['msg'], 'error')
|
||||
return redirect(url_for('create_template'))
|
||||
except:
|
||||
logging.error(traceback.print_exc())
|
||||
return redirect(url_for('error', code=500))
|
||||
return redirect(url_for('templates'))
|
||||
|
||||
|
||||
@app.route('/template/createfromzone', methods=['POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
def create_template_from_zone():
|
||||
try:
|
||||
jdata = request.json
|
||||
name = jdata['name']
|
||||
description = jdata['description']
|
||||
domain_name = jdata['domain']
|
||||
|
||||
if ' ' in name or not name or not type:
|
||||
return make_response(jsonify({'status': 'error', 'msg': 'Please correct template name'}), 500)
|
||||
|
||||
if DomainTemplate.query.filter(DomainTemplate.name == name).first():
|
||||
return make_response(jsonify({'status': 'error', 'msg': 'A template with the name %s already exists!' % name}), 500)
|
||||
|
||||
t = DomainTemplate(name=name, description=description)
|
||||
result = t.create()
|
||||
if result['status'] == 'ok':
|
||||
history = History(msg='Add domain template %s' % name, detail=str({'name': name, 'description': description}), created_by=current_user.username)
|
||||
history.add()
|
||||
|
||||
records = []
|
||||
r = Record()
|
||||
domain = Domain.query.filter(Domain.name == domain_name).first()
|
||||
if domain:
|
||||
# query domain info from PowerDNS API
|
||||
zone_info = r.get_record_data(domain.name)
|
||||
if zone_info:
|
||||
jrecords = zone_info['records']
|
||||
|
||||
if NEW_SCHEMA:
|
||||
for jr in jrecords:
|
||||
name = '@' if jr['name'] == domain_name else jr['name']
|
||||
if jr['type'] in app.config['RECORDS_ALLOW_EDIT']:
|
||||
for subrecord in jr['records']:
|
||||
|
||||
record = DomainTemplateRecord(name=name, type=jr['type'], status=True if subrecord['disabled'] else False, ttl=jr['ttl'], data=subrecord['content'])
|
||||
records.append(record)
|
||||
else:
|
||||
for jr in jrecords:
|
||||
if jr['type'] in app.config['RECORDS_ALLOW_EDIT']:
|
||||
record = DomainTemplateRecord(name=name, type=jr['type'], status=True if jr['disabled'] else False, ttl=jr['ttl'], data=jr['content'])
|
||||
records.append(record)
|
||||
result_records = t.replace_records(records)
|
||||
|
||||
if result_records['status'] == 'ok':
|
||||
return make_response(jsonify({'status': 'ok', 'msg': result['msg']}), 200)
|
||||
else:
|
||||
result = t.delete_template()
|
||||
return make_response(jsonify({'status': 'error', 'msg': result_records['msg']}), 500)
|
||||
|
||||
else:
|
||||
return make_response(jsonify({'status': 'error', 'msg': result['msg']}), 500)
|
||||
except:
|
||||
logging.error(traceback.print_exc())
|
||||
return make_response(jsonify({'status': 'error', 'msg': 'Error when applying new changes'}), 500)
|
||||
|
||||
|
||||
@app.route('/template/<string:template>/edit', methods=['GET'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
def edit_template(template):
|
||||
try:
|
||||
t = DomainTemplate.query.filter(DomainTemplate.name == template).first()
|
||||
if t is not None:
|
||||
records = []
|
||||
for jr in t.records:
|
||||
if jr.type in app.config['RECORDS_ALLOW_EDIT']:
|
||||
record = DomainTemplateRecord(name=jr.name, type=jr.type, status='Disabled' if jr.status else 'Active', ttl=jr.ttl, data=jr.data)
|
||||
records.append(record)
|
||||
|
||||
return render_template('template_edit.html', template=t.name, records=records, editable_records=app.config['RECORDS_ALLOW_EDIT'])
|
||||
except:
|
||||
logging.error(traceback.print_exc())
|
||||
return redirect(url_for('error', code=500))
|
||||
return redirect(url_for('templates'))
|
||||
|
||||
|
||||
@app.route('/template/<string:template>/apply', methods=['POST'], strict_slashes=False)
|
||||
@login_required
|
||||
def apply_records(template):
|
||||
try:
|
||||
jdata = request.json
|
||||
records = []
|
||||
|
||||
for j in jdata:
|
||||
name = '@' if j['record_name'] in ['@', ''] else j['record_name']
|
||||
type = j['record_type']
|
||||
data = j['record_data']
|
||||
disabled = True if j['record_status'] == 'Disabled' else False
|
||||
ttl = int(j['record_ttl']) if j['record_ttl'] else 3600
|
||||
|
||||
dtr = DomainTemplateRecord(name=name, type=type, data=data, status=disabled, ttl=ttl)
|
||||
records.append(dtr)
|
||||
|
||||
t = DomainTemplate.query.filter(DomainTemplate.name == template).first()
|
||||
result = t.replace_records(records)
|
||||
if result['status'] == 'ok':
|
||||
history = History(msg='Apply domain template record changes to domain template %s' % template, detail=str(jdata), created_by=current_user.username)
|
||||
history.add()
|
||||
return make_response(jsonify(result), 200)
|
||||
else:
|
||||
return make_response(jsonify(result), 400)
|
||||
except:
|
||||
logging.error(traceback.print_exc())
|
||||
return make_response(jsonify({'status': 'error', 'msg': 'Error when applying new changes'}), 500)
|
||||
|
||||
|
||||
@app.route('/template/<string:template>/delete', methods=['GET'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
def delete_template(template):
|
||||
try:
|
||||
t = DomainTemplate.query.filter(DomainTemplate.name == template).first()
|
||||
if t is not None:
|
||||
result = t.delete_template()
|
||||
if result['status'] == 'ok':
|
||||
history = History(msg='Deleted domain template %s' % template, detail=str({'name': template}), created_by=current_user.username)
|
||||
history.add()
|
||||
return redirect(url_for('templates'))
|
||||
else:
|
||||
flash(result['msg'], 'error')
|
||||
return redirect(url_for('templates'))
|
||||
except:
|
||||
logging.error(traceback.print_exc())
|
||||
return redirect(url_for('error', code=500))
|
||||
return redirect(url_for('templates'))
|
||||
|
||||
|
||||
@app.route('/admin', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@admin_role_required
|
||||
@ -718,7 +913,7 @@ def admin_manageuser():
|
||||
else:
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'Action not supported.' } ), 400)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
logging.error(traceback.print_exc())
|
||||
return make_response(jsonify( { 'status': 'error', 'msg': 'There is something wrong, please contact Administrator.' } ), 400)
|
||||
|
||||
|
||||
@ -883,7 +1078,7 @@ def dyndns_update():
|
||||
r = Record()
|
||||
r.name = hostname
|
||||
# check if the user requested record exists within this domain
|
||||
if r.exists(domain.name) and r.is_allowed:
|
||||
if r.exists(domain.name) and r.is_allowed_edit():
|
||||
if r.data == myip:
|
||||
# record content did not change, return 'nochg'
|
||||
history = History(msg="DynDNS update: attempted update of %s but record did not change" % hostname, created_by=current_user.username)
|
||||
@ -898,7 +1093,7 @@ def dyndns_update():
|
||||
return render_template('dyndns.html', response='good'), 200
|
||||
else:
|
||||
return render_template('dyndns.html', response='911'), 200
|
||||
elif r.is_allowed:
|
||||
elif r.is_allowed_edit():
|
||||
ondemand_creation = DomainSetting.query.filter(DomainSetting.domain == domain).filter(DomainSetting.setting == 'create_via_dyndns').first()
|
||||
if (ondemand_creation != None) and (strtobool(ondemand_creation.value) == True):
|
||||
record = Record(name=hostname,type='A',data=myip,status=False,ttl=3600)
|
||||
|
26
create_db.py
26
create_db.py
@ -9,7 +9,7 @@ from migrate.versioning import api
|
||||
from config import SQLALCHEMY_DATABASE_URI
|
||||
from config import SQLALCHEMY_MIGRATE_REPO
|
||||
from app import db
|
||||
from app.models import Role, Setting
|
||||
from app.models import Role, Setting, DomainTemplate
|
||||
|
||||
|
||||
def start():
|
||||
@ -69,6 +69,23 @@ def init_settings(db, setting_names):
|
||||
for setting in settings:
|
||||
db.session.add(setting)
|
||||
|
||||
|
||||
def init_domain_templates(db, domain_template_names):
|
||||
|
||||
# Get key name of data
|
||||
name_of_domain_templates = map(lambda r: r.name, domain_template_names)
|
||||
|
||||
# Query to get current data
|
||||
rows = db.session.query(DomainTemplate).filter(DomainTemplate.name.in_(name_of_domain_templates)).all()
|
||||
|
||||
# Check which data that need to insert
|
||||
name_of_rows = map(lambda r: r.name, rows)
|
||||
domain_templates = filter(lambda r: r.name not in name_of_rows, domain_template_names)
|
||||
|
||||
# Insert data
|
||||
for domain_template in domain_templates:
|
||||
db.session.add(domain_template)
|
||||
|
||||
def init_records():
|
||||
# Create initial user roles and turn off maintenance mode
|
||||
init_roles(db, [
|
||||
@ -84,7 +101,12 @@ def init_records():
|
||||
Setting('default_domain_table_size', '10'),
|
||||
Setting('auto_ptr','False')
|
||||
])
|
||||
|
||||
# TODO: add sample records to sample templates
|
||||
init_domain_templates(db, [
|
||||
DomainTemplate('basic_template_1', 'Basic Template #1'),
|
||||
DomainTemplate('basic_template_2', 'Basic Template #2'),
|
||||
DomainTemplate('basic_template_3', 'Basic Template #3')
|
||||
])
|
||||
db_commit = db.session.commit()
|
||||
commit_version_control(db_commit)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user