Compare commits

...

11 Commits

Author SHA1 Message Date
jorgepastorr cc4a9b9b91 add icon nextcloud on SAS 2023-09-14 17:18:46 +02:00
jorgepastorr 3ddd25b456 fix last nyapa with target_server on SAS 2023-09-14 10:44:02 +02:00
jorgepastorr a8808366e1 nyapa hiden target server in SAS 2023-09-07 13:46:48 +02:00
jorgepastorr d5980fd0c8 fix webappUser create user with groups dont exist 2023-09-05 17:41:44 +02:00
jorgepastorr 076f5dbb96 fix problem with sftpuser onnSAslist and webalizer 2023-09-05 12:27:45 +02:00
jorgepastorr f5e20c8858 delete local bokworm settiongs 2023-09-01 18:01:13 +02:00
jorgepastorr f3e0a62bf2 Merge branch 'devel'
fusion devel on master
2023-09-01 17:54:47 +02:00
jorgepastorr 638c1ceb44 delete fields password in lists 2023-09-01 17:47:43 +02:00
jorgepastorr 631c27cd14 add filter servers on accounts and mailboxes to send messages 2023-08-24 17:49:13 +02:00
jorgepastorr ca9dcceb88 hidden sftpuser in webalizer form 2023-08-24 12:39:59 +02:00
jorgepastorr adc59e2e3c delete local bookworm 2023-08-20 09:11:14 +02:00
18 changed files with 114 additions and 56 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

@ -700,7 +700,6 @@ class UNIXUserControllerNewServers(ServiceController):
def get_groups(self, user):
groups = []
if user.is_main:
groups = list(user.account.systemusers.exclude(username=user.username).values_list('username', flat=True))
groups.append("main-systemusers")
return groups
@ -812,7 +811,8 @@ class WebappUserController(ServiceController):
def get_groups(self, user):
groups = []
groups = list(user.account.systemusers.exclude(username=user.username).values_list('username', flat=True))
# groups = list(user.account.systemusers.exclude(username=user.username).values_list('username', flat=True))
groups.append(user.account.main_systemuser.username)
groups.append("webapp-systemusers")
return groups

View File

@ -58,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',)

View File

@ -114,7 +114,6 @@ WEBAPPS_PHP_VERSIONS_SERVERS = Setting('WEBAPPS_PHP_VERSIONS_SERVERS', {
'web-ng' : ('5.6-fpm', '7.0-fpm', '7.3-fpm',),
'web-11.pangea.lan': ('7.4-fpm',),
'web-12.pangea.lan' : ('8.1-fpm', '8.2-fpm'),
'bookworm' : ('8.1-fpm', '8.2-fpm'),
},
help_text="PHP available for each server",
)

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
@ -23,6 +23,11 @@ class StaticApp(AppType):
return ('static', self.instance.get_path())
class WebalizerAppform(PluginDataForm):
def __init__(self, *args, **kwargs):
super(WebalizerAppform, self).__init__(*args, **kwargs)
self.fields['sftpuser'].widget = forms.HiddenInput()
class WebalizerApp(AppType):
name = 'webalizer'
verbose_name = "Webalizer"
@ -32,6 +37,8 @@ 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
form = WebalizerAppform
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

@ -93,7 +93,6 @@ ORCHESTRA_SSH_CONTROL_PATH = Setting('ORCHESTRA_SSH_CONTROL_PATH',
NEW_SERVERS = Setting('NEW_SERVERS',
(
'bookworm',
'web-11.pangea.lan',
'web-12.pangea.lan',
)
@ -104,6 +103,5 @@ WEB_SERVERS = Setting('WEBAPPS_SERVERS', (
'web-ng',
'web-11.pangea.lan',
'web-12.pangea.lan',
'bookworm',
)
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,25 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="225.000000pt" height="225.000000pt" viewBox="0 0 225.000000 225.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,225.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1020 2240 c-441 -44 -804 -329 -953 -747 -80 -222 -80 -515 0 -736
117 -328 364 -574 690 -690 221 -80 515 -80 736 0 382 136 658 457 733 850 22
114 22 302 0 416 -75 393 -352 714 -733 850 -134 48 -328 72 -473 57z m237
-832 c59 -28 122 -90 147 -145 l18 -41 32 35 c99 114 273 87 337 -52 76 -163
-102 -341 -266 -266 -22 10 -54 34 -71 54 l-32 35 -18 -41 c-25 -56 -87 -117
-149 -147 -73 -35 -180 -34 -256 1 -64 30 -129 93 -154 149 l-17 38 -32 -35
c-99 -114 -273 -87 -337 52 -76 163 102 341 266 266 22 -10 54 -34 71 -54 l32
-35 17 38 c67 149 262 219 412 148z"/>
<path d="M1045 1294 c-126 -66 -142 -234 -30 -320 65 -49 170 -45 232 9 44 38
63 82 63 141 0 111 -75 186 -187 186 -26 0 -61 -7 -78 -16z"/>
<path d="M590 1180 c-12 -12 -20 -33 -20 -55 0 -45 29 -75 73 -75 51 0 77 24
77 71 0 50 -27 79 -75 79 -22 0 -43 -8 -55 -20z"/>
<path d="M1550 1182 c-16 -13 -22 -29 -22 -57 0 -48 28 -75 78 -75 45 0 74 30
74 75 0 45 -29 75 -74 75 -19 0 -44 -8 -56 -18z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB