from django import forms from django.utils.translation import gettext_lazy as _ from common.utils import validate_ssh_public_key from orgs.mixins.forms import OrgModelForm from ..models import User from ..utils import ( check_password_rules, get_current_org_members, get_source_choices ) __all__ = [ 'UserCreateForm', 'UserUpdateForm', 'UserBulkUpdateForm', 'UserCheckOtpCodeForm', 'UserCheckPasswordForm' ] 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") ) source = forms.ChoiceField( choices=get_source_choices, required=True, initial=User.SOURCE_LOCAL, label=_("Source") ) 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', 'source', 'phone', 'role', 'date_expired', 'comment', 'mfa_level' ] widgets = { 'mfa_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, User.ROLE.ADMIN.label)) roles.append((User.ROLE.USER, User.ROLE.USER.label)) roles.append((User.ROLE.AUDITOR, User.ROLE.AUDITOR.label)) # Org admin user else: user = kwargs.get('instance') # Update if user: role = kwargs.get('instance').role roles.append((role, User.ROLE[role])) # Create else: roles.append((User.ROLE.USER, User.ROLE.USER.label)) 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 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 def save(self, commit=True): password = self.cleaned_data.get('password') mfa_level = self.cleaned_data.get('mfa_level') public_key = self.cleaned_data.get('public_key') user = super().save(commit=commit) if password: user.reset_password(password) if mfa_level: user.mfa_level = mfa_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 UserBulkUpdateForm(OrgModelForm): users = forms.ModelMultipleChoiceField( required=True, label=_('Select users'), queryset=User.objects.none(), widget=forms.SelectMultiple( attrs={ 'class': 'users-select2', 'data-placeholder': _('Select users') } ) ) 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() 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 class UserCheckPasswordForm(forms.Form): 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)