delete fields password in lists
edited 2023/11/24 by pedro
This commit is contained in:
parent
a6ef81ad8f
commit
d4eec5dd08
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
# Generated by Django 2.2.28 on 2023-09-01 14:59
|
||||
|
||||
from django.db import models, migrations
|
||||
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),
|
||||
('domains', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='List',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
|
||||
('name', models.CharField(max_length=128, validators=[orchestra.core.validators.validate_name], unique=True, verbose_name='name', help_text='Default list address <name>@lists.orchestra.lan')),
|
||||
('address_name', models.CharField(max_length=128, validators=[orchestra.core.validators.validate_name], verbose_name='address name', blank=True)),
|
||||
('admin_email', models.EmailField(max_length=254, verbose_name='admin email', help_text='Administration email address')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='active', help_text='Designates whether this account should be treated as active. Unselect this instead of deleting accounts.')),
|
||||
('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(on_delete=django.db.models.deletion.CASCADE, null=True, blank=True, to='domains.Domain', verbose_name='address domain')),
|
||||
('address_domain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='domains.Domain', verbose_name='address domain')),
|
||||
],
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='list',
|
||||
unique_together=set([('address_name', 'address_domain')]),
|
||||
options={
|
||||
'unique_together': {('address_name', 'address_domain')},
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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."
|
||||
)
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ class SystemUserAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, Extende
|
|||
|
||||
class WebappUserAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModelAdmin):
|
||||
list_display = (
|
||||
'username', 'account_link', 'shell', 'home', 'target_server'
|
||||
'username', 'account_link', 'home', 'target_server'
|
||||
)
|
||||
fieldsets = (
|
||||
(None, {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 2.2.28 on 2023-08-13 07:20
|
||||
|
||||
from django.db import migrations, models
|
||||
import orchestra.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('systemusers', '0003_auto_20230724_1813'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='webappusers',
|
||||
name='username',
|
||||
field=models.CharField(help_text='Required. 32 characters or fewer. Letters, digits and ./-/_ only.', max_length=32, validators=[orchestra.core.validators.validate_username], verbose_name='username'),
|
||||
),
|
||||
]
|
|
@ -146,7 +146,7 @@ class WebappUsers(models.Model):
|
|||
System users for webapp
|
||||
Username max_length determined by LINUX system user/group lentgh: 32
|
||||
"""
|
||||
username = models.CharField(_("username"), max_length=32, unique=True,
|
||||
username = models.CharField(_("username"), max_length=32,
|
||||
help_text=_("Required. 32 characters or fewer. Letters, digits and ./-/_ only."),
|
||||
validators=[validators.validate_username])
|
||||
password = models.CharField(_("password"), max_length=128)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.28 on 2023-08-17 09:08
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('webapps', '0003_auto_20230728_1639'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='webapp',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('php', 'PHP'), ('static', 'Static'), ('webalizer', 'Webalizer'), ('wordpress-php', 'WordPress')], max_length=32, verbose_name='type'),
|
||||
),
|
||||
]
|
|
@ -114,6 +114,7 @@ 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",
|
||||
)
|
||||
|
|
|
@ -1,61 +1,65 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
# Generated by Django 2.2.28 on 2023-08-17 09:45
|
||||
|
||||
from django.db import models, migrations
|
||||
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 = [
|
||||
('orchestration', '__first__'),
|
||||
('domains', '__first__'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('domains', '0001_initial'),
|
||||
('webapps', '0001_initial'),
|
||||
('webapps', '__first__'),
|
||||
# ('webapps', '0004_auto_20230817_1108'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Content',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
|
||||
('path', models.CharField(validators=[orchestra.core.validators.validate_url_path], verbose_name='path', max_length=256, blank=True)),
|
||||
('webapp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, verbose_name='web application', to='webapps.WebApp')),
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('path', models.CharField(blank=True, max_length=256, validators=[orchestra.core.validators.validate_url_path], verbose_name='path')),
|
||||
('webapp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='webapps.WebApp', verbose_name='web application')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Website',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
|
||||
('name', models.CharField(validators=[orchestra.core.validators.validate_name], verbose_name='name', max_length=128)),
|
||||
('protocol', models.CharField(verbose_name='protocol', default='http', choices=[('http', 'HTTP'), ('https', 'HTTPS'), ('http/https', 'HTTP and HTTPS'), ('https-only', 'HTTPS only')], help_text='Select the protocol(s) for this website<br><tt>HTTPS only</tt> performs a redirection from <tt>http</tt> to <tt>https</tt>.', max_length=16)),
|
||||
('is_active', models.BooleanField(verbose_name='active', default=True)),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='websites', verbose_name='Account', to=settings.AUTH_USER_MODEL)),
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=128, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
||||
('protocol', models.CharField(choices=[('http', 'HTTP'), ('https', 'HTTPS'), ('http/https', 'HTTP and HTTPS'), ('https-only', 'HTTPS only')], default='http', help_text='Select the protocol(s) for this website<br><tt>HTTPS only</tt> performs a redirection from <tt>http</tt> to <tt>https</tt>.', max_length=16, verbose_name='protocol')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='active')),
|
||||
('comments', models.TextField(blank=True, default='')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='websites', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('contents', models.ManyToManyField(through='websites.Content', to='webapps.WebApp')),
|
||||
('domains', models.ManyToManyField(verbose_name='domains', related_name='websites', to='domains.Domain')),
|
||||
('domains', models.ManyToManyField(blank=True, related_name='websites', to='domains.Domain', verbose_name='domains')),
|
||||
('target_server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='websites', to='orchestration.Server', verbose_name='Target Server')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('name', 'account')},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WebsiteDirective',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
|
||||
('name', models.CharField(verbose_name='name', choices=[(None, '-------'), ('SSL', [('ssl-ca', 'SSL CA'), ('ssl-cert', 'SSL cert'), ('ssl-key', 'SSL key')]), ('HTTPD', [('redirect', 'Redirection'), ('proxy', 'Proxy'), ('error-document', 'ErrorDocumentRoot')]), ('ModSecurity', [('sec-rule-remove', 'SecRuleRemoveById'), ('sec-engine', 'SecRuleEngine Off')]), ('SaaS', [('wordpress-saas', 'WordPress SaaS'), ('dokuwiki-saas', 'DokuWiki SaaS'), ('drupal-saas', 'Drupdal SaaS')])], max_length=128)),
|
||||
('value', models.CharField(verbose_name='value', max_length=256)),
|
||||
('website', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='directives', verbose_name='web site', to='websites.Website')),
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(choices=[(None, '-------'), ('HTTPD', [('redirect', 'Redirection'), ('proxy', 'Proxy'), ('error-document', 'ErrorDocumentRoot')]), ('SSL', [('ssl-ca', 'SSL CA'), ('ssl-cert', 'SSL cert'), ('ssl-key', 'SSL key')]), ('ModSecurity', [('sec-rule-remove', 'SecRuleRemoveById'), ('sec-engine', 'SecRuleEngine Off')]), ('SaaS', [('wordpress-saas', 'WordPress SaaS'), ('dokuwiki-saas', 'DokuWiki SaaS'), ('drupal-saas', 'Drupdal SaaS'), ('moodle-saas', 'Moodle SaaS')])], db_index=True, max_length=128, verbose_name='name')),
|
||||
('value', models.CharField(blank=True, max_length=256, verbose_name='value')),
|
||||
('website', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='directives', to='websites.Website', verbose_name='web site')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='website',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, verbose_name='web site', to='websites.Website'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='website',
|
||||
unique_together=set([('name', 'account')]),
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='websites.Website', verbose_name='web site'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='content',
|
||||
unique_together=set([('website', 'path')]),
|
||||
unique_together={('website', 'path')},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 2.2.28 on 2023-08-17 09:49
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('orchestration', '__first__'),
|
||||
('websites', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='website',
|
||||
unique_together={('name', 'account', 'target_server')},
|
||||
),
|
||||
]
|
|
@ -40,7 +40,7 @@ class Website(models.Model):
|
|||
comments = models.TextField(default="", blank=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = ('name', 'account')
|
||||
unique_together = ('name', 'account', 'target_server')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
|
|
@ -93,6 +93,7 @@ ORCHESTRA_SSH_CONTROL_PATH = Setting('ORCHESTRA_SSH_CONTROL_PATH',
|
|||
|
||||
NEW_SERVERS = Setting('NEW_SERVERS',
|
||||
(
|
||||
'bookworm',
|
||||
'web-11.pangea.lan',
|
||||
'web-12.pangea.lan',
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue