未验证 提交 9126c778 编写于 作者: F fit2bot 提交者: GitHub

perf: 工单优化(审批人可以填写工单对应的授权规则名称) (#5468)

* perf: 工单优化(审批人可以填写工单对应的授权规则名称)

* perf: 工单优化(优化推荐的资产、应用、系统用户等逻辑)

* perf: 工单优化(优化工单邮件内容)

* perf: MethodSerializer优化(优化当Serializer不需要时, 默认可以不传递对应字段)
Co-authored-by: NBai <bugatti_it@163.com>
上级 0842553f
......@@ -18,22 +18,28 @@ class ApplicationSerializerMixin(serializers.Serializer):
attrs = MethodSerializer()
def get_attrs_serializer(self):
serializer_class = None
default_serializer = serializers.Serializer(read_only=True)
if isinstance(self.instance, models.Application):
instance_type = self.instance.type
serializer_class = type_serializer_classes_mapping.get(instance_type)
_type = self.instance.type
_category = self.instance.category
else:
request = self.context['request']
query_type = request.query_params.get('type')
query_category = request.query_params.get('category')
if query_type:
serializer_class = type_serializer_classes_mapping.get(query_type)
elif query_category:
serializer_class = category_serializer_classes_mapping.get(query_category)
if serializer_class is None:
serializer_class = serializers.Serializer
serializer = serializer_class()
_type = self.context['request'].query_params.get('type')
_category = self.context['request'].query_params.get('category')
if _type:
serializer_class = type_serializer_classes_mapping.get(_type)
elif _category:
serializer_class = category_serializer_classes_mapping.get(_category)
else:
serializer_class = default_serializer
if not serializer_class:
serializer_class = default_serializer
if isinstance(serializer_class, type):
serializer = serializer_class()
else:
serializer = serializer_class
return serializer
......
......@@ -113,16 +113,25 @@ class ReplayStorageSerializer(serializers.ModelSerializer):
return _meta
def get_meta_serializer(self):
serializer_class = None
query_type = self.context['request'].query_params.get('type')
if query_type:
serializer_class = replay_storage_type_serializer_classes_mapping.get(query_type)
default_serializer = serializers.Serializer(read_only=True)
if isinstance(self.instance, ReplayStorage):
instance_type = self.instance.type
serializer_class = replay_storage_type_serializer_classes_mapping.get(instance_type)
if serializer_class is None:
serializer_class = serializers.Serializer
serializer = serializer_class()
_type = self.instance.type
else:
_type = self.context['request'].query_params.get('type')
if _type:
serializer_class = replay_storage_type_serializer_classes_mapping.get(_type)
else:
serializer_class = default_serializer
if not serializer_class:
serializer_class = default_serializer
if isinstance(serializer_class, type):
serializer = serializer_class()
else:
serializer = serializer_class
return serializer
......@@ -187,14 +196,23 @@ class CommandStorageSerializer(serializers.ModelSerializer):
return _meta
def get_meta_serializer(self):
serializer_class = None
query_type = self.context['request'].query_params.get('type')
if query_type:
serializer_class = command_storage_type_serializer_classes_mapping.get(query_type)
default_serializer = serializers.Serializer(read_only=True)
if isinstance(self.instance, CommandStorage):
instance_type = self.instance.type
serializer_class = command_storage_type_serializer_classes_mapping.get(instance_type)
if serializer_class is None:
serializer_class = serializers.Serializer
serializer = serializer_class()
_type = self.instance.type
else:
_type = self.context['request'].query_params.get('type')
if _type:
serializer_class = command_storage_type_serializer_classes_mapping.get(_type)
else:
serializer_class = default_serializer
if not serializer_class:
serializer_class = default_serializer
if isinstance(serializer_class, type):
serializer = serializer_class()
else:
serializer = serializer_class
return serializer
......@@ -88,12 +88,13 @@ class Handler(BaseHandler):
apply_category = self.ticket.meta.get('apply_category')
apply_type = self.ticket.meta.get('apply_type')
approve_permission_name = self.ticket.meta.get('approve_permission_name', '')
approved_applications_id = self.ticket.meta.get('approve_applications', [])
approve_system_users_id = self.ticket.meta.get('approve_system_users', [])
approve_date_start = self.ticket.meta.get('approve_date_start')
approve_date_expired = self.ticket.meta.get('approve_date_expired')
permission_name = _('Created by ticket ({}) ({})'.format(
self.ticket.title, str(self.ticket.id)[:4])
permission_created_by = '{}:{}'.format(
str(self.ticket.__class__.__name__), str(self.ticket.id)
)
permission_comment = _(
'Created by the ticket, '
......@@ -101,18 +102,19 @@ class Handler(BaseHandler):
'ticket applicant: {}, '
'ticket processor: {}, '
'ticket ID: {}'
''.format(
self.ticket.title, self.ticket.applicant_display,
self.ticket.processor_display, str(self.ticket.id)
)
).format(
self.ticket.title,
self.ticket.applicant_display,
self.ticket.processor_display,
str(self.ticket.id)
)
permissions_data = {
'id': self.ticket.id,
'name': str(permission_name),
'name': approve_permission_name,
'category': apply_category,
'type': apply_type,
'comment': str(permission_comment),
'created_by': '{}:{}'.format(str(self.__class__.__name__), str(self.ticket.id)),
'created_by': permission_created_by,
'date_start': approve_date_start,
'date_expired': approve_date_expired,
}
......
......@@ -90,13 +90,14 @@ class Handler(BaseHandler):
if asset_permission:
return asset_permission
approve_permission_name = self.ticket.meta.get('approve_permission_name', )
approve_assets_id = self.ticket.meta.get('approve_assets', [])
approve_system_users_id = self.ticket.meta.get('approve_system_users', [])
approve_actions = self.ticket.meta.get('approve_actions', Action.NONE)
approve_date_start = self.ticket.meta.get('approve_date_start')
approve_date_expired = self.ticket.meta.get('approve_date_expired')
permission_name = _('Created by ticket ({}) ({})'.format(
self.ticket.title, str(self.ticket.id)[:4])
permission_created_by = '{}:{}'.format(
str(self.ticket.__class__.__name__), str(self.ticket.id)
)
permission_comment = _(
'Created by the ticket, '
......@@ -104,18 +105,18 @@ class Handler(BaseHandler):
'ticket applicant: {}, '
'ticket processor: {}, '
'ticket ID: {}'
''.format(
self.ticket.title,
self.ticket.applicant_display,
self.ticket.processor_display,
str(self.ticket.id)
)
).format(
self.ticket.title,
self.ticket.applicant_display,
self.ticket.processor_display,
str(self.ticket.id)
)
permission_data = {
'id': self.ticket.id,
'name': str(permission_name),
'comment': permission_comment,
'created_by': '{}:{}'.format(str(self.__class__.__name__), str(self.ticket.id)),
'name': approve_permission_name,
'comment': str(permission_comment),
'created_by': permission_created_by,
'actions': approve_actions,
'date_start': approve_date_start,
'date_expired': approve_date_expired,
......
......@@ -86,17 +86,17 @@ class BaseHandler(object):
{}: {},
{}: {},
{}: {},
{}: {},
{}: {}
'''.format(
_('Ticket title'), self.ticket.title,
_('Ticket type'), self.ticket.get_type_display(),
_('Ticket status'), self.ticket.get_status_display(),
_('Ticket action'), self.ticket.get_action_display(),
_('Ticket applicant'), self.ticket.applicant_display,
_('Ticket assignees'), self.ticket.assignees_display,
_('Ticket processor'), self.ticket.processor_display or _('No'),
_('Ticket action'), self.ticket.get_action_display(),
_('Ticket status'), self.ticket.get_status_display()
)
if self.ticket.status_closed:
basic_body += '''{}: {}'''.format(_('Ticket processor'), self.ticket.processor_display)
body = self.body_html_format.format(_("Ticket basic info"), basic_body)
return body
......
......@@ -29,5 +29,6 @@ type_serializer_classes_mapping = {
const.TicketTypeChoices.login_confirm.value: {
'default': login_confirm.LoginConfirmSerializer,
action_open: login_confirm.ApplySerializer,
action_approve: login_confirm.LoginConfirmSerializer(read_only=True),
}
}
from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
from django.db.models import Q
from perms.models import ApplicationPermission
from applications.models import Application
from applications.const import ApplicationCategoryChoices, ApplicationTypeChoices
from assets.models import SystemUser
from orgs.utils import tmp_to_org
from tickets.models import Ticket
from .common import DefaultPermissionName
__all__ = [
'ApplyApplicationSerializer', 'ApplySerializer', 'ApproveSerializer',
......@@ -47,6 +49,9 @@ class ApplySerializer(serializers.Serializer):
class ApproveSerializer(serializers.Serializer):
# 审批信息
approve_permission_name = serializers.CharField(
max_length=128, default=DefaultPermissionName(), label=_('Permission name')
)
approve_applications = serializers.ListField(
required=True, child=serializers.UUIDField(), label=_('Approve applications'),
allow_null=True
......@@ -72,6 +77,19 @@ class ApproveSerializer(serializers.Serializer):
required=True, label=_('Date expired'), allow_null=True
)
def validate_approve_permission_name(self, permission_name):
if not isinstance(self.root.instance, Ticket):
return permission_name
with tmp_to_org(self.root.instance.org_id):
already_exists = ApplicationPermission.objects.filter(name=permission_name).exists()
if not already_exists:
return permission_name
raise serializers.ValidationError(_(
'Permission named `{}` already exists'.format(permission_name)
))
def validate_approve_applications(self, approve_applications):
if not isinstance(self.root.instance, Ticket):
return []
......@@ -118,6 +136,9 @@ class ApplyApplicationSerializer(ApplySerializer, ApproveSerializer):
return []
apply_application_group = value.get('apply_application_group', [])
if not apply_application_group:
return []
apply_type = value.get('apply_type')
queries = Q()
for application in apply_application_group:
......@@ -133,8 +154,11 @@ class ApplyApplicationSerializer(ApplySerializer, ApproveSerializer):
if not isinstance(self.root.instance, Ticket):
return []
apply_type = value.get('apply_type')
apply_system_user_group = value.get('apply_system_user_group', [])
if not apply_system_user_group:
return []
apply_type = value.get('apply_type')
protocol = SystemUser.get_protocol_by_application_type(apply_type)
queries = Q()
for system_user in apply_system_user_group:
......
......@@ -2,9 +2,11 @@ from django.utils.translation import ugettext_lazy as _
from django.db.models import Q
from rest_framework import serializers
from perms.serializers import ActionsField
from perms.models import AssetPermission
from assets.models import Asset, SystemUser
from orgs.utils import tmp_to_org
from tickets.models import Ticket
from .common import DefaultPermissionName
__all__ = [
......@@ -44,6 +46,9 @@ class ApplySerializer(serializers.Serializer):
class ApproveSerializer(serializers.Serializer):
# 审批信息
approve_permission_name = serializers.CharField(
max_length=128, default=DefaultPermissionName(), label=_('Permission name')
)
approve_assets = serializers.ListField(
required=True, allow_null=True, child=serializers.UUIDField(), label=_('Approve assets')
)
......@@ -76,6 +81,19 @@ class ApproveSerializer(serializers.Serializer):
required=True, label=_('Date expired'), allow_null=True
)
def validate_approve_permission_name(self, permission_name):
if not isinstance(self.root.instance, Ticket):
return permission_name
with tmp_to_org(self.root.instance.org_id):
already_exists = AssetPermission.objects.filter(name=permission_name).exists()
if not already_exists:
return permission_name
raise serializers.ValidationError(_(
'Permission named `{}` already exists'.format(permission_name)
))
def validate_approve_assets(self, approve_assets):
if not isinstance(self.root.instance, Ticket):
return []
......@@ -118,10 +136,13 @@ class ApplyAssetSerializer(ApplySerializer, ApproveSerializer):
apply_ip_group = value.get('apply_ip_group', [])
apply_hostname_group = value.get('apply_hostname_group', [])
queries = Q(ip__in=apply_ip_group)
queries = Q()
if apply_ip_group:
queries |= Q(ip__in=apply_ip_group)
for hostname in apply_hostname_group:
queries |= Q(hostname__icontains=hostname)
if not queries:
return []
with tmp_to_org(self.root.instance.org_id):
assets_id = Asset.objects.filter(queries).values_list('id', flat=True)[:5]
assets_id = [str(asset_id) for asset_id in assets_id]
......@@ -132,6 +153,9 @@ class ApplyAssetSerializer(ApplySerializer, ApproveSerializer):
return []
apply_system_user_group = value.get('apply_system_user_group', [])
if not apply_system_user_group:
return []
queries = Q()
for system_user in apply_system_user_group:
queries |= Q(username__icontains=system_user)
......
from django.utils.translation import ugettext as _
from tickets.models import Ticket
__all__ = ['DefaultPermissionName', 'get_default_permission_name']
def get_default_permission_name(ticket):
name = ''
if isinstance(ticket, Ticket):
name = _('Created by ticket ({}-{})').format(ticket.title, str(ticket.id)[:4])
return name
class DefaultPermissionName(object):
default = None
@staticmethod
def _construct_default_permission_name(serializer_field):
permission_name = ''
ticket = serializer_field.root.instance
if isinstance(ticket, Ticket):
permission_name = get_default_permission_name(ticket)
return permission_name
def set_context(self, serializer_field):
self.default = self._construct_default_permission_name(serializer_field)
def __call__(self):
return self.default
......@@ -38,31 +38,34 @@ class TicketSerializer(OrgResourceModelSerializerMixin):
]
def get_meta_serializer(self):
request = self.context['request']
default_serializer_class = serializers.Serializer
default_serializer = serializers.Serializer(read_only=True)
if isinstance(self.instance, Ticket):
_type = self.instance.type
else:
_type = request.query_params.get('type')
if not _type:
return default_serializer_class()
action_serializer_classes_mapping = type_serializer_classes_mapping.get(_type)
if not action_serializer_classes_mapping:
return default_serializer_class()
_type = self.context['request'].query_params.get('type')
if _type:
action_serializer_classes_mapping = type_serializer_classes_mapping.get(_type)
if action_serializer_classes_mapping:
query_action = self.context['request'].query_params.get('action')
action = query_action if query_action else self.context['view'].action
serializer_class = action_serializer_classes_mapping.get(action)
if not serializer_class:
serializer_class = action_serializer_classes_mapping.get('default')
else:
serializer_class = default_serializer
else:
serializer_class = default_serializer
query_action = request.query_params.get('action')
_action = query_action if query_action else self.context['view'].action
serializer_class = action_serializer_classes_mapping.get(_action)
if serializer_class:
return serializer_class()
if not serializer_class:
serializer_class = default_serializer
serializer_class = action_serializer_classes_mapping.get('default')
if serializer_class:
return serializer_class()
if isinstance(serializer_class, type):
serializer = serializer_class()
else:
serializer = serializer_class
return default_serializer_class()
return serializer
class TicketDisplaySerializer(TicketSerializer):
......
......@@ -10,6 +10,20 @@ from . import const
logger = get_logger(__file__)
EMAIL_TEMPLATE = '''
<div>
<p>
{title}
<a href={ticket_detail_url}>
<strong>{ticket_detail_url_description}</strong>
</a>
</p>
<div>
{body}
</div>
</div>
'''
def send_ticket_applied_mail_to_assignees(ticket):
if not ticket.assignees:
......@@ -18,22 +32,13 @@ def send_ticket_applied_mail_to_assignees(ticket):
)
return
subject = _('New Ticket: {} ({})'.format(ticket.title, ticket.get_type_display()))
ticket_detail_url = urljoin(
settings.SITE_URL, const.TICKET_DETAIL_URL.format(id=str(ticket.id))
)
message = """
<div>
<p>{title} <a href={ticket_detail_url}>{ticket_detail_url_description}</a></p>
<div>
{body}
</div>
</div>
""".format(
title=_('Your has a new ticket, from applicant - {}').format(str(ticket.applicant)),
ticket_detail_url=ticket_detail_url,
ticket_detail_url_description=_('click here to review'),
body=ticket.body.replace('\n', '<br/>'),
ticket_detail_url = urljoin(settings.SITE_URL, const.TICKET_DETAIL_URL.format(id=str(ticket.id)))
subject = _('New Ticket - {} ({})').format(ticket.title, ticket.get_type_display())
message = EMAIL_TEMPLATE.format(
title=_('Your has a new ticket, applicant - {}').format(str(ticket.applicant_display)),
ticket_detail_url=ticket_detail_url,
ticket_detail_url_description=_('click here to review'),
body=ticket.body.replace('\n', '<br/>'),
)
if settings.DEBUG:
logger.debug(message)
......@@ -45,18 +50,15 @@ def send_ticket_processed_mail_to_applicant(ticket):
if not ticket.applicant:
logger.error("Not found applicant: {}({})".format(ticket.title, ticket.id))
return
subject = _('Ticket has processed: {} ({})').format(ticket.title, ticket.processor_display)
message = """
<div>
<p>{title}</p>
<div>
{body}
</div>
</div>
""".format(
title=_('Your ticket has been ({}) processed').format(ticket.processor_display),
body=ticket.body.replace('\n', '<br/>'),
)
ticket_detail_url = urljoin(settings.SITE_URL, const.TICKET_DETAIL_URL.format(id=str(ticket.id)))
subject = _('Ticket has processed - {} ({})').format(ticket.title, ticket.processor_display)
message = EMAIL_TEMPLATE.format(
title=_('Your ticket has been processed, processor - {}').format(ticket.processor_display),
ticket_detail_url=ticket_detail_url,
ticket_detail_url_description=_('click here to review'),
body=ticket.body.replace('\n', '<br/>'),
)
if settings.DEBUG:
logger.debug(message)
recipient_list = [ticket.applicant.email]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册