Skip to content
Snippets Groups Projects
Commit 6888b518 authored by Tom Teichler's avatar Tom Teichler :beers:
Browse files

Add new model for mail domain

parent 83e86914
No related branches found
No related tags found
1 merge request!7Resolve "Initialise app and move mailaddress stuff from TIC-Desk"
Pipeline #52811 passed
Showing
with 247 additions and 29 deletions
...@@ -2,12 +2,13 @@ from django import forms ...@@ -2,12 +2,13 @@ from django import forms
from django.core.validators import validate_email from django.core.validators import validate_email
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_select2.forms import ModelSelect2Widget
from material import Layout, Row from material import Layout, Row
from aleksis.core.mixins import ExtensibleForm from aleksis.core.mixins import ExtensibleForm
from aleksis.core.util.core_helpers import get_site_preferences from aleksis.core.util.core_helpers import get_site_preferences
from .models import MailAddress from .models import MailAddress, MailDomain
class MailAddForm(ExtensibleForm): class MailAddForm(ExtensibleForm):
...@@ -20,18 +21,17 @@ class MailAddForm(ExtensibleForm): ...@@ -20,18 +21,17 @@ class MailAddForm(ExtensibleForm):
model = MailAddress model = MailAddress
exclude = ["person"] exclude = ["person"]
domain = forms.ChoiceField( domain = forms.ModelChoiceField(
label=_("Domain"), label=_("Domain"),
required=True, required=True,
queryset=MailDomain.objects.all(),
help_text=_("Domain part of the mail address"), help_text=_("Domain part of the mail address"),
widget=ModelSelect2Widget(
search_fields=["domain__icontains"],
attrs={"data-minimum-input-length": 0, "class": "browser-default"},
),
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
mail_domains = tuple(get_site_preferences()["postbuero__mail_domains"].split(","))
self.fields["domain"].choices = [(_,f"@{_}") for _ in mail_domains]
def clean_local_part(self): def clean_local_part(self):
local_part = self.cleaned_data["local_part"] local_part = self.cleaned_data["local_part"]
...@@ -52,3 +52,13 @@ class MailAddForm(ExtensibleForm): ...@@ -52,3 +52,13 @@ class MailAddForm(ExtensibleForm):
self.instance.person = person self.instance.person = person
super().save(*args, **kwargs) super().save(*args, **kwargs)
class MailDomainForm(ExtensibleForm):
"""Form for managing mail domains."""
layout = Layout("Domain", Row("domain"))
class Meta:
model = MailDomain
exclude = []
...@@ -3,12 +3,34 @@ from django.utils.translation import ugettext_lazy as _ ...@@ -3,12 +3,34 @@ from django.utils.translation import ugettext_lazy as _
MENUS = { MENUS = {
"NAV_MENU_CORE": [ "NAV_MENU_CORE": [
{ {
"name": _("Mail addresses"), "name": _("Mail"),
"url": "manage_mail", "url": "#",
"icon": "email", "icon": "email",
"root": True,
"validators": [ "validators": [
"menu_generator.validators.is_authenticated", "menu_generator.validators.is_authenticated",
], ],
"submenu": [
{
"name": _("Mail addresses"),
"url": "manage_mail",
"icon": "email",
"validators": [
"menu_generator.validators.is_authenticated",
],
},
{
"name": _("Mail domains"),
"url": "mail_domains",
"icon": "domain_add",
"validators": [
(
"aleksis.core.util.predicates.permission_validator",
"core.view_schoolterm_rule",
),
],
},
],
}, },
] ]
} }
# Generated by Django 3.2.12 on 2022-02-01 18:47
import django.contrib.sites.managers
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('sites', '0002_alter_domain_unique'),
('core', '0035_preference_model_unique'),
('postbuero', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='MailDomain',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('extended_data', models.JSONField(default=dict, editable=False)),
('domain', models.CharField(max_length=255, verbose_name='Domain')),
('allowed_groups', models.ManyToManyField(blank=True, related_name='mail_domains', to='core.Group', verbose_name='Allowed groups')),
('site', models.ForeignKey(default=1, editable=False, on_delete=django.db.models.deletion.CASCADE, to='sites.site')),
],
options={
'abstract': False,
},
managers=[
('objects', django.contrib.sites.managers.CurrentSiteManager()),
],
),
migrations.AlterField(
model_name='mailaddress',
name='domain',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='postbuero.maildomain', verbose_name='Domain'),
),
]
...@@ -2,11 +2,23 @@ from django.db import models ...@@ -2,11 +2,23 @@ from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from aleksis.core.mixins import ExtensibleModel from aleksis.core.mixins import ExtensibleModel
from aleksis.core.models import Person from aleksis.core.models import Group, Person
class MailAddress(ExtensibleModel): class MailDomain(ExtensibleModel):
domain = models.CharField(verbose_name=_("Domain"), max_length=255) domain = models.CharField(verbose_name=_("Domain"), max_length=255)
allowed_groups = models.ManyToManyField(
Group, verbose_name=_("Allowed groups"), related_name="mail_domains", blank=True
)
def __str__(self) -> str:
return self.domain
class MailAddress(ExtensibleModel):
domain = models.ForeignKey(MailDomain, verbose_name=_("Domain"), on_delete=models.CASCADE)
local_part = models.CharField(verbose_name=_("Local part"), max_length=64) local_part = models.CharField(verbose_name=_("Local part"), max_length=64)
person = models.ForeignKey( person = models.ForeignKey(
Person, Person,
......
from django.forms import EmailField
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from dynamic_preferences.preferences import Section from dynamic_preferences.preferences import Section
from dynamic_preferences.types import LongStringPreference, BooleanPreference from dynamic_preferences.types import BooleanPreference, LongStringPreference
from aleksis.core.registries import site_preferences_registry from aleksis.core.registries import site_preferences_registry
postbuero = Section("postbuero", verbose_name=_("Postbuero")) postbuero = Section("postbuero", verbose_name=_("Postbuero"))
@site_preferences_registry.register
class MailDomains(LongStringPreference):
section = postbuero
name = "mail_domains"
required = False
default = ""
verbose_name = _("Comma-seperated list of avaiable mail domains")
@site_preferences_registry.register @site_preferences_registry.register
class DisallowedLocalParts(LongStringPreference): class DisallowedLocalParts(LongStringPreference):
section = postbuero section = postbuero
...@@ -38,6 +28,4 @@ class SendAdminMail(BooleanPreference): ...@@ -38,6 +28,4 @@ class SendAdminMail(BooleanPreference):
name = "admin_mail" name = "admin_mail"
required = False required = False
default = False default = False
verbose_name = _( verbose_name = _("Sent notification to admins if a new email address was registered.")
"Sent notification to admins if a new email address was registered."
)
import rules
from aleksis.core.util.predicates import has_global_perm, has_person
from .util.predicates import can_use_domain
can_use_domain_predicate = has_person & can_use_domain
rules.add_perm("postbuero.can_use_domain", can_use_domain_predicate)
view_mail_domain_predicate = has_person & has_global_perm("postbuero.view_maildomain")
rules.add_perm("postbuero.view_maildomain_rule", view_mail_domain_predicate)
create_mail_domain_predicate = has_person & has_global_perm("postbuero.add_maildomain")
rules.add_perm("postbuero.create_maildomain_rule", create_mail_domain_predicate)
edit_mail_domain_predicate = has_person & has_global_perm("postbuero.change_maildomain")
rules.add_perm("postbuero.edit_maildomain_rule", edit_mail_domain_predicate)
from django.utils.translation import gettext_lazy as _
import django_tables2 as tables
from django_tables2.utils import A
class MailDomainTable(tables.Table):
"""Table to list mail domains."""
class Meta:
attrs = {"class": "highlight"}
domain = tables.LinkColumn("edit_mail_domain", args=[A("id")])
edit = tables.LinkColumn(
"edit_mail_domain",
args=[A("id")],
text=_("Edit"),
attrs={"a": {"class": "btn-flat waves-effect waves-orange orange-text"}},
verbose_name=_("Actions"),
)
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load material_form i18n %}
{% block browser_title %}{% blocktrans %}Create mail domain{% endblocktrans %}{% endblock %}
{% block page_title %}{% blocktrans %}Create mail domain{% endblocktrans %}{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{% form form=form %}{% endform %}
{% include "core/partials/save_button.html" %}
</form>
{% endblock %}
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load material_form i18n %}
{% block browser_title %}{% blocktrans %}Edit mail domain{% endblocktrans %}{% endblock %}
{% block page_title %}{% blocktrans %}Edit mail domain{% endblocktrans %}{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{% form form=form %}{% endform %}
{% include "core/partials/save_button.html" %}
</form>
{% endblock %}
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load i18n %}
{% load render_table from django_tables2 %}
{% block browser_title %}{% blocktrans %}Mail domains{% endblocktrans %}{% endblock %}
{% block page_title %}{% blocktrans %}Mail domains{% endblocktrans %}{% endblock %}
{% block content %}
<a class="btn green waves-effect waves-light" href="{% url 'create_mail_domain' %}">
<i class="material-icons left">add</i>
{% trans "Create mail domain" %}
</a>
{% render_table table %}
{% endblock %}
...@@ -4,4 +4,7 @@ from . import views ...@@ -4,4 +4,7 @@ from . import views
urlpatterns = [ urlpatterns = [
path("mails/manage/", views.ManageMail.as_view(), name="manage_mail"), path("mails/manage/", views.ManageMail.as_view(), name="manage_mail"),
path("mail_domains/", views.MailDomainListView.as_view(), name="mail_domains"),
path("mail_domains/create/", views.MailDomainCreateView.as_view(), name="create_mail_domain"),
path("mail_domains/<int:pk>/", views.MailDomainEditView.as_view(), name="edit_mail_domain"),
] ]
from django.contrib.auth.models import User
from rules import predicate
from ..models import MailDomain
@predicate
def can_use_domain(user: User, domain: MailDomain) -> bool:
"""Check if user is allowed to use mail domain."""
if domain.allowed_groups:
return bool(user.member_of.all() & domain.allowed_groups.all())
else:
return True
from django.conf import settings from django.conf import settings
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.shortcuts import render, redirect from django.shortcuts import render
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from django.views.decorators.cache import never_cache
from django.views.generic.base import View from django.views.generic.base import View
import reversion import reversion
from django_tables2 import SingleTableView
from rules.contrib.views import PermissionRequiredMixin
from aleksis.core.mixins import AdvancedCreateView, AdvancedEditView
from aleksis.core.models import Activity from aleksis.core.models import Activity
from aleksis.core.util import messages from aleksis.core.util import messages
from aleksis.core.util.email import send_email
from aleksis.core.util.core_helpers import get_site_preferences from aleksis.core.util.core_helpers import get_site_preferences
from aleksis.core.util.email import send_email
from .forms import MailAddForm from .forms import MailAddForm, MailDomainForm
from .models import MailDomain
from .tables import MailDomainTable
class ManageMail(View): class ManageMail(View):
...@@ -69,3 +78,36 @@ class ManageMail(View): ...@@ -69,3 +78,36 @@ class ManageMail(View):
messages.success(request, _("Email address saved.")) messages.success(request, _("Email address saved."))
return render(request, "postbuero/mail_address/manage.html", context) return render(request, "postbuero/mail_address/manage.html", context)
class MailDomainListView(PermissionRequiredMixin, SingleTableView):
"""Table of all mail domains."""
model = MailDomain
table_class = MailDomainTable
permission_required = "postbuero.view_maildomain_rule"
template_name = "postbuero/mail_domain/list.html"
@method_decorator(never_cache, name="dispatch")
class MailDomainCreateView(PermissionRequiredMixin, AdvancedCreateView):
"""Create view for mail domains."""
model = MailDomain
form_class = MailDomainForm
permission_required = "postbuero.add_maildomain_rule"
template_name = "postbuero/mail_domain/create.html"
success_url = reverse_lazy("mail_domains")
success_message = _("The mail domain has been created.")
@method_decorator(never_cache, name="dispatch")
class MailDomainEditView(PermissionRequiredMixin, AdvancedEditView):
"""Edit view for mail domains."""
model = MailDomain
form_class = MailDomainForm
permission_required = "postbuero.edit_maildomain"
template_name = "postbuero/mail_domain/edit.html"
success_url = reverse_lazy("mail_domains")
success_message = _("The mail domain has been saved.")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment