From c6229c957e945e9926056f8c68e451ab1c33465e Mon Sep 17 00:00:00 2001 From: v_wmcowen Date: Fri, 6 Dec 2024 15:25:36 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0ITSM=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E9=85=8D=E7=BD=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pre-commit-config.yaml | 7 --- common/utils.py | 14 +++--- config/default.py | 19 ++++---- itsm/component/bkchat/utils.py | 20 +++++++-- itsm/meta/__init__.py | 0 itsm/meta/admin.py | 11 +++++ itsm/meta/apps.py | 6 +++ itsm/meta/migrations/0001_initial.py | 34 ++++++++++++++ itsm/meta/migrations/__init__.py | 0 itsm/meta/models.py | 45 +++++++++++++++++++ .../collections/itsm_approval_node.py | 10 ++++- 11 files changed, 139 insertions(+), 27 deletions(-) create mode 100644 itsm/meta/__init__.py create mode 100644 itsm/meta/admin.py create mode 100644 itsm/meta/apps.py create mode 100644 itsm/meta/migrations/0001_initial.py create mode 100644 itsm/meta/migrations/__init__.py create mode 100644 itsm/meta/models.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8906b81e0..3689787cf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,10 +19,3 @@ repos: - id: commitlint stages: [commit-msg] additional_dependencies: ['@commitlint/config-conventional'] - - repo: local - hooks: - - id: check-migrate - name: check migrate - entry: python scripts/check_migrate/check_migrate.py - language: system - types: [python] diff --git a/common/utils.py b/common/utils.py index 29c128c55..b8417f9c3 100644 --- a/common/utils.py +++ b/common/utils.py @@ -22,7 +22,6 @@ 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. """ -from django.conf import settings # 开发框架公用方法 # 1. 页面输入内容转义(防止xss攻击) @@ -37,6 +36,7 @@ from common.log import logger from common.pxfilter import XssHtml +from itsm.meta.models import ContextService def html_escape(html, is_json=False): @@ -56,7 +56,7 @@ def html_escape(html, is_json=False): html = html.replace(">", ">") # 单双引号转换 if not is_json: - html = html.replace(' ', " ") + html = html.replace(" ", " ") html = html.replace('"', """) html = html.replace("'", "'") return html @@ -65,7 +65,7 @@ def html_escape(html, is_json=False): def url_escape(url): url = url.replace("<", "") url = url.replace(">", "") - url = url.replace(' ', "") + url = url.replace(" ", "") url = url.replace('"', "") url = url.replace("'", "") return url @@ -101,11 +101,13 @@ def notice_receiver_filter(receivers): """ if not receivers: return receivers - + receiver_type = "list" if isinstance(receivers, str): receiver_type = "str" receivers = receivers.strip().split(",") - - receivers = [i for i in receivers if i not in settings.NOTICE_IGNORE_LIST] + + context_service = ContextService() + notice_blacklist = context_service.get_context_value_list("notice_blacklist") + receivers = [i for i in receivers if i not in notice_blacklist] return receivers if receiver_type == "list" else ",".join(receivers) diff --git a/config/default.py b/config/default.py index b716fc76d..12a82dbf1 100644 --- a/config/default.py +++ b/config/default.py @@ -25,7 +25,6 @@ import base64 import datetime import importlib -import os from urllib.parse import urljoin, urlparse from blueapps.conf.default_settings import * # noqa @@ -110,7 +109,8 @@ "blueapps.opentelemetry.instrument_app", "itsm.plugin_service", "bk_notice_sdk", - "pipeline.contrib.engine_admin" + "pipeline.contrib.engine_admin", + "itsm.meta", ) INSTALLED_APPS = ("itsm.helper",) + INSTALLED_APPS @@ -350,7 +350,7 @@ def _(s): "rest_framework.parsers.FormParser", "rest_framework.parsers.MultiPartParser", ), - "DEFAULT_RENDERER_CLASSES": ("rest_framework.renderers.JSONRenderer",) + "DEFAULT_RENDERER_CLASSES": ("rest_framework.renderers.JSONRenderer",), } # ============================================================================== @@ -959,16 +959,15 @@ def redirect_func(request): # 公共配置 -BK_SHARED_RES_URL = os.getenv("BKPAAS_SHARED_RES_URL") or os.getenv("BKAPP_SHARED_RES_URL") +BK_SHARED_RES_URL = os.getenv("BKPAAS_SHARED_RES_URL") or os.getenv( + "BKAPP_SHARED_RES_URL" +) BK_PLATFORM_NAME = os.getenv("BKAPP_PLATFORM_NAME", "") -# 通知过滤 -NOTICE_IGNORE_LIST = os.getenv("BKAPP_NOTICE_IGNORE_LIST", []) -if isinstance(NOTICE_IGNORE_LIST, str): - NOTICE_IGNORE_LIST = [i.lower().strip() for i in NOTICE_IGNORE_LIST.split(",")] - # SMS 邀请评价限额 TICKET_INVITE_SMS_COUNT = int(os.getenv("BKAPP_TICKET_INVITE_SMS_COUNT", 10)) # eri admin -PIPELINE_ENGINE_ADMIN_API_PERMISSION = "itsm.helper.permissions.check_permission_success" +PIPELINE_ENGINE_ADMIN_API_PERMISSION = ( + "itsm.helper.permissions.check_permission_success" +) diff --git a/itsm/component/bkchat/utils.py b/itsm/component/bkchat/utils.py index a49b9377f..3913986c2 100644 --- a/itsm/component/bkchat/utils.py +++ b/itsm/component/bkchat/utils.py @@ -11,6 +11,7 @@ from itsm.component.constants import APPROVE_RESULT, API, RUNNING, SHOW_BY_CONDITION from itsm.component.exceptions import ComponentCallError from itsm.component.utils.conversion import show_conditions_validate, format_exp_value +from itsm.meta.models import ContextService from itsm.ticket.models import Ticket, Status, TicketField, SignTask # 当前运行环境 @@ -113,12 +114,25 @@ def send_fast_approval_message(title, content, receivers, ticket, state_id): # 更新详情url ticket.generate_ticket_url(state_id, receivers) - + + # 如果ticket的service_id在黑名单中则不发送bkchat快速审批通知 + context_service = ContextService() + service_approval_blacklist = context_service.get_context_value_list( + key="service_approval_blacklist" + ) + if str(ticket.service_id) in service_approval_blacklist: + logger.info( + f"[fast_approval] service id is in service_approval_blacklist=>{ticket_id}" + ) + return + # 接收人过滤 receivers = notice_receiver_filter(receivers) if not receivers: - logger.info(f"[fast approval] receivers is empty after filter, ticket_id=>{ticket_id}") - return + logger.info( + f"[fast approval] receivers is empty after filter, ticket_id=>{ticket_id}" + ) + return # 构造data信息 data = { diff --git a/itsm/meta/__init__.py b/itsm/meta/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/itsm/meta/admin.py b/itsm/meta/admin.py new file mode 100644 index 000000000..398879724 --- /dev/null +++ b/itsm/meta/admin.py @@ -0,0 +1,11 @@ +from django.contrib import admin +from .models import Context + + +class ContextAdmin(admin.ModelAdmin): + list_display = ("id", "key", "value", "created_at", "updated_at") + search_fields = ("key", "value") + list_filter = ("key",) + + +admin.site.register(Context, ContextAdmin) diff --git a/itsm/meta/apps.py b/itsm/meta/apps.py new file mode 100644 index 000000000..69fd69fbc --- /dev/null +++ b/itsm/meta/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MetaConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "itsm.meta" diff --git a/itsm/meta/migrations/0001_initial.py b/itsm/meta/migrations/0001_initial.py new file mode 100644 index 000000000..a05eaa61c --- /dev/null +++ b/itsm/meta/migrations/0001_initial.py @@ -0,0 +1,34 @@ +# Generated by Django 3.2.25 on 2024-12-06 14:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Context", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ("key", models.CharField(max_length=255, unique=True)), + ("value", models.TextField(blank=True)), + ], + options={ + "db_table": "meta_context", + }, + ), + ] diff --git a/itsm/meta/migrations/__init__.py b/itsm/meta/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/itsm/meta/models.py b/itsm/meta/models.py new file mode 100644 index 000000000..15afe5e83 --- /dev/null +++ b/itsm/meta/models.py @@ -0,0 +1,45 @@ +from django.core.cache import cache +from django.db import models +from django.db.models.signals import post_save +from django.dispatch import receiver + + +class Context(models.Model): + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + key = models.CharField(max_length=255, unique=True) + value = models.TextField(blank=True) + + def __str__(self): + return self.key + + class Meta: + db_table = "meta_context" + + +@receiver(post_save, sender=Context) +def update_cache(sender, instance, **kwargs): + cache_key = f"meta_context_{instance.key}" + cache.set(cache_key, instance.value, 30) + + +class ContextService: + @staticmethod + def get_context_value(key): + cache_key = f"meta_context_{key}" + context_value = cache.get(cache_key) + if not context_value: + try: + context_value = Context.objects.get(key=key).value + except Context.DoesNotExist: + context_value = "" + cache.set(cache_key, context_value, 30) + return context_value + + @staticmethod + def get_context_value_list(key): + context_value = ContextService.get_context_value(key) + context_value = ( + [item.strip() for item in context_value.split(",")] if context_value else [] + ) + return context_value diff --git a/itsm/pipeline_plugins/components/collections/itsm_approval_node.py b/itsm/pipeline_plugins/components/collections/itsm_approval_node.py index 70543d35f..3be85ad0f 100644 --- a/itsm/pipeline_plugins/components/collections/itsm_approval_node.py +++ b/itsm/pipeline_plugins/components/collections/itsm_approval_node.py @@ -28,6 +28,7 @@ from django.conf import settings from django.core.cache import cache from itsm.component.constants import PROCESS_COUNT +from itsm.meta.models import ContextService from itsm.ticket.models import Ticket, Status from pipeline.component_framework.component import Component @@ -61,7 +62,14 @@ def execute(self, data, parent_data): ) is_multi = ticket.flow.get_state(state_id)["is_multi"] user_count = str(self.get_user_count(ticket_id, state_id)) if is_multi else "1" - ticket.create_moa_ticket(state_id) + + # 如果service_id不在service_approval_blacklist中,则创建moa单据 + context_service = ContextService() + service_approval_blacklist = context_service.get_context_value_list( + "service_approval_blacklist" + ) + if str(ticket.service_id) not in service_approval_blacklist: + ticket.create_moa_ticket(state_id) # 如果是普通的审批节点,则自动生成条件 if not is_multi: From dfa13f4248eff990d1411ab7f7801ffef430533d Mon Sep 17 00:00:00 2001 From: v_wmcowen Date: Mon, 9 Dec 2024 12:18:32 +0800 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0ITSM=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E9=85=8D=E7=BD=AE=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=89=88=E6=9D=83=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/utils.py | 19 ------ itsm/component/bkchat/utils.py | 10 +-- itsm/component/notify.py | 4 +- itsm/meta/__init__.py | 24 +++++++ itsm/meta/admin.py | 25 +++++++ itsm/meta/apps.py | 25 +++++++ itsm/meta/migrations/0001_initial.py | 25 +++++++ itsm/meta/migrations/__init__.py | 24 +++++++ itsm/meta/models.py | 66 +++++++++++++++++-- .../collections/itsm_approval_node.py | 3 +- 10 files changed, 191 insertions(+), 34 deletions(-) diff --git a/common/utils.py b/common/utils.py index b8417f9c3..f74bad202 100644 --- a/common/utils.py +++ b/common/utils.py @@ -36,7 +36,6 @@ from common.log import logger from common.pxfilter import XssHtml -from itsm.meta.models import ContextService def html_escape(html, is_json=False): @@ -93,21 +92,3 @@ def texteditor_escape(str_escape, is_support_img=True): def cmp(a, b): """适配py2的cmp方法""" return (a > b) - (a < b) - - -def notice_receiver_filter(receivers): - """ - 通知名单过滤 - """ - if not receivers: - return receivers - - receiver_type = "list" - if isinstance(receivers, str): - receiver_type = "str" - receivers = receivers.strip().split(",") - - context_service = ContextService() - notice_blacklist = context_service.get_context_value_list("notice_blacklist") - receivers = [i for i in receivers if i not in notice_blacklist] - return receivers if receiver_type == "list" else ",".join(receivers) diff --git a/itsm/component/bkchat/utils.py b/itsm/component/bkchat/utils.py index 3913986c2..8e7eebefe 100644 --- a/itsm/component/bkchat/utils.py +++ b/itsm/component/bkchat/utils.py @@ -6,12 +6,11 @@ from django.http import JsonResponse from common.log import logger -from common.utils import notice_receiver_filter from config.default import CLOSE_NOTIFY from itsm.component.constants import APPROVE_RESULT, API, RUNNING, SHOW_BY_CONDITION from itsm.component.exceptions import ComponentCallError from itsm.component.utils.conversion import show_conditions_validate, format_exp_value -from itsm.meta.models import ContextService +from itsm.meta.models import context_service from itsm.ticket.models import Ticket, Status, TicketField, SignTask # 当前运行环境 @@ -116,18 +115,19 @@ def send_fast_approval_message(title, content, receivers, ticket, state_id): ticket.generate_ticket_url(state_id, receivers) # 如果ticket的service_id在黑名单中则不发送bkchat快速审批通知 - context_service = ContextService() service_approval_blacklist = context_service.get_context_value_list( key="service_approval_blacklist" ) if str(ticket.service_id) in service_approval_blacklist: logger.info( - f"[fast_approval] service id is in service_approval_blacklist=>{ticket_id}" + logger.info( + f"[fast_approval] service id is in service_approval_blacklist, ticket_id=>{ticket_id}" + ) ) return # 接收人过滤 - receivers = notice_receiver_filter(receivers) + receivers = context_service.notice_receiver_filter(receivers) if not receivers: logger.info( f"[fast approval] receivers is empty after filter, ticket_id=>{ticket_id}" diff --git a/itsm/component/notify.py b/itsm/component/notify.py index ad31c2c8c..b9976b8f2 100644 --- a/itsm/component/notify.py +++ b/itsm/component/notify.py @@ -29,18 +29,18 @@ from django.utils.translation import ugettext as _ from common.log import logger -from common.utils import notice_receiver_filter from itsm.component.constants import GENERAL_NOTICE from itsm.component.esb.esbclient import client_backend from itsm.component.exceptions import ComponentCallError from itsm.component.utils.basic import merge_dict_list +from itsm.meta.models import context_service from weixin.core.settings import WEIXIN_APP_EXTERNAL_HOST class BaseNotifier(object): def __init__(self, title, receivers, message, notify_type=GENERAL_NOTICE): self.title = title - self.receivers = notice_receiver_filter(receivers) + self.receivers = context_service.notice_receiver_filter(receivers) self.message = message self.notify_type = notify_type diff --git a/itsm/meta/__init__.py b/itsm/meta/__init__.py index e69de29bb..7525a6a43 100644 --- a/itsm/meta/__init__.py +++ b/itsm/meta/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" diff --git a/itsm/meta/admin.py b/itsm/meta/admin.py index 398879724..50b69151b 100644 --- a/itsm/meta/admin.py +++ b/itsm/meta/admin.py @@ -1,3 +1,28 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" + from django.contrib import admin from .models import Context diff --git a/itsm/meta/apps.py b/itsm/meta/apps.py index 69fd69fbc..5c6283b41 100644 --- a/itsm/meta/apps.py +++ b/itsm/meta/apps.py @@ -1,3 +1,28 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" + from django.apps import AppConfig diff --git a/itsm/meta/migrations/0001_initial.py b/itsm/meta/migrations/0001_initial.py index a05eaa61c..daf5f1e01 100644 --- a/itsm/meta/migrations/0001_initial.py +++ b/itsm/meta/migrations/0001_initial.py @@ -1,3 +1,28 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" + # Generated by Django 3.2.25 on 2024-12-06 14:55 from django.db import migrations, models diff --git a/itsm/meta/migrations/__init__.py b/itsm/meta/migrations/__init__.py index e69de29bb..7525a6a43 100644 --- a/itsm/meta/migrations/__init__.py +++ b/itsm/meta/migrations/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" diff --git a/itsm/meta/models.py b/itsm/meta/models.py index 15afe5e83..068140b91 100644 --- a/itsm/meta/models.py +++ b/itsm/meta/models.py @@ -1,7 +1,35 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" + from django.core.cache import cache from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver +from common.log import logger + +CACHE_TIMEOUT = 30 # 缓存过期时间 class Context(models.Model): @@ -20,26 +48,52 @@ class Meta: @receiver(post_save, sender=Context) def update_cache(sender, instance, **kwargs): cache_key = f"meta_context_{instance.key}" - cache.set(cache_key, instance.value, 30) + cache.set(cache_key, instance.value, CACHE_TIMEOUT) class ContextService: @staticmethod def get_context_value(key): + """返回str类型的context_value""" cache_key = f"meta_context_{key}" context_value = cache.get(cache_key) - if not context_value: + if context_value is None: try: context_value = Context.objects.get(key=key).value except Context.DoesNotExist: + logger.info(f"key为'{key}'的上下文配置不存在") context_value = "" - cache.set(cache_key, context_value, 30) + cache.set(cache_key, context_value, CACHE_TIMEOUT) return context_value @staticmethod def get_context_value_list(key): + """返回list类型的context_value""" context_value = ContextService.get_context_value(key) - context_value = ( - [item.strip() for item in context_value.split(",")] if context_value else [] + + if context_value: + # 分割字符串,去除空白字符,并去重 + unique_values = list(set(item.strip() for item in context_value.split(","))) + return unique_values + return [] + + @staticmethod + def notice_receiver_filter(receivers): + """通知名单过滤""" + if not receivers: + return receivers + + if isinstance(receivers, str): + receivers = receivers.strip().split(",") + + # 对黑名单的内容进行去重 + notice_blacklist = ContextService.get_context_value_list("notice_blacklist") + filtered_receivers = [i for i in receivers if i not in notice_blacklist] + return ( + filtered_receivers + if isinstance(receivers, list) + else ",".join(filtered_receivers) ) - return context_value + + +context_service = ContextService() diff --git a/itsm/pipeline_plugins/components/collections/itsm_approval_node.py b/itsm/pipeline_plugins/components/collections/itsm_approval_node.py index 3be85ad0f..0ba586b0d 100644 --- a/itsm/pipeline_plugins/components/collections/itsm_approval_node.py +++ b/itsm/pipeline_plugins/components/collections/itsm_approval_node.py @@ -28,7 +28,7 @@ from django.conf import settings from django.core.cache import cache from itsm.component.constants import PROCESS_COUNT -from itsm.meta.models import ContextService +from itsm.meta.models import context_service from itsm.ticket.models import Ticket, Status from pipeline.component_framework.component import Component @@ -64,7 +64,6 @@ def execute(self, data, parent_data): user_count = str(self.get_user_count(ticket_id, state_id)) if is_multi else "1" # 如果service_id不在service_approval_blacklist中,则创建moa单据 - context_service = ContextService() service_approval_blacklist = context_service.get_context_value_list( "service_approval_blacklist" ) From 3bfda192aeb2f1301a9b24968aadb613238f87e3 Mon Sep 17 00:00:00 2001 From: v_wmcowen Date: Mon, 9 Dec 2024 12:18:32 +0800 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0ITSM=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E9=85=8D=E7=BD=AE=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=89=88=E6=9D=83=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/utils.py | 19 ------ itsm/component/bkchat/utils.py | 8 +-- itsm/component/notify.py | 4 +- itsm/meta/__init__.py | 24 +++++++ itsm/meta/admin.py | 25 +++++++ itsm/meta/apps.py | 25 +++++++ itsm/meta/migrations/0001_initial.py | 25 +++++++ itsm/meta/migrations/__init__.py | 24 +++++++ itsm/meta/models.py | 66 +++++++++++++++++-- .../collections/itsm_approval_node.py | 3 +- 10 files changed, 189 insertions(+), 34 deletions(-) diff --git a/common/utils.py b/common/utils.py index b8417f9c3..f74bad202 100644 --- a/common/utils.py +++ b/common/utils.py @@ -36,7 +36,6 @@ from common.log import logger from common.pxfilter import XssHtml -from itsm.meta.models import ContextService def html_escape(html, is_json=False): @@ -93,21 +92,3 @@ def texteditor_escape(str_escape, is_support_img=True): def cmp(a, b): """适配py2的cmp方法""" return (a > b) - (a < b) - - -def notice_receiver_filter(receivers): - """ - 通知名单过滤 - """ - if not receivers: - return receivers - - receiver_type = "list" - if isinstance(receivers, str): - receiver_type = "str" - receivers = receivers.strip().split(",") - - context_service = ContextService() - notice_blacklist = context_service.get_context_value_list("notice_blacklist") - receivers = [i for i in receivers if i not in notice_blacklist] - return receivers if receiver_type == "list" else ",".join(receivers) diff --git a/itsm/component/bkchat/utils.py b/itsm/component/bkchat/utils.py index 3913986c2..04a22920f 100644 --- a/itsm/component/bkchat/utils.py +++ b/itsm/component/bkchat/utils.py @@ -6,12 +6,11 @@ from django.http import JsonResponse from common.log import logger -from common.utils import notice_receiver_filter from config.default import CLOSE_NOTIFY from itsm.component.constants import APPROVE_RESULT, API, RUNNING, SHOW_BY_CONDITION from itsm.component.exceptions import ComponentCallError from itsm.component.utils.conversion import show_conditions_validate, format_exp_value -from itsm.meta.models import ContextService +from itsm.meta.models import context_service from itsm.ticket.models import Ticket, Status, TicketField, SignTask # 当前运行环境 @@ -116,18 +115,17 @@ def send_fast_approval_message(title, content, receivers, ticket, state_id): ticket.generate_ticket_url(state_id, receivers) # 如果ticket的service_id在黑名单中则不发送bkchat快速审批通知 - context_service = ContextService() service_approval_blacklist = context_service.get_context_value_list( key="service_approval_blacklist" ) if str(ticket.service_id) in service_approval_blacklist: logger.info( - f"[fast_approval] service id is in service_approval_blacklist=>{ticket_id}" + f"[fast_approval] service id is in service_approval_blacklist, ticket_id=>{ticket_id}" ) return # 接收人过滤 - receivers = notice_receiver_filter(receivers) + receivers = context_service.notice_receiver_filter(receivers) if not receivers: logger.info( f"[fast approval] receivers is empty after filter, ticket_id=>{ticket_id}" diff --git a/itsm/component/notify.py b/itsm/component/notify.py index ad31c2c8c..b9976b8f2 100644 --- a/itsm/component/notify.py +++ b/itsm/component/notify.py @@ -29,18 +29,18 @@ from django.utils.translation import ugettext as _ from common.log import logger -from common.utils import notice_receiver_filter from itsm.component.constants import GENERAL_NOTICE from itsm.component.esb.esbclient import client_backend from itsm.component.exceptions import ComponentCallError from itsm.component.utils.basic import merge_dict_list +from itsm.meta.models import context_service from weixin.core.settings import WEIXIN_APP_EXTERNAL_HOST class BaseNotifier(object): def __init__(self, title, receivers, message, notify_type=GENERAL_NOTICE): self.title = title - self.receivers = notice_receiver_filter(receivers) + self.receivers = context_service.notice_receiver_filter(receivers) self.message = message self.notify_type = notify_type diff --git a/itsm/meta/__init__.py b/itsm/meta/__init__.py index e69de29bb..7525a6a43 100644 --- a/itsm/meta/__init__.py +++ b/itsm/meta/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" diff --git a/itsm/meta/admin.py b/itsm/meta/admin.py index 398879724..50b69151b 100644 --- a/itsm/meta/admin.py +++ b/itsm/meta/admin.py @@ -1,3 +1,28 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" + from django.contrib import admin from .models import Context diff --git a/itsm/meta/apps.py b/itsm/meta/apps.py index 69fd69fbc..5c6283b41 100644 --- a/itsm/meta/apps.py +++ b/itsm/meta/apps.py @@ -1,3 +1,28 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" + from django.apps import AppConfig diff --git a/itsm/meta/migrations/0001_initial.py b/itsm/meta/migrations/0001_initial.py index a05eaa61c..daf5f1e01 100644 --- a/itsm/meta/migrations/0001_initial.py +++ b/itsm/meta/migrations/0001_initial.py @@ -1,3 +1,28 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" + # Generated by Django 3.2.25 on 2024-12-06 14:55 from django.db import migrations, models diff --git a/itsm/meta/migrations/__init__.py b/itsm/meta/migrations/__init__.py index e69de29bb..7525a6a43 100644 --- a/itsm/meta/migrations/__init__.py +++ b/itsm/meta/migrations/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" diff --git a/itsm/meta/models.py b/itsm/meta/models.py index 15afe5e83..068140b91 100644 --- a/itsm/meta/models.py +++ b/itsm/meta/models.py @@ -1,7 +1,35 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" + from django.core.cache import cache from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver +from common.log import logger + +CACHE_TIMEOUT = 30 # 缓存过期时间 class Context(models.Model): @@ -20,26 +48,52 @@ class Meta: @receiver(post_save, sender=Context) def update_cache(sender, instance, **kwargs): cache_key = f"meta_context_{instance.key}" - cache.set(cache_key, instance.value, 30) + cache.set(cache_key, instance.value, CACHE_TIMEOUT) class ContextService: @staticmethod def get_context_value(key): + """返回str类型的context_value""" cache_key = f"meta_context_{key}" context_value = cache.get(cache_key) - if not context_value: + if context_value is None: try: context_value = Context.objects.get(key=key).value except Context.DoesNotExist: + logger.info(f"key为'{key}'的上下文配置不存在") context_value = "" - cache.set(cache_key, context_value, 30) + cache.set(cache_key, context_value, CACHE_TIMEOUT) return context_value @staticmethod def get_context_value_list(key): + """返回list类型的context_value""" context_value = ContextService.get_context_value(key) - context_value = ( - [item.strip() for item in context_value.split(",")] if context_value else [] + + if context_value: + # 分割字符串,去除空白字符,并去重 + unique_values = list(set(item.strip() for item in context_value.split(","))) + return unique_values + return [] + + @staticmethod + def notice_receiver_filter(receivers): + """通知名单过滤""" + if not receivers: + return receivers + + if isinstance(receivers, str): + receivers = receivers.strip().split(",") + + # 对黑名单的内容进行去重 + notice_blacklist = ContextService.get_context_value_list("notice_blacklist") + filtered_receivers = [i for i in receivers if i not in notice_blacklist] + return ( + filtered_receivers + if isinstance(receivers, list) + else ",".join(filtered_receivers) ) - return context_value + + +context_service = ContextService() diff --git a/itsm/pipeline_plugins/components/collections/itsm_approval_node.py b/itsm/pipeline_plugins/components/collections/itsm_approval_node.py index 3be85ad0f..0ba586b0d 100644 --- a/itsm/pipeline_plugins/components/collections/itsm_approval_node.py +++ b/itsm/pipeline_plugins/components/collections/itsm_approval_node.py @@ -28,7 +28,7 @@ from django.conf import settings from django.core.cache import cache from itsm.component.constants import PROCESS_COUNT -from itsm.meta.models import ContextService +from itsm.meta.models import context_service from itsm.ticket.models import Ticket, Status from pipeline.component_framework.component import Component @@ -64,7 +64,6 @@ def execute(self, data, parent_data): user_count = str(self.get_user_count(ticket_id, state_id)) if is_multi else "1" # 如果service_id不在service_approval_blacklist中,则创建moa单据 - context_service = ContextService() service_approval_blacklist = context_service.get_context_value_list( "service_approval_blacklist" ) From c559a84f85302a37ea8462fc23e784b247153add Mon Sep 17 00:00:00 2001 From: v_wmcowen Date: Mon, 9 Dec 2024 12:27:29 +0800 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0ITSM=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E9=85=8D=E7=BD=AE=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=89=88=E6=9D=83=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- itsm/component/bkchat/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/itsm/component/bkchat/utils.py b/itsm/component/bkchat/utils.py index e61a8c2b6..04a22920f 100644 --- a/itsm/component/bkchat/utils.py +++ b/itsm/component/bkchat/utils.py @@ -120,7 +120,7 @@ def send_fast_approval_message(title, content, receivers, ticket, state_id): ) if str(ticket.service_id) in service_approval_blacklist: logger.info( - f"[fast_approval] service id is in service_approval_blacklist=>{ticket_id}" + f"[fast_approval] service id is in service_approval_blacklist, ticket_id=>{ticket_id}" ) return From 22937b07b37b3b0f9d0176dfd0fd4a342d5e6159 Mon Sep 17 00:00:00 2001 From: v_wmcowen Date: Wed, 11 Dec 2024 15:12:38 +0800 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0ITSM=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E9=85=8D=E7=BD=AE=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- itsm/component/bkchat/utils.py | 12 ++--- itsm/component/notify.py | 4 +- itsm/meta/models.py | 21 -------- itsm/meta/utils.py | 53 +++++++++++++++++++ .../collections/itsm_approval_node.py | 13 +++-- 5 files changed, 69 insertions(+), 34 deletions(-) create mode 100644 itsm/meta/utils.py diff --git a/itsm/component/bkchat/utils.py b/itsm/component/bkchat/utils.py index 04a22920f..81fd707b3 100644 --- a/itsm/component/bkchat/utils.py +++ b/itsm/component/bkchat/utils.py @@ -10,7 +10,7 @@ from itsm.component.constants import APPROVE_RESULT, API, RUNNING, SHOW_BY_CONDITION from itsm.component.exceptions import ComponentCallError from itsm.component.utils.conversion import show_conditions_validate, format_exp_value -from itsm.meta.models import context_service +from itsm.meta.utils import notice_filter_service from itsm.ticket.models import Ticket, Status, TicketField, SignTask # 当前运行环境 @@ -114,18 +114,16 @@ def send_fast_approval_message(title, content, receivers, ticket, state_id): # 更新详情url ticket.generate_ticket_url(state_id, receivers) - # 如果ticket的service_id在黑名单中则不发送bkchat快速审批通知 - service_approval_blacklist = context_service.get_context_value_list( - key="service_approval_blacklist" - ) + # 如果ticket的service_id在service_approval_blacklist中,则不发送bkchat快速审批通知 + service_approval_blacklist = notice_filter_service.get_service_approval_blacklist() if str(ticket.service_id) in service_approval_blacklist: logger.info( - f"[fast_approval] service id is in service_approval_blacklist, ticket_id=>{ticket_id}" + f"[fast_approval]Bypass due to service id is in service_approval_blacklist, ticket_id=>{ticket_id}" ) return # 接收人过滤 - receivers = context_service.notice_receiver_filter(receivers) + receivers = notice_filter_service.notice_receiver_filter(receivers) if not receivers: logger.info( f"[fast approval] receivers is empty after filter, ticket_id=>{ticket_id}" diff --git a/itsm/component/notify.py b/itsm/component/notify.py index b9976b8f2..367e9dad4 100644 --- a/itsm/component/notify.py +++ b/itsm/component/notify.py @@ -33,14 +33,14 @@ from itsm.component.esb.esbclient import client_backend from itsm.component.exceptions import ComponentCallError from itsm.component.utils.basic import merge_dict_list -from itsm.meta.models import context_service +from itsm.meta.utils import notice_filter_service from weixin.core.settings import WEIXIN_APP_EXTERNAL_HOST class BaseNotifier(object): def __init__(self, title, receivers, message, notify_type=GENERAL_NOTICE): self.title = title - self.receivers = context_service.notice_receiver_filter(receivers) + self.receivers = notice_filter_service.notice_receiver_filter(receivers) self.message = message self.notify_type = notify_type diff --git a/itsm/meta/models.py b/itsm/meta/models.py index 068140b91..be8d0ebc1 100644 --- a/itsm/meta/models.py +++ b/itsm/meta/models.py @@ -76,24 +76,3 @@ def get_context_value_list(key): unique_values = list(set(item.strip() for item in context_value.split(","))) return unique_values return [] - - @staticmethod - def notice_receiver_filter(receivers): - """通知名单过滤""" - if not receivers: - return receivers - - if isinstance(receivers, str): - receivers = receivers.strip().split(",") - - # 对黑名单的内容进行去重 - notice_blacklist = ContextService.get_context_value_list("notice_blacklist") - filtered_receivers = [i for i in receivers if i not in notice_blacklist] - return ( - filtered_receivers - if isinstance(receivers, list) - else ",".join(filtered_receivers) - ) - - -context_service = ContextService() diff --git a/itsm/meta/utils.py b/itsm/meta/utils.py new file mode 100644 index 000000000..a838cb5f9 --- /dev/null +++ b/itsm/meta/utils.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" + +from itsm.meta.models import ContextService + + +class NoticeFilterService: + @staticmethod + def notice_receiver_filter(receivers): + """通知名单过滤""" + if not receivers: + return receivers + + if isinstance(receivers, str): + receivers = receivers.strip().split(",") + + notice_blacklist = ContextService.get_context_value_list("notice_blacklist") + filtered_receivers = [i for i in receivers if i not in notice_blacklist] + return ( + filtered_receivers + if isinstance(receivers, list) + else ",".join(filtered_receivers) + ) + + @staticmethod + def get_service_approval_blacklist(): + """获取审批服务黑名单""" + return ContextService.get_context_value_list("service_approval_blacklist") + + +notice_filter_service = NoticeFilterService() diff --git a/itsm/pipeline_plugins/components/collections/itsm_approval_node.py b/itsm/pipeline_plugins/components/collections/itsm_approval_node.py index 0ba586b0d..b2ca5621f 100644 --- a/itsm/pipeline_plugins/components/collections/itsm_approval_node.py +++ b/itsm/pipeline_plugins/components/collections/itsm_approval_node.py @@ -28,7 +28,7 @@ from django.conf import settings from django.core.cache import cache from itsm.component.constants import PROCESS_COUNT -from itsm.meta.models import context_service +from itsm.meta.utils import notice_filter_service from itsm.ticket.models import Ticket, Status from pipeline.component_framework.component import Component @@ -63,12 +63,17 @@ def execute(self, data, parent_data): is_multi = ticket.flow.get_state(state_id)["is_multi"] user_count = str(self.get_user_count(ticket_id, state_id)) if is_multi else "1" - # 如果service_id不在service_approval_blacklist中,则创建moa单据 - service_approval_blacklist = context_service.get_context_value_list( - "service_approval_blacklist" + service_approval_blacklist = ( + notice_filter_service.get_service_approval_blacklist() ) if str(ticket.service_id) not in service_approval_blacklist: + # 如果service_id不在service_approval_blacklist中,则创建moa单据 ticket.create_moa_ticket(state_id) + else: + # 否则,记录日志 + logger.info( + "Bypass create_moa_ticket due to service id is in service_approval_blacklist" + ) # 如果是普通的审批节点,则自动生成条件 if not is_multi: From a3dd4858c4113315a46120b7fcb7dae625be2cf4 Mon Sep 17 00:00:00 2001 From: v_wmcowen Date: Wed, 11 Dec 2024 16:49:03 +0800 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0ITSM=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E9=85=8D=E7=BD=AE=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- itsm/component/bkchat/utils.py | 2 +- itsm/component/notify.py | 2 +- itsm/meta/models.py | 32 +-------- itsm/meta/services/context.py | 66 +++++++++++++++++++ .../{utils.py => services/notice_filter.py} | 3 +- .../collections/itsm_approval_node.py | 2 +- 6 files changed, 72 insertions(+), 35 deletions(-) create mode 100644 itsm/meta/services/context.py rename itsm/meta/{utils.py => services/notice_filter.py} (97%) diff --git a/itsm/component/bkchat/utils.py b/itsm/component/bkchat/utils.py index 81fd707b3..6938ef2f7 100644 --- a/itsm/component/bkchat/utils.py +++ b/itsm/component/bkchat/utils.py @@ -10,7 +10,7 @@ from itsm.component.constants import APPROVE_RESULT, API, RUNNING, SHOW_BY_CONDITION from itsm.component.exceptions import ComponentCallError from itsm.component.utils.conversion import show_conditions_validate, format_exp_value -from itsm.meta.utils import notice_filter_service +from itsm.meta.services.notice_filter import notice_filter_service from itsm.ticket.models import Ticket, Status, TicketField, SignTask # 当前运行环境 diff --git a/itsm/component/notify.py b/itsm/component/notify.py index 367e9dad4..0299c884a 100644 --- a/itsm/component/notify.py +++ b/itsm/component/notify.py @@ -33,7 +33,7 @@ from itsm.component.esb.esbclient import client_backend from itsm.component.exceptions import ComponentCallError from itsm.component.utils.basic import merge_dict_list -from itsm.meta.utils import notice_filter_service +from itsm.meta.services.notice_filter import notice_filter_service from weixin.core.settings import WEIXIN_APP_EXTERNAL_HOST diff --git a/itsm/meta/models.py b/itsm/meta/models.py index be8d0ebc1..6757968c5 100644 --- a/itsm/meta/models.py +++ b/itsm/meta/models.py @@ -27,9 +27,8 @@ from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver -from common.log import logger -CACHE_TIMEOUT = 30 # 缓存过期时间 +from itsm.component.constants import CACHE_5MIN class Context(models.Model): @@ -48,31 +47,4 @@ class Meta: @receiver(post_save, sender=Context) def update_cache(sender, instance, **kwargs): cache_key = f"meta_context_{instance.key}" - cache.set(cache_key, instance.value, CACHE_TIMEOUT) - - -class ContextService: - @staticmethod - def get_context_value(key): - """返回str类型的context_value""" - cache_key = f"meta_context_{key}" - context_value = cache.get(cache_key) - if context_value is None: - try: - context_value = Context.objects.get(key=key).value - except Context.DoesNotExist: - logger.info(f"key为'{key}'的上下文配置不存在") - context_value = "" - cache.set(cache_key, context_value, CACHE_TIMEOUT) - return context_value - - @staticmethod - def get_context_value_list(key): - """返回list类型的context_value""" - context_value = ContextService.get_context_value(key) - - if context_value: - # 分割字符串,去除空白字符,并去重 - unique_values = list(set(item.strip() for item in context_value.split(","))) - return unique_values - return [] + cache.set(cache_key, instance.value, CACHE_5MIN) diff --git a/itsm/meta/services/context.py b/itsm/meta/services/context.py new file mode 100644 index 000000000..3f4004f76 --- /dev/null +++ b/itsm/meta/services/context.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +""" +Tencent is pleased to support the open source community by making BK-ITSM 蓝鲸流程服务 available. + +Copyright (C)2024 THL A29 Limited, a Tencent company. All rights reserved. + +BK-ITSM 蓝鲸流程服务 is licensed under the MIT License. + +License for BK-ITSM 蓝鲸流程服务: +-------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. +""" + +from django.core.cache import cache + +from itsm.component.constants import CACHE_5MIN +from itsm.meta.models import Context +from common.log import logger + + +class ContextService: + @staticmethod + def get_context_value(key): + """返回context_value,若不存在则返回None""" + cache_key = f"meta_context_{key}" + context_value = cache.get(cache_key) + + # 如果缓存中没有找到值 + if context_value is None: + try: + # 尝试从数据库中获取值 + context_value = Context.objects.get(key=key).value + except Context.DoesNotExist: + logger.info(f"数据库中key为'{key}'的上下文配置不存在") + context_value = None + except Exception as e: + logger.error(f"获取key为'{key}'的上下文配置时发生错误: {str(e)}") + context_value = None + + # 将获取到的值存入缓存 + cache.set(cache_key, context_value, CACHE_5MIN) + + return context_value + + @staticmethod + def get_context_value_list(key): + """返回list类型的context_value,若不存在则返回空列表""" + context_value = ContextService.get_context_value(key) + + if context_value: + # 分割字符串,去除空白字符,并去重 + unique_values = list(set(item.strip() for item in context_value.split(","))) + return unique_values + return [] diff --git a/itsm/meta/utils.py b/itsm/meta/services/notice_filter.py similarity index 97% rename from itsm/meta/utils.py rename to itsm/meta/services/notice_filter.py index a838cb5f9..cc26615c7 100644 --- a/itsm/meta/utils.py +++ b/itsm/meta/services/notice_filter.py @@ -22,8 +22,7 @@ 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. """ - -from itsm.meta.models import ContextService +from itsm.meta.services.context import ContextService class NoticeFilterService: diff --git a/itsm/pipeline_plugins/components/collections/itsm_approval_node.py b/itsm/pipeline_plugins/components/collections/itsm_approval_node.py index b2ca5621f..39c2a8e85 100644 --- a/itsm/pipeline_plugins/components/collections/itsm_approval_node.py +++ b/itsm/pipeline_plugins/components/collections/itsm_approval_node.py @@ -28,7 +28,7 @@ from django.conf import settings from django.core.cache import cache from itsm.component.constants import PROCESS_COUNT -from itsm.meta.utils import notice_filter_service +from itsm.meta.services.notice_filter import notice_filter_service from itsm.ticket.models import Ticket, Status from pipeline.component_framework.component import Component From e951d65ece707a97a195db2d7750b09d6d79040f Mon Sep 17 00:00:00 2001 From: v_wmcowen Date: Thu, 12 Dec 2024 11:57:22 +0800 Subject: [PATCH 7/7] =?UTF-8?q?fix:=20=E5=BF=AB=E9=80=9F=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E5=8F=91=E9=80=81=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- itsm/meta/services/notice_filter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/itsm/meta/services/notice_filter.py b/itsm/meta/services/notice_filter.py index cc26615c7..9e51e635a 100644 --- a/itsm/meta/services/notice_filter.py +++ b/itsm/meta/services/notice_filter.py @@ -32,14 +32,16 @@ def notice_receiver_filter(receivers): if not receivers: return receivers + receiver_type = "list" if isinstance(receivers, str): + receiver_type = "str" receivers = receivers.strip().split(",") notice_blacklist = ContextService.get_context_value_list("notice_blacklist") filtered_receivers = [i for i in receivers if i not in notice_blacklist] return ( filtered_receivers - if isinstance(receivers, list) + if receiver_type == "list" else ",".join(filtered_receivers) )