Merge updates from master branch

This commit is contained in:
Khanh Ngo 2018-04-18 10:12:07 +07:00
commit fba93a57e1
10 changed files with 174 additions and 76 deletions

View File

@ -7,6 +7,10 @@ app = Flask(__name__)
app.config.from_object('config') app.config.from_object('config')
app.wsgi_app = ProxyFix(app.wsgi_app) app.wsgi_app = ProxyFix(app.wsgi_app)
#### CONFIGURE LOGGER ####
from app.lib.log import logger
logging = logger('powerdns-admin', app.config['LOG_LEVEL'], app.config['LOG_FILE']).config()
login_manager = LoginManager() login_manager = LoginManager()
login_manager.init_app(app) login_manager.init_app(app)
db = SQLAlchemy(app) db = SQLAlchemy(app)

View File

@ -130,7 +130,7 @@ def display_record_name(data):
if record_name == domain_name: if record_name == domain_name:
return '@' return '@'
else: else:
return record_name.replace('.'+domain_name, '') return re.sub('\.{}$'.format(domain_name), '', record_name)
def display_master_name(data): def display_master_name(data):
@ -196,6 +196,9 @@ def email_to_gravatar_url(email="", size=100):
""" """
AD doesn't necessarily have email AD doesn't necessarily have email
""" """
if email is None:
email = ""
hash_string = hashlib.md5(email.encode('utf-8')).hexdigest() hash_string = hashlib.md5(email.encode('utf-8')).hexdigest()
return "https://s.gravatar.com/avatar/{0}?s={1}".format(hash_string, size) return "https://s.gravatar.com/avatar/{0}?s={1}".format(hash_string, size)

View File

