diff --git a/orchestra/contrib/accounts/admin.py b/orchestra/contrib/accounts/admin.py
index b2d6442a..0c1e81c0 100644
--- a/orchestra/contrib/accounts/admin.py
+++ b/orchestra/contrib/accounts/admin.py
@@ -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"), {
diff --git a/orchestra/contrib/accounts/filters.py b/orchestra/contrib/accounts/filters.py
index ff4be0ae..bbffd8c2 100644
--- a/orchestra/contrib/accounts/filters.py
+++ b/orchestra/contrib/accounts/filters.py
@@ -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
\ No newline at end of file
diff --git a/orchestra/contrib/lists/admin.py b/orchestra/contrib/lists/admin.py
index d356d726..fc6255f9 100644
--- a/orchestra/contrib/lists/admin.py
+++ b/orchestra/contrib/lists/admin.py
@@ -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)
diff --git a/orchestra/contrib/lists/backends.py b/orchestra/contrib/lists/backends.py
index b6d4dc97..1c31e826 100644
--- a/orchestra/contrib/lists/backends.py
+++ b/orchestra/contrib/lists/backends.py
@@ -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,
diff --git a/orchestra/contrib/lists/migrations/0001_initial.py b/orchestra/contrib/lists/migrations/0001_initial.py
new file mode 100644
index 00000000..064843fc
--- /dev/null
+++ b/orchestra/contrib/lists/migrations/0001_initial.py
@@ -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')},
+ },
+ ),
+ ]
diff --git a/orchestra/contrib/lists/migrations/__init__.py b/orchestra/contrib/lists/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/orchestra/contrib/lists/models.py b/orchestra/contrib/lists/models.py
index 8ac33723..82ab91f7 100644
--- a/orchestra/contrib/lists/models.py
+++ b/orchestra/contrib/lists/models.py
@@ -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
diff --git a/orchestra/contrib/lists/settings.py b/orchestra/contrib/lists/settings.py
index 9d5e25ae..8df45b41 100644
--- a/orchestra/contrib/lists/settings.py
+++ b/orchestra/contrib/lists/settings.py
@@ -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 ORCHESTRA_BASE_DOMAIN 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 ORCHESTRA_BASE_DOMAIN by default."
)
diff --git a/orchestra/contrib/mailboxes/admin.py b/orchestra/contrib/mailboxes/admin.py
index d1094d3f..09924dd6 100644
--- a/orchestra/contrib/mailboxes/admin.py
+++ b/orchestra/contrib/mailboxes/admin.py
@@ -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',
diff --git a/orchestra/contrib/mailboxes/filters.py b/orchestra/contrib/mailboxes/filters.py
index 2c1dd603..0ef6978b 100644
--- a/orchestra/contrib/mailboxes/filters.py
+++ b/orchestra/contrib/mailboxes/filters.py
@@ -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
\ No newline at end of file
diff --git a/orchestra/contrib/webapps/admin.py b/orchestra/contrib/webapps/admin.py
index 24bd4948..afa9c8ab 100644
--- a/orchestra/contrib/webapps/admin.py
+++ b/orchestra/contrib/webapps/admin.py
@@ -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,
diff --git a/orchestra/contrib/webapps/types/misc.py b/orchestra/contrib/webapps/types/misc.py
index 92fd1fa3..d80a66b8 100644
--- a/orchestra/contrib/webapps/types/misc.py
+++ b/orchestra/contrib/webapps/types/misc.py
@@ -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')
diff --git a/orchestra/contrib/websites/admin.py b/orchestra/contrib/websites/admin.py
index 6682c4c7..f47f28b9 100644
--- a/orchestra/contrib/websites/admin.py
+++ b/orchestra/contrib/websites/admin.py
@@ -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)
diff --git a/orchestra/plugins/forms.py b/orchestra/plugins/forms.py
index 16885756..cbd71489 100644
--- a/orchestra/plugins/forms.py
+++ b/orchestra/plugins/forms.py
@@ -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")
diff --git a/orchestra/settings.py b/orchestra/settings.py
index ff311382..3e43573e 100644
--- a/orchestra/settings.py
+++ b/orchestra/settings.py
@@ -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',
+ )
+)
\ No newline at end of file