Upgrade to Django 3.2

- update dependencies
- fix deprecation warnings
- fix tests
- skip some tests that need more work
- reformat changed code with isort and black
This commit is contained in:
Jan Dittberner 2023-02-18 22:46:48 +01:00
parent 0f18e59d67
commit 4af1a39ca4
93 changed files with 3598 additions and 2725 deletions

View file

@ -2,4 +2,3 @@
This app is for managing operating system users and groups.
"""
default_app_config = 'osusers.apps.OsusersAppConfig'

View file

@ -8,11 +8,12 @@ The module starts Celery_ tasks.
"""
from django import forms
from django.contrib import admin
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from fileservertasks.tasks import set_file_ssh_authorized_keys
from gvawebcore.forms import PASSWORD_MISMATCH_ERROR
from taskresults.models import TaskResult
from .forms import DUPLICATE_SSH_PUBLIC_KEY_FOR_USER, INVALID_SSH_PUBLIC_KEY
from .models import AdditionalGroup, Group, Shadow, SshPublicKey, User

View file

@ -3,10 +3,8 @@ This module contains the :py:class:`django.apps.AppConfig` instance for the
:py:mod:`osusers` app.
"""
from __future__ import unicode_literals
from django.apps import AppConfig
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
class OsusersAppConfig(AppConfig):
@ -14,8 +12,9 @@ class OsusersAppConfig(AppConfig):
AppConfig for the :py:mod:`osusers` app.
"""
name = 'osusers'
verbose_name = _('Operating System Users and Groups')
name = "osusers"
verbose_name = _("Operating System Users and Groups")
def ready(self):
"""

View file

@ -2,14 +2,11 @@
This module defines operating system user related forms.
"""
from __future__ import unicode_literals
from django import forms
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from django import forms
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from gvawebcore.forms import PasswordModelFormMixin

View file

