fix(ticket): 修改工单获取系统用户的字段 (#4274)

fix(ticket): 申请资产工单修改bug
pull/4282/head
xinwen 2020-07-09 14:06:06 +08:00 committed by GitHub
parent f430c9e435
commit 8eb6cfa9c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 102 additions and 33 deletions

Binary file not shown.

View File

@ -8,7 +8,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: 2020-07-08 15:05+0800\n" "POT-Creation-Date: 2020-07-09 10:05+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\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"
@ -211,7 +211,7 @@ msgstr "IP"
#: assets/models/asset.py:187 assets/serializers/asset_user.py:45 #: assets/models/asset.py:187 assets/serializers/asset_user.py:45
#: assets/serializers/gathered_user.py:20 settings/serializers/settings.py:51 #: assets/serializers/gathered_user.py:20 settings/serializers/settings.py:51
#: tickets/serializers/request_asset_perm.py:13 #: tickets/serializers/request_asset_perm.py:14
#: users/templates/users/_granted_assets.html:25 #: users/templates/users/_granted_assets.html:25
#: users/templates/users/user_asset_permission.html:157 #: users/templates/users/user_asset_permission.html:157
msgid "Hostname" msgid "Hostname"
@ -485,7 +485,7 @@ msgstr "每行一个命令"
#: assets/models/cmd_filter.py:55 audits/models.py:57 #: assets/models/cmd_filter.py:55 audits/models.py:57
#: authentication/templates/authentication/_access_key_modal.html:34 #: authentication/templates/authentication/_access_key_modal.html:34
#: perms/forms/asset_permission.py:20 #: perms/forms/asset_permission.py:20
#: tickets/serializers/request_asset_perm.py:51 #: tickets/serializers/request_asset_perm.py:54
#: tickets/serializers/ticket.py:26 #: tickets/serializers/ticket.py:26
#: users/templates/users/_granted_assets.html:29 #: users/templates/users/_granted_assets.html:29
#: users/templates/users/user_asset_permission.html:44 #: users/templates/users/user_asset_permission.html:44
@ -540,7 +540,7 @@ msgstr "默认资产组"
#: templates/index.html:78 terminal/backends/command/models.py:18 #: templates/index.html:78 terminal/backends/command/models.py:18
#: terminal/backends/command/serializers.py:12 terminal/models.py:185 #: terminal/backends/command/serializers.py:12 terminal/models.py:185
#: tickets/models/ticket.py:35 tickets/models/ticket.py:130 #: tickets/models/ticket.py:35 tickets/models/ticket.py:130
#: tickets/serializers/request_asset_perm.py:52 #: tickets/serializers/request_asset_perm.py:55
#: tickets/serializers/ticket.py:27 users/forms/group.py:15 #: tickets/serializers/ticket.py:27 users/forms/group.py:15
#: users/models/user.py:160 users/models/user.py:176 users/models/user.py:615 #: users/models/user.py:160 users/models/user.py:176 users/models/user.py:615
#: users/serializers/group.py:20 #: users/serializers/group.py:20
@ -648,6 +648,7 @@ msgstr "SFTP根路径"
#: perms/models/remote_app_permission.py:16 templates/_nav.html:45 #: perms/models/remote_app_permission.py:16 templates/_nav.html:45
#: terminal/backends/command/models.py:20 #: terminal/backends/command/models.py:20
#: terminal/backends/command/serializers.py:14 terminal/models.py:189 #: terminal/backends/command/serializers.py:14 terminal/models.py:189
#: tickets/serializers/request_asset_perm.py:16
#: users/templates/users/_granted_assets.html:27 #: users/templates/users/_granted_assets.html:27
#: users/templates/users/user_asset_permission.html:42 #: users/templates/users/user_asset_permission.html:42
#: users/templates/users/user_asset_permission.html:76 #: users/templates/users/user_asset_permission.html:76
@ -918,7 +919,7 @@ msgid "Success"
msgstr "成功" msgstr "成功"
#: audits/models.py:43 ops/models/command.py:28 perms/models/base.py:52 #: audits/models.py:43 ops/models/command.py:28 perms/models/base.py:52
#: terminal/models.py:199 tickets/serializers/request_asset_perm.py:15 #: terminal/models.py:199 tickets/serializers/request_asset_perm.py:18
#: xpack/plugins/change_auth_plan/models.py:177 #: xpack/plugins/change_auth_plan/models.py:177
#: xpack/plugins/change_auth_plan/models.py:308 #: xpack/plugins/change_auth_plan/models.py:308
#: xpack/plugins/gathered_user/models.py:76 #: xpack/plugins/gathered_user/models.py:76
@ -1009,7 +1010,7 @@ msgstr "多因子认证"
msgid "Reason" msgid "Reason"
msgstr "原因" msgstr "原因"
#: audits/models.py:106 tickets/serializers/request_asset_perm.py:50 #: audits/models.py:106 tickets/serializers/request_asset_perm.py:53
#: tickets/serializers/ticket.py:25 xpack/plugins/cloud/models.py:214 #: tickets/serializers/ticket.py:25 xpack/plugins/cloud/models.py:214
#: xpack/plugins/cloud/models.py:272 #: xpack/plugins/cloud/models.py:272
msgid "Status" msgid "Status"
@ -1699,7 +1700,7 @@ msgstr "动作"
msgid "Asset permission" msgid "Asset permission"
msgstr "资产授权" msgstr "资产授权"
#: perms/models/base.py:53 tickets/serializers/request_asset_perm.py:17 #: perms/models/base.py:53 tickets/serializers/request_asset_perm.py:20
#: users/models/user.py:505 users/templates/users/user_detail.html:93 #: users/models/user.py:505 users/templates/users/user_detail.html:93
#: users/templates/users/user_profile.html:120 #: users/templates/users/user_profile.html:120
msgid "Date expired" msgid "Date expired"
@ -2432,36 +2433,40 @@ msgstr "结束日期"
msgid "Args" msgid "Args"
msgstr "参数" msgstr "参数"
#: tickets/api/request_asset_perm.py:36 #: tickets/api/request_asset_perm.py:40
msgid "Ticket closed" msgid "Ticket closed"
msgstr "工单已关闭" msgstr "工单已关闭"
#: tickets/api/request_asset_perm.py:39 #: tickets/api/request_asset_perm.py:43
#, python-format #, python-format
msgid "Ticket has %s" msgid "Ticket has %s"
msgstr "工单已%s" msgstr "工单已%s"
#: tickets/api/request_asset_perm.py:59 #: tickets/api/request_asset_perm.py:69
msgid "Superuser"
msgstr "超级管理员"
#: tickets/api/request_asset_perm.py:102
msgid "Confirm assets first" msgid "Confirm assets first"
msgstr "请先确认资产" msgstr "请先确认资产"
#: tickets/api/request_asset_perm.py:62 #: tickets/api/request_asset_perm.py:105
msgid "Confirmed assets changed" msgid "Confirmed assets changed"
msgstr "确认的资产变更了" msgstr "确认的资产变更了"
#: tickets/api/request_asset_perm.py:66 #: tickets/api/request_asset_perm.py:109
msgid "Confirm system-user first" msgid "Confirm system-user first"
msgstr "请先确认系统用户" msgstr "请先确认系统用户"
#: tickets/api/request_asset_perm.py:70 #: tickets/api/request_asset_perm.py:113
msgid "Confirmed system-user changed" msgid "Confirmed system-user changed"
msgstr "确认的系统用户变更了" msgstr "确认的系统用户变更了"
#: tickets/api/request_asset_perm.py:73 xpack/plugins/cloud/models.py:205 #: tickets/api/request_asset_perm.py:116 xpack/plugins/cloud/models.py:205
msgid "Succeed" msgid "Succeed"
msgstr "成功" msgstr "成功"
#: tickets/api/request_asset_perm.py:81 #: tickets/api/request_asset_perm.py:124
msgid "{} request assets, approved by {}" msgid "{} request assets, approved by {}"
msgstr "{} 申请资产,通过人 {}" msgstr "{} 申请资产,通过人 {}"
@ -2525,19 +2530,19 @@ msgstr "{} {} 这个工单"
msgid "this ticket" msgid "this ticket"
msgstr "这个工单" msgstr "这个工单"
#: tickets/serializers/request_asset_perm.py:11 #: tickets/serializers/request_asset_perm.py:12
msgid "IP group" msgid "IP group"
msgstr "IP组" msgstr "IP组"
#: tickets/serializers/request_asset_perm.py:21 #: tickets/serializers/request_asset_perm.py:24
msgid "Confirmed assets" msgid "Confirmed assets"
msgstr "确认的资产" msgstr "确认的资产"
#: tickets/serializers/request_asset_perm.py:25 #: tickets/serializers/request_asset_perm.py:28
msgid "Confirmed system user" msgid "Confirmed system user"
msgstr "确认的系统用户" msgstr "确认的系统用户"
#: tickets/serializers/request_asset_perm.py:58 #: tickets/serializers/request_asset_perm.py:65
msgid "Must be organization admin or superuser" msgid "Must be organization admin or superuser"
msgstr "必须是组织管理员或者超级管理员" msgstr "必须是组织管理员或者超级管理员"
@ -2778,10 +2783,6 @@ msgstr "最后更新密码日期"
msgid "Administrator is the super user of system" msgid "Administrator is the super user of system"
msgstr "Administrator是初始的超级管理员" msgstr "Administrator是初始的超级管理员"
#: users/serializers/group.py:50
msgid "Auditors cannot be join in the user group"
msgstr "审计员不能被加入到用户组"
#: users/serializers/user.py:69 users/serializers/user.py:229 #: users/serializers/user.py:69 users/serializers/user.py:229
msgid "Is first login" msgid "Is first login"
msgstr "首次登录" msgstr "首次登录"
@ -3948,6 +3949,9 @@ msgstr "企业版"
msgid "Ultimate edition" msgid "Ultimate edition"
msgstr "旗舰版" msgstr "旗舰版"
#~ msgid "Auditors cannot be join in the user group"
#~ msgstr "审计员不能被加入到用户组"
#~ msgid "Always update" #~ msgid "Always update"
#~ msgstr "总是更新" #~ msgstr "总是更新"
@ -4758,9 +4762,6 @@ msgstr "旗舰版"
#~ msgid "Tips: Some provider use token except password" #~ msgid "Tips: Some provider use token except password"
#~ msgstr "提示一些邮件提供商需要输入的是Token" #~ msgstr "提示一些邮件提供商需要输入的是Token"
#~ msgid "Send user"
#~ msgstr "发送账号"
#~ msgid "Tips: Send mail account, default SMTP account as the send account" #~ msgid "Tips: Send mail account, default SMTP account as the send account"
#~ msgstr "提示发送邮件账号默认使用SMTP账号作为发送账号" #~ msgstr "提示发送邮件账号默认使用SMTP账号作为发送账号"

View File

@ -1,9 +1,13 @@
from collections import namedtuple
from django.db.transaction import atomic from django.db.transaction import atomic
from django.db.models import F
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from common.const.http import POST from users.models.user import User
from common.const.http import POST, GET
from common.drf.api import JMSModelViewSet from common.drf.api import JMSModelViewSet
from common.permissions import IsValidUser from common.permissions import IsValidUser
from common.utils.django import get_object_or_none from common.utils.django import get_object_or_none
@ -26,6 +30,7 @@ class RequestAssetPermTicketViewSet(JMSModelViewSet):
'default': serializers.RequestAssetPermTicketSerializer, 'default': serializers.RequestAssetPermTicketSerializer,
'approve': EmptySerializer, 'approve': EmptySerializer,
'reject': EmptySerializer, 'reject': EmptySerializer,
'assignees': serializers.OrgAssigneeSerializer,
} }
permission_classes = (IsValidUser,) permission_classes = (IsValidUser,)
filter_fields = ['status', 'title', 'action', 'user_display'] filter_fields = ['status', 'title', 'action', 'user_display']
@ -38,6 +43,41 @@ class RequestAssetPermTicketViewSet(JMSModelViewSet):
action_display = dict(instance.ACTION_CHOICES).get(action) action_display = dict(instance.ACTION_CHOICES).get(action)
raise TicketActionYet(detail=_('Ticket has %s') % action_display) raise TicketActionYet(detail=_('Ticket has %s') % action_display)
@action(detail=False, methods=[GET], permission_classes=[IsValidUser])
def assignees(self, request, *args, **kwargs):
org_mapper = {}
UserTuple = namedtuple('UserTuple', ('id', 'name', 'username'))
user = request.user
superusers = User.objects.filter(role=User.ROLE_ADMIN)
admins_with_org = User.objects.filter(related_admin_orgs__users=user).annotate(
org_id=F('related_admin_orgs__id'), org_name=F('related_admin_orgs__name')
)
for user in admins_with_org:
org_id = user.org_id
if org_id not in org_mapper:
org_mapper[org_id] = {
'org_name': user.org_name,
'org_admins': set() # 去重
}
org_mapper[org_id]['org_admins'].add(UserTuple(user.id, user.name, user.username))
result = [
{
'org_name': _('Superuser'),
'org_admins': set(UserTuple(user.id, user.name, user.username)
for user in superusers)
}
]
for org in org_mapper.values():
result.append(org)
serializer_class = self.get_serializer_class()
serilizer = serializer_class(instance=result, many=True)
return Response(data=serilizer.data)
@action(detail=True, methods=[POST], permission_classes=[IsAssignee, IsValidUser]) @action(detail=True, methods=[POST], permission_classes=[IsAssignee, IsValidUser])
def reject(self, request, *args, **kwargs): def reject(self, request, *args, **kwargs):
instance = self.get_object() instance = self.get_object()

