2016-08-14 11:18:41 +00:00
|
|
|
# ~*~ coding: utf-8 ~*~
|
|
|
|
|
2016-08-16 14:13:06 +00:00
|
|
|
from django import forms
|
2016-09-05 13:38:21 +00:00
|
|
|
from django.contrib.auth.forms import AuthenticationForm
|
2016-09-03 16:51:36 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2016-09-05 13:38:21 +00:00
|
|
|
from captcha.fields import CaptchaField
|
|
|
|
|
2016-11-09 15:49:10 +00:00
|
|
|
from common.utils import validate_ssh_public_key
|
2018-07-14 16:55:05 +00:00
|
|
|
from orgs.mixins import OrgModelForm
|
2018-07-20 09:49:47 +00:00
|
|
|
from orgs.utils import current_org
|
2016-08-21 14:37:55 +00:00
|
|
|
from .models import User, UserGroup
|
2016-08-14 11:18:41 +00:00
|
|
|
|
|
|
|
|
2016-09-05 13:38:21 +00:00
|
|
|
class UserLoginForm(AuthenticationForm):
|
2018-04-24 05:00:36 +00:00
|
|
|
username = forms.CharField(label=_('Username'), max_length=100)
|
|
|
|
password = forms.CharField(
|
|
|
|
label=_('Password'), widget=forms.PasswordInput,
|
|
|
|
max_length=128, strip=False
|
|
|
|
)
|
|
|
|
|
2018-06-08 08:34:15 +00:00
|
|
|
def confirm_login_allowed(self, user):
|
|
|
|
if not user.is_staff:
|
|
|
|
raise forms.ValidationError(
|
|
|
|
self.error_messages['inactive'],
|
|
|
|
code='inactive',)
|
2018-04-24 05:00:36 +00:00
|
|
|
|
2018-06-08 08:34:15 +00:00
|
|
|
|
|
|
|
class UserLoginCaptchaForm(UserLoginForm):
|
2016-09-03 06:37:01 +00:00
|
|
|
captcha = CaptchaField()
|
2016-08-25 11:29:59 +00:00
|
|
|
|
|
|
|
|
2018-04-18 04:48:07 +00:00
|
|
|
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):
|
2018-04-20 08:15:45 +00:00
|
|
|
otp_code = forms.CharField(label=_('MFA code'), max_length=6)
|
2018-04-18 04:48:07 +00:00
|
|
|
|
|
|
|
|
2018-07-14 16:55:05 +00:00
|
|
|
class UserCreateUpdateForm(OrgModelForm):
|
2018-03-11 11:46:40 +00:00
|
|
|
role_choices = ((i, n) for i, n in User.ROLE_CHOICES if i != User.ROLE_APP)
|
2017-12-18 10:38:30 +00:00
|
|
|
password = forms.CharField(
|
|
|
|
label=_('Password'), widget=forms.PasswordInput,
|
|
|
|
max_length=128, strip=False, required=False,
|
|
|
|
)
|
2018-04-23 13:04:46 +00:00
|
|
|
role = forms.ChoiceField(
|
|
|
|
choices=role_choices, required=True,
|
|
|
|
initial=User.ROLE_USER, label=_("Role")
|
|
|
|
)
|
2018-03-21 07:22:10 +00:00
|
|
|
public_key = forms.CharField(
|
2018-03-27 09:47:53 +00:00
|
|
|
label=_('ssh public key'), max_length=5000, required=False,
|
2018-03-21 07:22:10 +00:00
|
|
|
widget=forms.Textarea(attrs={'placeholder': _('ssh-rsa AAAA...')}),
|
|
|
|
help_text=_('Paste user id_rsa.pub here.')
|
|
|
|
)
|
2017-12-18 10:38:30 +00:00
|
|
|
|
2016-08-14 11:18:41 +00:00
|
|
|
class Meta:
|
|
|
|
model = User
|
|
|
|
fields = [
|
2016-08-17 14:17:16 +00:00
|
|
|
'username', 'name', 'email', 'groups', 'wechat',
|
2018-04-20 08:15:45 +00:00
|
|
|
'phone', 'role', 'date_expired', 'comment', 'otp_level'
|
2016-08-14 11:18:41 +00:00
|
|
|
]
|
2016-08-19 16:42:50 +00:00
|
|
|
help_texts = {
|
|
|
|
'username': '* required',
|
2016-10-31 11:31:56 +00:00
|
|
|
'name': '* required',
|
2016-08-19 16:42:50 +00:00
|
|
|
'email': '* required',
|
|
|
|
}
|
|
|
|
widgets = {
|
2018-06-05 09:26:31 +00:00
|
|
|
'otp_level': forms.RadioSelect(),
|
2018-07-14 16:55:05 +00:00
|
|
|
'groups': forms.SelectMultiple(
|
|
|
|
attrs={
|
|
|
|
'class': 'select2',
|
|
|
|
'data-placeholder': _('Join user groups')
|
|
|
|
}
|
|
|
|
)
|
2016-08-19 16:42:50 +00:00
|
|
|
}
|
2016-08-16 14:13:06 +00:00
|
|
|
|
2018-08-01 02:44:43 +00:00
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
self.request = kwargs.pop("request", None)
|
|
|
|
super(UserCreateUpdateForm, 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)))
|
|
|
|
|
|
|
|
# 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)
|
|
|
|
|
2018-03-21 07:22:10 +00:00
|
|
|
def clean_public_key(self):
|
|
|
|
public_key = self.cleaned_data['public_key']
|
2018-03-27 09:47:53 +00:00
|
|
|
if not public_key:
|
|
|
|
return public_key
|
2018-03-21 07:22:10 +00:00
|
|
|
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
|
|
|
|
|
2017-12-18 10:38:30 +00:00
|
|
|
def save(self, commit=True):
|
2018-01-10 07:15:29 +00:00
|
|
|
password = self.cleaned_data.get('password')
|
2018-04-20 08:15:45 +00:00
|
|
|
otp_level = self.cleaned_data.get('otp_level')
|
2018-03-21 07:22:10 +00:00
|
|
|
public_key = self.cleaned_data.get('public_key')
|
2017-12-18 10:38:30 +00:00
|
|
|
user = super().save(commit=commit)
|
|
|
|
if password:
|
|
|
|
user.set_password(password)
|
|
|
|
user.save()
|
2018-04-20 08:15:45 +00:00
|
|
|
if otp_level:
|
|
|
|
user.otp_level = otp_level
|
|
|
|
user.save()
|
2018-03-21 07:22:10 +00:00
|
|
|
if public_key:
|
|
|
|
user.public_key = public_key
|
|
|
|
user.save()
|
2017-12-18 10:38:30 +00:00
|
|
|
return user
|
|
|
|
|
2016-08-16 14:13:06 +00:00
|
|
|
|
2017-03-29 16:51:36 +00:00
|
|
|
class UserProfileForm(forms.ModelForm):
|
|
|
|
class Meta:
|
|
|
|
model = User
|
|
|
|
fields = [
|
2017-03-30 08:28:00 +00:00
|
|
|
'username', 'name', 'email',
|
|
|
|
'wechat', 'phone',
|
2017-03-29 16:51:36 +00:00
|
|
|
]
|
|
|
|
help_texts = {
|
|
|
|
'username': '* required',
|
|
|
|
'name': '* required',
|
|
|
|
'email': '* required',
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-21 07:22:10 +00:00
|
|
|
UserProfileForm.verbose_name = _("Profile")
|
|
|
|
|
|
|
|
|
2018-04-23 13:04:46 +00:00
|
|
|
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")
|
|
|
|
|
|
|
|
|
2017-03-30 08:28:00 +00:00
|
|
|
class UserPasswordForm(forms.Form):
|
|
|
|
old_password = forms.CharField(
|
2017-12-21 03:31:13 +00:00
|
|
|
max_length=128, widget=forms.PasswordInput,
|
|
|
|
label=_("Old password")
|
|
|
|
)
|
2017-03-30 08:28:00 +00:00
|
|
|
new_password = forms.CharField(
|
2017-12-21 03:31:13 +00:00
|
|
|
min_length=5, max_length=128,
|
|
|
|
widget=forms.PasswordInput,
|
|
|
|
label=_("New password")
|
|
|
|
)
|
2017-03-30 08:28:00 +00:00
|
|
|
confirm_password = forms.CharField(
|
2017-12-21 03:31:13 +00:00
|
|
|
min_length=5, max_length=128,
|
|
|
|
widget=forms.PasswordInput,
|
|
|
|
label=_("Confirm password")
|
|
|
|
)
|
2017-03-30 08:28:00 +00:00
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
self.instance = kwargs.pop('instance')
|
2017-12-21 03:31:13 +00:00
|
|
|
super().__init__(*args, **kwargs)
|
2017-03-30 08:28:00 +00:00
|
|
|
|
|
|
|
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.set_password(password)
|
|
|
|
self.instance.save()
|
|
|
|
return self.instance
|
|
|
|
|
|
|
|
|
|
|
|
class UserPublicKeyForm(forms.Form):
|
2018-04-23 13:04:46 +00:00
|
|
|
pubkey_description = _('Automatically configure and download the SSH key')
|
2017-03-30 08:28:00 +00:00
|
|
|
public_key = forms.CharField(
|
2018-03-21 07:22:10 +00:00
|
|
|
label=_('ssh public key'), max_length=5000, required=False,
|
2017-03-30 08:28:00 +00:00
|
|
|
widget=forms.Textarea(attrs={'placeholder': _('ssh-rsa AAAA...')}),
|
2017-12-21 03:31:13 +00:00
|
|
|
help_text=_('Paste your id_rsa.pub here.')
|
|
|
|
)
|
2017-03-30 08:28:00 +00:00
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
2017-03-31 15:46:00 +00:00
|
|
|
if 'instance' in kwargs:
|
|
|
|
self.instance = kwargs.pop('instance')
|
|
|
|
else:
|
|
|
|
self.instance = None
|
2017-12-21 03:31:13 +00:00
|
|
|
super().__init__(*args, **kwargs)
|
2017-03-30 08:28:00 +00:00
|
|
|
|
|
|
|
def clean_public_key(self):
|
|
|
|
public_key = self.cleaned_data['public_key']
|
|
|
|
if self.instance.public_key and public_key == self.instance.public_key:
|
2017-12-21 03:31:13 +00:00
|
|
|
msg = _('Public key should not be the same as your old one.')
|
|
|
|
raise forms.ValidationError(msg)
|
2017-03-30 08:28:00 +00:00
|
|
|
|
2018-03-21 07:22:10 +00:00
|
|
|
if public_key and not validate_ssh_public_key(public_key):
|
2017-03-30 08:28:00 +00:00
|
|
|
raise forms.ValidationError(_('Not a valid ssh public key'))
|
|
|
|
return public_key
|
|
|
|
|
|
|
|
def save(self):
|
|
|
|
public_key = self.cleaned_data['public_key']
|
2018-03-21 07:22:10 +00:00
|
|
|
if public_key:
|
|
|
|
self.instance.public_key = public_key
|
|
|
|
self.instance.save()
|
2017-03-30 08:28:00 +00:00
|
|
|
return self.instance
|
|
|
|
|
|
|
|
|
2018-03-21 07:22:10 +00:00
|
|
|
UserPublicKeyForm.verbose_name = _("Public key")
|
|
|
|
|
|
|
|
|
2017-04-10 14:55:15 +00:00
|
|
|
class UserBulkUpdateForm(forms.ModelForm):
|
2017-12-21 03:31:13 +00:00
|
|
|
users = forms.ModelMultipleChoiceField(
|
2017-04-12 03:50:15 +00:00
|
|
|
required=True,
|
|
|
|
help_text='* required',
|
|
|
|
label=_('Select users'),
|
2018-07-14 16:55:05 +00:00
|
|
|
queryset = User.objects.all(),
|
2017-04-12 03:50:15 +00:00
|
|
|
widget=forms.SelectMultiple(
|
|
|
|
attrs={
|
|
|
|
'class': 'select2',
|
|
|
|
'data-placeholder': _('Select users')
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2016-10-01 12:26:43 +00:00
|
|
|
class Meta:
|
|
|
|
model = User
|
2018-01-10 09:38:10 +00:00
|
|
|
fields = ['users', 'role', 'groups', 'date_expired']
|
2017-04-12 03:50:15 +00:00
|
|
|
widgets = {
|
2017-12-18 10:38:30 +00:00
|
|
|
"groups": forms.SelectMultiple(
|
|
|
|
attrs={
|
|
|
|
'class': 'select2',
|
|
|
|
'data-placeholder': _('Select users')
|
|
|
|
}
|
|
|
|
)
|
2017-04-12 03:50:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
def save(self, commit=True):
|
2017-12-18 10:38:30 +00:00
|
|
|
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}
|
2017-12-21 03:31:13 +00:00
|
|
|
users = cleaned_data.pop('users', '')
|
2017-12-18 10:38:30 +00:00
|
|
|
groups = cleaned_data.pop('groups', [])
|
2017-12-21 03:31:13 +00:00
|
|
|
users = User.objects.filter(id__in=[user.id for user in users])
|
2017-04-12 03:50:15 +00:00
|
|
|
users.update(**cleaned_data)
|
|
|
|
if groups:
|
|
|
|
for user in users:
|
|
|
|
user.groups.set(groups)
|
|
|
|
return users
|
2016-10-01 12:26:43 +00:00
|
|
|
|
|
|
|
|
2018-07-14 16:55:05 +00:00
|
|
|
def user_limit_to():
|
2018-07-20 09:49:47 +00:00
|
|
|
return {"orgs": current_org}
|
2018-07-14 16:55:05 +00:00
|
|
|
|
|
|
|
|
2016-09-05 13:38:21 +00:00
|
|
|
class UserGroupForm(forms.ModelForm):
|
2017-12-18 10:38:30 +00:00
|
|
|
users = forms.ModelMultipleChoiceField(
|
2018-01-10 09:38:10 +00:00
|
|
|
queryset=User.objects.exclude(role=User.ROLE_APP),
|
2018-01-08 03:22:19 +00:00
|
|
|
label=_("User"),
|
2017-12-18 10:38:30 +00:00
|
|
|
widget=forms.SelectMultiple(
|
|
|
|
attrs={
|
|
|
|
'class': 'select2',
|
|
|
|
'data-placeholder': _('Select users')
|
|
|
|
}
|
2018-01-08 03:22:19 +00:00
|
|
|
),
|
|
|
|
required=False,
|
2018-07-14 16:55:05 +00:00
|
|
|
limit_choices_to=user_limit_to
|
2017-12-18 10:38:30 +00:00
|
|
|
)
|
2016-09-08 13:51:44 +00:00
|
|
|
|
2017-12-18 10:38:30 +00:00
|
|
|
def __init__(self, **kwargs):
|
|
|
|
instance = kwargs.get('instance')
|
|
|
|
if instance:
|
|
|
|
initial = kwargs.get('initial', {})
|
2018-07-20 05:25:50 +00:00
|
|
|
initial.update({'users': instance.users.all()})
|
2017-12-18 10:38:30 +00:00
|
|
|
kwargs['initial'] = initial
|
|
|
|
super().__init__(**kwargs)
|
2018-07-18 04:57:08 +00:00
|
|
|
if 'initial' not in kwargs:
|
|
|
|
return
|
|
|
|
users_field = self.fields.get('users')
|
|
|
|
if hasattr(users_field, 'queryset'):
|
2018-07-20 05:25:50 +00:00
|
|
|
users_field.queryset = current_org.get_org_users()
|
2016-09-08 13:51:44 +00:00
|
|
|
|
2016-09-16 17:04:52 +00:00
|
|
|
def save(self, commit=True):
|
2017-12-18 10:38:30 +00:00
|
|
|
group = super().save(commit=commit)
|
|
|
|
users = self.cleaned_data['users']
|
|
|
|
group.users.set(users)
|
|
|
|
return group
|
2016-09-16 17:04:52 +00:00
|
|
|
|
|
|
|
class Meta:
|
2017-12-18 10:38:30 +00:00
|
|
|
model = UserGroup
|
2016-09-16 17:04:52 +00:00
|
|
|
fields = [
|
2017-12-18 10:38:30 +00:00
|
|
|
'name', 'users', 'comment'
|
2016-09-16 17:04:52 +00:00
|
|
|
]
|
2017-12-18 10:38:30 +00:00
|
|
|
help_texts = {
|
|
|
|
'name': '* required'
|
2016-09-16 17:04:52 +00:00
|
|
|
}
|
2016-11-09 15:49:10 +00:00
|
|
|
|
|
|
|
|
2018-07-14 16:55:05 +00:00
|
|
|
class OrgUserField(forms.ModelMultipleChoiceField):
|
|
|
|
|
|
|
|
def get_limit_choices_to(self):
|
|
|
|
|
|
|
|
return {"orgs"}
|
|
|
|
|
2016-11-15 11:33:04 +00:00
|
|
|
|
2016-11-09 15:49:10 +00:00
|
|
|
class FileForm(forms.Form):
|
2016-11-24 07:45:08 +00:00
|
|
|
file = forms.FileField()
|