Support IDN domain

This commit is contained in:
Khanh Ngo 2019-12-08 14:32:38 +07:00
parent 354383f0ec
commit 26a43c174c
No known key found for this signature in database
GPG key ID: D5FAA6A16150E49E
6 changed files with 41 additions and 10 deletions

View file

@ -65,6 +65,7 @@ def create_app(config=None):
'email_to_gravatar_url'] = utils.email_to_gravatar_url 'email_to_gravatar_url'] = utils.email_to_gravatar_url
app.jinja_env.filters[ app.jinja_env.filters[
'display_setting_state'] = utils.display_setting_state 'display_setting_state'] = utils.display_setting_state
app.jinja_env.filters['pretty_domain_name'] = utils.pretty_domain_name
# Register context proccessors # Register context proccessors
from .models.setting import Setting from .models.setting import Setting

View file

@ -300,6 +300,24 @@ def validate_ipaddress(address):
return [] return []
def pretty_domain_name(value):
"""
Display domain name in original format.
If it is IDN domain (Punycode starts with xn--), do the
idna decoding.
"""
if isinstance(value, str):
if value.startswith('xn--'):
try:
return value.encode().decode('idna')
except:
raise Exception("Cannot decode IDN domain")
else:
return value
else:
raise Exception("Require the Punycode in sring format")
class customBoxes: class customBoxes:
boxes = { boxes = {
"reverse": (" ", " "), "reverse": (" ", " "),

View file

@ -5,6 +5,7 @@ from distutils.version import StrictVersion
from flask import Blueprint, render_template, make_response, url_for, current_app, request, redirect, abort, jsonify from flask import Blueprint, render_template, make_response, url_for, current_app, request, redirect, abort, jsonify
from flask_login import login_required, current_user from flask_login import login_required, current_user
from ..lib.utils import pretty_domain_name
from ..decorators import can_create_domain, operator_role_required, can_access_domain, can_configure_dnssec from ..decorators import can_create_domain, operator_role_required, can_access_domain, can_configure_dnssec
from ..models.user import User from ..models.user import User
from ..models.account import Account from ..models.account import Account
@ -111,6 +112,15 @@ def add():
return render_template('errors/400.html', return render_template('errors/400.html',
msg="Please enter a valid domain name"), 400 msg="Please enter a valid domain name"), 400
try:
domain_name = domain_name.encode('idna').decode()
except:
current_app.logger.error("Cannot encode the domain name {}".format(domain_name))
current_app.logger.debug(traceback.format_exc())
return render_template(
'errors/400.html',
msg="Please enter a valid domain name"), 400
if domain_type == 'slave': if domain_type == 'slave':
if request.form.getlist('domain_master_address'): if request.form.getlist('domain_master_address'):
domain_master_string = request.form.getlist( domain_master_string = request.form.getlist(
@ -130,7 +140,8 @@ def add():
domain_master_ips=domain_master_ips, domain_master_ips=domain_master_ips,
account_name=account_name) account_name=account_name)
if result['status'] == 'ok': if result['status'] == 'ok':
history = History(msg='Add domain {0}'.format(domain_name), history = History(msg='Add domain {0}'.format(
pretty_domain_name(domain_name)),
detail=str({ detail=str({
'domain_type': domain_type, 'domain_type': domain_type,
'domain_master_ips': domain_master_ips, 'domain_master_ips': domain_master_ips,

View file

@ -1,5 +1,5 @@
{% macro name(domain) %} {% macro name(domain) %}
<a href="{{ url_for('domain.domain', domain_name=domain.name) }}"><strong>{{ domain.name }}</strong></a> <a href="{{ url_for('domain.domain', domain_name=domain.name) }}"><strong>{{ domain.name | pretty_domain_name }}</strong></a>
{% endmacro %} {% endmacro %}
{% macro dnssec(domain) %} {% macro dnssec(domain) %}

View file

@ -1,16 +1,16 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}<title>{{ domain.name }} - {{ SITE_NAME }}</title>{% endblock %} {% block title %}<title>{{ domain.name | pretty_domain_name }} - {{ SITE_NAME }}</title>{% endblock %}
{% block dashboard_stat %} {% block dashboard_stat %}
<section class="content-header"> <section class="content-header">
<h1> <h1>
Manage domain: <b>{{ domain.name }}</b> Manage domain: <b>{{ domain.name | pretty_domain_name }}</b>
</h1> </h1>
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><a href="{{ url_for('dashboard.dashboard') }}"><i <li><a href="{{ url_for('dashboard.dashboard') }}"><i
class="fa fa-dashboard"></i> Home</a></li> class="fa fa-dashboard"></i> Home</a></li>
<li>Domain</li> <li>Domain</li>
<li class="active">{{ domain.name }}</li> <li class="active">{{ domain.name | pretty_domain_name }}</li>
</ol> </ol>
</section> </section>
{% endblock %} {% endblock %}

View file

@ -19,7 +19,7 @@
{% endif %} {% endif %}
<section class="content-header"> <section class="content-header">
<h1> <h1>
Manage domain <small>{{ domain.name }}</small> Manage domain <small>{{ domain.name | pretty_domain_name }}</small>
</h1> </h1>
<ol class="breadcrumb"> <ol class="breadcrumb">
<li><a href="{{ url_for('dashboard.dashboard') }}"><i class="fa fa-dashboard"></i> Home</a></li> <li><a href="{{ url_for('dashboard.dashboard') }}"><i class="fa fa-dashboard"></i> Home</a></li>
@ -42,7 +42,7 @@
<div class="row"> <div class="row">
<div class="col-xs-2"> <div class="col-xs-2">
<p>Users on the right have access to manage the records in <p>Users on the right have access to manage the records in
the {{ domain.name }} domain.</p> the {{ domain.name | pretty_domain_name }} domain.</p>
<p>Click on users to move from between columns.</p> <p>Click on users to move from between columns.</p>
<p> <p>
Users in <font style="color: red;">red</font> are Administrators Users in <font style="color: red;">red</font> are Administrators
@ -94,7 +94,7 @@
{% endfor %} {% endfor %}
</select><br /> </select><br />
<button type="submit" class="btn btn-flat btn-primary" id="change_soa_edit_api"> <button type="submit" class="btn btn-flat btn-primary" id="change_soa_edit_api">
<i class="fa fa-check"></i>&nbsp;Change account for {{ domain.name }} <i class="fa fa-check"></i>&nbsp;Change account for {{ domain.name | pretty_domain_name }}
</button> </button>
</form> </form>
</div> </div>
@ -170,7 +170,8 @@
<option>OFF</option> <option>OFF</option>
</select><br /> </select><br />
<button type="submit" class="btn btn-flat btn-primary" id="change_soa_edit_api"> <button type="submit" class="btn btn-flat btn-primary" id="change_soa_edit_api">
<i class="fa fa-check"></i>&nbsp;Change SOA-EDIT-API setting for {{ domain.name }} <i class="fa fa-check"></i>&nbsp;Change SOA-EDIT-API setting for
{{ domain.name | pretty_domain_name }}
</button> </button>
</form> </form>
</div> </div>
@ -189,7 +190,7 @@
reverted.</p> reverted.</p>
<button type="button" class="btn btn-flat btn-danger pull-left delete_domain" <button type="button" class="btn btn-flat btn-danger pull-left delete_domain"
id="{{ domain.name }}"> id="{{ domain.name }}">
<i class="fa fa-trash"></i>&nbsp;DELETE DOMAIN {{ domain.name }} <i class="fa fa-trash"></i>&nbsp;DELETE DOMAIN {{ domain.name | pretty_domain_name}}
</button> </button>
</div> </div>
</div> </div>