Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.7.0 版本准备 #1412

Merged
merged 9 commits into from
Sep 26, 2024
10 changes: 9 additions & 1 deletion docs/RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Changelog
## [Version: 2.7.0] - 2024-08-29
【新增】通知人员黑名单过滤
【优化】esb鉴权信息迁移到header,支持版本 open-paas/esb >= 2.12.20
【优化】导航栏中“我的经办”改为“我的已办”
【优化】流程中新增【审批节点】时调整默认项
Expand All @@ -8,7 +9,14 @@
【修复】修复单据列表在非首页搜索报错的问题
【修复】任务模板编辑点击上一步返回路径优化
【修复】tooltips组件XSS问题修复
【修复】修复部分模块鉴权异常的问题
【修复】修复部分模块鉴权异常的问题
【修复】修复 APM 部署无数据问题
【修复】修复部分模块鉴权异常的问题
【修复】修复服务可见范围未生效的问题
【修复】修复工单评论父级评论显示异常的问题
【修复】修复运营分析结束时间不准确的问题
【修复】修复并行网关死锁问题


## [Version: 2.6.30] - 2024-08-15
【修复】项目初始化时登录后重定向url异常修复
Expand Down
7 changes: 7 additions & 0 deletions docs/RELEASE_EN.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Changelog
## [Version: 2.7.0] - 2024-08-29
【Feature】Notification recipient blacklist filtering.
【Improved】Migrated the authentication information to header when calling esb, support open-paas/esb >= 2.12.20
【Improved】Adjust default items when adding an Approval Node in the process.
【Fixed】The navigation bar style has been standardized according to the design specifications.
Expand All @@ -8,6 +9,12 @@
【Fixed】Optimized the return path when clicking ‘Previous’ during task template editing.
【Fixed】Fixed XSS vulnerability in tooltips component.
【Fixed】Fix the issue with authentication anomalies in certain modules.
【Fixed】Resolved the issue of APM deployment without data.
【Fixed】Resolved authentication exceptions in some modules.
【Fixed】Resolved the issue where the service visibility range was not effective.
【Fixed】Resolved the issue of abnormal display of parent comments in the work order comments.
【Fixed】Resolved the issue of inaccurate end time in operation analysis.
【Fixed】Resolved the deadlock issue in the parallel gateway.


## [Version: 2.6.30] - 2024-08-15
Expand Down
2 changes: 1 addition & 1 deletion itsm/component/drf/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def perform_create(self, serializer):

user = serializer.context.get('request').user
username = getattr(user, 'username', 'guest')
serializer.save(creator=username, updated_by=username)
return serializer.save(creator=username, updated_by=username)

def perform_update(self, serializer):
"""更新时补充基础Model中的字段
Expand Down
8 changes: 4 additions & 4 deletions itsm/component/generics.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,12 @@ def exception_handler(exc, context):
else:
# 调试模式
logger.error(traceback.format_exc())
print(traceback.format_exc())
if settings.RUN_MODE != 'PRODUCT':
raise exc
# 正式环境,屏蔽500
data.update(
{'code': ResponseCodeStatus.SERVER_500_ERROR, 'message': exc.message, }
{
'code': ResponseCodeStatus.SERVER_500_ERROR,
'message': getattr(exc, "message", str(exc))
}
)

return Response(data, status=status.HTTP_200_OK)
3 changes: 2 additions & 1 deletion itsm/ticket/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,8 @@ def create_log(
to_state_id=to_state_id,
)

ticket.set_history_operators(log_operator)
from itsm.ticket.tasks import ticket_set_history_operators
ticket_set_history_operators.delay(ticket.id, log_operator)

return log

Expand Down
12 changes: 2 additions & 10 deletions itsm/ticket/models/ticket.py
Original file line number Diff line number Diff line change
Expand Up @@ -3828,14 +3828,6 @@ def _formatted(processors_type, processors):
slave.current_processors = node_processors
bulk_update(slaves, update_fields=["current_processors"])

def set_history_operators(self, current_operator):
"""设置历史处理人"""
history_operators = [user for user in self.updated_by.split(",") if user]
if current_operator not in history_operators:
history_operators.append(current_operator)
self.updated_by = dotted_name(",".join(set(history_operators)))
self.save(update_fields=("updated_by",))

def do_in_sign_state(self, node_status, fields, operator, source):
"""
In sign node action
Expand Down Expand Up @@ -3904,8 +3896,8 @@ def do_in_sign_state(self, node_status, fields, operator, source):

# Update ticket priority, processors, history operators
self.update_priority()
# self.set_current_processors()
self.set_history_operators(operator)
from itsm.ticket.tasks import ticket_set_history_operators
ticket_set_history_operators.delay(self.id, operator)