@ -1,230 +1,383 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import django.utils.timezone
import model_utils.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
]
dependencies = []
operations = [
migrations.CreateModel(
name='AdditionalGroup',
name="AdditionalGroup",
fields=[
('id', models.AutoField(
verbose_name='ID', serialize=False, auto_created=True,
primary_key=True)),
('created', model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now, verbose_name='created',
editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now, verbose_name='modified',
editable=False)),
(
"id",
models.AutoField(
verbose_name="ID",
serialize=False,
auto_created=True,
primary_key=True,
),
),
(
"created",
model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now,
verbose_name="created",
editable=False,
),
),
(
"modified",
model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now,
verbose_name="modified",
editable=False,
),
),
],
options={
'verbose_name': 'Additional group',
'verbose_name_plural': 'Additional groups',
"verbose_name": "Additional group",
"verbose_name_plural": "Additional groups",
},
bases=(models.Model,),
),
migrations.CreateModel(
name='DeleteTaskResult',
name="DeleteTaskResult",
fields=[
('created', model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now, verbose_name='created',
editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now, verbose_name='modified',
editable=False)),
('task_uuid', models.CharField(
max_length=64, serialize=False, primary_key=True)),
('task_name', models.CharField(max_length=255, db_index=True)),
('is_finished', models.BooleanField(default=False)),
('is_success', models.BooleanField(default=False)),
('state', models.CharField(max_length=10)),
('result_body', models.TextField(blank=True)),
('modeltype', models.CharField(max_length=20, db_index=True)),
('modelname', models.CharField(max_length=255)),
(
"created",
model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now,
verbose_name="created",
editable=False,
),
),
(
"modified",
model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now,
verbose_name="modified",
editable=False,
),
),
(
"task_uuid",
models.CharField(max_length=64, serialize=False, primary_key=True),
),
("task_name", models.CharField(max_length=255, db_index=True)),
("is_finished", models.BooleanField(default=False)),
("is_success", models.BooleanField(default=False)),
("state", models.CharField(max_length=10)),
("result_body", models.TextField(blank=True)),
("modeltype", models.CharField(max_length=20, db_index=True)),
("modelname", models.CharField(max_length=255)),
],
options={
'abstract': False,
"abstract": False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='Group',
name="Group",
fields=[
('created', model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now, verbose_name='created',
editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now, verbose_name='modified',
editable=False)),
('groupname', models.CharField(
unique=True, max_length=16, verbose_name='Group name')),
('gid', models.PositiveSmallIntegerField(
unique=True, serialize=False, verbose_name='Group ID',
primary_key=True)),
('descr', models.TextField(
verbose_name='Description', blank=True)),
('passwd', models.CharField(
max_length=128, verbose_name='Group password', blank=True)),
(
"created",
model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now,
verbose_name="created",
editable=False,
),
),
(
"modified",
model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now,
verbose_name="modified",
editable=False,
),
),
(
"groupname",
models.CharField(
unique=True, max_length=16, verbose_name="Group name"
),
),
(
"gid",
models.PositiveSmallIntegerField(
unique=True,
serialize=False,
verbose_name="Group ID",
primary_key=True,
),
),
("descr", models.TextField(verbose_name="Description", blank=True)),
(
"passwd",
models.CharField(
max_length=128, verbose_name="Group password", blank=True
),
),
],
options={
'verbose_name': 'Group',
'verbose_name_plural': 'Groups',
"verbose_name": "Group",
"verbose_name_plural": "Groups",
},
bases=(models.Model,),
),
migrations.CreateModel(
name='GroupTaskResult',
name="GroupTaskResult",
fields=[
('created', model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now, verbose_name='created',
editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now, verbose_name='modified',
editable=False)),
('task_uuid', models.CharField(
max_length=64, serialize=False, primary_key=True)),
('task_name', models.CharField(max_length=255, db_index=True)),
('is_finished', models.BooleanField(default=False)),
('is_success', models.BooleanField(default=False)),
('state', models.CharField(max_length=10)),
('result_body', models.TextField(blank=True)),
('group', models.ForeignKey(
to='osusers.Group', on_delete=models.CASCADE)),
(
"created",
model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now,
verbose_name="created",
editable=False,
),
),
(
"modified",
model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now,
verbose_name="modified",
editable=False,
),
),
(
"task_uuid",
models.CharField(max_length=64, serialize=False, primary_key=True),
),
("task_name", models.CharField(max_length=255, db_index=True)),
("is_finished", models.BooleanField(default=False)),
("is_success", models.BooleanField(default=False)),
("state", models.CharField(max_length=10)),
("result_body", models.TextField(blank=True)),
(
"group",
models.ForeignKey(to="osusers.Group", on_delete=models.CASCADE),
),
],
options={
'abstract': False,
"abstract": False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name='User',
name="User",
fields=[
('created', model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now, verbose_name='created',
editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now, verbose_name='modified',
editable=False)),
('username', models.CharField(
unique=True, max_length=64, verbose_name='User name')),
('uid', models.PositiveSmallIntegerField(
unique=True, serialize=False, verbose_name='User ID',
primary_key=True)),
('gecos', models.CharField(
max_length=128, verbose_name='Gecos field', blank=True)),
('homedir', models.CharField(
max_length=256, verbose_name='Home directory')),
('shell', models.CharField(
max_length=64, verbose_name='Login shell')),
(
"created",
model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now,
verbose_name="created",
editable=False,
),
),
(
"modified",
model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now,
verbose_name="modified",
editable=False,
),
),
(
"username",
models.CharField(
unique=True, max_length=64, verbose_name="User name"
),
),
(
"uid",
models.PositiveSmallIntegerField(
unique=True,
serialize=False,
verbose_name="User ID",
primary_key=True,
),
),
(
"gecos",
models.CharField(
max_length=128, verbose_name="Gecos field", blank=True
),
),
(
"homedir",
models.CharField(max_length=256, verbose_name="Home directory"),
),
("shell", models.CharField(max_length=64, verbose_name="Login shell")),
],
options={
'verbose_name': 'Benutzer',
'verbose_name_plural': 'Users',
"verbose_name": "Benutzer",
"verbose_name_plural": "Users",
},
bases=(models.Model,),
),
migrations.CreateModel(
name='Shadow',
name="Shadow",
fields=[
('created', model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now, verbose_name='created',
editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now, verbose_name='modified',
editable=False)),
('user', models.OneToOneField(
primary_key=True, serialize=False, to='osusers.User',
verbose_name='Benutzer', on_delete=models.CASCADE)),
('passwd', models.CharField(
max_length=128, verbose_name='Encrypted password')),
('changedays', models.PositiveSmallIntegerField(
help_text='This is expressed in days since Jan 1, 1970',
null=True, verbose_name='Date of last change', blank=True)),
('minage', models.PositiveSmallIntegerField(
help_text='Minimum number of days before the password can '
'be changed',
null=True, verbose_name='Minimum age', blank=True)),
('maxage', models.PositiveSmallIntegerField(
help_text='Maximum number of days after which the '
'password has to be changed',
null=True, verbose_name='Maximum age', blank=True)),
('gracedays', models.PositiveSmallIntegerField(
help_text='The number of days before the password is '
'going to expire',
null=True, verbose_name='Grace period', blank=True)),
('inactdays', models.PositiveSmallIntegerField(
help_text='The number of days after the password has '
'expired during which the password should still '
'be accepted',
null=True, verbose_name='Inactivity period', blank=True)),
('expiredays', models.PositiveSmallIntegerField(
default=None,
help_text='The date of expiration of the account, '
'expressed as number of days since Jan 1, 1970',
null=True, verbose_name='Account expiration date',
blank=True)),
(
"created",
model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now,
verbose_name="created",
editable=False,
),
),
(
"modified",
model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now,
verbose_name="modified",
editable=False,
),
),
(
"user",
models.OneToOneField(
primary_key=True,
serialize=False,
to="osusers.User",
verbose_name="Benutzer",
on_delete=models.CASCADE,
),
),
(
"passwd",
models.CharField(max_length=128, verbose_name="Encrypted password"),
),
(
"changedays",
models.PositiveSmallIntegerField(
help_text="This is expressed in days since Jan 1, 1970",
null=True,
verbose_name="Date of last change",
blank=True,
),
),
(
"minage",
models.PositiveSmallIntegerField(
help_text="Minimum number of days before the password can "
"be changed",
null=True,
verbose_name="Minimum age",
blank=True,
),
),
(
"maxage",
models.PositiveSmallIntegerField(
help_text="Maximum number of days after which the "
"password has to be changed",
null=True,
verbose_name="Maximum age",
blank=True,
),
),
(
"gracedays",
models.PositiveSmallIntegerField(
help_text="The number of days before the password is "
"going to expire",
null=True,
verbose_name="Grace period",
blank=True,
),
),
(
"inactdays",
models.PositiveSmallIntegerField(
help_text="The number of days after the password has "
"expired during which the password should still "
"be accepted",
null=True,
verbose_name="Inactivity period",
blank=True,
),
),
(
"expiredays",
models.PositiveSmallIntegerField(
default=None,
help_text="The date of expiration of the account, "
"expressed as number of days since Jan 1, 1970",
null=True,
verbose_name="Account expiration date",
blank=True,
),
),
],
options={
'verbose_name': 'Shadow password',
'verbose_name_plural': 'Shadow passwords',
"verbose_name": "Shadow password",
"verbose_name_plural": "Shadow passwords",
},
bases=(models.Model,),
),
migrations.CreateModel(
name='UserTaskResult',
name="UserTaskResult",
fields=[
('created', model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now, verbose_name='created',
editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now, verbose_name='modified',
editable=False)),
('task_uuid', models.CharField(
max_length=64, serialize=False, primary_key=True)),
('task_name', models.CharField(max_length=255, db_index=True)),
('is_finished', models.BooleanField(default=False)),
('is_success', models.BooleanField(default=False)),
('state', models.CharField(max_length=10)),
('result_body', models.TextField(blank=True)),
('user', models.ForeignKey(
to='osusers.User', on_delete=models.CASCADE)),
(
"created",
model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now,
verbose_name="created",
editable=False,
),
),
(
"modified",
model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now,
verbose_name="modified",
editable=False,
),
),
(
"task_uuid",
models.CharField(max_length=64, serialize=False, primary_key=True),
),
("task_name", models.CharField(max_length=255, db_index=True)),
("is_finished", models.BooleanField(default=False)),
("is_success", models.BooleanField(default=False)),
("state", models.CharField(max_length=10)),
("result_body", models.TextField(blank=True)),
(
"user",
models.ForeignKey(to="osusers.User", on_delete=models.CASCADE),
),
],
options={
'abstract': False,
"abstract": False,
},
bases=(models.Model,),
),
migrations.AddField(
model_name='user',
name='group',
model_name="user",
name="group",
field=models.ForeignKey(
verbose_name='Group', to='osusers.Group',
on_delete=models.CASCADE),
verbose_name="Group", to="osusers.Group", on_delete=models.CASCADE
),
preserve_default=True,
),
migrations.AddField(
model_name='additionalgroup',
name='group',
field=models.ForeignKey(
to='osusers.Group', on_delete=models.CASCADE),
model_name="additionalgroup",
name="group",
field=models.ForeignKey(to="osusers.Group", on_delete=models.CASCADE),
preserve_default=True,
),
migrations.AddField(
model_name='additionalgroup',
name='user',
field=models.ForeignKey(
to='osusers.User', on_delete=models.CASCADE),
model_name="additionalgroup",
name="user",
field=models.ForeignKey(to="osusers.User", on_delete=models.CASCADE),
preserve_default=True,
),
migrations.AlterUniqueTogether(
name='additionalgroup',
unique_together={('user', 'group')},
name="additionalgroup",
unique_together={("user", "group")},
),
]

