jumpserver/apps/users/forms.py

340 lines
10 KiB
Python

# ~*~ coding: utf-8 ~*~
from django import forms
from django.utils.translation import gettext_lazy as _
from common.utils import validate_ssh_public_key
from orgs.mixins import OrgModelForm
from orgs.utils import current_org
from .models import User, UserGroup
class UserCheckPasswordForm(forms.Form):
username = forms.CharField(label=_('Username'), max_length=100)
password = forms.CharField(
label=_('Password'), widget=forms.PasswordInput,
max_length=128, strip=False
)
class UserCheckOtpCodeForm(forms.Form):
otp_code = forms.CharField(label=_('MFA code'), max_length=6)
class UserCreateUpdateFormMixin(OrgModelForm):
role_choices = ((i, n) for i, n in User.ROLE_CHOICES if i != User.ROLE_APP)
password = forms.CharField(
label=_('Password'), widget=forms.PasswordInput,
max_length=128, strip=False, required=False,
)
role = forms.ChoiceField(
choices=role_choices, required=True,
initial=User.ROLE_USER, label=_("Role")
)
public_key = forms.CharField(
label=_('ssh public key'), max_length=5000, required=False,
widget=forms.Textarea(attrs={'placeholder': _('ssh-rsa AAAA...')}),
help_text=_('Paste user id_rsa.pub here.')
)
class Meta:
model = User
fields = [
'username', 'name', 'email', 'groups', 'wechat',
'phone', 'role', 'date_expired', 'comment', 'otp_level'
]
widgets = {
'otp_level': forms.RadioSelect(),
'groups': forms.SelectMultiple(
attrs={
'class': 'select2',
'data-placeholder': _('Join user groups')
}
)
}
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
super(UserCreateUpdateFormMixin, self).__init__(*args, **kwargs)
roles = []
# Super admin user
if self.request.user.is_superuser:
roles.append((User.ROLE_ADMIN, dict(User.ROLE_CHOICES).get(User.ROLE_ADMIN)))
roles.append((User.ROLE_USER, dict(User.ROLE_CHOICES).get(User.ROLE_USER)))
roles.append((User.ROLE_AUDITOR, dict(User.ROLE_CHOICES).get(User.ROLE_AUDITOR)))
# Org admin user
else:
user = kwargs.get('instance')
# Update
if user:
role = kwargs.get('instance').role
roles.append((role, dict(User.ROLE_CHOICES).get(role)))
# Create
else:
roles.append((User.ROLE_USER, dict(User.ROLE_CHOICES).get(User.ROLE_USER)))
field = self.fields['role']
field.choices = set(roles)
def clean_public_key(self):
public_key = self.cleaned_data['public_key']
if not public_key:
return public_key
if self.instance.public_key and public_key == self.instance.public_key:
msg = _('Public key should not be the same as your old one.')
raise forms.ValidationError(msg)
if not validate_ssh_public_key(public_key):
raise forms.ValidationError(_('Not a valid ssh public key'))
return public_key
def save(self, commit=True):
password = self.cleaned_data.get('password')
otp_level = self.cleaned_data.get('otp_level')
public_key = self.cleaned_data.get('public_key')
user = super().save(commit=commit)
if password:
user.reset_password(password)
if otp_level:
user.otp_level = otp_level
user.save()
if public_key:
user.public_key = public_key
user.save()
return user
class UserCreateForm(UserCreateUpdateFormMixin):
EMAIL_SET_PASSWORD = _('Reset link will be generated and sent to the user')
CUSTOM_PASSWORD = _('Set password')
PASSWORD_STRATEGY_CHOICES = (
(0, EMAIL_SET_PASSWORD),
(1, CUSTOM_PASSWORD)
)
password_strategy = forms.ChoiceField(
choices=PASSWORD_STRATEGY_CHOICES, required=True, initial=0,
widget=forms.RadioSelect(), label=_('Password strategy')
)
class UserUpdateForm(UserCreateUpdateFormMixin):
pass
class UserProfileForm(forms.ModelForm):
username = forms.CharField(disabled=True)
name = forms.CharField(disabled=True)
email = forms.CharField(disabled=True)
class Meta:
model = User
fields = [
'username', 'name', 'email',
'wechat', 'phone',
]
UserProfileForm.verbose_name = _("Profile")
class UserMFAForm(forms.ModelForm):
mfa_description = _(
'Tip: when enabled, '
'you will enter the MFA binding process the next time you log in. '
'you can also directly bind in '
'"personal information -> quick modification -> change MFA Settings"!')
class Meta:
model = User
fields = ['otp_level']
widgets = {'otp_level': forms.RadioSelect()}
help_texts = {
'otp_level': _('* Enable MFA authentication '
'to make the account more secure.'),
}
UserMFAForm.verbose_name = _("MFA")
class UserFirstLoginFinishForm(forms.Form):
finish_description = _(
'In order to protect you and your company, '
'please keep your account, '
'password and key sensitive information properly. '
'(for example: setting complex password, enabling MFA authentication)'
)
UserFirstLoginFinishForm.verbose_name = _("Finish")
class UserPasswordForm(forms.Form):
old_password = forms.CharField(
max_length=128, widget=forms.PasswordInput,
label=_("Old password")
)
new_password = forms.CharField(
min_length=5, max_length=128,
widget=forms.PasswordInput,
label=_("New password")
)
confirm_password = forms.CharField(
min_length=5, max_length=128,
widget=forms.PasswordInput,
label=_("Confirm password")
)
def __init__(self, *args, **kwargs):
self.instance = kwargs.pop('instance')
super().__init__(*args, **kwargs)
def clean_old_password(self):
old_password = self.cleaned_data['old_password']
if not self.instance.check_password(old_password):
raise forms.ValidationError(_('Old password error'))
return old_password
def clean_confirm_password(self):
new_password = self.cleaned_data['new_password']
confirm_password = self.cleaned_data['confirm_password']
if new_password != confirm_password:
raise forms.ValidationError(_('Password does not match'))
return confirm_password
def save(self):
password = self.cleaned_data['new_password']
self.instance.reset_password(new_password=password)
return self.instance
class UserPublicKeyForm(forms.Form):
pubkey_description = _('Automatically configure and download the SSH key')
public_key = forms.CharField(
label=_('ssh public key'), max_length=5000, required=False,
widget=forms.Textarea(attrs={'placeholder': _('ssh-rsa AAAA...')}),
help_text=_('Paste your id_rsa.pub here.')
)
def __init__(self, *args, **kwargs):
if 'instance' in kwargs:
self.instance = kwargs.pop('instance')
else:
self.instance = None
super().__init__(*args, **kwargs)
def clean_public_key(self):
public_key = self.cleaned_data['public_key']
if self.instance.public_key and public_key == self.instance.public_key:
msg = _('Public key should not be the same as your old one.')
raise forms.ValidationError(msg)
if public_key and not validate_ssh_public_key(public_key):
raise forms.ValidationError(_('Not a valid ssh public key'))
return public_key
def save(self):
public_key = self.cleaned_data['public_key']
if public_key:
self.instance.public_key = public_key
self.instance.save()
return self.instance
UserPublicKeyForm.verbose_name = _("Public key")
class UserBulkUpdateForm(OrgModelForm):
users = forms.ModelMultipleChoiceField(
required=True,
label=_('Select users'),
queryset=User.objects.all(),
widget=forms.SelectMultiple(
attrs={
'class': 'select2',
'data-placeholder': _('Select users')
}
)
)
class Meta:
model = User
fields = ['users', 'groups', 'date_expired']
widgets = {
"groups": forms.SelectMultiple(
attrs={
'class': 'select2',
'data-placeholder': _('User group')
}
)
}
def save(self, commit=True):
changed_fields = []
for field in self._meta.fields:
if self.data.get(field) is not None:
changed_fields.append(field)
cleaned_data = {k: v for k, v in self.cleaned_data.items()
if k in changed_fields}
users = cleaned_data.pop('users', '')
groups = cleaned_data.pop('groups', [])
users = User.objects.filter(id__in=[user.id for user in users])
users.update(**cleaned_data)
if groups:
for user in users:
user.groups.set(groups)
return users
def user_limit_to():
return {"orgs": current_org}
class UserGroupForm(OrgModelForm):
users = forms.ModelMultipleChoiceField(
queryset=User.objects.all(),
label=_("User"),
widget=forms.SelectMultiple(
attrs={
'class': 'select2',
'data-placeholder': _('Select users')
}
),
required=False,
limit_choices_to=user_limit_to
)
def __init__(self, **kwargs):
instance = kwargs.get('instance')
if instance:
initial = kwargs.get('initial', {})
initial.update({'users': instance.users.all()})
kwargs['initial'] = initial
super().__init__(**kwargs)
if 'initial' not in kwargs:
return
users_field = self.fields.get('users')
if hasattr(users_field, 'queryset'):
users_field.queryset = current_org.get_org_users()
def save(self, commit=True):
group = super().save(commit=commit)
users = self.cleaned_data['users']
group.users.set(users)
return group
class Meta:
model = UserGroup
fields = [
'name', 'users', 'comment',
]
class FileForm(forms.Form):
file = forms.FileField()