# Update sla task
# if self._sla_tasks:
Expand Down
16 changes: 16 additions & 0 deletions itsm/ticket/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
import operator
from functools import reduce

from django.utils.translation import ugettext as _
from django.conf import settings
Expand Down Expand Up @@ -60,6 +62,20 @@ class TicketPermissionValidate(permissions.BasePermission):

def __init__(self):
self.message = _("抱歉,您无权查看该单据")

def has_permission(self, request, view):
"""工单创建权限"""
if view.action != "create":
return True

service_id = request.data.get("service_id")
if not service_id:
return False

queryset = Service.objects.filter(pk=service_id, is_valid=True)
conditions = Service.permission_filter(request.user.username)
queryset = queryset.filter(reduce(operator.or_, conditions))
return queryset.exists()

def has_object_permission(self, request, view, obj):

Expand Down
14 changes: 13 additions & 1 deletion itsm/ticket/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from celery.schedules import crontab
from celery.task import periodic_task, task
from django.db.models import Q
from django.db import connection
from django.db import connection, transaction
from django.utils.translation import ugettext as _

from common.log import logger
Expand Down Expand Up @@ -519,3 +519,15 @@ def consume_notify():
for item in range(1, end):
user = email_notify.lpop("notify_queue")
send_message(user, queryset)


@task
def ticket_set_history_operators(ticket_id, current_operator):
"""设置历史处理人"""
with transaction.atomic():
ticket = Ticket.objects.select_for_update().get(pk=ticket_id)
history_operators = [user for user in ticket.updated_by.split(",") if user]
if current_operator not in history_operators:
history_operators.append(current_operator)
ticket.updated_by = dotted_name(",".join(set(history_operators)))
ticket.save(update_fields=("updated_by",))
3 changes: 3 additions & 0 deletions itsm/ticket/views/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class CommentViewSet(component_viewsets.NormalModelViewSet):
"stars": ["exact"],
}
ordering_fields = "__all__"

def list(self, request, *args, **kwargs):
return Response()

@action(detail=False, methods=["get"])
def get_comment(self, request):
Expand Down
21 changes: 14 additions & 7 deletions itsm/ticket/views/operational.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""

from datetime import datetime, timedelta
from datetime import datetime, timedelta, time
from functools import reduce

from django.db import connection
Expand Down Expand Up @@ -231,7 +231,7 @@ def service_statistics(self, request):
project_key = request.query_params.get("project_key", None)
filter_serializer = StatisticsSerializer(data=request.query_params)
filter_serializer.is_valid(raise_exception=True)
kwargs = filter_serializer.validated_data
kwargs = self.combine_date(filter_serializer.validated_data)

