From 60deef2abffdfde92fb5ef4a3cdbb81e6ff84cd8 Mon Sep 17 00:00:00 2001 From: wangruidong <940853815@qq.com> Date: Wed, 18 Jun 2025 15:17:43 +0800 Subject: [PATCH] fix: Org admin cannot use system tools. --- apps/ops/ws.py | 24 ++---------------------- apps/orgs/mixins/ws.py | 28 ++++++++++++++++++++++++++++ apps/settings/api/settings.py | 2 +- apps/settings/ws.py | 7 +++++-- 4 files changed, 36 insertions(+), 25 deletions(-) create mode 100644 apps/orgs/mixins/ws.py diff --git a/apps/ops/ws.py b/apps/ops/ws.py index 5acb0c1b7..a7de28819 100644 --- a/apps/ops/ws.py +++ b/apps/ops/ws.py @@ -1,6 +1,5 @@ import asyncio import os -from http.cookies import SimpleCookie import aiofiles from asgiref.sync import sync_to_async @@ -8,6 +7,7 @@ from channels.generic.websocket import AsyncJsonWebsocketConsumer from common.db.utils import close_old_connections from common.utils import get_logger +from orgs.mixins.ws import OrgMixin from orgs.utils import tmp_to_org from rbac.builtin import BuiltinRole from .ansible.utils import get_ansible_task_log_path @@ -18,10 +18,8 @@ from .models import CeleryTaskExecution logger = get_logger(__name__) -class TaskLogWebsocket(AsyncJsonWebsocketConsumer): +class TaskLogWebsocket(AsyncJsonWebsocketConsumer, OrgMixin): disconnected = False - cookie = None - org = None user_tasks = ( 'ops.tasks.run_ops_job', 'ops.tasks.run_ops_job_execution', @@ -32,19 +30,6 @@ class TaskLogWebsocket(AsyncJsonWebsocketConsumer): 'ansible': get_ansible_task_log_path } - def get_cookie(self): - try: - headers = self.scope['headers'] - headers_dict = {key.decode('utf-8'): value.decode('utf-8') for key, value in headers} - cookie = SimpleCookie(headers_dict.get('cookie', '')) - except Exception as e: - cookie = SimpleCookie() - return cookie - - def get_current_org(self): - oid = self.cookie.get('X-JMS-ORG') - return oid.value if oid else None - async def connect(self): user = self.scope["user"] if user.is_authenticated: @@ -77,11 +62,6 @@ class TaskLogWebsocket(AsyncJsonWebsocketConsumer): user_role_ids = set(map(str, roles.values_list('id', flat=True))) return user_role_ids - @sync_to_async - def has_perms(self, user, perms): - with tmp_to_org(self.org): - return user.has_perms(perms) - async def receive_json(self, content, **kwargs): task_id = content.get('task') task = await self.get_task(task_id) diff --git a/apps/orgs/mixins/ws.py b/apps/orgs/mixins/ws.py new file mode 100644 index 000000000..46ea9dfb7 --- /dev/null +++ b/apps/orgs/mixins/ws.py @@ -0,0 +1,28 @@ +from http.cookies import SimpleCookie + +from asgiref.sync import sync_to_async + +from orgs.utils import tmp_to_org + + +class OrgMixin: + cookie = None + org = None + + def get_cookie(self): + try: + headers = self.scope['headers'] + headers_dict = {key.decode('utf-8'): value.decode('utf-8') for key, value in headers} + cookie = SimpleCookie(headers_dict.get('cookie', '')) + except Exception as e: + cookie = SimpleCookie() + return cookie + + def get_current_org(self): + oid = self.cookie.get('X-JMS-ORG') + return oid.value if oid else None + + @sync_to_async + def has_perms(self, user, perms): + with tmp_to_org(self.org): + return user.has_perms(perms) diff --git a/apps/settings/api/settings.py b/apps/settings/api/settings.py index dbbf57938..b986b0394 100644 --- a/apps/settings/api/settings.py +++ b/apps/settings/api/settings.py @@ -74,7 +74,7 @@ class SettingsApi(generics.RetrieveUpdateAPIView): rbac_category_permissions = { 'basic': 'settings.view_setting', - 'tool': 'settings.view_setting', + 'tool': 'rbac.view_systemtools', 'terminal': 'settings.change_terminal', 'ops': 'settings.change_ops', 'ticket': 'settings.change_ticket', diff --git a/apps/settings/ws.py b/apps/settings/ws.py index e9d9ec8b3..4dd5cea5a 100644 --- a/apps/settings/ws.py +++ b/apps/settings/ws.py @@ -13,6 +13,7 @@ from django.utils.translation import gettext_lazy as _ from common.db.utils import close_old_connections from common.utils import get_logger +from orgs.mixins.ws import OrgMixin from orgs.models import Organization from orgs.utils import current_org from settings.serializers import ( @@ -38,7 +39,7 @@ CACHE_KEY_LDAP_TEST_CONFIG_TASK_STATUS = 'CACHE_KEY_LDAP_TEST_CONFIG_TASK_STATUS TASK_STATUS_IS_OVER = 'OVER' -class ToolsWebsocket(AsyncJsonWebsocketConsumer): +class ToolsWebsocket(AsyncJsonWebsocketConsumer, OrgMixin): is_closed: bool = False @staticmethod @@ -55,7 +56,9 @@ class ToolsWebsocket(AsyncJsonWebsocketConsumer): async def connect(self): user = self.scope["user"] if user.is_authenticated: - has_perm = await sync_to_async(user.has_perm)('rbac.view_systemtools') + self.cookie = self.get_cookie() + self.org = self.get_current_org() + has_perm = self.has_perms(user, ['rbac.view_systemtools']) if await self.is_superuser(user) or (settings.TOOL_USER_ENABLED and has_perm): await self.accept() else: