Merge pull request #118 from jallakim/pretty-ipv6-ptr

Pretty IPv6 PTR. Use the actual IPv6 address when editing PTR.
This commit is contained in:
Khanh Ngo 2016-08-25 09:51:10 +07:00 committed by GitHub
commit 02bd378391
5 changed files with 70 additions and 24 deletions

View File

@ -10,6 +10,7 @@ PowerDNS Web-GUI - Built by Flask
- User activity logging - User activity logging
- Dashboard and pdns service statistics - Dashboard and pdns service statistics
- DynDNS 2 protocol support - DynDNS 2 protocol support
- Edit IPv6 PTRs using IPv6 addresses directly (no more editing of literal addresses!)
## Setup ## Setup

View File

@ -7,6 +7,9 @@ import urlparse
import itertools import itertools
import traceback import traceback
import onetimepass import onetimepass
import dns.inet
import dns.name
import dns.reversename
from datetime import datetime from datetime import datetime
from distutils.version import StrictVersion from distutils.version import StrictVersion
@ -32,6 +35,7 @@ PDNS_STATS_URL = app.config['PDNS_STATS_URL']
PDNS_API_KEY = app.config['PDNS_API_KEY'] PDNS_API_KEY = app.config['PDNS_API_KEY']
PDNS_VERSION = app.config['PDNS_VERSION'] PDNS_VERSION = app.config['PDNS_VERSION']
API_EXTENDED_URL = utils.pdns_api_extended_uri(PDNS_VERSION) API_EXTENDED_URL = utils.pdns_api_extended_uri(PDNS_VERSION)
PRETTY_IPV6_PTR = app.config['PRETTY_IPV6_PTR']
# Flag for pdns v4.x.x # Flag for pdns v4.x.x
# TODO: Find another way to do this # TODO: Find another way to do this
@ -742,7 +746,13 @@ class Record(object):
if NEW_SCHEMA: if NEW_SCHEMA:
rrsets = jdata['rrsets'] rrsets = jdata['rrsets']
for rrset in rrsets: for rrset in rrsets:
rrset['name'] = rrset['name'].rstrip('.') r_name = rrset['name'].rstrip('.')
if PRETTY_IPV6_PTR: # only if activated
if rrset['type'] == 'PTR': # only ptr
if 'ip6.arpa' in r_name: # only if v6-ptr
r_name = dns.reversename.to_address(dns.name.from_text(r_name))
rrset['name'] = r_name
rrset['content'] = rrset['records'][0]['content'] rrset['content'] = rrset['records'][0]['content']
rrset['disabled'] = rrset['records'][0]['disabled'] rrset['disabled'] = rrset['records'][0]['disabled']
return {'records': rrsets} return {'records': rrsets}
@ -838,13 +848,40 @@ class Record(object):
""" """
Apply record changes to domain Apply record changes to domain
""" """
deleted_records, new_records = self.compare(domain, post_records) records = []
for r in post_records:
r_name = domain if r['record_name'] in ['@', ''] else r['record_name'] + '.' + domain
r_type = r['record_type']
if PRETTY_IPV6_PTR: # only if activated
if NEW_SCHEMA: # only if new schema
if r_type == 'PTR': # only ptr
if ':' in r['record_name']: # dirty ipv6 check
r_name = r['record_name']
record = {
"name": r_name,
"type": r_type,
"content": r['record_data'],
"disabled": True if r['record_status'] == 'Disabled' else False,
"ttl": int(r['record_ttl']) if r['record_ttl'] else 3600,
}
records.append(record)
deleted_records, new_records = self.compare(domain, records)
records = [] records = []
for r in deleted_records: for r in deleted_records:
r_name = r['name'] + '.' if NEW_SCHEMA else r['name']
r_type = r['type']
if PRETTY_IPV6_PTR: # only if activated
if NEW_SCHEMA: # only if new schema
if r_type == 'PTR': # only ptr
if ':' in r['name']: # dirty ipv6 check
r_name = dns.reversename.from_address(r['name']).to_text()
record = { record = {
"name": r['name'] + '.' if NEW_SCHEMA else r['name'], "name": r_name,
"type": r['type'], "type": r_type,
"changetype": "DELETE", "changetype": "DELETE",
"records": [ "records": [
] ]
@ -856,9 +893,16 @@ class Record(object):
records = [] records = []
for r in new_records: for r in new_records:
if NEW_SCHEMA: if NEW_SCHEMA:
r_name = r['name'] + '.'
r_type = r['type']
if PRETTY_IPV6_PTR: # only if activated
if r_type == 'PTR': # only ptr
if ':' in r['name']: # dirty ipv6 check
r_name = r['name']
record = { record = {
"name": r['name'] + '.', "name": r_name,
"type": r['type'], "type": r_type,
"changetype": "REPLACE", "changetype": "REPLACE",
"ttl": r['ttl'], "ttl": r['ttl'],
"records": [ "records": [
@ -892,10 +936,19 @@ class Record(object):
records = sorted(records, key = lambda item: (item["name"], item["type"], item["changetype"])) records = sorted(records, key = lambda item: (item["name"], item["type"], item["changetype"]))
for key, group in itertools.groupby(records, lambda item: (item["name"], item["type"], item["changetype"])): for key, group in itertools.groupby(records, lambda item: (item["name"], item["type"], item["changetype"])):
if NEW_SCHEMA: if NEW_SCHEMA:
r_name = key[0]
r_type = key[1]
r_changetype = key[2]
if PRETTY_IPV6_PTR: # only if activated
if r_type == 'PTR': # only ptr
if ':' in r_name: # dirty ipv6 check
r_name = dns.reversename.from_address(r_name).to_text()
new_record = { new_record = {
"name": key[0], "name": r_name,
"type": key[1], "type": r_type,
"changetype": key[2], "changetype": r_changetype,
"ttl": None, "ttl": None,
"records": [] "records": []
} }

View File

@ -311,6 +311,7 @@ def domain(domain_name):
if jr['type'] in app.config['RECORDS_ALLOW_EDIT']: if jr['type'] in app.config['RECORDS_ALLOW_EDIT']:
record = Record(name=jr['name'], type=jr['type'], status='Disabled' if jr['disabled'] else 'Active', ttl=jr['ttl'], data=jr['content']) record = Record(name=jr['name'], type=jr['type'], status='Disabled' if jr['disabled'] else 'Active', ttl=jr['ttl'], data=jr['content'])
records.append(record) records.append(record)
return render_template('domain.html', domain=domain, records=records, editable_records=app.config['RECORDS_ALLOW_EDIT']) return render_template('domain.html', domain=domain, records=records, editable_records=app.config['RECORDS_ALLOW_EDIT'])
else: else:
return redirect(url_for('error', code=404)) return redirect(url_for('error', code=404))
@ -408,24 +409,11 @@ def record_apply(domain_name):
try: try:
pdata = request.data pdata = request.data
jdata = json.loads(pdata) jdata = json.loads(pdata)
records = []
for j in jdata:
record = {
"name": domain_name if j['record_name'] in ['@', ''] else j['record_name'] + '.' + domain_name,
"type": j['record_type'],
"content": j['record_data'],
"disabled": True if j['record_status'] == 'Disabled' else False,
"name": domain_name if j['record_name'] in ['@', ''] else j['record_name'] + '.' + domain_name,
"ttl": int(j['record_ttl']) if j['record_ttl'] else 3600,
"type": j['record_type'],
}
records.append(record)
r = Record() r = Record()
result = r.apply(domain_name, records) result = r.apply(domain_name, jdata)
if result['status'] == 'ok': if result['status'] == 'ok':
history = History(msg='Apply record changes to domain %s' % domain_name, detail=str(records), created_by=current_user.username) history = History(msg='Apply record changes to domain %s' % domain_name, detail=str(jdata), created_by=current_user.username)
history.add() history.add()
return make_response(jsonify( result ), 200) return make_response(jsonify( result ), 200)
else: else:

View File

@ -76,3 +76,6 @@ PDNS_VERSION = '3.4.7'
# RECORDS ALLOWED TO EDIT # RECORDS ALLOWED TO EDIT
RECORDS_ALLOW_EDIT = ['A', 'AAAA', 'CNAME', 'SPF', 'PTR', 'MX', 'TXT'] RECORDS_ALLOW_EDIT = ['A', 'AAAA', 'CNAME', 'SPF', 'PTR', 'MX', 'TXT']
# EXPERIMENTAL FEATURES
PRETTY_IPV6_PTR = False

View File

@ -11,3 +11,4 @@ sqlalchemy-migrate==0.10.0
onetimepass==1.0.1 onetimepass==1.0.1
PyQRCode==1.2 PyQRCode==1.2
Flask-OAuthlib==0.9.3 Flask-OAuthlib==0.9.3
dnspython>=1.12.0