mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
Test: - Submit the domain form unchanged. Message is printed that settings are unchanged. - Submit the domain form with changes. Message is printed that domain has been updated. Configuration reflects the new domain. - On page load, the current domain is shown in the domain configuration form. - Clicking the repair button the service alert section triggers the repair operations as seen in the console. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
222 lines
7.8 KiB
Python
222 lines
7.8 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""
|
|
Views for the email app.
|
|
"""
|
|
|
|
from django.contrib import messages
|
|
from django.core.exceptions import ValidationError
|
|
from django.http import HttpResponseBadRequest
|
|
from django.shortcuts import redirect
|
|
from django.urls import reverse_lazy
|
|
from django.utils.translation import gettext_lazy as _
|
|
from django.views.generic.base import TemplateView, View
|
|
from django.views.generic.edit import FormView
|
|
|
|
import plinth.actions
|
|
import plinth.utils
|
|
from plinth.views import AppView
|
|
|
|
from . import aliases as aliases_module
|
|
from . import audit, forms
|
|
|
|
|
|
class ExceptionsMixin(View):
|
|
|
|
def render_validation_error(self, validation_error, status=400):
|
|
context = self.get_context_data()
|
|
context['error'] = validation_error
|
|
return self.render_to_response(context, status=status)
|
|
|
|
def render_exception(self, exception, status=500):
|
|
context = self.get_context_data()
|
|
context['error'] = [str(exception)]
|
|
return self.render_to_response(context, status=status)
|
|
|
|
def catch_exceptions(self, function, request):
|
|
try:
|
|
return function(request)
|
|
except ValidationError as validation_error:
|
|
return self.render_validation_error(validation_error)
|
|
except Exception as error:
|
|
return self.render_exception(error)
|
|
|
|
|
|
class EmailServerView(ExceptionsMixin, AppView):
|
|
"""Server configuration page"""
|
|
app_id = 'email_server'
|
|
form_class = forms.DomainForm
|
|
template_name = 'email_server.html'
|
|
audit_modules = ('tls', 'rcube')
|
|
|
|
def get_initial(self):
|
|
"""Return the initial values to populate in the form."""
|
|
initial = super().get_initial()
|
|
domains = audit.domain.get_domains()
|
|
initial['primary_domain'] = domains['primary_domain']
|
|
return initial
|
|
|
|
def get_context_data(self, *args, **kwargs):
|
|
context = super().get_context_data(*args, **kwargs)
|
|
|
|
dlist = []
|
|
for module_name in self.audit_modules:
|
|
self._get_audit_results(module_name, dlist)
|
|
dlist.sort(key=audit.models.Diagnosis.sorting_key)
|
|
|
|
context['related_diagnostics'] = dlist
|
|
return context
|
|
|
|
def _get_audit_results(self, module_name, dlist):
|
|
try:
|
|
results = getattr(audit, module_name).get()
|
|
except Exception as e:
|
|
title = _('Internal error in {0}').format('audit.' + module_name)
|
|
diagnosis = audit.models.Diagnosis(title)
|
|
diagnosis.critical(str(e))
|
|
diagnosis.critical(_('Check syslog for more information'))
|
|
results = [diagnosis]
|
|
|
|
for diagnosis in results:
|
|
if diagnosis.action:
|
|
diagnosis.action = '%s.%s' % (module_name, diagnosis.action)
|
|
if diagnosis.has_failed:
|
|
dlist.append(diagnosis)
|
|
|
|
def post(self, request):
|
|
repair_field = request.POST.get('repair')
|
|
if repair_field:
|
|
module_name, sep, action_name = repair_field.partition('.')
|
|
if not sep or module_name not in self.audit_modules:
|
|
return HttpResponseBadRequest('Bad post data')
|
|
|
|
self._repair(module_name, action_name)
|
|
return redirect(request.path)
|
|
|
|
return super().post(request)
|
|
|
|
def form_valid(self, form):
|
|
"""Update the settings for changed domain values."""
|
|
old_data = form.initial
|
|
new_data = form.cleaned_data
|
|
if old_data['primary_domain'] != new_data['primary_domain']:
|
|
try:
|
|
audit.domain.set_domains(new_data['primary_domain'])
|
|
messages.success(self.request, _('Configuration updated'))
|
|
except Exception:
|
|
messages.success(self.request,
|
|
_('An error occurred during configuration.'))
|
|
|
|
return super().form_valid(form)
|
|
|
|
def _repair(self, module_name, action_name):
|
|
"""Repair the configuration of the given audit module."""
|
|
module = getattr(audit, module_name)
|
|
if not hasattr(module, 'repair_component'):
|
|
return
|
|
|
|
reload_list = []
|
|
try:
|
|
reload_list = module.repair_component(action_name)
|
|
except Exception:
|
|
pass
|
|
|
|
for service in reload_list:
|
|
# plinth.action_utils.service_reload(service)
|
|
plinth.actions.superuser_run('service', ['reload', service])
|
|
|
|
|
|
class AliasView(FormView):
|
|
"""View to create, list, enable, disable and delete aliases.
|
|
|
|
This view has two forms. Form to list (and manage) existing aliases, and a
|
|
form to create a new aliases. When GET operation is used, both forms
|
|
created and template is rendered. When POST operation is used, the form
|
|
posted is detected using hidden form values and the appropriate form is
|
|
initialized for the FormView base class to work with.
|
|
"""
|
|
template_name = 'email_alias.html'
|
|
form_classes = (forms.AliasCreateForm, forms.AliasListForm)
|
|
success_url = reverse_lazy('email_server:aliases')
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
"""Initialize the view."""
|
|
super().__init__(*args, **kwargs)
|
|
self.posted_form = None
|
|
|
|
def get_form_class(self):
|
|
"""Return form class to build."""
|
|
if self.posted_form == 'create':
|
|
return forms.AliasCreateForm
|
|
|
|
return forms.AliasListForm
|
|
|
|
def get_form_kwargs(self):
|
|
"""Send aliases to list form."""
|
|
kwargs = super().get_form_kwargs()
|
|
if self.posted_form != 'create':
|
|
kwargs['aliases'] = self._get_current_aliases()
|
|
|
|
return kwargs
|
|
|
|
def _get_current_aliases(self):
|
|
"""Return current list of aliases."""
|
|
return aliases_module.get(self.request.user.username)
|
|
|
|
def get_context_data(self, *args, **kwargs):
|
|
context = super().get_context_data(*args, **kwargs)
|
|
if isinstance(context['form'], forms.AliasCreateForm):
|
|
context['create_form'] = context['form']
|
|
aliases = self._get_current_aliases()
|
|
context['list_form'] = forms.AliasListForm(aliases)
|
|
else:
|
|
context['create_form'] = forms.AliasCreateForm()
|
|
context['list_form'] = context['form']
|
|
|
|
return context
|
|
|
|
def post(self, request, *args, **kwargs):
|
|
"""Find which form was submitted before proceeding."""
|
|
self.posted_form = request.POST.get('form')
|
|
return super().post(request, *args, **kwargs)
|
|
|
|
def form_valid(self, form):
|
|
"""Handle a valid submission."""
|
|
if isinstance(form, forms.AliasListForm):
|
|
self._list_form_valid(form)
|
|
elif isinstance(form, forms.AliasCreateForm):
|
|
self._create_form_valid(form)
|
|
|
|
return super().form_valid(form)
|
|
|
|
def _list_form_valid(self, form):
|
|
"""Handle a valid alias list form operation."""
|
|
aliases = form.cleaned_data['aliases']
|
|
action = form.cleaned_data['action']
|
|
username = self.request.user.username
|
|
if action == 'delete':
|
|
aliases_module.delete(username, aliases)
|
|
elif action == 'disable':
|
|
aliases_module.disable(username, aliases)
|
|
elif action == 'enable':
|
|
aliases_module.enable(username, aliases)
|
|
|
|
def _create_form_valid(self, form):
|
|
"""Handle a valid create alias form operation."""
|
|
username = self.request.user.username
|
|
aliases_module.put(username, form.cleaned_data['alias'])
|
|
|
|
|
|
class XmlView(TemplateView):
|
|
template_name = 'email_autoconfig.xml'
|
|
|
|
def render_to_response(self, *args, **kwargs):
|
|
kwargs['content_type'] = 'text/xml; charset=utf-8'
|
|
response = super().render_to_response(*args, **kwargs)
|
|
response['X-Robots-Tag'] = 'noindex, nofollow, noarchive'
|
|
return response
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super().get_context_data(**kwargs)
|
|
context['host'] = self.request.get_host()
|
|
return context
|