Merge branch 'devel'

fusion devel on master
This commit is contained in:
jorgepastorr 2023-09-01 17:54:47 +02:00
commit f3e0a62bf2
15 changed files with 109 additions and 55 deletions

View File

@ -26,12 +26,13 @@ from .actions import (list_contacts, service_report, delete_related_services, di
enable_selected)
from .forms import AccountCreationForm
from .models import Account
from .filters import HasTipeServerFilter
class AccountAdmin(ChangePasswordAdminMixin, auth.UserAdmin, ExtendedModelAdmin):
list_display = ('username', 'full_name', 'type', 'is_active')
list_filter = (
'type', 'is_active',
'type', 'is_active', HasTipeServerFilter
)
add_fieldsets = (
(_("User"), {

View File

@ -1,7 +1,9 @@
from django.contrib.admin import SimpleListFilter
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.orchestration.models import Server
from orchestra.contrib.websites.models import Website
from orchestra.settings import WEB_SERVERS
class IsActiveListFilter(SimpleListFilter):
title = _("is active")
@ -25,3 +27,16 @@ class IsActiveListFilter(SimpleListFilter):
elif self.value() == 'object':
return queryset.filter(is_active=False)
return queryset
class HasTipeServerFilter(SimpleListFilter):
title = _("has type server")
parameter_name = 'has_servers'
def lookups(self, request, model_admin):
return [ (x.id, x.name) for x in Server.objects.filter(name__in=WEB_SERVERS) ]
def queryset(self, request, queryset):
if self.value() is not None:
serverWebsites = Website.objects.filter(target_server=self.value())
return queryset.filter(id__in=[ x.account.id for x in serverWebsites ] )
return queryset

View File

@ -16,7 +16,7 @@ from .filters import HasCustomAddressListFilter
from .models import List
class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModelAdmin):
class ListAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
list_display = (
'name', 'address_name', 'address_domain_link', 'account_link', 'display_active'
)
@ -31,7 +31,7 @@ class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModel
}),
(_("Admin"), {
'classes': ('wide',),
'fields': ('admin_email', 'password1', 'password2'),
'fields': ('admin_email',),
}),
)
fieldsets = (
@ -45,35 +45,15 @@ class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModel
) % settings.LISTS_DEFAULT_DOMAIN,
'fields': (('address_name', 'address_domain'),)
}),
(_("Admin"), {
'classes': ('wide',),
'fields': ('password',),
}),
)
search_fields = ('name', 'address_name', 'address_domain__name', 'account__username')
list_filter = (IsActiveListFilter, HasCustomAddressListFilter)
readonly_fields = ('account_link',)
change_readonly_fields = ('name',)
form = NonStoredUserChangeForm
add_form = UserCreationForm
list_select_related = ('account', 'address_domain',)
filter_by_account_fields = ['address_domain']
actions = (disable, enable, list_accounts)
address_domain_link = admin_link('address_domain', order='address_domain__name')
def get_urls(self):
useradmin = UserAdmin(List, self.admin_site)
return [
url(r'^(\d+)/password/$',
self.admin_site.admin_view(useradmin.user_change_password))
] + super(ListAdmin, self).get_urls()
def save_model(self, request, obj, form, change):
""" set password """
if not change:
obj.set_password(form.cleaned_data["password1"])
super(ListAdmin, self).save_model(request, obj, form, change)
admin.site.register(List, ListAdmin)

View File