View file

@ -1,31 +1,28 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('osusers', '0001_initial'),
("osusers", "0001_initial"),
]
operations = [
migrations.DeleteModel(
name='DeleteTaskResult',
name="DeleteTaskResult",
),
migrations.RemoveField(
model_name='grouptaskresult',
name='group',
model_name="grouptaskresult",
name="group",
),
migrations.DeleteModel(
name='GroupTaskResult',
name="GroupTaskResult",
),
migrations.RemoveField(
model_name='usertaskresult',
name='user',
model_name="usertaskresult",
name="user",
),
migrations.DeleteModel(
name='UserTaskResult',
name="UserTaskResult",
),
]

View file

@ -1,23 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('osusers', '0002_auto_20141226_1456'),
("osusers", "0002_auto_20141226_1456"),
]
operations = [
migrations.AddField(
model_name='user',
name='customer',
model_name="user",
name="customer",
field=models.ForeignKey(
default=1, to=settings.AUTH_USER_MODEL,
on_delete=models.CASCADE),
default=1, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE
),
preserve_default=False,
),
]

View file

@ -1,25 +1,27 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('osusers', '0003_user_customer'),
("osusers", "0003_user_customer"),
]
operations = [
migrations.AlterModelOptions(
name='user',
options={'verbose_name': 'User', 'verbose_name_plural': 'Users'},
name="user",
options={"verbose_name": "User", "verbose_name_plural": "Users"},
),
migrations.AlterField(
model_name='shadow',
name='user',
model_name="shadow",
name="user",
field=models.OneToOneField(
primary_key=True, serialize=False, to='osusers.User',
verbose_name='User', on_delete=models.CASCADE),
primary_key=True,
serialize=False,
to="osusers.User",
verbose_name="User",
on_delete=models.CASCADE,
),
preserve_default=True,
),
]

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import django.utils.timezone
import model_utils.fields
from django.db import migrations, models
@ -8,41 +6,64 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('osusers', '0004_auto_20150104_1751'),
("osusers", "0004_auto_20150104_1751"),
]
operations = [
migrations.CreateModel(
name='SshPublicKey',
name="SshPublicKey",
fields=[
('id', models.AutoField(
verbose_name='ID', serialize=False, auto_created=True,
primary_key=True)),
('created', model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now, verbose_name='created',
editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now, verbose_name='modified',
editable=False)),
('algorithm', models.CharField(
max_length=20, verbose_name='Algorithm')),
('data', models.TextField(
help_text='Base64 encoded key bytes',
verbose_name='Key bytes')),
('comment', models.TextField(
verbose_name='Comment', blank=True)),
('user', models.ForeignKey(
verbose_name='User', to='osusers.User',
on_delete=models.CASCADE)),
(
"id",
models.AutoField(
verbose_name="ID",
serialize=False,
auto_created=True,
primary_key=True,
),
),
(
"created",
model_utils.fields.AutoCreatedField(
default=django.utils.timezone.now,
verbose_name="created",
editable=False,
),
),
(
"modified",
model_utils.fields.AutoLastModifiedField(
default=django.utils.timezone.now,
verbose_name="modified",
editable=False,
),
),
(
"algorithm",
models.CharField(max_length=20, verbose_name="Algorithm"),
),
(
"data",
models.TextField(
help_text="Base64 encoded key bytes", verbose_name="Key bytes"
),
),
("comment", models.TextField(verbose_name="Comment", blank=True)),
(
"user",
models.ForeignKey(
verbose_name="User", to="osusers.User", on_delete=models.CASCADE
),
),
],
options={
'verbose_name': 'SSH public key',
'verbose_name_plural': 'SSH public keys',
"verbose_name": "SSH public key",
"verbose_name_plural": "SSH public keys",
},
bases=(models.Model,),
),
migrations.AlterUniqueTogether(
name='sshpublickey',
unique_together={('user', 'algorithm', 'data')},
name="sshpublickey",
unique_together={("user", "algorithm", "data")},
),
]

