Fixed errors with systemuser form and serializer
This commit is contained in:
parent
b93be150c2
commit
a0b531ed68
|
@ -17,6 +17,7 @@ from orchestra.forms import UserCreationForm, UserChangeForm
|
|||
from . import settings
|
||||
from .actions import grant_permission
|
||||
from .filters import IsMainListFilter
|
||||
from .forms import SystemUserCreationForm, SystemUserChangeForm
|
||||
from .models import SystemUser
|
||||
|
||||
|
||||
|
@ -46,8 +47,8 @@ class SystemUserAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, Extende
|
|||
change_readonly_fields = ('username',)
|
||||
filter_horizontal = ('groups',)
|
||||
filter_by_account_fields = ('groups',)
|
||||
add_form = UserCreationForm
|
||||
form = UserChangeForm
|
||||
add_form = SystemUserCreationForm
|
||||
form = SystemUserChangeForm
|
||||
ordering = ('-id',)
|
||||
actions = (grant_permission,)
|
||||
change_view_actions = actions
|
||||
|
@ -70,49 +71,13 @@ class SystemUserAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, Extende
|
|||
|
||||
def get_form(self, request, obj=None, **kwargs):
|
||||
form = super(SystemUserAdmin, self).get_form(request, obj=obj, **kwargs)
|
||||
duplicate = lambda n: (n, n)
|
||||
form.account = self.account
|
||||
if obj:
|
||||
# Has to be done here and not in the form because of strange phenomenon
|
||||
# derived from monkeypatching formfield.widget.render on AccountAdminMinxin,
|
||||
# don't ask.
|
||||
formfield = form.base_fields['groups']
|
||||
formfield.queryset = formfield.queryset.exclude(id=obj.id)
|
||||
username = obj.username
|
||||
choices=(
|
||||
duplicate(self.account.main_systemuser.get_home()),
|
||||
duplicate(obj.get_home()),
|
||||
)
|
||||
else:
|
||||
username = '<username>'
|
||||
choices=(
|
||||
duplicate(self.account.main_systemuser.get_home()),
|
||||
duplicate(SystemUser(username=username).get_home()),
|
||||
)
|
||||
form.base_fields['home'].widget = forms.Select(choices=choices)
|
||||
if obj and (obj.is_main or obj.has_shell):
|
||||
# hidde home option for shell users
|
||||
form.base_fields['home'].widget = forms.HiddenInput()
|
||||
form.base_fields['directory'].widget = forms.HiddenInput()
|
||||
else:
|
||||
# Some javascript for hidde home/directory inputs when convinient
|
||||
form.base_fields['shell'].widget.attrs = {
|
||||
'onChange': textwrap.dedent("""\
|
||||
field = $(".form-row.field-home.field-directory");
|
||||
if ($.inArray(this.value, %s) < 0) {
|
||||
field.addClass("hidden");
|
||||
} else {
|
||||
field.removeClass("hidden");
|
||||
};""" % str(list(settings.SYSTEMUSERS_DISABLED_SHELLS)))
|
||||
}
|
||||
form.base_fields['home'].widget.attrs = {
|
||||
'onChange': textwrap.dedent("""\
|
||||
field = $(".field-box.field-directory");
|
||||
if (this.value.search("%s") > 0) {
|
||||
field.addClass("hidden");
|
||||
} else {
|
||||
field.removeClass("hidden");
|
||||
};""" % username)
|
||||
}
|
||||
return form
|
||||
|
||||
def has_delete_permission(self, request, obj=None):
|
||||
|
|
72
orchestra/apps/systemusers/forms.py
Normal file
72
orchestra/apps/systemusers/forms.py
Normal file
|
@ -0,0 +1,72 @@
|
|||
import textwrap
|
||||
|
||||
from django import forms
|
||||
|
||||
from orchestra.forms import UserCreationForm, UserChangeForm
|
||||
|
||||
from . import settings
|
||||
from .models import SystemUser
|
||||
|
||||
class SystemUserFormMixin(object):
|
||||
MOCK_USERNAME = '<username>'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SystemUserFormMixin, self).__init__(*args, **kwargs)
|
||||
duplicate = lambda n: (n, n)
|
||||
if self.instance.pk:
|
||||
username = self.instance.username
|
||||
choices=(
|
||||
duplicate(self.account.main_systemuser.get_base_home()),
|
||||
duplicate(self.instance.get_base_home()),
|
||||
)
|
||||
else:
|
||||
username = self.MOCK_USERNAME
|
||||
choices=(
|
||||
duplicate(self.account.main_systemuser.get_base_home()),
|
||||
duplicate(SystemUser(username=username).get_base_home()),
|
||||
)
|
||||
self.fields['home'].widget = forms.Select(choices=choices)
|
||||
if self.instance.pk and (self.instance.is_main or self.instance.has_shell):
|
||||
# hidde home option for shell users
|
||||
self.fields['home'].widget = forms.HiddenInput()
|
||||
self.fields['directory'].widget = forms.HiddenInput()
|
||||
elif self.instance.pk and (self.instance.get_base_home() == self.instance.home):
|
||||
self.fields['directory'].widget = forms.HiddenInput()
|
||||
if self.instance.pk and not self.instance.is_main:
|
||||
# Some javascript for hidde home/directory inputs when convinient
|
||||
self.fields['shell'].widget.attrs = {
|
||||
'onChange': textwrap.dedent("""\
|
||||
field = $(".field-home, .field-directory");
|
||||
input = $("#id_home, #id_directory");
|
||||
if ($.inArray(this.value, %s) < 0) {
|
||||
field.addClass("hidden");
|
||||
} else {
|
||||
field.removeClass("hidden");
|
||||
input.removeAttr("type");
|
||||
};""" % str(list(settings.SYSTEMUSERS_DISABLED_SHELLS)))
|
||||
}
|
||||
self.fields['home'].widget.attrs = {
|
||||
'onChange': textwrap.dedent("""\
|
||||
field = $(".field-box.field-directory");
|
||||
input = $("#id_directory");
|
||||
if (this.value.search("%s") > 0) {
|
||||
field.addClass("hidden");
|
||||
} else {
|
||||
field.removeClass("hidden");
|
||||
input.removeAttr("type");
|
||||
};""" % username)
|
||||
}
|
||||
|
||||
def clean(self):
|
||||
home = self.cleaned_data.get('home')
|
||||
if home and self.MOCK_USERNAME in home:
|
||||
username = self.cleaned_data.get('username', '')
|
||||
self.cleaned_data['home'] = home.replace(self.MOCK_USERNAME, username)
|
||||
|
||||
|
||||
class SystemUserCreationForm(SystemUserFormMixin, UserCreationForm):
|
||||
pass
|
||||
|
||||
|
||||
class SystemUserChangeForm(SystemUserFormMixin, UserChangeForm):
|
||||
pass
|
|
@ -2,6 +2,7 @@ import os
|
|||
|
||||
from django.contrib.auth.hashers import make_password
|
||||
from django.core import validators
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.mail import send_mail
|
||||
from django.db import models
|
||||
from django.utils.functional import cached_property
|
||||
|
@ -30,7 +31,7 @@ class SystemUser(models.Model):
|
|||
password = models.CharField(_("password"), max_length=128)
|
||||
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"),
|
||||
related_name='systemusers')
|
||||
home = models.CharField(_("home"), max_length=256, blank=False,
|
||||
home = models.CharField(_("home"), max_length=256, blank=True,
|
||||
help_text=_("Starting location when login with this no-shell user."))
|
||||
directory = models.CharField(_("directory"), max_length=256, blank=True,
|
||||
help_text=_("Optional directory relative to user's home."))
|
||||
|
@ -68,10 +69,26 @@ class SystemUser(models.Model):
|
|||
def has_shell(self):
|
||||
return self.shell not in settings.SYSTEMUSERS_DISABLED_SHELLS
|
||||
|
||||
def clean(self):
|
||||
if self.has_shell or self.is_main:
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.home:
|
||||
self.home = self.get_base_home()
|
||||
self.directory = ''
|
||||
super(SystemUser, self).save(*args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
# TODO do it right
|
||||
if self.has_shell and self.directory:
|
||||
raise ValidationError({
|
||||
'directory': _("Directory with shell users can not be specified.")
|
||||
})
|
||||
if self.pk and self.is_main and self.directory:
|
||||
raise ValidationError({
|
||||
'directory': _("Directory with main system users can not be specified.")
|
||||
})
|
||||
if self.home == self.get_base_home() and self.directory:
|
||||
raise ValidationError({
|
||||
'directory': _("Directory on the user's base home is not allowed.")
|
||||
})
|
||||
# TODO valid home exists
|
||||
|
||||
def set_password(self, raw_password):
|
||||
self.password = make_password(raw_password)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.contrib.auth import get_user_model
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms import widgets
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
@ -34,6 +35,24 @@ class SystemUserSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
|
|||
)
|
||||
postonly_fields = ('username',)
|
||||
|
||||
def validate(self, attrs):
|
||||
user = SystemUser(
|
||||
username=attrs.get('username') or self.object.username,
|
||||
shell=attrs.get('shell') or self.object.shell,
|
||||
)
|
||||
if 'home' in attrs and attrs['home']:
|
||||
home = attrs['home'].rstrip('/') + '/'
|
||||
if user.has_shell:
|
||||
if home != user.get_base_home():
|
||||
raise ValidationError({
|
||||
'home': _("Not a valid home directory.")
|
||||
})
|
||||
elif home not in (user.get_home(), self.account.main_systemuser.get_home()):
|
||||
raise ValidationError({
|
||||
'home': _("Not a valid home directory.")
|
||||
})
|
||||
return attrs
|
||||
|
||||
def validate_password(self, attrs, source):
|
||||
""" POST only password """
|
||||
if self.object:
|
||||
|
|
Loading…
Reference in a new issue