@ -182,7 +182,6 @@ class MailmanController(MailmanVirtualDomainController):
context.update({
'banner': self.get_banner(mail_list),
'name': mail_list.name,
'password': mail_list.password,
'domain': mail_list.address_domain or settings.LISTS_DEFAULT_DOMAIN,
'address_name': mail_list.get_address_name(),
'address_domain': mail_list.address_domain,

View File

@ -0,0 +1,34 @@
# Generated by Django 2.2.28 on 2023-09-01 14:59
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import orchestra.core.validators
class Migration(migrations.Migration):
initial = True
dependencies = [
('domains', '__first__'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='List',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='Default list address <name>@grups.pangea.org', max_length=64, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
('address_name', models.CharField(blank=True, max_length=64, validators=[orchestra.core.validators.validate_name], verbose_name='address name')),
('admin_email', models.EmailField(help_text='Administration email address', max_length=254, verbose_name='admin email')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this account should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lists', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
('address_domain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='domains.Domain', verbose_name='address domain')),
],
options={
'unique_together': {('address_name', 'address_domain')},
},
),
]

View File

@ -8,17 +8,6 @@ from orchestra.core.validators import validate_name
from . import settings
class ListQuerySet(models.QuerySet):
def create(self, **kwargs):
""" Sets password if provided, all within a single DB operation """
password = kwargs.pop('password')
instance = self.model(**kwargs)
if password:
instance.set_password(password)
instance.save()
return instance
# TODO address and domain, perhaps allow only domain?
class List(models.Model):
name = models.CharField(_("name"), max_length=64, unique=True, validators=[validate_name],
@ -35,9 +24,6 @@ class List(models.Model):
is_active = models.BooleanField(_("active"), default=True,
help_text=_("Designates whether this account should be treated as active. "
"Unselect this instead of deleting accounts."))
password = None
objects = ListQuerySet.as_manager()
class Meta:
unique_together = ('address_name', 'address_domain')
@ -75,9 +61,6 @@ class List(models.Model):
def get_username(self):
return self.name
def set_password(self, password):
self.password = password
def get_absolute_url(self):
context = {
'name': self.name

View File

@ -9,13 +9,14 @@ LISTS_DOMAIN_MODEL = Setting('LISTS_DOMAIN_MODEL',
LISTS_DEFAULT_DOMAIN = Setting('LISTS_DEFAULT_DOMAIN',
'lists.{}'.format(ORCHESTRA_BASE_DOMAIN),
'grups.{}'.format(ORCHESTRA_BASE_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
)
LISTS_LIST_URL = Setting('LISTS_LIST_URL',
'https://lists.{}/mailman/listinfo/%(name)s'.format(ORCHESTRA_BASE_DOMAIN),
# 'https://lists.{}/mailman/listinfo/%(name)s'.format(ORCHESTRA_BASE_DOMAIN),
'https://www.{0}/mailman3/lists/%(name)s.{0}'.format(LISTS_DEFAULT_DOMAIN),
help_text="Uses <tt>ORCHESTRA_BASE_DOMAIN</tt> by default."
)

View File

@ -20,7 +20,7 @@ from orchestra.core import caches
from . import settings
from .actions import SendMailboxEmail, SendAddressEmail
from .filters import HasMailboxListFilter, HasForwardListFilter, HasAddressListFilter
from .filters import HasMailboxListFilter, HasForwardListFilter, HasAddressListFilter, HasTipeServerFilter
from .forms import MailboxCreationForm, MailboxChangeForm, AddressForm
from .models import Mailbox, Address, Autoresponse
from .widgets import OpenCustomFilteringOnSelect
@ -40,7 +40,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
list_display = (
'name', 'account_link', 'display_filtering', 'display_addresses', 'display_active',
)
list_filter = (IsActiveListFilter, HasAddressListFilter, 'filtering')
list_filter = (IsActiveListFilter, HasAddressListFilter, 'filtering', HasTipeServerFilter)
search_fields = (
'account__username', 'account__short_name', 'account__full_name', 'name',
'addresses__name', 'addresses__domain__name',

View File

@ -1,6 +1,8 @@
from django.contrib.admin import SimpleListFilter
from django.utils.translation import gettext_lazy as _
from orchestra.contrib.orchestration.models import Server
from orchestra.contrib.websites.models import Website
from orchestra.settings import WEB_SERVERS
class HasMailboxListFilter(SimpleListFilter):
""" Filter addresses whether they have any mailbox or not """
@ -45,3 +47,17 @@ class HasAddressListFilter(HasMailboxListFilter):
elif self.value() == 'False':
return queryset.filter(addresses__isnull=True)
return queryset
class HasTipeServerFilter(SimpleListFilter):
title = _("has type server")
parameter_name = 'has_servers'
def lookups(self, request, model_admin):
return [ (x.id, x.name) for x in Server.objects.filter(name__in=WEB_SERVERS) ]
def queryset(self, request, queryset):
if self.value() is not None:
serverWebsites = Website.objects.filter(target_server=self.value())
return queryset.filter(account__in=[ x.account.id for x in serverWebsites ] )
return queryset

View File

@ -15,6 +15,7 @@ from orchestra.contrib.systemusers.models import WebappUsers
from orchestra.forms.widgets import DynamicHelpTextSelect
from orchestra.plugins.admin import SelectPluginAdminMixin, display_plugin_field
from orchestra.utils.html import get_on_site_link
from orchestra.settings import NEW_SERVERS
from .filters import HasWebsiteListFilter, DetailListFilter
from .models import WebApp, WebAppOption
@ -57,7 +58,7 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
list_display = (
'name', 'display_type', 'display_detail', 'display_websites', 'account_link', 'target_server',
)
list_filter = ('type', HasWebsiteListFilter, DetailListFilter)
list_filter = ('type', HasWebsiteListFilter, DetailListFilter, 'target_server')
inlines = [WebAppOptionInline]
readonly_fields = ('account_link',)
change_readonly_fields = ('name', 'type', 'display_websites', 'display_sftpuser', 'target_server',)
@ -110,7 +111,8 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
def save_model(self, request, obj, form, change):
if not change:
user = form.cleaned_data.get('username')
if user:
server = form.cleaned_data.get('target_server')
if user and server.name in NEW_SERVERS:
user = WebappUsers(
username=form.cleaned_data['username'],
account_id=obj.account.pk,

View File

@ -3,7 +3,7 @@ import os
from django import forms
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from orchestra.plugins.forms import ExtendedPluginDataForm
from orchestra.plugins.forms import ExtendedPluginDataForm, PluginDataForm
from ..options import AppOption
from . import AppType
@ -32,6 +32,7 @@ class WebalizerApp(AppType):
"Statistics will be collected once this app is mounted into one or more Websites.")
icon = 'orchestra/icons/apps/Stats.png'
option_groups = ()
form = PluginDataForm
def get_directive(self):
webalizer_path = os.path.join(self.instance.get_path(), '%(site_name)s')

View File

@ -63,7 +63,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
'name', 'display_domains', 'display_webapps', 'account_link', 'target_server', 'display_active'
)
list_filter = (
'protocol', IsActiveListFilter, HasWebAppsListFilter, HasDomainsFilter
'protocol', IsActiveListFilter, HasWebAppsListFilter, HasDomainsFilter, 'target_server'
)
change_readonly_fields = ('name',)
inlines = (ContentInline, WebsiteDirectiveInline)

View File

@ -7,9 +7,11 @@ from orchestra.forms.widgets import SpanWidget
from django.core.exceptions import ValidationError
from orchestra.core import validators
from orchestra.utils.python import random_ascii
from orchestra.settings import NEW_SERVERS
from orchestra.settings import NEW_SERVERS, WEB_SERVERS
from django.utils.translation import gettext_lazy as _
import textwrap
from orchestra.contrib.orchestration.models import Server
class PluginForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
@ -21,12 +23,13 @@ class PluginForm(forms.ModelForm):
help_text = self.fields[self.plugin_field].help_text
self.fields[self.plugin_field].help_text = getattr(self.plugin, 'help_text', help_text)
class PluginDataForm(PluginForm):
data = forms.CharField(widget=forms.HiddenInput, required=False)
target_server = forms.ModelChoiceField(queryset=Server.objects.filter(name__in=WEB_SERVERS),)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['sftpuser'].widget = forms.HiddenInput()
if self.instance:
for field in self.declared_fields:
initial = self.fields[field].initial
@ -98,15 +101,25 @@ class ExtendedPluginDataForm(PluginDataForm):
widget=forms.PasswordInput,
help_text=_("Enter the same password as above, for verification."))
def __init__(self, *args, **kwargs):
super(ExtendedPluginDataForm, self).__init__(*args, **kwargs)
self.fields['sftpuser'].widget = forms.HiddenInput()
if self.instance.id is not None:
self.fields['username'].widget = forms.HiddenInput()
self.fields['password1'].widget = forms.HiddenInput()
self.fields['password2'].widget = forms.HiddenInput()
if not self.instance.pk:
self.fields['target_server'].widget.attrs['onChange'] = textwrap.dedent("""\
field = $(".field-username, .field-password1, .field-password2");
input = $("#id_username, #id_password1, #id_password2");
if (%s.includes(this.options[this.selectedIndex].text)) {
field.removeClass("hidden");
} else {
field.addClass("hidden");
input.val("");
};""" % list(NEW_SERVERS)
)
def clean_username(self):
if not self.instance.id:
webapp_server = self.cleaned_data.get("target_server")

View File

@ -97,3 +97,12 @@ NEW_SERVERS = Setting('NEW_SERVERS',
'web-12.pangea.lan',
)
)
WEB_SERVERS = Setting('WEBAPPS_SERVERS', (
'web.pangea.lan',
'web-ng',
'web-11.pangea.lan',
'web-12.pangea.lan',
'bookworm',
)
)