services = Service.objects.filter()
service_name = kwargs.pop("service_name", "")
Expand Down Expand Up @@ -292,7 +292,7 @@ def biz_statistics(self, request):
project_key = request.query_params.get("project_key", None)
filter_serializer = StatisticsSerializer(data=request.query_params)
filter_serializer.is_valid(raise_exception=True)
kwargs = filter_serializer.validated_data
kwargs = self.combine_date(filter_serializer.validated_data)
biz_id = kwargs.pop("biz_id", "")
biz_names = get_biz_names()
order = kwargs.pop("order_by")
Expand Down Expand Up @@ -328,7 +328,7 @@ def category_statistics(self, request):
project_key = request.query_params.get("project_key", None)
filter_serializer = StatisticsSerializer(data=request.query_params)
filter_serializer.is_valid(raise_exception=True)
kwargs = filter_serializer.validated_data
kwargs = self.combine_date(filter_serializer.validated_data)
order = kwargs.pop("order_by")
service_category = ServiceCategory.objects.all().values("key", "name")
category_dict = {
Expand Down Expand Up @@ -358,7 +358,7 @@ def status_statistics(self, request):
project_key = request.query_params.get("project_key", None)
filter_serializer = BaseFilterSerializer(data=request.query_params)
filter_serializer.is_valid(raise_exception=True)
kwargs = filter_serializer.validated_data
kwargs = self.combine_date(filter_serializer.validated_data)
not_running_status = ["FINISHED", "TERMINATED", "REVOKED"]
ticket_info = (
self.queryset.filter(**kwargs)
Expand Down Expand Up @@ -431,7 +431,7 @@ def top_creator_statistics(self, request):
project_key = request.query_params.get("project_key", None)
filter_serializer = ServiceStatisticsFilterSerializer(data=request.query_params)
filter_serializer.is_valid(raise_exception=True)
kwargs = filter_serializer.validated_data
kwargs = self.combine_date(filter_serializer.validated_data)
kwargs.pop("timedelta")
max_ids = (
TicketOrganization.objects.filter(
Expand Down Expand Up @@ -481,7 +481,8 @@ def top_creator_statistics(self, request):
def distribute_statistics(self, request):
filter_serializer = TicketOrganizationSerializer(data=request.query_params)
filter_serializer.is_valid(raise_exception=True)
kwargs = filter_serializer.validated_data
kwargs = self.combine_date(filter_serializer.validated_data)

level_dict = {
1: ("first_level_id", "first_level_name"),
2: ("second_level_id", "second_level_name"),
Expand Down Expand Up @@ -1161,3 +1162,9 @@ def new_tickets(self, request, *args, **kwargs):

filter_result.sort(key=lambda x: x["day"])
return Response(filter_result)

@staticmethod
def combine_date(kwargs):
if kwargs.get("create_at__lte"):
kwargs["create_at__lte"] = datetime.combine(kwargs["create_at__lte"], time(23, 59, 59))
return kwargs
2 changes: 1 addition & 1 deletion itsm/ticket/views/ticket.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ def send_email(self, request, *args, **kwargs):
}
)
except ComponentCallError as error:
logger.warning("send email execption: %s" % error)
logger.warning(f"[send email] ticket_url=>{ticket_url}, execption=>{error}")
return Response(
{
"result": False,
Expand Down
32 changes: 14 additions & 18 deletions itsm/ticket/views/ticket_remark.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,16 @@
# -*- coding: utf-8 -*-
from django.http import Http404
from django.utils.translation import ugettext as _
from rest_framework.decorators import action
from rest_framework.response import Response

from itsm.component.drf import viewsets as component_viewsets
from itsm.component.drf.viewsets import ModelViewSet
from itsm.component.exceptions import ValidateError
from itsm.ticket.models import TicketRemark, Ticket
from itsm.ticket.permissions import RemarkPermissionValidate
from itsm.ticket.serializers import TicketRemarkSerializer


class ModelViewSet(component_viewsets.ModelViewSet):
"""按需改造DRF默认的ModelViewSet类"""

def perform_create(self, serializer):
"""创建时补充基础Model中的字段"""
user = serializer.context.get("request").user
username = getattr(user, "username", "guest")
return serializer.save(creator=username, updated_by=username)

def perform_update(self, serializer):
"""更新时补充基础Model中的字段"""
user = serializer.context.get("request").user
username = getattr(user, "username", "guest")
serializer.save(updated_by=username)


class TicketRemarkModelViewSet(ModelViewSet):
queryset = TicketRemark.objects.filter(is_deleted=False).order_by(
"-create_at", "level"
Expand All @@ -34,6 +21,8 @@ class TicketRemarkModelViewSet(ModelViewSet):
def list(self, request, *args, **kwargs):
# 后面这个接口要重构一部分
ticket_id = request.query_params.get("ticket_id", "")
if not ticket_id:
raise ValidateError(_("ticket_id 不能为空"))
show_type = request.query_params.get("show_type", "PUBLIC")

ticket = Ticket.objects.get(id=ticket_id)
Expand All @@ -59,7 +48,14 @@ def list(self, request, *args, **kwargs):
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)


def retrieve(self, request, *args, **kwargs):
try:
return super().retrieve(request, *args, **kwargs)
except Http404:
"""兼容父级评论删除情况"""
return Response([])

@action(detail=False, methods=["get"])
def tree_view(self, request):
"""评论视图"""
Expand Down
2 changes: 1 addition & 1 deletion itsm/workflow/models/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ def get_state_fields(self, state_id):
state = self.get_state(state_id)
all_fields = map(lambda field_id: self.get_field(field_id), state["fields"])

return list(filter(lambda f: f["is_valid"], all_fields))
return list(filter(lambda f: f and f["is_valid"], all_fields))

def get_first_state_fields(self):
return self.get_state_fields(self.first_state["id"])
Expand Down
8 changes: 5 additions & 3 deletions pipeline/engine/models/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,9 +496,11 @@ def destroy_and_wake_up_parent(self, destination_id):
data_service.set_object(self._context_key(), self.top_pipeline.context)
data_service.set_object(self._data_key(), self.top_pipeline.data)

self.__class__.objects.filter(id=self.parent_id).update(
ack_num=models.F("ack_num") + 1
)
with transaction.atomic():
parent = self.__class__.objects.select_for_update().get(id=self.parent_id)
parent.ack_num += 1
parent.save()

can_wake_up = False

with transaction.atomic():
Expand Down
Loading