Compare commits

...

9 Commits

Author SHA1 Message Date
xinwen
8f63b38a76 fix: 其他组织中创建的用户不要添加到默认组织了 2021-06-04 04:29:49 -05:00
Bai
457784bf0d fix: 修复组织批量删除的问题(翻译) 2021-06-03 11:36:03 +08:00
Bai
3e1883ceda fix: 修复组织批量删除的问题 2021-06-03 11:36:03 +08:00
Michael Bai
d183e3ddd0 fix: 修复创建/更新用户时密码策略相关的问题 2021-05-23 21:56:16 -05:00
Michael Bai
911ed45d6a fix: 修复parser没有处理int类型数据的问题 2021-05-23 21:53:49 -05:00
ibuler
344c291583 fix(assets): 修复网关信息没有密码的bug 2021-05-21 15:16:55 +08:00
Bai
162e5b204f fix: 修改cloud翻译 2021-05-20 22:27:53 -05:00
xinwen
e0c3998c45 fix: 修复 default 组织用户数量统计错误 2021-05-21 10:36:06 +08:00
ibuler
b912031cc2 fix: 修复周期监测任务配置的bug 2021-05-21 10:34:45 +08:00
11 changed files with 111 additions and 102 deletions

View File

@@ -59,7 +59,7 @@ class GatewaySerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
'created_by', 'comment', 'created_by', 'comment',
] ]
fields_fk = ['domain'] fields_fk = ['domain']
fields = fields_small + fields_fk fields = fields_small + fields_fk
extra_kwargs = { extra_kwargs = {
'password': {'write_only': True, 'validators': [NoSpecialChars()]}, 'password': {'write_only': True, 'validators': [NoSpecialChars()]},
'private_key': {"write_only": True}, 'private_key': {"write_only": True},
@@ -78,12 +78,12 @@ class GatewaySerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
class GatewayWithAuthSerializer(GatewaySerializer): class GatewayWithAuthSerializer(GatewaySerializer):
def get_field_names(self, declared_fields, info): class Meta(GatewaySerializer.Meta):
fields = super().get_field_names(declared_fields, info) extra_kwargs = {
fields.extend( 'password': {'write_only': False, 'validators': [NoSpecialChars()]},
['password', 'private_key'] 'private_key': {"write_only": False},
) 'public_key': {"write_only": False},
return fields }
class DomainWithGatewaySerializer(BulkOrgResourceModelSerializer): class DomainWithGatewaySerializer(BulkOrgResourceModelSerializer):

View File

@@ -94,7 +94,7 @@ class BaseFileParser(BaseParser):
new_row_data = {} new_row_data = {}
serializer_fields = self.serializer_fields serializer_fields = self.serializer_fields
for k, v in row_data.items(): for k, v in row_data.items():
if isinstance(v, list) or isinstance(v, dict) or isinstance(v, str) and k.strip() and v.strip(): if type(v) in [list, dict, int] or (isinstance(v, str) and k.strip() and v.strip()):
# 解决类似disk_info为字符串的'{}'的问题 # 解决类似disk_info为字符串的'{}'的问题
if not isinstance(v, str) and isinstance(serializer_fields[k], serializers.CharField): if not isinstance(v, str) and isinstance(serializer_fields[k], serializers.CharField):
v = str(v) v = str(v)

View File

@@ -279,7 +279,7 @@ class Config(dict):
'WINDOWS_SSH_DEFAULT_SHELL': 'cmd', 'WINDOWS_SSH_DEFAULT_SHELL': 'cmd',
'FLOWER_URL': "127.0.0.1:5555", 'FLOWER_URL': "127.0.0.1:5555",
'DEFAULT_ORG_SHOW_ALL_USERS': True, 'DEFAULT_ORG_SHOW_ALL_USERS': True,
'PERIOD_TASK_ENABLE': True, 'PERIOD_TASK_ENABLED': True,
'FORCE_SCRIPT_NAME': '', 'FORCE_SCRIPT_NAME': '',
'LOGIN_CONFIRM_ENABLE': False, 'LOGIN_CONFIRM_ENABLE': False,
'WINDOWS_SKIP_ALL_MANUAL_PASSWORD': False, 'WINDOWS_SKIP_ALL_MANUAL_PASSWORD': False,

Binary file not shown.

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n" "Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-20 14:56+0800\n" "POT-Creation-Date: 2021-06-03 11:34+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n" "Language-Team: JumpServer team<ibuler@qq.com>\n"
@@ -99,7 +99,7 @@ msgstr "动作"
#: terminal/backends/command/models.py:18 #: terminal/backends/command/models.py:18
#: terminal/backends/command/serializers.py:12 terminal/models/session.py:38 #: terminal/backends/command/serializers.py:12 terminal/models/session.py:38
#: tickets/models/comment.py:17 users/models/user.py:176 #: tickets/models/comment.py:17 users/models/user.py:176
#: users/models/user.py:738 users/models/user.py:764 #: users/models/user.py:740 users/models/user.py:766
#: users/serializers/group.py:20 #: users/serializers/group.py:20
#: users/templates/users/user_asset_permission.html:38 #: users/templates/users/user_asset_permission.html:38
#: users/templates/users/user_asset_permission.html:64 #: users/templates/users/user_asset_permission.html:64
@@ -184,7 +184,7 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. "
#: users/templates/users/_select_user_modal.html:14 #: users/templates/users/_select_user_modal.html:14
#: xpack/plugins/change_auth_plan/models.py:47 #: xpack/plugins/change_auth_plan/models.py:47
#: xpack/plugins/change_auth_plan/models.py:278 #: xpack/plugins/change_auth_plan/models.py:278
#: xpack/plugins/cloud/serializers.py:71 #: xpack/plugins/cloud/serializers.py:65
msgid "Username" msgid "Username"
msgstr "用户名" msgstr "用户名"
@@ -285,7 +285,7 @@ msgid "Cluster"
msgstr "集群" msgstr "集群"
#: applications/serializers/attrs/application_category/db.py:11 #: applications/serializers/attrs/application_category/db.py:11
#: ops/models/adhoc.py:146 xpack/plugins/cloud/serializers.py:69 #: ops/models/adhoc.py:146 xpack/plugins/cloud/serializers.py:63
msgid "Host" msgid "Host"
msgstr "主机" msgstr "主机"
@@ -295,7 +295,7 @@ msgstr "主机"
#: applications/serializers/attrs/application_type/oracle.py:11 #: applications/serializers/attrs/application_type/oracle.py:11
#: applications/serializers/attrs/application_type/pgsql.py:11 #: applications/serializers/attrs/application_type/pgsql.py:11
#: assets/models/asset.py:188 assets/models/domain.py:53 #: assets/models/asset.py:188 assets/models/domain.py:53
#: xpack/plugins/cloud/serializers.py:70 #: xpack/plugins/cloud/serializers.py:64
msgid "Port" msgid "Port"
msgstr "端口" msgstr "端口"
@@ -325,7 +325,7 @@ msgstr "目标URL"
#: xpack/plugins/change_auth_plan/models.py:68 #: xpack/plugins/change_auth_plan/models.py:68
#: xpack/plugins/change_auth_plan/models.py:190 #: xpack/plugins/change_auth_plan/models.py:190
#: xpack/plugins/change_auth_plan/models.py:285 #: xpack/plugins/change_auth_plan/models.py:285
#: xpack/plugins/cloud/serializers.py:73 #: xpack/plugins/cloud/serializers.py:67
msgid "Password" msgid "Password"
msgstr "密码" msgstr "密码"
@@ -407,7 +407,7 @@ msgstr "激活"
#: assets/models/asset.py:196 assets/models/cluster.py:19 #: assets/models/asset.py:196 assets/models/cluster.py:19
#: assets/models/user.py:66 templates/_nav.html:44 #: assets/models/user.py:66 templates/_nav.html:44
#: xpack/plugins/cloud/models.py:92 xpack/plugins/cloud/serializers.py:166 #: xpack/plugins/cloud/models.py:92 xpack/plugins/cloud/serializers.py:160
msgid "Admin user" msgid "Admin user"
msgstr "管理用户" msgstr "管理用户"
@@ -497,7 +497,7 @@ msgstr "创建者"
#: assets/models/label.py:25 common/db/models.py:72 common/mixins/models.py:50 #: assets/models/label.py:25 common/db/models.py:72 common/mixins/models.py:50
#: ops/models/adhoc.py:38 ops/models/command.py:29 orgs/models.py:25 #: ops/models/adhoc.py:38 ops/models/command.py:29 orgs/models.py:25
#: orgs/models.py:420 perms/models/base.py:56 users/models/group.py:18 #: orgs/models.py:420 perms/models/base.py:56 users/models/group.py:18
#: users/models/user.py:765 xpack/plugins/cloud/models.py:107 #: users/models/user.py:767 xpack/plugins/cloud/models.py:107
msgid "Date created" msgid "Date created"
msgstr "创建日期" msgstr "创建日期"
@@ -569,7 +569,7 @@ msgid "Default"
msgstr "默认" msgstr "默认"
#: assets/models/cluster.py:36 assets/models/label.py:14 #: assets/models/cluster.py:36 assets/models/label.py:14
#: users/models/user.py:750 #: users/models/user.py:752
msgid "System" msgid "System"
msgstr "系统" msgstr "系统"
@@ -678,7 +678,7 @@ msgstr "ssh私钥"
#: users/templates/users/user_asset_permission.html:41 #: users/templates/users/user_asset_permission.html:41
#: users/templates/users/user_asset_permission.html:73 #: users/templates/users/user_asset_permission.html:73
#: users/templates/users/user_asset_permission.html:158 #: users/templates/users/user_asset_permission.html:158
#: xpack/plugins/cloud/models.py:89 xpack/plugins/cloud/serializers.py:167 #: xpack/plugins/cloud/models.py:89 xpack/plugins/cloud/serializers.py:161
msgid "Node" msgid "Node"
msgstr "节点" msgstr "节点"
@@ -1978,13 +1978,13 @@ msgstr "更新任务内容: {}"
msgid "Disk used more than 80%: {} => {}" msgid "Disk used more than 80%: {} => {}"
msgstr "磁盘使用率超过 80%: {} => {}" msgstr "磁盘使用率超过 80%: {} => {}"
#: orgs/api.py:79 #: orgs/api.py:77
msgid "Have {} exists, Please delete" msgid "The current organization ({}) cannot be deleted"
msgstr "{} 存在数据, 请先删除" msgstr "当前组织 ({}) 不能被删除"
#: orgs/api.py:83 #: orgs/api.py:85
msgid "The current organization cannot be deleted" msgid "The organization have resource ({}) cannot be deleted"
msgstr "当前组织不能被删除" msgstr "组织有资源 ({}) 不能被删除"
#: orgs/mixins/models.py:45 orgs/mixins/serializers.py:25 orgs/models.py:36 #: orgs/mixins/models.py:45 orgs/mixins/serializers.py:25 orgs/models.py:36
#: orgs/models.py:417 orgs/serializers.py:108 #: orgs/models.py:417 orgs/serializers.py:108
@@ -2100,8 +2100,8 @@ msgid ""
msgstr "应用列表中包含与授权类型不同的应用。({})" msgstr "应用列表中包含与授权类型不同的应用。({})"
#: perms/serializers/asset/permission.py:45 #: perms/serializers/asset/permission.py:45
#: perms/serializers/asset/permission.py:69 users/serializers/user.py:34 #: perms/serializers/asset/permission.py:69 users/serializers/user.py:33
#: users/serializers/user.py:82 #: users/serializers/user.py:81
msgid "Is expired" msgid "Is expired"
msgstr "是否过期" msgstr "是否过期"
@@ -2121,7 +2121,7 @@ msgstr "资产名称"
msgid "System users name" msgid "System users name"
msgstr "系统用户名称" msgstr "系统用户名称"
#: perms/serializers/asset/permission.py:70 users/serializers/user.py:81 #: perms/serializers/asset/permission.py:70 users/serializers/user.py:80
msgid "Is valid" msgid "Is valid"
msgstr "账户是否有效" msgstr "账户是否有效"
@@ -3897,11 +3897,15 @@ msgstr "用户来源"
msgid "Date password last updated" msgid "Date password last updated"
msgstr "最后更新密码日期" msgstr "最后更新密码日期"
#: users/models/user.py:746 #: users/models/user.py:603
msgid "Need update password"
msgstr "需要更新密码"
#: users/models/user.py:748
msgid "Administrator" msgid "Administrator"
msgstr "管理员" msgstr "管理员"
#: users/models/user.py:749 #: users/models/user.py:751
msgid "Administrator is the super user of system" msgid "Administrator is the super user of system"
msgstr "Administrator是初始的超级管理员" msgstr "Administrator是初始的超级管理员"
@@ -3909,7 +3913,7 @@ msgstr "Administrator是初始的超级管理员"
msgid "The old password is incorrect" msgid "The old password is incorrect"
msgstr "旧密码错误" msgstr "旧密码错误"
#: users/serializers/profile.py:36 users/serializers/user.py:125 #: users/serializers/profile.py:36 users/serializers/user.py:126
msgid "Password does not match security rules" msgid "Password does not match security rules"
msgstr "密码不满足安全规则" msgstr "密码不满足安全规则"
@@ -3921,76 +3925,76 @@ msgstr "新密码不能是最近 {} 次的密码"
msgid "The newly set password is inconsistent" msgid "The newly set password is inconsistent"
msgstr "两次密码不一致" msgstr "两次密码不一致"
#: users/serializers/profile.py:119 users/serializers/user.py:80 #: users/serializers/profile.py:119 users/serializers/user.py:79
msgid "Is first login" msgid "Is first login"
msgstr "首次登录" msgstr "首次登录"
#: users/serializers/user.py:20 #: users/serializers/user.py:22
msgid "Reset link will be generated and sent to the user" msgid "Reset link will be generated and sent to the user"
msgstr "生成重置密码链接,通过邮件发送给用户" msgstr "生成重置密码链接,通过邮件发送给用户"
#: users/serializers/user.py:21 #: users/serializers/user.py:23
msgid "Set password" msgid "Set password"
msgstr "设置密码" msgstr "设置密码"
#: users/serializers/user.py:28 xpack/plugins/change_auth_plan/models.py:61 #: users/serializers/user.py:27 xpack/plugins/change_auth_plan/models.py:61
#: xpack/plugins/change_auth_plan/serializers.py:30 #: xpack/plugins/change_auth_plan/serializers.py:30
msgid "Password strategy" msgid "Password strategy"
msgstr "密码策略" msgstr "密码策略"
#: users/serializers/user.py:30 #: users/serializers/user.py:29
msgid "MFA enabled" msgid "MFA enabled"
msgstr "是否开启多因子认证" msgstr "是否开启多因子认证"
#: users/serializers/user.py:31 #: users/serializers/user.py:30
msgid "MFA force enabled" msgid "MFA force enabled"
msgstr "强制启用多因子认证" msgstr "强制启用多因子认证"
#: users/serializers/user.py:32 #: users/serializers/user.py:31
msgid "MFA level for display" msgid "MFA level for display"
msgstr "多因子认证等级(显示名称)" msgstr "多因子认证等级(显示名称)"
#: users/serializers/user.py:33 #: users/serializers/user.py:32
msgid "Login blocked" msgid "Login blocked"
msgstr "登录被阻塞" msgstr "登录被阻塞"
#: users/serializers/user.py:35 #: users/serializers/user.py:34
msgid "Can update" msgid "Can update"
msgstr "是否可更新" msgstr "是否可更新"
#: users/serializers/user.py:36 #: users/serializers/user.py:35
msgid "Can delete" msgid "Can delete"
msgstr "是否可删除" msgstr "是否可删除"
#: users/serializers/user.py:39 users/serializers/user.py:87 #: users/serializers/user.py:38 users/serializers/user.py:86
msgid "Organization role name" msgid "Organization role name"
msgstr "组织角色名称" msgstr "组织角色名称"
#: users/serializers/user.py:83 #: users/serializers/user.py:82
msgid "Avatar url" msgid "Avatar url"
msgstr "头像路径" msgstr "头像路径"
#: users/serializers/user.py:85 #: users/serializers/user.py:84
msgid "Groups name" msgid "Groups name"
msgstr "用户组名" msgstr "用户组名"
#: users/serializers/user.py:86 #: users/serializers/user.py:85
msgid "Source name" msgid "Source name"
msgstr "用户来源名" msgstr "用户来源名"
#: users/serializers/user.py:88 #: users/serializers/user.py:87
msgid "Super role name" msgid "Super role name"
msgstr "超级角色名称" msgstr "超级角色名称"
#: users/serializers/user.py:89 #: users/serializers/user.py:88
msgid "Total role name" msgid "Total role name"
msgstr "汇总角色名称" msgstr "汇总角色名称"
#: users/serializers/user.py:113 #: users/serializers/user.py:112
msgid "Role limit to {}" msgid "Role limit to {}"
msgstr "角色只能为 {}" msgstr "角色只能为 {}"
#: users/serializers/user.py:210 #: users/serializers/user.py:211
msgid "name not unique" msgid "name not unique"
msgstr "名称重复" msgstr "名称重复"
@@ -3999,7 +4003,7 @@ msgid "Security token validation"
msgstr "安全令牌验证" msgstr "安全令牌验证"
#: users/templates/users/_base_otp.html:14 xpack/plugins/cloud/models.py:78 #: users/templates/users/_base_otp.html:14 xpack/plugins/cloud/models.py:78
#: xpack/plugins/cloud/serializers.py:165 #: xpack/plugins/cloud/serializers.py:159
msgid "Account" msgid "Account"
msgstr "账户" msgstr "账户"
@@ -4740,7 +4744,7 @@ msgstr "云服务商"
msgid "Cloud account" msgid "Cloud account"
msgstr "云账号" msgstr "云账号"
#: xpack/plugins/cloud/models.py:81 xpack/plugins/cloud/serializers.py:146 #: xpack/plugins/cloud/models.py:81 xpack/plugins/cloud/serializers.py:140
msgid "Regions" msgid "Regions"
msgstr "地域" msgstr "地域"
@@ -4748,7 +4752,7 @@ msgstr "地域"
msgid "Hostname strategy" msgid "Hostname strategy"
msgstr "主机名策略" msgstr "主机名策略"
#: xpack/plugins/cloud/models.py:95 xpack/plugins/cloud/serializers.py:169 #: xpack/plugins/cloud/models.py:95 xpack/plugins/cloud/serializers.py:163
msgid "Always update" msgid "Always update"
msgstr "总是更新" msgstr "总是更新"
@@ -4940,19 +4944,19 @@ msgstr ""
msgid "Subscription ID" msgid "Subscription ID"
msgstr "" msgstr ""
#: xpack/plugins/cloud/serializers.py:55 #: xpack/plugins/cloud/serializers.py:49
msgid "{} is required" msgid "This field is required"
msgstr "{} 字段是必填项" msgstr "这个字段是必填项"
#: xpack/plugins/cloud/serializers.py:144 #: xpack/plugins/cloud/serializers.py:138
msgid "History count" msgid "History count"
msgstr "执行次数" msgstr "执行次数"
#: xpack/plugins/cloud/serializers.py:145 #: xpack/plugins/cloud/serializers.py:139
msgid "Instance count" msgid "Instance count"
msgstr "实例个数" msgstr "实例个数"
#: xpack/plugins/cloud/serializers.py:168 #: xpack/plugins/cloud/serializers.py:162
#: xpack/plugins/gathered_user/serializers.py:20 #: xpack/plugins/gathered_user/serializers.py:20
msgid "Periodic display" msgid "Periodic display"
msgstr "定时执行" msgstr "定时执行"
@@ -5045,6 +5049,12 @@ msgstr "旗舰版"
msgid "Community edition" msgid "Community edition"
msgstr "社区版" msgstr "社区版"
#~ msgid "Have {} exists, Please delete"
#~ msgstr "{} 存在数据, 请先删除"
#~ msgid "{} is required"
#~ msgstr "{} 字段是必填项"
#~ msgid "AppSecret is required" #~ msgid "AppSecret is required"
#~ msgstr "AppSecret 是必须的" #~ msgstr "AppSecret 是必须的"

View File

@@ -48,7 +48,6 @@ class OrgViewSet(BulkModelViewSet):
queryset = Organization.objects.all() queryset = Organization.objects.all()
serializer_class = OrgSerializer serializer_class = OrgSerializer
permission_classes = (IsSuperUserOrAppUser,) permission_classes = (IsSuperUserOrAppUser,)
org = None
def get_serializer_class(self): def get_serializer_class(self):
mapper = { mapper = {
@@ -58,32 +57,36 @@ class OrgViewSet(BulkModelViewSet):
return mapper.get(self.action, super().get_serializer_class()) return mapper.get(self.action, super().get_serializer_class())
@tmp_to_root_org() @tmp_to_root_org()
def get_data_from_model(self, model): def get_data_from_model(self, org, model):
if model == User: if model == User:
data = model.objects.filter( data = model.objects.filter(
orgs__id=self.org.id, orgs__id=org.id, m2m_org_members__role__in=[ROLE.USER, ROLE.ADMIN, ROLE.AUDITOR]
m2m_org_members__role__in=[ROLE.USER, ROLE.ADMIN, ROLE.AUDITOR]
) )
elif model == Node: elif model == Node:
# 节点不能手动删除,所以排除检查 # 节点不能手动删除,所以排除检查
data = model.objects.filter(org_id=self.org.id).exclude(parent_key='', key__regex=r'^[0-9]+$') data = model.objects.filter(org_id=org.id).exclude(parent_key='', key__regex=r'^[0-9]+$')
else: else:
data = model.objects.filter(org_id=self.org.id) data = model.objects.filter(org_id=org.id)
return data return data
def destroy(self, request, *args, **kwargs): def allow_bulk_destroy(self, qs, filtered):
self.org = self.get_object() return False
def perform_destroy(self, instance):
if str(current_org) == str(instance):
msg = _('The current organization ({}) cannot be deleted'.format(current_org))
raise PermissionDenied(detail=msg)
for model in org_related_models: for model in org_related_models:
data = self.get_data_from_model(model) data = self.get_data_from_model(instance, model)
if data: if not data:
msg = _('Have {} exists, Please delete').format(model._meta.verbose_name) continue
return Response(data={'error': msg}, status=status.HTTP_403_FORBIDDEN) msg = _(
else: 'The organization have resource ({}) cannot be deleted'
if str(current_org) == str(self.org): ).format(model._meta.verbose_name)
msg = _('The current organization cannot be deleted') raise PermissionDenied(detail=msg)
return Response(data={'error': msg}, status=status.HTTP_403_FORBIDDEN)
self.org.delete() super().perform_destroy(instance)
return Response({'msg': True}, status=status.HTTP_200_OK)
class OrgMemberRelationBulkViewSet(JMSBulkRelationModelViewSet): class OrgMemberRelationBulkViewSet(JMSBulkRelationModelViewSet):

View File

@@ -78,12 +78,12 @@ class OrgResourceStatisticsCache(OrgRelatedCache):
return self.org return self.org
def compute_users_amount(self): def compute_users_amount(self):
if self.org.is_root(): users = User.objects.exclude(role='App')
users_amount = User.objects.exclude(role='App').count()
else: if not self.org.is_root():
users_amount = OrganizationMember.objects.values( users = users.filter(m2m_org_members__org_id=self.org.id)
'user_id'
).filter(org_id=self.org.id).distinct().count() users_amount = users.values('id').distinct().count()
return users_amount return users_amount
def compute_assets_amount(self): def compute_assets_amount(self):

View File

@@ -167,10 +167,3 @@ def on_org_user_changed(action, instance, reverse, pk_set, **kwargs):
leaved_users = set(pk_set) - set(org.members.filter(id__in=user_pk_set).values_list('id', flat=True)) leaved_users = set(pk_set) - set(org.members.filter(id__in=user_pk_set).values_list('id', flat=True))
_clear_users_from_org(org, leaved_users) _clear_users_from_org(org, leaved_users)
@receiver(post_save, sender=User)
def on_user_create_refresh_cache(sender, instance, created, **kwargs):
if created:
default_org = Organization.default()
default_org.members.add(instance)

View File

@@ -599,7 +599,9 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser):
auto_now_add=True, blank=True, null=True, auto_now_add=True, blank=True, null=True,
verbose_name=_('Date password last updated') verbose_name=_('Date password last updated')
) )
need_update_password = models.BooleanField(default=False) need_update_password = models.BooleanField(
default=False, verbose_name=_('Need update password')
)
wecom_id = models.CharField(null=True, default=None, unique=True, max_length=128) wecom_id = models.CharField(null=True, default=None, unique=True, max_length=128)
dingtalk_id = models.CharField(null=True, default=None, unique=True, max_length=128) dingtalk_id = models.CharField(null=True, default=None, unique=True, max_length=128)

View File

@@ -2,6 +2,7 @@
# #
from django.core.cache import cache from django.core.cache import cache
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.db.models import TextChoices
from rest_framework import serializers from rest_framework import serializers
from common.mixins import CommonBulkSerializerMixin from common.mixins import CommonBulkSerializerMixin
@@ -17,15 +18,13 @@ __all__ = [
class UserSerializer(CommonBulkSerializerMixin, serializers.ModelSerializer): class UserSerializer(CommonBulkSerializerMixin, serializers.ModelSerializer):
EMAIL_SET_PASSWORD = _('Reset link will be generated and sent to the user') class PasswordStrategy(TextChoices):
CUSTOM_PASSWORD = _('Set password') email = 'email', _('Reset link will be generated and sent to the user')
PASSWORD_STRATEGY_CHOICES = ( custom = 'custom', _('Set password')
(0, EMAIL_SET_PASSWORD),
(1, CUSTOM_PASSWORD)
)
password_strategy = serializers.ChoiceField( password_strategy = serializers.ChoiceField(
choices=PASSWORD_STRATEGY_CHOICES, required=False, choices=PasswordStrategy.choices, default=PasswordStrategy.email, required=False,
label=_('Password strategy'), write_only=True, default=0 write_only=True, label=_('Password strategy')
) )
mfa_enabled = serializers.BooleanField(read_only=True, label=_('MFA enabled')) mfa_enabled = serializers.BooleanField(read_only=True, label=_('MFA enabled'))
mfa_force_enabled = serializers.BooleanField(read_only=True, label=_('MFA force enabled')) mfa_force_enabled = serializers.BooleanField(read_only=True, label=_('MFA force enabled'))
@@ -117,9 +116,11 @@ class UserSerializer(CommonBulkSerializerMixin, serializers.ModelSerializer):
def validate_password(self, password): def validate_password(self, password):
from ..utils import check_password_rules from ..utils import check_password_rules
password_strategy = self.initial_data.get('password_strategy') password_strategy = self.initial_data.get('password_strategy')
if password_strategy == '0': if self.instance is None and password_strategy != self.PasswordStrategy.custom:
# 创建用户,使用邮件设置密码
return return
if password_strategy is None and not password: if self.instance and not password:
# 更新用户, 未设置密码
return return
if not check_password_rules(password): if not check_password_rules(password):
msg = _('Password does not match security rules') msg = _('Password does not match security rules')

View File

@@ -122,7 +122,7 @@ REDIS_PORT: 6379
# USER_LOGIN_SINGLE_MACHINE_ENABLED: False # USER_LOGIN_SINGLE_MACHINE_ENABLED: False
# #
# 启用定时任务 # 启用定时任务
# PERIOD_TASK_ENABLE: True # PERIOD_TASK_ENABLED: True
# #
# 启用二次复合认证配置 # 启用二次复合认证配置
# LOGIN_CONFIRM_ENABLE: False # LOGIN_CONFIRM_ENABLE: False