View File

@ -1,8 +1,9 @@
from rest_framework import serializers from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.urls import reverse from django.urls import reverse
from django.db.models import Q
from orgs.utils import current_org from users.models.user import User
from ..models import Ticket from ..models import Ticket
@ -10,7 +11,9 @@ class RequestAssetPermTicketSerializer(serializers.ModelSerializer):
ips = serializers.ListField(child=serializers.IPAddressField(), source='meta.ips', ips = serializers.ListField(child=serializers.IPAddressField(), source='meta.ips',
default=list, label=_('IP group')) default=list, label=_('IP group'))
hostname = serializers.CharField(max_length=256, source='meta.hostname', default=None, hostname = serializers.CharField(max_length=256, source='meta.hostname', default=None,
allow_blank=True, label=_('Hostname')) allow_blank=True, label=_('Hostname'))
system_user = serializers.CharField(max_length=256, source='meta.system_user', default='',
allow_blank=True, label=_('System user'))
date_start = serializers.DateTimeField(source='meta.date_start', allow_null=True, date_start = serializers.DateTimeField(source='meta.date_start', allow_null=True,
required=False, label=_('Date start')) required=False, label=_('Date start'))
date_expired = serializers.DateTimeField(source='meta.date_expired', allow_null=True, date_expired = serializers.DateTimeField(source='meta.date_expired', allow_null=True,
@ -33,7 +36,7 @@ class RequestAssetPermTicketSerializer(serializers.ModelSerializer):
'status', 'action', 'date_created', 'date_updated', 'system_user_waitlist_url', 'status', 'action', 'date_created', 'date_updated', 'system_user_waitlist_url',
'type', 'type_display', 'action_display', 'ips', 'confirmed_assets', 'type', 'type_display', 'action_display', 'ips', 'confirmed_assets',
'date_start', 'date_expired', 'confirmed_system_user', 'hostname', 'date_start', 'date_expired', 'confirmed_system_user', 'hostname',
'assets_waitlist_url' 'assets_waitlist_url', 'system_user'
] ]
m2m_fields = [ m2m_fields = [
'user', 'user_display', 'assignees', 'assignees_display', 'user', 'user_display', 'assignees', 'assignees_display',
@ -53,7 +56,11 @@ class RequestAssetPermTicketSerializer(serializers.ModelSerializer):
} }
def validate_assignees(self, assignees): def validate_assignees(self, assignees):
count = current_org.org_admins().filter(id__in=[assignee.id for assignee in assignees]).count() user = self.context['request'].user
count = User.objects.filter(Q(related_admin_orgs__users=user) | Q(role=User.ROLE_ADMIN)).filter(
id__in=[assignee.id for assignee in assignees]).distinct().count()
if count != len(assignees): if count != len(assignees):
raise serializers.ValidationError(_('Must be organization admin or superuser')) raise serializers.ValidationError(_('Must be organization admin or superuser'))
return assignees return assignees
@ -61,7 +68,10 @@ class RequestAssetPermTicketSerializer(serializers.ModelSerializer):
def get_system_user_waitlist_url(self, instance: Ticket): def get_system_user_waitlist_url(self, instance: Ticket):
if not self._is_assignee(instance): if not self._is_assignee(instance):
return None return None
return {'url': reverse('api-assets:system-user-list')} meta = instance.meta
url = reverse('api-assets:system-user-list')
query = meta.get('system_user', '')
return '{}?search={}'.format(url, query)
def get_assets_waitlist_url(self, instance: Ticket): def get_assets_waitlist_url(self, instance: Ticket):
if not self._is_assignee(instance): if not self._is_assignee(instance):
@ -118,3 +128,14 @@ class RequestAssetPermTicketSerializer(serializers.ModelSerializer):
def _is_assignee(self, obj: Ticket): def _is_assignee(self, obj: Ticket):
user = self.context['request'].user user = self.context['request'].user
return obj.is_assignee(user) return obj.is_assignee(user)
class AssigneeSerializer(serializers.Serializer):
id = serializers.UUIDField()
name = serializers.CharField()
username = serializers.CharField()
class OrgAssigneeSerializer(serializers.Serializer):
org_name = serializers.CharField()
org_admins = AssigneeSerializer(many=True)

View File

@ -1,6 +1,7 @@
from rest_framework.compat import coreapi, coreschema from rest_framework.compat import coreapi, coreschema
from rest_framework import filters from rest_framework import filters
from users.models.user import User
from orgs.utils import current_org from orgs.utils import current_org
@ -11,7 +12,7 @@ class OrgRoleUserFilterBackend(filters.BaseFilterBackend):
return queryset return queryset
if org_role == 'admins': if org_role == 'admins':
return queryset & current_org.get_org_admins() return queryset & (current_org.get_org_admins() | User.objects.filter(role=User.ROLE_ADMIN))
elif org_role == 'auditors': elif org_role == 'auditors':
return queryset & current_org.get_org_auditors() return queryset & current_org.get_org_auditors()
elif org_role == 'users': elif org_role == 'users':

View File

@ -320,3 +320,9 @@ class UserUpdatePublicKeySerializer(serializers.ModelSerializer):
new_public_key = self.validated_data.get('public_key') new_public_key = self.validated_data.get('public_key')
instance.set_public_key(new_public_key) instance.set_public_key(new_public_key)
return instance return instance
class MiniUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'name', 'username']