Add PDNS global search feature

This commit is contained in:
Khanh Ngo 2019-12-11 09:55:18 +07:00
parent 67e6df6880
commit de69eaf825
No known key found for this signature in database
GPG key ID: D5FAA6A16150E49E
4 changed files with 256 additions and 0 deletions

View file

@ -61,3 +61,26 @@ class Server(object):
"Can not get server statistics. DETAIL: {0}".format(e))
current_app.logger.debug(traceback.format_exc())
return []
def global_search(self, object_type='all', query=''):
"""
Search zone/record/comment directly from PDNS API
"""
headers = {}
headers['X-API-Key'] = self.PDNS_API_KEY
try:
jdata = utils.fetch_json(urljoin(
self.PDNS_STATS_URL, self.API_EXTENDED_URL +
'/servers/{}/search-data?object_type={}&q={}'.format(
self.server_id, object_type, query)),
headers=headers,
timeout=int(
Setting().get('pdns_api_timeout')),
method='GET')
return jdata
except Exception as e:
current_app.logger.error(
"Can not make global search. DETAIL: {0}".format(e))
current_app.logger.debug(traceback.format_exc())
return []

View file

@ -1015,3 +1015,44 @@ def delete_template(template):
current_app.logger.debug(traceback.format_exc())
abort(500)
return redirect(url_for('admin.templates'))
@admin_bp.route('/global-search', methods=['GET', 'POST'])
@login_required
@operator_role_required
def global_search():
if request.method == 'GET':
domains = []
records = []
comments = []
query = request.args.get('q')
if query:
server = Server(server_id='localhost')
results = server.global_search(object_type='all', query=query)
# Format the search result
for result in results:
if result['object_type'] == 'zone':
# Remove the dot at the end of string
result['name'] = result['name'][:-1]
domains.append(result)
elif result['object_type'] == 'record':
# Remove the dot at the end of string
result['name'] = result['name'][:-1]
result['zone_id'] = result['zone_id'][:-1]
records.append(result)
elif result['object_type'] == 'comment':
# Get the actual record name, exclude the domain part
result['name'] = result['name'].replace(result['zone_id'], '')
if result['name']:
result['name'] = result['name'][:-1]
else:
result['name'] = '@'
# Remove the dot at the end of string
result['zone_id'] = result['zone_id'][:-1]
comments.append(result)
else:
pass
return render_template('admin_global_search.html', domains=domains, records=records, comments=comments)

View file

@ -0,0 +1,189 @@
{% extends "base.html" %}
{% set active_page = "admin_global_search" %}
{% block title %}
<title>Global Search - {{ SITE_NAME }}</title>
{% endblock %} {% block dashboard_stat %}
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
Global Search <small>Search for domains, records and comments directly from PDNS API</small>
</h1>
<ol class="breadcrumb">
<li><a href="{{ url_for('dashboard.dashboard') }}"><i class="fa fa-dashboard"></i> Home</a></li>
<li class="active">Global Search</li>
</ol>
</section>
{% endblock %} {% block content %}
<section class="content">
<div class="row">
<div class="col-xs-12">
<div class="box-body">
<!-- search form -->
<form action="#" method="get">
<div class="input-group">
<input type="text" name="q" class="form-control" placeholder="Your keyword...">
<div class="input-group-btn">
<button type="submit" class="btn btn-success"><i class="fa fa-search"></i></button>
</div>
</div>
</form>
<div>
<p><b>Hints:</b> The * character can be used in your keyword as a wildcard character and the ? character can be used as a wildcard for a
single character.</p>
</div>
<!-- /.search form -->
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-header">
<h3 class="box-title">Domains ({{ domains|length }})</h3>
</div>
<div class="box-body">
<table id="tbl_domain" class="table table-bordered table-striped">
<thead>
<tr>
<th>Domain</th>
</tr>
</thead>
<tbody>
{% for domain in domains %}
<tr class="odd gradeX">
<td>
<a href="{{ url_for('domain.domain', domain_name=domain['name']) }}">{{ domain['name'] }}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
<!-- /.col -->
</div>
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-header">
<h3 class="box-title">Records ({{ records|length }})</h3>
</div>
<div class="box-body">
<table id="tbl_record" class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Status</th>
<th>TTL</th>
<th>Data</th>
</tr>
</thead>
<tbody>
{% for record in records %}
<tr class="odd gradeX">
<td>
<a href="{{ url_for('domain.domain', domain_name=record['zone_id']) }}">{{ record['name'] }}</a>
</td>
<td>{{ record['type'] }}</td>
<td>{{ 'Disabled' if record['disabled'] else 'Active' }}</td>
<td>{{ record['ttl'] }}</td>
<td>{{ record['content'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
<!-- /.col -->
</div>
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-header">
<h3 class="box-title">Comments ({{ comments|length }})</h3>
</div>
<div class="box-body">
<table id="tbl_comment" class="table table-bordered table-striped">
<thead>
<tr>
<th>Comment</th>
<th>Record</th>
<th>Domain</th>
</tr>
</thead>
<tbody>
{% for comment in comments %}
<tr class="odd gradeX">
<td>{{ comment['content'] }}</td>
<td>{{ comment['name'] }}</td>
<td>
<a href="{{ url_for('domain.domain', domain_name=comment['zone_id']) }}">{{ comment['zone_id'] }}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
<!-- /.col -->
</div>
</section>
{% endblock %}
{% block extrascripts %}
<script>
// set up domain result data table
$("#tbl_domain").DataTable({
"paging": false,
"lengthChange": false,
"searching": false,
"ordering": true,
"info": false,
"autoWidth": false,
"order": [
[0, "asc"]
]
});
</script>
<script>
// set up domain result data table
$("#tbl_record").DataTable({
"paging": false,
"lengthChange": false,
"searching": false,
"ordering": true,
"info": false,
"autoWidth": false,
"order": [
[0, "asc"]
]
});
</script>
<script>
// set up domain result data table
$("#tbl_comment").DataTable({
"paging": false,
"lengthChange": false,
"searching": false,
"ordering": true,
"info": false,
"autoWidth": false,
"order": [
[0, "asc"]
]
});
</script>
{% endblock %}

View file

@ -106,6 +106,9 @@
<li class="{{ 'active' if active_page == 'admin_console' else '' }}">
<a href="{{ url_for('admin.pdns_stats') }}"><i class="fa fa-info-circle"></i> <span>PDNS</span></a>
</li>
<li class="{{ 'active' if active_page == 'admin_global_search' else '' }}">
<a href="{{ url_for('admin.global_search') }}"><i class="fa fa-search"></i> <span>Global Search</span></a>
</li>
<li class="{{ 'active' if active_page == 'admin_history' else '' }}">
<a href="{{ url_for('admin.history') }}"><i class="fa fa-calendar"></i> <span>History</span></a>
</li>