2016-08-14 11:18:41 +00:00
|
|
|
|
2016-08-16 14:13:06 +00:00
|
|
|
from django import forms
|
2016-09-03 16:51:36 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2016-09-05 13:38:21 +00:00
|
|
|
|
2016-11-09 15:49:10 +00:00
|
|
|
from common.utils import validate_ssh_public_key
|
2019-08-21 12:27:21 +00:00
|
|
|
from orgs.mixins.forms import OrgModelForm
|
2019-12-16 08:53:29 +00:00
|
|
|
from ..models import User
|
|
|
|
from ..utils import (
|
|
|
|
check_password_rules, get_current_org_members, get_source_choices
|
|
|
|
)
|
2016-08-14 11:18:41 +00:00
|
|
|
|
|
|
|
|
2019-12-16 08:53:29 +00:00
|
|
|
__all__ = [
|
|
|
|
'UserCreateForm', 'UserUpdateForm', 'UserBulkUpdateForm',
|
|
|
|
'UserCheckOtpCodeForm', 'UserCheckPasswordForm'
|
|
|
|
]
|
2019-11-06 03:57:00 +00:00
|
|
|
|
|
|
|
|
2019-05-28 04:11:55 +00:00
|
|
|
class UserCreateUpdateFormMixin(OrgModelForm):
|
2020-07-20 02:42:22 +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,
|
2020-07-20 02:42:22 +00:00
|
|
|
initial=User.ROLE.USER, label=_("Role")
|
2018-04-23 13:04:46 +00:00
|
|
|
)
|
2019-11-06 03:57:00 +00:00
|
|
|
source = forms.ChoiceField(
|
|
|
|
choices=get_source_choices, required=True,
|
|
|
|
initial=User.SOURCE_LOCAL, label=_("Source")
|
|
|
|
)
|
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',
|
2019-11-06 03:57:00 +00:00
|
|
|
'source', 'phone', 'role', 'date_expired',
|
2019-11-18 08:30:26 +00:00
|
|
|
'comment', 'mfa_level'
|
2016-08-14 11:18:41 +00:00
|
|
|
]
|
2016-08-19 16:42:50 +00:00
|
|
|
widgets = {
|
2019-11-18 08:30:26 +00:00
|
|
|
'mfa_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)
|
2019-05-28 04:11:55 +00:00
|
|
|
super(UserCreateUpdateFormMixin, self).__init__(*args, **kwargs)
|
2018-08-01 02:44:43 +00:00
|
|
|
|
|
|
|
roles = []
|
|
|
|
# Super admin user
|
|
|
|
if self.request.user.is_superuser:
|
2020-07-28 09:53:01 +00:00
|
|
|
roles.append((User.ROLE.ADMIN, User.ROLE.ADMIN.label))
|
|
|
|
roles.append((User.ROLE.USER, User.ROLE.USER.label))
|
|
|
|
roles.append((User.ROLE.AUDITOR, User.ROLE.AUDITOR.label))
|
2018-08-01 02:44:43 +00:00
|
|
|
|
|
|
|
# Org admin user
|
|
|
|
else:
|
|
|
|
user = kwargs.get('instance')
|
|
|
|
# Update
|
|
|
|
if user:
|
|
|
|
role = kwargs.get('instance').role
|
2020-07-28 09:53:01 +00:00
|
|
|
roles.append((role, User.ROLE[role]))
|
2018-08-01 02:44:43 +00:00
|
|
|
# Create
|
|
|
|
else:
|
2020-07-28 09:53:01 +00:00
|
|
|
roles.append((User.ROLE.USER, User.ROLE.USER.label))
|
2018-08-01 02:44:43 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2019-07-04 08:14:00 +00:00
|
|
|
def clean_password(self):
|
|
|
|
password_strategy = self.data.get('password_strategy')
|
|
|
|
# 创建-不设置密码
|
|
|
|
if password_strategy == '0':
|
|
|
|
return
|
|
|
|
password = self.data.get('password')
|
|
|
|
# 更新-密码为空
|
|
|
|
if password_strategy is None and not password:
|
|
|
|
return
|
|
|
|
if not check_password_rules(password):
|
|
|
|
msg = _('* Your password does not meet the requirements')
|
|
|
|
raise forms.ValidationError(msg)
|
|
|
|
return password
|
|
|
|
|
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')
|
2019-11-18 08:30:26 +00:00
|
|
|
mfa_level = self.cleaned_data.get('mfa_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:
|
2018-11-22 10:02:12 +00:00
|
|
|
user.reset_password(password)
|
2019-11-18 08:30:26 +00:00
|
|
|
if mfa_level:
|
|
|
|
user.mfa_level = mfa_level
|
2018-04-20 08:15:45 +00:00
|
|
|
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
|
|
|
|
2019-05-28 04:11:55 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2018-08-13 07:01:56 +00:00
|
|
|
class UserBulkUpdateForm(OrgModelForm):
|
2017-12-21 03:31:13 +00:00
|
|
|
users = forms.ModelMultipleChoiceField(
|
2017-04-12 03:50:15 +00:00
|
|
|
required=True,
|
|
|
|
label=_('Select users'),
|
2019-10-18 07:05:45 +00:00
|
|
|
queryset=User.objects.none(),
|
2017-04-12 03:50:15 +00:00
|
|
|
widget=forms.SelectMultiple(
|
|
|
|
attrs={
|
2019-10-18 07:05:45 +00:00
|
|
|
'class': 'users-select2',
|
2017-04-12 03:50:15 +00:00
|
|
|
'data-placeholder': _('Select users')
|
|
|
|
}
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2019-10-18 07:05:45 +00:00
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.set_fields_queryset()
|
|
|
|
|
|
|
|
def set_fields_queryset(self):
|
|
|
|
users_field = self.fields['users']
|
|
|
|
users_field.queryset = get_current_org_members()
|
|
|
|
|
2016-10-01 12:26:43 +00:00
|
|
|
class Meta:
|
|
|
|
model = User
|
2018-08-13 07:01:56 +00:00
|
|
|
fields = ['users', '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',
|
2018-08-13 07:01:56 +00:00
|
|
|
'data-placeholder': _('User group')
|
2017-12-18 10:38:30 +00:00
|
|
|
}
|
|
|
|
)
|
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
|
|
|
|
|
|
|
|
2019-12-16 08:53:29 +00:00
|
|
|
class UserCheckPasswordForm(forms.Form):
|
|
|
|
password = forms.CharField(
|
|
|
|
label=_('Password'), widget=forms.PasswordInput,
|
|
|
|
max_length=128, strip=False
|
2017-12-18 10:38:30 +00:00
|
|
|
)
|
2016-09-08 13:51:44 +00:00
|
|
|
|
2019-10-18 07:05:45 +00:00
|
|
|
|
2019-12-16 08:53:29 +00:00
|
|
|
class UserCheckOtpCodeForm(forms.Form):
|
|
|
|
otp_code = forms.CharField(label=_('MFA code'), max_length=6)
|