mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-09-19 04:59:01 +00:00
dynamicdns: Implement adding multiple domains
Tests: - Functional tests pass. - Adding domain triggers domain_added signal. - Editing a domain triggers domain removed and domain added signals. - Deleting a domain trigger domain removed signal. - For each of the action, the status table shows updated information. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
6d2f992a42
commit
4176f53e05
@ -12,8 +12,8 @@ from plinth import cfg
|
|||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
|
|
||||||
class ConfigureForm(forms.Form):
|
class DomainForm(forms.Form):
|
||||||
"""Form to configure the Dynamic DNS client."""
|
"""Form to add/edit a domain in the Dynamic DNS client."""
|
||||||
help_update_url = \
|
help_update_url = \
|
||||||
gettext_lazy('The Variables <User>, <Pass>, <Ip>, '
|
gettext_lazy('The Variables <User>, <Pass>, <Ip>, '
|
||||||
'<Domain> may be used within the URL. For details '
|
'<Domain> may be used within the URL. For details '
|
||||||
|
|||||||
@ -28,29 +28,29 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const FREEDNS = 'https://freedns.afraid.org/dynamic/update.php?' +
|
const FREEDNS = 'https://freedns.afraid.org/dynamic/update.php?' +
|
||||||
'_YOURAPIKEYHERE_';
|
'_YOURAPIKEYHERE_';
|
||||||
|
|
||||||
document.getElementById('id_service_type').addEventListener('change', () => {
|
document.getElementById('id_domain-service_type').addEventListener('change', () => {
|
||||||
setMode();
|
setMode();
|
||||||
|
|
||||||
const service_type = document.getElementById('id_service_type').value;
|
const service_type = document.getElementById('id_domain-service_type').value;
|
||||||
if (service_type === "noip.com") {
|
if (service_type === "noip.com") {
|
||||||
document.getElementById('id_update_url').value = NOIP;
|
document.getElementById('id_domain-update_url').value = NOIP;
|
||||||
} else if (service_type === "freedns.afraid.org") {
|
} else if (service_type === "freedns.afraid.org") {
|
||||||
document.getElementById('id_update_url').value = FREEDNS;
|
document.getElementById('id_domain-update_url').value = FREEDNS;
|
||||||
} else { // GnuDIP and other
|
} else { // GnuDIP and other
|
||||||
document.getElementById('id_update_url').value = '';
|
document.getElementById('id_domain-update_url').value = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('id_show_password').addEventListener('change', () => {
|
document.getElementById('id_domain-show_password').addEventListener('change', () => {
|
||||||
if (document.getElementById('id_show_password').checked) {
|
if (document.getElementById('id_domain-show_password').checked) {
|
||||||
document.getElementById('id_password').type = 'text';
|
document.getElementById('id_domain-password').type = 'text';
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('id_password').type = 'password';
|
document.getElementById('id_domain-password').type = 'password';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function setMode() {
|
function setMode() {
|
||||||
const service_type = document.getElementById('id_service_type').value;
|
const service_type = document.getElementById('id_domain-service_type').value;
|
||||||
if (service_type === "gnudip") {
|
if (service_type === "gnudip") {
|
||||||
setGnudipMode();
|
setGnudipMode();
|
||||||
} else {
|
} else {
|
||||||
@ -62,19 +62,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
document.querySelectorAll('.form-group').forEach((element) => {
|
document.querySelectorAll('.form-group').forEach((element) => {
|
||||||
element.style.display = 'block';
|
element.style.display = 'block';
|
||||||
});
|
});
|
||||||
document.getElementById('id_update_url').closest('.form-group').style.display = 'none';
|
document.getElementById('id_domain-update_url').closest('.form-group').style.display = 'none';
|
||||||
document.getElementById('id_disable_ssl_cert_check').closest('.form-group').style.display = 'none';
|
document.getElementById('id_domain-disable_ssl_cert_check').closest('.form-group').style.display = 'none';
|
||||||
document.getElementById('id_use_http_basic_auth').closest('.form-group').style.display = 'none';
|
document.getElementById('id_domain-use_http_basic_auth').closest('.form-group').style.display = 'none';
|
||||||
document.getElementById('id_use_ipv6').closest('.form-group').style.display = 'none';
|
document.getElementById('id_domain-use_ipv6').closest('.form-group').style.display = 'none';
|
||||||
document.getElementById('id_server').closest('.form-group').style.display = 'block';
|
document.getElementById('id_domain-server').closest('.form-group').style.display = 'block';
|
||||||
}
|
}
|
||||||
|
|
||||||
function setUpdateUrlMode() {
|
function setUpdateUrlMode() {
|
||||||
document.getElementById('id_update_url').closest('.form-group').style.display = 'block';
|
document.getElementById('id_domain-update_url').closest('.form-group').style.display = 'block';
|
||||||
document.getElementById('id_disable_ssl_cert_check').closest('.form-group').style.display = 'block';
|
document.getElementById('id_domain-disable_ssl_cert_check').closest('.form-group').style.display = 'block';
|
||||||
document.getElementById('id_use_http_basic_auth').closest('.form-group').style.display = 'block';
|
document.getElementById('id_domain-use_http_basic_auth').closest('.form-group').style.display = 'block';
|
||||||
document.getElementById('id_use_ipv6').closest('.form-group').style.display = 'block';
|
document.getElementById('id_domain-use_ipv6').closest('.form-group').style.display = 'block';
|
||||||
document.getElementById('id_server').closest('.form-group').style.display = 'none';
|
document.getElementById('id_domain-server').closest('.form-group').style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
setMode();
|
setMode();
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% comment %}
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h3>{{ title }}</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
App configurations will be updated.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<form class="form form-delete" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
<input type="submit" class="btn btn-md btn-danger"
|
||||||
|
value="{% blocktrans %}Delete{% endblocktrans %}"/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
11
plinth/modules/dynamicdns/templates/dynamicdns-domain.html
Normal file
11
plinth/modules/dynamicdns/templates/dynamicdns-domain.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{% extends "form.html" %}
|
||||||
|
{% comment %}
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block page_js %}
|
||||||
|
<script type="text/javascript" src="{% static 'dynamicdns/dynamicdns.js' %}"
|
||||||
|
defer></script>
|
||||||
|
{% endblock %}
|
||||||
@ -5,18 +5,20 @@
|
|||||||
|
|
||||||
{% load bootstrap %}
|
{% load bootstrap %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
{% block page_js %}
|
|
||||||
<script type="text/javascript" src="{% static 'dynamicdns/dynamicdns.js' %}"
|
|
||||||
defer></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block extra_content %}
|
{% block extra_content %}
|
||||||
<h3>{% trans "Status" %}</h3>
|
<h3>{% trans "Domains" %}</h3>
|
||||||
|
|
||||||
|
<div class="btn-toolbar">
|
||||||
|
<a href="{% url 'dynamicdns:domain-add' %}" class="btn btn-primary"
|
||||||
|
role="button" title="{% trans 'Add Domain' %}">
|
||||||
|
<span class="fa fa-plus" aria-hidden="true"></span>
|
||||||
|
{% trans 'Add Domain' %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if domains_status %}
|
{% if domains_status %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive domains-status">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -24,12 +26,20 @@
|
|||||||
<th>{% trans "Last update" %}</th>
|
<th>{% trans "Last update" %}</th>
|
||||||
<th>{% trans "Result" %}</th>
|
<th>{% trans "Result" %}</th>
|
||||||
<th>{% trans "IP Address" %}</th>
|
<th>{% trans "IP Address" %}</th>
|
||||||
|
<th>{% trans "Actions" %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for domain in domains_status.values %}
|
{% for domain in domains_status.values %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ domain.domain }}</td>
|
<td class="domain-name">
|
||||||
|
<a href="{% url 'dynamicdns:domain-edit' domain.domain %}"
|
||||||
|
title="{% blocktrans trimmed with domain=domain.domain %}
|
||||||
|
Edit domain {{ domain }}
|
||||||
|
{% endblocktrans %}">
|
||||||
|
{{ domain.domain }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td>{{ domain.timestamp|timesince }}</td>
|
<td>{{ domain.timestamp|timesince }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if domain.result %}
|
{% if domain.result %}
|
||||||
@ -48,12 +58,28 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ domain.ip_address|default_if_none:'-' }}</td>
|
<td>{{ domain.ip_address|default_if_none:'-' }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{% url 'dynamicdns:domain-edit' domain.domain %}"
|
||||||
|
class="btn btn-default btn-sm domain-edit" role="button"
|
||||||
|
title="{% blocktrans trimmed with domain=domain.domain %}
|
||||||
|
Edit domain {{ domain }}
|
||||||
|
{% endblocktrans %}">
|
||||||
|
<span class="fa fa-pencil-square-o" aria-hidden="true"></span>
|
||||||
|
</a>
|
||||||
|
<a href="{% url 'dynamicdns:domain-delete' domain.domain %}"
|
||||||
|
class="btn btn-default btn-sm domain-delete" role="button"
|
||||||
|
title="{% blocktrans trimmed with domain=domain.main %}
|
||||||
|
Delete domain {{ domain }}
|
||||||
|
{% endblocktrans %}">
|
||||||
|
<span class="fa fa-trash" aria-hidden="true"></span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% trans "No status available." %}
|
<p>{% trans "No domains configured." %}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@ -76,8 +76,8 @@ class TestDynamicDNSApp(functional.BaseAppTests):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def test_capitalized_domain_name(session_browser):
|
def test_capitalized_domain_name(session_browser):
|
||||||
"""Test handling of capitalized domain name."""
|
"""Test handling of capitalized domain name."""
|
||||||
_configure(session_browser, _configs['gnudip1'])
|
config = dict(_configs['gnudip1'], domain='FreedomBox.example.com')
|
||||||
_configure(session_browser, {'domain': 'FreedomBox.example.com'})
|
_configure(session_browser, config)
|
||||||
_assert_has_config(session_browser,
|
_assert_has_config(session_browser,
|
||||||
{'domain': 'freedombox.example.com'})
|
{'domain': 'freedombox.example.com'})
|
||||||
|
|
||||||
@ -105,32 +105,54 @@ class TestDynamicDNSApp(functional.BaseAppTests):
|
|||||||
|
|
||||||
def _configure(browser, config):
|
def _configure(browser, config):
|
||||||
functional.nav_to_module(browser, 'dynamicdns')
|
functional.nav_to_module(browser, 'dynamicdns')
|
||||||
|
current_domains = _get_domains(browser)
|
||||||
|
for domain in current_domains:
|
||||||
|
if domain.endswith('.example.com'):
|
||||||
|
_delete_domain(browser, domain)
|
||||||
|
|
||||||
|
functional.nav_to_module(browser, 'dynamicdns')
|
||||||
|
functional.click_link_by_href(browser,
|
||||||
|
'/plinth/sys/dynamicdns/domain/add/')
|
||||||
for key, value in config.items():
|
for key, value in config.items():
|
||||||
|
field_id = f'id_domain-{key}'
|
||||||
if key == 'service_type':
|
if key == 'service_type':
|
||||||
browser.find_by_id(f'id_{key}').select(value)
|
browser.find_by_id(field_id).select(value)
|
||||||
elif isinstance(value, bool):
|
elif isinstance(value, bool):
|
||||||
if value:
|
if value:
|
||||||
browser.find_by_id(f'id_{key}').check()
|
browser.find_by_id(field_id).check()
|
||||||
else:
|
else:
|
||||||
browser.find_by_id(f'id_{key}').uncheck()
|
browser.find_by_id(field_id).uncheck()
|
||||||
else:
|
else:
|
||||||
browser.find_by_id(f'id_{key}').fill(value)
|
browser.find_by_id(field_id).fill(value)
|
||||||
|
|
||||||
functional.submit(browser, form_class='form-configuration')
|
functional.submit(browser, form_class='form-domain')
|
||||||
|
|
||||||
|
|
||||||
def _assert_has_config(browser, config):
|
def _assert_has_config(browser, config):
|
||||||
functional.nav_to_module(browser, 'dynamicdns')
|
functional.nav_to_module(browser, 'dynamicdns')
|
||||||
|
link = f'/plinth/sys/dynamicdns/domain/{config["domain"]}/edit/'
|
||||||
|
functional.click_link_by_href(browser, link)
|
||||||
for key, value in config.items():
|
for key, value in config.items():
|
||||||
if key == 'password':
|
if key == 'password':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
field_id = f'id_domain-{key}'
|
||||||
if isinstance(value, bool):
|
if isinstance(value, bool):
|
||||||
assert browser.find_by_id(f'id_{key}').checked == value
|
assert browser.find_by_id(field_id).checked == value
|
||||||
else:
|
else:
|
||||||
assert value == browser.find_by_id(f'id_{key}').value
|
assert value == browser.find_by_id(field_id).value
|
||||||
|
|
||||||
|
|
||||||
def _get_domain(browser):
|
def _get_domains(browser):
|
||||||
|
"""Return the list of configured domains."""
|
||||||
functional.nav_to_module(browser, 'dynamicdns')
|
functional.nav_to_module(browser, 'dynamicdns')
|
||||||
return browser.find_by_id('id_domain').value
|
elements = browser.find_by_css('.domains-status .domain-name a')
|
||||||
|
return [element.text.strip() for element in elements]
|
||||||
|
|
||||||
|
|
||||||
|
def _delete_domain(browser, domain):
|
||||||
|
"""Delete a given domain."""
|
||||||
|
functional.nav_to_module(browser, 'dynamicdns')
|
||||||
|
link = f'/plinth/sys/dynamicdns/domain/{domain}/delete/'
|
||||||
|
functional.click_link_by_href(browser, link)
|
||||||
|
functional.submit(browser, form_class='form-delete')
|
||||||
|
|||||||
@ -10,4 +10,10 @@ from . import views
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
re_path(r'^sys/dynamicdns/$', views.DynamicDNSAppView.as_view(),
|
re_path(r'^sys/dynamicdns/$', views.DynamicDNSAppView.as_view(),
|
||||||
name='index'),
|
name='index'),
|
||||||
|
re_path(r'^sys/dynamicdns/domain/add/$', views.DomainView.as_view(),
|
||||||
|
name='domain-add'),
|
||||||
|
re_path(r'^sys/dynamicdns/domain/(?P<domain>[^/]+)/edit/$',
|
||||||
|
views.DomainView.as_view(), name='domain-edit'),
|
||||||
|
re_path(r'^sys/dynamicdns/domain/(?P<domain>[^/]+)/delete/$',
|
||||||
|
views.DomainDeleteView.as_view(), name='domain-delete'),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,24 +1,26 @@
|
|||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
"""
|
"""Views for the dynamicsdns module."""
|
||||||
Views for the dynamicsdns module.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.urls import reverse_lazy
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.views.generic import TemplateView
|
||||||
|
from django.views.generic.edit import FormView
|
||||||
|
|
||||||
from plinth import views
|
from plinth import views
|
||||||
from plinth.modules import dynamicdns
|
from plinth.modules import dynamicdns
|
||||||
|
|
||||||
from .forms import ConfigureForm
|
from .forms import DomainForm
|
||||||
|
|
||||||
|
|
||||||
class DynamicDNSAppView(views.AppView):
|
class DynamicDNSAppView(views.AppView):
|
||||||
"""Serve configuration page."""
|
"""View to show app status."""
|
||||||
|
|
||||||
app_id = 'dynamicdns'
|
app_id = 'dynamicdns'
|
||||||
template_name = 'dynamicdns.html'
|
template_name = 'dynamicdns.html'
|
||||||
form_class = ConfigureForm
|
|
||||||
|
|
||||||
_error_messages = {
|
_error_messages = {
|
||||||
'timeout': _('Connection timed out'),
|
'timeout': _('Connection timed out'),
|
||||||
@ -31,8 +33,10 @@ class DynamicDNSAppView(views.AppView):
|
|||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Return the context data for rendering the template view."""
|
"""Return the context data for rendering the template view."""
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
status = dynamicdns.get_status()
|
|
||||||
config = dynamicdns.get_config()
|
config = dynamicdns.get_config()
|
||||||
|
context['domains'] = config['domains']
|
||||||
|
|
||||||
|
status = dynamicdns.get_status()
|
||||||
domains_status = {}
|
domains_status = {}
|
||||||
for domain_name, domain in status['domains'].items():
|
for domain_name, domain in status['domains'].items():
|
||||||
if domain_name not in config['domains']:
|
if domain_name not in config['domains']:
|
||||||
@ -49,11 +53,35 @@ class DynamicDNSAppView(views.AppView):
|
|||||||
context['domains_status'] = domains_status
|
context['domains_status'] = domains_status
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class DomainView(FormView):
|
||||||
|
"""View to add/edit a dynamic DNS domain."""
|
||||||
|
|
||||||
|
template_name = 'dynamicdns-domain.html'
|
||||||
|
form_class = DomainForm
|
||||||
|
prefix = 'domain'
|
||||||
|
success_url = reverse_lazy('dynamicdns:index')
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
"""Return the context data for rendering the template view."""
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
domain_name = self.kwargs.get('domain')
|
||||||
|
if not domain_name:
|
||||||
|
context['title'] = _('Add Dynamic Domain')
|
||||||
|
else:
|
||||||
|
context['title'] = _('Edit Dynamic Domain')
|
||||||
|
|
||||||
|
return context
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
"""Get the current values for the form."""
|
"""Get the current values for the form."""
|
||||||
initial = super().get_initial()
|
initial = super().get_initial()
|
||||||
|
domain_name = self.kwargs.get('domain')
|
||||||
domains = dynamicdns.get_config()['domains']
|
domains = dynamicdns.get_config()['domains']
|
||||||
domain = list(domains.values())[0] if domains else {}
|
domain = {}
|
||||||
|
if domains and domain_name and domain_name in domains:
|
||||||
|
domain = domains[domain_name]
|
||||||
|
|
||||||
initial.update(domain)
|
initial.update(domain)
|
||||||
return domain
|
return domain
|
||||||
|
|
||||||
@ -63,21 +91,59 @@ class DynamicDNSAppView(views.AppView):
|
|||||||
new_status = form.cleaned_data
|
new_status = form.cleaned_data
|
||||||
|
|
||||||
if old_status != new_status:
|
if old_status != new_status:
|
||||||
config = dynamicdns.get_config()
|
|
||||||
try:
|
try:
|
||||||
del config['domains'][old_status['domain']]
|
_domain_delete(old_status['domain'])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
config['domains'][new_status['domain']] = new_status
|
_domain_add(new_status['domain'], new_status)
|
||||||
dynamicdns.set_config(config)
|
|
||||||
if old_status.get('domain'):
|
|
||||||
dynamicdns.notify_domain_removed(old_status['domain'])
|
|
||||||
|
|
||||||
dynamicdns.notify_domain_added(new_status['domain'])
|
|
||||||
messages.success(self.request, _('Configuration updated'))
|
messages.success(self.request, _('Configuration updated'))
|
||||||
|
|
||||||
# Perform an immediate update, even when configuration is not changed.
|
# Perform an immediate update, even when configuration is not changed.
|
||||||
dynamicdns.update_dns(None)
|
dynamicdns.update_dns(None)
|
||||||
|
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
def _domain_add(domain: str, domain_config: dict):
|
||||||
|
"""Add a domain to the configuration."""
|
||||||
|
config = dynamicdns.get_config()
|
||||||
|
config['domains'][domain] = domain_config
|
||||||
|
dynamicdns.set_config(config)
|
||||||
|
dynamicdns.notify_domain_added(domain)
|
||||||
|
|
||||||
|
|
||||||
|
def _domain_delete(domain: str):
|
||||||
|
"""Remove a domain from the configuration.
|
||||||
|
|
||||||
|
Raises KeyError if the domain is not found in the configuration.
|
||||||
|
"""
|
||||||
|
config = dynamicdns.get_config()
|
||||||
|
del config['domains'][domain]
|
||||||
|
dynamicdns.set_config(config)
|
||||||
|
if domain:
|
||||||
|
dynamicdns.notify_domain_removed(domain)
|
||||||
|
|
||||||
|
|
||||||
|
class DomainDeleteView(TemplateView):
|
||||||
|
"""Confirm and delete a domain."""
|
||||||
|
template_name = 'dynamicdns-domain-delete.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
"""Return additional context data for rendering the template."""
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
domain = self.kwargs['domain']
|
||||||
|
context['domain'] = domain
|
||||||
|
context['title'] = str(
|
||||||
|
_('Delete Domain {domain}?')).format(domain=domain)
|
||||||
|
return context
|
||||||
|
|
||||||
|
def post(self, request, domain):
|
||||||
|
"""Delete a domain."""
|
||||||
|
try:
|
||||||
|
_domain_delete(domain)
|
||||||
|
messages.success(request, _('Domain deleted.'))
|
||||||
|
except KeyError:
|
||||||
|
raise
|
||||||
|
|
||||||
|
return redirect('dynamicdns:index')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user