jumpserver/apps/users/forms/user.py

200 lines
6.3 KiB
Python
Raw Normal View History

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-11-09 15:49:10 +00:00
from common.utils import validate_ssh_public_key
Dev beta (#3048) * [Update] 统一url地址 * [Update] 修改api * [Update] 使用规范的签名 * [Update] 修改url * [Update] 修改swagger * [Update] 添加serializer class避免报错 * [Update] 修改token * [Update] 支持api key * [Update] 支持生成api key * [Update] 修改api重定向 * [Update] 修改翻译 * [Update] 添加说明文档 * [Update] 修复浏览器关闭后session不失效的问题 * [Update] 修改一些内容 * [Update] 修改 jms脚本 * [Update] 修改重定向 * [Update] 修改搜索trim * [Update] 修改搜索trim * [Update] 添加sys log * [Bugfix] 修改登陆错误 * [Update] 优化User操作private_token的接口 (#3091) * [Update] 优化User操作private_token的接口 * [Update] 优化User操作private_token的接口 2 * [Bugfix] 解决授权了一个节点,当移动节点后,被移动的节点下的资产会放到未分组节点下的问题 * [Update] 升级jquery * [Update] 默认使用page * [Update] 修改使用Orgmodel view set * [Update] 支持 nv的硬盘 https://github.com/jumpserver/jumpserver/issues/1804 * [UPdate] 解决命令执行宽度问题 * [Update] 优化节点 * [Update] 修改nodes过多时创建比较麻烦 * [Update] 修改导入 * [Update] 节点获取更新 * [Update] 修改nodes * [Update] nodes显示full value * [Update] 统一使用nodes select2 函数 * [Update] 修改磁盘大小小数 * [Update] 修改 Node service * [Update] 优化授权节点 * [Update] 修改 node permission * [Update] 修改asset permission * [Stash] * [Update] 修改node assets api * [Update] 修改tree service,支持资产数量 * [Update] 修改暂时完成 * [Update] 修改一些bug
2019-08-21 12:27:21 +00:00
from orgs.mixins.forms import OrgModelForm
Asset meta (#3539) - 更改了资产表单,影响 - 资产创建和更新 - 增加了资产平台数据库,影响 - 平台创建更新和删除 - 更改了资产的platform字段,又一个字符字段,改为一个外键,影响 - 资产创建和更新 - 资产连接 [windows,linux] - 测试连接等ansible任务 - 自动化云导入 - 更改了资产的序列化器,影响 - 资产创建更新列表 - 统一了树列表基础模板,影响 - 资产列表页,权限列表页,vault页,资产收集页 - 统一了导入导出组件,影响 - 资产导入导出 - 用户导入导出 - 用户组导入导出 - 系统用户导入导出 - 管理用户导入导出 - vault导出导出 - 收集用户列表导入导出 - 修改用户更新密码信号,影响 - 修改用户密码产生的改密日志 - 新增Model instance序列化工具函数,影响 - 操作日志生成 - 修改api mixin,新增 serializer_classes字段,serializer_classes = {"default": "", "display": "", "list": .., "other_action": ""}, 根据用户请求的方式返回不同的serializer_class,影响 - 用户的viewset - 资产权限的viewset - 统一系统配置中的tab切换 - 统一没有nav的页面,影响 - 重置密码 - 忘记密码 - 重置中设置密码 - 独立的message页面 - 修改用户组列表页,不再返还用户组下的用户,仅有数量 - 组织的一些方法变为layzproperty,避免重复计算 - 修改用户组详情页,影响 - 用户组增加删除用户
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
Asset meta (#3539) - 更改了资产表单,影响 - 资产创建和更新 - 增加了资产平台数据库,影响 - 平台创建更新和删除 - 更改了资产的platform字段,又一个字符字段,改为一个外键,影响 - 资产创建和更新 - 资产连接 [windows,linux] - 测试连接等ansible任务 - 自动化云导入 - 更改了资产的序列化器,影响 - 资产创建更新列表 - 统一了树列表基础模板,影响 - 资产列表页,权限列表页,vault页,资产收集页 - 统一了导入导出组件,影响 - 资产导入导出 - 用户导入导出 - 用户组导入导出 - 系统用户导入导出 - 管理用户导入导出 - vault导出导出 - 收集用户列表导入导出 - 修改用户更新密码信号,影响 - 修改用户密码产生的改密日志 - 新增Model instance序列化工具函数,影响 - 操作日志生成 - 修改api mixin,新增 serializer_classes字段,serializer_classes = {"default": "", "display": "", "list": .., "other_action": ""}, 根据用户请求的方式返回不同的serializer_class,影响 - 用户的viewset - 资产权限的viewset - 统一系统配置中的tab切换 - 统一没有nav的页面,影响 - 重置密码 - 忘记密码 - 重置中设置密码 - 独立的message页面 - 修改用户组列表页,不再返还用户组下的用户,仅有数量 - 组织的一些方法变为layzproperty,避免重复计算 - 修改用户组详情页,影响 - 用户组增加删除用户
2019-12-16 08:53:29 +00:00
__all__ = [
'UserCreateForm', 'UserUpdateForm', 'UserBulkUpdateForm',
'UserCheckOtpCodeForm', 'UserCheckPasswordForm'
]
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
)
source = forms.ChoiceField(
choices=get_source_choices, required=True,
initial=User.SOURCE_LOCAL, label=_("Source")
)
public_key = forms.CharField(
2018-03-27 09:47:53 +00:00
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.')
)
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',
'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
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:
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))
# 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]))
# Create
else:
2020-07-28 09:53:01 +00:00
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']
2018-03-27 09:47:53 +00:00
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
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')
public_key = self.cleaned_data.get('public_key')
2017-12-18 10:38:30 +00:00
user = super().save(commit=commit)
if password:
user.reset_password(password)
2019-11-18 08:30:26 +00:00
if mfa_level:
user.mfa_level = mfa_level
user.save()
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
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):
2017-12-21 03:31:13 +00:00
users = forms.ModelMultipleChoiceField(
2017-04-12 03:50:15 +00:00
required=True,
label=_('Select users'),
queryset=User.objects.none(),
2017-04-12 03:50:15 +00:00
widget=forms.SelectMultiple(
attrs={
'class': 'users-select2',
2017-04-12 03:50:15 +00:00
'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']
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': _('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
Asset meta (#3539) - 更改了资产表单,影响 - 资产创建和更新 - 增加了资产平台数据库,影响 - 平台创建更新和删除 - 更改了资产的platform字段,又一个字符字段,改为一个外键,影响 - 资产创建和更新 - 资产连接 [windows,linux] - 测试连接等ansible任务 - 自动化云导入 - 更改了资产的序列化器,影响 - 资产创建更新列表 - 统一了树列表基础模板,影响 - 资产列表页,权限列表页,vault页,资产收集页 - 统一了导入导出组件,影响 - 资产导入导出 - 用户导入导出 - 用户组导入导出 - 系统用户导入导出 - 管理用户导入导出 - vault导出导出 - 收集用户列表导入导出 - 修改用户更新密码信号,影响 - 修改用户密码产生的改密日志 - 新增Model instance序列化工具函数,影响 - 操作日志生成 - 修改api mixin,新增 serializer_classes字段,serializer_classes = {"default": "", "display": "", "list": .., "other_action": ""}, 根据用户请求的方式返回不同的serializer_class,影响 - 用户的viewset - 资产权限的viewset - 统一系统配置中的tab切换 - 统一没有nav的页面,影响 - 重置密码 - 忘记密码 - 重置中设置密码 - 独立的message页面 - 修改用户组列表页,不再返还用户组下的用户,仅有数量 - 组织的一些方法变为layzproperty,避免重复计算 - 修改用户组详情页,影响 - 用户组增加删除用户
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
Asset meta (#3539) - 更改了资产表单,影响 - 资产创建和更新 - 增加了资产平台数据库,影响 - 平台创建更新和删除 - 更改了资产的platform字段,又一个字符字段,改为一个外键,影响 - 资产创建和更新 - 资产连接 [windows,linux] - 测试连接等ansible任务 - 自动化云导入 - 更改了资产的序列化器,影响 - 资产创建更新列表 - 统一了树列表基础模板,影响 - 资产列表页,权限列表页,vault页,资产收集页 - 统一了导入导出组件,影响 - 资产导入导出 - 用户导入导出 - 用户组导入导出 - 系统用户导入导出 - 管理用户导入导出 - vault导出导出 - 收集用户列表导入导出 - 修改用户更新密码信号,影响 - 修改用户密码产生的改密日志 - 新增Model instance序列化工具函数,影响 - 操作日志生成 - 修改api mixin,新增 serializer_classes字段,serializer_classes = {"default": "", "display": "", "list": .., "other_action": ""}, 根据用户请求的方式返回不同的serializer_class,影响 - 用户的viewset - 资产权限的viewset - 统一系统配置中的tab切换 - 统一没有nav的页面,影响 - 重置密码 - 忘记密码 - 重置中设置密码 - 独立的message页面 - 修改用户组列表页,不再返还用户组下的用户,仅有数量 - 组织的一些方法变为layzproperty,避免重复计算 - 修改用户组详情页,影响 - 用户组增加删除用户
2019-12-16 08:53:29 +00:00
class UserCheckOtpCodeForm(forms.Form):
otp_code = forms.CharField(label=_('MFA code'), max_length=6)