# SPDX-License-Identifier: AGPL-3.0-or-later import io import itertools import pwd import plinth.utils from django.core.exceptions import ValidationError from django.utils.html import escape from django.utils.translation import ugettext_lazy as _ from django.views.generic.base import TemplateView, View from plinth.views import AppView, render_tabs from . import aliases from . import audit from . import forms class TabMixin(View): admin_tabs = [ ('', _('Home')), ('my_mail', _('My Mail')), ('my_aliases', _('My Aliases')), ('security', _('Security')), ('domains', _('Domains')) ] user_tabs = [ ('my_mail', _('Home')), ('my_aliases', _('My Aliases')) ] def get_context_data(self, *args, **kwargs): # Retrieve context data from the next method in the MRO context = super().get_context_data(*args, **kwargs) # Populate context with customized data context['tabs'] = self.render_dynamic_tabs() return context def render_dynamic_tabs(self): if plinth.utils.is_user_admin(self.request): return render_tabs(self.request.path, self.admin_tabs) else: return render_tabs(self.request.path, self.user_tabs) 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) def find_button(self, post): key_filter = (k for k in post.keys() if k.startswith('btn_')) lst = list(itertools.islice(key_filter, 2)) if len(lst) != 1: raise ValidationError('Bad post data') if not isinstance(lst[0], str): raise ValidationError('Bad post data') return lst[0][len('btn_'):] def find_form(self, post): form_name = post.get('form') for cls in self.form_classes: if cls.__name__ == form_name: return cls(post) raise ValidationError('Form was unspecified') class EmailServerView(TabMixin, AppView): """Server configuration page""" app_id = 'email_server' template_name = 'email_server.html' class MyMailView(TabMixin, TemplateView): template_name = 'my_mail.html' def get_context_data(self, *args, **kwargs): context = super().get_context_data(*args, **kwargs) nam = self.request.user.username context['has_homedir'] = audit.home.exists_nam(nam) return context def post(self, request): return self.catch_exceptions(self._post, request) def _post(self, request): if 'btn_mkhome' not in request.POST: raise ValidationError('Bad post data') audit.home.put_nam(request.user.username) return self.render_to_response(self.get_context_data()) class AliasView(TabMixin, TemplateView): class Checkboxes: def __init__(self, post=None, initial=None): self.models = initial self.post = post self.cleaned_data = {} # HTML rendering self.sb = io.StringIO() self.counter = 0 def render(self): if self.models is None: raise RuntimeError('Uninitialized form') if self.sb.tell() > 0: raise RuntimeError('render has been called') enabled = [a.email_name for a in self.models if a.enabled] disabled = [a.email_name for a in self.models if not a.enabled] self._render_fieldset(enabled, _('Enabled aliases')) self._render_fieldset(disabled, _('Disabled aliases')) return self.sb.getvalue() def _render_fieldset(self, email_names, legend): if len(email_names) > 0: self.sb.write('
') def _render_boxes(self, email_names): for email_name in email_names: input_id = 'cb_alias_%d' % self._count() value = escape(email_name) self.sb.write('