django-orchestra/orchestra/contrib/systemusers/forms.py

190 lines
7.4 KiB
Python
Raw Normal View History

2015-05-13 12:16:51 +00:00
import os
import textwrap
from django import forms
2015-05-11 14:05:39 +00:00
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from orchestra.forms import UserCreationForm, UserChangeForm
2023-08-01 14:41:03 +00:00
from orchestra.settings import NEW_SERVERS
from . import settings
from .models import SystemUser
2016-02-09 12:17:42 +00:00
from .validators import validate_home, validate_paths_exist
2015-03-04 21:06:16 +00:00
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
2015-05-13 13:52:20 +00:00
self.fields['home'].widget.input_type = 'hidden'
self.fields['directory'].widget.input_type = 'hidden'
elif self.instance.pk and (self.instance.get_base_home() == self.instance.home):
self.fields['directory'].widget = forms.HiddenInput()
else:
self.fields['directory'].widget = forms.TextInput(attrs={'size':'70'})
if not self.instance.pk or not self.instance.is_main:
# Some javascript for hidde home/directory inputs when convinient
2015-05-13 13:52:20 +00:00
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");
2015-10-05 13:31:08 +00:00
};""" % list(settings.SYSTEMUSERS_DISABLED_SHELLS)
2015-05-13 13:52:20 +00:00
)
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
)
2015-07-29 09:05:07 +00:00
def clean_directory(self):
directory = self.cleaned_data['directory']
return directory.lstrip('/')
def clean(self):
2015-04-09 14:32:10 +00:00
super(SystemUserFormMixin, self).clean()
2015-05-12 12:38:40 +00:00
cleaned_data = self.cleaned_data
home = cleaned_data.get('home')
2015-05-13 13:52:20 +00:00
shell = cleaned_data.get('shell')
if home and self.MOCK_USERNAME in home:
2015-05-12 12:38:40 +00:00
username = cleaned_data.get('username', '')
cleaned_data['home'] = home.replace(self.MOCK_USERNAME, username)
2015-05-13 13:52:20 +00:00
elif home and shell not in settings.SYSTEMUSERS_DISABLED_SHELLS:
cleaned_data['home'] = ''
cleaned_data['directory'] = ''
2015-05-12 12:38:40 +00:00
validate_home(self.instance, cleaned_data, self.account)
return cleaned_data
class SystemUserCreationForm(SystemUserFormMixin, UserCreationForm):
pass
class SystemUserChangeForm(SystemUserFormMixin, UserChangeForm):
pass
2016-02-09 12:17:42 +00:00
class LinkForm(forms.Form):
base_home = forms.ChoiceField(label=_("Target path"), choices=(),
help_text=_("Target link will be under this directory."))
2015-05-11 14:05:39 +00:00
home_extension = forms.CharField(label=_("Home extension"), required=False, initial='',
2016-02-10 12:07:55 +00:00
widget=forms.TextInput(attrs={'size':'70'}),
help_text=_("Relative path to chosen directory."))
2016-02-09 12:17:42 +00:00
link_name = forms.CharField(label=_("Link name"), required=False, initial='',
2016-06-17 10:00:04 +00:00
widget=forms.TextInput(attrs={'size':'70'}))
def __init__(self, *args, **kwargs):
2015-05-11 14:05:39 +00:00
self.instance = args[0]
2016-02-09 12:17:42 +00:00
self.queryset = kwargs.pop('queryset', [])
super_args = []
if len(args) > 1:
super_args.append(args[1])
2016-02-09 12:17:42 +00:00
super(LinkForm, self).__init__(*super_args, **kwargs)
2015-05-11 14:05:39 +00:00
related_users = type(self.instance).objects.filter(account=self.instance.account_id)
self.fields['base_home'].choices = (
(user.get_base_home(), user.get_base_home()) for user in related_users
)
2016-06-17 10:00:04 +00:00
if len(self.queryset) == 1:
user = self.instance
help_text = _("If left blank or relative path: the link will be created in %s home.") % user
else:
help_text = _("If left blank or relative path: the link will be created in each user home.")
self.fields['link_name'].help_text = help_text
2015-05-11 14:05:39 +00:00
2015-07-29 09:05:07 +00:00
def clean_home_extension(self):
home_extension = self.cleaned_data['home_extension']
return home_extension.lstrip('/')
2016-02-09 12:17:42 +00:00
def clean_link_name(self):
link_name = self.cleaned_data['link_name']
if link_name:
if link_name.startswith('/'):
if len(self.queryset) > 1:
2016-02-10 12:07:55 +00:00
raise ValidationError(
_("Link name can not be a full path when multiple users."))
2016-02-09 12:17:42 +00:00
link_names = [os.path.dirname(link_name)]
else:
2016-02-10 12:07:55 +00:00
dir_name = os.path.dirname(link_name)
link_names = [os.path.join(user.home, dir_name) for user in self.queryset]
2016-02-09 12:17:42 +00:00
validate_paths_exist(self.instance, link_names)
return link_name
2015-05-11 14:05:39 +00:00
def clean(self):
2016-02-09 12:17:42 +00:00
cleaned_data = super(LinkForm, self).clean()
2015-05-12 12:38:40 +00:00
path = os.path.join(cleaned_data['base_home'], cleaned_data['home_extension'])
try:
2016-02-09 12:17:42 +00:00
validate_paths_exist(self.instance, [path])
2015-05-12 12:38:40 +00:00
except ValidationError as err:
2015-05-11 14:05:39 +00:00
raise ValidationError({
2015-05-12 12:38:40 +00:00
'home_extension': err,
2015-05-11 14:05:39 +00:00
})
return cleaned_data
2016-02-09 12:17:42 +00:00
class PermissionForm(LinkForm):
set_action = forms.ChoiceField(label=_("Action"), initial='grant',
choices=(
('grant', _("Grant")),
('revoke', _("Revoke"))
))
base_home = forms.ChoiceField(label=_("Set permissions to"), choices=(),
help_text=_("User will be granted/revoked access to this directory."))
home_extension = forms.CharField(label=_("Home extension"), required=False, initial='',
widget=forms.TextInput(attrs={'size':'70'}), help_text=_("Relative to chosen home."))
permissions = forms.ChoiceField(label=_("Permissions"), initial='read-write',
choices=(
('rw', _("Read and write")),
('r', _("Read only")),
('w', _("Write only"))
))
# ----------------------------
class WebappUserFormMixin(object):
def __init__(self, *args, **kwargs):
super(WebappUserFormMixin, self).__init__(*args, **kwargs)
def clean(self):
if not self.instance.pk:
server = self.cleaned_data.get('target_server')
if server:
2023-08-01 14:41:03 +00:00
if server.name not in NEW_SERVERS:
self.add_error("target_server", _(f"{server} does not belong to the new servers"))
return self.cleaned_data
class WebappUserCreationForm(WebappUserFormMixin, UserCreationForm):
pass
class WebappUserChangeForm(WebappUserFormMixin, UserChangeForm):
pass