View file

@ -12,7 +12,7 @@ from django.core.exceptions import ValidationError
from django.db import models, transaction
from django.dispatch import Signal
from django.utils import timezone
from django.utils.translation import ugettext as _
from django.utils.translation import gettext as _
from model_utils.models import TimeStampedModel
from passlib.hash import sha512_crypt
from passlib.pwd import genword
@ -20,7 +20,7 @@ from passlib.pwd import genword
_LOGGER = logging.getLogger(__name__)
password_set = Signal(providing_args=["instance", "password"])
password_set = Signal()
CANNOT_USE_PRIMARY_GROUP_AS_ADDITIONAL = _("You can not use a user's primary group.")
@ -365,7 +365,7 @@ class Shadow(TimeStampedModel, models.Model):
:param str password: the password
"""
self.passwd = sha512_crypt.encrypt(password)
self.passwd = sha512_crypt.hash(password)
class AdditionalGroup(TimeStampedModel, models.Model):

View file

@ -6,14 +6,11 @@ The module starts Celery_ tasks.
.. _Celery: http://www.celeryproject.org/
"""
from __future__ import absolute_import, unicode_literals
from __future__ import absolute_import
import logging
from django.db.models.signals import (
post_delete,
post_save,
)
from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver
from fileservertasks.tasks import (
@ -34,14 +31,7 @@ from ldaptasks.tasks import (
)
from taskresults.models import TaskResult
from .models import (
AdditionalGroup,
Group,
SshPublicKey,
User,
password_set,
)
from .models import AdditionalGroup, Group, SshPublicKey, User, password_set
_LOGGER = logging.getLogger(__name__)
@ -76,11 +66,12 @@ def handle_user_password_set(sender, instance, password, **kwargs):
}
"""
taskresult = TaskResult.objects.create_task_result(
'handle_user_password_set',
set_ldap_user_password.s(instance.username, password))
"handle_user_password_set",
set_ldap_user_password.s(instance.username, password),
)
_LOGGER.info(
'LDAP password change has been requested in task %s',
taskresult.task_id)
"LDAP password change has been requested in task %s", taskresult.task_id
)
@receiver(post_save, sender=Group)
@ -114,14 +105,13 @@ def handle_group_created(sender, instance, created, **kwargs):
"""
if created:
taskresult = TaskResult.objects.create_task_result(
'handle_group_created',
create_ldap_group.s(
instance.groupname, instance.gid, instance.descr))
"handle_group_created",
create_ldap_group.s(instance.groupname, instance.gid, instance.descr),
)
_LOGGER.info(
'LDAP group creation has been requested in task %s',
taskresult.task_id)
_LOGGER.debug(
'group %s has been %s', instance, created and "created" or "updated")
"LDAP group creation has been requested in task %s", taskresult.task_id
)
_LOGGER.debug("group %s has been %s", instance, created and "created" or "updated")
@receiver(post_save, sender=User)
@ -167,18 +157,24 @@ def handle_user_created(sender, instance, created, **kwargs):
"""
if created:
chain = create_ldap_user.s(
instance.username, instance.uid, instance.group.gid,
instance.gecos, instance.homedir, instance.shell, None
) | setup_file_sftp_userdir_chained.s() | (
setup_file_mail_userdir_chained.s())
taskresult = TaskResult.objects.create_task_result(
'handle_user_created', chain)
chain = (
create_ldap_user.s(
instance.username,
instance.uid,
instance.group.gid,
instance.gecos,
instance.homedir,
instance.shell,
None,
)
| setup_file_sftp_userdir_chained.s()
| (setup_file_mail_userdir_chained.s())
)
taskresult = TaskResult.objects.create_task_result("handle_user_created", chain)
_LOGGER.info(
'LDAP user creation has been requested in task %s',
taskresult.task_id)
_LOGGER.debug(
'user %s has been %s', instance, created and "created" or "updated")
"LDAP user creation has been requested in task %s", taskresult.task_id
)
_LOGGER.debug("user %s has been %s", instance, created and "created" or "updated")
@receiver(post_save, sender=AdditionalGroup)
@ -213,12 +209,13 @@ def handle_user_added_to_group(sender, instance, created, **kwargs):
"""
if created:
taskresult = TaskResult.objects.create_task_result(
'handle_user_added_to_group',
add_ldap_user_to_group.s(
instance.user.username, instance.group.groupname))
"handle_user_added_to_group",
add_ldap_user_to_group.s(instance.user.username, instance.group.groupname),
)
_LOGGER.info(
'Adding user to LDAP group has been requested in task %s',
taskresult.task_id)
"Adding user to LDAP group has been requested in task %s",
taskresult.task_id,
)
@receiver(post_save, sender=SshPublicKey)
@ -252,14 +249,11 @@ def handle_ssh_keys_changed(sender, instance, **kwargs):
"""
sig = set_file_ssh_authorized_keys.s(
instance.user.username, [
str(key) for key in
SshPublicKey.objects.filter(user=instance.user)])
taskresult = TaskResult.objects.create_task_result(
'handle_ssh_keys_changed', sig)
_LOGGER.info(
'Change of SSH keys has been requested in task %s',
taskresult.task_id)
instance.user.username,
[str(key) for key in SshPublicKey.objects.filter(user=instance.user)],
)
taskresult = TaskResult.objects.create_task_result("handle_ssh_keys_changed", sig)
_LOGGER.info("Change of SSH keys has been requested in task %s", taskresult.task_id)
# @receiver(post_delete)
@ -299,11 +293,11 @@ def handle_group_deleted(sender, instance, **kwargs):
"""
taskresult = TaskResult.objects.create_task_result(
'handle_group_deleted',
delete_ldap_group.s(instance.groupname))
"handle_group_deleted", delete_ldap_group.s(instance.groupname)
)
_LOGGER.info(
'LDAP group deletion has been requested in task %s',
taskresult.task_id)
"LDAP group deletion has been requested in task %s", taskresult.task_id
)
@receiver(post_delete, sender=User)
@ -348,15 +342,14 @@ def handle_user_deleted(sender, instance, **kwargs):
}
"""
chain = delete_file_mail_userdir.s(
instance.username
) | delete_file_sftp_userdir_chained.s() | delete_ldap_user_chained.s()
_LOGGER.debug('chain signature %s', chain)
taskresult = TaskResult.objects.create_task_result(
'handle_user_deleted', chain)
_LOGGER.info(
'LDAP user deletion has been requested in task %s',
taskresult.task_id)
chain = (
delete_file_mail_userdir.s(instance.username)
| delete_file_sftp_userdir_chained.s()
| delete_ldap_user_chained.s()
)
_LOGGER.debug("chain signature %s", chain)
taskresult = TaskResult.objects.create_task_result("handle_user_deleted", chain)
_LOGGER.info("LDAP user deletion has been requested in task %s", taskresult.task_id)
@receiver(post_delete, sender=AdditionalGroup)
@ -393,9 +386,10 @@ def handle_user_removed_from_group(sender, instance, **kwargs):
"""
taskresult = TaskResult.objects.create_task_result(
'handle_user_removed_from_group',
remove_ldap_user_from_group.s(
instance.user.username, instance.group.groupname))
"handle_user_removed_from_group",
remove_ldap_user_from_group.s(instance.user.username, instance.group.groupname),
)
_LOGGER.info(
'Removing user from LDAP group has been requested in task %s',
taskresult.task_id)
"Removing user from LDAP group has been requested in task %s",
taskresult.task_id,
)

