mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-09-25 06:42:49 +00:00
feat: 工单多级审批 + 模版创建 (#6640)
* feat: 工单多级审批 + 模版创建 * feat: 工单权限处理 * fix: 工单关闭后 再审批bug * perf: 修改一点 Co-authored-by: feng626 <1304903146@qq.com> Co-authored-by: ibuler <ibuler@qq.com>
This commit is contained in:
@@ -26,7 +26,7 @@ class CommentSerializer(serializers.ModelSerializer):
|
||||
'body', 'user_display',
|
||||
'date_created', 'date_updated'
|
||||
]
|
||||
fields_fk = ['ticket', 'user',]
|
||||
fields_fk = ['ticket', 'user', ]
|
||||
fields = fields_small + fields_fk
|
||||
read_only_fields = [
|
||||
'user_display', 'date_created', 'date_updated'
|
||||
|
@@ -1,6 +1,7 @@
|
||||
from tickets import const
|
||||
from .ticket_type import (
|
||||
apply_asset, apply_application, login_confirm, login_asset_confirm, command_confirm
|
||||
apply_asset, apply_application, login_confirm,
|
||||
login_asset_confirm, command_confirm
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
@@ -10,35 +11,31 @@ __all__ = [
|
||||
# ticket action
|
||||
# -------------
|
||||
|
||||
action_open = const.TicketActionChoices.open.value
|
||||
action_approve = const.TicketActionChoices.approve.value
|
||||
action_open = const.TicketAction.open.value
|
||||
action_approve = const.TicketAction.approve.value
|
||||
|
||||
|
||||
# defines `meta` field dynamic mapping serializers
|
||||
# ------------------------------------------------
|
||||
|
||||
type_serializer_classes_mapping = {
|
||||
const.TicketTypeChoices.apply_asset.value: {
|
||||
'default': apply_asset.ApplyAssetSerializer,
|
||||
action_open: apply_asset.ApplySerializer,
|
||||
action_approve: apply_asset.ApproveSerializer,
|
||||
const.TicketType.apply_asset.value: {
|
||||
'default': apply_asset.ApplySerializer
|
||||
},
|
||||
const.TicketTypeChoices.apply_application.value: {
|
||||
'default': apply_application.ApplyApplicationSerializer,
|
||||
action_open: apply_application.ApplySerializer,
|
||||
action_approve: apply_application.ApproveSerializer,
|
||||
const.TicketType.apply_application.value: {
|
||||
'default': apply_application.ApplySerializer
|
||||
},
|
||||
const.TicketTypeChoices.login_confirm.value: {
|
||||
const.TicketType.login_confirm.value: {
|
||||
'default': login_confirm.LoginConfirmSerializer,
|
||||
action_open: login_confirm.ApplySerializer,
|
||||
action_approve: login_confirm.LoginConfirmSerializer(read_only=True),
|
||||
},
|
||||
const.TicketTypeChoices.login_asset_confirm.value: {
|
||||
const.TicketType.login_asset_confirm.value: {
|
||||
'default': login_asset_confirm.LoginAssetConfirmSerializer,
|
||||
action_open: login_asset_confirm.ApplySerializer,
|
||||
action_approve: login_asset_confirm.LoginAssetConfirmSerializer(read_only=True),
|
||||
},
|
||||
const.TicketTypeChoices.command_confirm.value: {
|
||||
const.TicketType.command_confirm.value: {
|
||||
'default': command_confirm.CommandConfirmSerializer,
|
||||
action_open: command_confirm.ApplySerializer,
|
||||
action_approve: command_confirm.CommandConfirmSerializer(read_only=True)
|
||||
|
@@ -1,20 +1,20 @@
|
||||
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 AppCategory, AppType
|
||||
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',
|
||||
'ApplySerializer',
|
||||
]
|
||||
|
||||
|
||||
class ApplySerializer(serializers.Serializer):
|
||||
apply_permission_name = serializers.CharField(
|
||||
max_length=128, default=DefaultPermissionName(), label=_('Apply name')
|
||||
)
|
||||
# 申请信息
|
||||
apply_category = serializers.ChoiceField(
|
||||
required=True, choices=AppCategory.choices, label=_('Category'),
|
||||
@@ -31,13 +31,23 @@ class ApplySerializer(serializers.Serializer):
|
||||
required=False, read_only=True, label=_('Type display'),
|
||||
allow_null=True
|
||||
)
|
||||
apply_application_group = serializers.ListField(
|
||||
required=False, child=serializers.CharField(), label=_('Application group'),
|
||||
default=list, allow_null=True
|
||||
apply_applications = serializers.ListField(
|
||||
required=True, child=serializers.UUIDField(), label=_('Apply applications'),
|
||||
allow_null=True
|
||||
)
|
||||
apply_system_user_group = serializers.ListField(
|
||||
required=False, child=serializers.CharField(), label=_('System user group'),
|
||||
default=list, allow_null=True
|
||||
apply_applications_display = serializers.ListField(
|
||||
required=False, read_only=True, child=serializers.CharField(),
|
||||
label=_('Apply applications display'), allow_null=True,
|
||||
default=list
|
||||
)
|
||||
apply_system_users = serializers.ListField(
|
||||
required=True, child=serializers.UUIDField(), label=_('Apply system users'),
|
||||
allow_null=True
|
||||
)
|
||||
apply_system_users_display = serializers.ListField(
|
||||
required=False, read_only=True, child=serializers.CharField(),
|
||||
label=_('Apply system user display'), allow_null=True,
|
||||
default=list
|
||||
)
|
||||
apply_date_start = serializers.DateTimeField(
|
||||
required=True, label=_('Date start'), allow_null=True
|
||||
@@ -46,37 +56,6 @@ class ApplySerializer(serializers.Serializer):
|
||||
required=True, label=_('Date expired'), allow_null=True
|
||||
)
|
||||
|
||||
|
||||
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
|
||||
)
|
||||
approve_applications_display = serializers.ListField(
|
||||
required=False, read_only=True, child=serializers.CharField(),
|
||||
label=_('Approve applications display'), allow_null=True,
|
||||
default=list
|
||||
)
|
||||
approve_system_users = serializers.ListField(
|
||||
required=True, child=serializers.UUIDField(), label=_('Approve system users'),
|
||||
allow_null=True
|
||||
)
|
||||
approve_system_users_display = serializers.ListField(
|
||||
required=False, read_only=True, child=serializers.CharField(),
|
||||
label=_('Approve system user display'), allow_null=True,
|
||||
default=list
|
||||
)
|
||||
approve_date_start = serializers.DateTimeField(
|
||||
required=True, label=_('Date start'), allow_null=True
|
||||
)
|
||||
approve_date_expired = serializers.DateTimeField(
|
||||
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
|
||||
@@ -90,83 +69,5 @@ class ApproveSerializer(serializers.Serializer):
|
||||
'Permission named `{}` already exists'.format(permission_name)
|
||||
))
|
||||
|
||||
def validate_approve_applications(self, approve_applications):
|
||||
if not isinstance(self.root.instance, Ticket):
|
||||
return []
|
||||
|
||||
with tmp_to_org(self.root.instance.org_id):
|
||||
apply_type = self.root.instance.meta.get('apply_type')
|
||||
queries = Q(type=apply_type)
|
||||
queries &= Q(id__in=approve_applications)
|
||||
application_ids = Application.objects.filter(queries).values_list('id', flat=True)
|
||||
application_ids = [str(application_id) for application_id in application_ids]
|
||||
if application_ids:
|
||||
return application_ids
|
||||
|
||||
raise serializers.ValidationError(_(
|
||||
'No `Application` are found under Organization `{}`'.format(self.root.instance.org_name)
|
||||
))
|
||||
|
||||
def validate_approve_system_users(self, approve_system_users):
|
||||
if not isinstance(self.root.instance, Ticket):
|
||||
return []
|
||||
|
||||
with tmp_to_org(self.root.instance.org_id):
|
||||
apply_type = self.root.instance.meta.get('apply_type')
|
||||
protocol = SystemUser.get_protocol_by_application_type(apply_type)
|
||||
queries = Q(protocol=protocol)
|
||||
queries &= Q(id__in=approve_system_users)
|
||||
system_user_ids = SystemUser.objects.filter(queries).values_list('id', flat=True)
|
||||
system_user_ids = [str(system_user_id) for system_user_id in system_user_ids]
|
||||
if system_user_ids:
|
||||
return system_user_ids
|
||||
|
||||
raise serializers.ValidationError(_(
|
||||
'No `SystemUser` are found under Organization `{}`'.format(self.root.instance.org_name)
|
||||
))
|
||||
|
||||
|
||||
class ApplyApplicationSerializer(ApplySerializer, ApproveSerializer):
|
||||
# 推荐信息
|
||||
recommend_applications = serializers.SerializerMethodField()
|
||||
recommend_system_users = serializers.SerializerMethodField()
|
||||
|
||||
def get_recommend_applications(self, value):
|
||||
if not isinstance(self.root.instance, Ticket):
|
||||
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:
|
||||
queries |= Q(name__icontains=application)
|
||||
queries &= Q(type=apply_type)
|
||||
|
||||
with tmp_to_org(self.root.instance.org_id):
|
||||
application_ids = Application.objects.filter(queries).values_list('id', flat=True)[:15]
|
||||
application_ids = [str(application_id) for application_id in application_ids]
|
||||
return application_ids
|
||||
|
||||
def get_recommend_system_users(self, value):
|
||||
if not isinstance(self.root.instance, Ticket):
|
||||
return []
|
||||
|
||||
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:
|
||||
queries |= Q(username__icontains=system_user)
|
||||
queries |= Q(name__icontains=system_user)
|
||||
queries &= Q(protocol=protocol)
|
||||
|
||||
with tmp_to_org(self.root.instance.org_id):
|
||||
system_user_ids = SystemUser.objects.filter(queries).values_list('id', flat=True)[:5]
|
||||
system_user_ids = [str(system_user_id) for system_user_id in system_user_ids]
|
||||
return system_user_ids
|
||||
|
@@ -1,39 +1,44 @@
|
||||
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__ = [
|
||||
'ApplyAssetSerializer', 'ApplySerializer', 'ApproveSerializer',
|
||||
'ApplySerializer',
|
||||
]
|
||||
|
||||
|
||||
class ApplySerializer(serializers.Serializer):
|
||||
apply_permission_name = serializers.CharField(
|
||||
max_length=128, default=DefaultPermissionName(), label=_('Apply name')
|
||||
)
|
||||
# 申请信息
|
||||
apply_ip_group = serializers.ListField(
|
||||
required=False, child=serializers.IPAddressField(), label=_('IP group'),
|
||||
default=list, allow_null=True,
|
||||
apply_assets = serializers.ListField(
|
||||
required=True, allow_null=True, child=serializers.UUIDField(), label=_('Apply assets')
|
||||
)
|
||||
apply_hostname_group = serializers.ListField(
|
||||
required=False, child=serializers.CharField(), label=_('Hostname group'),
|
||||
default=list, allow_null=True,
|
||||
apply_assets_display = serializers.ListField(
|
||||
required=False, read_only=True, child=serializers.CharField(),
|
||||
label=_('Approve assets display'), allow_null=True,
|
||||
default=list,
|
||||
)
|
||||
apply_system_user_group = serializers.ListField(
|
||||
required=False, child=serializers.CharField(), label=_('System user group'),
|
||||
default=list, allow_null=True
|
||||
apply_system_users = serializers.ListField(
|
||||
required=True, allow_null=True, child=serializers.UUIDField(),
|
||||
label=_('Approve system users')
|
||||
)
|
||||
apply_system_users_display = serializers.ListField(
|
||||
required=False, read_only=True, child=serializers.CharField(),
|
||||
label=_('Apply assets display'), allow_null=True,
|
||||
default=list,
|
||||
)
|
||||
apply_actions = ActionsField(
|
||||
required=True, allow_null=True
|
||||
)
|
||||
apply_actions_display = serializers.ListField(
|
||||
required=False, read_only=True, child=serializers.CharField(),
|
||||
label=_('Approve assets display'), allow_null=True,
|
||||
label=_('Apply assets display'), allow_null=True,
|
||||
default=list,
|
||||
)
|
||||
apply_date_start = serializers.DateTimeField(
|
||||
@@ -43,44 +48,6 @@ class ApplySerializer(serializers.Serializer):
|
||||
required=True, label=_('Date expired'), allow_null=True,
|
||||
)
|
||||
|
||||
|
||||
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')
|
||||
)
|
||||
approve_assets_display = serializers.ListField(
|
||||
required=False, read_only=True, child=serializers.CharField(),
|
||||
label=_('Approve assets display'), allow_null=True,
|
||||
default=list,
|
||||
)
|
||||
approve_system_users = serializers.ListField(
|
||||
required=True, allow_null=True, child=serializers.UUIDField(),
|
||||
label=_('Approve system users')
|
||||
)
|
||||
approve_system_users_display = serializers.ListField(
|
||||
required=False, read_only=True, child=serializers.CharField(),
|
||||
label=_('Approve assets display'), allow_null=True,
|
||||
default=list,
|
||||
)
|
||||
approve_actions = ActionsField(
|
||||
required=True, allow_null=True,
|
||||
)
|
||||
approve_actions_display = serializers.ListField(
|
||||
required=False, read_only=True, child=serializers.CharField(),
|
||||
label=_('Approve assets display'), allow_null=True,
|
||||
default=list,
|
||||
)
|
||||
approve_date_start = serializers.DateTimeField(
|
||||
required=True, label=_('Date start'), allow_null=True,
|
||||
)
|
||||
approve_date_expired = serializers.DateTimeField(
|
||||
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
|
||||
@@ -93,76 +60,3 @@ class ApproveSerializer(serializers.Serializer):
|
||||
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 []
|
||||
|
||||
with tmp_to_org(self.root.instance.org_id):
|
||||
asset_ids = Asset.objects.filter(id__in=approve_assets).values_list('id', flat=True)
|
||||
asset_ids = [str(asset_id) for asset_id in asset_ids]
|
||||
if asset_ids:
|
||||
return asset_ids
|
||||
|
||||
raise serializers.ValidationError(_(
|
||||
'No `Asset` are found under Organization `{}`'.format(self.root.instance.org_name)
|
||||
))
|
||||
|
||||
def validate_approve_system_users(self, approve_system_users):
|
||||
if not isinstance(self.root.instance, Ticket):
|
||||
return []
|
||||
|
||||
with tmp_to_org(self.root.instance.org_id):
|
||||
queries = Q(protocol__in=SystemUser.ASSET_CATEGORY_PROTOCOLS)
|
||||
queries &= Q(id__in=approve_system_users)
|
||||
system_user_ids = SystemUser.objects.filter(queries).values_list('id', flat=True)
|
||||
system_user_ids = [str(system_user_id) for system_user_id in system_user_ids]
|
||||
if system_user_ids:
|
||||
return system_user_ids
|
||||
|
||||
raise serializers.ValidationError(_(
|
||||
'No `SystemUser` are found under Organization `{}`'.format(self.root.instance.org_name)
|
||||
))
|
||||
|
||||
|
||||
class ApplyAssetSerializer(ApplySerializer, ApproveSerializer):
|
||||
# 推荐信息
|
||||
recommend_assets = serializers.SerializerMethodField()
|
||||
recommend_system_users = serializers.SerializerMethodField()
|
||||
|
||||
def get_recommend_assets(self, value):
|
||||
if not isinstance(self.root.instance, Ticket):
|
||||
return []
|
||||
|
||||
apply_ip_group = value.get('apply_ip_group', [])
|
||||
apply_hostname_group = value.get('apply_hostname_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):
|
||||
asset_ids = Asset.objects.filter(queries).values_list('id', flat=True)[:100]
|
||||
asset_ids = [str(asset_id) for asset_id in asset_ids]
|
||||
return asset_ids
|
||||
|
||||
def get_recommend_system_users(self, value):
|
||||
if not isinstance(self.root.instance, Ticket):
|
||||
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)
|
||||
queries |= Q(name__icontains=system_user)
|
||||
queries &= Q(protocol__in=SystemUser.ASSET_CATEGORY_PROTOCOLS)
|
||||
|
||||
with tmp_to_org(self.root.instance.org_id):
|
||||
system_user_ids = SystemUser.objects.filter(queries).values_list('id', flat=True)[:5]
|
||||
system_user_ids = [str(system_user_id) for system_user_id in system_user_ids]
|
||||
return system_user_ids
|
||||
|
@@ -1,43 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.db.transaction import atomic
|
||||
from rest_framework import serializers
|
||||
from common.drf.serializers import MethodSerializer
|
||||
from orgs.mixins.serializers import OrgResourceModelSerializerMixin
|
||||
from perms.models import AssetPermission
|
||||
from orgs.models import Organization
|
||||
from orgs.utils import tmp_to_org
|
||||
from users.models import User
|
||||
from tickets.models import Ticket
|
||||
from tickets.models import Ticket, TicketFlow, ApprovalRule
|
||||
from tickets.const import TicketApprovalStrategy
|
||||
from .meta import type_serializer_classes_mapping
|
||||
|
||||
|
||||
__all__ = [
|
||||
'TicketDisplaySerializer', 'TicketApplySerializer', 'TicketApproveSerializer',
|
||||
'TicketDisplaySerializer', 'TicketApplySerializer', 'TicketApproveSerializer', 'TicketFlowSerializer'
|
||||
]
|
||||
|
||||
|
||||
class TicketSerializer(OrgResourceModelSerializerMixin):
|
||||
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type display'))
|
||||
action_display = serializers.ReadOnlyField(
|
||||
source='get_action_display', label=_('Action display')
|
||||
)
|
||||
status_display = serializers.ReadOnlyField(
|
||||
source='get_status_display', label=_('Status display')
|
||||
)
|
||||
status_display = serializers.ReadOnlyField(source='get_status_display', label=_('Status display'))
|
||||
meta = MethodSerializer()
|
||||
|
||||
class Meta:
|
||||
model = Ticket
|
||||
fields_mini = ['id', 'title']
|
||||
fields_small = fields_mini + [
|
||||
'type', 'type_display', 'meta', 'body',
|
||||
'action', 'action_display', 'status', 'status_display',
|
||||
'applicant_display', 'processor_display', 'assignees_display',
|
||||
'date_created', 'date_updated',
|
||||
'comment', 'org_id', 'org_name',
|
||||
'type', 'type_display', 'meta', 'state', 'approval_step',
|
||||
'status', 'status_display', 'applicant_display', 'process_map',
|
||||
'date_created', 'date_updated', 'comment', 'org_id', 'org_name', 'body'
|
||||
]
|
||||
fields_fk = ['applicant', 'processor',]
|
||||
fields_m2m = ['assignees']
|
||||
fields = fields_small + fields_fk + fields_m2m
|
||||
fields_fk = ['applicant', ]
|
||||
fields = fields_small + fields_fk
|
||||
|
||||
def get_meta_serializer(self):
|
||||
default_serializer = serializers.Serializer(read_only=True)
|
||||
@@ -71,7 +66,6 @@ class TicketSerializer(OrgResourceModelSerializerMixin):
|
||||
|
||||
|
||||
class TicketDisplaySerializer(TicketSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Ticket
|
||||
fields = TicketSerializer.Meta.fields
|
||||
@@ -87,7 +81,7 @@ class TicketApplySerializer(TicketSerializer):
|
||||
model = Ticket
|
||||
fields = TicketSerializer.Meta.fields
|
||||
writeable_fields = [
|
||||
'id', 'title', 'type', 'meta', 'assignees', 'comment', 'org_id'
|
||||
'id', 'title', 'type', 'meta', 'comment', 'org_id'
|
||||
]
|
||||
read_only_fields = list(set(fields) - set(writeable_fields))
|
||||
extra_kwargs = {
|
||||
@@ -112,27 +106,115 @@ class TicketApplySerializer(TicketSerializer):
|
||||
raise serializers.ValidationError(error)
|
||||
return org_id
|
||||
|
||||
def validate_assignees(self, assignees):
|
||||
org_id = self.initial_data.get('org_id')
|
||||
self.validate_org_id(org_id)
|
||||
org = Organization.get_instance(org_id)
|
||||
admins = User.get_super_and_org_admins(org)
|
||||
valid_assignees = list(set(assignees) & set(admins))
|
||||
if not valid_assignees:
|
||||
error = _('None of the assignees belong to Organization `{}` admins'.format(org.name))
|
||||
def validate(self, attrs):
|
||||
ticket_type = attrs.get('type')
|
||||
flow = TicketFlow.get_org_related_flows().filter(type=ticket_type).first()
|
||||
if flow:
|
||||
attrs['flow'] = flow
|
||||
else:
|
||||
error = _('The ticket flow `{}` does not exist'.format(ticket_type))
|
||||
raise serializers.ValidationError(error)
|
||||
return valid_assignees
|
||||
return attrs
|
||||
|
||||
@atomic
|
||||
def create(self, validated_data):
|
||||
instance = super().create(validated_data)
|
||||
name = _('Created by ticket ({}-{})').format(instance.title, str(instance.id)[:4])
|
||||
with tmp_to_org(instance.org_id):
|
||||
if not AssetPermission.objects.filter(name=name).exists():
|
||||
instance.meta.update({'apply_permission_name': name})
|
||||
return instance
|
||||
raise serializers.ValidationError(_('Permission named `{}` already exists'.format(name)))
|
||||
|
||||
|
||||
class TicketApproveSerializer(TicketSerializer):
|
||||
meta = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = Ticket
|
||||
fields = TicketSerializer.Meta.fields
|
||||
writeable_fields = ['meta']
|
||||
read_only_fields = list(set(fields) - set(writeable_fields))
|
||||
read_only_fields = fields
|
||||
|
||||
def validate_meta(self, meta):
|
||||
_meta = self.instance.meta if self.instance else {}
|
||||
_meta.update(meta)
|
||||
return _meta
|
||||
|
||||
class TicketFlowApproveSerializer(serializers.ModelSerializer):
|
||||
strategy_display = serializers.ReadOnlyField(source='get_strategy_display', label=_('Approve strategy'))
|
||||
assignees_read_only = serializers.SerializerMethodField(label=_("Assignees"))
|
||||
|
||||
class Meta:
|
||||
model = ApprovalRule
|
||||
fields_small = [
|
||||
'level', 'strategy', 'assignees_read_only', 'assignees_display', 'strategy_display'
|
||||
]
|
||||
fields_m2m = ['assignees', ]
|
||||
fields = fields_small + fields_m2m
|
||||
read_only_fields = ['level', 'assignees_display']
|
||||
extra_kwargs = {
|
||||
'assignees': {'write_only': True, 'allow_empty': True}
|
||||
}
|
||||
|
||||
def get_assignees_read_only(self, obj):
|
||||
if obj.strategy == TicketApprovalStrategy.custom:
|
||||
return obj.assignees.values_list('id', flat=True)
|
||||
return []
|
||||
|
||||
|
||||
class TicketFlowSerializer(OrgResourceModelSerializerMixin):
|
||||
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type display'))
|
||||
rules = TicketFlowApproveSerializer(many=True, required=True)
|
||||
|
||||
class Meta:
|
||||
model = TicketFlow
|
||||
fields_mini = ['id', ]
|
||||
fields_small = fields_mini + [
|
||||
'type', 'type_display', 'approval_level', 'created_by', 'date_created', 'date_updated',
|
||||
'org_id', 'org_name'
|
||||
]
|
||||
fields = fields_small + ['rules', ]
|
||||
read_only_fields = ['created_by', 'org_id', 'date_created', 'date_updated']
|
||||
extra_kwargs = {
|
||||
'type': {'required': True},
|
||||
'approval_level': {'required': True}
|
||||
}
|
||||
|
||||
def validate_type(self, value):
|
||||
if not self.instance or (self.instance and self.instance.type != value):
|
||||
if self.Meta.model.objects.filter(type=value).exists():
|
||||
error = _('The current organization type already exists')
|
||||
raise serializers.ValidationError(error)
|
||||
return value
|
||||
|
||||
def create_or_update(self, action, validated_data, related, assignees, instance=None):
|
||||
childs = validated_data.pop(related, [])
|
||||
if not instance:
|
||||
instance = getattr(super(), action)(validated_data)
|
||||
else:
|
||||
instance = getattr(super(), action)(instance, validated_data)
|
||||
getattr(instance, related).all().delete()
|
||||
instance_related = getattr(instance, related)
|
||||
child_instances = []
|
||||
related_model = instance_related.model
|
||||
for level, data in enumerate(childs, 1):
|
||||
data_m2m = data.pop(assignees, None)
|
||||
child_instance = related_model.objects.create(**data, level=level)
|
||||
if child_instance.strategy == 'super':
|
||||
data_m2m = list(User.get_super_admins())
|
||||
elif child_instance.strategy == 'admin':
|
||||
data_m2m = list(User.get_org_admins())
|
||||
elif child_instance.strategy == 'super_admin':
|
||||
data_m2m = list(User.get_super_and_org_admins())
|
||||
getattr(child_instance, assignees).set(data_m2m)
|
||||
child_instances.append(child_instance)
|
||||
instance_related.set(child_instances)
|
||||
return instance
|
||||
|
||||
@atomic
|
||||
def create(self, validated_data):
|
||||
return self.create_or_update('create', validated_data, 'rules', 'assignees')
|
||||
|
||||
@atomic
|
||||
def update(self, instance, validated_data):
|
||||
if instance.org_id == Organization.ROOT_ID:
|
||||
instance = self.create(validated_data)
|
||||
else:
|
||||
instance = self.create_or_update('update', validated_data, 'rules', 'assignees', instance)
|
||||
return instance
|
||||
|
Reference in New Issue
Block a user