@ -10,6 +10,7 @@ import pyotp
import re import re
import dns.reversename import dns.reversename
import sys import sys
import logging as logger
from datetime import datetime from datetime import datetime
from urllib.parse import urljoin from urllib.parse import urljoin
@ -19,10 +20,8 @@ from flask_login import AnonymousUserMixin
from app import app, db from app import app, db
from app.lib import utils from app.lib import utils
from app.lib.log import logger
# LOG CONFIGS logging = logger.getLogger(__name__)
logging = logger('MODEL', app.config['LOG_LEVEL'], app.config['LOG_FILE']).config()
if 'LDAP_TYPE' in app.config.keys(): if 'LDAP_TYPE' in app.config.keys():
LDAP_URI = app.config['LDAP_URI'] LDAP_URI = app.config['LDAP_URI']
@ -135,6 +134,9 @@ class User(db.Model):
def get_hashed_password(self, plain_text_password=None): def get_hashed_password(self, plain_text_password=None):
# Hash a password for the first time # Hash a password for the first time
# (Using bcrypt, the salt is saved into the hash itself) # (Using bcrypt, the salt is saved into the hash itself)
if plain_text_password == None:
return plain_text_password
pw = plain_text_password if plain_text_password else self.plain_text_password pw = plain_text_password if plain_text_password else self.plain_text_password
return bcrypt.hashpw(pw.encode('utf-8'), bcrypt.gensalt()) return bcrypt.hashpw(pw.encode('utf-8'), bcrypt.gensalt())
@ -316,6 +318,9 @@ class User(db.Model):
self.password = self.get_hashed_password(self.plain_text_password) self.password = self.get_hashed_password(self.plain_text_password)
if self.password:
self.password = self.password.decode("utf-8")
db.session.add(self) db.session.add(self)
db.session.commit() db.session.commit()
return {'status': True, 'msg': 'Created user successfully'} return {'status': True, 'msg': 'Created user successfully'}
@ -335,7 +340,9 @@ class User(db.Model):
user.password = self.get_hashed_password(self.plain_text_password) if self.plain_text_password else user.password user.password = self.get_hashed_password(self.plain_text_password) if self.plain_text_password else user.password
user.avatar = self.avatar if self.avatar else user.avatar user.avatar = self.avatar if self.avatar else user.avatar
user.otp_secret = "" if enable_otp is not None:
user.otp_secret = ""
if enable_otp == True: if enable_otp == True:
# generate the opt secret key # generate the opt secret key
user.otp_secret = base64.b32encode(os.urandom(10)).decode('utf-8') user.otp_secret = base64.b32encode(os.urandom(10)).decode('utf-8')
@ -502,24 +509,18 @@ class Domain(db.Model):
logging.error('Can not create setting {0} for domain {1}. {2}'.format(setting, self.name, e)) logging.error('Can not create setting {0} for domain {1}. {2}'.format(setting, self.name, e))
return False return False
def get_domain_info(self, domain_name):
"""
Get all domains which has in PowerDNS
"""
headers = {}
headers['X-API-Key'] = PDNS_API_KEY
jdata = utils.fetch_json(urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain_name)), headers=headers)
return jdata
def get_domains(self): def get_domains(self):
""" """
Get all domains which has in PowerDNS Get all domains which has in PowerDNS
jdata example:
[
{
"id": "example.org.",
"url": "/servers/localhost/zones/example.org.",
"name": "example.org",
"kind": "Native",
"dnssec": false,
"account": "",
"masters": [],
"serial": 2015101501,
"notified_serial": 0,
"last_check": 0
}
]
""" """
headers = {} headers = {}
headers['X-API-Key'] = PDNS_API_KEY headers['X-API-Key'] = PDNS_API_KEY
@ -878,6 +879,7 @@ class Domain(db.Model):
else: else:
return {'status': 'error', 'msg': 'This domain doesnot exist'} return {'status': 'error', 'msg': 'This domain doesnot exist'}
class DomainUser(db.Model): class DomainUser(db.Model):
__tablename__ = 'domain_user' __tablename__ = 'domain_user'
id = db.Column(db.Integer, primary_key = True) id = db.Column(db.Integer, primary_key = True)
@ -1175,6 +1177,7 @@ class Record(object):
return {'status': 'error', 'msg': jdata2['error']} return {'status': 'error', 'msg': jdata2['error']}
else: else:
self.auto_ptr(domain, new_records, deleted_records) self.auto_ptr(domain, new_records, deleted_records)
self.update_db_serial(domain)
logging.info('Record was applied successfully.') logging.info('Record was applied successfully.')
return {'status': 'ok', 'msg': 'Record was applied successfully'} return {'status': 'ok', 'msg': 'Record was applied successfully'}
except Exception as e: except Exception as e:
@ -1327,6 +1330,20 @@ class Record(object):
logging.error("Cannot add record {0}/{1}/{2} to domain {3}. DETAIL: {4}".format(self.name, self.type, self.data, domain, e)) logging.error("Cannot add record {0}/{1}/{2} to domain {3}. DETAIL: {4}".format(self.name, self.type, self.data, domain, e))
return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'} return {'status': 'error', 'msg': 'There was something wrong, please contact administrator'}
def update_db_serial(self, domain):
headers = {}
headers['X-API-Key'] = PDNS_API_KEY
jdata = utils.fetch_json(urljoin(PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones/{0}'.format(domain)), headers=headers, method='GET')
serial = jdata['serial']
domain = Domain.query.filter(Domain.name==domain).first()
if domain:
domain.serial = serial
db.session.commit()
return {'status': True, 'msg': 'Synced local serial for domain name {0}'.format(domain)}
else:
return {'status': False, 'msg': 'Could not find domain name {0} in local db'.format(domain)}
class Server(object): class Server(object):
""" """
@ -1544,7 +1561,7 @@ class DomainTemplateRecord(db.Model):
name = db.Column(db.String(255)) name = db.Column(db.String(255))
type = db.Column(db.String(64)) type = db.Column(db.String(64))
ttl = db.Column(db.Integer) ttl = db.Column(db.Integer)
data = db.Column(db.String(255)) data = db.Column(db.Text)
status = db.Column(db.Boolean) status = db.Column(db.Boolean)
template_id = db.Column(db.Integer, db.ForeignKey('domain_template.id')) template_id = db.Column(db.Integer, db.ForeignKey('domain_template.id'))
template = db.relationship('DomainTemplate', back_populates='records') template = db.relationship('DomainTemplate', back_populates='records')

View File

@ -30,6 +30,37 @@ function applyChanges(data, url, showResult, refreshPage) {
}); });
} }
function applyRecordChanges(data, domain) {
var success = false;
$.ajax({
type : "POST",
url : $SCRIPT_ROOT + '/domain/' + domain + '/apply',
data : JSON.stringify(data),// now data come in this function
contentType : "application/json; charset=utf-8",
crossDomain : true,
dataType : "json",
success : function(data, status, jqXHR) {
// update Apply button value
$.getJSON($SCRIPT_ROOT + '/domain/' + domain + '/info', function(data) {
$(".button_apply_changes").val(data['serial']);
});
console.log("Applied changes successfully.")
var modal = $("#modal_success");
modal.find('.modal-body p').text("Applied changes successfully");
modal.modal('show');
},
error : function(jqXHR, status) {
console.log(jqXHR);
var modal = $("#modal_error");
var responseJson = jQuery.parseJSON(jqXHR.responseText);
modal.find('.modal-body p').text(responseJson['msg']);
modal.modal('show');
}
});
}
function getTableData(table) { function getTableData(table) {
var rData = [] var rData = []

View File

@ -96,7 +96,7 @@
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-flat btn-default pull-left" <button type="button" class="btn btn-flat btn-default pull-left"
data-dismiss="modal">Close</button> data-dismiss="modal">Close</button>
<button type="button" class="btn btn-flat btn-danger" onclick="applyChanges('', $SCRIPT_ROOT + '/admin/history');location.reload();">Clear History</button> <button type="button" class="btn btn-flat btn-danger" onclick="applyChanges('', $SCRIPT_ROOT + '/admin/history', false, true);">Clear History</button>
</div> </div>
</div> </div>
<!-- /.modal-content --> <!-- /.modal-content -->

View File

@ -25,7 +25,7 @@
<button type="button" class="btn btn-flat btn-primary pull-left button_add_record" id="{{ domain.name }}"> <button type="button" class="btn btn-flat btn-primary pull-left button_add_record" id="{{ domain.name }}">
Add Record&nbsp;<i class="fa fa-plus"></i> Add Record&nbsp;<i class="fa fa-plus"></i>
</button> </button>
<button type="button" class="btn btn-flat btn-primary pull-right button_apply_changes" id="{{ domain.name }}"> <button type="button" class="btn btn-flat btn-primary pull-right button_apply_changes" id="{{ domain.name }}" value="{{ domain.serial }}">
Apply Changes&nbsp;<i class="fa fa-floppy-o"></i> Apply Changes&nbsp;<i class="fa fa-floppy-o"></i>
</button> </button>
{% else %} {% else %}
@ -196,11 +196,14 @@
var modal = $("#modal_apply_changes"); var modal = $("#modal_apply_changes");
var table = $("#tbl_records").DataTable(); var table = $("#tbl_records").DataTable();
var domain = $(this).prop('id'); var domain = $(this).prop('id');
var serial = $(".button_apply_changes").val();
var info = "Are you sure you want to apply your changes?"; var info = "Are you sure you want to apply your changes?";
modal.find('.modal-body p').text(info); modal.find('.modal-body p').text(info);
modal.find('#button_apply_confirm').click(function() {
var data = getTableData(table); // following unbind("click") is to avoid multiple times execution
applyChanges(data, $SCRIPT_ROOT + '/domain/' + domain + '/apply', true); modal.find('#button_apply_confirm').unbind("click").click(function() {
var data = {'serial': serial, 'record': getTableData(table)};
applyRecordChanges(data, domain);
modal.modal('hide'); modal.modal('hide');
}) })
modal.modal('show'); modal.modal('show');

View File

@ -32,7 +32,8 @@
{% if not external_account %}<li><a href="#tabs-password" data-toggle="tab">Change {% if not external_account %}<li><a href="#tabs-password" data-toggle="tab">Change
Password</a></li> Password</a></li>
<li><a href="#tabs-authentication" data-toggle="tab">Authentication <li><a href="#tabs-authentication" data-toggle="tab">Authentication
</a></li>{% endif %}> </a></li>
{% endif %}
</ul> </ul>
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane active" id="tabs-personal"> <div class="tab-pane active" id="tabs-personal">

View File

@ -1,5 +1,6 @@
import base64 import base64
import json import json
import logging as logger
import os import os
import traceback import traceback
import re import re
@ -19,15 +20,13 @@ from werkzeug.security import gen_salt
from .models import User, Domain, Record, Server, History, Anonymous, Setting, DomainSetting, DomainTemplate, DomainTemplateRecord from .models import User, Domain, Record, Server, History, Anonymous, Setting, DomainSetting, DomainTemplate, DomainTemplateRecord
from app import app, login_manager, github, google from app import app, login_manager, github, google
from app.lib import utils from app.lib import utils
from app.lib.log import logger
from app.decorators import admin_role_required, can_access_domain from app.decorators import admin_role_required, can_access_domain
if app.config['SAML_ENABLED']: if app.config['SAML_ENABLED']:
from onelogin.saml2.auth import OneLogin_Saml2_Auth from onelogin.saml2.auth import OneLogin_Saml2_Auth
from onelogin.saml2.utils import OneLogin_Saml2_Utils from onelogin.saml2.utils import OneLogin_Saml2_Utils
# LOG CONFIG logging = logger.getLogger(__name__)
logging = logger('MODEL', app.config['LOG_LEVEL'], app.config['LOG_FILE']).config()
# FILTERS # FILTERS
jinja2.filters.FILTERS['display_record_name'] = utils.display_record_name jinja2.filters.FILTERS['display_record_name'] = utils.display_record_name
@ -118,7 +117,7 @@ def login_via_authorization_header(request):
if auth_header: if auth_header:
auth_header = auth_header.replace('Basic ', '', 1) auth_header = auth_header.replace('Basic ', '', 1)
try: try:
auth_header = base64.b64decode(auth_header) auth_header = str(base64.b64decode(auth_header), 'utf-8')
username,password = auth_header.split(":") username,password = auth_header.split(":")
except TypeError as e: except TypeError as e:
return None return None
@ -312,12 +311,13 @@ def login():
return redirect(url_for('index')) return redirect(url_for('index'))
if request.method == 'GET': if request.method == 'GET':
return render_template('login.html', return render_template('login.html', github_enabled=GITHUB_ENABLE,
github_enabled=GITHUB_ENABLE, google_enabled=GOOGLE_ENABLE,
google_enabled=GOOGLE_ENABLE, saml_enabled=SAML_ENABLED,
saml_enabled=SAML_ENABLED, ldap_enabled=LDAP_ENABLED,
ldap_enabled=LDAP_ENABLED, login_title=LOGIN_TITLE, login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED, signup_enabled=SIGNUP_ENABLED) basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
# process login # process login
username = request.form['username'] username = request.form['username']
@ -331,6 +331,9 @@ def login():
email = request.form.get('email') email = request.form.get('email')
rpassword = request.form.get('rpassword') rpassword = request.form.get('rpassword')
if auth_method != 'LOCAL':
session['external_auth'] = True
if None in [firstname, lastname, email]: if None in [firstname, lastname, email]:
#login case #login case
remember_me = False remember_me = False
@ -342,37 +345,46 @@ def login():
try: try:
auth = user.is_validate(method=auth_method) auth = user.is_validate(method=auth_method)
if auth == False: if auth == False:
return render_template('login.html', error='Invalid credentials', ldap_enabled=LDAP_ENABLED, return render_template('login.html', error='Invalid credentials',
login_title=LOGIN_TITLE, github_enabled=GITHUB_ENABLE,
basic_enabled=BASIC_ENABLED, google_enabled=GOOGLE_ENABLE,
signup_enabled=SIGNUP_ENABLED, saml_enabled=SAML_ENABLED,
github_enabled=GITHUB_ENABLE, ldap_enabled=LDAP_ENABLED,
saml_enabled=SAML_ENABLED) login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
except Exception as e: except Exception as e:
return render_template('login.html', error=e, ldap_enabled=LDAP_ENABLED, login_title=LOGIN_TITLE, return render_template('login.html', error=e,
basic_enabled=BASIC_ENABLED, github_enabled=GITHUB_ENABLE,
signup_enabled=SIGNUP_ENABLED, google_enabled=GOOGLE_ENABLE,
github_enabled=GITHUB_ENABLE, saml_enabled=SAML_ENABLED,
saml_enabled=SAML_ENABLED) ldap_enabled=LDAP_ENABLED,
login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
# check if user enabled OPT authentication # check if user enabled OPT authentication
if user.otp_secret: if user.otp_secret:
if otp_token: if otp_token:
good_token = user.verify_totp(otp_token) good_token = user.verify_totp(otp_token)
if not good_token: if not good_token:
return render_template('login.html', error='Invalid credentials', ldap_enabled=LDAP_ENABLED, return render_template('login.html', error='Invalid credentials',
login_title=LOGIN_TITLE, github_enabled=GITHUB_ENABLE,
basic_enabled=BASIC_ENABLED, google_enabled=GOOGLE_ENABLE,
signup_enabled=SIGNUP_ENABLED, saml_enabled=SAML_ENABLED,
github_enabled=GITHUB_ENABLE, ldap_enabled=LDAP_ENABLED,
saml_enabled=SAML_ENABLED) login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
else: else:
return render_template('login.html', error='Token required', ldap_enabled=LDAP_ENABLED, return render_template('login.html', error='Token required',
login_title=LOGIN_TITLE, github_enabled=GITHUB_ENABLE,
basic_enabled=BASIC_ENABLED, google_enabled=GOOGLE_ENABLE,
signup_enabled=SIGNUP_ENABLED, saml_enabled=SAML_ENABLED,
github_enabled = GITHUB_ENABLE, ldap_enabled=LDAP_ENABLED,
saml_enabled = SAML_ENABLED) login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
login_user(user, remember = remember_me) login_user(user, remember = remember_me)
return redirect(request.args.get('next') or url_for('index')) return redirect(request.args.get('next') or url_for('index'))
@ -389,9 +401,14 @@ def login():
try: try:
result = user.create_local_user() result = user.create_local_user()
if result == True: if result == True:
return render_template('login.html', username=username, password=password, ldap_enabled=LDAP_ENABLED, return render_template('login.html', username=username, password=password,
login_title=LOGIN_TITLE, basic_enabled=BASIC_ENABLED, signup_enabled=SIGNUP_ENABLED, github_enabled=GITHUB_ENABLE,
github_enabled=GITHUB_ENABLE,saml_enabled=SAML_ENABLED) google_enabled=GOOGLE_ENABLE,
saml_enabled=SAML_ENABLED,
ldap_enabled=LDAP_ENABLED,
login_title=LOGIN_TITLE,
basic_enabled=BASIC_ENABLED,
signup_enabled=SIGNUP_ENABLED)
else: else:
return render_template('register.html', error=result['msg']) return render_template('register.html', error=result['msg'])
except Exception as e: except Exception as e:
@ -523,7 +540,6 @@ def dashboard_domains():
@app.route('/domain/<path:domain_name>', methods=['GET', 'POST']) @app.route('/domain/<path:domain_name>', methods=['GET', 'POST'])
@app.route('/domain', methods=['GET', 'POST'])
@login_required @login_required
@can_access_domain @can_access_domain
def domain(domain_name): def domain(domain_name):
@ -551,7 +567,7 @@ def domain(domain_name):
if not re.search('ip6\.arpa|in-addr\.arpa$', domain_name): if not re.search('ip6\.arpa|in-addr\.arpa$', domain_name):
editable_records = app.config['RECORDS_ALLOW_EDIT'] editable_records = app.config['RECORDS_ALLOW_EDIT']
else: else:
editable_records = app.config['REVERSE_ALLOW_EDIT'] editable_records = app.config['REVERSE_RECORDS_ALLOW_EDIT']
return render_template('domain.html', domain=domain, records=records, editable_records=editable_records) return render_template('domain.html', domain=domain, records=records, editable_records=editable_records)
else: else:
for jr in jrecords: for jr in jrecords:
@ -562,7 +578,7 @@ def domain(domain_name):
editable_records = app.config['FORWARD_RECORDS_ALLOW_EDIT'] editable_records = app.config['FORWARD_RECORDS_ALLOW_EDIT']
else: else:
editable_records = app.config['REVERSE_RECORDS_ALLOW_EDIT'] editable_records = app.config['REVERSE_RECORDS_ALLOW_EDIT']
return render_template('domain.html', domain=domain, records=records, editable_records=editable_records,pdns_version=app.config['PDNS_VERSION']) return render_template('domain.html', domain=domain, records=records, editable_records=editable_records, pdns_version=app.config['PDNS_VERSION'])
@app.route('/admin/domain/add', methods=['GET', 'POST']) @app.route('/admin/domain/add', methods=['GET', 'POST'])
@ -575,7 +591,6 @@ def domain_add():
domain_name = request.form.getlist('domain_name')[0] domain_name = request.form.getlist('domain_name')[0]
domain_type = request.form.getlist('radio_type')[0] domain_type = request.form.getlist('radio_type')[0]
domain_template = request.form.getlist('domain_template')[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] soa_edit_api = request.form.getlist('radio_type_soa_edit_api')[0]
if ' ' in domain_name or not domain_name or not domain_type: if ' ' in domain_name or not domain_name or not domain_type:
@ -698,11 +713,26 @@ def record_apply(domain_name):
example jdata: {u'record_ttl': u'1800', u'record_type': u'CNAME', u'record_name': u'test4', u'record_status': u'Active', u'record_data': u'duykhanh.me'} example jdata: {u'record_ttl': u'1800', u'record_type': u'CNAME', u'record_name': u'test4', u'record_status': u'Active', u'record_data': u'duykhanh.me'}
""" """
#TODO: filter removed records / name modified records. #TODO: filter removed records / name modified records.
try: try:
jdata = request.json jdata = request.json
submitted_serial = jdata['serial']
submitted_record = jdata['record']
domain = Domain.query.filter(Domain.name==domain_name).first()
logging.debug('Your submitted serial: {0}'.format(submitted_serial))
logging.debug('Current domain serial: {0}'.format(domain.serial))
if domain:
if int(submitted_serial) != domain.serial:
return make_response(jsonify( {'status': 'error', 'msg': 'The zone has been changed by another session or user. Please refresh this web page to load updated records.'} ), 500)
else:
return make_response(jsonify( {'status': 'error', 'msg': 'Domain name {0} does not exist'.format(domain_name)} ), 404)
r = Record() r = Record()
result = r.apply(domain_name, jdata) result = r.apply(domain_name, submitted_record)
if result['status'] == 'ok': if result['status'] == 'ok':
history = History(msg='Apply record changes to domain {0}'.format(domain_name), detail=str(jdata), created_by=current_user.username) history = History(msg='Apply record changes to domain {0}'.format(domain_name), detail=str(jdata), created_by=current_user.username)
history.add() history.add()
@ -752,6 +782,15 @@ def record_delete(domain_name, record_name, record_type):
return redirect(url_for('domain', domain_name=domain_name)) return redirect(url_for('domain', domain_name=domain_name))
@app.route('/domain/<path:domain_name>/info', methods=['GET'])
@login_required
@can_access_domain
def domain_info(domain_name):
domain = Domain()
domain_info = domain.get_domain_info(domain_name)
return make_response(jsonify(domain_info), 200)
@app.route('/domain/<path:domain_name>/dnssec', methods=['GET']) @app.route('/domain/<path:domain_name>/dnssec', methods=['GET'])
@login_required @login_required
@can_access_domain @can_access_domain
@ -898,17 +937,18 @@ def create_template_from_zone():
if NEW_SCHEMA: if NEW_SCHEMA:
for jr in jrecords: for jr in jrecords:
name = '@' if jr['name'] == domain_name else jr['name']
if jr['type'] in app.config['RECORDS_ALLOW_EDIT']: if jr['type'] in app.config['RECORDS_ALLOW_EDIT']:
name = '@' if jr['name'] == domain_name else re.sub('\.{}$'.format(domain_name), '', jr['name'])
for subrecord in jr['records']: 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']) record = DomainTemplateRecord(name=name, type=jr['type'], status=True if subrecord['disabled'] else False, ttl=jr['ttl'], data=subrecord['content'])
records.append(record) records.append(record)
else: else:
for jr in jrecords: for jr in jrecords:
if jr['type'] in app.config['RECORDS_ALLOW_EDIT']: if jr['type'] in app.config['RECORDS_ALLOW_EDIT']:
name = '@' if jr['name'] == domain_name else re.sub('\.{}$'.format(domain_name), '', jr['name'])
record = DomainTemplateRecord(name=name, type=jr['type'], status=True if jr['disabled'] else False, ttl=jr['ttl'], data=jr['content']) record = DomainTemplateRecord(name=name, type=jr['type'], status=True if jr['disabled'] else False, ttl=jr['ttl'], data=jr['content'])
records.append(record) records.append(record)
result_records = t.replace_records(records) result_records = t.replace_records(records)
if result_records['status'] == 'ok': if result_records['status'] == 'ok':
@ -1150,7 +1190,7 @@ def admin_settings_edit(setting):
@login_required @login_required
def user_profile(): def user_profile():
external_account = False external_account = False
if session.has_key('external_auth'): if 'external_auth' in session:
external_account = session['external_auth'] external_account = session['external_auth']
if request.method == 'GET' or external_account: if request.method == 'GET' or external_account:
return render_template('user_profile.html', external_account=external_account) return render_template('user_profile.html', external_account=external_account)

View File

@ -123,7 +123,7 @@ PDNS_VERSION = '4.1.1'
# RECORDS ALLOWED TO EDIT # RECORDS ALLOWED TO EDIT
RECORDS_ALLOW_EDIT = ['SOA', 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'PTR', 'SPF', 'SRV', 'TXT', 'LOC', 'NS', 'PTR'] RECORDS_ALLOW_EDIT = ['SOA', 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'PTR', 'SPF', 'SRV', 'TXT', 'LOC', 'NS', 'PTR']
FORWARD_RECORDS_ALLOW_EDIT = ['A', 'AAAA', 'CAA', 'CNAME', 'MX', 'PTR', 'SPF', 'SRV', 'TXT', 'LOC' 'NS'] FORWARD_RECORDS_ALLOW_EDIT = ['A', 'AAAA', 'CAA', 'CNAME', 'MX', 'PTR', 'SPF', 'SRV', 'TXT', 'LOC' 'NS']
REVERSE_RECORDS_ALLOW_EDIT = ['TXT', 'LOC', 'NS', 'PTR'] REVERSE_RECORDS_ALLOW_EDIT = ['SOA', 'TXT', 'LOC', 'NS', 'PTR']
# EXPERIMENTAL FEATURES # EXPERIMENTAL FEATURES
PRETTY_IPV6_PTR = False PRETTY_IPV6_PTR = False

View File

@ -111,10 +111,9 @@ PDNS_API_KEY = os.environ.get('PDNS_API_KEY')
PDNS_VERSION = '4.1.1' PDNS_VERSION = '4.1.1'
# RECORDS ALLOWED TO EDIT # RECORDS ALLOWED TO EDIT
RECORDS_ALLOW_EDIT = ['A', 'AAAA', 'CAA', 'CNAME', 'MX', 'PTR', 'SPF', 'SRV', 'TXT', 'NS'] RECORDS_ALLOW_EDIT = ['SOA', 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'PTR', 'SPF', 'SRV', 'TXT', 'LOC', 'NS', 'PTR']
FORWARD_RECORDS_ALLOW_EDIT = ['A', 'AAAA', 'CAA', 'CNAME', 'MX', 'PTR', 'SPF', 'SRV', 'TXT', 'LOC' 'NS']
# RECORDS ALLOWED TO EDIT FOR REVERSE DOMAINS REVERSE_RECORDS_ALLOW_EDIT = ['SOA', 'TXT', 'LOC', 'NS', 'PTR']
REVERSE_ALLOW_EDIT = ['PTR', 'NS']
# EXPERIMENTAL FEATURES # EXPERIMENTAL FEATURES
PRETTY_IPV6_PTR = False PRETTY_IPV6_PTR = False