diff --git a/apps/tickets/filters.py b/apps/tickets/filters.py index 255908305..bf20014cc 100644 --- a/apps/tickets/filters.py +++ b/apps/tickets/filters.py @@ -1,8 +1,10 @@ from django_filters import rest_framework as filters +from django.db.models import Subquery, OuterRef + from common.drf.filters import BaseFilterSet from tickets.models import ( - Ticket, ApplyAssetTicket, ApplyApplicationTicket, + Ticket, TicketStep, ApplyAssetTicket, ApplyApplicationTicket, ApplyLoginTicket, ApplyLoginAssetTicket, ApplyCommandTicket ) @@ -17,7 +19,13 @@ class TicketFilter(BaseFilterSet): ) def filter_assignees_id(self, queryset, name, value): - return queryset.filter(ticket_steps__ticket_assignees__assignee__id=value) + step_qs = TicketStep.objects.filter( + level=OuterRef("approval_step") + ).values_list('id', flat=True) + return queryset.filter( + ticket_steps__id__in=Subquery(step_qs), + ticket_steps__ticket_assignees__assignee__id=value + ) class ApplyAssetTicketFilter(BaseFilterSet): diff --git a/apps/tickets/handlers/base.py b/apps/tickets/handlers/base.py index 308f9f914..6165d035b 100644 --- a/apps/tickets/handlers/base.py +++ b/apps/tickets/handlers/base.py @@ -55,10 +55,7 @@ class BaseHandler: def _send_processed_mail_to_applicant(self, step=None): applicant = self.ticket.applicant - if self.ticket.status == TicketStatus.closed: - processor = applicant - else: - processor = step.processor if step else self.ticket.processor + processor = step.processor if step else applicant logger.debug('Send processed mail to applicant: {}'.format(applicant)) send_ticket_processed_mail_to_applicant(self.ticket, processor) diff --git a/apps/tickets/models/ticket/general.py b/apps/tickets/models/ticket/general.py index 2e8f1d886..c87b3aa7f 100644 --- a/apps/tickets/models/ticket/general.py +++ b/apps/tickets/models/ticket/general.py @@ -13,6 +13,7 @@ from common.utils.timezone import as_current_tz from common.mixins.models import CommonModelMixin from common.db.encoder import ModelJSONFieldEncoder from orgs.models import Organization +from orgs.utils import tmp_to_org from tickets.const import ( TicketType, TicketStatus, TicketState, TicketLevel, StepState, StepStatus @@ -336,14 +337,15 @@ class Ticket(StatusMixin, CommonModelMixin): m2m_fields.add(name) snapshot = {} - for field in rel_fields: - value = getattr(self, field) + with tmp_to_org(self.org_id): + for field in rel_fields: + value = getattr(self, field) - if field in m2m_fields: - value = [str(v) for v in value.all()] - else: - value = str(value) if value else '' - snapshot[field] = value + if field in m2m_fields: + value = [str(v) for v in value.all()] + else: + value = str(value) if value else '' + snapshot[field] = value self.rel_snapshot.update(snapshot) if save: diff --git a/apps/tickets/models/ticket/login_confirm.py b/apps/tickets/models/ticket/login_confirm.py index 89fb32e94..ee9d9fa80 100644 --- a/apps/tickets/models/ticket/login_confirm.py +++ b/apps/tickets/models/ticket/login_confirm.py @@ -1,7 +1,7 @@ from django.db import models from django.utils.translation import gettext_lazy as _ -from .general import Ticket, SubTicketManager +from .general import Ticket __all__ = ['ApplyLoginTicket'] diff --git a/apps/tickets/serializers/ticket/apply_application.py b/apps/tickets/serializers/ticket/apply_application.py index 1b5165bbd..700f7b45e 100644 --- a/apps/tickets/serializers/ticket/apply_application.py +++ b/apps/tickets/serializers/ticket/apply_application.py @@ -23,7 +23,9 @@ class ApplyApplicationSerializer(BaseApplyAssetApplicationSerializer, TicketAppl fields = TicketApplySerializer.Meta.fields + writeable_fields + ['apply_permission_name'] read_only_fields = list(set(fields) - set(writeable_fields)) ticket_extra_kwargs = TicketApplySerializer.Meta.extra_kwargs - extra_kwargs = {} + extra_kwargs = { + 'apply_system_users': {'required': True}, + } extra_kwargs.update(ticket_extra_kwargs) def validate_apply_applications(self, applications): diff --git a/apps/tickets/serializers/ticket/apply_asset.py b/apps/tickets/serializers/ticket/apply_asset.py index fe54eadeb..c32de52c1 100644 --- a/apps/tickets/serializers/ticket/apply_asset.py +++ b/apps/tickets/serializers/ticket/apply_asset.py @@ -31,7 +31,8 @@ class ApplyAssetSerializer(BaseApplyAssetApplicationSerializer, TicketApplySeria ticket_extra_kwargs = TicketApplySerializer.Meta.extra_kwargs extra_kwargs = { 'apply_nodes': {'required': False, 'help_text': asset_or_node_help_text}, - 'apply_assets': {'required': False, 'help_text': asset_or_node_help_text} + 'apply_assets': {'required': False, 'help_text': asset_or_node_help_text}, + 'apply_system_users': {'required': True}, } extra_kwargs.update(ticket_extra_kwargs) diff --git a/apps/tickets/views/approve.py b/apps/tickets/views/approve.py index 5be230f0a..f5f20e3d9 100644 --- a/apps/tickets/views/approve.py +++ b/apps/tickets/views/approve.py @@ -7,11 +7,17 @@ from django.shortcuts import redirect, reverse from django.core.cache import cache from django.utils.translation import ugettext as _ -from tickets.models import Ticket +from orgs.utils import tmp_to_root_org +from tickets.models import ( + Ticket, ApplyAssetTicket, ApplyApplicationTicket, + ApplyLoginTicket, ApplyLoginAssetTicket, ApplyCommandTicket +) +from tickets.const import TicketType from tickets.errors import AlreadyClosed from common.utils import get_logger, FlashMessageUtil logger = get_logger(__name__) + __all__ = ['TicketDirectApproveView'] @@ -19,6 +25,14 @@ class TicketDirectApproveView(TemplateView): template_name = 'tickets/approve_check_password.html' redirect_field_name = 'next' + TICKET_SUB_MODEL_MAP = { + TicketType.apply_asset: ApplyAssetTicket, + TicketType.apply_application: ApplyApplicationTicket, + TicketType.login_confirm: ApplyLoginTicket, + TicketType.login_asset_confirm: ApplyLoginAssetTicket, + TicketType.command_confirm: ApplyCommandTicket, + } + @property def message_data(self): return { @@ -84,7 +98,10 @@ class TicketDirectApproveView(TemplateView): return self.redirect_message_response(redirect_url=self.login_url) try: ticket_id = ticket_info.get('ticket_id') - ticket = Ticket.all().get(id=ticket_id) + with tmp_to_root_org(): + ticket = Ticket.all().get(id=ticket_id) + ticket_sub_model = self.TICKET_SUB_MODEL_MAP[ticket.type] + ticket = ticket_sub_model.objects.get(id=ticket_id) if not ticket.has_current_assignee(user): raise Exception(_("This user is not authorized to approve this ticket")) getattr(ticket, action)(user)