From 23b13db9e25dc7ebe878b99010e083a1185031c8 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 28 Mar 2023 15:04:24 +0800 Subject: [PATCH 1/6] perf: category order (#10087) Co-authored-by: feng <1304903146@qq.com> --- apps/assets/const/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py index 00a496eee..3f2335ceb 100644 --- a/apps/assets/const/types.py +++ b/apps/assets/const/types.py @@ -136,8 +136,8 @@ class AllTypes(ChoicesMixin): (Category.HOST, HostTypes), (Category.DEVICE, DeviceTypes), (Category.DATABASE, DatabaseTypes), + (Category.CLOUD, CloudTypes), (Category.WEB, WebTypes), - (Category.CLOUD, CloudTypes) ) @classmethod From 8d3319717edf6ba00758199d5884ee790a4d583a Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 28 Mar 2023 16:26:40 +0800 Subject: [PATCH 2/6] =?UTF-8?q?perf:=20=E5=BC=80=E5=90=AF=E5=AE=89?= =?UTF-8?q?=E5=85=A8=E6=A8=A1=E5=BC=8F=E5=90=8E=E8=BF=87=E6=BB=A4root=20ad?= =?UTF-8?q?ministrator=20(#10089)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/accounts/automations/change_secret/manager.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/accounts/automations/change_secret/manager.py b/apps/accounts/automations/change_secret/manager.py index 999fc2c75..7bad9e5f6 100644 --- a/apps/accounts/automations/change_secret/manager.py +++ b/apps/accounts/automations/change_secret/manager.py @@ -78,7 +78,9 @@ class ChangeSecretManager(AccountBasePlaybookManager): accounts = accounts.filter(secret_type=self.secret_type) if settings.CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED: - accounts = accounts.filter(privileged=False) + accounts = accounts.filter(privileged=False).exclude( + username__in=['root', 'administrator'] + ) return accounts def host_callback( From 5b017daba144a9aae1a61eca66b0f31977655d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com> Date: Wed, 29 Mar 2023 10:03:14 +0800 Subject: [PATCH 3/6] =?UTF-8?q?perf:=20=E4=BD=BF=E7=94=A8=20docker.io=20?= =?UTF-8?q?=E4=BB=93=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile-ee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile-ee b/Dockerfile-ee index dc2ae308e..63c65d21c 100644 --- a/Dockerfile-ee +++ b/Dockerfile-ee @@ -1,6 +1,6 @@ ARG VERSION FROM registry.fit2cloud.com/jumpserver/xpack:${VERSION} as build-xpack -FROM ghcr.io/jumpserver/core:${VERSION} +FROM jumpserver/core:${VERSION} COPY --from=build-xpack /opt/xpack /opt/jumpserver/apps/xpack WORKDIR /opt/jumpserver From 678df5bf3ec707a7bf1408746bfbb5dd01076225 Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Wed, 29 Mar 2023 13:48:51 +0800 Subject: [PATCH 4/6] =?UTF-8?q?perf:=20=E8=A1=A5=E5=9B=9Eget=5Fterminal=5F?= =?UTF-8?q?latest=5Fstat=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/models/component/status.py | 38 +++++++++++++++++++++- apps/terminal/models/component/terminal.py | 5 +++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/apps/terminal/models/component/status.py b/apps/terminal/models/component/status.py index 3da13d9f0..279d6ac95 100644 --- a/apps/terminal/models/component/status.py +++ b/apps/terminal/models/component/status.py @@ -1,11 +1,12 @@ import uuid +from django.core.cache import cache from django.db import models +from django.forms.models import model_to_dict from django.utils.translation import ugettext_lazy as _ from common.utils import get_logger - logger = get_logger(__name__) @@ -21,9 +22,44 @@ class Status(models.Model): terminal = models.ForeignKey('terminal.Terminal', null=True, on_delete=models.CASCADE) date_created = models.DateTimeField(auto_now_add=True) + CACHE_KEY = 'TERMINAL_STATUS_{}' + class Meta: db_table = 'terminal_status' get_latest_by = 'date_created' verbose_name = _("Status") + @classmethod + def get_terminal_latest_stat(cls, terminal): + key = cls.CACHE_KEY.format(terminal.id) + data = cache.get(key) + if not data: + return None + data.pop('terminal', None) + stat = cls(**data) + stat.terminal = terminal + stat.is_alive = terminal.is_alive + stat.keep_one_decimal_place() + return stat + def keep_one_decimal_place(self): + keys = ['cpu_load', 'memory_used', 'disk_used'] + for key in keys: + value = getattr(self, key, 0) + if not isinstance(value, (int, float)): + continue + value = '%.1f' % value + setattr(self, key, float(value)) + + def save(self, force_insert=False, force_update=False, using=None, + update_fields=None): + self.terminal.set_alive(ttl=120) + return self.save_to_cache() + + def save_to_cache(self): + if not self.terminal: + return + key = self.CACHE_KEY.format(self.terminal.id) + data = model_to_dict(self) + cache.set(key, data, 60 * 3) + return data diff --git a/apps/terminal/models/component/terminal.py b/apps/terminal/models/component/terminal.py index 406d2192a..df09df680 100644 --- a/apps/terminal/models/component/terminal.py +++ b/apps/terminal/models/component/terminal.py @@ -1,6 +1,7 @@ import time from django.conf import settings +from django.core.cache import cache from django.db import models from django.utils.translation import ugettext_lazy as _ @@ -35,6 +36,10 @@ class TerminalStatusMixin: return False return time.time() - self.last_stat.date_created.timestamp() < 150 + def set_alive(self, ttl=120): + key = self.ALIVE_KEY.format(self.id) + cache.set(key, True, ttl) + class StorageMixin: command_storage: str From 344451ba553793d93bdc45a62289f189bbc8844c Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 29 Mar 2023 14:28:00 +0800 Subject: [PATCH 5/6] =?UTF-8?q?perf:=20navicat=20=E7=A7=BB=E5=88=B0?= =?UTF-8?q?=E4=BC=81=E4=B8=9A=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/applets/navicat/README.md | 4 - apps/terminal/applets/navicat/app.py | 411 ------------------ apps/terminal/applets/navicat/common.py | 215 --------- apps/terminal/applets/navicat/const.py | 8 - apps/terminal/applets/navicat/i18n.yml | 3 - apps/terminal/applets/navicat/icon.png | Bin 5132 -> 0 bytes apps/terminal/applets/navicat/main.py | 22 - apps/terminal/applets/navicat/manifest.yml | 17 - apps/terminal/applets/navicat/setup.yml | 6 - .../deploy_applet_host/playbook.yml | 13 - 10 files changed, 699 deletions(-) delete mode 100644 apps/terminal/applets/navicat/README.md delete mode 100644 apps/terminal/applets/navicat/app.py delete mode 100644 apps/terminal/applets/navicat/common.py delete mode 100644 apps/terminal/applets/navicat/const.py delete mode 100644 apps/terminal/applets/navicat/i18n.yml delete mode 100644 apps/terminal/applets/navicat/icon.png delete mode 100644 apps/terminal/applets/navicat/main.py delete mode 100644 apps/terminal/applets/navicat/manifest.yml delete mode 100644 apps/terminal/applets/navicat/setup.yml diff --git a/apps/terminal/applets/navicat/README.md b/apps/terminal/applets/navicat/README.md deleted file mode 100644 index ee18cd491..000000000 --- a/apps/terminal/applets/navicat/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## Navicat Premium - -- 需要先手动导入License激活 - diff --git a/apps/terminal/applets/navicat/app.py b/apps/terminal/applets/navicat/app.py deleted file mode 100644 index 7c2dfd3bc..000000000 --- a/apps/terminal/applets/navicat/app.py +++ /dev/null @@ -1,411 +0,0 @@ -import os -import shutil -import time - -import winreg -import win32api -import win32con - -import const as c - -from pywinauto import Application -from pywinauto.keyboard import send_keys -from pywinauto.controls.uia_controls import ( - EditWrapper, ComboBoxWrapper, ButtonWrapper -) - -from common import wait_pid, BaseApplication, _messageBox - -_default_path = r'C:\Program Files\PremiumSoft\Navicat Premium 16\navicat.exe' - - -class AppletApplication(BaseApplication): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.path = _default_path - self.username = self.account.username - self.password = self.account.secret - self.privileged = self.account.privileged - self.host = self.asset.address - self.port = self.asset.get_protocol_port(self.protocol) - self.db = self.asset.spec_info.db_name - self.name = '%s-%s-%s' % (self.host, self.db, int(time.time())) - self.use_ssl = self.asset.spec_info.use_ssl - self.client_key = self.asset.secret_info.client_key - self.client_key_path = None - self.pid = None - self.app = None - - @staticmethod - def get_cert_path(): - win_user_name = win32api.GetUserName() - cert_path = r'C:\Users\%s\AppData\Roaming\Navicat\certs' % win_user_name - return cert_path - - def clean_up(self): - protocols = ( - 'NavicatMARIADB', 'NavicatMONGODB', 'Navicat', - 'NavicatORA', 'NavicatMSSQL', 'NavicatPG' - ) - for p in protocols: - sub_key = r'Software\PremiumSoft\%s\Servers' % p - try: - win32api.RegDeleteTree(winreg.HKEY_CURRENT_USER, sub_key) - except Exception: - pass - cert_path = self.get_cert_path() - shutil.rmtree(cert_path, ignore_errors=True) - - def gen_asset_file(self): - if self.use_ssl and self.client_key: - cert_path = self.get_cert_path() - if not os.path.exists(cert_path): - os.makedirs(cert_path, exist_ok=True) - filepath = os.path.join(cert_path, str(int(time.time()))) - with open(filepath, 'w') as f: - f.write(self.client_key) - self.client_key_path = filepath - - @staticmethod - def edit_regedit(): - sub_key = r'Software\PremiumSoft\NavicatPremium' - try: - key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, sub_key) - # 禁止弹出欢迎页面 - winreg.SetValueEx(key, 'AlreadyShowNavicatV16WelcomeScreen', 0, winreg.REG_DWORD, 1) - # 禁止开启自动检查更新 - winreg.SetValueEx(key, 'AutoCheckUpdate', 0, winreg.REG_DWORD, 0) - # 禁止弹出初始化界面 - winreg.SetValueEx(key, 'ShareUsageData', 0, winreg.REG_DWORD, 0) - except Exception as err: - print('Launch error: %s' % err) - - def launch(self): - # 清理因为异常未关闭的会话历史记录 - self.clean_up() - # 生成资产依赖的相关文件 - self.gen_asset_file() - # 修改注册表,达到一些配置目的 - self.edit_regedit() - - @staticmethod - def _exec_commands(commands): - for command in commands: - pre_check = command.get('pre_check', lambda: True) - if not pre_check(): - _messageBox('程序启动异常,请重新连接!!', 'Error', win32con.MB_DEFAULT_DESKTOP_ONLY) - return - - time.sleep(0.5) - if command['type'] == 'key': - send_keys(' '.join(command['commands'])) - elif command['type'] == 'action': - for f in command['commands']: - f() - - def _pre_check_is_password_input(self): - try: - self.app.window(best_match='Connection Password') - except Exception: - return False - return True - - def _action_ele_click(self, ele_name, conn_win=None): - if not conn_win: - conn_win = self.app.window(best_match='Dialog'). \ - child_window(title_re='New Connection') - conn_win.child_window(best_match=ele_name).click() - - def _fill_mysql_auth_info(self): - conn_window = self.app.window(best_match='Dialog'). \ - child_window(title_re='New Connection') - - name_ele = conn_window.child_window(best_match='Edit5') - EditWrapper(name_ele.element_info).set_edit_text(self.name) - - host_ele = conn_window.child_window(best_match='Edit4') - EditWrapper(host_ele.element_info).set_edit_text(self.host) - - port_ele = conn_window.child_window(best_match='Edit2') - EditWrapper(port_ele.element_info).set_edit_text(self.port) - - username_ele = conn_window.child_window(best_match='Edit1') - EditWrapper(username_ele.element_info).set_edit_text(self.username) - - def _get_mysql_commands(self): - commands = [ - { - 'type': 'key', - 'commands': [ - '%f', c.DOWN, c.RIGHT, c.ENTER - ], - }, - { - 'type': 'action', - 'commands': [ - self._fill_mysql_auth_info, lambda: self._action_ele_click('Save password') - ] - }, - { - 'type': 'key', - 'commands': [c.ENTER] - } - ] - return commands - - def _get_mariadb_commands(self): - commands = [ - { - 'type': 'key', - 'commands': [ - '%f', c.DOWN, c.RIGHT, c.DOWN * 5, c.ENTER, - ], - }, - { - 'type': 'action', - 'commands': [ - self._fill_mysql_auth_info, lambda: self._action_ele_click('Save password') - ] - }, - { - 'type': 'key', - 'commands': [c.ENTER] - } - ] - return commands - - def _fill_mongodb_auth_info(self): - conn_window = self.app.window(best_match='Dialog'). \ - child_window(title_re='New Connection') - - auth_type_ele = conn_window.child_window(best_match='ComboBox2') - ComboBoxWrapper(auth_type_ele.element_info).select('Password') - - name_ele = conn_window.child_window(best_match='Edit5') - EditWrapper(name_ele.element_info).set_edit_text(self.name) - - host_ele = conn_window.child_window(best_match='Edit4') - EditWrapper(host_ele.element_info).set_edit_text(self.host) - - port_ele = conn_window.child_window(best_match='Edit2') - EditWrapper(port_ele.element_info).set_edit_text(self.port) - - db_ele = conn_window.child_window(best_match='Edit6') - EditWrapper(db_ele.element_info).set_edit_text(self.db) - - username_ele = conn_window.child_window(best_match='Edit1') - EditWrapper(username_ele.element_info).set_edit_text(self.username) - - def _get_mongodb_commands(self): - commands = [ - { - 'type': 'key', - 'commands': [ - '%f', c.DOWN, c.RIGHT, c.DOWN * 6, c.ENTER, - ], - }, - { - 'type': 'action', - 'commands': [ - self._fill_mongodb_auth_info, lambda: self._action_ele_click('Save password') - ] - }, - { - 'type': 'key', - 'commands': [c.ENTER] - } - ] - if self.use_ssl: - ssl_commands = [ - { - 'type': 'key', - 'commands': [c.TAB * 5, c.RIGHT * 3, c.TAB] - }, - { - 'type': 'action', - 'commands': [ - lambda: self._action_ele_click('Use SSL'), - lambda: self._action_ele_click('Use authentication'), - ] - }, - { - 'type': 'key', - 'commands': [c.TAB, self.client_key_path] - }, - { - 'type': 'action', - 'commands': [lambda: self._action_ele_click('Allow invalid host names')] - } - ] - commands = commands[:2] + ssl_commands + commands[2:] - return commands - - def _fill_postgresql_auth_info(self): - conn_window = self.app.window(best_match='Dialog'). \ - child_window(title_re='New Connection') - - name_ele = conn_window.child_window(best_match='Edit6') - EditWrapper(name_ele.element_info).set_edit_text(self.name) - - host_ele = conn_window.child_window(best_match='Edit5') - EditWrapper(host_ele.element_info).set_edit_text(self.host) - - port_ele = conn_window.child_window(best_match='Edit2') - EditWrapper(port_ele.element_info).set_edit_text(self.port) - - db_ele = conn_window.child_window(best_match='Edit4') - EditWrapper(db_ele.element_info).set_edit_text(self.db) - - username_ele = conn_window.child_window(best_match='Edit1') - EditWrapper(username_ele.element_info).set_edit_text(self.username) - - def _get_postgresql_commands(self): - commands = [ - { - 'type': 'key', - 'commands': [ - '%f', c.DOWN, c.RIGHT, c.DOWN, c.ENTER, - ], - }, - { - 'type': 'action', - 'commands': [ - self._fill_postgresql_auth_info, lambda: self._action_ele_click('Save password') - ] - }, - { - 'type': 'key', - 'commands': [c.ENTER] - } - ] - return commands - - def _fill_sqlserver_auth_info(self): - conn_window = self.app.window(best_match='Dialog'). \ - child_window(title_re='New Connection') - - name_ele = conn_window.child_window(best_match='Edit5') - EditWrapper(name_ele.element_info).set_edit_text(self.name) - - host_ele = conn_window.child_window(best_match='Edit4') - EditWrapper(host_ele.element_info).set_edit_text('%s,%s' % (self.host, self.port)) - - db_ele = conn_window.child_window(best_match='Edit3') - EditWrapper(db_ele.element_info).set_edit_text(self.db) - - username_ele = conn_window.child_window(best_match='Edit6') - EditWrapper(username_ele.element_info).set_edit_text(self.username) - - def _get_sqlserver_commands(self): - commands = [ - { - 'type': 'key', - 'commands': [ - '%f', c.DOWN, c.RIGHT, c.DOWN * 4, c.ENTER, - ], - }, - { - 'type': 'action', - 'commands': [ - self._fill_sqlserver_auth_info, lambda: self._action_ele_click('Save password') - ] - }, - { - 'type': 'key', - 'commands': [c.ENTER] - } - ] - return commands - - def _fill_oracle_auth_info(self): - conn_window = self.app.window(best_match='Dialog'). \ - child_window(title_re='New Connection') - - name_ele = conn_window.child_window(best_match='Edit6') - EditWrapper(name_ele.element_info).set_edit_text(self.name) - - host_ele = conn_window.child_window(best_match='Edit5') - EditWrapper(host_ele.element_info).set_edit_text(self.host) - - port_ele = conn_window.child_window(best_match='Edit3') - EditWrapper(port_ele.element_info).set_edit_text(self.port) - - db_ele = conn_window.child_window(best_match='Edit2') - EditWrapper(db_ele.element_info).set_edit_text(self.db) - - username_ele = conn_window.child_window(best_match='Edit') - EditWrapper(username_ele.element_info).set_edit_text(self.username) - - if self.privileged: - conn_window.child_window(best_match='Advanced', control_type='TabItem').click_input() - role_ele = conn_window.child_window(best_match='ComboBox2') - ComboBoxWrapper(role_ele.element_info).select('SYSDBA') - - def _get_oracle_commands(self): - commands = [ - { - 'type': 'key', - 'commands': [ - '%f', c.DOWN, c.RIGHT, c.DOWN * 2, c.ENTER, - ], - }, - { - 'type': 'action', - 'commands': [ - lambda: self._action_ele_click('Save password'), self._fill_oracle_auth_info - ] - }, - { - 'type': 'key', - 'commands': [c.ENTER] - } - ] - return commands - - def run(self): - self.launch() - self.app = Application(backend='uia') - work_dir = os.path.dirname(self.path) - self.app.start(self.path, work_dir=work_dir) - self.pid = self.app.process - - # 检测是否为试用版本 - try: - trial_btn = self.app.top_window().child_window( - best_match='Trial', control_type='Button' - ) - ButtonWrapper(trial_btn.element_info).click() - time.sleep(0.5) - except Exception: - pass - - # 根据协议获取相应操作命令 - action = getattr(self, '_get_%s_commands' % self.protocol, None) - if action is None: - raise ValueError('This protocol is not supported: %s' % self.protocol) - commands = action() - # 关闭掉桌面许可弹框 - commands.insert(0, {'type': 'key', 'commands': (c.ESC,)}) - # 登录 - commands.extend([ - { - 'type': 'key', - 'commands': ( - '%f', c.DOWN * 5, c.ENTER - ) - }, - { - 'type': 'key', - 'commands': (self.password, c.ENTER), - 'pre_check': self._pre_check_is_password_input - } - ]) - self._exec_commands(commands) - - def wait(self): - try: - wait_pid(self.pid) - except Exception: - pass - finally: - self.clean_up() diff --git a/apps/terminal/applets/navicat/common.py b/apps/terminal/applets/navicat/common.py deleted file mode 100644 index 62becd792..000000000 --- a/apps/terminal/applets/navicat/common.py +++ /dev/null @@ -1,215 +0,0 @@ -import abc -import base64 -import json -import locale -import os -import subprocess -import sys -import time -from subprocess import CREATE_NO_WINDOW - -_blockInput = None -_messageBox = None -if sys.platform == 'win32': - import ctypes - from ctypes import wintypes - import win32ui - - # import win32con - - _messageBox = win32ui.MessageBox - - _blockInput = ctypes.windll.user32.BlockInput - _blockInput.argtypes = [wintypes.BOOL] - _blockInput.restype = wintypes.BOOL - - -def block_input(): - if _blockInput: - _blockInput(True) - - -def unblock_input(): - if _blockInput: - _blockInput(False) - - -def decode_content(content: bytes) -> str: - for encoding_name in ['utf-8', 'gbk', 'gb2312']: - try: - return content.decode(encoding_name) - except Exception as e: - print(e) - encoding_name = locale.getpreferredencoding() - return content.decode(encoding_name) - - -def notify_err_message(msg): - if _messageBox: - _messageBox(msg, 'Error') - - -def check_pid_alive(pid) -> bool: - # tasklist /fi "PID eq 508" /fo csv - # '"映像名称","PID","会话名 ","会话# ","内存使用 "\r\n"wininit.exe","508","Services","0","6,920 K"\r\n' - try: - - csv_ret = subprocess.check_output(["tasklist", "/fi", f'PID eq {pid}', "/fo", "csv"], - creationflags=CREATE_NO_WINDOW) - content = decode_content(csv_ret) - content_list = content.strip().split("\r\n") - if len(content_list) != 2: - print("check pid {} ret invalid: {}".format(pid, content)) - return False - ret_pid = content_list[1].split(",")[1].strip('"') - return str(pid) == ret_pid - except Exception as e: - print("check pid {} err: {}".format(pid, e)) - return False - - -def wait_pid(pid): - while 1: - time.sleep(5) - ok = check_pid_alive(pid) - if not ok: - print("pid {} is not alive".format(pid)) - break - - -class DictObj: - def __init__(self, in_dict: dict): - assert isinstance(in_dict, dict) - for key, val in in_dict.items(): - if isinstance(val, (list, tuple)): - setattr(self, key, [DictObj(x) if isinstance(x, dict) else x for x in val]) - else: - setattr(self, key, DictObj(val) if isinstance(val, dict) else val) - - -class User(DictObj): - id: str - name: str - username: str - - -class Specific(DictObj): - # web - autofill: str - username_selector: str - password_selector: str - submit_selector: str - script: list - - # database - db_name: str - use_ssl: str - - -class Secret(DictObj): - client_key: str - - -class Category(DictObj): - value: str - label: str - - -class Protocol(DictObj): - id: str - name: str - port: int - - -class Asset(DictObj): - id: str - name: str - address: str - protocols: list[Protocol] - category: Category - spec_info: Specific - secret_info: Secret - - def get_protocol_port(self, protocol): - for item in self.protocols: - if item.name == protocol: - return item.port - return None - - -class LabelValue(DictObj): - label: str - value: str - - -class Account(DictObj): - id: str - name: str - username: str - secret: str - privileged: bool - secret_type: LabelValue - - -class Platform(DictObj): - charset: str - name: str - charset: LabelValue - type: LabelValue - - -class Manifest(DictObj): - name: str - version: str - path: str - exec_type: str - connect_type: str - protocols: list[str] - - -def get_manifest_data() -> dict: - current_dir = os.path.dirname(__file__) - manifest_file = os.path.join(current_dir, 'manifest.json') - try: - with open(manifest_file, "r", encoding='utf8') as f: - return json.load(f) - except Exception as e: - print(e) - return {} - - -def read_app_manifest(app_dir) -> dict: - main_json_file = os.path.join(app_dir, "manifest.json") - if not os.path.exists(main_json_file): - return {} - with open(main_json_file, 'r', encoding='utf8') as f: - return json.load(f) - - -def convert_base64_to_dict(base64_str: str) -> dict: - try: - data_json = base64.decodebytes(base64_str.encode('utf-8')).decode('utf-8') - return json.loads(data_json) - except Exception as e: - print(e) - return {} - - -class BaseApplication(abc.ABC): - - def __init__(self, *args, **kwargs): - self.app_name = kwargs.get('app_name', '') - self.protocol = kwargs.get('protocol', '') - self.manifest = Manifest(kwargs.get('manifest', {})) - self.user = User(kwargs.get('user', {})) - self.asset = Asset(kwargs.get('asset', {})) - self.account = Account(kwargs.get('account', {})) - self.platform = Platform(kwargs.get('platform', {})) - - @abc.abstractmethod - def run(self): - raise NotImplementedError('run') - - @abc.abstractmethod - def wait(self): - raise NotImplementedError('wait') diff --git a/apps/terminal/applets/navicat/const.py b/apps/terminal/applets/navicat/const.py deleted file mode 100644 index 7c186b8cc..000000000 --- a/apps/terminal/applets/navicat/const.py +++ /dev/null @@ -1,8 +0,0 @@ - -UP = '{UP}' -LEFT = '{LEFT}' -DOWN = '{DOWN}' -RIGHT = '{RIGHT}' -TAB = '{VK_TAB}' -ESC = '{ESC}' -ENTER = '{VK_RETURN}' diff --git a/apps/terminal/applets/navicat/i18n.yml b/apps/terminal/applets/navicat/i18n.yml deleted file mode 100644 index ec6427048..000000000 --- a/apps/terminal/applets/navicat/i18n.yml +++ /dev/null @@ -1,3 +0,0 @@ -- zh: - display_name: Navicat premium 16 - comment: 数据库管理软件 diff --git a/apps/terminal/applets/navicat/icon.png b/apps/terminal/applets/navicat/icon.png deleted file mode 100644 index 10b343bf0144f6b88f9d36eeb86db264eca67579..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5132 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 z Date: Wed, 29 Mar 2023 15:17:55 +0800 Subject: [PATCH 6/6] =?UTF-8?q?perf:=20issues=20=E6=A8=A1=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/ISSUE_TEMPLATE/----.md | 5 ++++- .github/ISSUE_TEMPLATE/bug---.md | 4 +++- .github/ISSUE_TEMPLATE/question.md | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/----.md b/.github/ISSUE_TEMPLATE/----.md index b407e8a25..147f42db4 100644 --- a/.github/ISSUE_TEMPLATE/----.md +++ b/.github/ISSUE_TEMPLATE/----.md @@ -3,7 +3,10 @@ name: 需求建议 about: 提出针对本项目的想法和建议 title: "[Feature] " labels: 类型:需求 -assignees: ibuler +assignees: + - ibuler + - baijiangjie + --- diff --git a/.github/ISSUE_TEMPLATE/bug---.md b/.github/ISSUE_TEMPLATE/bug---.md index 3c590459c..e4a21adde 100644 --- a/.github/ISSUE_TEMPLATE/bug---.md +++ b/.github/ISSUE_TEMPLATE/bug---.md @@ -3,7 +3,9 @@ name: Bug 提交 about: 提交产品缺陷帮助我们更好的改进 title: "[Bug] " labels: 类型:bug -assignees: wojiushixiaobai +assignees: + - wojiushixiaobai + - baijiangjie --- diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index 1dd2a68d6..b15719590 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -3,7 +3,9 @@ name: 问题咨询 about: 提出针对本项目安装部署、使用及其他方面的相关问题 title: "[Question] " labels: 类型:提问 -assignees: wojiushixiaobai +assignees: + - wojiushixiaobai + - baijiangjie ---