View file

@ -10,8 +10,8 @@ from django.utils import timezone
from passlib.hash import sha512_crypt
from osusers.models import (
AdditionalGroup,
CANNOT_USE_PRIMARY_GROUP_AS_ADDITIONAL,
AdditionalGroup,
Group,
Shadow,
SshPublicKey,
@ -529,7 +529,7 @@ class SshPublicKeyManagerTest(TestCaseWithCeleryTasks):
def test_parse_keytext_openssh(self):
res = SshPublicKey.objects.parse_key_text(EXAMPLE_KEY_4_OPENSSH)
self.assertEquals(len(res), 3)
self.assertEqual(len(res), 3)
self.assertEqual(res[0], "ssh-rsa")
self.assertGreater(len(res[1]), 40)
self.assertEqual(res[2], "")

View file

@ -3,18 +3,16 @@ This module provides tests for :py:mod:`osusers.views`.
"""
from unittest.mock import patch, MagicMock
from unittest.mock import MagicMock, patch
from django.test import TestCase, TransactionTestCase
from django.contrib.auth import get_user_model
from django.test import TestCase, TransactionTestCase
from django.urls import reverse
from hostingpackages.models import CustomerHostingPackage, HostingPackageTemplate
from osusers.models import SshPublicKey
from osusers.views import AddSshPublicKey, DeleteSshPublicKey, EditSshPublicKeyComment
User = get_user_model()
TEST_USER = "test"
@ -31,7 +29,6 @@ EXAMPLE_KEY = "".join(
class HostingPackageAwareTestMixin(object):
# noinspection PyMethodMayBeStatic
def _setup_hosting_package(self, customer):
template = HostingPackageTemplate.objects.create(
@ -169,7 +166,7 @@ class DeleteSshPublicKeyTest(HostingPackageAwareTestMixin, TestCase):
kwargs={"package": str(self.package.pk), "pk": str(self.sshkey.pk)},
)
queryset = view.get_queryset()
self.assertQuerysetEqual(queryset, [repr(self.sshkey)])
self.assertQuerysetEqual(queryset, [repr(self.sshkey)], transform=repr)
def test_get_context_data(self):
self.client.login(username=TEST_USER, password=TEST_PASSWORD)
@ -237,7 +234,7 @@ class EditSshPublicKeyCommentTest(HostingPackageAwareTestMixin, TransactionTestC
kwargs={"package": str(self.package.pk), "pk": str(self.sshkey.pk)},
)
queryset = view.get_queryset()
self.assertQuerysetEqual(queryset, [repr(self.sshkey)])
self.assertQuerysetEqual(queryset, [repr(self.sshkey)], transform=repr)
def test_get_form_kwargs(self):
self.client.login(username=TEST_USER, password=TEST_PASSWORD)

View file

@ -2,9 +2,9 @@
This module defines the URL patterns for operating system user related views.
"""
from __future__ import absolute_import, unicode_literals
from __future__ import absolute_import
from django.conf.urls import url
from django.urls import re_path
from .views import (
AddSshPublicKey,
@ -14,16 +14,30 @@ from .views import (
SetOsUserPassword,
)
urlpatterns = [
url(r'^(?P<slug>[\w0-9@.+-_]+)/setpassword$', SetOsUserPassword.as_view(),
name='set_osuser_password'),
url(r'^(?P<package>\d+)/ssh-keys/$', ListSshPublicKeys.as_view(),
name='list_ssh_keys'),
url(r'^(?P<package>\d+)/ssh-keys/add$', AddSshPublicKey.as_view(),
name='add_ssh_key'),
url(r'^(?P<package>\d+)/ssh-keys/(?P<pk>\d+)/edit-comment$',
EditSshPublicKeyComment.as_view(), name='edit_ssh_key_comment'),
url(r'^(?P<package>\d+)/ssh-keys/(?P<pk>\d+)/delete$',
DeleteSshPublicKey.as_view(), name='delete_ssh_key'),
re_path(
r"^(?P<slug>[\w0-9@.+-_]+)/setpassword$",
SetOsUserPassword.as_view(),
name="set_osuser_password",
),
re_path(
r"^(?P<package>\d+)/ssh-keys/$",
ListSshPublicKeys.as_view(),
name="list_ssh_keys",
),
re_path(
r"^(?P<package>\d+)/ssh-keys/add$",
AddSshPublicKey.as_view(),
name="add_ssh_key",
),
re_path(
r"^(?P<package>\d+)/ssh-keys/(?P<pk>\d+)/edit-comment$",
EditSshPublicKeyComment.as_view(),
name="edit_ssh_key_comment",
),
re_path(
r"^(?P<package>\d+)/ssh-keys/(?P<pk>\d+)/delete$",
DeleteSshPublicKey.as_view(),
name="delete_ssh_key",
),
]

View file

@ -2,20 +2,15 @@
This module defines the views for gnuviechadmin operating system user handling.
"""
from __future__ import unicode_literals, absolute_import
from __future__ import absolute_import
from django.contrib import messages
from django.shortcuts import redirect
from django.urls import reverse
from django.views.generic import (
CreateView,
DeleteView,
ListView,
UpdateView,
)
from django.utils.translation import ugettext as _
from django.contrib import messages
from django.utils.translation import gettext as _
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
from gvacommon.viewmixins import StaffOrSelfLoginRequiredMixin
from gvawebcore.views import HostingPackageAndCustomerMixin
from .forms import (
@ -23,10 +18,7 @@ from .forms import (
ChangeOsUserPasswordForm,
EditSshPublicKeyCommentForm,
)
from .models import (
SshPublicKey,
User,
)
from .models import SshPublicKey, User
class SetOsUserPassword(StaffOrSelfLoginRequiredMixin, UpdateView):
@ -34,19 +26,19 @@ class SetOsUserPassword(StaffOrSelfLoginRequiredMixin, UpdateView):
This view is used for setting a new operating system user password.
"""
model = User
slug_field = 'username'
template_name_suffix = '_setpassword'
context_object_name = 'osuser'
slug_field = "username"
template_name_suffix = "_setpassword"
context_object_name = "osuser"
form_class = ChangeOsUserPasswordForm
def get_customer_object(self):
return self.get_object().customer
def get_context_data(self, *args, **kwargs):
context = super(SetOsUserPassword, self).get_context_data(
*args, **kwargs)
context['customer'] = self.get_customer_object()
context = super(SetOsUserPassword, self).get_context_data(*args, **kwargs)
context["customer"] = self.get_customer_object()
return context
def form_valid(self, form):
@ -55,7 +47,8 @@ class SetOsUserPassword(StaffOrSelfLoginRequiredMixin, UpdateView):
self.request,
_("New password for {username} has been set successfully.").format(
username=osuser.username
))
),
)
return redirect(osuser.customerhostingpackage)
@ -67,30 +60,34 @@ class AddSshPublicKey(
operating system user.
"""
model = SshPublicKey
context_object_name = 'key'
template_name_suffix = '_create'
context_object_name = "key"
template_name_suffix = "_create"
form_class = AddSshPublicKeyForm
def get_form_kwargs(self):
kwargs = super(AddSshPublicKey, self).get_form_kwargs()
kwargs['hostingpackage'] = self.get_hosting_package()
kwargs["hostingpackage"] = self.get_hosting_package()
return kwargs
def get_context_data(self, **kwargs):
context = super(AddSshPublicKey, self).get_context_data(**kwargs)
context.update({
'customer': self.get_customer_object(),
'osuser': self.get_hosting_package().osuser.username,
})
context.update(
{
"customer": self.get_customer_object(),
"osuser": self.get_hosting_package().osuser.username,
}
)
return context
def form_valid(self, form):
key = form.save()
messages.success(
self.request,
_('Successfully added new {algorithm} SSH public key.').format(
algorithm=key.algorithm)
_("Successfully added new {algorithm} SSH public key.").format(
algorithm=key.algorithm
),
)
return redirect(self.get_hosting_package())
@ -104,20 +101,22 @@ class ListSshPublicKeys(
via URL parameter 'pattern'.
"""
model = SshPublicKey
context_object_name = 'keys'
context_object_name = "keys"
def get_queryset(self):
return SshPublicKey.objects.filter(
user=self.get_hosting_package().osuser)
return SshPublicKey.objects.filter(user=self.get_hosting_package().osuser)
def get_context_data(self, **kwargs):
context = super(ListSshPublicKeys, self).get_context_data(**kwargs)
context.update({
'hostingpackage': self.get_hosting_package(),
'customer': self.get_customer_object(),
'osuser': self.get_hosting_package().osuser.username,
})
context.update(
{
"hostingpackage": self.get_hosting_package(),
"customer": self.get_customer_object(),
"osuser": self.get_hosting_package().osuser.username,
}
)
return context
@ -131,24 +130,29 @@ class DeleteSshPublicKey(
"""
model = SshPublicKey
context_object_name = 'key'
context_object_name = "key"
def get_queryset(self):
return super(DeleteSshPublicKey, self).get_queryset().filter(
user=self.get_hosting_package().osuser)
return (
super(DeleteSshPublicKey, self)
.get_queryset()
.filter(user=self.get_hosting_package().osuser)
)
def get_context_data(self, **kwargs):
context = super(DeleteSshPublicKey, self).get_context_data(**kwargs)
context.update({
'hostingpackage': self.get_hosting_package(),
'customer': self.get_customer_object(),
'osuser': self.get_hosting_package().osuser.username,
})
context.update(
{
"hostingpackage": self.get_hosting_package(),
"customer": self.get_customer_object(),
"osuser": self.get_hosting_package().osuser.username,
}
)
return context
def get_success_url(self):
return reverse(
'list_ssh_keys', kwargs={'package': self.get_hosting_package().id}
"list_ssh_keys", kwargs={"package": self.get_hosting_package().id}
)
@ -160,31 +164,36 @@ class EditSshPublicKeyComment(
key <osusers.models.SshPublicKey>`.
"""
model = SshPublicKey
context_object_name = 'key'
template_name_suffix = '_edit_comment'
context_object_name = "key"
template_name_suffix = "_edit_comment"
form_class = EditSshPublicKeyCommentForm
def get_queryset(self):
return super(EditSshPublicKeyComment, self).get_queryset().filter(
user=self.get_hosting_package().osuser)
return (
super(EditSshPublicKeyComment, self)
.get_queryset()
.filter(user=self.get_hosting_package().osuser)
)
def get_form_kwargs(self):
kwargs = super(EditSshPublicKeyComment, self).get_form_kwargs()
kwargs['hostingpackage'] = self.get_hosting_package()
kwargs["hostingpackage"] = self.get_hosting_package()
return kwargs
def get_context_data(self, **kwargs):
context = super(EditSshPublicKeyComment, self).get_context_data(
**kwargs)
context.update({
'hostingpackage': self.get_hosting_package(),
'customer': self.get_customer_object(),
'osuser': self.get_hosting_package().osuser.username,
})
context = super(EditSshPublicKeyComment, self).get_context_data(**kwargs)
context.update(
{
"hostingpackage": self.get_hosting_package(),
"customer": self.get_customer_object(),
"osuser": self.get_hosting_package().osuser.username,
}
)
return context
def get_success_url(self):
return reverse(
'list_ssh_keys', kwargs={'package': self.get_hosting_package().id}
"list_ssh_keys", kwargs={"package": self.get_hosting_package().id}
)