From 96ef56da6721af36b13cc50c6017042ffcffc9f9 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 15 Jun 2023 15:41:07 +0800 Subject: [PATCH 001/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=20(#10733)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 62 ++++++++++++++-------------- apps/locale/zh/LC_MESSAGES/django.mo | 2 +- apps/locale/zh/LC_MESSAGES/django.po | 62 ++++++++++++++-------------- 4 files changed, 65 insertions(+), 65 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 3d7539330..f057cb635 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a76aa384867a4732eb7d2365515a1a972502ebadcba4de8236c1dcb3c5c7fdd2 -size 145757 +oid sha256:cd4fb6a0396c8636f8a36645354a5102790c020d73cdeb1f0e1d1f1b34ea39e9 +size 145760 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index aee6c1f8c..dbfc085e6 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-14 20:40+0800\n" +"POT-Creation-Date: 2023-06-15 15:35+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -28,7 +28,7 @@ msgstr "パラメータ 'action' は [{}] でなければなりません。" #: authentication/confirm/password.py:9 authentication/forms.py:32 #: authentication/templates/authentication/login.html:274 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 -#: users/forms/profile.py:22 users/serializers/user.py:105 +#: users/forms/profile.py:22 users/serializers/user.py:104 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:28 @@ -505,7 +505,7 @@ msgstr "特権アカウント" #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:114 -#: terminal/models/applet/applet.py:39 users/serializers/user.py:170 +#: terminal/models/applet/applet.py:39 users/serializers/user.py:169 msgid "Is active" msgstr "アクティブです。" @@ -1281,7 +1281,7 @@ msgstr "資産ハードウェア情報の収集" #: assets/models/asset/common.py:159 assets/serializers/asset/custom.py:14 msgid "Custom info" -msgstr "自动化信息" +msgstr "カスタム属性" #: assets/models/asset/common.py:335 msgid "Can refresh asset hardware info" @@ -1645,8 +1645,8 @@ msgstr "プロトコルが必要です: {}" msgid "Default database" msgstr "デフォルト・データベース" -#: assets/serializers/asset/database.py:28 common/db/fields.py:570 -#: common/db/fields.py:575 common/serializers/fields.py:104 +#: assets/serializers/asset/database.py:28 common/db/fields.py:579 +#: common/db/fields.py:584 common/serializers/fields.py:104 #: tickets/serializers/ticket/common.py:58 #: xpack/plugins/cloud/serializers/account_attrs.py:56 #: xpack/plugins/cloud/serializers/account_attrs.py:79 @@ -2654,7 +2654,7 @@ msgstr "アクション" #: authentication/serializers/connection_token.py:44 #: perms/serializers/permission.py:38 perms/serializers/permission.py:57 -#: users/serializers/user.py:97 users/serializers/user.py:173 +#: users/serializers/user.py:96 users/serializers/user.py:172 msgid "Is expired" msgstr "期限切れです" @@ -2680,8 +2680,8 @@ msgid "The {} cannot be empty" msgstr "{} 空にしてはならない" #: authentication/serializers/token.py:79 perms/serializers/permission.py:37 -#: perms/serializers/permission.py:58 users/serializers/user.py:98 -#: users/serializers/user.py:171 +#: perms/serializers/permission.py:58 users/serializers/user.py:97 +#: users/serializers/user.py:170 msgid "Is valid" msgstr "有効です" @@ -3116,7 +3116,7 @@ msgstr "テキストフィールドへのマーシャルデータ" msgid "Encrypt field using Secret Key" msgstr "Secret Keyを使用したフィールドの暗号化" -#: common/db/fields.py:558 +#: common/db/fields.py:567 msgid "" "Invalid JSON data for JSONManyToManyField, should be like {'type': 'all'} or " "{'type': 'ids', 'ids': []} or {'type': 'attrs', 'attrs': [{'name': 'ip', " @@ -3126,19 +3126,19 @@ msgstr "" "{'type':'ids','ids':[]}或 #タイプ:属性、属性:[#名前:ip、照合:正確、" "値:1.1.1.1}" -#: common/db/fields.py:565 +#: common/db/fields.py:574 msgid "Invalid type, should be \"all\", \"ids\" or \"attrs\"" msgstr "無効なタイプです。all、ids、またはattrsでなければなりません" -#: common/db/fields.py:568 +#: common/db/fields.py:577 msgid "Invalid ids for ids, should be a list" msgstr "無効なID、リストでなければなりません" -#: common/db/fields.py:573 common/db/fields.py:578 +#: common/db/fields.py:582 common/db/fields.py:587 msgid "Invalid attrs, should be a list of dict" msgstr "無効な属性、dictリストでなければなりません" -#: common/db/fields.py:580 +#: common/db/fields.py:589 msgid "Invalid attrs, should be has name and value" msgstr "名前と値が必要な無効な属性" @@ -3654,7 +3654,7 @@ msgstr "Material" msgid "Material Type" msgstr "Material を選択してオプションを設定します。" -#: ops/models/job.py:460 +#: ops/models/job.py:461 msgid "Job Execution" msgstr "ジョブ実行" @@ -6711,7 +6711,7 @@ msgstr "公開キー" msgid "Force enable" msgstr "強制有効" -#: users/models/user.py:765 users/serializers/user.py:172 +#: users/models/user.py:765 users/serializers/user.py:171 msgid "Is service account" msgstr "サービスアカウントです" @@ -6723,7 +6723,7 @@ msgstr "アバター" msgid "Wechat" msgstr "微信" -#: users/models/user.py:773 users/serializers/user.py:109 +#: users/models/user.py:773 users/serializers/user.py:108 msgid "Phone" msgstr "電話" @@ -6740,7 +6740,7 @@ msgid "Secret key" msgstr "秘密キー" #: users/models/user.py:794 users/serializers/profile.py:149 -#: users/serializers/user.py:169 +#: users/serializers/user.py:168 msgid "Is first login" msgstr "最初のログインです" @@ -6823,55 +6823,55 @@ msgstr "新しいパスワードを最後の {} 個のパスワードにする msgid "The newly set password is inconsistent" msgstr "新しく設定されたパスワードが一致しない" -#: users/serializers/user.py:43 +#: users/serializers/user.py:42 msgid "System roles" msgstr "システムの役割" -#: users/serializers/user.py:47 +#: users/serializers/user.py:46 msgid "Org roles" msgstr "組織ロール" -#: users/serializers/user.py:90 +#: users/serializers/user.py:89 msgid "Password strategy" msgstr "パスワード戦略" -#: users/serializers/user.py:92 +#: users/serializers/user.py:91 msgid "MFA enabled" msgstr "MFA有効化" -#: users/serializers/user.py:94 +#: users/serializers/user.py:93 msgid "MFA force enabled" msgstr "MFAフォース有効化" -#: users/serializers/user.py:96 +#: users/serializers/user.py:95 msgid "Login blocked" msgstr "ログインがロックされました" -#: users/serializers/user.py:99 users/serializers/user.py:177 +#: users/serializers/user.py:98 users/serializers/user.py:176 msgid "Is OTP bound" msgstr "仮想MFAがバインドされているか" -#: users/serializers/user.py:101 +#: users/serializers/user.py:100 msgid "Can public key authentication" msgstr "公開鍵認証が可能" -#: users/serializers/user.py:174 +#: users/serializers/user.py:173 msgid "Avatar url" msgstr "アバターURL" -#: users/serializers/user.py:178 +#: users/serializers/user.py:177 msgid "MFA level" msgstr "MFA レベル" -#: users/serializers/user.py:284 +#: users/serializers/user.py:283 msgid "Select users" msgstr "ユーザーの選択" -#: users/serializers/user.py:285 +#: users/serializers/user.py:284 msgid "For security, only list several users" msgstr "セキュリティのために、複数のユーザーのみをリストします" -#: users/serializers/user.py:318 +#: users/serializers/user.py:317 msgid "name not unique" msgstr "名前が一意ではない" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index ef7c79319..1c7c46cca 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f32e327dd50762b76d209f80b7de470df6faf5242af383dd6152b0c7ea5a7974 +oid sha256:0efb248e80873f34d20f0fc3d4dd5c5a346048cb683c2b6bda3df939697fc52c size 119261 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 3408c2622..48b00a44f 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-14 20:40+0800\n" +"POT-Creation-Date: 2023-06-15 15:35+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -27,7 +27,7 @@ msgstr "参数 'action' 必须是 [{}]" #: authentication/confirm/password.py:9 authentication/forms.py:32 #: authentication/templates/authentication/login.html:274 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 -#: users/forms/profile.py:22 users/serializers/user.py:105 +#: users/forms/profile.py:22 users/serializers/user.py:104 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:28 @@ -504,7 +504,7 @@ msgstr "特权账号" #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:114 -#: terminal/models/applet/applet.py:39 users/serializers/user.py:170 +#: terminal/models/applet/applet.py:39 users/serializers/user.py:169 msgid "Is active" msgstr "激活" @@ -1274,7 +1274,7 @@ msgstr "收集资产硬件信息" #: assets/models/asset/common.py:159 assets/serializers/asset/custom.py:14 msgid "Custom info" -msgstr "自动化信息" +msgstr "自定义属性" #: assets/models/asset/common.py:335 msgid "Can refresh asset hardware info" @@ -1636,8 +1636,8 @@ msgstr "协议是必填的: {}" msgid "Default database" msgstr "默认数据库" -#: assets/serializers/asset/database.py:28 common/db/fields.py:570 -#: common/db/fields.py:575 common/serializers/fields.py:104 +#: assets/serializers/asset/database.py:28 common/db/fields.py:579 +#: common/db/fields.py:584 common/serializers/fields.py:104 #: tickets/serializers/ticket/common.py:58 #: xpack/plugins/cloud/serializers/account_attrs.py:56 #: xpack/plugins/cloud/serializers/account_attrs.py:79 @@ -2629,7 +2629,7 @@ msgstr "动作" #: authentication/serializers/connection_token.py:44 #: perms/serializers/permission.py:38 perms/serializers/permission.py:57 -#: users/serializers/user.py:97 users/serializers/user.py:173 +#: users/serializers/user.py:96 users/serializers/user.py:172 msgid "Is expired" msgstr "已过期" @@ -2653,8 +2653,8 @@ msgid "The {} cannot be empty" msgstr "{} 不能为空" #: authentication/serializers/token.py:79 perms/serializers/permission.py:37 -#: perms/serializers/permission.py:58 users/serializers/user.py:98 -#: users/serializers/user.py:171 +#: perms/serializers/permission.py:58 users/serializers/user.py:97 +#: users/serializers/user.py:170 msgid "Is valid" msgstr "是否有效" @@ -3081,7 +3081,7 @@ msgstr "编码数据为 text" msgid "Encrypt field using Secret Key" msgstr "加密的字段" -#: common/db/fields.py:558 +#: common/db/fields.py:567 msgid "" "Invalid JSON data for JSONManyToManyField, should be like {'type': 'all'} or " "{'type': 'ids', 'ids': []} or {'type': 'attrs', 'attrs': [{'name': 'ip', " @@ -3091,19 +3091,19 @@ msgstr "" "{'type': 'attrs', 'attrs': [{'name': 'ip', 'match': 'exact', 'value': " "'1.1.1.1'}}" -#: common/db/fields.py:565 +#: common/db/fields.py:574 msgid "Invalid type, should be \"all\", \"ids\" or \"attrs\"" msgstr "无效类型,应为 all、ids 或 attrs" -#: common/db/fields.py:568 +#: common/db/fields.py:577 msgid "Invalid ids for ids, should be a list" msgstr "无效的ID,应为列表" -#: common/db/fields.py:573 common/db/fields.py:578 +#: common/db/fields.py:582 common/db/fields.py:587 msgid "Invalid attrs, should be a list of dict" msgstr "无效的属性,应为dict列表" -#: common/db/fields.py:580 +#: common/db/fields.py:589 msgid "Invalid attrs, should be has name and value" msgstr "无效属性,应具有名称和值" @@ -3612,7 +3612,7 @@ msgstr "Material" msgid "Material Type" msgstr "Material 类型" -#: ops/models/job.py:460 +#: ops/models/job.py:461 msgid "Job Execution" msgstr "作业执行" @@ -6618,7 +6618,7 @@ msgstr "SSH公钥" msgid "Force enable" msgstr "强制启用" -#: users/models/user.py:765 users/serializers/user.py:172 +#: users/models/user.py:765 users/serializers/user.py:171 msgid "Is service account" msgstr "服务账号" @@ -6630,7 +6630,7 @@ msgstr "头像" msgid "Wechat" msgstr "微信" -#: users/models/user.py:773 users/serializers/user.py:109 +#: users/models/user.py:773 users/serializers/user.py:108 msgid "Phone" msgstr "手机" @@ -6647,7 +6647,7 @@ msgid "Secret key" msgstr "Secret key" #: users/models/user.py:794 users/serializers/profile.py:149 -#: users/serializers/user.py:169 +#: users/serializers/user.py:168 msgid "Is first login" msgstr "首次登录" @@ -6730,55 +6730,55 @@ msgstr "新密码不能是最近 {} 次的密码" msgid "The newly set password is inconsistent" msgstr "两次密码不一致" -#: users/serializers/user.py:43 +#: users/serializers/user.py:42 msgid "System roles" msgstr "系统角色" -#: users/serializers/user.py:47 +#: users/serializers/user.py:46 msgid "Org roles" msgstr "组织角色" -#: users/serializers/user.py:90 +#: users/serializers/user.py:89 msgid "Password strategy" msgstr "密码策略" -#: users/serializers/user.py:92 +#: users/serializers/user.py:91 msgid "MFA enabled" msgstr "MFA 已启用" -#: users/serializers/user.py:94 +#: users/serializers/user.py:93 msgid "MFA force enabled" msgstr "强制 MFA" -#: users/serializers/user.py:96 +#: users/serializers/user.py:95 msgid "Login blocked" msgstr "登录被锁定" -#: users/serializers/user.py:99 users/serializers/user.py:177 +#: users/serializers/user.py:98 users/serializers/user.py:176 msgid "Is OTP bound" msgstr "是否绑定了虚拟 MFA" -#: users/serializers/user.py:101 +#: users/serializers/user.py:100 msgid "Can public key authentication" msgstr "可以使用公钥认证" -#: users/serializers/user.py:174 +#: users/serializers/user.py:173 msgid "Avatar url" msgstr "头像路径" -#: users/serializers/user.py:178 +#: users/serializers/user.py:177 msgid "MFA level" msgstr "MFA 级别" -#: users/serializers/user.py:284 +#: users/serializers/user.py:283 msgid "Select users" msgstr "选择用户" -#: users/serializers/user.py:285 +#: users/serializers/user.py:284 msgid "For security, only list several users" msgstr "为了安全,仅列出几个用户" -#: users/serializers/user.py:318 +#: users/serializers/user.py:317 msgid "name not unique" msgstr "名称重复" From c06368d812465afa9ea99e66463bcca42dd90a6f Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 15 Jun 2023 16:53:28 +0800 Subject: [PATCH 002/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E9=95=9C=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 4 ++-- Dockerfile.loong64 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3dc78a9df..2183c7b36 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9-slim-buster as stage-build +FROM python:3.9-slim-bullseye as stage-build ARG TARGETARCH ARG VERSION @@ -8,7 +8,7 @@ WORKDIR /opt/jumpserver ADD . . RUN cd utils && bash -ixeu build.sh -FROM python:3.9-slim-buster +FROM python:3.9-slim-bullseye ARG TARGETARCH MAINTAINER JumpServer Team diff --git a/Dockerfile.loong64 b/Dockerfile.loong64 index f5682aec2..72b172794 100644 --- a/Dockerfile.loong64 +++ b/Dockerfile.loong64 @@ -1,4 +1,4 @@ -FROM python:3.9-slim-buster as stage-build +FROM python:3.9-slim-bullseye as stage-build ARG TARGETARCH ARG VERSION @@ -8,7 +8,7 @@ WORKDIR /opt/jumpserver ADD . . RUN cd utils && bash -ixeu build.sh -FROM python:3.9-slim-buster +FROM python:3.9-slim-bullseye ARG TARGETARCH MAINTAINER JumpServer Team From 269a5e9d52e7199375d151a0dba7539f45b74579 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 15 Jun 2023 17:27:41 +0800 Subject: [PATCH 003/167] =?UTF-8?q?perf:=20=E9=BE=99=E8=8A=AF=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20buster=20=E9=95=9C=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile.loong64 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.loong64 b/Dockerfile.loong64 index 72b172794..f5682aec2 100644 --- a/Dockerfile.loong64 +++ b/Dockerfile.loong64 @@ -1,4 +1,4 @@ -FROM python:3.9-slim-bullseye as stage-build +FROM python:3.9-slim-buster as stage-build ARG TARGETARCH ARG VERSION @@ -8,7 +8,7 @@ WORKDIR /opt/jumpserver ADD . . RUN cd utils && bash -ixeu build.sh -FROM python:3.9-slim-bullseye +FROM python:3.9-slim-buster ARG TARGETARCH MAINTAINER JumpServer Team From cdd47f4bc6d01c73485305e959d886f8ca28255a Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 15 Jun 2023 18:13:51 +0800 Subject: [PATCH 004/167] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=20acl=20?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=E5=90=8E=E6=97=A0=E6=B3=95=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/db/fields.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/common/db/fields.py b/apps/common/db/fields.py index 5b7ee7c5f..d1695c19d 100644 --- a/apps/common/db/fields.py +++ b/apps/common/db/fields.py @@ -328,13 +328,13 @@ class RelatedManager: q = Q() if isinstance(val, str): val = [val] + if ['*'] in val: + return Q() for ip in val: if not ip: continue try: - if ip == '*': - return Q() - elif '/' in ip: + if '/' in ip: network = ipaddress.ip_network(ip) ips = network.hosts() q |= Q(**{"{}__in".format(name): ips}) @@ -378,7 +378,7 @@ class RelatedManager: if match == 'ip_in': q = cls.get_ip_in_q(name, val) - elif match in ("exact", "contains", "startswith", "endswith", "gte", "lte", "gt", "lt"): + elif match in ("contains", "startswith", "endswith", "gte", "lte", "gt", "lt"): lookup = "{}__{}".format(name, match) q = Q(**{lookup: val}) elif match == 'regex': @@ -470,9 +470,9 @@ class JSONManyToManyDescriptor: continue if rule_match == 'in': - res &= value in rule_value + res &= value in rule_value or '*' in rule_value elif rule_match == 'exact': - res &= value == rule_value + res &= value == rule_value or rule_value == '*' elif rule_match == 'contains': res &= rule_value in value elif rule_match == 'startswith': @@ -499,7 +499,7 @@ class JSONManyToManyDescriptor: elif rule['match'] == 'ip_in': if isinstance(rule_value, str): rule_value = [rule_value] - res &= contains_ip(value, rule_value) + res &= '*' in rule_value or contains_ip(value, rule_value) elif rule['match'] == 'm2m': if isinstance(value, Manager): value = value.values_list('id', flat=True) From ef4132d2c5c43f2cb4c5f1d20f4d7c6dc61cfcf0 Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Thu, 15 Jun 2023 18:33:05 +0800 Subject: [PATCH 005/167] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=8C=96=E4=BB=BB=E5=8A=A1rdp=20ping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../verify_account/custom/rdp/main.yml | 5 +++-- .../verify_account/custom/ssh/main.yml | 2 +- apps/assets/automations/ping/custom/rdp/main.yml | 15 +++++++++++++++ .../automations/ping/custom/rdp/manifest.yml | 13 +++++++++++++ .../automations/ping/custom/{ => ssh}/main.yml | 2 +- .../ping/custom/{ => ssh}/manifest.yml | 0 apps/ops/ansible/modules/rdp_ping.py | 16 ++++++++++++---- 7 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 apps/assets/automations/ping/custom/rdp/main.yml create mode 100644 apps/assets/automations/ping/custom/rdp/manifest.yml rename apps/assets/automations/ping/custom/{ => ssh}/main.yml (90%) rename apps/assets/automations/ping/custom/{ => ssh}/manifest.yml (100%) diff --git a/apps/accounts/automations/verify_account/custom/rdp/main.yml b/apps/accounts/automations/verify_account/custom/rdp/main.yml index cf4a937a7..b0c7cbe4f 100644 --- a/apps/accounts/automations/verify_account/custom/rdp/main.yml +++ b/apps/accounts/automations/verify_account/custom/rdp/main.yml @@ -1,11 +1,12 @@ - hosts: custom gather_facts: no vars: + ansible_shell_type: sh ansible_connection: local tasks: - - name: Verify account - ssh_ping: + - name: Verify account (pyfreerdp) + rdp_ping: login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" login_user: "{{ account.username }}" diff --git a/apps/accounts/automations/verify_account/custom/ssh/main.yml b/apps/accounts/automations/verify_account/custom/ssh/main.yml index cf4a937a7..29b1dc22b 100644 --- a/apps/accounts/automations/verify_account/custom/ssh/main.yml +++ b/apps/accounts/automations/verify_account/custom/ssh/main.yml @@ -4,7 +4,7 @@ ansible_connection: local tasks: - - name: Verify account + - name: Verify account (paramiko) ssh_ping: login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" diff --git a/apps/assets/automations/ping/custom/rdp/main.yml b/apps/assets/automations/ping/custom/rdp/main.yml new file mode 100644 index 000000000..75e40c027 --- /dev/null +++ b/apps/assets/automations/ping/custom/rdp/main.yml @@ -0,0 +1,15 @@ +- hosts: custom + gather_facts: no + vars: + ansible_shell_type: sh + ansible_connection: local + + tasks: + - name: Test asset connection (pyfreerdp) + rdp_ping: + login_user: "{{ jms_account.username }}" + login_password: "{{ jms_account.secret }}" + login_host: "{{ jms_asset.address }}" + login_port: "{{ jms_asset.port }}" + login_secret_type: "{{ jms_account.secret_type }}" + login_private_key_path: "{{ jms_account.private_key_path }}" diff --git a/apps/assets/automations/ping/custom/rdp/manifest.yml b/apps/assets/automations/ping/custom/rdp/manifest.yml new file mode 100644 index 000000000..77b8a855e --- /dev/null +++ b/apps/assets/automations/ping/custom/rdp/manifest.yml @@ -0,0 +1,13 @@ +id: ping_by_rdp +name: "{{ 'Ping by pyfreerdp' | trans }}" +category: + - device + - host +type: + - windows +method: ping +i18n: + Ping by pyfreerdp: + zh: 使用 Python 模块 pyfreerdp 测试主机可连接性 + en: Ping by pyfreerdp module + ja: Pyfreerdpモジュールを使用してホストにPingする diff --git a/apps/assets/automations/ping/custom/main.yml b/apps/assets/automations/ping/custom/ssh/main.yml similarity index 90% rename from apps/assets/automations/ping/custom/main.yml rename to apps/assets/automations/ping/custom/ssh/main.yml index 50911847b..9725f63d7 100644 --- a/apps/assets/automations/ping/custom/main.yml +++ b/apps/assets/automations/ping/custom/ssh/main.yml @@ -4,7 +4,7 @@ ansible_connection: local tasks: - - name: Test asset connection + - name: Test asset connection (paramiko) ssh_ping: login_user: "{{ jms_account.username }}" login_password: "{{ jms_account.secret }}" diff --git a/apps/assets/automations/ping/custom/manifest.yml b/apps/assets/automations/ping/custom/ssh/manifest.yml similarity index 100% rename from apps/assets/automations/ping/custom/manifest.yml rename to apps/assets/automations/ping/custom/ssh/manifest.yml diff --git a/apps/ops/ansible/modules/rdp_ping.py b/apps/ops/ansible/modules/rdp_ping.py index f069b5bf7..6098f155d 100644 --- a/apps/ops/ansible/modules/rdp_ping.py +++ b/apps/ops/ansible/modules/rdp_ping.py @@ -39,10 +39,6 @@ import pyfreerdp from typing import NamedTuple from ansible.module_utils.basic import AnsibleModule -from ops.ansible.modules_utils.custom_common import ( - common_argument_spec -) - # ========================================= # Module execution. @@ -55,6 +51,18 @@ class Param(NamedTuple): password: str +def common_argument_spec(): + options = dict( + login_host=dict(type='str', required=False, default='localhost'), + login_port=dict(type='int', required=False, default=22), + login_user=dict(type='str', required=False, default='root'), + login_password=dict(type='str', required=False, no_log=True), + login_secret_type=dict(type='str', required=False, default='password'), + login_private_key_path=dict(type='str', required=False, no_log=True), + ) + return options + + def main(): options = common_argument_spec() module = AnsibleModule(argument_spec=options, supports_check_mode=True) From 9ec3147b5f0eca763bf984b197647805f7523e23 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 16 Jun 2023 11:30:38 +0800 Subject: [PATCH 006/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20login=20ac?= =?UTF-8?q?ls=20=E8=BF=81=E7=A7=BB=E5=86=B2=E7=AA=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit perf: 修改 login acls 迁移,避免冲突 --- .../acls/migrations/0016_auto_20230606_1857.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/apps/acls/migrations/0016_auto_20230606_1857.py b/apps/acls/migrations/0016_auto_20230606_1857.py index 2838b5d1f..d703dac52 100644 --- a/apps/acls/migrations/0016_auto_20230606_1857.py +++ b/apps/acls/migrations/0016_auto_20230606_1857.py @@ -1,5 +1,4 @@ # Generated by Django 3.2.17 on 2023-06-06 10:57 -from collections import defaultdict from django.db import migrations, models @@ -8,17 +7,20 @@ import common.db.fields def migrate_users_login_acls(apps, schema_editor): login_acl_model = apps.get_model('acls', 'LoginACL') - name_used = defaultdict(int) - for login_acl in login_acl_model.objects.all(): - name = login_acl.name - if name_used[name] > 0: - login_acl.name += "_{}".format(name_used[name]) - name_used[name] += 1 + name_used = [] + login_acls = [] + for login_acl in login_acl_model.objects.all().select_related('user'): + name = '{}_{}'.format(login_acl.name, login_acl.user.username) + if name.lower() in name_used: + name += '_{}'.format(str(login_acl.user_id)[:4]) + name_used.append(name.lower()) + login_acl.name = name login_acl.users = { "type": "ids", "ids": [str(login_acl.user_id)] } - login_acl.save() + login_acls.append(login_acl) + login_acl_model.objects.bulk_update(login_acls, ['name', 'users']) class Migration(migrations.Migration): From 9e3e183f954b75d6f8bcdd199916075211021a04 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 16 Jun 2023 15:07:17 +0800 Subject: [PATCH 007/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=20platform=20field?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/serializers/dynamic.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/common/serializers/dynamic.py b/apps/common/serializers/dynamic.py index cac9ae0dc..49e1e062d 100644 --- a/apps/common/serializers/dynamic.py +++ b/apps/common/serializers/dynamic.py @@ -44,19 +44,21 @@ def set_default_by_type(tp, data, field_info): def create_serializer_class(serializer_name, fields_info): serializer_fields = {} - fields_name = ['name', 'label', 'default', 'type', 'help_text'] + fields_name = ['name', 'label', 'default', 'required', 'type', 'help_text'] for i, field_info in enumerate(fields_info): data = {k: field_info.get(k) for k in fields_name} field_type = data.pop('type', 'str') - if data.get('default') is None: + # 用户定义 default 和 required 可能会冲突, 所以要处理一下 + default = data.get('default', '') + if default not in ['', None]: + data['required'] = False + else: data.pop('default', None) - data['required'] = field_info.get('required', True) + data['required'] = True data = set_default_by_type(field_type, data, field_info) data = set_default_if_need(data, i) - if data.get('default', None) is not None: - data['required'] = False field_name = data.pop('name') field_class = type_field_map.get(field_type, serializers.CharField) serializer_fields[field_name] = field_class(**data) From 50b64f6cf55e898cf92251ad0f9f7e802f50959a Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 16 Jun 2023 10:35:05 +0800 Subject: [PATCH 008/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20category?= =?UTF-8?q?=20=E5=BC=95=E8=B5=B7=E7=9A=84=20sql=20=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E8=BF=87=E5=A4=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pref: stash perf: 添加装饰器 perf: 优化 category api --- apps/assets/const/custom.py | 29 +++++++++++++++++++++-------- apps/assets/const/types.py | 1 - apps/authentication/views/login.py | 17 +++++++++-------- apps/common/decorators.py | 22 ++++++++++++++++++++++ 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/apps/assets/const/custom.py b/apps/assets/const/custom.py index 5c72127b3..878207f26 100644 --- a/apps/assets/const/custom.py +++ b/apps/assets/const/custom.py @@ -1,3 +1,6 @@ +from collections import defaultdict + +from common.decorators import cached_method from .base import BaseType @@ -9,7 +12,8 @@ class CustomTypes(BaseType): except Exception: return [] types = set([p.type for p in platforms]) - return [(t, t) for t in types] + choices = [(t, t) for t in types] + return choices @classmethod def _get_base_constrains(cls) -> dict: @@ -37,13 +41,20 @@ class CustomTypes(BaseType): return constrains @classmethod + @cached_method(5) def _get_protocol_constrains(cls) -> dict: - constrains = {} - for platform in cls.get_custom_platforms(): - choices = list(platform.protocols.values_list('name', flat=True)) - if platform.type in constrains: - choices = constrains[platform.type]['choices'] + choices - constrains[platform.type] = {'choices': choices} + from assets.models import PlatformProtocol + _constrains = defaultdict(set) + protocols = PlatformProtocol.objects \ + .filter(platform__category='custom') \ + .values_list('name', 'platform__type') + for name, tp in protocols: + _constrains[tp].add(name) + + constrains = { + tp: {'choices': list(choices)} + for tp, choices in _constrains.items() + } return constrains @classmethod @@ -51,6 +62,8 @@ class CustomTypes(BaseType): return {} @classmethod + @cached_method(5) def get_custom_platforms(cls): from assets.models import Platform - return Platform.objects.filter(category='custom') + platforms = Platform.objects.filter(category='custom') + return platforms diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py index 69fa36bb3..1f0156b7f 100644 --- a/apps/assets/const/types.py +++ b/apps/assets/const/types.py @@ -193,7 +193,6 @@ class AllTypes(ChoicesMixin): } return node - @classmethod def asset_to_node(cls, asset, pid): node = { diff --git a/apps/authentication/views/login.py b/apps/authentication/views/login.py index dfba7155c..acc8ed51c 100644 --- a/apps/authentication/views/login.py +++ b/apps/authentication/views/login.py @@ -2,15 +2,19 @@ # from __future__ import unicode_literals -import os + import datetime +import os from typing import Callable -from django.db import IntegrityError -from django.templatetags.static import static +from django.conf import settings +from django.contrib.auth import BACKEND_SESSION_KEY from django.contrib.auth import login as auth_login, logout as auth_logout -from django.http import HttpResponse, HttpRequest +from django.db import IntegrityError +from django.http import HttpRequest, HttpResponse from django.shortcuts import reverse, redirect +from django.templatetags.static import static +from django.urls import reverse_lazy from django.utils.decorators import method_decorator from django.utils.translation import ugettext as _, get_language from django.views.decorators.cache import never_cache @@ -18,16 +22,13 @@ from django.views.decorators.csrf import csrf_protect from django.views.decorators.debug import sensitive_post_parameters from django.views.generic.base import TemplateView, RedirectView from django.views.generic.edit import FormView -from django.conf import settings -from django.urls import reverse_lazy -from django.contrib.auth import BACKEND_SESSION_KEY from common.utils import FlashMessageUtil, static_or_direct from users.utils import ( redirect_user_first_login_or_index ) -from ..const import RSA_PRIVATE_KEY, RSA_PUBLIC_KEY from .. import mixins, errors +from ..const import RSA_PRIVATE_KEY, RSA_PUBLIC_KEY from ..forms import get_user_login_form_cls __all__ = [ diff --git a/apps/common/decorators.py b/apps/common/decorators.py index c100c5025..4881c1517 100644 --- a/apps/common/decorators.py +++ b/apps/common/decorators.py @@ -6,6 +6,7 @@ import inspect import threading import time from concurrent.futures import ThreadPoolExecutor +from functools import wraps from django.db import transaction @@ -217,3 +218,24 @@ def do_test(): end = time.time() using = end - s print("end : %s, using: %s" % (end, using)) + + +def cached_method(ttl=20): + _cache = {} + + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + key = (func, args, tuple(sorted(kwargs.items()))) + # 检查缓存是否存在且未过期 + if key in _cache and time.time() - _cache[key]['timestamp'] < ttl: + return _cache[key]['result'] + + # 缓存过期或不存在,执行方法并缓存结果 + result = func(*args, **kwargs) + _cache[key] = {'result': result, 'timestamp': time.time()} + return result + + return wrapper + + return decorator From f4b5a302a197131dec356ef6df2693d74e9ca758 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 16 Jun 2023 16:44:05 +0800 Subject: [PATCH 009/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E8=B5=84=E4=BA=A7=E6=A0=B9=E6=8D=AE=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E9=87=8D=E5=A4=8D=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset/asset.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index 82733b03e..81b2b8fca 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -82,7 +82,7 @@ class AssetFilterSet(BaseFilterSet): @staticmethod def filter_protocols(queryset, name, value): value = value.split(',') - return queryset.filter(protocols__name__in=value) + return queryset.filter(protocols__name__in=value).distinct() @staticmethod def filter_labels(queryset, name, value): @@ -91,7 +91,7 @@ class AssetFilterSet(BaseFilterSet): queryset = queryset.filter(labels__name=n, labels__value=v) else: q = Q(labels__name__contains=value) | Q(labels__value__contains=value) - queryset = queryset.filter(q) + queryset = queryset.filter(q).distinct() return queryset From da4337168f548039e49f84002a1ce5dfc0b9f00c Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 16 Jun 2023 18:44:13 +0800 Subject: [PATCH 010/167] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E8=B5=84=E4=BA=A7=E8=AF=A6=E6=83=85=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=20auto=5Fconfig=20=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/models/asset/common.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index 6e6d6b836..7a564f787 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -206,15 +206,14 @@ class Asset(NodesRelationMixin, AbsConnectivity, JSONFilterMixin, JMSOrgBaseMode @lazyproperty def auto_config(self): platform = self.platform - automation = self.platform.automation auto_config = { 'su_enabled': platform.su_enabled, 'domain_enabled': platform.domain_enabled, 'ansible_enabled': False } + automation = getattr(self.platform, 'automation', None) if not automation: return auto_config - auto_config.update(model_to_dict(automation)) return auto_config From a8ef40593916b9ad28540b7ea4cccc1f9bc6154a Mon Sep 17 00:00:00 2001 From: "fangfang.dong" Date: Sun, 18 Jun 2023 20:24:14 +0800 Subject: [PATCH 011/167] =?UTF-8?q?perf:=20=E6=8E=A5=E5=8F=A3=20/api/v1/as?= =?UTF-8?q?sets/domains/=20sql=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/domain.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/assets/api/domain.py b/apps/assets/api/domain.py index f27f09c90..40d676d78 100644 --- a/apps/assets/api/domain.py +++ b/apps/assets/api/domain.py @@ -26,6 +26,8 @@ class DomainViewSet(OrgBulkModelViewSet): return serializers.DomainWithGatewaySerializer return serializers.DomainSerializer + def get_queryset(self): + return super().get_queryset().prefetch_related('assets') class GatewayViewSet(HostViewSet): perm_model = Gateway From 39ba52e4de23ecbf06be4cc0dd849296688fe871 Mon Sep 17 00:00:00 2001 From: "fangfang.dong" Date: Sun, 18 Jun 2023 20:26:19 +0800 Subject: [PATCH 012/167] =?UTF-8?q?perf:=20=E6=8E=A5=E5=8F=A3=20/api/v1/as?= =?UTF-8?q?sets/label/=20sql=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/label.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/assets/api/label.py b/apps/assets/api/label.py index cbb7b5bb3..d970d2180 100644 --- a/apps/assets/api/label.py +++ b/apps/assets/api/label.py @@ -38,5 +38,6 @@ class LabelViewSet(OrgBulkModelViewSet): return super().list(request, *args, **kwargs) def get_queryset(self): - self.queryset = Label.objects.annotate(asset_count=Count("assets")) + self.queryset = Label.objects.prefetch_related( + 'assets').annotate(asset_count=Count("assets")) return self.queryset From 471411a1aa2f508408904efbc9ce32af5f9607c5 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Mon, 19 Jun 2023 14:36:39 +0800 Subject: [PATCH 013/167] fix some typos Signed-off-by: cui fliter --- apps/accounts/urls.py | 2 +- apps/common/auth/signature.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/accounts/urls.py b/apps/accounts/urls.py index 5c57ad67b..94c8311e0 100644 --- a/apps/accounts/urls.py +++ b/apps/accounts/urls.py @@ -39,7 +39,7 @@ urlpatterns = [ path('push-account//asset/remove/', api.PushAccountRemoveAssetApi.as_view(), name='push-account-remove-asset'), - path('push-accountt//asset/add/', api.PushAccountAddAssetApi.as_view(), name='push-account-add-asset'), + path('push-account//asset/add/', api.PushAccountAddAssetApi.as_view(), name='push-account-add-asset'), path('push-account//nodes/', api.PushAccountNodeAddRemoveApi.as_view(), name='push-account-add-or-remove-node'), path('push-account//assets/', api.PushAccountAssetsListApi.as_view(), name='push-account-assets'), diff --git a/apps/common/auth/signature.py b/apps/common/auth/signature.py index 793d2a639..9661b9620 100644 --- a/apps/common/auth/signature.py +++ b/apps/common/auth/signature.py @@ -40,7 +40,7 @@ class SignatureAuthentication(authentication.BaseAuthentication): required_headers = ["(request-target)", "date"] def fetch_user_data(self, key_id, algorithm=None): - """Retuns a tuple (User, secret) or (None, None).""" + """Returns a tuple (User, secret) or (None, None).""" raise NotImplementedError() def authenticate_header(self, request): From 4d4644dddddf2e6e608cc2c319e4a37cd5a87177 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 19 Jun 2023 17:46:33 +0800 Subject: [PATCH 014/167] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E5=8E=9F?= =?UTF-8?q?=E6=9D=A5=20platform=20=E4=B8=BA=20device=20=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=9A=84=20asset=20=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E4=B8=8D=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0093_auto_20220403_1627.py | 3 +- .../migrations/0098_auto_20220430_2126.py | 21 ++++++++++- apps/notifications/signal_handlers.py | 3 +- utils/clean_host_to_device.py | 37 +++++++++++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 utils/clean_host_to_device.py diff --git a/apps/assets/migrations/0093_auto_20220403_1627.py b/apps/assets/migrations/0093_auto_20220403_1627.py index c34c70ed7..484da9740 100644 --- a/apps/assets/migrations/0093_auto_20220403_1627.py +++ b/apps/assets/migrations/0093_auto_20220403_1627.py @@ -2,6 +2,7 @@ import django.db from django.db import migrations, models + import common.db.fields @@ -118,7 +119,7 @@ class Migration(migrations.Migration): primary_key=True, serialize=False, to='assets.asset')), ], options={ - 'verbose_name': 'Host', + 'verbose_name': 'Host', }, ), migrations.CreateModel( diff --git a/apps/assets/migrations/0098_auto_20220430_2126.py b/apps/assets/migrations/0098_auto_20220430_2126.py index f388ca731..ed7de94e0 100644 --- a/apps/assets/migrations/0098_auto_20220430_2126.py +++ b/apps/assets/migrations/0098_auto_20220430_2126.py @@ -137,6 +137,24 @@ def migrate_to_nodes(apps, *args): parent.save() +def migrate_ori_host_to_devices(apps, *args): + device_model = apps.get_model('assets', 'Device') + asset_model = apps.get_model('assets', 'Asset') + host_model = apps.get_model('assets', 'Host') + hosts_need_migrate_to_device = host_model.objects.filter(asset_ptr__platform__category='device') + assets = asset_model.objects.filter(id__in=hosts_need_migrate_to_device.values_list('asset_ptr_id', flat=True)) + assets_map = {asset.id: asset for asset in assets} + + for host in hosts_need_migrate_to_device: + asset = assets_map.get(host.asset_ptr_id) + if not asset: + continue + device = device_model(asset_ptr_id=asset.id) + device.__dict__.update(asset.__dict__) + device.save() + host.delete(keep_parents=True) + + class Migration(migrations.Migration): dependencies = [ ('assets', '0097_auto_20220426_1558'), @@ -146,5 +164,6 @@ class Migration(migrations.Migration): operations = [ migrations.RunPython(migrate_database_to_asset), migrations.RunPython(migrate_cloud_to_asset), - migrations.RunPython(migrate_to_nodes) + migrations.RunPython(migrate_to_nodes), + migrations.RunPython(migrate_ori_host_to_devices), ] diff --git a/apps/notifications/signal_handlers.py b/apps/notifications/signal_handlers.py index 5b6b75a7e..797724755 100644 --- a/apps/notifications/signal_handlers.py +++ b/apps/notifications/signal_handlers.py @@ -72,8 +72,7 @@ def create_system_messages(app_config: AppConfig, **kwargs): sub, created = SystemMsgSubscription.objects.get_or_create(message_type=message_type) if created: obj.post_insert_to_db(sub) - logger.info( - f'Create SystemMsgSubscription: package={app_config.module.__package__} type={message_type}') + logger.info(f'Create MsgSubscription: package={app_config.module.__package__} type={message_type}') except ModuleNotFoundError: pass diff --git a/utils/clean_host_to_device.py b/utils/clean_host_to_device.py new file mode 100644 index 000000000..0bc767b6a --- /dev/null +++ b/utils/clean_host_to_device.py @@ -0,0 +1,37 @@ +import os +import sys + +import django + +if os.path.exists('../apps'): + sys.path.insert(0, '../apps') +elif os.path.exists('./apps'): + sys.path.insert(0, './apps') + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jumpserver.settings") +django.setup() + +from assets.models import Asset as asset_model, Host as host_model, Device as device_model +from orgs.models import Organization + + +def clean_host(): + root = Organization.root() + root.change_to() + + devices = host_model.objects.filter(platform__category='device') + assets = asset_model.objects.filter(id__in=devices.values_list('asset_ptr_id', flat=True)) + assets_map = {asset.id: asset for asset in assets} + + for host in devices: + asset = assets_map.get(host.asset_ptr_id) + if not asset: + continue + device = device_model(asset_ptr_id=asset.id) + device.__dict__.update(asset.__dict__) + device.save() + host.delete(keep_parents=True) + + +if __name__ == "__main__": + clean_host() From 42852c368ce336b12595815e4b764d692a7e3ac0 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 19 Jun 2023 18:06:23 +0800 Subject: [PATCH 015/167] =?UTF-8?q?perf:=20=E6=96=B0=E5=A2=9E=20chen=20?= =?UTF-8?q?=E7=BB=88=E7=AB=AF=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/connect_methods.py | 8 ++++++++ apps/terminal/const.py | 1 + 2 files changed, 9 insertions(+) diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index e38a8d123..b92a05271 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -214,6 +214,14 @@ class ConnectMethodUtil: 'support': [Protocol.rdp], 'match': 'map' }, + TerminalType.chen: { + 'web_methods': [WebMethod.web_gui], + 'listen': [Protocol.http], + 'support': [ + Protocol.mysql, Protocol.postgresql, Protocol.oracle, + ], + 'match': 'm2m' + }, } return protocols diff --git a/apps/terminal/const.py b/apps/terminal/const.py index cfec290c7..1f857b7c7 100644 --- a/apps/terminal/const.py +++ b/apps/terminal/const.py @@ -49,6 +49,7 @@ class TerminalType(TextChoices): razor = 'razor', 'Razor' tinker = 'tinker', 'Tinker' video_worker = 'video_worker', 'Video Worker' + chen = 'chen', 'Chen' @classmethod def types(cls): From 666df6ffef58a1f222027177ac431eb4dce68d26 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 19 Jun 2023 18:19:52 +0800 Subject: [PATCH 016/167] =?UTF-8?q?perf:=20=E6=8E=A5=E5=8F=A3=20/api/v1/ti?= =?UTF-8?q?ckets/tickets/=20sql=E4=BC=98=E5=8C=96=20(#10762)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf: 接口 /api/v1/tickets/tickets/ sql优化 * Update general.py * Update general.py * Update general.py --------- Co-authored-by: fangfang.dong Co-authored-by: nut --- apps/tickets/models/ticket/general.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/tickets/models/ticket/general.py b/apps/tickets/models/ticket/general.py index 45fdbac32..4d6c29483 100644 --- a/apps/tickets/models/ticket/general.py +++ b/apps/tickets/models/ticket/general.py @@ -4,7 +4,7 @@ import json from typing import Callable from django.db import models -from django.db.models import Q +from django.db.models import Prefetch, Q from django.db.models.fields import related from django.db.utils import IntegrityError from django.forms import model_to_dict @@ -326,7 +326,13 @@ class Ticket(StatusMixin, JMSBaseModel): @classmethod def get_user_related_tickets(cls, user): queries = Q(applicant=user) | Q(ticket_steps__ticket_assignees__assignee=user) - tickets = cls.objects.filter(queries).distinct() + # TODO: 与 StatusMixin.process_map 内连表查询有部分重叠 有优化空间 待验证排除是否不影响其它调用 + prefetch_ticket_assignee = Prefetch('ticket_steps__ticket_assignees', + queryset=TicketAssignee.objects.select_related('assignee'), ) + tickets = cls.objects.prefetch_related(prefetch_ticket_assignee)\ + .select_related('applicant')\ + .filter(queries)\ + .distinct() return tickets def get_current_ticket_flow_approve(self): From 9403b76333b361d7e7246dc8d4898045aea34f5e Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Mon, 19 Jun 2023 17:29:51 +0800 Subject: [PATCH 017/167] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=20push=5Facco?= =?UTF-8?q?unt=5Fparams=20=E6=95=B0=E6=8D=AE=E8=BF=81=E7=A7=BB=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E4=B8=8D=E5=9C=A8=E5=AF=BC=E5=85=A5=E5=85=AC?= =?UTF-8?q?=E5=85=B1=E6=96=B9=E6=B3=95=E7=94=9F=E6=88=90=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/migrations/0114_baseautomation_params.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/apps/assets/migrations/0114_baseautomation_params.py b/apps/assets/migrations/0114_baseautomation_params.py index 857c5d795..b48f5b302 100644 --- a/apps/assets/migrations/0114_baseautomation_params.py +++ b/apps/assets/migrations/0114_baseautomation_params.py @@ -2,16 +2,13 @@ from django.db import migrations, models -from assets.const import AllTypes - def migrate_automation_push_account_params(apps, schema_editor): platform_automation_model = apps.get_model('assets', 'PlatformAutomation') - platform_automation_methods = AllTypes.get_automation_methods() methods_id_data_map = { - i['id']: None if i['params_serializer'] is None else i['params_serializer']({}).data - for i in platform_automation_methods - if i['method'] == 'push_account' + 'push_account_aix': {'sudo': '/bin/whoami', 'shell': '/bin/bash', 'home': '', 'groups': ''}, + 'push_account_posix': {'sudo': '/bin/whoami', 'shell': '/bin/bash', 'home': '', 'groups': ''}, + 'push_account_local_windows': {'groups': 'Users,Remote Desktop Users'}, } automation_objs = [] for automation in platform_automation_model.objects.all(): From e4f21b8a5fcbb2ef0b9c6b23a53effb23ba8cfe8 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 19 Jun 2023 18:17:46 +0800 Subject: [PATCH 018/167] =?UTF-8?q?perf:=20=E7=A7=BB=E9=99=A4=20omnidb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/connect_methods.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index b92a05271..b5ba6360d 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -183,12 +183,12 @@ class ConnectMethodUtil: ], 'match': 'm2m' }, - TerminalType.omnidb: { + TerminalType.chen: { 'web_methods': [WebMethod.web_gui], 'listen': [Protocol.http], 'support': [ Protocol.mysql, Protocol.postgresql, - Protocol.oracle, Protocol.mariadb + Protocol.oracle ], 'match': 'm2m' }, @@ -214,14 +214,6 @@ class ConnectMethodUtil: 'support': [Protocol.rdp], 'match': 'map' }, - TerminalType.chen: { - 'web_methods': [WebMethod.web_gui], - 'listen': [Protocol.http], - 'support': [ - Protocol.mysql, Protocol.postgresql, Protocol.oracle, - ], - 'match': 'm2m' - }, } return protocols From 5d9979ec039de4951d8931c6f8f59c3310b84ef9 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 20 Jun 2023 16:16:59 +0800 Subject: [PATCH 019/167] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=20terminal?= =?UTF-8?q?=20=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/serializers/session.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/terminal/serializers/session.py b/apps/terminal/serializers/session.py index db7346d51..49a5af69a 100644 --- a/apps/terminal/serializers/session.py +++ b/apps/terminal/serializers/session.py @@ -33,7 +33,7 @@ class SessionSerializer(BulkOrgResourceModelSerializer): "user", "asset", "user_id", "asset_id", 'account', 'account_id', "protocol", 'type', "login_from", "remote_addr", "is_success", "is_finished", "has_replay", "has_command", - "date_start", "date_end", "comment" + "date_start", "date_end", "comment", "terminal_display" ] fields_fk = ["terminal", ] fields_custom = ["can_replay", "can_join", "can_terminate"] From 13fc2aa73c4656bea1f735aa9b550cb92dd0f981 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 20 Jun 2023 15:30:58 +0800 Subject: [PATCH 020/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96rbac=20?= =?UTF-8?q?=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/builtin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/rbac/builtin.py b/apps/rbac/builtin.py index cf80c64ab..f2dd13dae 100644 --- a/apps/rbac/builtin.py +++ b/apps/rbac/builtin.py @@ -151,7 +151,7 @@ class BuiltinRole: 'User': cls.system_user.get_role(), 'Auditor': cls.system_auditor.get_role() } - return cls.system_role_mapper[name] + return cls.system_role_mapper.get(name, cls.system_role_mapper['User']) @classmethod def get_org_role_by_old_name(cls, name): @@ -161,7 +161,7 @@ class BuiltinRole: 'User': cls.org_user.get_role(), 'Auditor': cls.org_auditor.get_role(), } - return cls.org_role_mapper[name] + return cls.org_role_mapper.get(name, cls.org_role_mapper['User']) @classmethod def sync_to_db(cls, show_msg=False): From cb0fd937c82398fcca114943fe67077094626f28 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 20 Jun 2023 13:54:53 +0800 Subject: [PATCH 021/167] =?UTF-8?q?perf:=20=E8=B5=84=E4=BA=A7=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E5=8F=AF=E4=BB=A5=E6=8C=87=E5=AE=9A=20AppletHost?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/models/connection_token.py | 2 +- apps/terminal/models/applet/applet.py | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py index 0407cf025..e362e207c 100644 --- a/apps/authentication/models/connection_token.py +++ b/apps/authentication/models/connection_token.py @@ -175,7 +175,7 @@ class ConnectionToken(JMSOrgBaseModel): if not applet: return None - host_account = applet.select_host_account(self.user) + host_account = applet.select_host_account(self.user, self.asset) if not host_account: raise JMSException({'error': 'No host account available'}) diff --git a/apps/terminal/models/applet/applet.py b/apps/terminal/models/applet/applet.py index ef8eca8bc..edf7b332b 100644 --- a/apps/terminal/models/applet/applet.py +++ b/apps/terminal/models/applet/applet.py @@ -148,14 +148,18 @@ class Applet(JMSBaseModel): shutil.copytree(path, pkg_path) return instance, serializer - def select_host(self, user): - hosts = [ - host for host in self.hosts.filter(is_active=True) - if host.load != 'offline' - ] + def select_host(self, user, asset): + hosts = self.hosts.filter(is_active=True) + hosts = [host for host in hosts if host.load != 'offline'] if not hosts: return None + spec_label = asset.labels.filter(name__in=['AppletHost', '发布机']).first() + if spec_label: + host = [host for host in hosts if host.name == spec_label.value] + if host: + return host[0] + prefer_key = 'applet_host_prefer_{}'.format(user.id) prefer_host_id = cache.get(prefer_key, None) pref_host = [host for host in hosts if host.id == prefer_host_id] @@ -189,9 +193,9 @@ class Applet(JMSBaseModel): cache.set(prefer_host_account_key, account.id, timeout=None) return account - def select_host_account(self, user): + def select_host_account(self, user, asset): # 选择激活的发布机 - host = self.select_host(user) + host = self.select_host(user, asset) if not host: return None host_concurrent = str(host.deploy_options.get('RDS_fSingleSessionPerUser', 0)) == '0' From 1d084311c55f83c21787155d50b3bc50e8b87260 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 19 Jun 2023 19:57:01 +0800 Subject: [PATCH 022/167] =?UTF-8?q?perf:=20=E7=BB=9F=E4=B8=80=20connect=20?= =?UTF-8?q?token=20=E9=85=8D=E7=BD=AE=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../authentication/models/connection_token.py | 2 +- .../serializers/connection_token.py | 2 +- apps/jumpserver/conf.py | 19 +++++++++++++++---- apps/jumpserver/settings/auth.py | 6 +----- apps/jumpserver/settings/custom.py | 7 ++++++- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py index e362e207c..acef092b1 100644 --- a/apps/authentication/models/connection_token.py +++ b/apps/authentication/models/connection_token.py @@ -21,7 +21,7 @@ from terminal.models import Applet def date_expired_default(): - return timezone.now() + timedelta(seconds=settings.CONNECTION_TOKEN_EXPIRATION) + return timezone.now() + timedelta(seconds=settings.CONNECTION_TOKEN_ONETIME_EXPIRATION) class ConnectionToken(JMSOrgBaseModel): diff --git a/apps/authentication/serializers/connection_token.py b/apps/authentication/serializers/connection_token.py index 74b645aec..28cf79127 100644 --- a/apps/authentication/serializers/connection_token.py +++ b/apps/authentication/serializers/connection_token.py @@ -70,7 +70,7 @@ class ConnectionTokenUpdateSerializer(ConnectionTokenSerializer): if delta.total_seconds() > 3600 * 24: return self.instance.date_expired - seconds = settings.CONNECTION_TOKEN_EXPIRATION_MAX + seconds = settings.CONNECTION_TOKEN_REUSABLE_EXPIRATION return timezone.now() + timezone.timedelta(seconds=seconds) @staticmethod diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index dd056b091..a0672422a 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -231,8 +231,8 @@ class Config(dict): 'SESSION_COOKIE_AGE': 3600 * 24, 'SESSION_EXPIRE_AT_BROWSER_CLOSE': False, 'LOGIN_URL': reverse_lazy('authentication:login'), - 'CONNECTION_TOKEN_EXPIRATION': 5 * 60, # 默认 - 'CONNECTION_TOKEN_EXPIRATION_MAX': 60 * 60 * 24 * 30, # 最大 + 'CONNECTION_TOKEN_ONETIME_EXPIRATION': 5 * 60, # 默认 + 'CONNECTION_TOKEN_REUSABLE_EXPIRATION': 60 * 60 * 24 * 30, # 最大 'CONNECTION_TOKEN_REUSABLE': False, # Custom Config @@ -558,6 +558,11 @@ class Config(dict): 'FTP_FILE_MAX_STORE': 100, } + old_config_map = { + 'CONNECTION_TOKEN_ONETIME_EXPIRATION': 'CONNECTION_TOKEN_EXPIRATION', + 'CONNECTION_TOKEN_REUSABLE_EXPIRATION': 'CONNECTION_TOKEN_EXPIRATION_MAX', + } + def __init__(self, *args): super().__init__(*args) self.secret_encryptor = ConfigCrypto.get_secret_encryptor() @@ -698,13 +703,19 @@ class Config(dict): value = self.convert_type(item, value) return value - def get(self, item): + def get(self, item, default=None): # 再从配置文件中获取 value = self.get_from_config(item) if value is None: value = self.get_from_env(item) + + # 因为要递归,所以优先从上次返回的递归中获取 + if default is None: + default = self.defaults.get(item) + if value is None and item in self.old_config_map: + return self.get(self.old_config_map[item], default) if value is None: - value = self.defaults.get(item) + value = default if self.secret_encryptor: value = self.secret_encryptor.decrypt_if_need(value, item) return value diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index 2a45555bd..fa3217f50 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -175,13 +175,9 @@ AUTH_OAUTH2_LOGOUT_URL_NAME = "authentication:oauth2:logout" AUTH_TEMP_TOKEN = CONFIG.AUTH_TEMP_TOKEN # Other setting +# 这个是 User Login Private Token TOKEN_EXPIRATION = CONFIG.TOKEN_EXPIRATION OTP_IN_RADIUS = CONFIG.OTP_IN_RADIUS -# Connection token -CONNECTION_TOKEN_EXPIRATION = CONFIG.CONNECTION_TOKEN_EXPIRATION -if CONNECTION_TOKEN_EXPIRATION < 5 * 60: - # 最少5分钟 - CONNECTION_TOKEN_EXPIRATION = 5 * 60 RBAC_BACKEND = 'rbac.backends.RBACBackend' AUTH_BACKEND_MODEL = 'authentication.backends.base.JMSModelBackend' diff --git a/apps/jumpserver/settings/custom.py b/apps/jumpserver/settings/custom.py index 78298db25..b9be9c75b 100644 --- a/apps/jumpserver/settings/custom.py +++ b/apps/jumpserver/settings/custom.py @@ -133,8 +133,13 @@ TICKETS_ENABLED = CONFIG.TICKETS_ENABLED REFERER_CHECK_ENABLED = CONFIG.REFERER_CHECK_ENABLED CONNECTION_TOKEN_ENABLED = CONFIG.CONNECTION_TOKEN_ENABLED +# Connection token +CONNECTION_TOKEN_ONETIME_EXPIRATION = CONFIG.CONNECTION_TOKEN_ONETIME_EXPIRATION +if CONNECTION_TOKEN_ONETIME_EXPIRATION < 5 * 60: + # 最少5分钟 + CONNECTION_TOKEN_ONETIME_EXPIRATION = 5 * 60 CONNECTION_TOKEN_REUSABLE = CONFIG.CONNECTION_TOKEN_REUSABLE -CONNECTION_TOKEN_EXPIRATION_MAX = CONFIG.CONNECTION_TOKEN_EXPIRATION_MAX +CONNECTION_TOKEN_REUSABLE_EXPIRATION = CONFIG.CONNECTION_TOKEN_REUSABLE_EXPIRATION FORGOT_PASSWORD_URL = CONFIG.FORGOT_PASSWORD_URL From a2bbf11f9d7b3906631a9ec46dfd71238a7f96b9 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 20 Jun 2023 17:54:02 +0800 Subject: [PATCH 023/167] =?UTF-8?q?perf:=20=E6=B7=BB=E5=8A=A0=20migrate=20?= =?UTF-8?q?debug=20msg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/migrations/0098_auto_20220430_2126.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/assets/migrations/0098_auto_20220430_2126.py b/apps/assets/migrations/0098_auto_20220430_2126.py index ed7de94e0..8d1cfdc5e 100644 --- a/apps/assets/migrations/0098_auto_20220430_2126.py +++ b/apps/assets/migrations/0098_auto_20220430_2126.py @@ -145,6 +145,7 @@ def migrate_ori_host_to_devices(apps, *args): assets = asset_model.objects.filter(id__in=hosts_need_migrate_to_device.values_list('asset_ptr_id', flat=True)) assets_map = {asset.id: asset for asset in assets} + print("\t- Migrate ori host to device: ", len(hosts_need_migrate_to_device)) for host in hosts_need_migrate_to_device: asset = assets_map.get(host.asset_ptr_id) if not asset: From b9c1a89f51e4db2f2b57112937bce732a28b2950 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 21 Jun 2023 10:58:14 +0800 Subject: [PATCH 024/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=BF=81?= =?UTF-8?q?=E7=A7=BB=E6=96=87=E4=BB=B6=E6=97=B6=E8=A7=A6=E5=8F=91=E4=BF=A1?= =?UTF-8?q?=E5=8F=B7=E8=AE=B0=E5=BD=95=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E8=BF=81=E7=A7=BB=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/audits/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/audits/utils.py b/apps/audits/utils.py index 33e0d9639..2c54565d5 100644 --- a/apps/audits/utils.py +++ b/apps/audits/utils.py @@ -42,7 +42,7 @@ def _get_instance_field_value( if getattr(f, 'attname', None) in model_need_continue_fields: continue - value = getattr(instance, f.name) or getattr(instance, f.attname) + value = getattr(instance, f.name, None) or getattr(instance, f.attname, None) if not isinstance(value, bool) and not value: continue From fa24a8e2f37a21c2f9e3cc3e961cd5d2bc41ada7 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 21 Jun 2023 11:47:53 +0800 Subject: [PATCH 025/167] =?UTF-8?q?perf:=20=E6=B7=BB=E5=8A=A0=20sql=20debu?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/middleware.py | 13 +++++++++++++ apps/jumpserver/settings/base.py | 1 + 2 files changed, 14 insertions(+) diff --git a/apps/jumpserver/middleware.py b/apps/jumpserver/middleware.py index f76077b7f..5ce0616c1 100644 --- a/apps/jumpserver/middleware.py +++ b/apps/jumpserver/middleware.py @@ -101,6 +101,19 @@ class RefererCheckMiddleware: return response +class SQLCountMiddleware: + def __init__(self, get_response): + self.get_response = get_response + if not settings.DEBUG_DEV: + raise MiddlewareNotUsed + + def __call__(self, request): + from django.db import connection + response = self.get_response(request) + response['X-JMS-SQL-COUNT'] = len(connection.queries) + return response + + class StartMiddleware: def __init__(self, get_response): self.get_response = get_response diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index e956dbd69..7477f3f83 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -128,6 +128,7 @@ MIDDLEWARE = [ 'jumpserver.middleware.DemoMiddleware', 'jumpserver.middleware.RequestMiddleware', 'jumpserver.middleware.RefererCheckMiddleware', + 'jumpserver.middleware.SQLCountMiddleware', 'orgs.middleware.OrgMiddleware', 'authentication.backends.oidc.middleware.OIDCRefreshIDTokenMiddleware', 'authentication.backends.cas.middleware.CASMiddleware', From 1ca71f78ed603be5a3089711b43ac044ecc5fee6 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 21 Jun 2023 13:57:25 +0800 Subject: [PATCH 026/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E4=B8=80?= =?UTF-8?q?=E4=B8=8B=EF=BC=8C=E5=8E=BB=E6=8E=89=20rbac=20=E5=BC=95?= =?UTF-8?q?=E8=B5=B7=E7=9A=84=20sql=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/jumpserver/middleware.py b/apps/jumpserver/middleware.py index 5ce0616c1..a4738649f 100644 --- a/apps/jumpserver/middleware.py +++ b/apps/jumpserver/middleware.py @@ -110,7 +110,7 @@ class SQLCountMiddleware: def __call__(self, request): from django.db import connection response = self.get_response(request) - response['X-JMS-SQL-COUNT'] = len(connection.queries) + response['X-JMS-SQL-COUNT'] = len(connection.queries) - 2 return response From b2bff223873e2efce3ab26277b7f453b76d5117e Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 21 Jun 2023 12:02:12 +0800 Subject: [PATCH 027/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=BF=9C?= =?UTF-8?q?=E7=A8=8B=E5=BA=94=E7=94=A8=E4=BC=9A=E8=AF=9D=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E7=9B=91=E6=8E=A7=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/models/session/session.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/apps/terminal/models/session/session.py b/apps/terminal/models/session/session.py index 5ddd6e647..ccf5936b8 100644 --- a/apps/terminal/models/session/session.py +++ b/apps/terminal/models/session/session.py @@ -10,12 +10,11 @@ from django.db import models from django.utils import timezone from django.utils.translation import ugettext_lazy as _ -from assets.const import Protocol from assets.models import Asset from common.utils import get_object_or_none, lazyproperty from orgs.mixins.models import OrgModelMixin from terminal.backends import get_multi_command_storage -from terminal.const import SessionType +from terminal.const import SessionType, TerminalType from users.models import User @@ -112,6 +111,7 @@ class Session(OrgModelMixin): return rel_path except: pass + @property def asset_obj(self): return Asset.objects.get(id=self.asset_id) @@ -132,10 +132,7 @@ class Session(OrgModelMixin): if self.type != SessionType.normal: # 会话监控仅支持 normal,不支持 tunnel 和 command return False - if self.protocol in [ - Protocol.ssh, Protocol.vnc, Protocol.rdp, - Protocol.telnet, Protocol.k8s - ]: + if self.terminal.type in [TerminalType.lion, TerminalType.koko]: return True else: return False From 270ed5e2f84a4197410ed5492c9b1d3db512fc26 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 21 Jun 2023 17:42:25 +0800 Subject: [PATCH 028/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20logging=20?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/category.py | 7 +++---- apps/assets/models/group.py | 3 --- apps/common/api/filter.py | 6 +++++- apps/common/drf/filters.py | 6 ++++-- apps/common/signal_handlers.py | 9 ++++----- apps/jumpserver/settings/logging.py | 4 ++-- apps/ops/celery/signal_handler.py | 4 ++-- apps/perms/models/asset_permission.py | 12 ++++++------ apps/users/utils.py | 10 +++++----- requirements/requirements.txt | 4 ++-- 10 files changed, 33 insertions(+), 32 deletions(-) diff --git a/apps/assets/api/category.py b/apps/assets/api/category.py index 8c14e352d..b6ec6790b 100644 --- a/apps/assets/api/category.py +++ b/apps/assets/api/category.py @@ -1,11 +1,11 @@ -from rest_framework.mixins import ListModelMixin from rest_framework.decorators import action +from rest_framework.mixins import ListModelMixin from rest_framework.response import Response +from assets.const import AllTypes +from assets.serializers import CategorySerializer, TypeSerializer from common.api import JMSGenericViewSet from common.permissions import IsValidUser -from assets.serializers import CategorySerializer, TypeSerializer -from assets.const import AllTypes __all__ = ['CategoryViewSet'] @@ -32,4 +32,3 @@ class CategoryViewSet(ListModelMixin, JMSGenericViewSet): tp = request.query_params.get('type') constraints = AllTypes.get_constraints(category, tp) return Response(constraints) - diff --git a/apps/assets/models/group.py b/apps/assets/models/group.py index ee5472622..02db7f41f 100644 --- a/apps/assets/models/group.py +++ b/apps/assets/models/group.py @@ -7,12 +7,9 @@ from __future__ import unicode_literals import uuid from django.db import models -import logging from django.utils.translation import ugettext_lazy as _ - __all__ = ['AssetGroup'] -logger = logging.getLogger(__name__) class AssetGroup(models.Model): diff --git a/apps/common/api/filter.py b/apps/common/api/filter.py index c0307dd59..56c3e6483 100644 --- a/apps/common/api/filter.py +++ b/apps/common/api/filter.py @@ -10,6 +10,8 @@ from common.drf.filters import IDSpmFilter, CustomFilter, IDInFilter __all__ = ['ExtraFilterFieldsMixin', 'OrderingFielderFieldsMixin'] +logger = logging.getLogger('jumpserver.common') + class ExtraFilterFieldsMixin: """ @@ -54,7 +56,9 @@ class OrderingFielderFieldsMixin: try: valid_fields = self.get_valid_ordering_fields() except Exception as e: - logging.debug('get_valid_ordering_fields error: %s' % e) + logger.debug('get_valid_ordering_fields error: %s' % e) + # 这里千万不要这么用,会让 logging 重复,至于为什么,我也不知道 + # logging.debug('get_valid_ordering_fields error: %s' % e) valid_fields = [] fields = list(chain( diff --git a/apps/common/drf/filters.py b/apps/common/drf/filters.py index bac14190e..c44874fd5 100644 --- a/apps/common/drf/filters.py +++ b/apps/common/drf/filters.py @@ -14,6 +14,8 @@ from rest_framework.serializers import ValidationError from common import const +logger = logging.getLogger('jumpserver.common') + __all__ = [ "DatetimeRangeFilter", "IDSpmFilter", 'IDInFilter', "CustomFilter", @@ -70,7 +72,7 @@ class DatetimeRangeFilter(filters.BaseFilterBackend): ] ``` """.format(view.name) - logging.error(msg) + logger.error(msg) raise ImproperlyConfigured(msg) def filter_queryset(self, request, queryset, view): @@ -213,6 +215,6 @@ class AttrRulesFilterBackend(filters.BaseFilterBackend): except Exception: raise ValidationError({'attr_rules': 'attr_rules should be json'}) - logging.debug('attr_rules: %s', attr_rules) + logger.debug('attr_rules: %s', attr_rules) q = RelatedManager.get_to_filter_q(attr_rules, queryset.model) return queryset.filter(q).distinct() diff --git a/apps/common/signal_handlers.py b/apps/common/signal_handlers.py index b7acf6e79..df2019b60 100644 --- a/apps/common/signal_handlers.py +++ b/apps/common/signal_handlers.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # -import logging import os import re from collections import defaultdict @@ -14,9 +13,10 @@ from django.dispatch import receiver from jumpserver.utils import get_current_request from .local import thread_local from .signals import django_ready +from .utils import get_logger pattern = re.compile(r'FROM `(\w+)`') -logger = logging.getLogger("jumpserver.common") +logger = get_logger(__name__) class Counter: @@ -129,7 +129,6 @@ else: @receiver(django_ready) def check_migrations_file_prefix_conflict(*args, **kwargs): - if not settings.DEBUG_DEV: return @@ -172,7 +171,7 @@ def check_migrations_file_prefix_conflict(*args, **kwargs): if not conflict_count: return - print('='*80) + print('=' * 80) for conflict_file in conflict_files: msg_dir = '{:<15}'.format(conflict_file[0]) msg_split = '=> ' @@ -181,4 +180,4 @@ def check_migrations_file_prefix_conflict(*args, **kwargs): msg_right2 = ' ' * len(msg_left) + msg_split + conflict_file[2] print(f'{msg_left}{msg_right1}\n{msg_right2}\n') - print('='*80) + print('=' * 80) diff --git a/apps/jumpserver/settings/logging.py b/apps/jumpserver/settings/logging.py index a021d1716..8dae9e371 100644 --- a/apps/jumpserver/settings/logging.py +++ b/apps/jumpserver/settings/logging.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # import os + from ..const import PROJECT_DIR, CONFIG LOG_DIR = os.path.join(PROJECT_DIR, 'logs') @@ -105,7 +106,7 @@ LOGGING = { 'propagate': False, }, 'jumpserver': { - 'handlers': ['console', 'file'], + 'handlers': ['console'], 'level': LOG_LEVEL, }, 'drf_exception': { @@ -132,7 +133,6 @@ LOGGING = { 'handlers': ['null'], 'level': 'ERROR' } - } } diff --git a/apps/ops/celery/signal_handler.py b/apps/ops/celery/signal_handler.py index 5ca29f7ba..17455fe96 100644 --- a/apps/ops/celery/signal_handler.py +++ b/apps/ops/celery/signal_handler.py @@ -2,11 +2,11 @@ # import logging -from django.core.cache import cache from celery import subtask from celery.signals import ( worker_ready, worker_shutdown, after_setup_logger ) +from django.core.cache import cache from django_celery_beat.models import PeriodicTask from common.utils import get_logger @@ -46,6 +46,6 @@ def add_celery_logger_handler(sender=None, logger=None, loglevel=None, format=No return task_handler = CeleryThreadTaskFileHandler() task_handler.setLevel(loglevel) - formatter = logging.Formatter(format) + formatter = logging.Formatter('abc: ' + format) task_handler.setFormatter(formatter) logger.addHandler(task_handler) diff --git a/apps/perms/models/asset_permission.py b/apps/perms/models/asset_permission.py index c17a67acb..08484e88e 100644 --- a/apps/perms/models/asset_permission.py +++ b/apps/perms/models/asset_permission.py @@ -5,20 +5,20 @@ from django.db.models import Q from django.utils import timezone from django.utils.translation import ugettext_lazy as _ -from users.models import User -from assets.models import Asset +from accounts.const import AliasAccount from accounts.models import Account -from orgs.mixins.models import JMSOrgBaseModel -from orgs.mixins.models import OrgManager +from assets.models import Asset from common.utils import date_expired_default from common.utils.timezone import local_now +from orgs.mixins.models import JMSOrgBaseModel +from orgs.mixins.models import OrgManager from perms.const import ActionChoices -from accounts.const import AliasAccount +from users.models import User __all__ = ['AssetPermission', 'ActionChoices', 'AssetPermissionQuerySet'] # 使用场景 -logger = logging.getLogger(__name__) +logger = logging.getLogger('jumpserver.permissions') class AssetPermissionQuerySet(models.QuerySet): diff --git a/apps/users/utils.py b/apps/users/utils.py index 55ebd1aa1..29ce56cd1 100644 --- a/apps/users/utils.py +++ b/apps/users/utils.py @@ -1,20 +1,20 @@ # ~*~ coding: utf-8 ~*~ # -import os -import re -import pyotp import base64 import logging +import os +import re import time +import pyotp from django.conf import settings from django.core.cache import cache from common.tasks import send_mail_async -from common.utils import reverse, get_object_or_none, ip, pretty_string +from common.utils import reverse, get_object_or_none, ip from .models import User -logger = logging.getLogger('jumpserver') +logger = logging.getLogger('jumpserver.users') def send_user_created_mail(user): diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 33bc01dbe..df532adf3 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -16,7 +16,7 @@ ecdsa==0.13.3 enum-compat==0.0.2 ephem==3.7.6.0 future==0.16.0 -idna==2.6 +idna==2.8 itypes==1.2.0 Jinja2==3.1.2 jmespath==1.0.1 @@ -37,7 +37,7 @@ PyNaCl==1.5.0 python-dateutil==2.8.2 PyYAML==6.0 requests==2.31.0 -jms-storage==0.0.46 +jms-storage==0.0.47 simplejson==3.17.6 six==1.16.0 sshtunnel==0.4.0 From 26edd2f0401c164c7ab7274b8729c7ba158c3998 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 21 Jun 2023 17:45:09 +0800 Subject: [PATCH 029/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E5=8E=BB?= =?UTF-8?q?=E6=8E=89=E4=B8=80=E4=BA=9B=20debug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/settings/logging.py | 2 +- apps/ops/celery/signal_handler.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/jumpserver/settings/logging.py b/apps/jumpserver/settings/logging.py index 8dae9e371..6d4498e3f 100644 --- a/apps/jumpserver/settings/logging.py +++ b/apps/jumpserver/settings/logging.py @@ -106,7 +106,7 @@ LOGGING = { 'propagate': False, }, 'jumpserver': { - 'handlers': ['console'], + 'handlers': ['console', 'file'], 'level': LOG_LEVEL, }, 'drf_exception': { diff --git a/apps/ops/celery/signal_handler.py b/apps/ops/celery/signal_handler.py index 17455fe96..bfd68508a 100644 --- a/apps/ops/celery/signal_handler.py +++ b/apps/ops/celery/signal_handler.py @@ -46,6 +46,6 @@ def add_celery_logger_handler(sender=None, logger=None, loglevel=None, format=No return task_handler = CeleryThreadTaskFileHandler() task_handler.setLevel(loglevel) - formatter = logging.Formatter('abc: ' + format) + formatter = logging.Formatter(format) task_handler.setFormatter(formatter) logger.addHandler(task_handler) From b2ee8c82162c46534bd510b1aac797ae4c75f6c0 Mon Sep 17 00:00:00 2001 From: "fangfang.dong" Date: Wed, 21 Jun 2023 18:33:58 +0800 Subject: [PATCH 030/167] =?UTF-8?q?feat:=20=E7=B3=BB=E7=BB=9F=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=20-=20=E7=BB=88=E7=AB=AF=E8=AE=BE=E7=BD=AE=20-=20?= =?UTF-8?q?=E7=AB=AF=E7=82=B9=E8=A7=84=E5=88=99:=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=AD=97=E6=AE=B5is=5Factive=E6=8E=A7=E5=88=B6=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=90=AF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0050_auto_20220606_1745.py | 4 ++-- .../migrations/0063_auto_20230621_1133.py | 22 +++++++++++++++++++ apps/terminal/models/component/endpoint.py | 5 +++-- apps/terminal/serializers/endpoint.py | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 apps/terminal/migrations/0063_auto_20230621_1133.py diff --git a/apps/terminal/migrations/0050_auto_20220606_1745.py b/apps/terminal/migrations/0050_auto_20220606_1745.py index d0eb6ea5d..a47defba9 100644 --- a/apps/terminal/migrations/0050_auto_20220606_1745.py +++ b/apps/terminal/migrations/0050_auto_20220606_1745.py @@ -15,7 +15,7 @@ class Migration(migrations.Migration): field=models.CharField( choices=[('koko', 'KoKo'), ('guacamole', 'Guacamole'), ('omnidb', 'OmniDB'), ('xrdp', 'Xrdp'), ('lion', 'Lion'), ('core', 'Core'), ('celery', 'Celery'), ('magnus', 'Magnus'), - ('razor', 'Razor'), ('tinker', 'Tinker'), ('video_worker', 'Video Worker')], default='koko', - max_length=64, verbose_name='type'), + ('razor', 'Razor'), ('tinker', 'Tinker'), ('video_worker', 'Video Worker'), ('chen', 'Chen')], + default='koko', max_length=64, verbose_name='type'), ), ] diff --git a/apps/terminal/migrations/0063_auto_20230621_1133.py b/apps/terminal/migrations/0063_auto_20230621_1133.py new file mode 100644 index 000000000..85553e8f3 --- /dev/null +++ b/apps/terminal/migrations/0063_auto_20230621_1133.py @@ -0,0 +1,22 @@ +# Generated by Django 3.2.19 on 2023-06-21 10:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('terminal', '0062_applet_edition'), + ] + + operations = [ + migrations.AlterModelOptions( + name='endpointrule', + options={'ordering': ('priority', 'is_active', 'name'), 'verbose_name': 'Endpoint rule'}, + ), + migrations.AddField( + model_name='endpointrule', + name='is_active', + field=models.BooleanField(default=True, verbose_name='Is active'), + ), + ] diff --git a/apps/terminal/models/component/endpoint.py b/apps/terminal/models/component/endpoint.py index c5aab12d9..f19f72949 100644 --- a/apps/terminal/models/component/endpoint.py +++ b/apps/terminal/models/component/endpoint.py @@ -98,17 +98,18 @@ class EndpointRule(JMSBaseModel): on_delete=models.SET_NULL, verbose_name=_("Endpoint"), ) comment = models.TextField(default='', blank=True, verbose_name=_('Comment')) + is_active = models.BooleanField(default=True, verbose_name=_('Is active')) class Meta: verbose_name = _('Endpoint rule') - ordering = ('priority', 'name') + ordering = ('priority', 'is_active', 'name') def __str__(self): return f'{self.name}({self.priority})' @classmethod def match(cls, target_instance, target_ip, protocol): - for endpoint_rule in cls.objects.all().prefetch_related('endpoint'): + for endpoint_rule in cls.objects.prefetch_related('endpoint').filter(is_active=True): if not contains_ip(target_ip, endpoint_rule.ip_group): continue if not endpoint_rule.endpoint: diff --git a/apps/terminal/serializers/endpoint.py b/apps/terminal/serializers/endpoint.py index d7534adeb..82de09fce 100644 --- a/apps/terminal/serializers/endpoint.py +++ b/apps/terminal/serializers/endpoint.py @@ -79,7 +79,7 @@ class EndpointRuleSerializer(BulkModelSerializer): fields_small = fields_mini + ['ip_group', 'priority'] fields_fk = ['endpoint'] fields = fields_mini + fields_small + fields_fk + [ - 'comment', 'date_created', 'date_updated', 'created_by' + 'comment', 'date_created', 'date_updated', 'created_by', 'is_active' ] extra_kwargs = { 'priority': {'default': 50} From 780b1104deac708d7eed80f16a380148f406dab3 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Sun, 25 Jun 2023 09:41:22 +0800 Subject: [PATCH 031/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E9=A3=9E?= =?UTF-8?q?=E4=B9=A6=E6=8E=A5=E6=94=B6=E5=88=B0=E7=9A=84=E5=B7=A5=E5=8D=95?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E7=9A=84=E8=BF=9E=E6=8E=A5=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E7=82=B9=E5=87=BB=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/notifications/notifications.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notifications/notifications.py b/apps/notifications/notifications.py index 6c631ec16..19a86ac94 100644 --- a/apps/notifications/notifications.py +++ b/apps/notifications/notifications.py @@ -194,7 +194,7 @@ class Message(metaclass=MessageType): return self.markdown_msg def get_feishu_msg(self) -> dict: - return self.text_msg + return self.markdown_msg def get_email_msg(self) -> dict: return self.html_msg_with_sign From d7d554daf57f6e94f8609f91044458694685e179 Mon Sep 17 00:00:00 2001 From: "fangfang.dong" Date: Sun, 25 Jun 2023 18:08:59 +0800 Subject: [PATCH 032/167] =?UTF-8?q?perf:=20=E6=8E=A5=E5=8F=A3sql=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20/api/v1/assets/assets/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset/asset.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index 81b2b8fca..c9083f4b6 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -121,6 +121,10 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet): NodeFilterBackend, AttrRulesFilterBackend ] + def get_queryset(self): + return super().get_queryset().prefetch_related('nodes', 'protocols')\ + .select_related('platform', 'domain', 'host') + def get_serializer_class(self): cls = super().get_serializer_class() if self.action == "retrieve": From 768eb033eb574ae97d1a00f12477df56e2626f47 Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Sun, 25 Jun 2023 14:30:52 +0800 Subject: [PATCH 033/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=8C=96=E4=BB=BB=E5=8A=A1=E5=8E=9F=E5=AD=90=E6=80=A7?= =?UTF-8?q?error=20=E5=AF=BC=E8=87=B4=E6=95=B4=E4=B8=AA=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/ansible/callback.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/ops/ansible/callback.py b/apps/ops/ansible/callback.py index 2045b6f29..1ba87f575 100644 --- a/apps/ops/ansible/callback.py +++ b/apps/ops/ansible/callback.py @@ -109,21 +109,21 @@ class DefaultCallback: pass def playbook_on_stats(self, event_data, **kwargs): - failed = [] error_func = lambda err, task_detail: err + f"{task_detail[0]}: {task_detail[1]['stderr']};" for tp in ['dark', 'failures']: for host, tasks in self.result[tp].items(): - failed.append(host) error = reduce(error_func, tasks.items(), '').strip(';') self.summary[tp][host] = error + failures = list(self.result['failures'].keys()) + dark_or_failures = list(self.result['dark'].keys()) + failures for host, tasks in self.result.get('ignored', {}).items(): ignore_errors = reduce(error_func, tasks.items(), '').strip(';') - if host in failed: + if host in failures: self.summary['failures'][host] += {ignore_errors} - self.summary['ok'] = list(set(self.result['ok'].keys()) - set(failed)) - self.summary['skipped'] = list(set(self.result['skipped'].keys()) - set(failed)) + self.summary['ok'] = list(set(self.result['ok'].keys()) - set(dark_or_failures)) + self.summary['skipped'] = list(set(self.result['skipped'].keys()) - set(dark_or_failures)) def playbook_on_include(self, event_data, **kwargs): pass From 5a2f6bdfc9437e52c82894a9cddfaee2ec67274a Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Thu, 22 Jun 2023 21:36:19 +0800 Subject: [PATCH 034/167] =?UTF-8?q?perf:=20ldap=20sync=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=BC=80=E5=A7=8B=E6=97=B6=20=E5=85=88=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E5=8F=AF=E8=BF=9E=E6=8E=A5=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/settings/api/ldap.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/settings/api/ldap.py b/apps/settings/api/ldap.py index 256d21d31..8c98f821f 100644 --- a/apps/settings/api/ldap.py +++ b/apps/settings/api/ldap.py @@ -10,7 +10,7 @@ from rest_framework.generics import CreateAPIView from rest_framework.views import Response, APIView from common.api import AsyncApiMixin -from common.utils import get_logger, is_uuid +from common.utils import get_logger from orgs.models import Organization from orgs.utils import current_org from users.models import User @@ -166,6 +166,9 @@ class LDAPUserListApi(generics.ListAPIView): sync_util = LDAPSyncUtil() # 还没有同步任务 if sync_util.task_no_start: + ok, msg = LDAPTestUtil().test_config() + if not ok: + return Response(data={'msg': msg}, status=400) # 任务外部设置 task running 状态 sync_util.set_task_status(sync_util.TASK_STATUS_IS_RUNNING) t = threading.Thread(target=sync_ldap_user) From 358b3a1891bbae49ec01eb497181768e7e30ae7f Mon Sep 17 00:00:00 2001 From: nut Date: Mon, 26 Jun 2023 23:51:59 +0800 Subject: [PATCH 035/167] Update asset.py --- apps/assets/api/asset/asset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index c9083f4b6..affd28f03 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -123,7 +123,7 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet): def get_queryset(self): return super().get_queryset().prefetch_related('nodes', 'protocols')\ - .select_related('platform', 'domain', 'host') + .select_related('platform', 'domain') def get_serializer_class(self): cls = super().get_serializer_class() From b3dce273095af1915541ecc3cd76b34eae6a2abc Mon Sep 17 00:00:00 2001 From: "fangfang.dong" Date: Tue, 27 Jun 2023 10:24:47 +0800 Subject: [PATCH 036/167] =?UTF-8?q?perf:=20=E6=8E=A5=E5=8F=A3sql=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20/api/v1/assets/nodes/children/tree/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/tree.py | 9 ++++++--- apps/assets/models/node.py | 12 ------------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/apps/assets/api/tree.py b/apps/assets/api/tree.py index 794e093b7..1970d33ba 100644 --- a/apps/assets/api/tree.py +++ b/apps/assets/api/tree.py @@ -127,10 +127,13 @@ class NodeChildrenAsTreeApi(SerializeToTreeNodeMixin, NodeChildrenApi): if not self.instance or not include_assets: return Asset.objects.none() if query_all: - assets = self.instance.get_all_assets_for_tree() + assets = self.instance.get_all_assets() else: - assets = self.instance.get_assets_for_tree() - return assets + assets = self.instance.get_assets() + return assets.only( + "id", "name", "address", "platform_id", + "org_id", "is_active", 'comment' + ).prefetch_related('platform') def filter_queryset_for_assets(self, assets): search = self.request.query_params.get('search') diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index 3a729ba9f..94ff9aba5 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -429,18 +429,6 @@ class NodeAssetsMixin(NodeAllAssetsMappingMixin): assets = Asset.objects.filter(nodes=self) return assets.distinct() - def get_assets_for_tree(self): - return self.get_assets().only( - "id", "name", "address", "platform_id", - "org_id", "is_active" - ).prefetch_related('platform') - - def get_all_assets_for_tree(self): - return self.get_all_assets().only( - "id", "name", "address", "platform_id", - "org_id", "is_active" - ).prefetch_related('platform') - def get_valid_assets(self): return self.get_assets().valid() From 4e9012cc074c815c0e1612fd2fbf29d2320a3e62 Mon Sep 17 00:00:00 2001 From: "fangfang.dong" Date: Tue, 27 Jun 2023 10:45:50 +0800 Subject: [PATCH 037/167] =?UTF-8?q?perf:=20=E6=8E=A5=E5=8F=A3sql=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20/api/v1/accounts/account-templates/su-from-account-?= =?UTF-8?q?templates/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/api/account/template.py | 3 +-- apps/accounts/models/account.py | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/accounts/api/account/template.py b/apps/accounts/api/account/template.py index 0aecb5143..1d2508764 100644 --- a/apps/accounts/api/account/template.py +++ b/apps/accounts/api/account/template.py @@ -49,8 +49,7 @@ class AccountTemplateViewSet(OrgBulkModelViewSet): @action(methods=['get'], detail=False, url_path='su-from-account-templates') def su_from_account_templates(self, request, *args, **kwargs): pk = request.query_params.get('template_id') - template = AccountTemplate.objects.filter(pk=pk).first() - templates = AccountTemplate.get_su_from_account_templates(template) + templates = AccountTemplate.get_su_from_account_templates(pk) templates = self.filter_queryset(templates) serializer = self.get_serializer(templates, many=True) return Response(data=serializer.data) diff --git a/apps/accounts/models/account.py b/apps/accounts/models/account.py index 30eb853e3..81300e747 100644 --- a/apps/accounts/models/account.py +++ b/apps/accounts/models/account.py @@ -124,10 +124,10 @@ class AccountTemplate(BaseAccount): ] @classmethod - def get_su_from_account_templates(cls, instance=None): - if not instance: + def get_su_from_account_templates(cls, pk=None): + if pk is None: return cls.objects.all() - return cls.objects.exclude(Q(id=instance.id) | Q(su_from=instance)) + return cls.objects.exclude(Q(id=pk) | Q(_id=pk)) def get_su_from_account(self, asset): su_from = self.su_from From 77bcb05d8095f208d564589aa2b8be2e4dfa08e4 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 27 Jun 2023 11:23:56 +0800 Subject: [PATCH 038/167] =?UTF-8?q?perf:=20web=20=E5=92=8C=20=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E7=B1=BB=E5=9E=8B=E8=B5=84=E4=BA=A7=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=8C=BF=E5=90=8D=E8=B4=A6=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/const/account.py | 1 + apps/accounts/models/account.py | 13 ++ .../authentication/models/connection_token.py | 32 ++-- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 143 +++++++++--------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 143 +++++++++--------- apps/perms/utils/account.py | 19 ++- 8 files changed, 188 insertions(+), 171 deletions(-) diff --git a/apps/accounts/const/account.py b/apps/accounts/const/account.py index 55fa02d80..c57520db7 100644 --- a/apps/accounts/const/account.py +++ b/apps/accounts/const/account.py @@ -13,6 +13,7 @@ class AliasAccount(TextChoices): ALL = '@ALL', _('All') INPUT = '@INPUT', _('Manual input') USER = '@USER', _('Dynamic user') + ANON = '@ANON', _('Anonymous user') class Source(TextChoices): diff --git a/apps/accounts/models/account.py b/apps/accounts/models/account.py index 30eb853e3..98890b64f 100644 --- a/apps/accounts/models/account.py +++ b/apps/accounts/models/account.py @@ -88,11 +88,24 @@ class Account(AbsConnectivity, BaseAccount): def has_secret(self): return bool(self.secret) + @classmethod + def get_special_account(cls, name): + if name == AliasAccount.INPUT.value: + return cls.get_manual_account() + elif name == AliasAccount.ANON.value: + return cls.get_anonymous_account() + else: + return cls(name=name, username=name, secret=None) + @classmethod def get_manual_account(cls): """ @INPUT 手动登录的账号(any) """ return cls(name=AliasAccount.INPUT.label, username=AliasAccount.INPUT.value, secret=None) + @classmethod + def get_anonymous_account(cls): + return cls(name=AliasAccount.ANON.label, username=AliasAccount.ANON.value, secret=None) + @lazyproperty def versions(self): return self.history.count() diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py index acef092b1..340d275e4 100644 --- a/apps/authentication/models/connection_token.py +++ b/apps/authentication/models/connection_token.py @@ -209,29 +209,17 @@ class ConnectionToken(JMSOrgBaseModel): if not self.asset: return None - account = self.asset.accounts.filter(name=self.account).first() - if self.account == '@INPUT' or not account: - data = { - 'name': self.account, - 'username': self.input_username, - 'secret_type': 'password', - 'secret': self.input_secret, - 'su_from': None, - 'org_id': self.asset.org_id, - 'asset': self.asset - } + if self.account == '@ANON' and self.asset.category not in ['web', 'custom']: + raise JMSException({'error': 'Anonymous account is not supported in {}'.format(self.asset.category)}) + + if self.account.startswith('@'): + account = Account.get_special_account(self.account) else: - data = { - 'name': account.name, - 'username': account.username, - 'secret_type': account.secret_type, - 'secret': account.secret or self.input_secret, - 'su_from': account.su_from, - 'org_id': account.org_id, - 'privileged': account.privileged, - 'asset': self.asset - } - return Account(**data) + account = self.asset.accounts.filter(name=self.account).first() + + account.asset = self.asset + account.secret = account.secret or self.input_secret + return account @lazyproperty def domain(self): diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index f057cb635..ae0b7facf 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd4fb6a0396c8636f8a36645354a5102790c020d73cdeb1f0e1d1f1b34ea39e9 -size 145760 +oid sha256:36918c53144eaae27cb3b68d47882f6ca9b75669862f28f611fb737f6ca39631 +size 145810 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index dbfc085e6..7a86fc588 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-15 15:35+0800\n" +"POT-Creation-Date: 2023-06-27 10:17+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -62,32 +62,36 @@ msgstr "手動入力" msgid "Dynamic user" msgstr "動的コード" -#: accounts/const/account.py:19 users/models/user.py:699 +#: accounts/const/account.py:16 +msgid "Anonymous user" +msgstr "匿名ユーザー" + +#: accounts/const/account.py:20 users/models/user.py:699 msgid "Local" msgstr "ローカル" -#: accounts/const/account.py:20 +#: accounts/const/account.py:21 msgid "Collected" msgstr "集めました" -#: accounts/const/account.py:21 accounts/serializers/account/account.py:27 +#: accounts/const/account.py:22 accounts/serializers/account/account.py:27 #: settings/serializers/auth/sms.py:75 msgid "Template" msgstr "テンプレート" -#: accounts/const/account.py:25 ops/const.py:45 +#: accounts/const/account.py:26 ops/const.py:45 msgid "Skip" msgstr "スキップ" -#: accounts/const/account.py:26 audits/const.py:24 rbac/tree.py:229 +#: accounts/const/account.py:27 audits/const.py:24 rbac/tree.py:229 #: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 msgid "Update" msgstr "更新" -#: accounts/const/account.py:27 +#: accounts/const/account.py:28 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:61 xpack/plugins/cloud/const.py:41 +#: ops/const.py:58 terminal/const.py:62 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失敗しました" @@ -187,17 +191,17 @@ msgstr "作成のみ" #: accounts/serializers/automations/change_secret.py:112 #: accounts/serializers/automations/change_secret.py:132 #: acls/serializers/base.py:118 assets/models/asset/common.py:93 -#: assets/models/asset/common.py:332 assets/models/cmd_filter.py:36 +#: assets/models/asset/common.py:331 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:53 authentication/models/connection_token.py:35 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 -#: terminal/backends/command/models.py:20 terminal/models/session/session.py:32 +#: terminal/backends/command/models.py:20 terminal/models/session/session.py:31 #: terminal/notifications.py:95 terminal/serializers/command.py:17 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "資産" -#: accounts/models/account.py:53 accounts/models/account.py:113 +#: accounts/models/account.py:53 accounts/models/account.py:117 #: accounts/serializers/account/account.py:208 #: accounts/serializers/account/account.py:247 #: accounts/serializers/account/template.py:16 @@ -225,7 +229,7 @@ msgstr "ソース ID" #: acls/serializers/base.py:119 assets/serializers/asset/common.py:125 #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 -#: terminal/backends/command/models.py:21 terminal/models/session/session.py:34 +#: terminal/backends/command/models.py:21 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "アカウント" @@ -250,15 +254,15 @@ msgstr "アカウントを確認できます" msgid "Can push account" msgstr "アカウントをプッシュできます" -#: accounts/models/account.py:117 +#: accounts/models/account.py:121 msgid "Account template" msgstr "アカウント テンプレート" -#: accounts/models/account.py:122 +#: accounts/models/account.py:126 msgid "Can view asset account template secret" msgstr "アセット アカウント テンプレートのパスワードを表示できます" -#: accounts/models/account.py:123 +#: accounts/models/account.py:127 msgid "Can change asset account template secret" msgstr "アセット アカウント テンプレートのパスワードを変更できます" @@ -279,7 +283,7 @@ msgstr "アカウントバックアップ計画" #: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:192 #: ops/templates/ops/celery_task_log.html:75 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:137 -#: terminal/models/session/session.py:45 +#: terminal/models/session/session.py:44 #: tickets/models/ticket/apply_application.py:30 #: tickets/models/ticket/apply_asset.py:19 msgid "Date start" @@ -479,7 +483,7 @@ msgstr "アカウントの確認" #: applications/models.py:9 assets/models/_user.py:22 #: assets/models/asset/common.py:91 assets/models/asset/common.py:149 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 -#: assets/models/group.py:20 assets/models/label.py:18 +#: assets/models/group.py:17 assets/models/label.py:18 #: assets/models/platform.py:13 assets/models/platform.py:81 #: assets/serializers/asset/common.py:145 assets/serializers/platform.py:99 #: assets/serializers/platform.py:199 @@ -505,7 +509,8 @@ msgstr "特権アカウント" #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:114 -#: terminal/models/applet/applet.py:39 users/serializers/user.py:169 +#: terminal/models/applet/applet.py:39 +#: terminal/models/component/endpoint.py:101 users/serializers/user.py:169 msgid "Is active" msgstr "アクティブです。" @@ -644,7 +649,7 @@ msgstr "ID" #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 #: perms/serializers/permission.py:30 rbac/builtin.py:122 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:19 -#: terminal/models/session/session.py:30 terminal/models/session/sharing.py:32 +#: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 #: terminal/notifications.py:96 terminal/notifications.py:144 #: terminal/serializers/command.py:16 tickets/models/comment.py:21 #: users/const.py:14 users/models/user.py:947 users/models/user.py:978 @@ -729,7 +734,7 @@ msgstr "自動タスク実行履歴" #: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:40 -#: terminal/const.py:60 terminal/models/session/sharing.py:107 +#: terminal/const.py:61 terminal/models/session/sharing.py:107 #: tickets/views/approve.py:114 msgid "Success" msgstr "成功" @@ -825,8 +830,8 @@ msgid "Accounts" msgstr "アカウント" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:55 terminal/const.py:68 -#: terminal/models/session/session.py:43 terminal/serializers/command.py:18 +#: ops/serializers/job.py:55 terminal/const.py:69 +#: terminal/models/session/session.py:42 terminal/serializers/command.py:18 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 msgid "Command" @@ -970,7 +975,7 @@ msgstr "" "資産を直接作成することはできません。ホストまたはその他を作成する必要がありま" "す" -#: assets/api/domain.py:60 +#: assets/api/domain.py:62 msgid "Number required" msgstr "必要な数" @@ -1106,7 +1111,7 @@ msgstr "ファイアウォール" msgid "Other" msgstr "その他" -#: assets/const/types.py:223 +#: assets/const/types.py:222 msgid "All types" msgstr "いろんなタイプ" @@ -1141,20 +1146,20 @@ msgid "SSH public key" msgstr "SSHパブリックキー" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 -#: assets/models/cmd_filter.py:88 assets/models/group.py:23 +#: assets/models/cmd_filter.py:88 assets/models/group.py:20 #: common/db/models.py:36 ops/models/adhoc.py:27 ops/models/job.py:111 #: ops/models/playbook.py:26 rbac/models/role.py:37 settings/models.py:38 -#: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:244 +#: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:248 #: terminal/models/applet/host.py:139 terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:100 -#: terminal/models/session/session.py:47 tickets/models/comment.py:32 +#: terminal/models/session/session.py:46 tickets/models/comment.py:32 #: tickets/models/ticket/general.py:297 users/models/user.py:792 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 msgid "Comment" msgstr "コメント" #: assets/models/_user.py:28 assets/models/automations/base.py:114 -#: assets/models/cmd_filter.py:41 assets/models/group.py:22 +#: assets/models/cmd_filter.py:41 assets/models/group.py:19 #: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:191 #: users/models/user.py:979 msgid "Date created" @@ -1166,7 +1171,7 @@ msgid "Date updated" msgstr "更新日" #: assets/models/_user.py:30 assets/models/cmd_filter.py:44 -#: assets/models/cmd_filter.py:91 assets/models/group.py:21 +#: assets/models/cmd_filter.py:91 assets/models/group.py:18 #: common/db/models.py:32 users/models/user.py:799 #: users/serializers/group.py:29 msgid "Created by" @@ -1283,19 +1288,19 @@ msgstr "資産ハードウェア情報の収集" msgid "Custom info" msgstr "カスタム属性" -#: assets/models/asset/common.py:335 +#: assets/models/asset/common.py:334 msgid "Can refresh asset hardware info" msgstr "資産ハードウェア情報を更新できます" -#: assets/models/asset/common.py:336 +#: assets/models/asset/common.py:335 msgid "Can test asset connectivity" msgstr "資産接続をテストできます" -#: assets/models/asset/common.py:337 +#: assets/models/asset/common.py:336 msgid "Can match asset" msgstr "アセットを一致させることができます" -#: assets/models/asset/common.py:338 +#: assets/models/asset/common.py:337 msgid "Can change asset nodes" msgstr "資産ノードを変更できます" @@ -1356,7 +1361,7 @@ msgstr "アセットの自動化タスク" #: assets/models/automations/base.py:113 audits/models.py:199 #: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:184 -#: terminal/models/applet/applet.py:243 terminal/models/applet/host.py:136 +#: terminal/models/applet/applet.py:247 terminal/models/applet/host.py:136 #: terminal/models/component/status.py:30 terminal/serializers/applet.py:18 #: terminal/serializers/applet_host.py:107 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 @@ -1419,17 +1424,17 @@ msgstr "お気に入りのアセット" msgid "Gateway" msgstr "ゲートウェイ" -#: assets/models/group.py:30 +#: assets/models/group.py:27 msgid "Asset group" msgstr "資産グループ" -#: assets/models/group.py:34 assets/models/platform.py:17 +#: assets/models/group.py:31 assets/models/platform.py:17 #: assets/serializers/platform.py:102 #: xpack/plugins/cloud/providers/nutanix.py:30 msgid "Default" msgstr "デフォルト" -#: assets/models/group.py:34 +#: assets/models/group.py:31 msgid "Default asset group" msgstr "デフォルトアセットグループ" @@ -1950,7 +1955,7 @@ msgid "Job audit log" msgstr "ジョブ監査ログ" #: audits/models.py:51 audits/models.py:95 audits/models.py:166 -#: terminal/models/session/session.py:39 terminal/models/session/sharing.py:99 +#: terminal/models/session/session.py:38 terminal/models/session/sharing.py:99 msgid "Remote addr" msgstr "リモートaddr" @@ -2090,14 +2095,14 @@ msgid "Auth Token" msgstr "認証トークン" #: audits/signal_handlers/login_log.py:31 authentication/notifications.py:73 -#: authentication/views/login.py:74 authentication/views/wecom.py:159 +#: authentication/views/login.py:75 authentication/views/wecom.py:159 #: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10 #: users/models/user.py:706 users/models/user.py:814 msgid "WeCom" msgstr "企業微信" #: audits/signal_handlers/login_log.py:32 authentication/views/feishu.py:123 -#: authentication/views/login.py:86 notifications/backends/__init__.py:14 +#: authentication/views/login.py:87 notifications/backends/__init__.py:14 #: settings/serializers/auth/feishu.py:10 #: settings/serializers/auth/feishu.py:13 users/models/user.py:708 #: users/models/user.py:816 @@ -2105,7 +2110,7 @@ msgid "FeiShu" msgstr "本を飛ばす" #: audits/signal_handlers/login_log.py:33 authentication/views/dingtalk.py:160 -#: authentication/views/login.py:80 notifications/backends/__init__.py:12 +#: authentication/views/login.py:81 notifications/backends/__init__.py:12 #: settings/serializers/auth/dingtalk.py:10 users/models/user.py:707 #: users/models/user.py:815 msgid "DingTalk" @@ -2981,23 +2986,23 @@ msgstr "本を飛ばすのバインドに成功" msgid "Failed to get user from FeiShu" msgstr "本を飛ばすからユーザーを取得できませんでした" -#: authentication/views/login.py:182 +#: authentication/views/login.py:183 msgid "Redirecting" msgstr "リダイレクト" -#: authentication/views/login.py:183 +#: authentication/views/login.py:184 msgid "Redirecting to {} authentication" msgstr "{} 認証へのリダイレクト" -#: authentication/views/login.py:206 +#: authentication/views/login.py:207 msgid "Please enable cookies and try again." msgstr "クッキーを有効にして、もう一度お試しください。" -#: authentication/views/login.py:247 +#: authentication/views/login.py:248 msgid "User email already exists ({})" msgstr "ユーザー メールボックスは既に存在します ({})" -#: authentication/views/login.py:325 +#: authentication/views/login.py:326 msgid "" "Wait for {} confirm, You also can copy link to her/him
\n" " Don't close this page" @@ -3005,15 +3010,15 @@ msgstr "" "{} 確認を待ちます。彼女/彼へのリンクをコピーすることもできます
\n" " このページを閉じないでください" -#: authentication/views/login.py:330 +#: authentication/views/login.py:331 msgid "No ticket found" msgstr "チケットが見つかりません" -#: authentication/views/login.py:366 +#: authentication/views/login.py:367 msgid "Logout success" msgstr "ログアウト成功" -#: authentication/views/login.py:367 +#: authentication/views/login.py:368 msgid "Logout success, return login page" msgstr "ログアウト成功、ログインページを返す" @@ -3061,7 +3066,7 @@ msgstr "タイミングトリガー" msgid "Ready" msgstr "の準備を" -#: common/const/choices.py:16 terminal/const.py:59 tickets/const.py:29 +#: common/const/choices.py:16 terminal/const.py:60 tickets/const.py:29 #: tickets/const.py:39 msgid "Pending" msgstr "未定" @@ -4118,7 +4123,7 @@ msgid "My assets" msgstr "私の資産" #: rbac/tree.py:56 terminal/models/applet/applet.py:51 -#: terminal/models/applet/applet.py:240 terminal/models/applet/host.py:28 +#: terminal/models/applet/applet.py:244 terminal/models/applet/host.py:28 #: terminal/serializers/applet.py:15 msgid "Applet" msgstr "リモートアプリケーション" @@ -5640,7 +5645,7 @@ msgstr "クリティカル" msgid "High" msgstr "高い" -#: terminal/const.py:32 terminal/const.py:66 +#: terminal/const.py:32 terminal/const.py:67 #: users/templates/users/reset_password.html:50 msgid "Normal" msgstr "正常" @@ -5649,19 +5654,19 @@ msgstr "正常" msgid "Offline" msgstr "オフライン" -#: terminal/const.py:62 +#: terminal/const.py:63 msgid "Mismatch" msgstr "一致しない" -#: terminal/const.py:67 +#: terminal/const.py:68 msgid "Tunnel" msgstr "" -#: terminal/const.py:72 +#: terminal/const.py:73 msgid "Read Only" msgstr "読み取り専用" -#: terminal/const.py:73 +#: terminal/const.py:74 msgid "Writable" msgstr "書き込み可能" @@ -5717,7 +5722,7 @@ msgstr "カスタムプラットフォームのみをサポート" msgid "Missing type in platform.yml" msgstr "platform.ymlにタイプがありません" -#: terminal/models/applet/applet.py:242 terminal/models/applet/host.py:34 +#: terminal/models/applet/applet.py:246 terminal/models/applet/host.py:34 #: terminal/models/applet/host.py:134 msgid "Hosting" msgstr "ホスト マシン" @@ -5786,7 +5791,7 @@ msgstr "エンドポイント" msgid "IP group" msgstr "IP グループ" -#: terminal/models/component/endpoint.py:103 +#: terminal/models/component/endpoint.py:104 msgid "Endpoint rule" msgstr "エンドポイントルール" @@ -5864,39 +5869,39 @@ msgstr "セッションのリプレイをアップロードできます" msgid "Can download session replay" msgstr "セッション再生をダウンロードできます" -#: terminal/models/session/session.py:35 +#: terminal/models/session/session.py:34 msgid "Account id" msgstr "アカウント ID" -#: terminal/models/session/session.py:37 terminal/models/session/sharing.py:104 +#: terminal/models/session/session.py:36 terminal/models/session/sharing.py:104 msgid "Login from" msgstr "ログイン元" -#: terminal/models/session/session.py:42 +#: terminal/models/session/session.py:41 msgid "Replay" msgstr "リプレイ" -#: terminal/models/session/session.py:46 +#: terminal/models/session/session.py:45 msgid "Date end" msgstr "終了日" -#: terminal/models/session/session.py:243 +#: terminal/models/session/session.py:240 msgid "Session record" msgstr "セッション記録" -#: terminal/models/session/session.py:245 +#: terminal/models/session/session.py:242 msgid "Can monitor session" msgstr "セッションを監視できます" -#: terminal/models/session/session.py:246 +#: terminal/models/session/session.py:243 msgid "Can share session" msgstr "セッションを共有できます" -#: terminal/models/session/session.py:247 +#: terminal/models/session/session.py:244 msgid "Can terminate session" msgstr "セッションを終了できます" -#: terminal/models/session/session.py:248 +#: terminal/models/session/session.py:245 msgid "Can validate session action perm" msgstr "セッションアクションのパーマを検証できます" @@ -6447,11 +6452,11 @@ msgstr "承認ステップ" msgid "Relation snapshot" msgstr "製造オーダスナップショット" -#: tickets/models/ticket/general.py:392 +#: tickets/models/ticket/general.py:398 msgid "Please try again" msgstr "もう一度お試しください" -#: tickets/models/ticket/general.py:461 +#: tickets/models/ticket/general.py:467 msgid "Super ticket" msgstr "スーパーチケット" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 1c7c46cca..47f90fa82 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0efb248e80873f34d20f0fc3d4dd5c5a346048cb683c2b6bda3df939697fc52c -size 119261 +oid sha256:1f4301cf32731559d2e5ce41c2ab00e4655931914d8ce36bde4ad831cc5ee3f9 +size 119305 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 48b00a44f..6b10f0926 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-15 15:35+0800\n" +"POT-Creation-Date: 2023-06-27 10:17+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -61,32 +61,36 @@ msgstr "手动输入" msgid "Dynamic user" msgstr "同名账号" -#: accounts/const/account.py:19 users/models/user.py:699 +#: accounts/const/account.py:16 +msgid "Anonymous user" +msgstr "匿名用户" + +#: accounts/const/account.py:20 users/models/user.py:699 msgid "Local" msgstr "数据库" -#: accounts/const/account.py:20 +#: accounts/const/account.py:21 msgid "Collected" msgstr "收集" -#: accounts/const/account.py:21 accounts/serializers/account/account.py:27 +#: accounts/const/account.py:22 accounts/serializers/account/account.py:27 #: settings/serializers/auth/sms.py:75 msgid "Template" msgstr "模板" -#: accounts/const/account.py:25 ops/const.py:45 +#: accounts/const/account.py:26 ops/const.py:45 msgid "Skip" msgstr "跳过" -#: accounts/const/account.py:26 audits/const.py:24 rbac/tree.py:229 +#: accounts/const/account.py:27 audits/const.py:24 rbac/tree.py:229 #: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 msgid "Update" msgstr "更新" -#: accounts/const/account.py:27 +#: accounts/const/account.py:28 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:61 xpack/plugins/cloud/const.py:41 +#: ops/const.py:58 terminal/const.py:62 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失败" @@ -186,17 +190,17 @@ msgstr "仅创建" #: accounts/serializers/automations/change_secret.py:112 #: accounts/serializers/automations/change_secret.py:132 #: acls/serializers/base.py:118 assets/models/asset/common.py:93 -#: assets/models/asset/common.py:332 assets/models/cmd_filter.py:36 +#: assets/models/asset/common.py:331 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:53 authentication/models/connection_token.py:35 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 -#: terminal/backends/command/models.py:20 terminal/models/session/session.py:32 +#: terminal/backends/command/models.py:20 terminal/models/session/session.py:31 #: terminal/notifications.py:95 terminal/serializers/command.py:17 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "资产" -#: accounts/models/account.py:53 accounts/models/account.py:113 +#: accounts/models/account.py:53 accounts/models/account.py:117 #: accounts/serializers/account/account.py:208 #: accounts/serializers/account/account.py:247 #: accounts/serializers/account/template.py:16 @@ -224,7 +228,7 @@ msgstr "来源 ID" #: acls/serializers/base.py:119 assets/serializers/asset/common.py:125 #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 -#: terminal/backends/command/models.py:21 terminal/models/session/session.py:34 +#: terminal/backends/command/models.py:21 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "账号" @@ -249,15 +253,15 @@ msgstr "可以验证账号" msgid "Can push account" msgstr "可以推送账号" -#: accounts/models/account.py:117 +#: accounts/models/account.py:121 msgid "Account template" msgstr "账号模版" -#: accounts/models/account.py:122 +#: accounts/models/account.py:126 msgid "Can view asset account template secret" msgstr "可以查看资产账号模版密码" -#: accounts/models/account.py:123 +#: accounts/models/account.py:127 msgid "Can change asset account template secret" msgstr "可以更改资产账号模版密码" @@ -278,7 +282,7 @@ msgstr "账号备份计划" #: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:192 #: ops/templates/ops/celery_task_log.html:75 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:137 -#: terminal/models/session/session.py:45 +#: terminal/models/session/session.py:44 #: tickets/models/ticket/apply_application.py:30 #: tickets/models/ticket/apply_asset.py:19 msgid "Date start" @@ -478,7 +482,7 @@ msgstr "账号验证" #: applications/models.py:9 assets/models/_user.py:22 #: assets/models/asset/common.py:91 assets/models/asset/common.py:149 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 -#: assets/models/group.py:20 assets/models/label.py:18 +#: assets/models/group.py:17 assets/models/label.py:18 #: assets/models/platform.py:13 assets/models/platform.py:81 #: assets/serializers/asset/common.py:145 assets/serializers/platform.py:99 #: assets/serializers/platform.py:199 @@ -504,7 +508,8 @@ msgstr "特权账号" #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:114 -#: terminal/models/applet/applet.py:39 users/serializers/user.py:169 +#: terminal/models/applet/applet.py:39 +#: terminal/models/component/endpoint.py:101 users/serializers/user.py:169 msgid "Is active" msgstr "激活" @@ -640,7 +645,7 @@ msgstr "ID" #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 #: perms/serializers/permission.py:30 rbac/builtin.py:122 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:19 -#: terminal/models/session/session.py:30 terminal/models/session/sharing.py:32 +#: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 #: terminal/notifications.py:96 terminal/notifications.py:144 #: terminal/serializers/command.py:16 tickets/models/comment.py:21 #: users/const.py:14 users/models/user.py:947 users/models/user.py:978 @@ -725,7 +730,7 @@ msgstr "自动化任务执行历史" #: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:40 -#: terminal/const.py:60 terminal/models/session/sharing.py:107 +#: terminal/const.py:61 terminal/models/session/sharing.py:107 #: tickets/views/approve.py:114 msgid "Success" msgstr "成功" @@ -821,8 +826,8 @@ msgid "Accounts" msgstr "账号管理" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:55 terminal/const.py:68 -#: terminal/models/session/session.py:43 terminal/serializers/command.py:18 +#: ops/serializers/job.py:55 terminal/const.py:69 +#: terminal/models/session/session.py:42 terminal/serializers/command.py:18 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 msgid "Command" @@ -963,7 +968,7 @@ msgstr "匹配应用" msgid "Cannot create asset directly, you should create a host or other" msgstr "不能直接创建资产, 你应该创建主机或其他资产" -#: assets/api/domain.py:60 +#: assets/api/domain.py:62 msgid "Number required" msgstr "需要为数字" @@ -1099,7 +1104,7 @@ msgstr "防火墙" msgid "Other" msgstr "其它" -#: assets/const/types.py:223 +#: assets/const/types.py:222 msgid "All types" msgstr "所有类型" @@ -1134,20 +1139,20 @@ msgid "SSH public key" msgstr "SSH公钥" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 -#: assets/models/cmd_filter.py:88 assets/models/group.py:23 +#: assets/models/cmd_filter.py:88 assets/models/group.py:20 #: common/db/models.py:36 ops/models/adhoc.py:27 ops/models/job.py:111 #: ops/models/playbook.py:26 rbac/models/role.py:37 settings/models.py:38 -#: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:244 +#: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:248 #: terminal/models/applet/host.py:139 terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:100 -#: terminal/models/session/session.py:47 tickets/models/comment.py:32 +#: terminal/models/session/session.py:46 tickets/models/comment.py:32 #: tickets/models/ticket/general.py:297 users/models/user.py:792 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 msgid "Comment" msgstr "备注" #: assets/models/_user.py:28 assets/models/automations/base.py:114 -#: assets/models/cmd_filter.py:41 assets/models/group.py:22 +#: assets/models/cmd_filter.py:41 assets/models/group.py:19 #: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:191 #: users/models/user.py:979 msgid "Date created" @@ -1159,7 +1164,7 @@ msgid "Date updated" msgstr "更新日期" #: assets/models/_user.py:30 assets/models/cmd_filter.py:44 -#: assets/models/cmd_filter.py:91 assets/models/group.py:21 +#: assets/models/cmd_filter.py:91 assets/models/group.py:18 #: common/db/models.py:32 users/models/user.py:799 #: users/serializers/group.py:29 msgid "Created by" @@ -1276,19 +1281,19 @@ msgstr "收集资产硬件信息" msgid "Custom info" msgstr "自定义属性" -#: assets/models/asset/common.py:335 +#: assets/models/asset/common.py:334 msgid "Can refresh asset hardware info" msgstr "可以更新资产硬件信息" -#: assets/models/asset/common.py:336 +#: assets/models/asset/common.py:335 msgid "Can test asset connectivity" msgstr "可以测试资产连接性" -#: assets/models/asset/common.py:337 +#: assets/models/asset/common.py:336 msgid "Can match asset" msgstr "可以匹配资产" -#: assets/models/asset/common.py:338 +#: assets/models/asset/common.py:337 msgid "Can change asset nodes" msgstr "可以修改资产节点" @@ -1349,7 +1354,7 @@ msgstr "资产自动化任务" #: assets/models/automations/base.py:113 audits/models.py:199 #: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:184 -#: terminal/models/applet/applet.py:243 terminal/models/applet/host.py:136 +#: terminal/models/applet/applet.py:247 terminal/models/applet/host.py:136 #: terminal/models/component/status.py:30 terminal/serializers/applet.py:18 #: terminal/serializers/applet_host.py:107 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 @@ -1412,17 +1417,17 @@ msgstr "收藏的资产" msgid "Gateway" msgstr "网关" -#: assets/models/group.py:30 +#: assets/models/group.py:27 msgid "Asset group" msgstr "资产组" -#: assets/models/group.py:34 assets/models/platform.py:17 +#: assets/models/group.py:31 assets/models/platform.py:17 #: assets/serializers/platform.py:102 #: xpack/plugins/cloud/providers/nutanix.py:30 msgid "Default" msgstr "默认" -#: assets/models/group.py:34 +#: assets/models/group.py:31 msgid "Default asset group" msgstr "默认资产组" @@ -1939,7 +1944,7 @@ msgid "Job audit log" msgstr "作业审计日志" #: audits/models.py:51 audits/models.py:95 audits/models.py:166 -#: terminal/models/session/session.py:39 terminal/models/session/sharing.py:99 +#: terminal/models/session/session.py:38 terminal/models/session/sharing.py:99 msgid "Remote addr" msgstr "远端地址" @@ -2079,14 +2084,14 @@ msgid "Auth Token" msgstr "认证令牌" #: audits/signal_handlers/login_log.py:31 authentication/notifications.py:73 -#: authentication/views/login.py:74 authentication/views/wecom.py:159 +#: authentication/views/login.py:75 authentication/views/wecom.py:159 #: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10 #: users/models/user.py:706 users/models/user.py:814 msgid "WeCom" msgstr "企业微信" #: audits/signal_handlers/login_log.py:32 authentication/views/feishu.py:123 -#: authentication/views/login.py:86 notifications/backends/__init__.py:14 +#: authentication/views/login.py:87 notifications/backends/__init__.py:14 #: settings/serializers/auth/feishu.py:10 #: settings/serializers/auth/feishu.py:13 users/models/user.py:708 #: users/models/user.py:816 @@ -2094,7 +2099,7 @@ msgid "FeiShu" msgstr "飞书" #: audits/signal_handlers/login_log.py:33 authentication/views/dingtalk.py:160 -#: authentication/views/login.py:80 notifications/backends/__init__.py:12 +#: authentication/views/login.py:81 notifications/backends/__init__.py:12 #: settings/serializers/auth/dingtalk.py:10 users/models/user.py:707 #: users/models/user.py:815 msgid "DingTalk" @@ -2946,23 +2951,23 @@ msgstr "绑定 飞书 成功" msgid "Failed to get user from FeiShu" msgstr "从飞书获取用户失败" -#: authentication/views/login.py:182 +#: authentication/views/login.py:183 msgid "Redirecting" msgstr "跳转中" -#: authentication/views/login.py:183 +#: authentication/views/login.py:184 msgid "Redirecting to {} authentication" msgstr "正在跳转到 {} 认证" -#: authentication/views/login.py:206 +#: authentication/views/login.py:207 msgid "Please enable cookies and try again." msgstr "设置你的浏览器支持cookie" -#: authentication/views/login.py:247 +#: authentication/views/login.py:248 msgid "User email already exists ({})" msgstr "用户邮箱已存在 ({})" -#: authentication/views/login.py:325 +#: authentication/views/login.py:326 msgid "" "Wait for {} confirm, You also can copy link to her/him
\n" " Don't close this page" @@ -2970,15 +2975,15 @@ msgstr "" "等待 {} 确认, 你也可以复制链接发给他/她
\n" " 不要关闭本页面" -#: authentication/views/login.py:330 +#: authentication/views/login.py:331 msgid "No ticket found" msgstr "没有发现工单" -#: authentication/views/login.py:366 +#: authentication/views/login.py:367 msgid "Logout success" msgstr "退出登录成功" -#: authentication/views/login.py:367 +#: authentication/views/login.py:368 msgid "Logout success, return login page" msgstr "退出登录成功,返回到登录页面" @@ -3026,7 +3031,7 @@ msgstr "定时触发" msgid "Ready" msgstr "准备" -#: common/const/choices.py:16 terminal/const.py:59 tickets/const.py:29 +#: common/const/choices.py:16 terminal/const.py:60 tickets/const.py:29 #: tickets/const.py:39 msgid "Pending" msgstr "待定的" @@ -4074,7 +4079,7 @@ msgid "My assets" msgstr "我的资产" #: rbac/tree.py:56 terminal/models/applet/applet.py:51 -#: terminal/models/applet/applet.py:240 terminal/models/applet/host.py:28 +#: terminal/models/applet/applet.py:244 terminal/models/applet/host.py:28 #: terminal/serializers/applet.py:15 msgid "Applet" msgstr "远程应用" @@ -5558,7 +5563,7 @@ msgstr "严重" msgid "High" msgstr "较高" -#: terminal/const.py:32 terminal/const.py:66 +#: terminal/const.py:32 terminal/const.py:67 #: users/templates/users/reset_password.html:50 msgid "Normal" msgstr "正常" @@ -5567,19 +5572,19 @@ msgstr "正常" msgid "Offline" msgstr "离线" -#: terminal/const.py:62 +#: terminal/const.py:63 msgid "Mismatch" msgstr "未匹配" -#: terminal/const.py:67 +#: terminal/const.py:68 msgid "Tunnel" msgstr "隧道" -#: terminal/const.py:72 +#: terminal/const.py:73 msgid "Read Only" msgstr "只读" -#: terminal/const.py:73 +#: terminal/const.py:74 msgid "Writable" msgstr "读写" @@ -5635,7 +5640,7 @@ msgstr "只支持自定义平台" msgid "Missing type in platform.yml" msgstr "在 platform.yml 中缺少类型" -#: terminal/models/applet/applet.py:242 terminal/models/applet/host.py:34 +#: terminal/models/applet/applet.py:246 terminal/models/applet/host.py:34 #: terminal/models/applet/host.py:134 msgid "Hosting" msgstr "宿主机" @@ -5704,7 +5709,7 @@ msgstr "端点" msgid "IP group" msgstr "IP 组" -#: terminal/models/component/endpoint.py:103 +#: terminal/models/component/endpoint.py:104 msgid "Endpoint rule" msgstr "端点规则" @@ -5782,39 +5787,39 @@ msgstr "可以上传会话录像" msgid "Can download session replay" msgstr "可以下载会话录像" -#: terminal/models/session/session.py:35 +#: terminal/models/session/session.py:34 msgid "Account id" msgstr "账号 ID" -#: terminal/models/session/session.py:37 terminal/models/session/sharing.py:104 +#: terminal/models/session/session.py:36 terminal/models/session/sharing.py:104 msgid "Login from" msgstr "登录来源" -#: terminal/models/session/session.py:42 +#: terminal/models/session/session.py:41 msgid "Replay" msgstr "回放" -#: terminal/models/session/session.py:46 +#: terminal/models/session/session.py:45 msgid "Date end" msgstr "结束日期" -#: terminal/models/session/session.py:243 +#: terminal/models/session/session.py:240 msgid "Session record" msgstr "会话记录" -#: terminal/models/session/session.py:245 +#: terminal/models/session/session.py:242 msgid "Can monitor session" msgstr "可以监控会话" -#: terminal/models/session/session.py:246 +#: terminal/models/session/session.py:243 msgid "Can share session" msgstr "可以分享会话" -#: terminal/models/session/session.py:247 +#: terminal/models/session/session.py:244 msgid "Can terminate session" msgstr "可以终断会话" -#: terminal/models/session/session.py:248 +#: terminal/models/session/session.py:245 msgid "Can validate session action perm" msgstr "可以验证会话动作权限" @@ -6356,11 +6361,11 @@ msgstr "审批步骤" msgid "Relation snapshot" msgstr "工单快照" -#: tickets/models/ticket/general.py:392 +#: tickets/models/ticket/general.py:398 msgid "Please try again" msgstr "请再次尝试" -#: tickets/models/ticket/general.py:461 +#: tickets/models/ticket/general.py:467 msgid "Super ticket" msgstr "超级工单" diff --git a/apps/perms/utils/account.py b/apps/perms/utils/account.py index b66b247d8..73534afc8 100644 --- a/apps/perms/utils/account.py +++ b/apps/perms/utils/account.py @@ -1,8 +1,8 @@ from collections import defaultdict -from orgs.utils import tmp_to_org -from accounts.models import Account from accounts.const import AliasAccount +from accounts.models import Account +from orgs.utils import tmp_to_org from .permission import AssetPermissionUtil __all__ = ['PermAccountUtil'] @@ -31,14 +31,14 @@ class PermAccountUtil(AssetPermissionUtil): @staticmethod def get_permed_accounts_from_perms(perms, user, asset): - # alias: is a collection of account usernames and special accounts [@ALL, @INPUT, @USER] + # alias: is a collection of account usernames and special accounts [@ALL, @INPUT, @USER, @ANON] alias_action_bit_mapper = defaultdict(int) - alias_expired_mapper = defaultdict(list) + alias_date_expired_mapper = defaultdict(list) for perm in perms: for alias in perm.accounts: alias_action_bit_mapper[alias] |= perm.actions - alias_expired_mapper[alias].append(perm.date_expired) + alias_date_expired_mapper[alias].append(perm.date_expired) asset_accounts = asset.accounts.all().active() username_account_mapper = {account.username: account for account in asset_accounts} @@ -52,7 +52,7 @@ class PermAccountUtil(AssetPermissionUtil): for account in asset_accounts: cleaned_accounts_action_bit[account] |= all_action_bit cleaned_accounts_expired[account].extend( - alias_expired_mapper[AliasAccount.ALL] + alias_date_expired_mapper[AliasAccount.ALL] ) for alias, action_bit in alias_action_bit_mapper.items(): @@ -63,6 +63,10 @@ class PermAccountUtil(AssetPermissionUtil): account = Account.get_user_account() elif alias == AliasAccount.INPUT: account = Account.get_manual_account() + elif alias == AliasAccount.ANON: + account = Account.get_anonymous_account() + elif alias.startswith('@'): + continue elif alias in username_account_mapper: account = username_account_mapper[alias] else: @@ -70,11 +74,12 @@ class PermAccountUtil(AssetPermissionUtil): if account: cleaned_accounts_action_bit[account] |= action_bit - cleaned_accounts_expired[account].extend(alias_expired_mapper[alias]) + cleaned_accounts_expired[account].extend(alias_date_expired_mapper[alias]) accounts = [] for account, action_bit in cleaned_accounts_action_bit.items(): account.actions = action_bit account.date_expired = max(cleaned_accounts_expired[account]) accounts.append(account) + print("Accounts: ", accounts) return accounts From 17fa139bc92dc1b09e44026cb2e56dc964f155d2 Mon Sep 17 00:00:00 2001 From: Bryan Date: Tue, 27 Jun 2023 14:14:00 +0800 Subject: [PATCH 039/167] feat: Update ----.md --- .github/ISSUE_TEMPLATE/----.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/----.md b/.github/ISSUE_TEMPLATE/----.md index 147f42db4..47b19f79e 100644 --- a/.github/ISSUE_TEMPLATE/----.md +++ b/.github/ISSUE_TEMPLATE/----.md @@ -6,8 +6,7 @@ labels: 类型:需求 assignees: - ibuler - baijiangjie - - + - wojiushixiaobai --- **请描述您的需求或者改进建议.** From a22f36a06a3af7fdfce9871603bd13c6201a68d7 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 27 Jun 2023 14:31:20 +0800 Subject: [PATCH 040/167] =?UTF-8?q?perf:=20=E5=8E=BB=E6=8E=89=20debug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/const/account.py | 2 +- apps/authentication/models/connection_token.py | 3 ++- apps/locale/ja/LC_MESSAGES/django.mo | 4 ++-- apps/locale/ja/LC_MESSAGES/django.po | 2 +- apps/locale/zh/LC_MESSAGES/django.mo | 4 ++-- apps/locale/zh/LC_MESSAGES/django.po | 2 +- apps/perms/utils/account.py | 1 - 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/accounts/const/account.py b/apps/accounts/const/account.py index c57520db7..10a681969 100644 --- a/apps/accounts/const/account.py +++ b/apps/accounts/const/account.py @@ -13,7 +13,7 @@ class AliasAccount(TextChoices): ALL = '@ALL', _('All') INPUT = '@INPUT', _('Manual input') USER = '@USER', _('Dynamic user') - ANON = '@ANON', _('Anonymous user') + ANON = '@ANON', _('Anonymous account') class Source(TextChoices): diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py index 340d275e4..503489b90 100644 --- a/apps/authentication/models/connection_token.py +++ b/apps/authentication/models/connection_token.py @@ -9,6 +9,7 @@ from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from rest_framework.exceptions import PermissionDenied +from accounts.const import AliasAccount from assets.const import Protocol from assets.const.host import GATEWAY_NAME from common.db.fields import EncryptTextField @@ -209,7 +210,7 @@ class ConnectionToken(JMSOrgBaseModel): if not self.asset: return None - if self.account == '@ANON' and self.asset.category not in ['web', 'custom']: + if self.account == AliasAccount.ANON and self.asset.category not in ['web', 'custom']: raise JMSException({'error': 'Anonymous account is not supported in {}'.format(self.asset.category)}) if self.account.startswith('@'): diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index ae0b7facf..809f19e6d 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:36918c53144eaae27cb3b68d47882f6ca9b75669862f28f611fb737f6ca39631 -size 145810 +oid sha256:2e28e9c4ff5d91a24d0c176a134f913de93f4a9bd3e9c8fd7aeacaf875a242d5 +size 145813 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 7a86fc588..979bd2005 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -63,7 +63,7 @@ msgid "Dynamic user" msgstr "動的コード" #: accounts/const/account.py:16 -msgid "Anonymous user" +msgid "Anonymous account" msgstr "匿名ユーザー" #: accounts/const/account.py:20 users/models/user.py:699 diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 47f90fa82..131e221ae 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f4301cf32731559d2e5ce41c2ab00e4655931914d8ce36bde4ad831cc5ee3f9 -size 119305 +oid sha256:092b15ed84725ceb974bd46407e3d247e6ff9d0505b6044f18c122bf6da1b7f6 +size 119308 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 6b10f0926..084f49564 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -62,7 +62,7 @@ msgid "Dynamic user" msgstr "同名账号" #: accounts/const/account.py:16 -msgid "Anonymous user" +msgid "Anonymous account" msgstr "匿名用户" #: accounts/const/account.py:20 users/models/user.py:699 diff --git a/apps/perms/utils/account.py b/apps/perms/utils/account.py index 73534afc8..62c7b68d0 100644 --- a/apps/perms/utils/account.py +++ b/apps/perms/utils/account.py @@ -81,5 +81,4 @@ class PermAccountUtil(AssetPermissionUtil): account.actions = action_bit account.date_expired = max(cleaned_accounts_expired[account]) accounts.append(account) - print("Accounts: ", accounts) return accounts From a64aa89b3f79feb42edef70be349f9d8cb94d7b8 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 27 Jun 2023 10:48:57 +0800 Subject: [PATCH 041/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E8=BF=9C=E7=A8=8B=E5=BA=94=E7=94=A8=E7=9A=84?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/serializers/session.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/terminal/serializers/session.py b/apps/terminal/serializers/session.py index 49a5af69a..dc736a522 100644 --- a/apps/terminal/serializers/session.py +++ b/apps/terminal/serializers/session.py @@ -1,7 +1,6 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers -from assets.const import Protocol from common.serializers.fields import LabeledChoiceField from orgs.mixins.serializers import BulkOrgResourceModelSerializer from .terminal import TerminalSmallSerializer @@ -14,11 +13,9 @@ __all__ = [ ] - - class SessionSerializer(BulkOrgResourceModelSerializer): org_id = serializers.CharField(allow_blank=True) - protocol = serializers.ChoiceField(choices=Protocol.choices, label=_("Protocol")) + protocol = serializers.CharField(max_length=128, label=_("Protocol")) type = LabeledChoiceField( choices=SessionType.choices, label=_("Type"), default=SessionType.normal ) From d3d8fcbbb3c26942f5e8d2864f7c3641ebcb5c86 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 27 Jun 2023 14:41:07 +0800 Subject: [PATCH 042/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E7=BB=8F?= =?UTF-8?q?=E5=B8=B8=E9=81=87=E5=88=B0=E7=9A=84=E7=99=BB=E5=BD=95=E8=B6=85?= =?UTF-8?q?=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/views/login.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/authentication/views/login.py b/apps/authentication/views/login.py index acc8ed51c..8b5696dc9 100644 --- a/apps/authentication/views/login.py +++ b/apps/authentication/views/login.py @@ -11,7 +11,7 @@ from django.conf import settings from django.contrib.auth import BACKEND_SESSION_KEY from django.contrib.auth import login as auth_login, logout as auth_logout from django.db import IntegrityError -from django.http import HttpRequest, HttpResponse +from django.http import HttpRequest from django.shortcuts import reverse, redirect from django.templatetags.static import static from django.urls import reverse_lazy @@ -204,7 +204,9 @@ class UserLoginView(mixins.AuthMixin, UserLoginContextMixin, FormView): def form_valid(self, form): if not self.request.session.test_cookie_worked(): - return HttpResponse(_("Please enable cookies and try again.")) + form.add_error(None, _("Login timeout, please try again.")) + return self.form_invalid(form) + # https://docs.djangoproject.com/en/3.1/topics/http/sessions/#setting-test-cookies self.request.session.delete_test_cookie() From 4737e2cf4aafb2bc40f5302d4dfc1ba1d0a8b8b6 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 27 Jun 2023 15:22:18 +0800 Subject: [PATCH 043/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20=E5=8C=BF?= =?UTF-8?q?=E5=90=8D=E8=B4=A6=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/connection_token.py | 11 ++++++++--- apps/authentication/models/connection_token.py | 14 ++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 23344c9fb..7a0b38872 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -10,10 +10,11 @@ from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from rest_framework import status from rest_framework.decorators import action -from rest_framework.exceptions import PermissionDenied +from rest_framework.exceptions import PermissionDenied, ValidationError from rest_framework.request import Request from rest_framework.response import Response +from accounts.const import AliasAccount from common.api import JMSModelViewSet from common.exceptions import JMSException from common.utils import random_string, get_logger, get_request_ip @@ -282,13 +283,17 @@ class ConnectionTokenViewSet(ExtraActionApiMixin, RootOrgViewMixin, JMSModelView data['org_id'] = asset.org_id data['user'] = user data['value'] = random_string(16) + + if account_name == AliasAccount.ANON and asset.category not in ['web', 'custom']: + raise ValidationError(_('Anonymous account is not supported for this asset')) + account = self._validate_perm(user, asset, account_name) if account.has_secret: data['input_secret'] = '' - if account.username != '@INPUT': + if account.username != AliasAccount.INPUT: data['input_username'] = '' - if account.username == '@USER': + elif account.username == AliasAccount.USER: data['input_username'] = user.username ticket = self._validate_acl(user, asset, account) diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py index 503489b90..3375df145 100644 --- a/apps/authentication/models/connection_token.py +++ b/apps/authentication/models/connection_token.py @@ -210,16 +210,18 @@ class ConnectionToken(JMSOrgBaseModel): if not self.asset: return None - if self.account == AliasAccount.ANON and self.asset.category not in ['web', 'custom']: - raise JMSException({'error': 'Anonymous account is not supported in {}'.format(self.asset.category)}) - if self.account.startswith('@'): account = Account.get_special_account(self.account) + account.asset = self.asset + account.org_id = self.asset.org_id + + if self.account == AliasAccount.INPUT: + account.username = self.input_username + account.secret = self.input_secret else: account = self.asset.accounts.filter(name=self.account).first() - - account.asset = self.asset - account.secret = account.secret or self.input_secret + if not account.secret and self.input_secret: + account.secret = self.input_secret return account @lazyproperty From dfa12239d6cf83677976516e399409d3aadbea46 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 27 Jun 2023 16:00:45 +0800 Subject: [PATCH 044/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/zh/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 084f49564..c0c1ed87a 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -63,7 +63,7 @@ msgstr "同名账号" #: accounts/const/account.py:16 msgid "Anonymous account" -msgstr "匿名用户" +msgstr "匿名账号" #: accounts/const/account.py:20 users/models/user.py:699 msgid "Local" From a67ee976b404997404d3f3512237a0ab9f600071 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 27 Jun 2023 16:03:19 +0800 Subject: [PATCH 045/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.po | 68 +++++++++++++++------------- apps/locale/zh/LC_MESSAGES/django.po | 68 +++++++++++++++------------- 2 files changed, 72 insertions(+), 64 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 979bd2005..7f7ecfb1f 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-27 10:17+0800\n" +"POT-Creation-Date: 2023-06-27 16:02+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -193,7 +193,7 @@ msgstr "作成のみ" #: acls/serializers/base.py:118 assets/models/asset/common.py:93 #: assets/models/asset/common.py:331 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 -#: audits/models.py:53 authentication/models/connection_token.py:35 +#: audits/models.py:53 authentication/models/connection_token.py:36 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 #: terminal/backends/command/models.py:20 terminal/models/session/session.py:31 #: terminal/notifications.py:95 terminal/serializers/command.py:17 @@ -201,7 +201,7 @@ msgstr "作成のみ" msgid "Asset" msgstr "資産" -#: accounts/models/account.py:53 accounts/models/account.py:117 +#: accounts/models/account.py:53 accounts/models/account.py:126 #: accounts/serializers/account/account.py:208 #: accounts/serializers/account/account.py:247 #: accounts/serializers/account/template.py:16 @@ -254,15 +254,15 @@ msgstr "アカウントを確認できます" msgid "Can push account" msgstr "アカウントをプッシュできます" -#: accounts/models/account.py:121 +#: accounts/models/account.py:130 msgid "Account template" msgstr "アカウント テンプレート" -#: accounts/models/account.py:126 +#: accounts/models/account.py:135 msgid "Can view asset account template secret" msgstr "アセット アカウント テンプレートのパスワードを表示できます" -#: accounts/models/account.py:127 +#: accounts/models/account.py:136 msgid "Can change asset account template secret" msgstr "アセット アカウント テンプレートのパスワードを変更できます" @@ -643,7 +643,7 @@ msgstr "ID" #: accounts/serializers/account/account.py:427 acls/serializers/base.py:111 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:49 #: audits/models.py:85 audits/models.py:163 -#: authentication/models/connection_token.py:31 +#: authentication/models/connection_token.py:32 #: authentication/models/sso_token.py:16 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 @@ -812,7 +812,7 @@ msgid "Reviewers" msgstr "レビュー担当者" #: acls/models/base.py:48 authentication/models/access_key.py:17 -#: authentication/models/connection_token.py:52 +#: authentication/models/connection_token.py:53 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/asset_permission.py:76 terminal/models/session/sharing.py:27 #: tickets/const.py:37 @@ -1004,7 +1004,7 @@ msgid "{} disabled" msgstr "{} 無効" #: assets/automations/ping_gateway/manager.py:33 -#: authentication/models/connection_token.py:117 +#: authentication/models/connection_token.py:118 msgid "No account" msgstr "アカウントなし" @@ -1197,7 +1197,7 @@ msgstr "管理ユーザー" msgid "Username same with user" msgstr "ユーザーと同じユーザー名" -#: assets/models/_user.py:52 authentication/models/connection_token.py:40 +#: assets/models/_user.py:52 authentication/models/connection_token.py:41 #: authentication/serializers/connect_token_secret.py:111 #: terminal/models/applet/applet.py:41 terminal/serializers/session.py:21 #: terminal/serializers/session.py:42 terminal/serializers/storage.py:68 @@ -1444,7 +1444,7 @@ msgstr "システム" #: assets/models/label.py:19 assets/models/node.py:557 #: assets/serializers/cagegory.py:7 assets/serializers/cagegory.py:14 -#: authentication/models/connection_token.py:28 +#: authentication/models/connection_token.py:29 #: authentication/serializers/connect_token_secret.py:122 #: common/serializers/common.py:86 settings/models.py:34 msgid "Value" @@ -2133,19 +2133,23 @@ msgstr "外部ストレージへのFTPファイルのアップロード" msgid "This action require verify your MFA" msgstr "この操作には、MFAを検証する必要があります" -#: authentication/api/connection_token.py:305 +#: authentication/api/connection_token.py:288 +msgid "Anonymous account is not supported for this asset" +msgstr "匿名アカウントはこのプロパティではサポートされていません" + +#: authentication/api/connection_token.py:310 msgid "Account not found" msgstr "アカウントが見つかりません" -#: authentication/api/connection_token.py:308 +#: authentication/api/connection_token.py:313 msgid "Permission expired" msgstr "承認の有効期限が切れています" -#: authentication/api/connection_token.py:322 +#: authentication/api/connection_token.py:327 msgid "ACL action is reject: {}({})" msgstr "ACL アクションは拒否です: {}({})" -#: authentication/api/connection_token.py:326 +#: authentication/api/connection_token.py:331 msgid "ACL action is review" msgstr "ACL アクションはレビューです" @@ -2526,78 +2530,78 @@ msgstr "MFAタイプ ({}) が有効になっていない" msgid "Please change your password" msgstr "パスワードを変更してください" -#: authentication/models/connection_token.py:37 +#: authentication/models/connection_token.py:38 #: terminal/serializers/storage.py:111 msgid "Account name" msgstr "アカウント名" -#: authentication/models/connection_token.py:38 +#: authentication/models/connection_token.py:39 msgid "Input username" msgstr "カスタム ユーザー名" -#: authentication/models/connection_token.py:39 +#: authentication/models/connection_token.py:40 #: authentication/serializers/connection_token.py:20 msgid "Input secret" msgstr "カスタムパスワード" -#: authentication/models/connection_token.py:41 +#: authentication/models/connection_token.py:42 msgid "Connect method" msgstr "接続方法" -#: authentication/models/connection_token.py:42 +#: authentication/models/connection_token.py:43 msgid "Connect options" msgstr "接続アイテム" -#: authentication/models/connection_token.py:43 +#: authentication/models/connection_token.py:44 #: rbac/serializers/rolebinding.py:21 msgid "User display" msgstr "ユーザー表示" -#: authentication/models/connection_token.py:44 +#: authentication/models/connection_token.py:45 msgid "Asset display" msgstr "アセット名" -#: authentication/models/connection_token.py:45 +#: authentication/models/connection_token.py:46 msgid "Reusable" msgstr "再利用可能" -#: authentication/models/connection_token.py:46 +#: authentication/models/connection_token.py:47 #: authentication/models/temp_token.py:13 perms/models/asset_permission.py:74 #: tickets/models/ticket/apply_application.py:31 #: tickets/models/ticket/apply_asset.py:20 users/models/user.py:797 msgid "Date expired" msgstr "期限切れの日付" -#: authentication/models/connection_token.py:50 +#: authentication/models/connection_token.py:51 #: perms/models/asset_permission.py:77 msgid "From ticket" msgstr "チケットから" -#: authentication/models/connection_token.py:56 +#: authentication/models/connection_token.py:57 msgid "Connection token" msgstr "接続トークン" -#: authentication/models/connection_token.py:58 +#: authentication/models/connection_token.py:59 msgid "Can view connection token secret" msgstr "接続トークンの秘密を表示できます" -#: authentication/models/connection_token.py:105 +#: authentication/models/connection_token.py:106 msgid "Connection token inactive" msgstr "接続トークンがアクティブ化されていません" -#: authentication/models/connection_token.py:108 +#: authentication/models/connection_token.py:109 msgid "Connection token expired at: {}" msgstr "接続トークンの有効期限: {}" -#: authentication/models/connection_token.py:111 +#: authentication/models/connection_token.py:112 msgid "No user or invalid user" msgstr "ユーザーなしまたは期限切れのユーザー" -#: authentication/models/connection_token.py:114 +#: authentication/models/connection_token.py:115 msgid "No asset or inactive asset" msgstr "アセットがないか、有効化されていないアセット" -#: authentication/models/connection_token.py:267 +#: authentication/models/connection_token.py:258 msgid "Super connection token" msgstr "スーパー接続トークン" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index c0c1ed87a..a2e363cc0 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-27 10:17+0800\n" +"POT-Creation-Date: 2023-06-27 16:02+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -192,7 +192,7 @@ msgstr "仅创建" #: acls/serializers/base.py:118 assets/models/asset/common.py:93 #: assets/models/asset/common.py:331 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 -#: audits/models.py:53 authentication/models/connection_token.py:35 +#: audits/models.py:53 authentication/models/connection_token.py:36 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 #: terminal/backends/command/models.py:20 terminal/models/session/session.py:31 #: terminal/notifications.py:95 terminal/serializers/command.py:17 @@ -200,7 +200,7 @@ msgstr "仅创建" msgid "Asset" msgstr "资产" -#: accounts/models/account.py:53 accounts/models/account.py:117 +#: accounts/models/account.py:53 accounts/models/account.py:126 #: accounts/serializers/account/account.py:208 #: accounts/serializers/account/account.py:247 #: accounts/serializers/account/template.py:16 @@ -253,15 +253,15 @@ msgstr "可以验证账号" msgid "Can push account" msgstr "可以推送账号" -#: accounts/models/account.py:121 +#: accounts/models/account.py:130 msgid "Account template" msgstr "账号模版" -#: accounts/models/account.py:126 +#: accounts/models/account.py:135 msgid "Can view asset account template secret" msgstr "可以查看资产账号模版密码" -#: accounts/models/account.py:127 +#: accounts/models/account.py:136 msgid "Can change asset account template secret" msgstr "可以更改资产账号模版密码" @@ -639,7 +639,7 @@ msgstr "ID" #: accounts/serializers/account/account.py:427 acls/serializers/base.py:111 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:49 #: audits/models.py:85 audits/models.py:163 -#: authentication/models/connection_token.py:31 +#: authentication/models/connection_token.py:32 #: authentication/models/sso_token.py:16 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 @@ -808,7 +808,7 @@ msgid "Reviewers" msgstr "审批人" #: acls/models/base.py:48 authentication/models/access_key.py:17 -#: authentication/models/connection_token.py:52 +#: authentication/models/connection_token.py:53 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/asset_permission.py:76 terminal/models/session/sharing.py:27 #: tickets/const.py:37 @@ -997,7 +997,7 @@ msgid "{} disabled" msgstr "{} 已禁用" #: assets/automations/ping_gateway/manager.py:33 -#: authentication/models/connection_token.py:117 +#: authentication/models/connection_token.py:118 msgid "No account" msgstr "没有账号" @@ -1190,7 +1190,7 @@ msgstr "特权用户" msgid "Username same with user" msgstr "用户名与用户相同" -#: assets/models/_user.py:52 authentication/models/connection_token.py:40 +#: assets/models/_user.py:52 authentication/models/connection_token.py:41 #: authentication/serializers/connect_token_secret.py:111 #: terminal/models/applet/applet.py:41 terminal/serializers/session.py:21 #: terminal/serializers/session.py:42 terminal/serializers/storage.py:68 @@ -1437,7 +1437,7 @@ msgstr "系统" #: assets/models/label.py:19 assets/models/node.py:557 #: assets/serializers/cagegory.py:7 assets/serializers/cagegory.py:14 -#: authentication/models/connection_token.py:28 +#: authentication/models/connection_token.py:29 #: authentication/serializers/connect_token_secret.py:122 #: common/serializers/common.py:86 settings/models.py:34 msgid "Value" @@ -2122,19 +2122,23 @@ msgstr "上传 FTP 文件到外部存储" msgid "This action require verify your MFA" msgstr "该操作需要验证您的 MFA, 请先开启并配置" -#: authentication/api/connection_token.py:305 +#: authentication/api/connection_token.py:288 +msgid "Anonymous account is not supported for this asset" +msgstr "匿名账号不支持当前资产" + +#: authentication/api/connection_token.py:310 msgid "Account not found" msgstr "账号未找到" -#: authentication/api/connection_token.py:308 +#: authentication/api/connection_token.py:313 msgid "Permission expired" msgstr "授权已过期" -#: authentication/api/connection_token.py:322 +#: authentication/api/connection_token.py:327 msgid "ACL action is reject: {}({})" msgstr "ACL 动作是拒绝: {}({})" -#: authentication/api/connection_token.py:326 +#: authentication/api/connection_token.py:331 msgid "ACL action is review" msgstr "ACL 动作是复核" @@ -2501,78 +2505,78 @@ msgstr "该 MFA ({}) 方式没有启用" msgid "Please change your password" msgstr "请修改密码" -#: authentication/models/connection_token.py:37 +#: authentication/models/connection_token.py:38 #: terminal/serializers/storage.py:111 msgid "Account name" msgstr "账号名称" -#: authentication/models/connection_token.py:38 +#: authentication/models/connection_token.py:39 msgid "Input username" msgstr "自定义用户名" -#: authentication/models/connection_token.py:39 +#: authentication/models/connection_token.py:40 #: authentication/serializers/connection_token.py:20 msgid "Input secret" msgstr "自定义密码" -#: authentication/models/connection_token.py:41 +#: authentication/models/connection_token.py:42 msgid "Connect method" msgstr "连接方式" -#: authentication/models/connection_token.py:42 +#: authentication/models/connection_token.py:43 msgid "Connect options" msgstr "连接项" -#: authentication/models/connection_token.py:43 +#: authentication/models/connection_token.py:44 #: rbac/serializers/rolebinding.py:21 msgid "User display" msgstr "用户名称" -#: authentication/models/connection_token.py:44 +#: authentication/models/connection_token.py:45 msgid "Asset display" msgstr "资产名称" -#: authentication/models/connection_token.py:45 +#: authentication/models/connection_token.py:46 msgid "Reusable" msgstr "可以重复使用" -#: authentication/models/connection_token.py:46 +#: authentication/models/connection_token.py:47 #: authentication/models/temp_token.py:13 perms/models/asset_permission.py:74 #: tickets/models/ticket/apply_application.py:31 #: tickets/models/ticket/apply_asset.py:20 users/models/user.py:797 msgid "Date expired" msgstr "失效日期" -#: authentication/models/connection_token.py:50 +#: authentication/models/connection_token.py:51 #: perms/models/asset_permission.py:77 msgid "From ticket" msgstr "来自工单" -#: authentication/models/connection_token.py:56 +#: authentication/models/connection_token.py:57 msgid "Connection token" msgstr "连接令牌" -#: authentication/models/connection_token.py:58 +#: authentication/models/connection_token.py:59 msgid "Can view connection token secret" msgstr "可以查看连接令牌密文" -#: authentication/models/connection_token.py:105 +#: authentication/models/connection_token.py:106 msgid "Connection token inactive" msgstr "连接令牌未激活" -#: authentication/models/connection_token.py:108 +#: authentication/models/connection_token.py:109 msgid "Connection token expired at: {}" msgstr "连接令牌过期: {}" -#: authentication/models/connection_token.py:111 +#: authentication/models/connection_token.py:112 msgid "No user or invalid user" msgstr "没有用户或用户失效" -#: authentication/models/connection_token.py:114 +#: authentication/models/connection_token.py:115 msgid "No asset or inactive asset" msgstr "没有资产或资产未激活" -#: authentication/models/connection_token.py:267 +#: authentication/models/connection_token.py:258 msgid "Super connection token" msgstr "超级连接令牌" From 9ad8e53743edb8b51da8435f742dcaa5f8d0b331 Mon Sep 17 00:00:00 2001 From: "fangfang.dong" Date: Wed, 28 Jun 2023 16:02:31 +0800 Subject: [PATCH 046/167] =?UTF-8?q?perf:=20=E6=8E=A5=E5=8F=A3sql=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20/api/v1/index/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/api.py | 115 ++++++++++------------------------------- 1 file changed, 27 insertions(+), 88 deletions(-) diff --git a/apps/jumpserver/api.py b/apps/jumpserver/api.py index b5ebd9ebc..dae3107ce 100644 --- a/apps/jumpserver/api.py +++ b/apps/jumpserver/api.py @@ -50,6 +50,10 @@ class DateTimeMixin: t = local_now() - timezone.timedelta(days=days) return t + @lazyproperty + def date_start_end(self): + return self.days_to_datetime.date(), local_now().date() + @lazyproperty def dates_list(self): now = local_now() @@ -143,101 +147,36 @@ class DatesLoginMetricMixin: operate_logs_queryset: OperateLog.objects password_change_logs_queryset: PasswordChangeLog.objects - @staticmethod - def get_cache_key(date, tp): - date_str = date.strftime("%Y%m%d") - key = "SESSION_DATE_{}_{}_{}".format(current_org.id, tp, date_str) - return key - - def __get_data_from_cache(self, date, tp): - if date == timezone.now().date(): - return None - cache_key = self.get_cache_key(date, tp) - count = cache.get(cache_key) - return count - - def __set_data_to_cache(self, date, tp, count): - cache_key = self.get_cache_key(date, tp) - cache.set(cache_key, count, 3600) - - @staticmethod - def get_date_start_2_end(d): - time_min = timezone.datetime.min.time() - time_max = timezone.datetime.max.time() - tz = timezone.get_current_timezone() - ds = timezone.datetime.combine(d, time_min).replace(tzinfo=tz) - de = timezone.datetime.combine(d, time_max).replace(tzinfo=tz) - return ds, de - - def get_date_login_count(self, date): - tp = "LOGIN-USER" - count = self.__get_data_from_cache(date, tp) - if count is not None: - return count - ds, de = self.get_date_start_2_end(date) - count = UserLoginLog.objects.filter(datetime__range=(ds, de)).count() - self.__set_data_to_cache(date, tp, count) - return count - def get_dates_metrics_total_count_login(self): - data = [] - for d in self.dates_list: - count = self.get_date_login_count(d) - data.append(count) - if len(data) == 0: - data = [0] - return data - - def get_date_user_count(self, date): - tp = "USER" - count = self.__get_data_from_cache(date, tp) - if count is not None: - return count - ds, de = self.get_date_start_2_end(date) - count = len(set(Session.objects.filter(date_start__range=(ds, de)).values_list('user_id', flat=True))) - self.__set_data_to_cache(date, tp, count) - return count + queryset = UserLoginLog.objects.filter(datetime__range=(self.date_start_end)) \ + .values('datetime__date').annotate(id__count=Count(id)) \ + .order_by('datetime__date') + map_date_logincount = {i['datetime__date']: i['id__count'] for i in queryset} + return [map_date_logincount.get(d, 0) for d in self.dates_list] def get_dates_metrics_total_count_active_users(self): - data = [] - for d in self.dates_list: - count = self.get_date_user_count(d) - data.append(count) - return data - - def get_date_asset_count(self, date): - tp = "ASSET" - count = self.__get_data_from_cache(date, tp) - if count is not None: - return count - ds, de = self.get_date_start_2_end(date) - count = len(set(Session.objects.filter(date_start__range=(ds, de)).values_list('asset', flat=True))) - self.__set_data_to_cache(date, tp, count) - return count + queryset = Session.objects.filter(date_start__range=(self.date_start_end)) \ + .values('date_start__date') \ + .annotate(id__count=Count('user_id', distinct=True)) \ + .order_by('date_start__date') + map_date_usercount = {i['date_start__date']: i['id__count'] for i in queryset} + return [map_date_usercount.get(d, 0) for d in self.dates_list] def get_dates_metrics_total_count_active_assets(self): - data = [] - for d in self.dates_list: - count = self.get_date_asset_count(d) - data.append(count) - return data - - def get_date_session_count(self, date): - tp = "SESSION" - count = self.__get_data_from_cache(date, tp) - if count is not None: - return count - ds, de = self.get_date_start_2_end(date) - count = Session.objects.filter(date_start__range=(ds, de)).count() - self.__set_data_to_cache(date, tp, count) - return count + queryset = Session.objects.filter(date_start__range=(self.date_start_end)) \ + .values('date_start__date') \ + .annotate(id__count=Count('asset_id', distinct=True)) \ + .order_by('date_start__date') + map_date_assetcount = {i['date_start__date']: i['id__count'] for i in queryset} + return [map_date_assetcount.get(d, 0) for d in self.dates_list] def get_dates_metrics_total_count_sessions(self): - data = [] - for d in self.dates_list: - count = self.get_date_session_count(d) - data.append(count) - return data + queryset = Session.objects.filter(date_start__range=(self.date_start_end)) \ + .values('date_start__date') \ + .annotate(id__count=Count(id)) \ + .order_by('date_start__date') + map_date_usercount = {i['date_start__date']: i['id__count'] for i in queryset} + return [map_date_usercount.get(d, 0) for d in self.dates_list] @lazyproperty def get_type_to_assets(self): From ac906a5d5201c2c1c416b7da17d486f130ba0279 Mon Sep 17 00:00:00 2001 From: nut Date: Wed, 28 Jun 2023 16:15:35 +0800 Subject: [PATCH 047/167] Update api.py --- apps/jumpserver/api.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/jumpserver/api.py b/apps/jumpserver/api.py index dae3107ce..5b26a0532 100644 --- a/apps/jumpserver/api.py +++ b/apps/jumpserver/api.py @@ -148,14 +148,16 @@ class DatesLoginMetricMixin: password_change_logs_queryset: PasswordChangeLog.objects def get_dates_metrics_total_count_login(self): - queryset = UserLoginLog.objects.filter(datetime__range=(self.date_start_end)) \ + queryset = UserLoginLog.objects \ + .filter(datetime__range=(self.date_start_end)) \ .values('datetime__date').annotate(id__count=Count(id)) \ .order_by('datetime__date') map_date_logincount = {i['datetime__date']: i['id__count'] for i in queryset} return [map_date_logincount.get(d, 0) for d in self.dates_list] def get_dates_metrics_total_count_active_users(self): - queryset = Session.objects.filter(date_start__range=(self.date_start_end)) \ + queryset = Session.objects \ + .filter(date_start__range=(self.date_start_end)) \ .values('date_start__date') \ .annotate(id__count=Count('user_id', distinct=True)) \ .order_by('date_start__date') @@ -163,7 +165,8 @@ class DatesLoginMetricMixin: return [map_date_usercount.get(d, 0) for d in self.dates_list] def get_dates_metrics_total_count_active_assets(self): - queryset = Session.objects.filter(date_start__range=(self.date_start_end)) \ + queryset = Session.objects \ + .filter(date_start__range=(self.date_start_end)) \ .values('date_start__date') \ .annotate(id__count=Count('asset_id', distinct=True)) \ .order_by('date_start__date') @@ -171,7 +174,8 @@ class DatesLoginMetricMixin: return [map_date_assetcount.get(d, 0) for d in self.dates_list] def get_dates_metrics_total_count_sessions(self): - queryset = Session.objects.filter(date_start__range=(self.date_start_end)) \ + queryset = Session.objects \ + .filter(date_start__range=(self.date_start_end)) \ .values('date_start__date') \ .annotate(id__count=Count(id)) \ .order_by('date_start__date') From 08e0c5fdf57b4c92f175df3d704674676e117c13 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 11:12:23 +0800 Subject: [PATCH 048/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index 5388111d7..628cea3d9 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -23,15 +23,31 @@ jobs: add-label-if-not-author: runs-on: ubuntu-latest - if: (github.event.issue.user.id != github.event.comment.user.id) && !github.event.issue.pull_request && (github.event.issue.state == 'open') steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Get Repository Collaborators + id: collaborators + uses: octokit/request-action@v2.x + with: + route: GET /repos/{owner}/{repo}/collaborators + owner: ${{ github.repository_owner }} + repo: ${{ github.repository }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - run: "echo Collaborators: '${{ steps.collaborators.outputs.data }}'" + - name: Add require replay label + if: contains(steps.collaborators.outputs.data, github.event.comment.user.id) uses: actions-cool/issues-helper@v2 with: actions: 'add-labels' labels: '状态:待反馈' - name: Remove require handle label + if: contains(steps.collaborators.outputs.data, github.event.comment.user.id) uses: actions-cool/issues-helper@v2 with: actions: 'remove-labels' From d293a03649658736a274dec454898f4c6a6fbef9 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 11:28:56 +0800 Subject: [PATCH 049/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index 628cea3d9..2cf5884c2 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -21,7 +21,7 @@ jobs: actions: 'remove-labels' labels: '状态:待反馈' - add-label-if-not-author: + add-label-if-is-rd-members: runs-on: ubuntu-latest steps: - name: Checkout repository @@ -34,8 +34,8 @@ jobs: route: GET /repos/{owner}/{repo}/collaborators owner: ${{ github.repository_owner }} repo: ${{ github.repository }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: "echo Collaborators: '${{ steps.collaborators.outputs.data }}'" From 877a053717e0e5b68f1945fcb21156c1c5b04af3 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 11:38:11 +0800 Subject: [PATCH 050/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index 2cf5884c2..1c50ff452 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -27,20 +27,19 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - - name: Get Repository Collaborators - id: collaborators + - name: Get Project Developers uses: octokit/request-action@v2.x + id: developers with: - route: GET /repos/{owner}/{repo}/collaborators - owner: ${{ github.repository_owner }} - repo: ${{ github.repository }} + route: GET /repos/${{ github.repository }}/collaborators env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - run: "echo Collaborators: '${{ steps.collaborators.outputs.data }}'" + + - run: "echo Collaborators: '${{ steps.developers.outputs.data }}'" - name: Add require replay label - if: contains(steps.collaborators.outputs.data, github.event.comment.user.id) + if: contains(steps.developers.outputs.data, github.event.comment.user.id) uses: actions-cool/issues-helper@v2 with: actions: 'add-labels' From fbcb0da349db61d72ac1243c68d1f4691a3796c5 Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Thu, 29 Jun 2023 11:37:34 +0800 Subject: [PATCH 051/167] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81sqlserver=20?= =?UTF-8?q?=E9=80=9A=E8=BF=87chen=20=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/connect_methods.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index b5ba6360d..a4901b93c 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -39,7 +39,7 @@ class WebMethod(TextChoices): if not settings.XPACK_ENABLED: return methods - web_gui_dbs = [Protocol.mysql, Protocol.mariadb, Protocol.oracle, Protocol.postgresql] + web_gui_dbs = [Protocol.mysql, Protocol.mariadb, Protocol.oracle, Protocol.postgresql, Protocol.sqlserver] for db in web_gui_dbs: methods[db].append(cls.web_gui) return methods @@ -188,7 +188,7 @@ class ConnectMethodUtil: 'listen': [Protocol.http], 'support': [ Protocol.mysql, Protocol.postgresql, - Protocol.oracle + Protocol.oracle, Protocol.sqlserver, ], 'match': 'm2m' }, From 57fccc9bafa786bc0b56a31734aa8ca194089a7a Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 14:17:27 +0800 Subject: [PATCH 052/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index 1c50ff452..b46ee0b53 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -21,7 +21,7 @@ jobs: actions: 'remove-labels' labels: '状态:待反馈' - add-label-if-is-rd-members: + add-label-if-is-developers: runs-on: ubuntu-latest steps: - name: Checkout repository @@ -35,18 +35,25 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Process developers data + # 将 developers 中的数据转化为 login 字段的列表并输出 + id: developer_names + run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq -r '.[] | .login')" - - run: "echo Collaborators: '${{ steps.developers.outputs.data }}'" + - run: "echo developers: '${{ steps.developer.outputs.data }}' '${{github.event.comment.user.id}}'" + - run: "echo developer names: '${{ steps.developer_names.outputs.data }}'" + - run: "echo comment user: '${{ github.event.comment.user.id }}'" + - run: "echo contains? : '${{ contains(steps.developer_names.outputs.data, github.event.comment.user.id) }}'" - name: Add require replay label - if: contains(steps.developers.outputs.data, github.event.comment.user.id) + if: contains(steps.developer_names.outputs.data, github.event.comment.user.id) uses: actions-cool/issues-helper@v2 with: actions: 'add-labels' labels: '状态:待反馈' - name: Remove require handle label - if: contains(steps.collaborators.outputs.data, github.event.comment.user.id) + if: contains(steps.developer_names.outputs.data, github.event.comment.user.id) uses: actions-cool/issues-helper@v2 with: actions: 'remove-labels' From e3cf6cc4761a7b471f5cccd20367c3372edd4e74 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 14:27:13 +0800 Subject: [PATCH 053/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index b46ee0b53..daba13979 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -40,20 +40,20 @@ jobs: id: developer_names run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq -r '.[] | .login')" - - run: "echo developers: '${{ steps.developer.outputs.data }}' '${{github.event.comment.user.id}}'" + - run: "echo developers: '${{ steps.developers.outputs.data }}'" - run: "echo developer names: '${{ steps.developer_names.outputs.data }}'" - - run: "echo comment user: '${{ github.event.comment.user.id }}'" - - run: "echo contains? : '${{ contains(steps.developer_names.outputs.data, github.event.comment.user.id) }}'" + - run: "echo comment user: '${{ github.event.comment.user.login }}'" + - run: "echo contains? : '${{ contains(steps.developer_names.outputs.data, github.event.comment.user.login) }}'" - name: Add require replay label - if: contains(steps.developer_names.outputs.data, github.event.comment.user.id) + if: contains(steps.developer_names.outputs.data, github.event.comment.user.login) uses: actions-cool/issues-helper@v2 with: actions: 'add-labels' labels: '状态:待反馈' - name: Remove require handle label - if: contains(steps.developer_names.outputs.data, github.event.comment.user.id) + if: contains(steps.developer_names.outputs.data, github.event.comment.user.login) uses: actions-cool/issues-helper@v2 with: actions: 'remove-labels' From cea56a2f7e0bc127076d15736b9c1a35b943371f Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 14:37:15 +0800 Subject: [PATCH 054/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index daba13979..ea939c22e 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -38,7 +38,7 @@ jobs: - name: Process developers data # 将 developers 中的数据转化为 login 字段的列表并输出 id: developer_names - run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq -r '.[] | .login')" + run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq -r '.[].login')" - run: "echo developers: '${{ steps.developers.outputs.data }}'" - run: "echo developer names: '${{ steps.developer_names.outputs.data }}'" From 0020fe7be06a4ddeabb975afb91d511c3161fe3f Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 15:17:24 +0800 Subject: [PATCH 055/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index ea939c22e..528e3f4a2 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -38,7 +38,7 @@ jobs: - name: Process developers data # 将 developers 中的数据转化为 login 字段的列表并输出 id: developer_names - run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq -r '.[].login')" + run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq '{login}' | jq 'keys'" - run: "echo developers: '${{ steps.developers.outputs.data }}'" - run: "echo developer names: '${{ steps.developer_names.outputs.data }}'" From f3955a47f6eec895417c132280be8abaf618c89f Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 15:23:59 +0800 Subject: [PATCH 056/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index 528e3f4a2..c4d7e359e 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -38,7 +38,7 @@ jobs: - name: Process developers data # 将 developers 中的数据转化为 login 字段的列表并输出 id: developer_names - run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq '{login}' | jq 'keys'" + run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq '{login}' | jq 'keys')" - run: "echo developers: '${{ steps.developers.outputs.data }}'" - run: "echo developer names: '${{ steps.developer_names.outputs.data }}'" From fc8d226005017a30442d7e693061321d156c63a4 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 15:41:18 +0800 Subject: [PATCH 057/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index c4d7e359e..9475abdd5 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -38,7 +38,7 @@ jobs: - name: Process developers data # 将 developers 中的数据转化为 login 字段的列表并输出 id: developer_names - run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq '{login}' | jq 'keys')" + run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq '[.[].login]')" - run: "echo developers: '${{ steps.developers.outputs.data }}'" - run: "echo developer names: '${{ steps.developer_names.outputs.data }}'" From 9c1a6b8565bd22f1d2a91f305c3cd06dc82a35e1 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 16:05:59 +0800 Subject: [PATCH 058/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index 9475abdd5..d0bc8ba84 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -38,7 +38,7 @@ jobs: - name: Process developers data # 将 developers 中的数据转化为 login 字段的列表并输出 id: developer_names - run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq '[.[].login]')" + run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq '[.[].login] | join(",")')" - run: "echo developers: '${{ steps.developers.outputs.data }}'" - run: "echo developer names: '${{ steps.developer_names.outputs.data }}'" From 0b92e43e204bd46a7a4876095415e8f889ea535a Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 16:30:39 +0800 Subject: [PATCH 059/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index d0bc8ba84..beb879fd8 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -31,7 +31,7 @@ jobs: uses: octokit/request-action@v2.x id: developers with: - route: GET /repos/${{ github.repository }}/collaborators + route: GET /repos/${${{ github.repository }}%%/*}/collaborators env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From adcabf69ed053dfefe4949723504bcdfd9cff176 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 16:41:50 +0800 Subject: [PATCH 060/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index beb879fd8..d0b55e317 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -27,11 +27,15 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 + - name: Get Organization name + id: org_name + run: echo "::set-output name=data::$(echo '${{ github.repository }}' | cut -d '/' -f 1)" + - name: Get Project Developers uses: octokit/request-action@v2.x id: developers with: - route: GET /repos/${${{ github.repository }}%%/*}/collaborators + route: GET /orgs/${{ steps.org_name.outputs.data }}/members env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 1ed6c7e01d1ac3f480342a178e07f688efb0a0fe Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 16:53:06 +0800 Subject: [PATCH 061/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index d0b55e317..cbe066221 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -35,12 +35,12 @@ jobs: uses: octokit/request-action@v2.x id: developers with: - route: GET /orgs/${{ steps.org_name.outputs.data }}/members + route: GET /orgs/${{ steps.org_name.outputs.data }}/public_members env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Process developers data - # 将 developers 中的数据转化为 login 字段的列表并输出 + # 将 developers 中的数据转化为 login 字段的拼接字符串 id: developer_names run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq '[.[].login] | join(",")')" From ac0a673818761ab8327a52219de911d27288dd06 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 16:59:45 +0800 Subject: [PATCH 062/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index cbe066221..297143699 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -21,7 +21,7 @@ jobs: actions: 'remove-labels' labels: '状态:待反馈' - add-label-if-is-developers: + add-label-if-is-member: runs-on: ubuntu-latest steps: - name: Checkout repository @@ -31,33 +31,33 @@ jobs: id: org_name run: echo "::set-output name=data::$(echo '${{ github.repository }}' | cut -d '/' -f 1)" - - name: Get Project Developers + - name: Get Organization public members uses: octokit/request-action@v2.x - id: developers + id: members with: route: GET /orgs/${{ steps.org_name.outputs.data }}/public_members env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Process developers data - # 将 developers 中的数据转化为 login 字段的拼接字符串 - id: developer_names - run: echo "::set-output name=data::$(echo '${{ steps.developers.outputs.data }}' | jq '[.[].login] | join(",")')" + - name: Process public members data + # 将 members 中的数据转化为 login 字段的拼接字符串 + id: member_names + run: echo "::set-output name=data::$(echo '${{ steps.members.outputs.data }}' | jq '[.[].login] | join(",")')" - - run: "echo developers: '${{ steps.developers.outputs.data }}'" - - run: "echo developer names: '${{ steps.developer_names.outputs.data }}'" + - run: "echo members: '${{ steps.members.outputs.data }}'" + - run: "echo member names: '${{ steps.member_names.outputs.data }}'" - run: "echo comment user: '${{ github.event.comment.user.login }}'" - - run: "echo contains? : '${{ contains(steps.developer_names.outputs.data, github.event.comment.user.login) }}'" + - run: "echo contains? : '${{ contains(steps.member_names.outputs.data, github.event.comment.user.login) }}'" - name: Add require replay label - if: contains(steps.developer_names.outputs.data, github.event.comment.user.login) + if: contains(steps.member_names.outputs.data, github.event.comment.user.login) uses: actions-cool/issues-helper@v2 with: actions: 'add-labels' labels: '状态:待反馈' - name: Remove require handle label - if: contains(steps.developer_names.outputs.data, github.event.comment.user.login) + if: contains(steps.member_names.outputs.data, github.event.comment.user.login) uses: actions-cool/issues-helper@v2 with: actions: 'remove-labels' From 3c707996e066bf2b186a7f7a8b283313993ff823 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 17:04:41 +0800 Subject: [PATCH 063/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(10)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index 297143699..ec741a8c1 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -29,7 +29,7 @@ jobs: - name: Get Organization name id: org_name - run: echo "::set-output name=data::$(echo '${{ github.repository }}' | cut -d '/' -f 1)" + run: echo "{data}=$(echo '${{ github.repository }}' | cut -d '/' -f 1)" >> $GITHUB_OUTPUT - name: Get Organization public members uses: octokit/request-action@v2.x @@ -42,7 +42,8 @@ jobs: - name: Process public members data # 将 members 中的数据转化为 login 字段的拼接字符串 id: member_names - run: echo "::set-output name=data::$(echo '${{ steps.members.outputs.data }}' | jq '[.[].login] | join(",")')" + run: echo "{data}=$(echo '${{ steps.members.outputs.data }}' | jq '[.[].login] | join(",")')" >> $GITHUB_OUTPUT + - run: "echo members: '${{ steps.members.outputs.data }}'" - run: "echo member names: '${{ steps.member_names.outputs.data }}'" From d0bf5b46f63a63f0be8818977a186f10a216bdcc Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 29 Jun 2023 17:11:29 +0800 Subject: [PATCH 064/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(11)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/issue-comment.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index ec741a8c1..bcda24e2b 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -29,7 +29,7 @@ jobs: - name: Get Organization name id: org_name - run: echo "{data}=$(echo '${{ github.repository }}' | cut -d '/' -f 1)" >> $GITHUB_OUTPUT + run: echo "{data}=$(echo '${{ github.repository }}' | cut -d '/' -f 1)" >> "$GITHUB_OUTPUT" - name: Get Organization public members uses: octokit/request-action@v2.x @@ -42,7 +42,7 @@ jobs: - name: Process public members data # 将 members 中的数据转化为 login 字段的拼接字符串 id: member_names - run: echo "{data}=$(echo '${{ steps.members.outputs.data }}' | jq '[.[].login] | join(",")')" >> $GITHUB_OUTPUT + run: echo "{data}=$(echo '${{ steps.members.outputs.data }}' | jq '[.[].login] | join(",")')" >> "$GITHUB_OUTPUT" - run: "echo members: '${{ steps.members.outputs.data }}'" From f4bd06b970aa77e32502f19f7f60b30d7d60eaaf Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 29 Jun 2023 17:15:19 +0800 Subject: [PATCH 065/167] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Issue=20Gi?= =?UTF-8?q?tHub=20Actions=EF=BC=8C=E5=BD=93=E7=A0=94=E5=8F=91=E5=9B=A2?= =?UTF-8?q?=E9=98=9F=E6=88=90=E5=91=98=E8=AF=84=E8=AE=BA=E5=90=8E=E5=86=8D?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=20=E5=BE=85=E5=A4=84=E7=90=86=20=E6=A0=87?= =?UTF-8?q?=E7=AD=BE(12)=20(#10870)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bai Co-authored-by: Bryan --- .github/workflows/issue-comment.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index bcda24e2b..980d701cb 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -29,7 +29,7 @@ jobs: - name: Get Organization name id: org_name - run: echo "{data}=$(echo '${{ github.repository }}' | cut -d '/' -f 1)" >> "$GITHUB_OUTPUT" + run: echo "data=$(echo '${{ github.repository }}' | cut -d '/' -f 1)" >> $GITHUB_OUTPUT - name: Get Organization public members uses: octokit/request-action@v2.x @@ -42,7 +42,7 @@ jobs: - name: Process public members data # 将 members 中的数据转化为 login 字段的拼接字符串 id: member_names - run: echo "{data}=$(echo '${{ steps.members.outputs.data }}' | jq '[.[].login] | join(",")')" >> "$GITHUB_OUTPUT" + run: echo "data=$(echo '${{ steps.members.outputs.data }}' | jq '[.[].login] | join(",")')" >> $GITHUB_OUTPUT - run: "echo members: '${{ steps.members.outputs.data }}'" From ca1b82330e3006ec5635a5a5f73317c142091979 Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 30 Jun 2023 11:12:23 +0800 Subject: [PATCH 066/167] =?UTF-8?q?perf:=20=E8=B4=A6=E5=8F=B7=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=94=AF=E6=8C=81=E9=80=9A=E8=BF=87=20secret=5Ftype?= =?UTF-8?q?=20=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/filters.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/accounts/filters.py b/apps/accounts/filters.py index 67e243e1c..be2cf1dfd 100644 --- a/apps/accounts/filters.py +++ b/apps/accounts/filters.py @@ -45,7 +45,7 @@ class AccountFilterSet(BaseFilterSet): class Meta: model = Account - fields = ['id', 'asset_id', 'source_id'] + fields = ['id', 'asset_id', 'source_id', 'secret_type'] class GatheredAccountFilterSet(BaseFilterSet): From bbbd011cc21422cb0fdcda937e068a2ee8bd9c9f Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 30 Jun 2023 15:54:06 +0800 Subject: [PATCH 067/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20protocol?= =?UTF-8?q?=20setting=20(#10875)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 新增账号配置 * perf: 修改 platform protocol define * perf: 修改 account config * perf: 修改协议设置 --------- Co-authored-by: ibuler --- apps/accounts/models/__init__.py | 2 +- apps/accounts/serializers/account/base.py | 5 +- apps/assets/api/platform.py | 19 +- apps/assets/const/base.py | 10 +- apps/assets/const/protocol.py | 73 +++- apps/assets/const/web.py | 7 - apps/assets/models/asset/web.py | 2 +- apps/assets/serializers/asset/info/spec.py | 3 +- apps/assets/serializers/platform.py | 88 ++--- apps/assets/urls/api_urls.py | 4 +- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 378 ++++++++++++--------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 371 +++++++++++--------- 14 files changed, 570 insertions(+), 400 deletions(-) diff --git a/apps/accounts/models/__init__.py b/apps/accounts/models/__init__.py index c40ee786d..df686a50b 100644 --- a/apps/accounts/models/__init__.py +++ b/apps/accounts/models/__init__.py @@ -1,3 +1,3 @@ -from .base import * from .account import * from .automations import * +from .base import * diff --git a/apps/accounts/serializers/account/base.py b/apps/accounts/serializers/account/base.py index b79dd51be..2f9660bd5 100644 --- a/apps/accounts/serializers/account/base.py +++ b/apps/accounts/serializers/account/base.py @@ -78,5 +78,8 @@ class BaseAccountSerializer(AuthValidateMixin, BulkOrgResourceModelSerializer): ] extra_kwargs = { 'spec_info': {'label': _('Spec info')}, - 'username': {'help_text': _("Tip: If no username is required for authentication, fill in `null`")} + 'username': {'help_text': _( + "Tip: If no username is required for authentication, fill in `null`, " + "If AD account, like `username@domain`" + )}, } diff --git a/apps/assets/api/platform.py b/apps/assets/api/platform.py index fc32a3b5f..a6e34b38b 100644 --- a/apps/assets/api/platform.py +++ b/apps/assets/api/platform.py @@ -4,20 +4,20 @@ from rest_framework.decorators import action from rest_framework.response import Response from assets.const import AllTypes -from assets.models import Platform, Node, Asset -from assets.serializers import PlatformSerializer +from assets.models import Platform, Node, Asset, PlatformProtocol +from assets.serializers import PlatformSerializer, PlatformProtocolSerializer from common.api import JMSModelViewSet from common.permissions import IsValidUser from common.serializers import GroupedChoiceSerializer -__all__ = ['AssetPlatformViewSet', 'PlatformAutomationMethodsApi'] +__all__ = ['AssetPlatformViewSet', 'PlatformAutomationMethodsApi', 'PlatformProtocolViewSet'] class AssetPlatformViewSet(JMSModelViewSet): queryset = Platform.objects.all() serializer_classes = { 'default': PlatformSerializer, - 'categories': GroupedChoiceSerializer + 'categories': GroupedChoiceSerializer, } filterset_fields = ['name', 'category', 'type'] search_fields = ['name'] @@ -25,7 +25,7 @@ class AssetPlatformViewSet(JMSModelViewSet): 'categories': 'assets.view_platform', 'type_constraints': 'assets.view_platform', 'ops_methods': 'assets.view_platform', - 'filter_nodes_assets': 'assets.view_platform' + 'filter_nodes_assets': 'assets.view_platform', } def get_queryset(self): @@ -61,6 +61,15 @@ class AssetPlatformViewSet(JMSModelViewSet): return Response(serializer.data) +class PlatformProtocolViewSet(JMSModelViewSet): + queryset = PlatformProtocol.objects.all() + serializer_class = PlatformProtocolSerializer + filterset_fields = ['name', 'platform__name'] + rbac_perms = { + '*': 'assets.add_platform' + } + + class PlatformAutomationMethodsApi(generics.ListAPIView): permission_classes = (IsValidUser,) diff --git a/apps/assets/const/base.py b/apps/assets/const/base.py index 99ff06314..5aea334d4 100644 --- a/apps/assets/const/base.py +++ b/apps/assets/const/base.py @@ -1,7 +1,8 @@ +from django.db import models from django.db.models import TextChoices +from django.utils.translation import gettext_lazy as _ from jumpserver.utils import has_valid_xpack_license -from .protocol import Protocol class Type: @@ -28,6 +29,12 @@ class Type: ) +class FillType(models.TextChoices): + no = 'no', _('Disabled') + basic = 'basic', _('Basic') + script = 'script', _('Script') + + class BaseType(TextChoices): """ 约束应该考虑代是对平台对限制,避免多余对选项,如: mysql 开启 ssh, @@ -57,6 +64,7 @@ class BaseType(TextChoices): @classmethod def _parse_protocols(cls, protocol, tp): + from .protocol import Protocol settings = Protocol.settings() choices = protocol.get('choices', []) if choices == '__self__': diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index a0b7b7ec7..e66dde209 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -1,6 +1,8 @@ from django.db import models +from django.utils.translation import gettext_lazy as _ from common.db.models import ChoicesMixin +from .base import FillType __all__ = ['Protocol'] @@ -22,8 +24,7 @@ class Protocol(ChoicesMixin, models.TextChoices): mongodb = 'mongodb', 'MongoDB' k8s = 'k8s', 'K8S' - http = 'http', 'HTTP' - _settings = None + http = 'http', 'HTTP(s)' @classmethod def device_protocols(cls): @@ -32,16 +33,40 @@ class Protocol(ChoicesMixin, models.TextChoices): 'port': 22, 'secret_types': ['password', 'ssh_key'], 'setting': { - 'sftp_enabled': True, - 'sftp_home': '/tmp', + 'sftp_enabled': { + 'type': 'bool', + 'default': True, + 'label': _('SFTP enabled') + }, + 'sftp_home': { + 'type': 'str', + 'default': '/tmp', + 'label': _('SFTP home') + }, } }, cls.rdp: { 'port': 3389, 'secret_types': ['password'], 'setting': { - 'console': False, - 'security': 'any', + 'console': { + 'type': 'bool', + 'default': False, + 'label': _('Console'), + 'help_text': _("Connect to console session") + }, + 'security': { + 'type': 'choice', + 'choices': [('any', _('Any')), ('rdp', 'RDP'), ('tls', 'TLS'), ('nla', 'NLA')], + 'default': 'any', + 'label': _('Security'), + 'help_text': _("Security layer to use for the connection") + }, + # 'ad_domain': { + # 'type': 'str', + # "required": False, + # 'label': _('AD domain') + # } } }, cls.vnc: { @@ -56,7 +81,11 @@ class Protocol(ChoicesMixin, models.TextChoices): 'port': 5985, 'secret_types': ['password'], 'setting': { - 'use_ssl': False, + 'use_ssl': { + 'type': 'bool', + 'default': False, + 'label': _('Use SSL') + }, } }, } @@ -105,7 +134,11 @@ class Protocol(ChoicesMixin, models.TextChoices): 'required': True, 'secret_types': ['password'], 'setting': { - 'auth_username': True, + 'auth_username': { + 'type': 'bool', + 'default': False, + 'label': _('Auth username') + }, } }, } @@ -121,10 +154,28 @@ class Protocol(ChoicesMixin, models.TextChoices): cls.http: { 'port': 80, 'secret_types': ['password'], + 'label': 'HTTP(s)', 'setting': { - 'username_selector': 'name=username', - 'password_selector': 'name=password', - 'submit_selector': 'id=login_button', + 'autofill': { + 'type': 'choice', + 'choices': FillType.choices, + 'default': 'basic', + }, + 'username_selector': { + 'type': 'str', + 'default': 'name=username', + 'label': _('Username selector') + }, + 'password_selector': { + 'type': 'str', + 'default': 'name=password', + 'label': _('Password selector') + }, + 'submit_selector': { + 'type': 'str', + 'default': 'type=submit', + 'label': _('Submit selector') + } } }, } diff --git a/apps/assets/const/web.py b/apps/assets/const/web.py index bf9d9e3c8..42ea995ac 100644 --- a/apps/assets/const/web.py +++ b/apps/assets/const/web.py @@ -1,4 +1,3 @@ -from django.db import models from django.utils.translation import gettext_lazy as _ from .base import BaseType @@ -53,9 +52,3 @@ class WebTypes(BaseType): return [ cls.WEBSITE, ] - - -class FillType(models.TextChoices): - no = 'no', _('Disabled') - basic = 'basic', _('Basic') - script = 'script', _('Script') diff --git a/apps/assets/models/asset/web.py b/apps/assets/models/asset/web.py index a12965334..d46ce00c4 100644 --- a/apps/assets/models/asset/web.py +++ b/apps/assets/models/asset/web.py @@ -1,7 +1,7 @@ from django.db import models from django.utils.translation import gettext_lazy as _ -from assets.const.web import FillType +from assets.const import FillType from .common import Asset diff --git a/apps/assets/serializers/asset/info/spec.py b/apps/assets/serializers/asset/info/spec.py index 72be7edec..9a3dab960 100644 --- a/apps/assets/serializers/asset/info/spec.py +++ b/apps/assets/serializers/asset/info/spec.py @@ -1,7 +1,7 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import serializers -from assets.const.web import FillType +from assets.const import FillType from assets.models import Database, Web from common.serializers.fields import LabeledChoiceField @@ -14,6 +14,7 @@ class DatabaseSpecSerializer(serializers.ModelSerializer): class WebSpecSerializer(serializers.ModelSerializer): autofill = LabeledChoiceField(choices=FillType.choices, label=_('Autofill')) + class Meta: model = Web fields = [ diff --git a/apps/assets/serializers/platform.py b/apps/assets/serializers/platform.py index b78e134f4..1915adcdb 100644 --- a/apps/assets/serializers/platform.py +++ b/apps/assets/serializers/platform.py @@ -1,48 +1,17 @@ +from django.db.models import QuerySet from django.utils.translation import gettext_lazy as _ from rest_framework import serializers -from assets.const.web import FillType -from common.serializers import WritableNestedModelSerializer, type_field_map +from common.serializers import ( + WritableNestedModelSerializer, type_field_map, MethodSerializer, + DictSerializer, create_serializer_class +) from common.serializers.fields import LabeledChoiceField from common.utils import lazyproperty -from ..const import Category, AllTypes +from ..const import Category, AllTypes, Protocol from ..models import Platform, PlatformProtocol, PlatformAutomation -__all__ = ["PlatformSerializer", "PlatformOpsMethodSerializer"] - - -class ProtocolSettingSerializer(serializers.Serializer): - SECURITY_CHOICES = [ - ("any", "Any"), - ("rdp", "RDP"), - ("tls", "TLS"), - ("nla", "NLA"), - ] - # RDP - console = serializers.BooleanField(required=False, default=False) - security = serializers.ChoiceField(choices=SECURITY_CHOICES, default="any") - - # SFTP - sftp_enabled = serializers.BooleanField(default=True, label=_("SFTP enabled")) - sftp_home = serializers.CharField(default="/tmp", label=_("SFTP home")) - - # HTTP - autofill = serializers.ChoiceField(default='basic', choices=FillType.choices, label=_("Autofill")) - username_selector = serializers.CharField( - default="", allow_blank=True, label=_("Username selector") - ) - password_selector = serializers.CharField( - default="", allow_blank=True, label=_("Password selector") - ) - submit_selector = serializers.CharField( - default="", allow_blank=True, label=_("Submit selector") - ) - script = serializers.JSONField(default=list, label=_("Script")) - # Redis - auth_username = serializers.BooleanField(default=False, label=_("Auth with username")) - - # WinRM - use_ssl = serializers.BooleanField(default=False, label=_("Use SSL")) +__all__ = ["PlatformSerializer", "PlatformOpsMethodSerializer", "PlatformProtocolSerializer"] class PlatformAutomationSerializer(serializers.ModelSerializer): @@ -76,7 +45,7 @@ class PlatformAutomationSerializer(serializers.ModelSerializer): class PlatformProtocolSerializer(serializers.ModelSerializer): - setting = ProtocolSettingSerializer(required=False, allow_null=True) + setting = MethodSerializer(required=False, label=_("Setting")) class Meta: model = PlatformProtocol @@ -85,6 +54,47 @@ class PlatformProtocolSerializer(serializers.ModelSerializer): "required", "default", "public", "secret_types", "setting", ] + extra_kwargs = { + "primary": { + "help_text": _( + "This protocol is primary, and it must be set when adding assets. " + "Additionally, there can only be one primary protocol." + ) + }, + "required": { + "help_text": _("This protocol is required, and it must be set when adding assets.") + }, + "default": { + "help_text": _("This protocol is default, when adding assets, it will be displayed by default.") + }, + "public": { + "help_text": _("This protocol is public, asset will show this protocol to user") + }, + } + + def get_setting_serializer(self): + request = self.context.get('request') + default_field = DictSerializer() + + if not request: + return default_field + + if self.instance and isinstance(self.instance, (QuerySet, list)): + instance = self.instance[0] + else: + instance = self.instance + + protocol = request.query_params.get('name', '') + if instance and not protocol: + protocol = instance.name + + protocol_settings = Protocol.settings() + setting_fields = protocol_settings.get(protocol, {}).get('setting') + if not setting_fields: + return default_field + setting_fields = [{'name': k, **v} for k, v in setting_fields.items()] + name = '{}ProtocolSettingSerializer'.format(protocol.capitalize()) + return create_serializer_class(name, setting_fields)() def to_file_representation(self, data): return '{name}/{port}'.format(**data) diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py index 6b5f469d0..1a1384fdf 100644 --- a/apps/assets/urls/api_urls.py +++ b/apps/assets/urls/api_urls.py @@ -21,6 +21,7 @@ router.register(r'nodes', api.NodeViewSet, 'node') router.register(r'domains', api.DomainViewSet, 'domain') router.register(r'gateways', api.GatewayViewSet, 'gateway') router.register(r'favorite-assets', api.FavoriteAssetViewSet, 'favorite-asset') +router.register(r'protocol-settings', api.PlatformProtocolViewSet, 'protocol-setting') urlpatterns = [ # path('assets//gateways/', api.AssetGatewayListApi.as_view(), name='asset-gateway-list'), @@ -46,7 +47,8 @@ urlpatterns = [ path('nodes//tasks/', api.NodeTaskCreateApi.as_view(), name='node-task-create'), path('gateways//test-connective/', api.GatewayTestConnectionApi.as_view(), name='test-gateway-connective'), - path('platform-automation-methods/', api.PlatformAutomationMethodsApi.as_view(), name='platform-automation-methods'), + path('platform-automation-methods/', api.PlatformAutomationMethodsApi.as_view(), + name='platform-automation-methods'), ] urlpatterns += router.urls diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index f057cb635..3a7c3347a 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cd4fb6a0396c8636f8a36645354a5102790c020d73cdeb1f0e1d1f1b34ea39e9 -size 145760 +oid sha256:b0588a31da5eccf0c1408abb00126f3f5cff58c26c5995c1daf3d2d071d06abe +size 146993 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index dbfc085e6..ff25a1171 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-15 15:35+0800\n" +"POT-Creation-Date: 2023-06-30 15:41+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -87,7 +87,7 @@ msgstr "更新" #: accounts/const/account.py:27 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:61 xpack/plugins/cloud/const.py:41 +#: ops/const.py:58 terminal/const.py:62 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失敗しました" @@ -187,11 +187,11 @@ msgstr "作成のみ" #: accounts/serializers/automations/change_secret.py:112 #: accounts/serializers/automations/change_secret.py:132 #: acls/serializers/base.py:118 assets/models/asset/common.py:93 -#: assets/models/asset/common.py:332 assets/models/cmd_filter.py:36 +#: assets/models/asset/common.py:331 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:53 authentication/models/connection_token.py:35 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 -#: terminal/backends/command/models.py:20 terminal/models/session/session.py:32 +#: terminal/backends/command/models.py:20 terminal/models/session/session.py:31 #: terminal/notifications.py:95 terminal/serializers/command.py:17 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" @@ -225,7 +225,7 @@ msgstr "ソース ID" #: acls/serializers/base.py:119 assets/serializers/asset/common.py:125 #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 -#: terminal/backends/command/models.py:21 terminal/models/session/session.py:34 +#: terminal/backends/command/models.py:21 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "アカウント" @@ -279,7 +279,7 @@ msgstr "アカウントバックアップ計画" #: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:192 #: ops/templates/ops/celery_task_log.html:75 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:137 -#: terminal/models/session/session.py:45 +#: terminal/models/session/session.py:44 #: tickets/models/ticket/apply_application.py:30 #: tickets/models/ticket/apply_asset.py:19 msgid "Date start" @@ -311,7 +311,7 @@ msgstr "理由" #: accounts/models/automations/backup_account.py:99 #: accounts/serializers/automations/change_secret.py:111 #: accounts/serializers/automations/change_secret.py:134 -#: ops/serializers/job.py:56 terminal/serializers/session.py:46 +#: ops/serializers/job.py:56 terminal/serializers/session.py:43 msgid "Is success" msgstr "成功は" @@ -479,10 +479,10 @@ msgstr "アカウントの確認" #: applications/models.py:9 assets/models/_user.py:22 #: assets/models/asset/common.py:91 assets/models/asset/common.py:149 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 -#: assets/models/group.py:20 assets/models/label.py:18 +#: assets/models/group.py:17 assets/models/label.py:18 #: assets/models/platform.py:13 assets/models/platform.py:81 -#: assets/serializers/asset/common.py:145 assets/serializers/platform.py:99 -#: assets/serializers/platform.py:199 +#: assets/serializers/asset/common.py:145 assets/serializers/platform.py:109 +#: assets/serializers/platform.py:209 #: authentication/serializers/connect_token_secret.py:110 ops/mixin.py:21 #: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57 #: ops/models/job.py:92 ops/models/playbook.py:23 ops/serializers/job.py:20 @@ -505,7 +505,8 @@ msgstr "特権アカウント" #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:114 -#: terminal/models/applet/applet.py:39 users/serializers/user.py:169 +#: terminal/models/applet/applet.py:39 +#: terminal/models/component/endpoint.py:101 users/serializers/user.py:169 msgid "Is active" msgstr "アクティブです。" @@ -561,7 +562,7 @@ msgstr "アカウントの存在ポリシー" #: accounts/serializers/account/account.py:180 applications/models.py:11 #: assets/models/label.py:21 assets/models/platform.py:82 #: assets/serializers/asset/common.py:121 assets/serializers/cagegory.py:8 -#: assets/serializers/platform.py:117 assets/serializers/platform.py:200 +#: assets/serializers/platform.py:127 assets/serializers/platform.py:210 #: perms/serializers/user_permission.py:26 settings/models.py:35 #: tickets/models/ticket/apply_application.py:13 msgid "Category" @@ -572,13 +573,13 @@ msgstr "カテゴリ" #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:83 -#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:101 -#: assets/serializers/platform.py:116 audits/serializers.py:48 +#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:111 +#: assets/serializers/platform.py:126 audits/serializers.py:48 #: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:103 #: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:38 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29 -#: terminal/serializers/session.py:23 terminal/serializers/storage.py:224 +#: terminal/serializers/session.py:20 terminal/serializers/storage.py:224 #: terminal/serializers/storage.py:236 tickets/models/comment.py:26 #: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16 #: tickets/models/ticket/general.py:275 tickets/serializers/flow.py:53 @@ -644,7 +645,7 @@ msgstr "ID" #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 #: perms/serializers/permission.py:30 rbac/builtin.py:122 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:19 -#: terminal/models/session/session.py:30 terminal/models/session/sharing.py:32 +#: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 #: terminal/notifications.py:96 terminal/notifications.py:144 #: terminal/serializers/command.py:16 tickets/models/comment.py:21 #: users/const.py:14 users/models/user.py:947 users/models/user.py:978 @@ -688,9 +689,13 @@ msgstr "キーパスワード" msgid "Spec info" msgstr "特別情報" -#: accounts/serializers/account/base.py:81 -msgid "Tip: If no username is required for authentication, fill in `null`" -msgstr "ヒント: 認証にユーザー名が必要ない場合は、null を入力してください" +#: accounts/serializers/account/base.py:82 +msgid "" +"Tip: If no username is required for authentication, fill in `null`, If AD " +"account, like `username@domain`" +msgstr "" +"ヒント: 認証にユーザー名が必要ない場合は、`null`を入力します。ADアカウントの" +"場合は、`username@domain`のようになります。" #: accounts/serializers/automations/base.py:23 #: assets/models/asset/common.py:155 assets/models/automations/base.py:18 @@ -729,7 +734,7 @@ msgstr "自動タスク実行履歴" #: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:40 -#: terminal/const.py:60 terminal/models/session/sharing.py:107 +#: terminal/const.py:61 terminal/models/session/sharing.py:107 #: tickets/views/approve.py:114 msgid "Success" msgstr "成功" @@ -825,8 +830,8 @@ msgid "Accounts" msgstr "アカウント" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:55 terminal/const.py:68 -#: terminal/models/session/session.py:43 terminal/serializers/command.py:18 +#: ops/serializers/job.py:55 terminal/const.py:69 +#: terminal/models/session/session.py:42 terminal/serializers/command.py:18 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 msgid "Command" @@ -964,13 +969,13 @@ msgstr "アプリケーション" msgid "Can match application" msgstr "アプリケーションを一致させることができます" -#: assets/api/asset/asset.py:149 +#: assets/api/asset/asset.py:153 msgid "Cannot create asset directly, you should create a host or other" msgstr "" "資産を直接作成することはできません。ホストまたはその他を作成する必要がありま" "す" -#: assets/api/domain.py:60 +#: assets/api/domain.py:62 msgid "Number required" msgstr "必要な数" @@ -1044,6 +1049,19 @@ msgstr "テストゲートウェイ" msgid "Gather facts" msgstr "資産情報の収集" +#: assets/const/base.py:33 audits/const.py:47 +#: terminal/serializers/applet_host.py:32 +msgid "Disabled" +msgstr "無効" + +#: assets/const/base.py:34 settings/serializers/basic.py:27 +msgid "Basic" +msgstr "基本" + +#: assets/const/base.py:35 assets/models/asset/web.py:13 +msgid "Script" +msgstr "脚本" + #: assets/const/category.py:10 assets/models/asset/host.py:8 #: settings/serializers/auth/radius.py:16 settings/serializers/auth/sms.py:67 #: terminal/models/component/endpoint.py:13 terminal/serializers/applet.py:17 @@ -1106,28 +1124,65 @@ msgstr "ファイアウォール" msgid "Other" msgstr "その他" -#: assets/const/types.py:223 +#: assets/const/protocol.py:39 +msgid "SFTP enabled" +msgstr "SFTP が有効" + +#: assets/const/protocol.py:44 +msgid "SFTP home" +msgstr "SFTP ルート パス" + +#: assets/const/protocol.py:55 +msgid "Console" +msgstr "Console" + +#: assets/const/protocol.py:56 +msgid "Connect to console session" +msgstr "コンソールセッションに接続" + +#: assets/const/protocol.py:60 +msgid "Any" +msgstr "任意" + +#: assets/const/protocol.py:62 settings/serializers/security.py:151 +msgid "Security" +msgstr "セキュリティ" + +#: assets/const/protocol.py:63 +msgid "Security layer to use for the connection" +msgstr "接続に使用するセキュリティ レイヤー" + +#: assets/const/protocol.py:87 assets/models/asset/database.py:10 +#: settings/serializers/email.py:37 +msgid "Use SSL" +msgstr "SSLの使用" + +#: assets/const/protocol.py:140 +#, fuzzy +#| msgid "Auth with username" +msgid "Auth username" +msgstr "ユーザー名で認証する" + +#: assets/const/protocol.py:167 assets/models/asset/web.py:10 +msgid "Username selector" +msgstr "ユーザー名ピッカー" + +#: assets/const/protocol.py:172 assets/models/asset/web.py:11 +msgid "Password selector" +msgstr "パスワードセレクター" + +#: assets/const/protocol.py:177 assets/models/asset/web.py:12 +msgid "Submit selector" +msgstr "ボタンセレクターを確認する" + +#: assets/const/types.py:222 msgid "All types" msgstr "いろんなタイプ" -#: assets/const/web.py:8 +#: assets/const/web.py:7 msgid "Website" msgstr "Webサイト" -#: assets/const/web.py:59 audits/const.py:47 -#: terminal/serializers/applet_host.py:32 -msgid "Disabled" -msgstr "無効" - -#: assets/const/web.py:60 settings/serializers/basic.py:27 -msgid "Basic" -msgstr "基本" - -#: assets/const/web.py:61 assets/models/asset/web.py:13 -#: assets/serializers/platform.py:40 -msgid "Script" -msgstr "脚本" - #: assets/exceptions.py:12 msgid "This function is not supported temporarily" msgstr "この機能は一時的にサポートされていません" @@ -1141,20 +1196,20 @@ msgid "SSH public key" msgstr "SSHパブリックキー" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 -#: assets/models/cmd_filter.py:88 assets/models/group.py:23 +#: assets/models/cmd_filter.py:88 assets/models/group.py:20 #: common/db/models.py:36 ops/models/adhoc.py:27 ops/models/job.py:111 #: ops/models/playbook.py:26 rbac/models/role.py:37 settings/models.py:38 -#: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:244 +#: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:248 #: terminal/models/applet/host.py:139 terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:100 -#: terminal/models/session/session.py:47 tickets/models/comment.py:32 +#: terminal/models/session/session.py:46 tickets/models/comment.py:32 #: tickets/models/ticket/general.py:297 users/models/user.py:792 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 msgid "Comment" msgstr "コメント" #: assets/models/_user.py:28 assets/models/automations/base.py:114 -#: assets/models/cmd_filter.py:41 assets/models/group.py:22 +#: assets/models/cmd_filter.py:41 assets/models/group.py:19 #: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:191 #: users/models/user.py:979 msgid "Date created" @@ -1166,7 +1221,7 @@ msgid "Date updated" msgstr "更新日" #: assets/models/_user.py:30 assets/models/cmd_filter.py:44 -#: assets/models/cmd_filter.py:91 assets/models/group.py:21 +#: assets/models/cmd_filter.py:91 assets/models/group.py:18 #: common/db/models.py:32 users/models/user.py:799 #: users/serializers/group.py:29 msgid "Created by" @@ -1194,8 +1249,8 @@ msgstr "ユーザーと同じユーザー名" #: assets/models/_user.py:52 authentication/models/connection_token.py:40 #: authentication/serializers/connect_token_secret.py:111 -#: terminal/models/applet/applet.py:41 terminal/serializers/session.py:21 -#: terminal/serializers/session.py:42 terminal/serializers/storage.py:68 +#: terminal/models/applet/applet.py:41 terminal/serializers/session.py:18 +#: terminal/serializers/session.py:39 terminal/serializers/storage.py:68 msgid "Protocol" msgstr "プロトコル" @@ -1283,19 +1338,19 @@ msgstr "資産ハードウェア情報の収集" msgid "Custom info" msgstr "カスタム属性" -#: assets/models/asset/common.py:335 +#: assets/models/asset/common.py:334 msgid "Can refresh asset hardware info" msgstr "資産ハードウェア情報を更新できます" -#: assets/models/asset/common.py:336 +#: assets/models/asset/common.py:335 msgid "Can test asset connectivity" msgstr "資産接続をテストできます" -#: assets/models/asset/common.py:337 +#: assets/models/asset/common.py:336 msgid "Can match asset" msgstr "アセットを一致させることができます" -#: assets/models/asset/common.py:338 +#: assets/models/asset/common.py:337 msgid "Can change asset nodes" msgstr "資産ノードを変更できます" @@ -1303,11 +1358,6 @@ msgstr "資産ノードを変更できます" msgid "Custom asset" msgstr "カスタム アセット" -#: assets/models/asset/database.py:10 assets/serializers/platform.py:45 -#: settings/serializers/email.py:37 -msgid "Use SSL" -msgstr "SSLの使用" - #: assets/models/asset/database.py:11 msgid "CA cert" msgstr "CA 証明書" @@ -1325,22 +1375,9 @@ msgid "Allow invalid cert" msgstr "証明書チェックを無視" #: assets/models/asset/web.py:9 assets/serializers/asset/info/spec.py:16 -#: assets/serializers/platform.py:30 msgid "Autofill" msgstr "自動充填" -#: assets/models/asset/web.py:10 assets/serializers/platform.py:32 -msgid "Username selector" -msgstr "ユーザー名ピッカー" - -#: assets/models/asset/web.py:11 assets/serializers/platform.py:35 -msgid "Password selector" -msgstr "パスワードセレクター" - -#: assets/models/asset/web.py:12 assets/serializers/platform.py:38 -msgid "Submit selector" -msgstr "ボタンセレクターを確認する" - #: assets/models/automations/base.py:22 ops/models/job.py:187 #: settings/serializers/auth/sms.py:99 msgid "Parameters" @@ -1356,7 +1393,7 @@ msgstr "アセットの自動化タスク" #: assets/models/automations/base.py:113 audits/models.py:199 #: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:184 -#: terminal/models/applet/applet.py:243 terminal/models/applet/host.py:136 +#: terminal/models/applet/applet.py:247 terminal/models/applet/host.py:136 #: terminal/models/component/status.py:30 terminal/serializers/applet.py:18 #: terminal/serializers/applet_host.py:107 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 @@ -1419,17 +1456,17 @@ msgstr "お気に入りのアセット" msgid "Gateway" msgstr "ゲートウェイ" -#: assets/models/group.py:30 +#: assets/models/group.py:27 msgid "Asset group" msgstr "資産グループ" -#: assets/models/group.py:34 assets/models/platform.py:17 -#: assets/serializers/platform.py:102 +#: assets/models/group.py:31 assets/models/platform.py:17 +#: assets/serializers/platform.py:112 #: xpack/plugins/cloud/providers/nutanix.py:30 msgid "Default" msgstr "デフォルト" -#: assets/models/group.py:34 +#: assets/models/group.py:31 msgid "Default asset group" msgstr "デフォルトアセットグループ" @@ -1447,7 +1484,7 @@ msgstr "値" #: assets/models/label.py:40 assets/serializers/asset/common.py:123 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 -#: assets/serializers/platform.py:100 +#: assets/serializers/platform.py:110 #: authentication/serializers/connect_token_secret.py:121 #: common/serializers/common.py:85 perms/serializers/user_permission.py:28 #: settings/serializers/sms.py:7 @@ -1495,7 +1532,8 @@ msgstr "必要" msgid "Public" msgstr "開ける" -#: assets/models/platform.py:19 settings/serializers/settings.py:67 +#: assets/models/platform.py:19 assets/serializers/platform.py:48 +#: settings/serializers/settings.py:67 #: users/templates/users/reset_password.html:29 msgid "Setting" msgstr "設定" @@ -1509,11 +1547,11 @@ msgstr "有効化" msgid "Ansible config" msgstr "Ansible 構成" -#: assets/models/platform.py:34 assets/serializers/platform.py:63 +#: assets/models/platform.py:34 assets/serializers/platform.py:32 msgid "Ping enabled" msgstr "アセット ディスカバリを有効にする" -#: assets/models/platform.py:35 assets/serializers/platform.py:64 +#: assets/models/platform.py:35 assets/serializers/platform.py:33 msgid "Ping method" msgstr "資産検出方法" @@ -1522,12 +1560,12 @@ msgid "Ping params" msgstr "資産検出パラメータ" #: assets/models/platform.py:38 assets/models/platform.py:62 -#: assets/serializers/platform.py:65 +#: assets/serializers/platform.py:34 msgid "Gather facts enabled" msgstr "資産情報の収集を有効にする" #: assets/models/platform.py:40 assets/models/platform.py:64 -#: assets/serializers/platform.py:66 +#: assets/serializers/platform.py:35 msgid "Gather facts method" msgstr "情報収集の方法" @@ -1535,11 +1573,11 @@ msgstr "情報収集の方法" msgid "Gather facts params" msgstr "情報収集パラメータ" -#: assets/models/platform.py:44 assets/serializers/platform.py:69 +#: assets/models/platform.py:44 assets/serializers/platform.py:38 msgid "Change secret enabled" msgstr "パスワードの変更が有効" -#: assets/models/platform.py:46 assets/serializers/platform.py:70 +#: assets/models/platform.py:46 assets/serializers/platform.py:39 msgid "Change secret method" msgstr "パスワード変更モード" @@ -1547,11 +1585,11 @@ msgstr "パスワード変更モード" msgid "Change secret params" msgstr "パスワード変更パラメータ" -#: assets/models/platform.py:50 assets/serializers/platform.py:71 +#: assets/models/platform.py:50 assets/serializers/platform.py:40 msgid "Push account enabled" msgstr "アカウントのプッシュを有効にする" -#: assets/models/platform.py:52 assets/serializers/platform.py:72 +#: assets/models/platform.py:52 assets/serializers/platform.py:41 msgid "Push account method" msgstr "アカウントプッシュ方式" @@ -1559,11 +1597,11 @@ msgstr "アカウントプッシュ方式" msgid "Push account params" msgstr "アカウントプッシュパラメータ" -#: assets/models/platform.py:56 assets/serializers/platform.py:67 +#: assets/models/platform.py:56 assets/serializers/platform.py:36 msgid "Verify account enabled" msgstr "アカウントの確認をオンにする" -#: assets/models/platform.py:58 assets/serializers/platform.py:68 +#: assets/models/platform.py:58 assets/serializers/platform.py:37 msgid "Verify account method" msgstr "アカウント認証方法" @@ -1579,23 +1617,23 @@ msgstr "メタ" msgid "Internal" msgstr "ビルトイン" -#: assets/models/platform.py:89 assets/serializers/platform.py:115 +#: assets/models/platform.py:89 assets/serializers/platform.py:125 msgid "Charset" msgstr "シャーセット" -#: assets/models/platform.py:91 assets/serializers/platform.py:143 +#: assets/models/platform.py:91 assets/serializers/platform.py:153 msgid "Domain enabled" msgstr "ドメインを有効にする" -#: assets/models/platform.py:93 assets/serializers/platform.py:142 +#: assets/models/platform.py:93 assets/serializers/platform.py:152 msgid "Su enabled" msgstr "アカウントの切り替えを有効にする" -#: assets/models/platform.py:94 assets/serializers/platform.py:121 +#: assets/models/platform.py:94 assets/serializers/platform.py:131 msgid "Su method" msgstr "アカウントの切り替え方法" -#: assets/models/platform.py:95 assets/serializers/platform.py:124 +#: assets/models/platform.py:95 assets/serializers/platform.py:134 msgid "Custom fields" msgstr "カスタムフィールド" @@ -1612,7 +1650,7 @@ msgstr "" "プラットフォームタイプがスキップされた資産に合致しない、資産内の一括更新プ" "ラットフォーム" -#: assets/serializers/asset/common.py:124 assets/serializers/platform.py:118 +#: assets/serializers/asset/common.py:124 assets/serializers/platform.py:128 #: authentication/serializers/connect_token_secret.py:29 #: authentication/serializers/connect_token_secret.py:72 #: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:99 @@ -1728,47 +1766,60 @@ msgstr "値" msgid "Can't contains: /" msgstr "含まれない:/" -#: assets/serializers/platform.py:26 -msgid "SFTP enabled" -msgstr "SFTP が有効" - -#: assets/serializers/platform.py:27 -msgid "SFTP home" -msgstr "SFTP ルート パス" - #: assets/serializers/platform.py:42 -msgid "Auth with username" -msgstr "ユーザー名で認証する" - -#: assets/serializers/platform.py:73 msgid "Gather accounts enabled" msgstr "アカウント収集を有効にする" -#: assets/serializers/platform.py:74 +#: assets/serializers/platform.py:43 msgid "Gather accounts method" msgstr "アカウントの収集方法" -#: assets/serializers/platform.py:103 +#: assets/serializers/platform.py:60 +msgid "" +"This protocol is primary, and it must be set when adding assets. " +"Additionally, there can only be one primary protocol." +msgstr "" +"このプロトコルはプライマリであり、資産を追加するときに設定する必要がありま" +"す。また、プライマリプロトコルは1つしかありません" + +#: assets/serializers/platform.py:65 +msgid "This protocol is required, and it must be set when adding assets." +msgstr "このプロトコルは必須であり、資産を追加するときに設定する必要があります" + +#: assets/serializers/platform.py:68 +msgid "" +"This protocol is default, when adding assets, it will be displayed by " +"default." +msgstr "" +"このプロトコルはデフォルトです。資産を追加するときに、デフォルトで表示されま" +"す" + +#: assets/serializers/platform.py:71 +msgid "This protocol is public, asset will show this protocol to user" +msgstr "" +"このプロトコルは公開されており、資産はこのプロトコルをユーザーに表示します" + +#: assets/serializers/platform.py:113 msgid "Help text" msgstr "ヘルプ" -#: assets/serializers/platform.py:104 +#: assets/serializers/platform.py:114 msgid "Choices" msgstr "せんたく" -#: assets/serializers/platform.py:119 +#: assets/serializers/platform.py:129 msgid "Automation" msgstr "オートメーション" -#: assets/serializers/platform.py:144 +#: assets/serializers/platform.py:154 msgid "Default Domain" msgstr "デフォルト ドメイン" -#: assets/serializers/platform.py:153 +#: assets/serializers/platform.py:163 msgid "type is required" msgstr "タイプ このフィールドは必須です." -#: assets/serializers/platform.py:176 +#: assets/serializers/platform.py:186 msgid "Protocols is required" msgstr "同意が必要です" @@ -1912,7 +1963,7 @@ msgstr "パスワードを変更する" #: audits/const.py:35 settings/serializers/terminal.py:6 #: terminal/models/applet/host.py:25 terminal/models/component/terminal.py:163 -#: terminal/serializers/session.py:49 terminal/serializers/session.py:58 +#: terminal/serializers/session.py:46 terminal/serializers/session.py:55 msgid "Terminal" msgstr "ターミナル" @@ -1950,7 +2001,7 @@ msgid "Job audit log" msgstr "ジョブ監査ログ" #: audits/models.py:51 audits/models.py:95 audits/models.py:166 -#: terminal/models/session/session.py:39 terminal/models/session/sharing.py:99 +#: terminal/models/session/session.py:38 terminal/models/session/sharing.py:99 msgid "Remote addr" msgstr "リモートaddr" @@ -2090,14 +2141,14 @@ msgid "Auth Token" msgstr "認証トークン" #: audits/signal_handlers/login_log.py:31 authentication/notifications.py:73 -#: authentication/views/login.py:74 authentication/views/wecom.py:159 +#: authentication/views/login.py:75 authentication/views/wecom.py:159 #: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10 #: users/models/user.py:706 users/models/user.py:814 msgid "WeCom" msgstr "企業微信" #: audits/signal_handlers/login_log.py:32 authentication/views/feishu.py:123 -#: authentication/views/login.py:86 notifications/backends/__init__.py:14 +#: authentication/views/login.py:87 notifications/backends/__init__.py:14 #: settings/serializers/auth/feishu.py:10 #: settings/serializers/auth/feishu.py:13 users/models/user.py:708 #: users/models/user.py:816 @@ -2105,7 +2156,7 @@ msgid "FeiShu" msgstr "本を飛ばす" #: audits/signal_handlers/login_log.py:33 authentication/views/dingtalk.py:160 -#: authentication/views/login.py:80 notifications/backends/__init__.py:12 +#: authentication/views/login.py:81 notifications/backends/__init__.py:12 #: settings/serializers/auth/dingtalk.py:10 users/models/user.py:707 #: users/models/user.py:815 msgid "DingTalk" @@ -2981,23 +3032,23 @@ msgstr "本を飛ばすのバインドに成功" msgid "Failed to get user from FeiShu" msgstr "本を飛ばすからユーザーを取得できませんでした" -#: authentication/views/login.py:182 +#: authentication/views/login.py:183 msgid "Redirecting" msgstr "リダイレクト" -#: authentication/views/login.py:183 +#: authentication/views/login.py:184 msgid "Redirecting to {} authentication" msgstr "{} 認証へのリダイレクト" -#: authentication/views/login.py:206 -msgid "Please enable cookies and try again." -msgstr "クッキーを有効にして、もう一度お試しください。" +#: authentication/views/login.py:207 +msgid "Login timeout, please try again." +msgstr "ログインタイムアウト、もう一度お試しください" -#: authentication/views/login.py:247 +#: authentication/views/login.py:250 msgid "User email already exists ({})" msgstr "ユーザー メールボックスは既に存在します ({})" -#: authentication/views/login.py:325 +#: authentication/views/login.py:328 msgid "" "Wait for {} confirm, You also can copy link to her/him
\n" " Don't close this page" @@ -3005,15 +3056,15 @@ msgstr "" "{} 確認を待ちます。彼女/彼へのリンクをコピーすることもできます
\n" " このページを閉じないでください" -#: authentication/views/login.py:330 +#: authentication/views/login.py:333 msgid "No ticket found" msgstr "チケットが見つかりません" -#: authentication/views/login.py:366 +#: authentication/views/login.py:369 msgid "Logout success" msgstr "ログアウト成功" -#: authentication/views/login.py:367 +#: authentication/views/login.py:370 msgid "Logout success, return login page" msgstr "ログアウト成功、ログインページを返す" @@ -3061,7 +3112,7 @@ msgstr "タイミングトリガー" msgid "Ready" msgstr "の準備を" -#: common/const/choices.py:16 terminal/const.py:59 tickets/const.py:29 +#: common/const/choices.py:16 terminal/const.py:60 tickets/const.py:29 #: tickets/const.py:39 msgid "Pending" msgstr "未定" @@ -3702,7 +3753,7 @@ msgstr "保存後に実行" msgid "Job type" msgstr "タスクの種類" -#: ops/serializers/job.py:57 terminal/serializers/session.py:50 +#: ops/serializers/job.py:57 terminal/serializers/session.py:47 msgid "Is finished" msgstr "終了しました" @@ -4118,7 +4169,7 @@ msgid "My assets" msgstr "私の資産" #: rbac/tree.py:56 terminal/models/applet/applet.py:51 -#: terminal/models/applet/applet.py:240 terminal/models/applet/host.py:28 +#: terminal/models/applet/applet.py:244 terminal/models/applet/host.py:28 #: terminal/serializers/applet.py:15 msgid "Applet" msgstr "リモートアプリケーション" @@ -4148,23 +4199,23 @@ msgstr "テストの成功" msgid "Test mail sent to {}, please check" msgstr "{}に送信されたテストメールを確認してください" -#: settings/api/ldap.py:173 +#: settings/api/ldap.py:176 msgid "Synchronization start, please wait." msgstr "同期開始、お待ちください。" -#: settings/api/ldap.py:177 +#: settings/api/ldap.py:180 msgid "Synchronization is running, please wait." msgstr "同期が実行中です。しばらくお待ちください。" -#: settings/api/ldap.py:182 +#: settings/api/ldap.py:185 msgid "Synchronization error: {}" msgstr "同期エラー: {}" -#: settings/api/ldap.py:220 +#: settings/api/ldap.py:223 msgid "Get ldap users is None" msgstr "Ldapユーザーを取得するにはNone" -#: settings/api/ldap.py:230 +#: settings/api/ldap.py:233 msgid "Imported {} users successfully (Organization: {})" msgstr "{} 人のユーザーを正常にインポートしました (組織: {})" @@ -5078,10 +5129,6 @@ msgstr "ログインcaptchaの有効化" msgid "Enable captcha to prevent robot authentication" msgstr "Captchaを有効にしてロボット認証を防止する" -#: settings/serializers/security.py:151 -msgid "Security" -msgstr "セキュリティ" - #: settings/serializers/security.py:154 msgid "Enable terminal register" msgstr "ターミナルレジスタの有効化" @@ -5640,7 +5687,7 @@ msgstr "クリティカル" msgid "High" msgstr "高い" -#: terminal/const.py:32 terminal/const.py:66 +#: terminal/const.py:32 terminal/const.py:67 #: users/templates/users/reset_password.html:50 msgid "Normal" msgstr "正常" @@ -5649,19 +5696,19 @@ msgstr "正常" msgid "Offline" msgstr "オフライン" -#: terminal/const.py:62 +#: terminal/const.py:63 msgid "Mismatch" msgstr "一致しない" -#: terminal/const.py:67 +#: terminal/const.py:68 msgid "Tunnel" msgstr "" -#: terminal/const.py:72 +#: terminal/const.py:73 msgid "Read Only" msgstr "読み取り専用" -#: terminal/const.py:73 +#: terminal/const.py:74 msgid "Writable" msgstr "書き込み可能" @@ -5717,7 +5764,7 @@ msgstr "カスタムプラットフォームのみをサポート" msgid "Missing type in platform.yml" msgstr "platform.ymlにタイプがありません" -#: terminal/models/applet/applet.py:242 terminal/models/applet/host.py:34 +#: terminal/models/applet/applet.py:246 terminal/models/applet/host.py:34 #: terminal/models/applet/host.py:134 msgid "Hosting" msgstr "ホスト マシン" @@ -5786,7 +5833,7 @@ msgstr "エンドポイント" msgid "IP group" msgstr "IP グループ" -#: terminal/models/component/endpoint.py:103 +#: terminal/models/component/endpoint.py:104 msgid "Endpoint rule" msgstr "エンドポイントルール" @@ -5864,39 +5911,39 @@ msgstr "セッションのリプレイをアップロードできます" msgid "Can download session replay" msgstr "セッション再生をダウンロードできます" -#: terminal/models/session/session.py:35 +#: terminal/models/session/session.py:34 msgid "Account id" msgstr "アカウント ID" -#: terminal/models/session/session.py:37 terminal/models/session/sharing.py:104 +#: terminal/models/session/session.py:36 terminal/models/session/sharing.py:104 msgid "Login from" msgstr "ログイン元" -#: terminal/models/session/session.py:42 +#: terminal/models/session/session.py:41 msgid "Replay" msgstr "リプレイ" -#: terminal/models/session/session.py:46 +#: terminal/models/session/session.py:45 msgid "Date end" msgstr "終了日" -#: terminal/models/session/session.py:243 +#: terminal/models/session/session.py:240 msgid "Session record" msgstr "セッション記録" -#: terminal/models/session/session.py:245 +#: terminal/models/session/session.py:242 msgid "Can monitor session" msgstr "セッションを監視できます" -#: terminal/models/session/session.py:246 +#: terminal/models/session/session.py:243 msgid "Can share session" msgstr "セッションを共有できます" -#: terminal/models/session/session.py:247 +#: terminal/models/session/session.py:244 msgid "Can terminate session" msgstr "セッションを終了できます" -#: terminal/models/session/session.py:248 +#: terminal/models/session/session.py:245 msgid "Can validate session action perm" msgstr "セッションアクションのパーマを検証できます" @@ -6104,35 +6151,35 @@ msgstr "" msgid "Asset IP" msgstr "資産 IP" -#: terminal/serializers/session.py:25 terminal/serializers/session.py:47 +#: terminal/serializers/session.py:22 terminal/serializers/session.py:44 msgid "Can replay" msgstr "再生できます" -#: terminal/serializers/session.py:26 terminal/serializers/session.py:48 +#: terminal/serializers/session.py:23 terminal/serializers/session.py:45 msgid "Can join" msgstr "参加できます" -#: terminal/serializers/session.py:27 terminal/serializers/session.py:51 +#: terminal/serializers/session.py:24 terminal/serializers/session.py:48 msgid "Can terminate" msgstr "終了できます" -#: terminal/serializers/session.py:43 +#: terminal/serializers/session.py:40 msgid "User ID" msgstr "ユーザーID" -#: terminal/serializers/session.py:44 +#: terminal/serializers/session.py:41 msgid "Asset ID" msgstr "資産ID" -#: terminal/serializers/session.py:45 +#: terminal/serializers/session.py:42 msgid "Login from display" msgstr "表示からのログイン" -#: terminal/serializers/session.py:52 +#: terminal/serializers/session.py:49 msgid "Terminal display" msgstr "ターミナルディスプレイ" -#: terminal/serializers/session.py:57 +#: terminal/serializers/session.py:54 msgid "Command amount" msgstr "コマンド量" @@ -6447,11 +6494,11 @@ msgstr "承認ステップ" msgid "Relation snapshot" msgstr "製造オーダスナップショット" -#: tickets/models/ticket/general.py:392 +#: tickets/models/ticket/general.py:398 msgid "Please try again" msgstr "もう一度お試しください" -#: tickets/models/ticket/general.py:461 +#: tickets/models/ticket/general.py:467 msgid "Super ticket" msgstr "スーパーチケット" @@ -7726,3 +7773,6 @@ msgstr "究極のエディション" #: xpack/plugins/license/models.py:86 msgid "Community edition" msgstr "コミュニティ版" + +#~ msgid "Please enable cookies and try again." +#~ msgstr "クッキーを有効にして、もう一度お試しください。" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 1c7c46cca..a0ae902e3 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0efb248e80873f34d20f0fc3d4dd5c5a346048cb683c2b6bda3df939697fc52c -size 119261 +oid sha256:6cedb6d13bc42a5621b60813fb4db0c094a343568eb3f5678566cbbe7f763228 +size 120269 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 48b00a44f..9792d6a89 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-15 15:35+0800\n" +"POT-Creation-Date: 2023-06-30 15:41+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -86,7 +86,7 @@ msgstr "更新" #: accounts/const/account.py:27 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:61 xpack/plugins/cloud/const.py:41 +#: ops/const.py:58 terminal/const.py:62 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失败" @@ -186,11 +186,11 @@ msgstr "仅创建" #: accounts/serializers/automations/change_secret.py:112 #: accounts/serializers/automations/change_secret.py:132 #: acls/serializers/base.py:118 assets/models/asset/common.py:93 -#: assets/models/asset/common.py:332 assets/models/cmd_filter.py:36 +#: assets/models/asset/common.py:331 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:53 authentication/models/connection_token.py:35 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 -#: terminal/backends/command/models.py:20 terminal/models/session/session.py:32 +#: terminal/backends/command/models.py:20 terminal/models/session/session.py:31 #: terminal/notifications.py:95 terminal/serializers/command.py:17 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" @@ -224,7 +224,7 @@ msgstr "来源 ID" #: acls/serializers/base.py:119 assets/serializers/asset/common.py:125 #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 -#: terminal/backends/command/models.py:21 terminal/models/session/session.py:34 +#: terminal/backends/command/models.py:21 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "账号" @@ -278,7 +278,7 @@ msgstr "账号备份计划" #: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:192 #: ops/templates/ops/celery_task_log.html:75 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:137 -#: terminal/models/session/session.py:45 +#: terminal/models/session/session.py:44 #: tickets/models/ticket/apply_application.py:30 #: tickets/models/ticket/apply_asset.py:19 msgid "Date start" @@ -310,7 +310,7 @@ msgstr "原因" #: accounts/models/automations/backup_account.py:99 #: accounts/serializers/automations/change_secret.py:111 #: accounts/serializers/automations/change_secret.py:134 -#: ops/serializers/job.py:56 terminal/serializers/session.py:46 +#: ops/serializers/job.py:56 terminal/serializers/session.py:43 msgid "Is success" msgstr "是否成功" @@ -478,10 +478,10 @@ msgstr "账号验证" #: applications/models.py:9 assets/models/_user.py:22 #: assets/models/asset/common.py:91 assets/models/asset/common.py:149 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 -#: assets/models/group.py:20 assets/models/label.py:18 +#: assets/models/group.py:17 assets/models/label.py:18 #: assets/models/platform.py:13 assets/models/platform.py:81 -#: assets/serializers/asset/common.py:145 assets/serializers/platform.py:99 -#: assets/serializers/platform.py:199 +#: assets/serializers/asset/common.py:145 assets/serializers/platform.py:109 +#: assets/serializers/platform.py:209 #: authentication/serializers/connect_token_secret.py:110 ops/mixin.py:21 #: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57 #: ops/models/job.py:92 ops/models/playbook.py:23 ops/serializers/job.py:20 @@ -504,7 +504,8 @@ msgstr "特权账号" #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:114 -#: terminal/models/applet/applet.py:39 users/serializers/user.py:169 +#: terminal/models/applet/applet.py:39 +#: terminal/models/component/endpoint.py:101 users/serializers/user.py:169 msgid "Is active" msgstr "激活" @@ -557,7 +558,7 @@ msgstr "账号存在策略" #: accounts/serializers/account/account.py:180 applications/models.py:11 #: assets/models/label.py:21 assets/models/platform.py:82 #: assets/serializers/asset/common.py:121 assets/serializers/cagegory.py:8 -#: assets/serializers/platform.py:117 assets/serializers/platform.py:200 +#: assets/serializers/platform.py:127 assets/serializers/platform.py:210 #: perms/serializers/user_permission.py:26 settings/models.py:35 #: tickets/models/ticket/apply_application.py:13 msgid "Category" @@ -568,13 +569,13 @@ msgstr "类别" #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:83 -#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:101 -#: assets/serializers/platform.py:116 audits/serializers.py:48 +#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:111 +#: assets/serializers/platform.py:126 audits/serializers.py:48 #: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:103 #: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:38 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29 -#: terminal/serializers/session.py:23 terminal/serializers/storage.py:224 +#: terminal/serializers/session.py:20 terminal/serializers/storage.py:224 #: terminal/serializers/storage.py:236 tickets/models/comment.py:26 #: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16 #: tickets/models/ticket/general.py:275 tickets/serializers/flow.py:53 @@ -640,7 +641,7 @@ msgstr "ID" #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 #: perms/serializers/permission.py:30 rbac/builtin.py:122 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:19 -#: terminal/models/session/session.py:30 terminal/models/session/sharing.py:32 +#: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 #: terminal/notifications.py:96 terminal/notifications.py:144 #: terminal/serializers/command.py:16 tickets/models/comment.py:21 #: users/const.py:14 users/models/user.py:947 users/models/user.py:978 @@ -684,9 +685,13 @@ msgstr "密钥密码" msgid "Spec info" msgstr "特殊信息" -#: accounts/serializers/account/base.py:81 -msgid "Tip: If no username is required for authentication, fill in `null`" -msgstr "提示: 如果认证时不需要用户名,可填写为 null" +#: accounts/serializers/account/base.py:82 +msgid "" +"Tip: If no username is required for authentication, fill in `null`, If AD " +"account, like `username@domain`" +msgstr "" +"提示: 如果认证时不需要用户名,可填写为 null, 如果是 AD 账号,格式为 " +"username@domain" #: accounts/serializers/automations/base.py:23 #: assets/models/asset/common.py:155 assets/models/automations/base.py:18 @@ -725,7 +730,7 @@ msgstr "自动化任务执行历史" #: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:40 -#: terminal/const.py:60 terminal/models/session/sharing.py:107 +#: terminal/const.py:61 terminal/models/session/sharing.py:107 #: tickets/views/approve.py:114 msgid "Success" msgstr "成功" @@ -821,8 +826,8 @@ msgid "Accounts" msgstr "账号管理" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:55 terminal/const.py:68 -#: terminal/models/session/session.py:43 terminal/serializers/command.py:18 +#: ops/serializers/job.py:55 terminal/const.py:69 +#: terminal/models/session/session.py:42 terminal/serializers/command.py:18 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 msgid "Command" @@ -959,11 +964,11 @@ msgstr "应用程序" msgid "Can match application" msgstr "匹配应用" -#: assets/api/asset/asset.py:149 +#: assets/api/asset/asset.py:153 msgid "Cannot create asset directly, you should create a host or other" msgstr "不能直接创建资产, 你应该创建主机或其他资产" -#: assets/api/domain.py:60 +#: assets/api/domain.py:62 msgid "Number required" msgstr "需要为数字" @@ -1037,6 +1042,19 @@ msgstr "测试网关" msgid "Gather facts" msgstr "收集资产信息" +#: assets/const/base.py:33 audits/const.py:47 +#: terminal/serializers/applet_host.py:32 +msgid "Disabled" +msgstr "禁用" + +#: assets/const/base.py:34 settings/serializers/basic.py:27 +msgid "Basic" +msgstr "基本" + +#: assets/const/base.py:35 assets/models/asset/web.py:13 +msgid "Script" +msgstr "脚本" + #: assets/const/category.py:10 assets/models/asset/host.py:8 #: settings/serializers/auth/radius.py:16 settings/serializers/auth/sms.py:67 #: terminal/models/component/endpoint.py:13 terminal/serializers/applet.py:17 @@ -1099,28 +1117,63 @@ msgstr "防火墙" msgid "Other" msgstr "其它" -#: assets/const/types.py:223 +#: assets/const/protocol.py:39 +msgid "SFTP enabled" +msgstr "SFTP 已启用" + +#: assets/const/protocol.py:44 +msgid "SFTP home" +msgstr "SFTP 根路径" + +#: assets/const/protocol.py:55 +msgid "Console" +msgstr "控制台" + +#: assets/const/protocol.py:56 +msgid "Connect to console session" +msgstr "连接到控制台会话" + +#: assets/const/protocol.py:60 +msgid "Any" +msgstr "任意" + +#: assets/const/protocol.py:62 settings/serializers/security.py:151 +msgid "Security" +msgstr "安全" + +#: assets/const/protocol.py:63 +msgid "Security layer to use for the connection" +msgstr "连接 RDP 使用的安全层" + +#: assets/const/protocol.py:87 assets/models/asset/database.py:10 +#: settings/serializers/email.py:37 +msgid "Use SSL" +msgstr "使用 SSL" + +#: assets/const/protocol.py:140 +msgid "Auth username" +msgstr "使用用户名认证" + +#: assets/const/protocol.py:167 assets/models/asset/web.py:10 +msgid "Username selector" +msgstr "用户名选择器" + +#: assets/const/protocol.py:172 assets/models/asset/web.py:11 +msgid "Password selector" +msgstr "密码选择器" + +#: assets/const/protocol.py:177 assets/models/asset/web.py:12 +msgid "Submit selector" +msgstr "确认按钮选择器" + +#: assets/const/types.py:222 msgid "All types" msgstr "所有类型" -#: assets/const/web.py:8 +#: assets/const/web.py:7 msgid "Website" msgstr "网站" -#: assets/const/web.py:59 audits/const.py:47 -#: terminal/serializers/applet_host.py:32 -msgid "Disabled" -msgstr "禁用" - -#: assets/const/web.py:60 settings/serializers/basic.py:27 -msgid "Basic" -msgstr "基本" - -#: assets/const/web.py:61 assets/models/asset/web.py:13 -#: assets/serializers/platform.py:40 -msgid "Script" -msgstr "脚本" - #: assets/exceptions.py:12 msgid "This function is not supported temporarily" msgstr "暂时不支持此功能" @@ -1134,20 +1187,20 @@ msgid "SSH public key" msgstr "SSH公钥" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 -#: assets/models/cmd_filter.py:88 assets/models/group.py:23 +#: assets/models/cmd_filter.py:88 assets/models/group.py:20 #: common/db/models.py:36 ops/models/adhoc.py:27 ops/models/job.py:111 #: ops/models/playbook.py:26 rbac/models/role.py:37 settings/models.py:38 -#: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:244 +#: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:248 #: terminal/models/applet/host.py:139 terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:100 -#: terminal/models/session/session.py:47 tickets/models/comment.py:32 +#: terminal/models/session/session.py:46 tickets/models/comment.py:32 #: tickets/models/ticket/general.py:297 users/models/user.py:792 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 msgid "Comment" msgstr "备注" #: assets/models/_user.py:28 assets/models/automations/base.py:114 -#: assets/models/cmd_filter.py:41 assets/models/group.py:22 +#: assets/models/cmd_filter.py:41 assets/models/group.py:19 #: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:191 #: users/models/user.py:979 msgid "Date created" @@ -1159,7 +1212,7 @@ msgid "Date updated" msgstr "更新日期" #: assets/models/_user.py:30 assets/models/cmd_filter.py:44 -#: assets/models/cmd_filter.py:91 assets/models/group.py:21 +#: assets/models/cmd_filter.py:91 assets/models/group.py:18 #: common/db/models.py:32 users/models/user.py:799 #: users/serializers/group.py:29 msgid "Created by" @@ -1187,8 +1240,8 @@ msgstr "用户名与用户相同" #: assets/models/_user.py:52 authentication/models/connection_token.py:40 #: authentication/serializers/connect_token_secret.py:111 -#: terminal/models/applet/applet.py:41 terminal/serializers/session.py:21 -#: terminal/serializers/session.py:42 terminal/serializers/storage.py:68 +#: terminal/models/applet/applet.py:41 terminal/serializers/session.py:18 +#: terminal/serializers/session.py:39 terminal/serializers/storage.py:68 msgid "Protocol" msgstr "协议" @@ -1276,19 +1329,19 @@ msgstr "收集资产硬件信息" msgid "Custom info" msgstr "自定义属性" -#: assets/models/asset/common.py:335 +#: assets/models/asset/common.py:334 msgid "Can refresh asset hardware info" msgstr "可以更新资产硬件信息" -#: assets/models/asset/common.py:336 +#: assets/models/asset/common.py:335 msgid "Can test asset connectivity" msgstr "可以测试资产连接性" -#: assets/models/asset/common.py:337 +#: assets/models/asset/common.py:336 msgid "Can match asset" msgstr "可以匹配资产" -#: assets/models/asset/common.py:338 +#: assets/models/asset/common.py:337 msgid "Can change asset nodes" msgstr "可以修改资产节点" @@ -1296,11 +1349,6 @@ msgstr "可以修改资产节点" msgid "Custom asset" msgstr "自定义资产" -#: assets/models/asset/database.py:10 assets/serializers/platform.py:45 -#: settings/serializers/email.py:37 -msgid "Use SSL" -msgstr "使用 SSL" - #: assets/models/asset/database.py:11 msgid "CA cert" msgstr "CA 证书" @@ -1318,22 +1366,9 @@ msgid "Allow invalid cert" msgstr "忽略证书校验" #: assets/models/asset/web.py:9 assets/serializers/asset/info/spec.py:16 -#: assets/serializers/platform.py:30 msgid "Autofill" msgstr "自动代填" -#: assets/models/asset/web.py:10 assets/serializers/platform.py:32 -msgid "Username selector" -msgstr "用户名选择器" - -#: assets/models/asset/web.py:11 assets/serializers/platform.py:35 -msgid "Password selector" -msgstr "密码选择器" - -#: assets/models/asset/web.py:12 assets/serializers/platform.py:38 -msgid "Submit selector" -msgstr "确认按钮选择器" - #: assets/models/automations/base.py:22 ops/models/job.py:187 #: settings/serializers/auth/sms.py:99 msgid "Parameters" @@ -1349,7 +1384,7 @@ msgstr "资产自动化任务" #: assets/models/automations/base.py:113 audits/models.py:199 #: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:184 -#: terminal/models/applet/applet.py:243 terminal/models/applet/host.py:136 +#: terminal/models/applet/applet.py:247 terminal/models/applet/host.py:136 #: terminal/models/component/status.py:30 terminal/serializers/applet.py:18 #: terminal/serializers/applet_host.py:107 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 @@ -1412,17 +1447,17 @@ msgstr "收藏的资产" msgid "Gateway" msgstr "网关" -#: assets/models/group.py:30 +#: assets/models/group.py:27 msgid "Asset group" msgstr "资产组" -#: assets/models/group.py:34 assets/models/platform.py:17 -#: assets/serializers/platform.py:102 +#: assets/models/group.py:31 assets/models/platform.py:17 +#: assets/serializers/platform.py:112 #: xpack/plugins/cloud/providers/nutanix.py:30 msgid "Default" msgstr "默认" -#: assets/models/group.py:34 +#: assets/models/group.py:31 msgid "Default asset group" msgstr "默认资产组" @@ -1440,7 +1475,7 @@ msgstr "值" #: assets/models/label.py:40 assets/serializers/asset/common.py:123 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 -#: assets/serializers/platform.py:100 +#: assets/serializers/platform.py:110 #: authentication/serializers/connect_token_secret.py:121 #: common/serializers/common.py:85 perms/serializers/user_permission.py:28 #: settings/serializers/sms.py:7 @@ -1488,7 +1523,8 @@ msgstr "必须的" msgid "Public" msgstr "开放的" -#: assets/models/platform.py:19 settings/serializers/settings.py:67 +#: assets/models/platform.py:19 assets/serializers/platform.py:48 +#: settings/serializers/settings.py:67 #: users/templates/users/reset_password.html:29 msgid "Setting" msgstr "设置" @@ -1502,11 +1538,11 @@ msgstr "启用" msgid "Ansible config" msgstr "Ansible 配置" -#: assets/models/platform.py:34 assets/serializers/platform.py:63 +#: assets/models/platform.py:34 assets/serializers/platform.py:32 msgid "Ping enabled" msgstr "启用资产探活" -#: assets/models/platform.py:35 assets/serializers/platform.py:64 +#: assets/models/platform.py:35 assets/serializers/platform.py:33 msgid "Ping method" msgstr "资产探活方式" @@ -1515,12 +1551,12 @@ msgid "Ping params" msgstr "资产探活参数" #: assets/models/platform.py:38 assets/models/platform.py:62 -#: assets/serializers/platform.py:65 +#: assets/serializers/platform.py:34 msgid "Gather facts enabled" msgstr "启用收集资产信息" #: assets/models/platform.py:40 assets/models/platform.py:64 -#: assets/serializers/platform.py:66 +#: assets/serializers/platform.py:35 msgid "Gather facts method" msgstr "收集信息方式" @@ -1528,11 +1564,11 @@ msgstr "收集信息方式" msgid "Gather facts params" msgstr "收集信息参数" -#: assets/models/platform.py:44 assets/serializers/platform.py:69 +#: assets/models/platform.py:44 assets/serializers/platform.py:38 msgid "Change secret enabled" msgstr "启用改密" -#: assets/models/platform.py:46 assets/serializers/platform.py:70 +#: assets/models/platform.py:46 assets/serializers/platform.py:39 msgid "Change secret method" msgstr "改密方式" @@ -1540,11 +1576,11 @@ msgstr "改密方式" msgid "Change secret params" msgstr "改密参数" -#: assets/models/platform.py:50 assets/serializers/platform.py:71 +#: assets/models/platform.py:50 assets/serializers/platform.py:40 msgid "Push account enabled" msgstr "启用账号推送" -#: assets/models/platform.py:52 assets/serializers/platform.py:72 +#: assets/models/platform.py:52 assets/serializers/platform.py:41 msgid "Push account method" msgstr "账号推送方式" @@ -1552,11 +1588,11 @@ msgstr "账号推送方式" msgid "Push account params" msgstr "账号推送参数" -#: assets/models/platform.py:56 assets/serializers/platform.py:67 +#: assets/models/platform.py:56 assets/serializers/platform.py:36 msgid "Verify account enabled" msgstr "开启账号验证" -#: assets/models/platform.py:58 assets/serializers/platform.py:68 +#: assets/models/platform.py:58 assets/serializers/platform.py:37 msgid "Verify account method" msgstr "账号验证方式" @@ -1572,23 +1608,23 @@ msgstr "元数据" msgid "Internal" msgstr "内置" -#: assets/models/platform.py:89 assets/serializers/platform.py:115 +#: assets/models/platform.py:89 assets/serializers/platform.py:125 msgid "Charset" msgstr "编码" -#: assets/models/platform.py:91 assets/serializers/platform.py:143 +#: assets/models/platform.py:91 assets/serializers/platform.py:153 msgid "Domain enabled" msgstr "启用网域" -#: assets/models/platform.py:93 assets/serializers/platform.py:142 +#: assets/models/platform.py:93 assets/serializers/platform.py:152 msgid "Su enabled" msgstr "启用账号切换" -#: assets/models/platform.py:94 assets/serializers/platform.py:121 +#: assets/models/platform.py:94 assets/serializers/platform.py:131 msgid "Su method" msgstr "账号切换方式" -#: assets/models/platform.py:95 assets/serializers/platform.py:124 +#: assets/models/platform.py:95 assets/serializers/platform.py:134 msgid "Custom fields" msgstr "自定义属性" @@ -1603,7 +1639,7 @@ msgid "" "type" msgstr "资产中批量更新平台,不符合平台类型跳过的资产" -#: assets/serializers/asset/common.py:124 assets/serializers/platform.py:118 +#: assets/serializers/asset/common.py:124 assets/serializers/platform.py:128 #: authentication/serializers/connect_token_secret.py:29 #: authentication/serializers/connect_token_secret.py:72 #: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:99 @@ -1719,47 +1755,55 @@ msgstr "值" msgid "Can't contains: /" msgstr "不能包含: /" -#: assets/serializers/platform.py:26 -msgid "SFTP enabled" -msgstr "SFTP 已启用" - -#: assets/serializers/platform.py:27 -msgid "SFTP home" -msgstr "SFTP 根路径" - #: assets/serializers/platform.py:42 -msgid "Auth with username" -msgstr "使用用户名认证" - -#: assets/serializers/platform.py:73 msgid "Gather accounts enabled" msgstr "启用账号收集" -#: assets/serializers/platform.py:74 +#: assets/serializers/platform.py:43 msgid "Gather accounts method" msgstr "收集账号方式" -#: assets/serializers/platform.py:103 +#: assets/serializers/platform.py:60 +msgid "" +"This protocol is primary, and it must be set when adding assets. " +"Additionally, there can only be one primary protocol." +msgstr "该协议是主要的,添加资产时必须设置。并且只能有一个主要协议" + +#: assets/serializers/platform.py:65 +msgid "This protocol is required, and it must be set when adding assets." +msgstr "该协议是必填的,添加资产时必须设置" + +#: assets/serializers/platform.py:68 +msgid "" +"This protocol is default, when adding assets, it will be displayed by " +"default." +msgstr "该协议是默认的,添加资产时,将默认显示" + +#: assets/serializers/platform.py:71 +msgid "This protocol is public, asset will show this protocol to user" +msgstr "该协议是公开的,资产将向用户显示该协议并可以连接使用" + +#: assets/serializers/platform.py:113 msgid "Help text" msgstr "帮助" -#: assets/serializers/platform.py:104 +#: assets/serializers/platform.py:114 msgid "Choices" msgstr "选择" -#: assets/serializers/platform.py:119 +#: assets/serializers/platform.py:129 msgid "Automation" msgstr "自动化" -#: assets/serializers/platform.py:144 +#: assets/serializers/platform.py:154 msgid "Default Domain" msgstr "默认网域" -#: assets/serializers/platform.py:153 +#: assets/serializers/platform.py:163 msgid "type is required" msgstr "类型 该字段是必填项。" -#: assets/serializers/platform.py:176 +#: assets/serializers/platform.py:186 msgid "Protocols is required" msgstr "协议是必填的" @@ -1901,7 +1945,7 @@ msgstr "改密" #: audits/const.py:35 settings/serializers/terminal.py:6 #: terminal/models/applet/host.py:25 terminal/models/component/terminal.py:163 -#: terminal/serializers/session.py:49 terminal/serializers/session.py:58 +#: terminal/serializers/session.py:46 terminal/serializers/session.py:55 msgid "Terminal" msgstr "终端" @@ -1939,7 +1983,7 @@ msgid "Job audit log" msgstr "作业审计日志" #: audits/models.py:51 audits/models.py:95 audits/models.py:166 -#: terminal/models/session/session.py:39 terminal/models/session/sharing.py:99 +#: terminal/models/session/session.py:38 terminal/models/session/sharing.py:99 msgid "Remote addr" msgstr "远端地址" @@ -2079,14 +2123,14 @@ msgid "Auth Token" msgstr "认证令牌" #: audits/signal_handlers/login_log.py:31 authentication/notifications.py:73 -#: authentication/views/login.py:74 authentication/views/wecom.py:159 +#: authentication/views/login.py:75 authentication/views/wecom.py:159 #: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10 #: users/models/user.py:706 users/models/user.py:814 msgid "WeCom" msgstr "企业微信" #: audits/signal_handlers/login_log.py:32 authentication/views/feishu.py:123 -#: authentication/views/login.py:86 notifications/backends/__init__.py:14 +#: authentication/views/login.py:87 notifications/backends/__init__.py:14 #: settings/serializers/auth/feishu.py:10 #: settings/serializers/auth/feishu.py:13 users/models/user.py:708 #: users/models/user.py:816 @@ -2094,7 +2138,7 @@ msgid "FeiShu" msgstr "飞书" #: audits/signal_handlers/login_log.py:33 authentication/views/dingtalk.py:160 -#: authentication/views/login.py:80 notifications/backends/__init__.py:12 +#: authentication/views/login.py:81 notifications/backends/__init__.py:12 #: settings/serializers/auth/dingtalk.py:10 users/models/user.py:707 #: users/models/user.py:815 msgid "DingTalk" @@ -2946,23 +2990,23 @@ msgstr "绑定 飞书 成功" msgid "Failed to get user from FeiShu" msgstr "从飞书获取用户失败" -#: authentication/views/login.py:182 +#: authentication/views/login.py:183 msgid "Redirecting" msgstr "跳转中" -#: authentication/views/login.py:183 +#: authentication/views/login.py:184 msgid "Redirecting to {} authentication" msgstr "正在跳转到 {} 认证" -#: authentication/views/login.py:206 -msgid "Please enable cookies and try again." -msgstr "设置你的浏览器支持cookie" +#: authentication/views/login.py:207 +msgid "Login timeout, please try again." +msgstr "登录超时,请重新登录" -#: authentication/views/login.py:247 +#: authentication/views/login.py:250 msgid "User email already exists ({})" msgstr "用户邮箱已存在 ({})" -#: authentication/views/login.py:325 +#: authentication/views/login.py:328 msgid "" "Wait for {} confirm, You also can copy link to her/him
\n" " Don't close this page" @@ -2970,15 +3014,15 @@ msgstr "" "等待 {} 确认, 你也可以复制链接发给他/她
\n" " 不要关闭本页面" -#: authentication/views/login.py:330 +#: authentication/views/login.py:333 msgid "No ticket found" msgstr "没有发现工单" -#: authentication/views/login.py:366 +#: authentication/views/login.py:369 msgid "Logout success" msgstr "退出登录成功" -#: authentication/views/login.py:367 +#: authentication/views/login.py:370 msgid "Logout success, return login page" msgstr "退出登录成功,返回到登录页面" @@ -3026,7 +3070,7 @@ msgstr "定时触发" msgid "Ready" msgstr "准备" -#: common/const/choices.py:16 terminal/const.py:59 tickets/const.py:29 +#: common/const/choices.py:16 terminal/const.py:60 tickets/const.py:29 #: tickets/const.py:39 msgid "Pending" msgstr "待定的" @@ -3660,7 +3704,7 @@ msgstr "保存后执行" msgid "Job type" msgstr "任务类型" -#: ops/serializers/job.py:57 terminal/serializers/session.py:50 +#: ops/serializers/job.py:57 terminal/serializers/session.py:47 msgid "Is finished" msgstr "是否完成" @@ -4074,7 +4118,7 @@ msgid "My assets" msgstr "我的资产" #: rbac/tree.py:56 terminal/models/applet/applet.py:51 -#: terminal/models/applet/applet.py:240 terminal/models/applet/host.py:28 +#: terminal/models/applet/applet.py:244 terminal/models/applet/host.py:28 #: terminal/serializers/applet.py:15 msgid "Applet" msgstr "远程应用" @@ -4104,23 +4148,23 @@ msgstr "测试成功" msgid "Test mail sent to {}, please check" msgstr "邮件已经发送{}, 请检查" -#: settings/api/ldap.py:173 +#: settings/api/ldap.py:176 msgid "Synchronization start, please wait." msgstr "同步开始,请稍等" -#: settings/api/ldap.py:177 +#: settings/api/ldap.py:180 msgid "Synchronization is running, please wait." msgstr "同步正在运行,请稍等" -#: settings/api/ldap.py:182 +#: settings/api/ldap.py:185 msgid "Synchronization error: {}" msgstr "同步错误: {}" -#: settings/api/ldap.py:220 +#: settings/api/ldap.py:223 msgid "Get ldap users is None" msgstr "获取 LDAP 用户为 None" -#: settings/api/ldap.py:230 +#: settings/api/ldap.py:233 msgid "Imported {} users successfully (Organization: {})" msgstr "成功导入 {} 个用户 ( 组织: {} )" @@ -5013,10 +5057,6 @@ msgstr "启用登录验证码" msgid "Enable captcha to prevent robot authentication" msgstr "开启验证码,防止机器人登录" -#: settings/serializers/security.py:151 -msgid "Security" -msgstr "安全" - #: settings/serializers/security.py:154 msgid "Enable terminal register" msgstr "终端注册" @@ -5558,7 +5598,7 @@ msgstr "严重" msgid "High" msgstr "较高" -#: terminal/const.py:32 terminal/const.py:66 +#: terminal/const.py:32 terminal/const.py:67 #: users/templates/users/reset_password.html:50 msgid "Normal" msgstr "正常" @@ -5567,19 +5607,19 @@ msgstr "正常" msgid "Offline" msgstr "离线" -#: terminal/const.py:62 +#: terminal/const.py:63 msgid "Mismatch" msgstr "未匹配" -#: terminal/const.py:67 +#: terminal/const.py:68 msgid "Tunnel" msgstr "隧道" -#: terminal/const.py:72 +#: terminal/const.py:73 msgid "Read Only" msgstr "只读" -#: terminal/const.py:73 +#: terminal/const.py:74 msgid "Writable" msgstr "读写" @@ -5635,7 +5675,7 @@ msgstr "只支持自定义平台" msgid "Missing type in platform.yml" msgstr "在 platform.yml 中缺少类型" -#: terminal/models/applet/applet.py:242 terminal/models/applet/host.py:34 +#: terminal/models/applet/applet.py:246 terminal/models/applet/host.py:34 #: terminal/models/applet/host.py:134 msgid "Hosting" msgstr "宿主机" @@ -5704,7 +5744,7 @@ msgstr "端点" msgid "IP group" msgstr "IP 组" -#: terminal/models/component/endpoint.py:103 +#: terminal/models/component/endpoint.py:104 msgid "Endpoint rule" msgstr "端点规则" @@ -5782,39 +5822,39 @@ msgstr "可以上传会话录像" msgid "Can download session replay" msgstr "可以下载会话录像" -#: terminal/models/session/session.py:35 +#: terminal/models/session/session.py:34 msgid "Account id" msgstr "账号 ID" -#: terminal/models/session/session.py:37 terminal/models/session/sharing.py:104 +#: terminal/models/session/session.py:36 terminal/models/session/sharing.py:104 msgid "Login from" msgstr "登录来源" -#: terminal/models/session/session.py:42 +#: terminal/models/session/session.py:41 msgid "Replay" msgstr "回放" -#: terminal/models/session/session.py:46 +#: terminal/models/session/session.py:45 msgid "Date end" msgstr "结束日期" -#: terminal/models/session/session.py:243 +#: terminal/models/session/session.py:240 msgid "Session record" msgstr "会话记录" -#: terminal/models/session/session.py:245 +#: terminal/models/session/session.py:242 msgid "Can monitor session" msgstr "可以监控会话" -#: terminal/models/session/session.py:246 +#: terminal/models/session/session.py:243 msgid "Can share session" msgstr "可以分享会话" -#: terminal/models/session/session.py:247 +#: terminal/models/session/session.py:244 msgid "Can terminate session" msgstr "可以终断会话" -#: terminal/models/session/session.py:248 +#: terminal/models/session/session.py:245 msgid "Can validate session action perm" msgstr "可以验证会话动作权限" @@ -6017,35 +6057,35 @@ msgstr "如果不同端点下的资产 IP 有冲突,使用资产标签实现" msgid "Asset IP" msgstr "资产 IP" -#: terminal/serializers/session.py:25 terminal/serializers/session.py:47 +#: terminal/serializers/session.py:22 terminal/serializers/session.py:44 msgid "Can replay" msgstr "是否可重放" -#: terminal/serializers/session.py:26 terminal/serializers/session.py:48 +#: terminal/serializers/session.py:23 terminal/serializers/session.py:45 msgid "Can join" msgstr "是否可加入" -#: terminal/serializers/session.py:27 terminal/serializers/session.py:51 +#: terminal/serializers/session.py:24 terminal/serializers/session.py:48 msgid "Can terminate" msgstr "是否可中断" -#: terminal/serializers/session.py:43 +#: terminal/serializers/session.py:40 msgid "User ID" msgstr "用户 ID" -#: terminal/serializers/session.py:44 +#: terminal/serializers/session.py:41 msgid "Asset ID" msgstr "资产 ID" -#: terminal/serializers/session.py:45 +#: terminal/serializers/session.py:42 msgid "Login from display" msgstr "登录来源名称" -#: terminal/serializers/session.py:52 +#: terminal/serializers/session.py:49 msgid "Terminal display" msgstr "终端显示" -#: terminal/serializers/session.py:57 +#: terminal/serializers/session.py:54 msgid "Command amount" msgstr "命令数量" @@ -6356,11 +6396,11 @@ msgstr "审批步骤" msgid "Relation snapshot" msgstr "工单快照" -#: tickets/models/ticket/general.py:392 +#: tickets/models/ticket/general.py:398 msgid "Please try again" msgstr "请再次尝试" -#: tickets/models/ticket/general.py:461 +#: tickets/models/ticket/general.py:467 msgid "Super ticket" msgstr "超级工单" @@ -7617,3 +7657,6 @@ msgstr "旗舰版" #: xpack/plugins/license/models.py:86 msgid "Community edition" msgstr "社区版" + +#~ msgid "Please enable cookies and try again." +#~ msgstr "设置你的浏览器支持cookie" From ea07f9e56a240f0835033a2ad5e9023b9d3220c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com> Date: Fri, 30 Jun 2023 15:55:32 +0800 Subject: [PATCH 068/167] =?UTF-8?q?perf:=20=E6=9B=B4=E6=96=B0=20Chrome?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deploy_applet_host/playbook.yml | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/apps/terminal/automations/deploy_applet_host/playbook.yml b/apps/terminal/automations/deploy_applet_host/playbook.yml index 3e63bd175..306e6fe85 100644 --- a/apps/terminal/automations/deploy_applet_host/playbook.yml +++ b/apps/terminal/automations/deploy_applet_host/playbook.yml @@ -157,35 +157,43 @@ script: | pip install -r '{{ ansible_env.TEMP }}\pip_packages\pip_packages\requirements.txt' --no-index --find-links='{{ ansible_env.TEMP }}\pip_packages\pip_packages' - - name: Download chromedriver (Chromium) + - name: Download chromedriver (Chrome) ansible.windows.win_get_url: url: "{{ APPLET_DOWNLOAD_HOST }}/download/applets/chromedriver_win32.zip" dest: "{{ ansible_env.TEMP }}\\chromedriver_win32.zip" validate_certs: "{{ not IGNORE_VERIFY_CERTS }}" - - name: Unzip chromedriver (Chromium) + - name: Unzip chromedriver (Chrome) community.windows.win_unzip: src: "{{ ansible_env.TEMP }}\\chromedriver_win32.zip" dest: C:\Program Files\JumpServer\drivers - - name: Download chromium zip package (Chromium) + - name: Download Chrome zip package (Chrome) ansible.windows.win_get_url: url: "{{ APPLET_DOWNLOAD_HOST }}/download/applets/chrome-win.zip" dest: "{{ ansible_env.TEMP }}\\chrome-win.zip" validate_certs: "{{ not IGNORE_VERIFY_CERTS }}" - - name: Unzip Chromium (Chromium) + - name: Unzip Chrome (Chrome) community.windows.win_unzip: src: "{{ ansible_env.TEMP }}\\chrome-win.zip" - dest: C:\Program Files\Chrome + dest: C:\Program Files\JumpServer\applications - - name: Set chromium and driver on the global system path (Chromium) + - name: Check and Clean global system path (Chrome) ansible.windows.win_path: elements: - 'C:\Program Files\Chrome\chrome-win32' + - 'C:\Program Files\Chrome\chrome-win' + - 'C:\Program Files\chrome-win' + state: absent + + - name: Set Chrome and driver on the global system path (Chrome) + ansible.windows.win_path: + elements: + - 'C:\Program Files\JumpServer\applications\Chrome\Application' - 'C:\Program Files\JumpServer\drivers\chromedriver_win32' - - name: Set Chromium variables disable Google Api (Chromium) + - name: Set Chrome variables disable Google Api (Chrome) ansible.windows.win_environment: level: machine variables: From ce269e315aec25f399e2396d0cc21f6191e689e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com> Date: Fri, 30 Jun 2023 15:58:20 +0800 Subject: [PATCH 069/167] =?UTF-8?q?perf:=20=E6=9B=B4=E6=96=B0=20Python?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../automations/deploy_applet_host/playbook.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/terminal/automations/deploy_applet_host/playbook.yml b/apps/terminal/automations/deploy_applet_host/playbook.yml index 306e6fe85..25f2b7048 100644 --- a/apps/terminal/automations/deploy_applet_host/playbook.yml +++ b/apps/terminal/automations/deploy_applet_host/playbook.yml @@ -65,15 +65,15 @@ - '%USERPROFILE%\AppData\Local\Programs\Tinker\' scope: user - - name: Download python-3.10.8 + - name: Download python-3.10.11 ansible.windows.win_get_url: - url: "{{ APPLET_DOWNLOAD_HOST }}/download/applets/python-3.10.8-amd64.exe" - dest: "{{ ansible_env.TEMP }}\\python-3.10.8-amd64.exe" + url: "{{ APPLET_DOWNLOAD_HOST }}/download/applets/python-3.10.11-amd64.exe" + dest: "{{ ansible_env.TEMP }}\\python-3.10.11-amd64.exe" validate_certs: "{{ not IGNORE_VERIFY_CERTS }}" - - name: Install the python-3.10.8 + - name: Install the python-3.10.11 ansible.windows.win_package: - path: "{{ ansible_env.TEMP }}\\python-3.10.8-amd64.exe" + path: "{{ ansible_env.TEMP }}\\python-3.10.11-amd64.exe" product_id: '{371d0d73-d418-4ffe-b280-58c3e7987525}' arguments: - /quiet From 19de79fadfa09894b743812dc06f9a4f18263759 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 30 Jun 2023 17:35:49 +0800 Subject: [PATCH 070/167] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=20chatgpt=20?= =?UTF-8?q?=E8=B5=84=E4=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset/__init__.py | 1 + apps/assets/api/asset/gpt.py | 16 ++++++ apps/assets/const/category.py | 1 + apps/assets/const/gpt.py | 54 +++++++++++++++++++ apps/assets/const/protocol.py | 16 +++++- apps/assets/const/types.py | 4 +- .../migrations/0120_auto_20230630_1613.py | 39 ++++++++++++++ apps/assets/models/asset/__init__.py | 1 + apps/assets/models/asset/gpt.py | 11 ++++ apps/assets/serializers/asset/__init__.py | 1 + apps/assets/serializers/asset/gpt.py | 15 ++++++ apps/assets/urls/api_urls.py | 1 + 12 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 apps/assets/api/asset/gpt.py create mode 100644 apps/assets/const/gpt.py create mode 100644 apps/assets/migrations/0120_auto_20230630_1613.py create mode 100644 apps/assets/models/asset/gpt.py create mode 100644 apps/assets/serializers/asset/gpt.py diff --git a/apps/assets/api/asset/__init__.py b/apps/assets/api/asset/__init__.py index 0f1d81825..75c314df7 100644 --- a/apps/assets/api/asset/__init__.py +++ b/apps/assets/api/asset/__init__.py @@ -3,6 +3,7 @@ from .cloud import * from .custom import * from .database import * from .device import * +from .gpt import * from .host import * from .permission import * from .web import * diff --git a/apps/assets/api/asset/gpt.py b/apps/assets/api/asset/gpt.py new file mode 100644 index 000000000..ef9953a41 --- /dev/null +++ b/apps/assets/api/asset/gpt.py @@ -0,0 +1,16 @@ +from assets.models import GPT, Asset +from assets.serializers import GPTSerializer + +from .asset import AssetViewSet + +__all__ = ['GPTViewSet'] + + +class GPTViewSet(AssetViewSet): + model = GPT + perm_model = Asset + + def get_serializer_classes(self): + serializer_classes = super().get_serializer_classes() + serializer_classes['default'] = GPTSerializer + return serializer_classes diff --git a/apps/assets/const/category.py b/apps/assets/const/category.py index 8c4d387d8..9ccbb134e 100644 --- a/apps/assets/const/category.py +++ b/apps/assets/const/category.py @@ -12,6 +12,7 @@ class Category(ChoicesMixin, models.TextChoices): DATABASE = 'database', _("Database") CLOUD = 'cloud', _("Cloud service") WEB = 'web', _("Web") + GPT = 'gpt', "GPT" CUSTOM = 'custom', _("Custom type") @classmethod diff --git a/apps/assets/const/gpt.py b/apps/assets/const/gpt.py new file mode 100644 index 000000000..6a51dd3d6 --- /dev/null +++ b/apps/assets/const/gpt.py @@ -0,0 +1,54 @@ +from django.utils.translation import gettext_lazy as _ + +from .base import BaseType + + +class GPTTypes(BaseType): + CHATGPT = 'chatgpt', _('ChatGPT') + + @classmethod + def _get_base_constrains(cls) -> dict: + return { + '*': { + 'charset_enabled': False, + 'domain_enabled': False, + 'su_enabled': False, + } + } + + @classmethod + def _get_automation_constrains(cls) -> dict: + constrains = { + '*': { + 'ansible_enabled': False, + 'ping_enabled': False, + 'gather_facts_enabled': False, + 'verify_account_enabled': False, + 'change_secret_enabled': False, + 'push_account_enabled': False, + 'gather_accounts_enabled': False, + } + } + return constrains + + @classmethod + def _get_protocol_constrains(cls) -> dict: + return { + '*': { + 'choices': ['http'], + } + } + + @classmethod + def internal_platforms(cls): + return { + cls.CHATGPT: [ + {'name': 'ChatGPT'} + ], + } + + @classmethod + def get_community_types(cls): + return [ + cls.CHATGPT, + ] diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index e66dde209..be0dec4f2 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -26,6 +26,8 @@ class Protocol(ChoicesMixin, models.TextChoices): k8s = 'k8s', 'K8S' http = 'http', 'HTTP(s)' + chatgpt = 'chatgpt', 'ChatGPT' + @classmethod def device_protocols(cls): return { @@ -154,7 +156,6 @@ class Protocol(ChoicesMixin, models.TextChoices): cls.http: { 'port': 80, 'secret_types': ['password'], - 'label': 'HTTP(s)', 'setting': { 'autofill': { 'type': 'choice', @@ -180,12 +181,23 @@ class Protocol(ChoicesMixin, models.TextChoices): }, } + @classmethod + def gpt_protocols(cls): + return { + cls.chatgpt: { + 'port': 443, + 'required': True, + 'secret_types': ['token'], + } + } + @classmethod def settings(cls): return { **cls.device_protocols(), **cls.database_protocols(), - **cls.cloud_protocols() + **cls.cloud_protocols(), + **cls.gpt_protocols(), } @classmethod diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py index 1f0156b7f..2ce6082a8 100644 --- a/apps/assets/const/types.py +++ b/apps/assets/const/types.py @@ -10,6 +10,7 @@ from .cloud import CloudTypes from .custom import CustomTypes from .database import DatabaseTypes from .device import DeviceTypes +from .gpt import GPTTypes from .host import HostTypes from .web import WebTypes @@ -18,7 +19,7 @@ class AllTypes(ChoicesMixin): choices: list includes = [ HostTypes, DeviceTypes, DatabaseTypes, - CloudTypes, WebTypes, CustomTypes + CloudTypes, WebTypes, CustomTypes, GPTTypes ] _category_constrains = {} @@ -147,6 +148,7 @@ class AllTypes(ChoicesMixin): (Category.DATABASE, DatabaseTypes), (Category.CLOUD, CloudTypes), (Category.WEB, WebTypes), + (Category.GPT, GPTTypes), (Category.CUSTOM, CustomTypes), ) diff --git a/apps/assets/migrations/0120_auto_20230630_1613.py b/apps/assets/migrations/0120_auto_20230630_1613.py new file mode 100644 index 000000000..aa884a217 --- /dev/null +++ b/apps/assets/migrations/0120_auto_20230630_1613.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.19 on 2023-06-30 08:13 + +import django.db.models.deletion +from django.db import migrations, models + + +def add_chatgpt_platform(apps, schema_editor): + platform_cls = apps.get_model('assets', 'Platform') + automation_cls = apps.get_model('assets', 'PlatformAutomation') + platform = platform_cls.objects.create( + name='ChatGPT', internal=True, category='gpt', type='chatgpt', + domain_enabled=False, su_enabled=False, comment='ChatGPT', + created_by='System', updated_by='System', + ) + platform.protocols.create(name='chatgpt', port=443, primary=True) + automation_cls.objects.create(ansible_enabled=False, platform=platform) + + +class Migration(migrations.Migration): + dependencies = [ + ('assets', '0119_assets_add_default_node'), + ] + + operations = [ + migrations.CreateModel( + name='GPT', + fields=[ + ('asset_ptr', + models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, + primary_key=True, serialize=False, to='assets.asset')), + ('proxy', models.CharField(blank=True, default='', max_length=128, verbose_name='Proxy')), + ], + options={ + 'verbose_name': 'Web', + }, + bases=('assets.asset',), + ), + migrations.RunPython(add_chatgpt_platform) + ] diff --git a/apps/assets/models/asset/__init__.py b/apps/assets/models/asset/__init__.py index 0004bfbb5..7541f2f2e 100644 --- a/apps/assets/models/asset/__init__.py +++ b/apps/assets/models/asset/__init__.py @@ -3,5 +3,6 @@ from .common import * from .custom import * from .database import * from .device import * +from .gpt import * from .host import * from .web import * diff --git a/apps/assets/models/asset/gpt.py b/apps/assets/models/asset/gpt.py new file mode 100644 index 000000000..4522dfe93 --- /dev/null +++ b/apps/assets/models/asset/gpt.py @@ -0,0 +1,11 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from .common import Asset + + +class GPT(Asset): + proxy = models.CharField(max_length=128, blank=True, default='', verbose_name=_("Proxy")) + + class Meta: + verbose_name = _("Web") diff --git a/apps/assets/serializers/asset/__init__.py b/apps/assets/serializers/asset/__init__.py index 8e3e14cf3..481e90863 100644 --- a/apps/assets/serializers/asset/__init__.py +++ b/apps/assets/serializers/asset/__init__.py @@ -4,5 +4,6 @@ from .common import * from .custom import * from .database import * from .device import * +from .gpt import * from .host import * from .web import * diff --git a/apps/assets/serializers/asset/gpt.py b/apps/assets/serializers/asset/gpt.py new file mode 100644 index 000000000..88e28ed60 --- /dev/null +++ b/apps/assets/serializers/asset/gpt.py @@ -0,0 +1,15 @@ +from assets.models import GPT +from .common import AssetSerializer + +__all__ = ['GPTSerializer'] + + +class GPTSerializer(AssetSerializer): + class Meta(AssetSerializer.Meta): + model = GPT + fields = AssetSerializer.Meta.fields + [ + 'proxy', + ] + extra_kwargs = { + **AssetSerializer.Meta.extra_kwargs, + } diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py index 1a1384fdf..983e077f0 100644 --- a/apps/assets/urls/api_urls.py +++ b/apps/assets/urls/api_urls.py @@ -14,6 +14,7 @@ router.register(r'devices', api.DeviceViewSet, 'device') router.register(r'databases', api.DatabaseViewSet, 'database') router.register(r'webs', api.WebViewSet, 'web') router.register(r'clouds', api.CloudViewSet, 'cloud') +router.register(r'gpts', api.GPTViewSet, 'gpt') router.register(r'customs', api.CustomViewSet, 'custom') router.register(r'platforms', api.AssetPlatformViewSet, 'platform') router.register(r'labels', api.LabelViewSet, 'label') From 41e39c96142ef7949c26477b694a6f87442b4a7e Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 30 Jun 2023 18:33:18 +0800 Subject: [PATCH 071/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20chatgpt=20?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/const/account.py | 1 + apps/accounts/migrations/0001_initial.py | 25 +++++++++++++-------- apps/accounts/migrations/0003_automation.py | 16 ++++++++----- apps/assets/const/gpt.py | 2 +- apps/assets/const/protocol.py | 15 ++++++++++++- 5 files changed, 42 insertions(+), 17 deletions(-) diff --git a/apps/accounts/const/account.py b/apps/accounts/const/account.py index 55fa02d80..3d42814f7 100644 --- a/apps/accounts/const/account.py +++ b/apps/accounts/const/account.py @@ -7,6 +7,7 @@ class SecretType(TextChoices): SSH_KEY = 'ssh_key', _('SSH key') ACCESS_KEY = 'access_key', _('Access key') TOKEN = 'token', _('Token') + API_KEY = 'api_key', _("API key") class AliasAccount(TextChoices): diff --git a/apps/accounts/migrations/0001_initial.py b/apps/accounts/migrations/0001_initial.py index b8fe35670..97ae584c4 100644 --- a/apps/accounts/migrations/0001_initial.py +++ b/apps/accounts/migrations/0001_initial.py @@ -1,12 +1,14 @@ # Generated by Django 3.2.14 on 2022-12-28 07:29 +import uuid + +import django.db.models.deletion +import simple_history.models +from django.conf import settings +from django.db import migrations, models + import common.db.encoder import common.db.fields -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import simple_history.models -import uuid class Migration(migrations.Migration): @@ -29,13 +31,16 @@ class Migration(migrations.Migration): ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('connectivity', models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity')), + ('connectivity', + models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', + max_length=16, verbose_name='Connectivity')), ('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')), ('name', models.CharField(max_length=128, verbose_name='Name')), ('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')), ('secret_type', models.CharField( choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')), + ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, + verbose_name='Secret type')), ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), ('privileged', models.BooleanField(default=False, verbose_name='Privileged')), ('is_active', models.BooleanField(default=True, verbose_name='Is active')), @@ -61,7 +66,8 @@ class Migration(migrations.Migration): ('id', models.UUIDField(db_index=True, default=uuid.uuid4)), ('secret_type', models.CharField( choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')), + ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, + verbose_name='Secret type')), ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), ('version', models.IntegerField(default=0, verbose_name='Version')), ('history_id', models.AutoField(primary_key=True, serialize=False)), @@ -96,7 +102,8 @@ class Migration(migrations.Migration): ('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')), ('secret_type', models.CharField( choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')), + ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, + verbose_name='Secret type')), ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), ('privileged', models.BooleanField(default=False, verbose_name='Privileged')), ('is_active', models.BooleanField(default=True, verbose_name='Is active')), diff --git a/apps/accounts/migrations/0003_automation.py b/apps/accounts/migrations/0003_automation.py index 503c766af..a341e18b2 100644 --- a/apps/accounts/migrations/0003_automation.py +++ b/apps/accounts/migrations/0003_automation.py @@ -1,11 +1,13 @@ # Generated by Django 3.2.16 on 2022-12-30 08:08 +import uuid + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + import common.db.encoder import common.db.fields -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid class Migration(migrations.Migration): @@ -53,7 +55,8 @@ class Migration(migrations.Migration): primary_key=True, serialize=False, to='assets.baseautomation')), ('secret_type', models.CharField( choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')), + ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, + verbose_name='Secret type')), ('secret_strategy', models.CharField(choices=[('specific', 'Specific password'), ('random_one', 'All assets use the same random password'), ('random_all', @@ -156,7 +159,8 @@ class Migration(migrations.Migration): primary_key=True, serialize=False, to='assets.baseautomation')), ('secret_type', models.CharField( choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token')], default='password', max_length=16, verbose_name='Secret type')), + ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, + verbose_name='Secret type')), ('secret_strategy', models.CharField(choices=[('specific', 'Specific password'), ('random_one', 'All assets use the same random password'), ('random_all', diff --git a/apps/assets/const/gpt.py b/apps/assets/const/gpt.py index 6a51dd3d6..65d01ee97 100644 --- a/apps/assets/const/gpt.py +++ b/apps/assets/const/gpt.py @@ -35,7 +35,7 @@ class GPTTypes(BaseType): def _get_protocol_constrains(cls) -> dict: return { '*': { - 'choices': ['http'], + 'choices': '__self__', } } diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index be0dec4f2..a0a7c19e9 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -187,7 +187,20 @@ class Protocol(ChoicesMixin, models.TextChoices): cls.chatgpt: { 'port': 443, 'required': True, - 'secret_types': ['token'], + 'secret_types': ['api_key'], + 'setting': { + 'api_mode': { + 'type': 'choice', + 'default': 'gpt-3.5-turbo', + 'label': _('API mode'), + 'choices': [ + ('gpt-3.5-turbo', 'GPT-3.5 Turbo'), + ('gpt-3.5-turbo-16k', 'GPT-3.5 Turbo 16K'), + ('gpt-4', 'GPT-4'), + ('gpt-4-32k', 'GPT-4 32K'), + ] + } + } } } From 6001175629b09c5e639f7fa2afaf6bd7076e9250 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 30 Jun 2023 18:09:39 +0800 Subject: [PATCH 072/167] perf: add xrdp rdp7 port 3390 --- apps/assets/const/host.py | 8 ++- apps/assets/const/protocol.py | 9 +++ .../migrations/0120_auto_20230630_1555.py | 69 +++++++++++++++++++ apps/authentication/api/connection_token.py | 5 +- apps/terminal/connect_methods.py | 8 +++ .../migrations/0064_endpoint_rdp7_port.py | 20 ++++++ apps/terminal/models/component/endpoint.py | 4 ++ apps/terminal/serializers/endpoint.py | 2 +- 8 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 apps/assets/migrations/0120_auto_20230630_1555.py create mode 100644 apps/terminal/migrations/0064_endpoint_rdp7_port.py diff --git a/apps/assets/const/host.py b/apps/assets/const/host.py index afb92a447..60205ff2c 100644 --- a/apps/assets/const/host.py +++ b/apps/assets/const/host.py @@ -33,10 +33,10 @@ class HostTypes(BaseType): def _get_protocol_constrains(cls) -> dict: return { '*': { - 'choices': ['ssh', 'telnet', 'vnc', 'rdp'] + 'choices': ['ssh', 'telnet', 'vnc', 'rdp', 'rdp7'] }, cls.WINDOWS: { - 'choices': ['rdp', 'ssh', 'vnc', 'winrm'] + 'choices': ['rdp', 'rdp7', 'ssh', 'vnc', 'winrm'] } } @@ -116,6 +116,10 @@ class HostTypes(BaseType): 'required': True } } + }, + { + 'name': 'Windows-RDP7', + '_protocols': ['rdp7',], } ] } diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index e66dde209..e0c6ad25e 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -10,6 +10,7 @@ __all__ = ['Protocol'] class Protocol(ChoicesMixin, models.TextChoices): ssh = 'ssh', 'SSH' rdp = 'rdp', 'RDP' + rdp7 = 'rdp7', 'RDP7' telnet = 'telnet', 'Telnet' vnc = 'vnc', 'VNC' winrm = 'winrm', 'WinRM' @@ -69,6 +70,14 @@ class Protocol(ChoicesMixin, models.TextChoices): # } } }, + cls.rdp7: { + 'port': 3390, + 'secret_types': ['password'], + 'setting': { + 'console': False, + 'security': 'any', + } + }, cls.vnc: { 'port': 5900, 'secret_types': ['password'], diff --git a/apps/assets/migrations/0120_auto_20230630_1555.py b/apps/assets/migrations/0120_auto_20230630_1555.py new file mode 100644 index 000000000..6c303fdd7 --- /dev/null +++ b/apps/assets/migrations/0120_auto_20230630_1555.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.17 on 2023-06-30 07:55 + +import json + +from django.db import migrations + +platform_json_data = """{ + "category": "host", + "type": "windows", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "Windows-RDP7", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_shell_type": "cmd", + "ansible_connection": "ssh" + }, + "ping_enabled": true, + "gather_facts_enabled": true, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "win_ping", + "gather_facts_method": "gather_facts_windows", + "gather_accounts_method": "gather_accounts_windows", + "verify_account_method": "verify_account_windows", + "change_secret_method": "change_secret_local_windows", + "push_account_method": "push_account_local_windows" + }, + "protocols": [ + { + "name": "rdp7", + "port": 3390, + "setting": { + "console": false, + "security": "any" + }, + "primary": true, + "required": false, + "default": false + } + ] +}""" + + +def create_rdp7_internal_platform(apps, *args): + platform_cls = apps.get_model('assets', 'Platform') + platform_automation_cls = apps.get_model('assets', 'PlatformAutomation') + platform_data = json.loads(platform_json_data) + protocols = platform_data.pop('protocols') + automation_data = platform_data.pop('automation', {}) + rdp7_obj = platform_cls.objects.create(**platform_data) + for p in protocols: + rdp7_obj.protocols.create(**p) + platform_automation_cls.objects.create(platform=rdp7_obj, **automation_data) + + +class Migration(migrations.Migration): + dependencies = [ + ('assets', '0119_assets_add_default_node'), + ] + + operations = [ + migrations.RunPython(create_rdp7_internal_platform), + ] diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 23344c9fb..149ecc791 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -75,8 +75,9 @@ class RDPFileClientProtocolURLMixin: rdp_options['screen mode id:i'] = '2' if full_screen else '1' # 设置 RDP Server 地址 - endpoint = self.get_smart_endpoint(protocol='rdp', asset=token.asset) - rdp_options['full address:s'] = f'{endpoint.host}:{endpoint.rdp_port}' + endpoint = self.get_smart_endpoint(protocol=token.protocol, asset=token.asset) + protocol_port = endpoint.get_protocol_port(token.protocol, 3389) + rdp_options['full address:s'] = f'{endpoint.host}:{protocol_port}' # 设置用户名 rdp_options['username:s'] = '{}|{}'.format(token.user.username, str(token.id)) diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index a4901b93c..c3446a630 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -22,6 +22,7 @@ class WebMethod(TextChoices): Protocol.ssh: [cls.web_cli, cls.web_sftp], Protocol.telnet: [cls.web_cli], Protocol.rdp: [cls.web_gui], + Protocol.rdp7: [cls.web_gui], Protocol.vnc: [cls.web_gui], Protocol.mysql: [cls.web_cli], @@ -67,6 +68,7 @@ class NativeClient(TextChoices): 'windows': [cls.putty], }, Protocol.rdp: [cls.mstsc], + Protocol.rdp7: [cls.mstsc], Protocol.mysql: [cls.db_client], Protocol.mariadb: [cls.db_client], Protocol.redis: [cls.db_client], @@ -214,6 +216,12 @@ class ConnectMethodUtil: 'support': [Protocol.rdp], 'match': 'map' }, + TerminalType.xrdp: { + 'web_methods': [], + 'listen': [Protocol.rdp7], + 'support': [Protocol.rdp7], + 'match': 'map' + }, } return protocols diff --git a/apps/terminal/migrations/0064_endpoint_rdp7_port.py b/apps/terminal/migrations/0064_endpoint_rdp7_port.py new file mode 100644 index 000000000..d76719287 --- /dev/null +++ b/apps/terminal/migrations/0064_endpoint_rdp7_port.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.17 on 2023-06-30 09:04 + +import common.db.fields +import django.core.validators +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('terminal', '0063_auto_20230621_1133'), + ] + + operations = [ + migrations.AddField( + model_name='endpoint', + name='rdp7_port', + field=common.db.fields.PortField(default=3390, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='RDP7 port'), + ), + ] diff --git a/apps/terminal/models/component/endpoint.py b/apps/terminal/models/component/endpoint.py index f19f72949..1295e3efd 100644 --- a/apps/terminal/models/component/endpoint.py +++ b/apps/terminal/models/component/endpoint.py @@ -16,6 +16,7 @@ class Endpoint(JMSBaseModel): http_port = PortField(default=80, verbose_name=_('HTTP port')) ssh_port = PortField(default=2222, verbose_name=_('SSH port')) rdp_port = PortField(default=3389, verbose_name=_('RDP port')) + rdp7_port = PortField(default=3390, verbose_name=_('RDP7 port')) mysql_port = PortField(default=33061, verbose_name=_('MySQL port')) mariadb_port = PortField(default=33062, verbose_name=_('MariaDB port')) postgresql_port = PortField(default=54320, verbose_name=_('PostgreSQL port')) @@ -42,6 +43,9 @@ class Endpoint(JMSBaseModel): port = getattr(self, f'{protocol}_port', 0) return port + def get_protocol_port(self, protocol, default=0): + return getattr(self, f'{protocol}_port', default) + def is_default(self): return str(self.id) == self.default_id diff --git a/apps/terminal/serializers/endpoint.py b/apps/terminal/serializers/endpoint.py index 82de09fce..aafd68aca 100644 --- a/apps/terminal/serializers/endpoint.py +++ b/apps/terminal/serializers/endpoint.py @@ -26,7 +26,7 @@ class EndpointSerializer(BulkModelSerializer): model = Endpoint fields_mini = ['id', 'name'] fields_small = [ - 'host', 'https_port', 'http_port', 'ssh_port', 'rdp_port', + 'host', 'https_port', 'http_port', 'ssh_port', 'rdp_port', 'rdp7_port', 'mysql_port', 'mariadb_port', 'postgresql_port', 'redis_port', 'oracle_port_range', 'oracle_port', ] From 125dc2adf510e37bde1d1b68b99c525b80915adb Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 30 Jun 2023 18:25:58 +0800 Subject: [PATCH 073/167] =?UTF-8?q?perf:=20=E9=92=88=E5=AF=B9=20rdp7=20?= =?UTF-8?q?=E7=AB=AF=E5=8F=A3=E7=89=B9=E6=AE=8A=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/connection_token.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 149ecc791..ea00cfec6 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -76,7 +76,8 @@ class RDPFileClientProtocolURLMixin: # 设置 RDP Server 地址 endpoint = self.get_smart_endpoint(protocol=token.protocol, asset=token.asset) - protocol_port = endpoint.get_protocol_port(token.protocol, 3389) + # 由于 remoteapp 使用 mstsc 客户端连接的时候,都是 rdp 端口, 这里特殊判断 rdp7 端口 + protocol_port = endpoint.rdp7_port if token.protocol == 'rdp7' else endpoint.rdp_port rdp_options['full address:s'] = f'{endpoint.host}:{protocol_port}' # 设置用户名 From 411102ed85a2275b7ba86e8151718ab6fcb82491 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 30 Jun 2023 18:40:43 +0800 Subject: [PATCH 074/167] =?UTF-8?q?perf:=20=E5=AE=8C=E5=96=84=20protocol?= =?UTF-8?q?=20=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/connection_token.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index ea00cfec6..c779540a1 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -75,9 +75,10 @@ class RDPFileClientProtocolURLMixin: rdp_options['screen mode id:i'] = '2' if full_screen else '1' # 设置 RDP Server 地址 - endpoint = self.get_smart_endpoint(protocol=token.protocol, asset=token.asset) + protocol = 'rdp7' if token.protocol == 'rdp7' else 'rdp' + endpoint = self.get_smart_endpoint(protocol=protocol, asset=token.asset) # 由于 remoteapp 使用 mstsc 客户端连接的时候,都是 rdp 端口, 这里特殊判断 rdp7 端口 - protocol_port = endpoint.rdp7_port if token.protocol == 'rdp7' else endpoint.rdp_port + protocol_port = endpoint.get_protocol_port(protocol, default=3389) rdp_options['full address:s'] = f'{endpoint.host}:{protocol_port}' # 设置用户名 From 2f81196874882f3a6dae5fda6dc0293768d756ad Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 3 Jul 2023 10:22:49 +0800 Subject: [PATCH 075/167] =?UTF-8?q?perf:=20=E6=9B=B4=E6=96=B0=20rdp7=20pro?= =?UTF-8?q?tocol=20=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/const/protocol.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index e0c6ad25e..6779aabc4 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -74,8 +74,19 @@ class Protocol(ChoicesMixin, models.TextChoices): 'port': 3390, 'secret_types': ['password'], 'setting': { - 'console': False, - 'security': 'any', + 'console': { + 'type': 'bool', + 'default': False, + 'label': _('Console'), + 'help_text': _("Connect to console session") + }, + 'security': { + 'type': 'choice', + 'choices': [('any', _('Any')), ('rdp', 'RDP'), ('tls', 'TLS'), ('nla', 'NLA')], + 'default': 'any', + 'label': _('Security'), + 'help_text': _("Security layer to use for the connection") + }, } }, cls.vnc: { From 3971fce561c23ed3f15ce108434eb474f423a4cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com> Date: Mon, 3 Jul 2023 10:28:25 +0800 Subject: [PATCH 076/167] =?UTF-8?q?feat:=20=E5=90=88=E5=B9=B6=20Dockerfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 31 +++++++++------ Dockerfile.loong64 | 97 ---------------------------------------------- 2 files changed, 20 insertions(+), 108 deletions(-) delete mode 100644 Dockerfile.loong64 diff --git a/Dockerfile b/Dockerfile index 2183c7b36..5a6c5451d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9-slim-bullseye as stage-build +FROM jumpserver/python:3.9-slim-buster as stage-build ARG TARGETARCH ARG VERSION @@ -8,7 +8,7 @@ WORKDIR /opt/jumpserver ADD . . RUN cd utils && bash -ixeu build.sh -FROM python:3.9-slim-bullseye +FROM jumpserver/python:3.9-slim-buster ARG TARGETARCH MAINTAINER JumpServer Team @@ -24,6 +24,7 @@ ARG DEPENDENCIES=" \ libjpeg-dev \ libldap2-dev \ libsasl2-dev \ + libssl-dev \ libxml2-dev \ libxmlsec1-dev \ libxmlsec1-openssl \ @@ -66,27 +67,35 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \ ARG DOWNLOAD_URL=https://download.jumpserver.org -RUN mkdir -p /opt/oracle/ \ - && cd /opt/oracle/ \ - && wget ${DOWNLOAD_URL}/public/instantclient-basiclite-linux.${TARGETARCH}-19.10.0.0.0.zip \ - && unzip instantclient-basiclite-linux.${TARGETARCH}-19.10.0.0.0.zip \ - && sh -c "echo /opt/oracle/instantclient_19_10 > /etc/ld.so.conf.d/oracle-instantclient.conf" \ - && ldconfig \ - && rm -f instantclient-basiclite-linux.${TARGETARCH}-19.10.0.0.0.zip +RUN set -ex \ + && \ + if [ "${TARGETARCH}" == "amd64" ] || [ "${TARGETARCH}" == "arm64" ]; then \ + mkdir -p /opt/oracle; \ + wget ${DOWNLOAD_URL}/public/instantclient-basiclite-linux.${TARGETARCH}-19.10.0.0.0.zip; \ + unzip instantclient-basiclite-linux.${TARGETARCH}-19.10.0.0.0.zip; \ + echo "/opt/oracle/instantclient_19_10" > /etc/ld.so.conf.d/oracle-instantclient.conf; \ + ldconfig; \ + rm -f instantclient-basiclite-linux.${TARGETARCH}-19.10.0.0.0.zip; \ + fi WORKDIR /tmp/build COPY ./requirements ./requirements ARG PIP_MIRROR=https://pypi.douban.com/simple -ENV PIP_MIRROR=$PIP_MIRROR ARG PIP_JMS_MIRROR=https://pypi.douban.com/simple -ENV PIP_JMS_MIRROR=$PIP_JMS_MIRROR RUN --mount=type=cache,target=/root/.cache/pip \ set -ex \ && pip config set global.index-url ${PIP_MIRROR} \ && pip install --upgrade pip \ && pip install --upgrade setuptools wheel \ + && \ + if [ "${TARGETARCH}" == "loong64" ]; then \ + pip install https://download.jumpserver.org/pypi/simple/cryptography/cryptography-38.0.4-cp39-cp39-linux_loongarch64.whl; \ + pip install https://download.jumpserver.org/pypi/simple/greenlet/greenlet-1.1.2-cp39-cp39-linux_loongarch64.whl; \ + pip install https://download.jumpserver.org/pypi/simple/PyNaCl/PyNaCl-1.5.0-cp39-cp39-linux_loongarch64.whl; \ + pip install https://download.jumpserver.org/pypi/simple/grpcio/grpcio-1.54.2-cp39-cp39-linux_loongarch64.whl; \ + fi \ && pip install $(grep -E 'jms|jumpserver' requirements/requirements.txt) -i ${PIP_JMS_MIRROR} \ && pip install -r requirements/requirements.txt diff --git a/Dockerfile.loong64 b/Dockerfile.loong64 deleted file mode 100644 index f5682aec2..000000000 --- a/Dockerfile.loong64 +++ /dev/null @@ -1,97 +0,0 @@ -FROM python:3.9-slim-buster as stage-build -ARG TARGETARCH - -ARG VERSION -ENV VERSION=$VERSION - -WORKDIR /opt/jumpserver -ADD . . -RUN cd utils && bash -ixeu build.sh - -FROM python:3.9-slim-buster -ARG TARGETARCH -MAINTAINER JumpServer Team - -ARG BUILD_DEPENDENCIES=" \ - g++ \ - make \ - pkg-config" - -ARG DEPENDENCIES=" \ - freetds-dev \ - libpq-dev \ - libffi-dev \ - libjpeg-dev \ - libldap2-dev \ - libsasl2-dev \ - libssl-dev \ - libxml2-dev \ - libxmlsec1-dev \ - libxmlsec1-openssl \ - freerdp2-dev \ - libaio-dev" - -ARG TOOLS=" \ - ca-certificates \ - curl \ - default-libmysqlclient-dev \ - default-mysql-client \ - locales \ - openssh-client \ - procps \ - sshpass \ - telnet \ - unzip \ - vim \ - git \ - wget" - -RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \ - set -ex \ - && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ - && apt-get update \ - && apt-get -y install --no-install-recommends ${BUILD_DEPENDENCIES} \ - && apt-get -y install --no-install-recommends ${DEPENDENCIES} \ - && apt-get -y install --no-install-recommends ${TOOLS} \ - && mkdir -p /root/.ssh/ \ - && echo "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null\n\tCiphers +aes128-cbc\n\tKexAlgorithms +diffie-hellman-group1-sha1\n\tHostKeyAlgorithms +ssh-rsa" > /root/.ssh/config \ - && echo "set mouse-=a" > ~/.vimrc \ - && echo "no" | dpkg-reconfigure dash \ - && echo "zh_CN.UTF-8" | dpkg-reconfigure locales \ - && sed -i "s@# export @export @g" ~/.bashrc \ - && sed -i "s@# alias @alias @g" ~/.bashrc \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /tmp/build -COPY ./requirements ./requirements - -ARG PIP_MIRROR=https://pypi.douban.com/simple -ENV PIP_MIRROR=$PIP_MIRROR -ARG PIP_JMS_MIRROR=https://pypi.douban.com/simple -ENV PIP_JMS_MIRROR=$PIP_JMS_MIRROR - -RUN --mount=type=cache,target=/root/.cache/pip \ - set -ex \ - && pip config set global.index-url ${PIP_MIRROR} \ - && pip install --upgrade pip \ - && pip install --upgrade setuptools wheel \ - && pip install https://download.jumpserver.org/pypi/simple/cryptography/cryptography-38.0.4-cp39-cp39-linux_loongarch64.whl \ - && pip install https://download.jumpserver.org/pypi/simple/greenlet/greenlet-1.1.2-cp39-cp39-linux_loongarch64.whl \ - && pip install https://download.jumpserver.org/pypi/simple/PyNaCl/PyNaCl-1.5.0-cp39-cp39-linux_loongarch64.whl \ - && pip install https://download.jumpserver.org/pypi/simple/grpcio/grpcio-1.54.2-cp39-cp39-linux_loongarch64.whl \ - && pip install $(grep -E 'jms|jumpserver' requirements/requirements.txt) -i ${PIP_JMS_MIRROR} \ - && pip install -r requirements/requirements.txt - -COPY --from=stage-build /opt/jumpserver/release/jumpserver /opt/jumpserver -RUN echo > /opt/jumpserver/config.yml \ - && rm -rf /tmp/build - -WORKDIR /opt/jumpserver -VOLUME /opt/jumpserver/data -VOLUME /opt/jumpserver/logs - -ENV LANG=zh_CN.UTF-8 - -EXPOSE 8080 - -ENTRYPOINT ["./entrypoint.sh"] From eb49beaf468829fafe9aab4d9ee3ee59c7f44cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com> Date: Mon, 3 Jul 2023 10:37:42 +0800 Subject: [PATCH 077/167] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3=20oracle=20?= =?UTF-8?q?=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 5a6c5451d..d8fd27492 100644 --- a/Dockerfile +++ b/Dockerfile @@ -71,6 +71,7 @@ RUN set -ex \ && \ if [ "${TARGETARCH}" == "amd64" ] || [ "${TARGETARCH}" == "arm64" ]; then \ mkdir -p /opt/oracle; \ + cd /opt/oracle; \ wget ${DOWNLOAD_URL}/public/instantclient-basiclite-linux.${TARGETARCH}-19.10.0.0.0.zip; \ unzip instantclient-basiclite-linux.${TARGETARCH}-19.10.0.0.0.zip; \ echo "/opt/oracle/instantclient_19_10" > /etc/ld.so.conf.d/oracle-instantclient.conf; \ From d7f9f3b6706046bcbec931cc016b65ae29eb4123 Mon Sep 17 00:00:00 2001 From: Eric Date: Mon, 3 Jul 2023 19:19:20 +0800 Subject: [PATCH 078/167] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=20Connection?= =?UTF-8?q?Token=20=E4=B8=AD=20account=20id=20=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/models/connection_token.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py index acef092b1..b721cb982 100644 --- a/apps/authentication/models/connection_token.py +++ b/apps/authentication/models/connection_token.py @@ -222,6 +222,7 @@ class ConnectionToken(JMSOrgBaseModel): } else: data = { + 'id': account.id, 'name': account.name, 'username': account.username, 'secret_type': account.secret_type, From 8dbe61100b920f84f95435d9efd192abf2e5286b Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 4 Jul 2023 10:29:27 +0800 Subject: [PATCH 079/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=EF=BC=8C=E6=94=AF=E6=8C=81=20port=20from=20addr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/const/base.py | 2 +- apps/assets/const/protocol.py | 5 +++++ apps/assets/models/platform.py | 7 +++++++ apps/assets/serializers/platform.py | 6 +++--- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/assets/const/base.py b/apps/assets/const/base.py index 5aea334d4..6dc172c0e 100644 --- a/apps/assets/const/base.py +++ b/apps/assets/const/base.py @@ -56,7 +56,7 @@ class BaseType(TextChoices): for k, v in cls.get_choices(): tp_base = {**base_default, **base.get(k, {})} tp_auto = {**automation_default, **automation.get(k, {})} - tp_protocols = {**protocols_default, **protocols.get(k, {})} + tp_protocols = {**protocols_default, **{'port_from_addr': False}, **protocols.get(k, {})} tp_protocols = cls._parse_protocols(tp_protocols, k) tp_constrains = {**tp_base, 'protocols': tp_protocols, 'automation': tp_auto} constrains[k] = tp_constrains diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index a0a7c19e9..d20fd02c7 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -2,6 +2,7 @@ from django.db import models from django.utils.translation import gettext_lazy as _ from common.db.models import ChoicesMixin +from common.decorators import cached_method from .base import FillType __all__ = ['Protocol'] @@ -150,11 +151,13 @@ class Protocol(ChoicesMixin, models.TextChoices): return { cls.k8s: { 'port': 443, + 'port_from_addr': True, 'required': True, 'secret_types': ['token'], }, cls.http: { 'port': 80, + 'port_from_addr': True, 'secret_types': ['password'], 'setting': { 'autofill': { @@ -187,6 +190,7 @@ class Protocol(ChoicesMixin, models.TextChoices): cls.chatgpt: { 'port': 443, 'required': True, + 'port_from_addr': True, 'secret_types': ['api_key'], 'setting': { 'api_mode': { @@ -205,6 +209,7 @@ class Protocol(ChoicesMixin, models.TextChoices): } @classmethod + @cached_method(ttl=600) def settings(cls): return { **cls.device_protocols(), diff --git a/apps/assets/models/platform.py b/apps/assets/models/platform.py index f50177642..8fed01acf 100644 --- a/apps/assets/models/platform.py +++ b/apps/assets/models/platform.py @@ -8,6 +8,8 @@ from common.db.models import JMSBaseModel __all__ = ['Platform', 'PlatformProtocol', 'PlatformAutomation'] +from common.utils import lazyproperty + class PlatformProtocol(models.Model): name = models.CharField(max_length=32, verbose_name=_('Name')) @@ -26,6 +28,11 @@ class PlatformProtocol(models.Model): def secret_types(self): return Protocol.settings().get(self.name, {}).get('secret_types', ['password']) + @lazyproperty + def port_from_addr(self): + from assets.const.protocol import Protocol as ProtocolConst + return ProtocolConst.settings().get(self.name, {}).get('port_from_addr', False) + class PlatformAutomation(models.Model): ansible_enabled = models.BooleanField(default=False, verbose_name=_("Enabled")) diff --git a/apps/assets/serializers/platform.py b/apps/assets/serializers/platform.py index 1915adcdb..8101bde23 100644 --- a/apps/assets/serializers/platform.py +++ b/apps/assets/serializers/platform.py @@ -46,13 +46,13 @@ class PlatformAutomationSerializer(serializers.ModelSerializer): class PlatformProtocolSerializer(serializers.ModelSerializer): setting = MethodSerializer(required=False, label=_("Setting")) + port_from_addr = serializers.BooleanField(label=_("Port from addr"), read_only=True) class Meta: model = PlatformProtocol fields = [ - "id", "name", "port", "primary", - "required", "default", "public", - "secret_types", "setting", + "id", "name", "port", "port_from_addr", "primary", + "required", "default", "public", "secret_types", "setting", ] extra_kwargs = { "primary": { From 02550b38f897b2c7a155a6c18c257a4171ac9008 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 4 Jul 2023 12:52:36 +0800 Subject: [PATCH 080/167] =?UTF-8?q?perf:=20rdp7=20=E5=8F=AF=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20web=20gui=E6=96=B9=E5=BC=8F=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/connect_methods.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index c3446a630..f76b2b056 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -197,7 +197,7 @@ class ConnectMethodUtil: TerminalType.lion: { 'web_methods': [WebMethod.web_gui], 'listen': [Protocol.http], - 'support': [Protocol.rdp, Protocol.vnc], + 'support': [Protocol.rdp, Protocol.rdp7, Protocol.vnc], 'match': 'm2m' }, TerminalType.magnus: { From f095998096862bbce035ca9a6920bacba594befd Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:34:31 +0800 Subject: [PATCH 081/167] =?UTF-8?q?perf:=20=E6=94=B9=E5=AF=86=E4=B8=8E?= =?UTF-8?q?=E6=8E=A8=E9=80=81=E4=BF=9D=E6=8C=81=E4=B8=80=E8=87=B4=20(#1081?= =?UTF-8?q?2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf: 改密与推送保持一致 * perf: 增加 i18n --------- Co-authored-by: feng <1304903146@qq.com> Co-authored-by: Bai --- .../change_secret/host/aix/manifest.yml | 55 +++++++++++++++++- .../change_secret/host/posix/main.yml | 30 ++++++++++ .../change_secret/host/posix/manifest.yml | 56 ++++++++++++++++++- .../change_secret/host/windows/main.yml | 10 +--- .../change_secret/host/windows/manifest.yml | 19 ++++++- .../serializers/automations/change_secret.py | 2 +- .../serializers/automations/push_account.py | 2 +- 7 files changed, 156 insertions(+), 18 deletions(-) diff --git a/apps/accounts/automations/change_secret/host/aix/manifest.yml b/apps/accounts/automations/change_secret/host/aix/manifest.yml index e84a9b42b..a3df14a4d 100644 --- a/apps/accounts/automations/change_secret/host/aix/manifest.yml +++ b/apps/accounts/automations/change_secret/host/aix/manifest.yml @@ -4,9 +4,58 @@ category: host type: - AIX method: change_secret +params: + - name: sudo + type: str + label: 'Sudo' + default: '/bin/whoami' + help_text: "{{ 'Params sudo help text' | trans }}" + + - name: shell + type: str + label: 'Shell' + default: '/bin/bash' + + - name: home + type: str + label: "{{ 'Params home label' | trans }}" + default: '' + help_text: "{{ 'Params home help text' | trans }}" + + - name: groups + type: str + label: "{{ 'Params groups label' | trans }}" + default: '' + help_text: "{{ 'Params groups help text' | trans }}" i18n: AIX account change secret: - zh: 使用 Ansible 模块 user 执行账号改密 (DES) - ja: Ansible user モジュールを使用してアカウントのパスワード変更 (DES) - en: Using Ansible module user to change account secret (DES) + zh: '使用 Ansible 模块 user 执行账号改密 (DES)' + ja: 'Ansible user モジュールを使用してアカウントのパスワード変更 (DES)' + en: 'Using Ansible module user to change account secret (DES)' + + Params sudo help text: + zh: '使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig' + ja: 'コンマで区切って複数のコマンドを入力してください。例: /bin/whoami,/sbin/ifconfig' + en: 'Use commas to separate multiple commands, such as: /bin/whoami,/sbin/ifconfig' + + Params home help text: + zh: '默认家目录 /home/{账号用户名}' + ja: 'デフォルトのホームディレクトリ /home/{アカウントユーザ名}' + en: 'Default home directory /home/{account username}' + + Params groups help text: + zh: '请输入用户组,多个用户组使用逗号分隔(需填写已存在的用户组)' + ja: 'グループを入力してください。複数のグループはコンマで区切ってください(既存のグループを入力してください)' + en: 'Please enter the group. Multiple groups are separated by commas (please enter the existing group)' + + Params home label: + zh: '家目录' + ja: 'ホームディレクトリ' + en: 'Home' + + Params groups label: + zh: '用户组' + ja: 'グループ' + en: 'Groups' + diff --git a/apps/accounts/automations/change_secret/host/posix/main.yml b/apps/accounts/automations/change_secret/host/posix/main.yml index 80f0aa01c..325ad644d 100644 --- a/apps/accounts/automations/change_secret/host/posix/main.yml +++ b/apps/accounts/automations/change_secret/host/posix/main.yml @@ -4,6 +4,26 @@ - name: Test privileged account ansible.builtin.ping: + - name: Check user + ansible.builtin.user: + name: "{{ account.username }}" + shell: "{{ params.shell }}" + home: "{{ params.home | default('/home/' + account.username, true) }}" + groups: "{{ params.groups }}" + expires: -1 + state: present + + - name: "Add {{ account.username }} group" + ansible.builtin.group: + name: "{{ account.username }}" + state: present + + - name: Add user groups + ansible.builtin.user: + name: "{{ account.username }}" + groups: "{{ params.groups }}" + when: params.groups + - name: Change password ansible.builtin.user: name: "{{ account.username }}" @@ -33,6 +53,16 @@ exclusive: "{{ ssh_params.exclusive }}" when: account.secret_type == "ssh_key" + - name: Set sudo setting + ansible.builtin.lineinfile: + dest: /etc/sudoers + state: present + regexp: "^{{ account.username }} ALL=" + line: "{{ account.username + ' ALL=(ALL) NOPASSWD: ' + params.sudo }}" + validate: visudo -cf %s + when: + - params.sudo + - name: Refresh connection ansible.builtin.meta: reset_connection diff --git a/apps/accounts/automations/change_secret/host/posix/manifest.yml b/apps/accounts/automations/change_secret/host/posix/manifest.yml index 6aa1bba10..43d1ca5fd 100644 --- a/apps/accounts/automations/change_secret/host/posix/manifest.yml +++ b/apps/accounts/automations/change_secret/host/posix/manifest.yml @@ -5,9 +5,59 @@ type: - unix - linux method: change_secret +params: + - name: sudo + type: str + label: 'Sudo' + default: '/bin/whoami' + help_text: "{{ 'Params sudo help text' | trans }}" + + - name: shell + type: str + label: 'Shell' + default: '/bin/bash' + help_text: '' + + - name: home + type: str + label: "{{ 'Params home label' | trans }}" + default: '' + help_text: "{{ 'Params home help text' | trans }}" + + - name: groups + type: str + label: "{{ 'Params groups label' | trans }}" + default: '' + help_text: "{{ 'Params groups help text' | trans }}" i18n: Posix account change secret: - zh: 使用 Ansible 模块 user 执行账号改密 (SHA512) - ja: Ansible user モジュールを使用して アカウントのパスワード変更 (SHA512) - en: Using Ansible module user to change account secret (SHA512) + zh: '使用 Ansible 模块 user 执行账号改密 (SHA512)' + ja: 'Ansible user モジュールを使用して アカウントのパスワード変更 (SHA512)' + en: 'Using Ansible module user to change account secret (SHA512)' + + Params sudo help text: + zh: '使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig' + ja: 'コンマで区切って複数のコマンドを入力してください。例: /bin/whoami,/sbin/ifconfig' + en: 'Use commas to separate multiple commands, such as: /bin/whoami,/sbin/ifconfig' + + Params home help text: + zh: '默认家目录 /home/{账号用户名}' + ja: 'デフォルトのホームディレクトリ /home/{アカウントユーザ名}' + en: 'Default home directory /home/{account username}' + + Params groups help text: + zh: '请输入用户组,多个用户组使用逗号分隔(需填写已存在的用户组)' + ja: 'グループを入力してください。複数のグループはコンマで区切ってください(既存のグループを入力してください)' + en: 'Please enter the group. Multiple groups are separated by commas (please enter the existing group)' + + Params home label: + zh: '家目录' + ja: 'ホームディレクトリ' + en: 'Home' + + Params groups label: + zh: '用户组' + ja: 'グループ' + en: 'Groups' + diff --git a/apps/accounts/automations/change_secret/host/windows/main.yml b/apps/accounts/automations/change_secret/host/windows/main.yml index 86ea7a81f..a97166fef 100644 --- a/apps/accounts/automations/change_secret/host/windows/main.yml +++ b/apps/accounts/automations/change_secret/host/windows/main.yml @@ -8,17 +8,13 @@ # debug: # msg: "Username: {{ account.username }}, Password: {{ account.secret }}" - - - name: Get groups of a Windows user - ansible.windows.win_user: - name: "{{ jms_account.username }}" - register: user_info - - name: Change password ansible.windows.win_user: + fullname: "{{ account.username}}" name: "{{ account.username }}" password: "{{ account.secret }}" - groups: "{{ user_info.groups[0].name }}" + password_never_expires: yes + groups: "{{ params.groups }}" groups_action: add update_password: always ignore_errors: true diff --git a/apps/accounts/automations/change_secret/host/windows/manifest.yml b/apps/accounts/automations/change_secret/host/windows/manifest.yml index 4480a9ecf..884168974 100644 --- a/apps/accounts/automations/change_secret/host/windows/manifest.yml +++ b/apps/accounts/automations/change_secret/host/windows/manifest.yml @@ -5,9 +5,22 @@ method: change_secret category: host type: - windows +params: + - name: groups + type: str + label: '用户组' + default: 'Users,Remote Desktop Users' + help_text: "{{ 'Params groups help text' | trans }}" + i18n: Windows account change secret: - zh: 使用 Ansible 模块 win_user 执行 Windows 账号改密 - ja: Ansible win_user モジュールを使用して Windows アカウントのパスワード変更 - en: Using Ansible module win_user to change Windows account secret + zh: '使用 Ansible 模块 win_user 执行 Windows 账号改密' + ja: 'Ansible win_user モジュールを使用して Windows アカウントのパスワード変更' + en: 'Using Ansible module win_user to change Windows account secret' + + Params groups help text: + zh: '请输入用户组,多个用户组使用逗号分隔(需填写已存在的用户组)' + ja: 'グループを入力してください。複数のグループはコンマで区切ってください(既存のグループを入力してください)' + en: 'Please enter the group. Multiple groups are separated by commas (please enter the existing group)' + diff --git a/apps/accounts/serializers/automations/change_secret.py b/apps/accounts/serializers/automations/change_secret.py index 94a7dc428..3c6e11205 100644 --- a/apps/accounts/serializers/automations/change_secret.py +++ b/apps/accounts/serializers/automations/change_secret.py @@ -50,7 +50,7 @@ class ChangeSecretAutomationSerializer(AuthValidateMixin, BaseAutomationSerializ read_only_fields = BaseAutomationSerializer.Meta.read_only_fields fields = BaseAutomationSerializer.Meta.fields + read_only_fields + [ 'secret_type', 'secret_strategy', 'secret', 'password_rules', - 'ssh_key_change_strategy', 'passphrase', 'recipients', + 'ssh_key_change_strategy', 'passphrase', 'recipients', 'params' ] extra_kwargs = {**BaseAutomationSerializer.Meta.extra_kwargs, **{ 'accounts': {'required': True}, diff --git a/apps/accounts/serializers/automations/push_account.py b/apps/accounts/serializers/automations/push_account.py index 1d7bb3d36..baf1994a4 100644 --- a/apps/accounts/serializers/automations/push_account.py +++ b/apps/accounts/serializers/automations/push_account.py @@ -10,7 +10,7 @@ class PushAccountAutomationSerializer(ChangeSecretAutomationSerializer): class Meta(ChangeSecretAutomationSerializer.Meta): model = PushAccountAutomation - fields = ['params'] + [ + fields = [ n for n in ChangeSecretAutomationSerializer.Meta.fields if n not in ['recipients'] ] From 66c60ef5bed24e127de18006e9011e1a1bc8caa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=B9=BF?= Date: Tue, 4 Jul 2023 17:35:58 +0800 Subject: [PATCH 082/167] Revert "perf: add xrdp rdp7 port 3390" --- apps/assets/const/host.py | 8 +-- apps/assets/const/protocol.py | 20 ------ .../migrations/0120_auto_20230630_1555.py | 69 ------------------- apps/authentication/api/connection_token.py | 7 +- apps/terminal/connect_methods.py | 8 --- .../migrations/0064_endpoint_rdp7_port.py | 20 ------ apps/terminal/models/component/endpoint.py | 4 -- apps/terminal/serializers/endpoint.py | 2 +- 8 files changed, 5 insertions(+), 133 deletions(-) delete mode 100644 apps/assets/migrations/0120_auto_20230630_1555.py delete mode 100644 apps/terminal/migrations/0064_endpoint_rdp7_port.py diff --git a/apps/assets/const/host.py b/apps/assets/const/host.py index 60205ff2c..afb92a447 100644 --- a/apps/assets/const/host.py +++ b/apps/assets/const/host.py @@ -33,10 +33,10 @@ class HostTypes(BaseType): def _get_protocol_constrains(cls) -> dict: return { '*': { - 'choices': ['ssh', 'telnet', 'vnc', 'rdp', 'rdp7'] + 'choices': ['ssh', 'telnet', 'vnc', 'rdp'] }, cls.WINDOWS: { - 'choices': ['rdp', 'rdp7', 'ssh', 'vnc', 'winrm'] + 'choices': ['rdp', 'ssh', 'vnc', 'winrm'] } } @@ -116,10 +116,6 @@ class HostTypes(BaseType): 'required': True } } - }, - { - 'name': 'Windows-RDP7', - '_protocols': ['rdp7',], } ] } diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index 6779aabc4..e66dde209 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -10,7 +10,6 @@ __all__ = ['Protocol'] class Protocol(ChoicesMixin, models.TextChoices): ssh = 'ssh', 'SSH' rdp = 'rdp', 'RDP' - rdp7 = 'rdp7', 'RDP7' telnet = 'telnet', 'Telnet' vnc = 'vnc', 'VNC' winrm = 'winrm', 'WinRM' @@ -70,25 +69,6 @@ class Protocol(ChoicesMixin, models.TextChoices): # } } }, - cls.rdp7: { - 'port': 3390, - 'secret_types': ['password'], - 'setting': { - 'console': { - 'type': 'bool', - 'default': False, - 'label': _('Console'), - 'help_text': _("Connect to console session") - }, - 'security': { - 'type': 'choice', - 'choices': [('any', _('Any')), ('rdp', 'RDP'), ('tls', 'TLS'), ('nla', 'NLA')], - 'default': 'any', - 'label': _('Security'), - 'help_text': _("Security layer to use for the connection") - }, - } - }, cls.vnc: { 'port': 5900, 'secret_types': ['password'], diff --git a/apps/assets/migrations/0120_auto_20230630_1555.py b/apps/assets/migrations/0120_auto_20230630_1555.py deleted file mode 100644 index 6c303fdd7..000000000 --- a/apps/assets/migrations/0120_auto_20230630_1555.py +++ /dev/null @@ -1,69 +0,0 @@ -# Generated by Django 3.2.17 on 2023-06-30 07:55 - -import json - -from django.db import migrations - -platform_json_data = """{ - "category": "host", - "type": "windows", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Windows-RDP7", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_shell_type": "cmd", - "ansible_connection": "ssh" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "win_ping", - "gather_facts_method": "gather_facts_windows", - "gather_accounts_method": "gather_accounts_windows", - "verify_account_method": "verify_account_windows", - "change_secret_method": "change_secret_local_windows", - "push_account_method": "push_account_local_windows" - }, - "protocols": [ - { - "name": "rdp7", - "port": 3390, - "setting": { - "console": false, - "security": "any" - }, - "primary": true, - "required": false, - "default": false - } - ] -}""" - - -def create_rdp7_internal_platform(apps, *args): - platform_cls = apps.get_model('assets', 'Platform') - platform_automation_cls = apps.get_model('assets', 'PlatformAutomation') - platform_data = json.loads(platform_json_data) - protocols = platform_data.pop('protocols') - automation_data = platform_data.pop('automation', {}) - rdp7_obj = platform_cls.objects.create(**platform_data) - for p in protocols: - rdp7_obj.protocols.create(**p) - platform_automation_cls.objects.create(platform=rdp7_obj, **automation_data) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0119_assets_add_default_node'), - ] - - operations = [ - migrations.RunPython(create_rdp7_internal_platform), - ] diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index c25da482d..7a0b38872 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -76,11 +76,8 @@ class RDPFileClientProtocolURLMixin: rdp_options['screen mode id:i'] = '2' if full_screen else '1' # 设置 RDP Server 地址 - protocol = 'rdp7' if token.protocol == 'rdp7' else 'rdp' - endpoint = self.get_smart_endpoint(protocol=protocol, asset=token.asset) - # 由于 remoteapp 使用 mstsc 客户端连接的时候,都是 rdp 端口, 这里特殊判断 rdp7 端口 - protocol_port = endpoint.get_protocol_port(protocol, default=3389) - rdp_options['full address:s'] = f'{endpoint.host}:{protocol_port}' + endpoint = self.get_smart_endpoint(protocol='rdp', asset=token.asset) + rdp_options['full address:s'] = f'{endpoint.host}:{endpoint.rdp_port}' # 设置用户名 rdp_options['username:s'] = '{}|{}'.format(token.user.username, str(token.id)) diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index f76b2b056..a4e41c6f8 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -22,7 +22,6 @@ class WebMethod(TextChoices): Protocol.ssh: [cls.web_cli, cls.web_sftp], Protocol.telnet: [cls.web_cli], Protocol.rdp: [cls.web_gui], - Protocol.rdp7: [cls.web_gui], Protocol.vnc: [cls.web_gui], Protocol.mysql: [cls.web_cli], @@ -68,7 +67,6 @@ class NativeClient(TextChoices): 'windows': [cls.putty], }, Protocol.rdp: [cls.mstsc], - Protocol.rdp7: [cls.mstsc], Protocol.mysql: [cls.db_client], Protocol.mariadb: [cls.db_client], Protocol.redis: [cls.db_client], @@ -216,12 +214,6 @@ class ConnectMethodUtil: 'support': [Protocol.rdp], 'match': 'map' }, - TerminalType.xrdp: { - 'web_methods': [], - 'listen': [Protocol.rdp7], - 'support': [Protocol.rdp7], - 'match': 'map' - }, } return protocols diff --git a/apps/terminal/migrations/0064_endpoint_rdp7_port.py b/apps/terminal/migrations/0064_endpoint_rdp7_port.py deleted file mode 100644 index d76719287..000000000 --- a/apps/terminal/migrations/0064_endpoint_rdp7_port.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 3.2.17 on 2023-06-30 09:04 - -import common.db.fields -import django.core.validators -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0063_auto_20230621_1133'), - ] - - operations = [ - migrations.AddField( - model_name='endpoint', - name='rdp7_port', - field=common.db.fields.PortField(default=3390, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='RDP7 port'), - ), - ] diff --git a/apps/terminal/models/component/endpoint.py b/apps/terminal/models/component/endpoint.py index 1295e3efd..f19f72949 100644 --- a/apps/terminal/models/component/endpoint.py +++ b/apps/terminal/models/component/endpoint.py @@ -16,7 +16,6 @@ class Endpoint(JMSBaseModel): http_port = PortField(default=80, verbose_name=_('HTTP port')) ssh_port = PortField(default=2222, verbose_name=_('SSH port')) rdp_port = PortField(default=3389, verbose_name=_('RDP port')) - rdp7_port = PortField(default=3390, verbose_name=_('RDP7 port')) mysql_port = PortField(default=33061, verbose_name=_('MySQL port')) mariadb_port = PortField(default=33062, verbose_name=_('MariaDB port')) postgresql_port = PortField(default=54320, verbose_name=_('PostgreSQL port')) @@ -43,9 +42,6 @@ class Endpoint(JMSBaseModel): port = getattr(self, f'{protocol}_port', 0) return port - def get_protocol_port(self, protocol, default=0): - return getattr(self, f'{protocol}_port', default) - def is_default(self): return str(self.id) == self.default_id diff --git a/apps/terminal/serializers/endpoint.py b/apps/terminal/serializers/endpoint.py index aafd68aca..82de09fce 100644 --- a/apps/terminal/serializers/endpoint.py +++ b/apps/terminal/serializers/endpoint.py @@ -26,7 +26,7 @@ class EndpointSerializer(BulkModelSerializer): model = Endpoint fields_mini = ['id', 'name'] fields_small = [ - 'host', 'https_port', 'http_port', 'ssh_port', 'rdp_port', 'rdp7_port', + 'host', 'https_port', 'http_port', 'ssh_port', 'rdp_port', 'mysql_port', 'mariadb_port', 'postgresql_port', 'redis_port', 'oracle_port_range', 'oracle_port', ] From 9169f3546ab8fb5c8fd7eb14cbba43745e876e4f Mon Sep 17 00:00:00 2001 From: Eric_Lee Date: Tue, 4 Jul 2023 17:58:04 +0800 Subject: [PATCH 083/167] =?UTF-8?q?Revert=20"perf:=20rdp7=20=E5=8F=AF?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=20web=20gui=E6=96=B9=E5=BC=8F=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/connect_methods.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index a4e41c6f8..a4901b93c 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -195,7 +195,7 @@ class ConnectMethodUtil: TerminalType.lion: { 'web_methods': [WebMethod.web_gui], 'listen': [Protocol.http], - 'support': [Protocol.rdp, Protocol.rdp7, Protocol.vnc], + 'support': [Protocol.rdp, Protocol.vnc], 'match': 'm2m' }, TerminalType.magnus: { From dd846d4183ab0ba267cc89224412c52566efee3a Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Mon, 3 Jul 2023 09:33:07 +0800 Subject: [PATCH 084/167] =?UTF-8?q?feat:=20=E4=BA=91=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=85=AC=E6=9C=89=E4=BA=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements/requirements_xpack.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements/requirements_xpack.txt b/requirements/requirements_xpack.txt index c7d48e644..8f1930fad 100644 --- a/requirements/requirements_xpack.txt +++ b/requirements/requirements_xpack.txt @@ -23,3 +23,4 @@ psycopg2-binary==2.9.1 pymssql==2.2.5 IPy==1.1 psycopg2==2.9.4 +ucloud-sdk-python3==0.11.47 From 785e4cc3e47e36a53427721f817e51a70831cefb Mon Sep 17 00:00:00 2001 From: "fangfang.dong" Date: Mon, 3 Jul 2023 16:33:58 +0800 Subject: [PATCH 085/167] =?UTF-8?q?perf:=20=E6=8E=A5=E5=8F=A3sql=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20/api/v1/perms/asset-permissions//assets/al?= =?UTF-8?q?l/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/perms/api/asset_permission_relation.py | 3 +++ apps/perms/utils/user_perm.py | 9 +++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/perms/api/asset_permission_relation.py b/apps/perms/api/asset_permission_relation.py index f2bd3cf30..5a97192e0 100644 --- a/apps/perms/api/asset_permission_relation.py +++ b/apps/perms/api/asset_permission_relation.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- # +from functools import lru_cache + from rest_framework import generics from django.db.models import F from django.shortcuts import get_object_or_404 @@ -93,6 +95,7 @@ class AssetPermissionAllAssetListApi(generics.ListAPIView): filterset_fields = ("name", "address") search_fields = filterset_fields + @lru_cache(maxsize=2) def get_queryset(self): pk = self.kwargs.get("pk") assets = AssetPermissionPermAssetUtil(perm_ids=[pk]).get_all_assets() diff --git a/apps/perms/utils/user_perm.py b/apps/perms/utils/user_perm.py index d054e67ce..7c78c9149 100644 --- a/apps/perms/utils/user_perm.py +++ b/apps/perms/utils/user_perm.py @@ -24,12 +24,9 @@ class AssetPermissionPermAssetUtil: def get_perm_nodes_assets(self, flat=False): """ 获取所有授权节点下的资产 """ - node_ids = AssetPermission.nodes.through.objects \ - .filter(assetpermission_id__in=self.perm_ids) \ - .values_list('node_id', flat=True) \ - .distinct() - node_ids = list(node_ids) - nodes = PermNode.objects.filter(id__in=node_ids).only('id', 'key') + from assets.models import Node + nodes = Node.objects.prefetch_related('granted_by_permissions').filter( + granted_by_permissions__in=self.perm_ids).only('id', 'key') assets = PermNode.get_nodes_all_assets(*nodes) if flat: return assets.values_list('id', flat=True) From fb279dbc396ee153b634bc6d43924ec5f9805054 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 4 Jul 2023 17:04:25 +0800 Subject: [PATCH 086/167] =?UTF-8?q?perf:=20=E6=96=B0=E5=A2=9E=20SFTP=20?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.po | 67 +++++++++++++++------------- apps/locale/zh/LC_MESSAGES/django.po | 60 ++++++++++++++----------- apps/terminal/const.py | 1 + 3 files changed, 69 insertions(+), 59 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 546a6a635..4a39b57a5 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-27 16:02+0800\n" +"POT-Creation-Date: 2023-07-04 18:28+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1464,8 +1464,8 @@ msgstr "ゲートウェイ" msgid "Asset group" msgstr "資産グループ" -#: assets/models/group.py:34 assets/models/platform.py:17 -#: assets/serializers/platform.py:102 +#: assets/models/group.py:31 assets/models/platform.py:17 +#: assets/serializers/platform.py:112 #: xpack/plugins/cloud/providers/nutanix.py:30 msgid "Default" msgstr "デフォルト" @@ -1478,7 +1478,7 @@ msgstr "デフォルトアセットグループ" msgid "System" msgstr "システム" -#: assets/models/label.py:19 assets/models/node.py:557 +#: assets/models/label.py:19 assets/models/node.py:545 #: assets/serializers/cagegory.py:7 assets/serializers/cagegory.py:14 #: authentication/models/connection_token.py:29 #: authentication/serializers/connect_token_secret.py:122 @@ -1499,28 +1499,28 @@ msgstr "ラベル" msgid "New node" msgstr "新しいノード" -#: assets/models/node.py:485 audits/backends/db.py:55 audits/backends/db.py:56 +#: assets/models/node.py:473 audits/backends/db.py:55 audits/backends/db.py:56 msgid "empty" msgstr "空" -#: assets/models/node.py:556 perms/models/perm_node.py:28 +#: assets/models/node.py:544 perms/models/perm_node.py:28 msgid "Key" msgstr "キー" -#: assets/models/node.py:558 assets/serializers/node.py:20 +#: assets/models/node.py:546 assets/serializers/node.py:20 msgid "Full value" msgstr "フルバリュー" -#: assets/models/node.py:562 perms/models/perm_node.py:30 +#: assets/models/node.py:550 perms/models/perm_node.py:30 msgid "Parent key" msgstr "親キー" -#: assets/models/node.py:571 perms/serializers/permission.py:35 +#: assets/models/node.py:559 perms/serializers/permission.py:35 #: tickets/models/ticket/apply_asset.py:14 xpack/plugins/cloud/models.py:96 msgid "Node" msgstr "ノード" -#: assets/models/node.py:574 +#: assets/models/node.py:562 msgid "Can match node" msgstr "ノードを一致させることができます" @@ -3048,18 +3048,15 @@ msgstr "リダイレクト" msgid "Redirecting to {} authentication" msgstr "{} 認証へのリダイレクト" -#: authentication/views/login.py:207 -msgid "Please enable cookies and try again." -msgstr "クッキーを有効にして、もう一度お試しください。" #: authentication/views/login.py:207 msgid "Login timeout, please try again." msgstr "ログインタイムアウト、もう一度お試しください" -#: authentication/views/login.py:248 +#: authentication/views/login.py:250 msgid "User email already exists ({})" msgstr "ユーザー メールボックスは既に存在します ({})" -#: authentication/views/login.py:326 +#: authentication/views/login.py:328 msgid "" "Wait for {} confirm, You also can copy link to her/him
\n" " Don't close this page" @@ -3067,15 +3064,15 @@ msgstr "" "{} 確認を待ちます。彼女/彼へのリンクをコピーすることもできます
\n" " このページを閉じないでください" -#: authentication/views/login.py:331 +#: authentication/views/login.py:333 msgid "No ticket found" msgstr "チケットが見つかりません" -#: authentication/views/login.py:367 +#: authentication/views/login.py:369 msgid "Logout success" msgstr "ログアウト成功" -#: authentication/views/login.py:368 +#: authentication/views/login.py:370 msgid "Logout success, return login page" msgstr "ログアウト成功、ログインページを返す" @@ -5490,8 +5487,8 @@ msgstr "期限切れです。" #, python-format msgid "" "\n" -" Your password has expired, please click this link update password.\n" +" Your password has expired, please click this link update password.\n" " " msgstr "" "\n" @@ -5512,34 +5509,34 @@ msgid "" " " msgstr "" "\n" -" クリックしてください リンク パスワードの更新\n" +" クリックしてください リンク パスワードの更新\n" " " #: templates/_message.html:43 #, python-format msgid "" "\n" -" Your information was incomplete. Please click this link to complete your information.\n" +" Your information was incomplete. Please click this link to complete your information.\n" " " msgstr "" "\n" -" あなたの情報が不完全なので、クリックしてください。 リンク 補完\n" +" あなたの情報が不完全なので、クリックしてください。 リンク 補完\n" " " #: templates/_message.html:56 #, python-format msgid "" "\n" -" Your ssh public key not set or expired. Please click this link to update\n" +" Your ssh public key not set or expired. Please click this link to update\n" " " msgstr "" "\n" -" SSHキーが設定されていないか無効になっている場合は、 リンク 更新\n" +" SSHキーが設定されていないか無効になっている場合は、 リンク 更新\n" " " #: templates/_mfa_login_field.html:28 @@ -5715,11 +5712,17 @@ msgstr "一致しない" msgid "Tunnel" msgstr "" -#: terminal/const.py:73 +#: terminal/const.py:70 +#, fuzzy +#| msgid "SFTP home" +msgid "SFTP" +msgstr "SFTP ルート パス" + +#: terminal/const.py:74 msgid "Read Only" msgstr "読み取り専用" -#: terminal/const.py:74 +#: terminal/const.py:75 msgid "Writable" msgstr "書き込み可能" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index d2b7bc7f6..740af46c5 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-15 15:35+0800\n" +"POT-Creation-Date: 2023-07-04 18:28+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -1455,8 +1455,8 @@ msgstr "网关" msgid "Asset group" msgstr "资产组" -#: assets/models/group.py:34 assets/models/platform.py:17 -#: assets/serializers/platform.py:102 +#: assets/models/group.py:31 assets/models/platform.py:17 +#: assets/serializers/platform.py:112 #: xpack/plugins/cloud/providers/nutanix.py:30 msgid "Default" msgstr "默认" @@ -1469,7 +1469,7 @@ msgstr "默认资产组" msgid "System" msgstr "系统" -#: assets/models/label.py:19 assets/models/node.py:557 +#: assets/models/label.py:19 assets/models/node.py:545 #: assets/serializers/cagegory.py:7 assets/serializers/cagegory.py:14 #: authentication/models/connection_token.py:29 #: authentication/serializers/connect_token_secret.py:122 @@ -1490,28 +1490,28 @@ msgstr "标签" msgid "New node" msgstr "新节点" -#: assets/models/node.py:485 audits/backends/db.py:55 audits/backends/db.py:56 +#: assets/models/node.py:473 audits/backends/db.py:55 audits/backends/db.py:56 msgid "empty" msgstr "空" -#: assets/models/node.py:556 perms/models/perm_node.py:28 +#: assets/models/node.py:544 perms/models/perm_node.py:28 msgid "Key" msgstr "键" -#: assets/models/node.py:558 assets/serializers/node.py:20 +#: assets/models/node.py:546 assets/serializers/node.py:20 msgid "Full value" msgstr "全称" -#: assets/models/node.py:562 perms/models/perm_node.py:30 +#: assets/models/node.py:550 perms/models/perm_node.py:30 msgid "Parent key" msgstr "ssh私钥" -#: assets/models/node.py:571 perms/serializers/permission.py:35 +#: assets/models/node.py:559 perms/serializers/permission.py:35 #: tickets/models/ticket/apply_asset.py:14 xpack/plugins/cloud/models.py:96 msgid "Node" msgstr "节点" -#: assets/models/node.py:574 +#: assets/models/node.py:562 msgid "Can match node" msgstr "可以匹配节点" @@ -3010,11 +3010,11 @@ msgstr "正在跳转到 {} 认证" msgid "Login timeout, please try again." msgstr "登录超时,请重新登录" -#: authentication/views/login.py:247 +#: authentication/views/login.py:250 msgid "User email already exists ({})" msgstr "用户邮箱已存在 ({})" -#: authentication/views/login.py:325 +#: authentication/views/login.py:328 msgid "" "Wait for {} confirm, You also can copy link to her/him
\n" " Don't close this page" @@ -3022,15 +3022,15 @@ msgstr "" "等待 {} 确认, 你也可以复制链接发给他/她
\n" " 不要关闭本页面" -#: authentication/views/login.py:330 +#: authentication/views/login.py:333 msgid "No ticket found" msgstr "没有发现工单" -#: authentication/views/login.py:366 +#: authentication/views/login.py:369 msgid "Logout success" msgstr "退出登录成功" -#: authentication/views/login.py:367 +#: authentication/views/login.py:370 msgid "Logout success, return login page" msgstr "退出登录成功,返回到登录页面" @@ -5403,13 +5403,13 @@ msgstr "过期。" #, python-format msgid "" "\n" -" Your password has expired, please click this link update password.\n" +" Your password has expired, please click this link update password.\n" " " msgstr "" "\n" -" 您的密码已经过期,请点击 链接 更新密码\n" +" 您的密码已经过期,请点击 链接 更新密码\n" " " #: templates/_message.html:30 @@ -5433,8 +5433,8 @@ msgstr "" #, python-format msgid "" "\n" -" Your information was incomplete. Please click this link to complete your information.\n" +" Your information was incomplete. Please click this link to complete your information.\n" " " msgstr "" "\n" @@ -5446,13 +5446,13 @@ msgstr "" #, python-format msgid "" "\n" -" Your ssh public key not set or expired. Please click this link to update\n" +" Your ssh public key not set or expired. Please click this link to update\n" " " msgstr "" "\n" -" 您的SSH密钥没有设置或已失效,请点击 链接 更新\n" +" 您的SSH密钥没有设置或已失效,请点击 链接 更新\n" " " #: templates/_mfa_login_field.html:28 @@ -5623,11 +5623,17 @@ msgstr "未匹配" msgid "Tunnel" msgstr "隧道" -#: terminal/const.py:73 +#: terminal/const.py:70 +#, fuzzy +#| msgid "SFTP home" +msgid "SFTP" +msgstr "SFTP" + +#: terminal/const.py:74 msgid "Read Only" msgstr "只读" -#: terminal/const.py:74 +#: terminal/const.py:75 msgid "Writable" msgstr "读写" diff --git a/apps/terminal/const.py b/apps/terminal/const.py index 1f857b7c7..b8a33cee7 100644 --- a/apps/terminal/const.py +++ b/apps/terminal/const.py @@ -67,6 +67,7 @@ class SessionType(TextChoices): normal = 'normal', _('Normal') tunnel = 'tunnel', _('Tunnel') command = 'command', _('Command') + sftp = 'sftp', _('SFTP') class ActionPermission(TextChoices): From 3963881226ecd0865eb04879c7a833242026a1fe Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 4 Jul 2023 18:37:23 +0800 Subject: [PATCH 087/167] =?UTF-8?q?perf:=20=E6=97=A5=E6=96=87=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=E6=9B=B4=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 4a39b57a5..58b3f4d58 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -5716,7 +5716,7 @@ msgstr "" #, fuzzy #| msgid "SFTP home" msgid "SFTP" -msgstr "SFTP ルート パス" +msgstr "SFTP" #: terminal/const.py:74 msgid "Read Only" From 7f03639c3433e6e1102699b1273b7bda01533a1d Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 4 Jul 2023 18:49:10 +0800 Subject: [PATCH 088/167] =?UTF-8?q?perf:=20=E6=9B=B4=E6=96=B0=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.po | 4 ---- apps/locale/zh/LC_MESSAGES/django.po | 2 -- 2 files changed, 6 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 58b3f4d58..42a8a81b1 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -1162,8 +1162,6 @@ msgid "Use SSL" msgstr "SSLの使用" #: assets/const/protocol.py:140 -#, fuzzy -#| msgid "Auth with username" msgid "Auth username" msgstr "ユーザー名で認証する" @@ -5713,8 +5711,6 @@ msgid "Tunnel" msgstr "" #: terminal/const.py:70 -#, fuzzy -#| msgid "SFTP home" msgid "SFTP" msgstr "SFTP" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 740af46c5..339c287d6 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -5624,8 +5624,6 @@ msgid "Tunnel" msgstr "隧道" #: terminal/const.py:70 -#, fuzzy -#| msgid "SFTP home" msgid "SFTP" msgstr "SFTP" From f096014d0345f3e1df889d5e1b5dee179e0fe759 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 5 Jul 2023 15:17:28 +0800 Subject: [PATCH 089/167] =?UTF-8?q?perf:=20=E7=A7=BB=E9=99=A4=E9=92=88?= =?UTF-8?q?=E5=AF=B9=E7=AB=AF=E7=82=B9=20host=20=E7=9A=84=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/models/component/endpoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/terminal/models/component/endpoint.py b/apps/terminal/models/component/endpoint.py index f19f72949..d8c74e689 100644 --- a/apps/terminal/models/component/endpoint.py +++ b/apps/terminal/models/component/endpoint.py @@ -53,7 +53,7 @@ class Endpoint(JMSBaseModel): def is_valid_for(self, target_instance, protocol): if self.is_default(): return True - if self.host and self.get_port(target_instance, protocol) != 0: + if self.get_port(target_instance, protocol) != 0: return True return False From d6aaf23abb4c35189891a138b0ea6af3394caa3c Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 5 Jul 2023 16:42:50 +0800 Subject: [PATCH 090/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=AF=BC=E5=85=A5=E6=97=B6=E6=89=8B=E6=9C=BA=E5=8F=B7?= =?UTF-8?q?=E4=B8=BAdict=E7=B1=BB=E5=9E=8B=E6=8A=A5=E9=94=99=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/serializers/fields.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps/common/serializers/fields.py b/apps/common/serializers/fields.py index cf92391e1..844c424e5 100644 --- a/apps/common/serializers/fields.py +++ b/apps/common/serializers/fields.py @@ -212,6 +212,23 @@ class BitChoicesField(TreeChoicesField): class PhoneField(serializers.CharField): + + def to_internal_value(self, data): + if isinstance(data, dict): + code = data.get('code') + phone = data.get('phone', '') + if code and phone: + data = '{}{}'.format(code, phone) + else: + data = phone + try: + phone = phonenumbers.parse(data, 'CN') + data = '{}{}'.format(phone.country_code, phone.national_number) + except phonenumbers.NumberParseException: + data = '+86{}'.format(data) + + return super().to_internal_value(data) + def to_representation(self, value): if value: try: From 751bd35349f73ab21398b305eef28b73af7fdf5c Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 5 Jul 2023 18:28:31 +0800 Subject: [PATCH 091/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=AD=A3=20Chrome=20d?= =?UTF-8?q?river=20=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/automations/deploy_applet_host/playbook.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/terminal/automations/deploy_applet_host/playbook.yml b/apps/terminal/automations/deploy_applet_host/playbook.yml index 25f2b7048..cd9bc655e 100644 --- a/apps/terminal/automations/deploy_applet_host/playbook.yml +++ b/apps/terminal/automations/deploy_applet_host/playbook.yml @@ -166,7 +166,7 @@ - name: Unzip chromedriver (Chrome) community.windows.win_unzip: src: "{{ ansible_env.TEMP }}\\chromedriver_win32.zip" - dest: C:\Program Files\JumpServer\drivers + dest: C:\Program Files\JumpServer\drivers\chromedriver_win32 - name: Download Chrome zip package (Chrome) ansible.windows.win_get_url: @@ -229,4 +229,4 @@ - name: Sync all remote applets ansible.windows.win_powershell: script: | - tinkerd install all \ No newline at end of file + tinkerd install all From 6b189e61620ba282b557feed506f9ccfdec7a5b0 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 5 Jul 2023 18:45:46 +0800 Subject: [PATCH 092/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=AF=BC?= =?UTF-8?q?=E5=85=A5LDAP=E6=95=B0=E6=8D=AE=E5=BA=93=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=20Lock=20wait=20timeout=20=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/settings/tasks/ldap.py | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/settings/tasks/ldap.py b/apps/settings/tasks/ldap.py index fa2f4287c..b931efb48 100644 --- a/apps/settings/tasks/ldap.py +++ b/apps/settings/tasks/ldap.py @@ -23,7 +23,6 @@ def sync_ldap_user(): @shared_task(verbose_name=_('Periodic import ldap user')) -@transaction.atomic def import_ldap_user(): logger.info("Start import ldap user task") util_server = LDAPServerUtil() From b324c6cc8a4c7840322673c3719969fbe9680460 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 23:26:55 +0000 Subject: [PATCH 093/167] build(deps): bump django from 3.2.19 to 3.2.20 in /requirements Bumps [django](https://github.com/django/django) from 3.2.19 to 3.2.20. - [Commits](https://github.com/django/django/compare/3.2.19...3.2.20) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index df532adf3..65004e605 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -68,7 +68,7 @@ geoip2==4.5.0 ipip-ipdb==1.6.1 pywinrm==0.4.3 # Django environment -Django==3.2.19 +Django==3.2.20 django-bootstrap3==14.2.0 django-filter==2.4.0 django-formtools==2.2 From 89492410aa82d5312c156365bb7451cb6505e97a Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Wed, 5 Jul 2023 10:08:01 +0800 Subject: [PATCH 094/167] =?UTF-8?q?fix:=20=E6=8E=A8=E9=80=81=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=20=E4=B8=8D=E5=A1=AB=E5=86=99home=20=E6=8E=A8?= =?UTF-8?q?=E9=80=81=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/serializers/automations/base.py | 16 +++++++++------- apps/assets/automations/base/manager.py | 7 ++++++- apps/assets/serializers/automations/base.py | 12 ++++++------ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/apps/accounts/serializers/automations/base.py b/apps/accounts/serializers/automations/base.py index 1468ecf58..8e7f11f23 100644 --- a/apps/accounts/serializers/automations/base.py +++ b/apps/accounts/serializers/automations/base.py @@ -63,15 +63,17 @@ class AutomationExecutionSerializer(serializers.ModelSerializer): @staticmethod def get_snapshot(obj): - tp = obj.snapshot['type'] + tp = obj.snapshot.get('type', '') + type_display = tp if not hasattr(AutomationTypes, tp) \ + else getattr(AutomationTypes, tp).label snapshot = { 'type': tp, - 'name': obj.snapshot['name'], - 'comment': obj.snapshot['comment'], - 'accounts': obj.snapshot['accounts'], - 'node_amount': len(obj.snapshot['nodes']), - 'asset_amount': len(obj.snapshot['assets']), - 'type_display': getattr(AutomationTypes, tp).label, + 'name': obj.snapshot.get('name'), + 'comment': obj.snapshot.get('comment'), + 'accounts': obj.snapshot.get('accounts'), + 'node_amount': len(obj.snapshot.get('nodes', [])), + 'asset_amount': len(obj.snapshot.get('assets', [])), + 'type_display': type_display, } return snapshot diff --git a/apps/assets/automations/base/manager.py b/apps/assets/automations/base/manager.py index aa31c886f..b0215710a 100644 --- a/apps/assets/automations/base/manager.py +++ b/apps/assets/automations/base/manager.py @@ -55,8 +55,13 @@ class BasePlaybookManager: return {} data = self.params.get(method_id) + default_data = serializer().data if not data: - data = automation_params.get(method_id, {}) + data = automation_params.get(method_id, default_data) + + for k, v in default_data.items(): + data.setdefault(k, v) + params = serializer(data).data return { field_name: automation_params.get(field_name, '') diff --git a/apps/assets/serializers/automations/base.py b/apps/assets/serializers/automations/base.py index 527f71628..d930fd1dc 100644 --- a/apps/assets/serializers/automations/base.py +++ b/apps/assets/serializers/automations/base.py @@ -51,14 +51,14 @@ class AutomationExecutionSerializer(serializers.ModelSerializer): from assets.const import AutomationTypes as AssetTypes from accounts.const import AutomationTypes as AccountTypes tp_dict = dict(AssetTypes.choices) | dict(AccountTypes.choices) - tp = obj.snapshot['type'] + tp = obj.snapshot.get('type', '') snapshot = { 'type': {'value': tp, 'label': tp_dict.get(tp, tp)}, - 'name': obj.snapshot['name'], - 'comment': obj.snapshot['comment'], - 'accounts': obj.snapshot['accounts'], - 'node_amount': len(obj.snapshot['nodes']), - 'asset_amount': len(obj.snapshot['assets']), + 'name': obj.snapshot.get('name'), + 'comment': obj.snapshot.get('comment'), + 'accounts': obj.snapshot.get('accounts'), + 'node_amount': len(obj.snapshot.get('nodes', [])), + 'asset_amount': len(obj.snapshot.get('assets', [])), } return snapshot From ee3cdcd9e48a0edbb054724675bf1d55a42e3fa1 Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Wed, 5 Jul 2023 14:28:26 +0800 Subject: [PATCH 095/167] =?UTF-8?q?fix:=20=E6=9C=89=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=80=BC=20required=20=E4=B8=BAfalse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/automations/base/manager.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/apps/assets/automations/base/manager.py b/apps/assets/automations/base/manager.py index b0215710a..aa31c886f 100644 --- a/apps/assets/automations/base/manager.py +++ b/apps/assets/automations/base/manager.py @@ -55,13 +55,8 @@ class BasePlaybookManager: return {} data = self.params.get(method_id) - default_data = serializer().data if not data: - data = automation_params.get(method_id, default_data) - - for k, v in default_data.items(): - data.setdefault(k, v) - + data = automation_params.get(method_id, {}) params = serializer(data).data return { field_name: automation_params.get(field_name, '') From 9c2cc65ce8451f224afa5beafb1ab09afb1ddda7 Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Thu, 6 Jul 2023 18:26:05 +0800 Subject: [PATCH 096/167] =?UTF-8?q?perf:=20=E5=8E=BB=E9=99=A4readme=20?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E5=BE=AE=E4=BF=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 71872e4a2..a2b98e8a3 100644 --- a/README.md +++ b/README.md @@ -81,11 +81,7 @@ JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运 如果您在使用过程中有任何疑问或对建议,欢迎提交 [GitHub Issue](https://github.com/jumpserver/jumpserver/issues/new/choose)。 -您也可以到我们的 [社区论坛](https://bbs.fit2cloud.com/c/js/5) 及微信交流群当中进行交流沟通。 - -**微信交流群** - -微信群二维码 +您也可以到我们的 [社区论坛](https://bbs.fit2cloud.com/c/js/5) 当中进行交流沟通。 ### 参与贡献 From 6a720cde0ad230299912053440a8b07902ae6178 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 6 Jul 2023 11:47:25 +0800 Subject: [PATCH 097/167] =?UTF-8?q?perf:=20=E6=9B=B4=E6=96=B0=20chrome=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=8C=BF=E5=90=8D=E8=B4=A6=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/applets/chrome/ChangeLog | 3 +++ apps/terminal/applets/chrome/README.md | 3 +++ apps/terminal/applets/chrome/app.py | 20 +++++++++++++------- apps/terminal/applets/chrome/manifest.yml | 2 +- 4 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 apps/terminal/applets/chrome/ChangeLog diff --git a/apps/terminal/applets/chrome/ChangeLog b/apps/terminal/applets/chrome/ChangeLog new file mode 100644 index 000000000..7a03e6949 --- /dev/null +++ b/apps/terminal/applets/chrome/ChangeLog @@ -0,0 +1,3 @@ +# 2023-07-06 Version 0.5 +## 功能更新 + - 增加匿名用户的支持,如果账号是匿名用户,username 和 secret 则为空 diff --git a/apps/terminal/applets/chrome/README.md b/apps/terminal/applets/chrome/README.md index 068682bfb..991b0c3bb 100644 --- a/apps/terminal/applets/chrome/README.md +++ b/apps/terminal/applets/chrome/README.md @@ -5,3 +5,6 @@ - Chrome 和 ChromeDriver 版本要匹配 - Driver [下载地址](https://chromedriver.chromium.org/downloads) +## ChangeLog + +一些重要的更新记录参考 [ChangeLog](./ChangeLog.md) diff --git a/apps/terminal/applets/chrome/app.py b/apps/terminal/applets/chrome/app.py index 9cc452590..47cce8844 100644 --- a/apps/terminal/applets/chrome/app.py +++ b/apps/terminal/applets/chrome/app.py @@ -135,6 +135,14 @@ class WebAPP(object): self.account = account self.platform = platform self._steps = list() + # 确保 account_username 和 account_secret 不为 None + self._account_username = account.username if account.username else '' + self._account_secret = account.secret if account.secret else '' + + # 如果是匿名账号,account_username 和 account_secret 为空 + if account.username == "@ANON": + self._account_username = '' + self._account_secret = '' extra_data = self.asset.spec_info autofill_type = extra_data.autofill @@ -153,23 +161,22 @@ class WebAPP(object): for item in steps: val = item.value if val: - val = val.replace("{USERNAME}", self.account.username) - val = val.replace("{SECRET}", self.account.secret) + val = val.replace("{USERNAME}", self._account_username) + val = val.replace("{SECRET}", self._account_secret) item.value = val self._steps.append(item) def _default_custom_steps(self, spec_info) -> list: - account = self.account - default_steps = [ + return [ Step({ "step": 1, - "value": account.username, + "value": self._account_username, "target": spec_info.username_selector, "command": "type" }), Step({ "step": 2, - "value": account.secret, + "value": self._account_secret, "target": spec_info.password_selector, "command": "type" }), @@ -180,7 +187,6 @@ class WebAPP(object): "command": "click" }) ] - return default_steps def execute(self, driver: webdriver.Chrome) -> bool: if not self.asset.address: diff --git a/apps/terminal/applets/chrome/manifest.yml b/apps/terminal/applets/chrome/manifest.yml index 4c66515b6..0fd511f58 100644 --- a/apps/terminal/applets/chrome/manifest.yml +++ b/apps/terminal/applets/chrome/manifest.yml @@ -1,6 +1,6 @@ name: chrome display_name: "{{ 'Chrome Browser' | trans }}" -version: 0.4 +version: 0.5 comment: "{{ 'Chrome Browser Open URL Page Address' | trans }}" author: JumpServer Team exec_type: python From 61078ee2ed30751b052a92af2365bbe30fa495e6 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 6 Jul 2023 11:50:16 +0800 Subject: [PATCH 098/167] =?UTF-8?q?perf:=20=E6=9B=B4=E6=96=B0=20Chrome=20?= =?UTF-8?q?=E7=9A=84=20ChangeLog=20=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/applets/chrome/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/terminal/applets/chrome/README.md b/apps/terminal/applets/chrome/README.md index 991b0c3bb..cd03251ab 100644 --- a/apps/terminal/applets/chrome/README.md +++ b/apps/terminal/applets/chrome/README.md @@ -7,4 +7,4 @@ ## ChangeLog -一些重要的更新记录参考 [ChangeLog](./ChangeLog.md) +一些重要的更新记录参考 [ChangeLog](./ChangeLog) From 9607ab516476623efe21df3cf3e097c1fb70adcf Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 7 Jul 2023 16:15:32 +0800 Subject: [PATCH 099/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20AD=20(#10926)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * stash * perf: 修改支持 AD * perf: 优化 default --------- Co-authored-by: ibuler --- apps/assets/const/protocol.py | 11 ++++++----- apps/assets/const/types.py | 4 ++-- apps/common/serializers/dynamic.py | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index e66dde209..ecb173f86 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -62,11 +62,12 @@ class Protocol(ChoicesMixin, models.TextChoices): 'label': _('Security'), 'help_text': _("Security layer to use for the connection") }, - # 'ad_domain': { - # 'type': 'str', - # "required": False, - # 'label': _('AD domain') - # } + 'ad_domain': { + 'type': 'str', + 'required': False, + 'default': '', + 'label': _('AD domain') + } } }, cls.vnc: { diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py index 1f0156b7f..e9c3ae790 100644 --- a/apps/assets/const/types.py +++ b/apps/assets/const/types.py @@ -350,7 +350,7 @@ class AllTypes(ChoicesMixin): for d in platform_datas: name = d['name'] - # print("\t - Platform: {}".format(name)) + print("\t - Platform: {}".format(name)) _automation = d.pop('automation', {}) _protocols = d.pop('_protocols', []) _protocols_setting = d.pop('protocols_setting', {}) @@ -363,7 +363,7 @@ class AllTypes(ChoicesMixin): setting = _protocols_setting.get(p['name'], {}) p['required'] = setting.pop('required', False) p['default'] = setting.pop('default', False) - p['setting'] = {**p.get('setting', {}), **setting} + p['setting'] = {**p.get('setting', {}).get('default', ''), **setting} platform_data = { **default_platform_data, **d, diff --git a/apps/common/serializers/dynamic.py b/apps/common/serializers/dynamic.py index 49e1e062d..e3fab256a 100644 --- a/apps/common/serializers/dynamic.py +++ b/apps/common/serializers/dynamic.py @@ -51,8 +51,8 @@ def create_serializer_class(serializer_name, fields_info): field_type = data.pop('type', 'str') # 用户定义 default 和 required 可能会冲突, 所以要处理一下 - default = data.get('default', '') - if default not in ['', None]: + default = data.get('default', None) + if default is not None: data['required'] = False else: data.pop('default', None) From 76af71bbbe81151d1fa202bbb6a95cf3b76e2b95 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 7 Jul 2023 19:47:12 +0800 Subject: [PATCH 100/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20Platform?= =?UTF-8?q?=20=E7=BA=A6=E6=9D=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/const/base.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/assets/const/base.py b/apps/assets/const/base.py index 5aea334d4..338e02bb0 100644 --- a/apps/assets/const/base.py +++ b/apps/assets/const/base.py @@ -69,10 +69,15 @@ class BaseType(TextChoices): choices = protocol.get('choices', []) if choices == '__self__': choices = [tp] - protocols = [ - {'name': name, **settings.get(name, {})} - for name in choices - ] + + protocols = [] + for name in choices: + protocol = {'name': name, **settings.get(name, {})} + setting = protocol.pop('setting', {}) + setting_values = {k: v.get('default', None) for k, v in setting.items()} + protocol['setting'] = setting_values + protocols.append(protocol) + if protocols: protocols[0]['default'] = True return protocols From 7d17c1a450ad782d35de2dfe69e3d140049abe5b Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 10 Jul 2023 19:28:19 +0800 Subject: [PATCH 101/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20beat=20?= =?UTF-8?q?=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E9=87=8D=E5=A4=8D=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/celery/beat/__init__.py | 0 apps/ops/celery/beat/schedulers.py | 80 ++++++++++++++++++++++++++++++ utils/start_celery_beat.py | 2 +- 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 apps/ops/celery/beat/__init__.py create mode 100644 apps/ops/celery/beat/schedulers.py diff --git a/apps/ops/celery/beat/__init__.py b/apps/ops/celery/beat/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/ops/celery/beat/schedulers.py b/apps/ops/celery/beat/schedulers.py new file mode 100644 index 000000000..7be8d1cda --- /dev/null +++ b/apps/ops/celery/beat/schedulers.py @@ -0,0 +1,80 @@ +import logging +from celery.utils.log import get_logger +from django.db import close_old_connections +from django.core.exceptions import ObjectDoesNotExist +from django.db.utils import DatabaseError, InterfaceError + +from django_celery_beat.schedulers import DatabaseScheduler as DJDatabaseScheduler + +logger = get_logger(__name__) +debug, info, warning = logger.debug, logger.info, logger.warning + + +__all__ = ['DatabaseScheduler'] + + +class DatabaseScheduler(DJDatabaseScheduler): + + def sync(self): + if logger.isEnabledFor(logging.DEBUG): + debug('Writing entries...') + _tried = set() + _failed = set() + try: + close_old_connections() + + while self._dirty: + name = self._dirty.pop() + try: + # 源码 + # self.schedule[name].save() + # _tried.add(name) + + """ + ::Debug Description (2023.07.10):: + + 如果调用 self.schedule 可能会导致 self.save() 方法之前重新获取数据库中的数据, 而不是临时设置的 last_run_at 数据 + + 如果这里调用 self.schedule + 那么可能会导致调用 save 的 self.schedule[name] 的 last_run_at 是从数据库中获取回来的老数据 + 而不是任务执行后临时设置的 last_run_at (在 __next__() 方法中设置的) + 当 `max_interval` 间隔之后, 下一个任务检测周期还是会再次执行任务 + + ::Demo:: + 任务信息: + beat config: max_interval = 60s + + 任务名称: cap + 任务执行周期: 每 3 分钟执行一次 + 任务最后执行时间: 18:00 + + 任务第一次执行: 18:03 (执行时设置 last_run_at = 18:03, 此时在内存中) + + 任务执行完成后, + 检测到需要 sync, sync 中调用了 self.schedule, + self.schedule 中发现 schedule_changed() 为 True, 需要调用 all_as_schedule() + 此时,sync 中调用的 self.schedule[name] 的 last_run_at 是 18:00 + 这时候在 self.sync() 进行 self.save() + + + beat: Waking up 60s ... + + 任务第二次执行: 18:04 (因为获取回来的 last_run_at 是 18:00, entry.is_due() == True) + + ::解决方法:: + 所以这里为了避免从数据库中获取,直接使用 _schedule # + """ + self._schedule[name].save() + _tried.add(name) + except (KeyError, ObjectDoesNotExist): + _failed.add(name) + except DatabaseError as exc: + logger.exception('Database error while sync: %r', exc) + except InterfaceError: + warning( + 'DatabaseScheduler: InterfaceError in sync(), ' + 'waiting to retry in next call...' + ) + finally: + # retry later, only for the failed ones + self._dirty |= _failed diff --git a/utils/start_celery_beat.py b/utils/start_celery_beat.py index 23aa1cb83..19d578e70 100644 --- a/utils/start_celery_beat.py +++ b/utils/start_celery_beat.py @@ -54,7 +54,7 @@ else: connection_params['port'] = settings.REDIS_PORT redis_client = Redis(**connection_params) -scheduler = "django_celery_beat.schedulers:DatabaseScheduler" +scheduler = "ops.celery.beat.schedulers:DatabaseScheduler" processes = [] cmd = [ 'celery', From ad311c15caf9f7cb1d830818d6f430db079d4764 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 11 Jul 2023 10:19:31 +0800 Subject: [PATCH 102/167] =?UTF-8?q?fix:=20=E5=A2=9E=E5=8A=A0=20TypeError?= =?UTF-8?q?=20=E6=8D=95=E8=8E=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/celery/beat/schedulers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ops/celery/beat/schedulers.py b/apps/ops/celery/beat/schedulers.py index 7be8d1cda..17bdcea3c 100644 --- a/apps/ops/celery/beat/schedulers.py +++ b/apps/ops/celery/beat/schedulers.py @@ -66,7 +66,7 @@ class DatabaseScheduler(DJDatabaseScheduler): """ self._schedule[name].save() _tried.add(name) - except (KeyError, ObjectDoesNotExist): + except (KeyError, TypeError, ObjectDoesNotExist): _failed.add(name) except DatabaseError as exc: logger.exception('Database error while sync: %r', exc) From 89f1a1653d11c363463eb526202fc63edb5056a1 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 11 Jul 2023 10:31:36 +0800 Subject: [PATCH 103/167] =?UTF-8?q?perf:=20=E6=B7=BB=E5=8A=A0=20kael=20ter?= =?UTF-8?q?minal=20=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/const.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/terminal/const.py b/apps/terminal/const.py index b8a33cee7..16f1f0341 100644 --- a/apps/terminal/const.py +++ b/apps/terminal/const.py @@ -50,6 +50,7 @@ class TerminalType(TextChoices): tinker = 'tinker', 'Tinker' video_worker = 'video_worker', 'Video Worker' chen = 'chen', 'Chen' + kael = 'kael', 'Kael' @classmethod def types(cls): From 2b51a7590eeb124a8a9c6925896463da6fd74802 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 11 Jul 2023 11:28:09 +0800 Subject: [PATCH 104/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20api=20mode?= =?UTF-8?q?=20=E5=92=8C=20i18n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/const/protocol.py | 12 +- apps/assets/serializers/asset/gpt.py | 9 + apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 297 ++++++++++++++++----------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 293 +++++++++++++++----------- 6 files changed, 374 insertions(+), 245 deletions(-) diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index 2f4f9998f..1eff23a49 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.db import models from django.utils.translation import gettext_lazy as _ @@ -187,7 +188,7 @@ class Protocol(ChoicesMixin, models.TextChoices): @classmethod def gpt_protocols(cls): - return { + protocols = { cls.chatgpt: { 'port': 443, 'required': True, @@ -201,13 +202,18 @@ class Protocol(ChoicesMixin, models.TextChoices): 'choices': [ ('gpt-3.5-turbo', 'GPT-3.5 Turbo'), ('gpt-3.5-turbo-16k', 'GPT-3.5 Turbo 16K'), - ('gpt-4', 'GPT-4'), - ('gpt-4-32k', 'GPT-4 32K'), ] } } } } + if settings.XPACK_ENABLED: + choices = protocols[cls.chatgpt]['setting']['api_mode']['choices'] + choices.extend([ + ('gpt-4', 'GPT-4'), + ('gpt-4-32k', 'GPT-4 32K'), + ]) + return protocols @classmethod @cached_method(ttl=600) diff --git a/apps/assets/serializers/asset/gpt.py b/apps/assets/serializers/asset/gpt.py index 88e28ed60..9c79da313 100644 --- a/apps/assets/serializers/asset/gpt.py +++ b/apps/assets/serializers/asset/gpt.py @@ -1,3 +1,5 @@ +from django.utils.translation import gettext_lazy as _ + from assets.models import GPT from .common import AssetSerializer @@ -12,4 +14,11 @@ class GPTSerializer(AssetSerializer): ] extra_kwargs = { **AssetSerializer.Meta.extra_kwargs, + 'proxy': { + 'help_text': _( + 'If the server cannot directly connect to the API address, ' + 'you need set up an HTTP proxy. ' + 'e.g. http(s)://host:port' + ), + 'label': _('HTTP proxy')} } diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 809f19e6d..2d02dd7eb 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e28e9c4ff5d91a24d0c176a134f913de93f4a9bd3e9c8fd7aeacaf875a242d5 -size 145813 +oid sha256:3c01e373aea806f104ae77bb4dfbeab1a9c5d4af9ca5c421f62b40f00bbf4b33 +size 147721 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 42a8a81b1..b45d415ff 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-04 18:28+0800\n" +"POT-Creation-Date: 2023-07-11 11:18+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -49,49 +49,55 @@ msgstr "アクセスキー" msgid "Token" msgstr "トークン" -#: accounts/const/account.py:13 common/db/fields.py:244 +#: accounts/const/account.py:10 +#, fuzzy +#| msgid "API Key" +msgid "API key" +msgstr "API Key" + +#: accounts/const/account.py:14 common/db/fields.py:244 #: settings/serializers/terminal.py:14 msgid "All" msgstr "すべて" -#: accounts/const/account.py:14 +#: accounts/const/account.py:15 msgid "Manual input" msgstr "手動入力" -#: accounts/const/account.py:15 +#: accounts/const/account.py:16 msgid "Dynamic user" msgstr "動的コード" -#: accounts/const/account.py:16 +#: accounts/const/account.py:17 msgid "Anonymous account" msgstr "匿名ユーザー" -#: accounts/const/account.py:20 users/models/user.py:699 +#: accounts/const/account.py:21 users/models/user.py:699 msgid "Local" msgstr "ローカル" -#: accounts/const/account.py:21 +#: accounts/const/account.py:22 msgid "Collected" msgstr "集めました" -#: accounts/const/account.py:22 accounts/serializers/account/account.py:27 +#: accounts/const/account.py:23 accounts/serializers/account/account.py:27 #: settings/serializers/auth/sms.py:75 msgid "Template" msgstr "テンプレート" -#: accounts/const/account.py:26 ops/const.py:45 +#: accounts/const/account.py:27 ops/const.py:45 msgid "Skip" msgstr "スキップ" -#: accounts/const/account.py:27 audits/const.py:24 rbac/tree.py:229 +#: accounts/const/account.py:28 audits/const.py:24 rbac/tree.py:229 #: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 msgid "Update" msgstr "更新" -#: accounts/const/account.py:28 +#: accounts/const/account.py:29 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:62 xpack/plugins/cloud/const.py:41 +#: ops/const.py:58 terminal/const.py:63 xpack/plugins/cloud/const.py:43 msgid "Failed" msgstr "失敗しました" @@ -484,7 +490,7 @@ msgstr "アカウントの確認" #: assets/models/asset/common.py:91 assets/models/asset/common.py:149 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:17 assets/models/label.py:18 -#: assets/models/platform.py:13 assets/models/platform.py:81 +#: assets/models/platform.py:15 assets/models/platform.py:88 #: assets/serializers/asset/common.py:145 assets/serializers/platform.py:109 #: assets/serializers/platform.py:209 #: authentication/serializers/connect_token_secret.py:110 ops/mixin.py:21 @@ -564,7 +570,7 @@ msgid "Exist policy" msgstr "アカウントの存在ポリシー" #: accounts/serializers/account/account.py:180 applications/models.py:11 -#: assets/models/label.py:21 assets/models/platform.py:82 +#: assets/models/label.py:21 assets/models/platform.py:89 #: assets/serializers/asset/common.py:121 assets/serializers/cagegory.py:8 #: assets/serializers/platform.py:127 assets/serializers/platform.py:210 #: perms/serializers/user_permission.py:26 settings/models.py:35 @@ -576,7 +582,7 @@ msgstr "カテゴリ" #: accounts/serializers/automations/base.py:54 acls/models/command_acl.py:24 #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 -#: assets/models/cmd_filter.py:74 assets/models/platform.py:83 +#: assets/models/cmd_filter.py:74 assets/models/platform.py:90 #: assets/serializers/asset/common.py:122 assets/serializers/platform.py:111 #: assets/serializers/platform.py:126 audits/serializers.py:48 #: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:103 @@ -738,7 +744,7 @@ msgstr "自動タスク実行履歴" #: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:40 -#: terminal/const.py:61 terminal/models/session/sharing.py:107 +#: terminal/const.py:62 terminal/models/session/sharing.py:107 #: tickets/views/approve.py:114 msgid "Success" msgstr "成功" @@ -834,7 +840,7 @@ msgid "Accounts" msgstr "アカウント" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:55 terminal/const.py:69 +#: ops/serializers/job.py:55 terminal/const.py:70 #: terminal/models/session/session.py:42 terminal/serializers/command.py:18 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 @@ -961,7 +967,7 @@ msgid "Applications" msgstr "アプリケーション" #: applications/models.py:16 xpack/plugins/cloud/models.py:33 -#: xpack/plugins/cloud/serializers/account.py:62 +#: xpack/plugins/cloud/serializers/account.py:63 msgid "Attrs" msgstr "ツールバーの" @@ -1086,12 +1092,13 @@ msgstr "データベース" msgid "Cloud service" msgstr "クラウド サービス" -#: assets/const/category.py:14 assets/models/asset/web.py:16 audits/const.py:34 +#: assets/const/category.py:14 assets/models/asset/gpt.py:11 +#: assets/models/asset/web.py:16 audits/const.py:34 #: terminal/models/applet/applet.py:26 msgid "Web" msgstr "Web" -#: assets/const/category.py:15 common/sdk/sms/endpoint.py:20 +#: assets/const/category.py:16 common/sdk/sms/endpoint.py:20 msgid "Custom type" msgstr "カスタムタイプ" @@ -1124,60 +1131,74 @@ msgstr "ルーター" msgid "Firewall" msgstr "ファイアウォール" +#: assets/const/gpt.py:7 +msgid "ChatGPT" +msgstr "" + #: assets/const/host.py:12 rbac/tree.py:28 msgid "Other" msgstr "その他" -#: assets/const/protocol.py:39 +#: assets/const/protocol.py:42 msgid "SFTP enabled" msgstr "SFTP が有効" -#: assets/const/protocol.py:44 +#: assets/const/protocol.py:47 msgid "SFTP home" msgstr "SFTP ルート パス" -#: assets/const/protocol.py:55 +#: assets/const/protocol.py:58 msgid "Console" msgstr "Console" -#: assets/const/protocol.py:56 +#: assets/const/protocol.py:59 msgid "Connect to console session" msgstr "コンソールセッションに接続" -#: assets/const/protocol.py:60 +#: assets/const/protocol.py:63 msgid "Any" msgstr "任意" -#: assets/const/protocol.py:62 settings/serializers/security.py:151 +#: assets/const/protocol.py:65 settings/serializers/security.py:151 msgid "Security" msgstr "セキュリティ" -#: assets/const/protocol.py:63 +#: assets/const/protocol.py:66 msgid "Security layer to use for the connection" msgstr "接続に使用するセキュリティ レイヤー" -#: assets/const/protocol.py:87 assets/models/asset/database.py:10 +#: assets/const/protocol.py:72 +#, fuzzy +#| msgid "Domain" +msgid "AD domain" +msgstr "ドメイン" + +#: assets/const/protocol.py:91 assets/models/asset/database.py:10 #: settings/serializers/email.py:37 msgid "Use SSL" msgstr "SSLの使用" -#: assets/const/protocol.py:140 +#: assets/const/protocol.py:144 msgid "Auth username" msgstr "ユーザー名で認証する" -#: assets/const/protocol.py:167 assets/models/asset/web.py:10 +#: assets/const/protocol.py:172 assets/models/asset/web.py:10 msgid "Username selector" msgstr "ユーザー名ピッカー" -#: assets/const/protocol.py:172 assets/models/asset/web.py:11 +#: assets/const/protocol.py:177 assets/models/asset/web.py:11 msgid "Password selector" msgstr "パスワードセレクター" -#: assets/const/protocol.py:177 assets/models/asset/web.py:12 +#: assets/const/protocol.py:182 assets/models/asset/web.py:12 msgid "Submit selector" msgstr "ボタンセレクターを確認する" -#: assets/const/types.py:222 +#: assets/const/protocol.py:200 +msgid "API mode" +msgstr "APIモード" + +#: assets/const/types.py:224 msgid "All types" msgstr "いろんなタイプ" @@ -1304,7 +1325,7 @@ msgstr "システムユーザーに一致できます" msgid "Cloud" msgstr "クラウド サービス" -#: assets/models/asset/common.py:92 assets/models/platform.py:14 +#: assets/models/asset/common.py:92 assets/models/platform.py:16 #: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:68 #: xpack/plugins/cloud/serializers/account_attrs.py:73 msgid "Port" @@ -1314,7 +1335,7 @@ msgstr "ポート" msgid "Address" msgstr "アドレス" -#: assets/models/asset/common.py:151 assets/models/platform.py:112 +#: assets/models/asset/common.py:151 assets/models/platform.py:119 #: authentication/serializers/connect_token_secret.py:115 #: perms/serializers/user_permission.py:24 #: xpack/plugins/cloud/serializers/account_attrs.py:196 @@ -1376,6 +1397,10 @@ msgstr "クライアントキー" msgid "Allow invalid cert" msgstr "証明書チェックを無視" +#: assets/models/asset/gpt.py:8 +msgid "Proxy" +msgstr "" + #: assets/models/asset/web.py:9 assets/serializers/asset/info/spec.py:16 msgid "Autofill" msgstr "自動充填" @@ -1462,7 +1487,7 @@ msgstr "ゲートウェイ" msgid "Asset group" msgstr "資産グループ" -#: assets/models/group.py:31 assets/models/platform.py:17 +#: assets/models/group.py:31 assets/models/platform.py:19 #: assets/serializers/platform.py:112 #: xpack/plugins/cloud/providers/nutanix.py:30 msgid "Default" @@ -1522,120 +1547,120 @@ msgstr "ノード" msgid "Can match node" msgstr "ノードを一致させることができます" -#: assets/models/platform.py:15 +#: assets/models/platform.py:17 msgid "Primary" msgstr "主要" -#: assets/models/platform.py:16 +#: assets/models/platform.py:18 msgid "Required" msgstr "必要" -#: assets/models/platform.py:18 +#: assets/models/platform.py:20 msgid "Public" msgstr "開ける" -#: assets/models/platform.py:19 assets/serializers/platform.py:48 +#: assets/models/platform.py:21 assets/serializers/platform.py:48 #: settings/serializers/settings.py:67 #: users/templates/users/reset_password.html:29 msgid "Setting" msgstr "設定" -#: assets/models/platform.py:31 audits/const.py:48 settings/models.py:37 +#: assets/models/platform.py:38 audits/const.py:48 settings/models.py:37 #: terminal/serializers/applet_host.py:33 msgid "Enabled" msgstr "有効化" -#: assets/models/platform.py:32 +#: assets/models/platform.py:39 msgid "Ansible config" msgstr "Ansible 構成" -#: assets/models/platform.py:34 assets/serializers/platform.py:32 +#: assets/models/platform.py:41 assets/serializers/platform.py:32 msgid "Ping enabled" msgstr "アセット ディスカバリを有効にする" -#: assets/models/platform.py:35 assets/serializers/platform.py:33 +#: assets/models/platform.py:42 assets/serializers/platform.py:33 msgid "Ping method" msgstr "資産検出方法" -#: assets/models/platform.py:36 +#: assets/models/platform.py:43 msgid "Ping params" msgstr "資産検出パラメータ" -#: assets/models/platform.py:38 assets/models/platform.py:62 +#: assets/models/platform.py:45 assets/models/platform.py:69 #: assets/serializers/platform.py:34 msgid "Gather facts enabled" msgstr "資産情報の収集を有効にする" -#: assets/models/platform.py:40 assets/models/platform.py:64 +#: assets/models/platform.py:47 assets/models/platform.py:71 #: assets/serializers/platform.py:35 msgid "Gather facts method" msgstr "情報収集の方法" -#: assets/models/platform.py:42 assets/models/platform.py:66 +#: assets/models/platform.py:49 assets/models/platform.py:73 msgid "Gather facts params" msgstr "情報収集パラメータ" -#: assets/models/platform.py:44 assets/serializers/platform.py:38 +#: assets/models/platform.py:51 assets/serializers/platform.py:38 msgid "Change secret enabled" msgstr "パスワードの変更が有効" -#: assets/models/platform.py:46 assets/serializers/platform.py:39 +#: assets/models/platform.py:53 assets/serializers/platform.py:39 msgid "Change secret method" msgstr "パスワード変更モード" -#: assets/models/platform.py:48 +#: assets/models/platform.py:55 msgid "Change secret params" msgstr "パスワード変更パラメータ" -#: assets/models/platform.py:50 assets/serializers/platform.py:40 +#: assets/models/platform.py:57 assets/serializers/platform.py:40 msgid "Push account enabled" msgstr "アカウントのプッシュを有効にする" -#: assets/models/platform.py:52 assets/serializers/platform.py:41 +#: assets/models/platform.py:59 assets/serializers/platform.py:41 msgid "Push account method" msgstr "アカウントプッシュ方式" -#: assets/models/platform.py:54 +#: assets/models/platform.py:61 msgid "Push account params" msgstr "アカウントプッシュパラメータ" -#: assets/models/platform.py:56 assets/serializers/platform.py:36 +#: assets/models/platform.py:63 assets/serializers/platform.py:36 msgid "Verify account enabled" msgstr "アカウントの確認をオンにする" -#: assets/models/platform.py:58 assets/serializers/platform.py:37 +#: assets/models/platform.py:65 assets/serializers/platform.py:37 msgid "Verify account method" msgstr "アカウント認証方法" -#: assets/models/platform.py:60 +#: assets/models/platform.py:67 msgid "Verify account params" msgstr "アカウント認証パラメータ" -#: assets/models/platform.py:84 tickets/models/ticket/general.py:300 +#: assets/models/platform.py:91 tickets/models/ticket/general.py:300 msgid "Meta" msgstr "メタ" -#: assets/models/platform.py:85 +#: assets/models/platform.py:92 msgid "Internal" msgstr "ビルトイン" -#: assets/models/platform.py:89 assets/serializers/platform.py:125 +#: assets/models/platform.py:96 assets/serializers/platform.py:125 msgid "Charset" msgstr "シャーセット" -#: assets/models/platform.py:91 assets/serializers/platform.py:153 +#: assets/models/platform.py:98 assets/serializers/platform.py:153 msgid "Domain enabled" msgstr "ドメインを有効にする" -#: assets/models/platform.py:93 assets/serializers/platform.py:152 +#: assets/models/platform.py:100 assets/serializers/platform.py:152 msgid "Su enabled" msgstr "アカウントの切り替えを有効にする" -#: assets/models/platform.py:94 assets/serializers/platform.py:131 +#: assets/models/platform.py:101 assets/serializers/platform.py:131 msgid "Su method" msgstr "アカウントの切り替え方法" -#: assets/models/platform.py:95 assets/serializers/platform.py:134 +#: assets/models/platform.py:102 assets/serializers/platform.py:134 msgid "Custom fields" msgstr "カスタムフィールド" @@ -1694,6 +1719,16 @@ msgstr "デフォルト・データベース" msgid "This field is required." msgstr "このフィールドは必須です。" +#: assets/serializers/asset/gpt.py:19 +msgid "" +"If the server cannot directly connect to the API address, you need set up an " +"HTTP proxy. e.g. http(s)://host:port" +msgstr "サーバーが API アドレスに直接接続できない場合は、HTTP プロキシを設定する必要があります。例: http(s)://host:port" + +#: assets/serializers/asset/gpt.py:23 +msgid "HTTP proxy" +msgstr "HTTP プロキシ" + #: assets/serializers/asset/info/gathered.py:6 msgid "Vendor" msgstr "ベンダー" @@ -1776,6 +1811,10 @@ msgstr "アカウント収集を有効にする" msgid "Gather accounts method" msgstr "アカウントの収集方法" +#: assets/serializers/platform.py:49 +msgid "Port from addr" +msgstr "アドレスからのポート" + #: assets/serializers/platform.py:60 msgid "" "This protocol is primary, and it must be set when adding assets. " @@ -2963,7 +3002,7 @@ msgid "Copy success" msgstr "コピー成功" #: authentication/utils.py:28 common/utils/ip/geoip/utils.py:24 -#: xpack/plugins/cloud/const.py:27 +#: xpack/plugins/cloud/const.py:29 msgid "LAN" msgstr "ローカルエリアネットワーク" @@ -3118,7 +3157,7 @@ msgstr "タイミングトリガー" msgid "Ready" msgstr "の準備を" -#: common/const/choices.py:16 terminal/const.py:60 tickets/const.py:29 +#: common/const/choices.py:16 terminal/const.py:61 tickets/const.py:29 #: tickets/const.py:39 msgid "Pending" msgstr "未定" @@ -5294,7 +5333,7 @@ msgstr "" msgid "Periodic import ldap user" msgstr "LDAP ユーザーを定期的にインポートする" -#: settings/tasks/ldap.py:47 +#: settings/tasks/ldap.py:46 msgid "Registration periodic import ldap user task" msgstr "登録サイクルLDAPユーザータスクのインポート" @@ -5485,8 +5524,8 @@ msgstr "期限切れです。" #, python-format msgid "" "\n" -" Your password has expired, please click this link update password.\n" +" Your password has expired, please click this link update password.\n" " " msgstr "" "\n" @@ -5507,34 +5546,34 @@ msgid "" " " msgstr "" "\n" -" クリックしてください リンク パスワードの更新\n" +" クリックしてください リンク パスワードの更新\n" " " #: templates/_message.html:43 #, python-format msgid "" "\n" -" Your information was incomplete. Please click this link to complete your information.\n" +" Your information was incomplete. Please click this link to complete your information.\n" " " msgstr "" "\n" -" あなたの情報が不完全なので、クリックしてください。 リンク 補完\n" +" あなたの情報が不完全なので、クリックしてください。 リンク 補完\n" " " #: templates/_message.html:56 #, python-format msgid "" "\n" -" Your ssh public key not set or expired. Please click this link to update\n" +" Your ssh public key not set or expired. Please click this link to update\n" " " msgstr "" "\n" -" SSHキーが設定されていないか無効になっている場合は、 リンク 更新\n" +" SSHキーが設定されていないか無効になっている場合は、 リンク 更新\n" " " #: templates/_mfa_login_field.html:28 @@ -5693,7 +5732,7 @@ msgstr "クリティカル" msgid "High" msgstr "高い" -#: terminal/const.py:32 terminal/const.py:67 +#: terminal/const.py:32 terminal/const.py:68 #: users/templates/users/reset_password.html:50 msgid "Normal" msgstr "正常" @@ -5702,23 +5741,23 @@ msgstr "正常" msgid "Offline" msgstr "オフライン" -#: terminal/const.py:63 +#: terminal/const.py:64 msgid "Mismatch" msgstr "一致しない" -#: terminal/const.py:68 +#: terminal/const.py:69 msgid "Tunnel" msgstr "" -#: terminal/const.py:70 +#: terminal/const.py:71 msgid "SFTP" msgstr "SFTP" -#: terminal/const.py:74 +#: terminal/const.py:75 msgid "Read Only" msgstr "読み取り専用" -#: terminal/const.py:75 +#: terminal/const.py:76 msgid "Writable" msgstr "書き込み可能" @@ -6761,6 +6800,7 @@ msgid "Not a valid ssh public key" msgstr "有効なssh公開鍵ではありません" #: users/forms/profile.py:173 users/models/user.py:786 +#: xpack/plugins/cloud/serializers/account_attrs.py:206 msgid "Public key" msgstr "公開キー" @@ -6789,6 +6829,7 @@ msgid "OTP secret key" msgstr "OTP 秘密" #: users/models/user.py:783 +#: xpack/plugins/cloud/serializers/account_attrs.py:209 msgid "Private key" msgstr "ssh秘密鍵" @@ -7268,70 +7309,76 @@ msgid "Tencent Cloud (Lighthouse)" msgstr "テンセント雲(軽量アプリケーション)" #: xpack/plugins/cloud/const.py:19 -msgid "VMware" -msgstr "VMware" - -#: xpack/plugins/cloud/const.py:20 xpack/plugins/cloud/providers/nutanix.py:13 -msgid "Nutanix" -msgstr "Nutanix" - -#: xpack/plugins/cloud/const.py:21 -msgid "Huawei Private Cloud" -msgstr "華為私有雲" - -#: xpack/plugins/cloud/const.py:22 -msgid "Qingyun Private Cloud" -msgstr "青雲私有雲" - -#: xpack/plugins/cloud/const.py:23 -msgid "CTYun Private Cloud" -msgstr "スカイウィング私有雲" - -#: xpack/plugins/cloud/const.py:24 -msgid "OpenStack" -msgstr "OpenStack" - -#: xpack/plugins/cloud/const.py:25 msgid "Google Cloud Platform" msgstr "谷歌雲" +#: xpack/plugins/cloud/const.py:20 +#, fuzzy +#| msgid "Cloud" +msgid "UCloud" +msgstr "クラウド サービス" + +#: xpack/plugins/cloud/const.py:22 +msgid "VMware" +msgstr "VMware" + +#: xpack/plugins/cloud/const.py:23 xpack/plugins/cloud/providers/nutanix.py:13 +msgid "Nutanix" +msgstr "Nutanix" + +#: xpack/plugins/cloud/const.py:24 +msgid "Huawei Private Cloud" +msgstr "華為私有雲" + +#: xpack/plugins/cloud/const.py:25 +msgid "Qingyun Private Cloud" +msgstr "青雲私有雲" + #: xpack/plugins/cloud/const.py:26 +msgid "CTYun Private Cloud" +msgstr "スカイウィング私有雲" + +#: xpack/plugins/cloud/const.py:27 +msgid "OpenStack" +msgstr "OpenStack" + +#: xpack/plugins/cloud/const.py:28 msgid "Fusion Compute" msgstr "融合計算" -#: xpack/plugins/cloud/const.py:31 +#: xpack/plugins/cloud/const.py:33 msgid "Private IP" msgstr "プライベートIP" -#: xpack/plugins/cloud/const.py:32 +#: xpack/plugins/cloud/const.py:34 msgid "Public IP" msgstr "パブリックIP" -#: xpack/plugins/cloud/const.py:36 +#: xpack/plugins/cloud/const.py:38 msgid "Instance name" msgstr "インスタンス名" -#: xpack/plugins/cloud/const.py:37 +#: xpack/plugins/cloud/const.py:39 msgid "Instance name and Partial IP" msgstr "インスタンス名と部分IP" -#: xpack/plugins/cloud/const.py:42 +#: xpack/plugins/cloud/const.py:44 msgid "Succeed" msgstr "成功" -#: xpack/plugins/cloud/const.py:46 +#: xpack/plugins/cloud/const.py:48 msgid "Unsync" msgstr "同期していません" -#: xpack/plugins/cloud/const.py:47 +#: xpack/plugins/cloud/const.py:49 msgid "New Sync" msgstr "新しい同期" -#: xpack/plugins/cloud/const.py:48 +#: xpack/plugins/cloud/const.py:50 msgid "Synced" msgstr "同期済み" -#: xpack/plugins/cloud/const.py:49 +#: xpack/plugins/cloud/const.py:51 msgid "Released" msgstr "リリース済み" @@ -7597,11 +7644,11 @@ msgstr "華南-広州-友好ユーザー環境" msgid "CN East-Suqian" msgstr "華東-宿遷" -#: xpack/plugins/cloud/serializers/account.py:63 +#: xpack/plugins/cloud/serializers/account.py:64 msgid "Validity display" msgstr "有効表示" -#: xpack/plugins/cloud/serializers/account.py:64 +#: xpack/plugins/cloud/serializers/account.py:65 msgid "Provider display" msgstr "プロバイダ表示" @@ -7621,6 +7668,7 @@ msgstr "サブスクリプションID" #: xpack/plugins/cloud/serializers/account_attrs.py:103 #: xpack/plugins/cloud/serializers/account_attrs.py:119 #: xpack/plugins/cloud/serializers/account_attrs.py:149 +#: xpack/plugins/cloud/serializers/account_attrs.py:202 msgid "API Endpoint" msgstr "APIエンドポイント" @@ -7686,6 +7734,12 @@ msgstr "テストポート" msgid "Test timeout" msgstr "テストタイムアウト" +#: xpack/plugins/cloud/serializers/account_attrs.py:212 +#, fuzzy +#| msgid "Reject" +msgid "Project" +msgstr "拒否" + #: xpack/plugins/cloud/serializers/task.py:28 msgid "" "Only instances matching the IP range will be synced.
If the instance " @@ -7784,5 +7838,8 @@ msgstr "究極のエディション" msgid "Community edition" msgstr "コミュニティ版" +#~ msgid "e.g. http(s)://host" +#~ msgstr "HTTP プロキシ、例えば http(s)://host" + #~ msgid "Please enable cookies and try again." #~ msgstr "クッキーを有効にして、もう一度お試しください。" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 131e221ae..f9f875d29 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:092b15ed84725ceb974bd46407e3d247e6ff9d0505b6044f18c122bf6da1b7f6 -size 119308 +oid sha256:3d81d525d06bd1446780753e7627adbcc344144a3c0ed856d7953b9758913028 +size 120819 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 339c287d6..f5dfcabd4 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-04 18:28+0800\n" +"POT-Creation-Date: 2023-07-11 11:18+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -48,49 +48,55 @@ msgstr "Access key" msgid "Token" msgstr "Token" -#: accounts/const/account.py:13 common/db/fields.py:244 +#: accounts/const/account.py:10 +#, fuzzy +#| msgid "API Key" +msgid "API key" +msgstr "API Key" + +#: accounts/const/account.py:14 common/db/fields.py:244 #: settings/serializers/terminal.py:14 msgid "All" msgstr "全部" -#: accounts/const/account.py:14 +#: accounts/const/account.py:15 msgid "Manual input" msgstr "手动输入" -#: accounts/const/account.py:15 +#: accounts/const/account.py:16 msgid "Dynamic user" msgstr "同名账号" -#: accounts/const/account.py:16 +#: accounts/const/account.py:17 msgid "Anonymous account" msgstr "匿名账号" -#: accounts/const/account.py:20 users/models/user.py:699 +#: accounts/const/account.py:21 users/models/user.py:699 msgid "Local" msgstr "数据库" -#: accounts/const/account.py:21 +#: accounts/const/account.py:22 msgid "Collected" msgstr "收集" -#: accounts/const/account.py:22 accounts/serializers/account/account.py:27 +#: accounts/const/account.py:23 accounts/serializers/account/account.py:27 #: settings/serializers/auth/sms.py:75 msgid "Template" msgstr "模板" -#: accounts/const/account.py:26 ops/const.py:45 +#: accounts/const/account.py:27 ops/const.py:45 msgid "Skip" msgstr "跳过" -#: accounts/const/account.py:27 audits/const.py:24 rbac/tree.py:229 +#: accounts/const/account.py:28 audits/const.py:24 rbac/tree.py:229 #: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 msgid "Update" msgstr "更新" -#: accounts/const/account.py:28 +#: accounts/const/account.py:29 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:62 xpack/plugins/cloud/const.py:41 +#: ops/const.py:58 terminal/const.py:63 xpack/plugins/cloud/const.py:43 msgid "Failed" msgstr "失败" @@ -483,7 +489,7 @@ msgstr "账号验证" #: assets/models/asset/common.py:91 assets/models/asset/common.py:149 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:17 assets/models/label.py:18 -#: assets/models/platform.py:13 assets/models/platform.py:81 +#: assets/models/platform.py:15 assets/models/platform.py:88 #: assets/serializers/asset/common.py:145 assets/serializers/platform.py:109 #: assets/serializers/platform.py:209 #: authentication/serializers/connect_token_secret.py:110 ops/mixin.py:21 @@ -560,7 +566,7 @@ msgid "Exist policy" msgstr "账号存在策略" #: accounts/serializers/account/account.py:180 applications/models.py:11 -#: assets/models/label.py:21 assets/models/platform.py:82 +#: assets/models/label.py:21 assets/models/platform.py:89 #: assets/serializers/asset/common.py:121 assets/serializers/cagegory.py:8 #: assets/serializers/platform.py:127 assets/serializers/platform.py:210 #: perms/serializers/user_permission.py:26 settings/models.py:35 @@ -572,7 +578,7 @@ msgstr "类别" #: accounts/serializers/automations/base.py:54 acls/models/command_acl.py:24 #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 -#: assets/models/cmd_filter.py:74 assets/models/platform.py:83 +#: assets/models/cmd_filter.py:74 assets/models/platform.py:90 #: assets/serializers/asset/common.py:122 assets/serializers/platform.py:111 #: assets/serializers/platform.py:126 audits/serializers.py:48 #: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:103 @@ -734,7 +740,7 @@ msgstr "自动化任务执行历史" #: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:40 -#: terminal/const.py:61 terminal/models/session/sharing.py:107 +#: terminal/const.py:62 terminal/models/session/sharing.py:107 #: tickets/views/approve.py:114 msgid "Success" msgstr "成功" @@ -830,7 +836,7 @@ msgid "Accounts" msgstr "账号管理" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:55 terminal/const.py:69 +#: ops/serializers/job.py:55 terminal/const.py:70 #: terminal/models/session/session.py:42 terminal/serializers/command.py:18 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 @@ -956,7 +962,7 @@ msgid "Applications" msgstr "应用管理" #: applications/models.py:16 xpack/plugins/cloud/models.py:33 -#: xpack/plugins/cloud/serializers/account.py:62 +#: xpack/plugins/cloud/serializers/account.py:63 msgid "Attrs" msgstr "属性" @@ -1079,12 +1085,13 @@ msgstr "数据库" msgid "Cloud service" msgstr "云服务" -#: assets/const/category.py:14 assets/models/asset/web.py:16 audits/const.py:34 +#: assets/const/category.py:14 assets/models/asset/gpt.py:11 +#: assets/models/asset/web.py:16 audits/const.py:34 #: terminal/models/applet/applet.py:26 msgid "Web" msgstr "Web" -#: assets/const/category.py:15 common/sdk/sms/endpoint.py:20 +#: assets/const/category.py:16 common/sdk/sms/endpoint.py:20 msgid "Custom type" msgstr "自定义" @@ -1117,60 +1124,74 @@ msgstr "路由器" msgid "Firewall" msgstr "防火墙" +#: assets/const/gpt.py:7 +msgid "ChatGPT" +msgstr "ChatGPT" + #: assets/const/host.py:12 rbac/tree.py:28 msgid "Other" msgstr "其它" -#: assets/const/protocol.py:39 +#: assets/const/protocol.py:42 msgid "SFTP enabled" msgstr "SFTP 已启用" -#: assets/const/protocol.py:44 +#: assets/const/protocol.py:47 msgid "SFTP home" msgstr "SFTP 根路径" -#: assets/const/protocol.py:55 +#: assets/const/protocol.py:58 msgid "Console" msgstr "控制台" -#: assets/const/protocol.py:56 +#: assets/const/protocol.py:59 msgid "Connect to console session" msgstr "连接到控制台会话" -#: assets/const/protocol.py:60 +#: assets/const/protocol.py:63 msgid "Any" msgstr "任意" -#: assets/const/protocol.py:62 settings/serializers/security.py:151 +#: assets/const/protocol.py:65 settings/serializers/security.py:151 msgid "Security" msgstr "安全" -#: assets/const/protocol.py:63 +#: assets/const/protocol.py:66 msgid "Security layer to use for the connection" msgstr "连接 RDP 使用的安全层" -#: assets/const/protocol.py:87 assets/models/asset/database.py:10 +#: assets/const/protocol.py:72 +#, fuzzy +#| msgid "Domain" +msgid "AD domain" +msgstr "网域" + +#: assets/const/protocol.py:91 assets/models/asset/database.py:10 #: settings/serializers/email.py:37 msgid "Use SSL" msgstr "使用 SSL" -#: assets/const/protocol.py:140 +#: assets/const/protocol.py:144 msgid "Auth username" msgstr "使用用户名认证" -#: assets/const/protocol.py:167 assets/models/asset/web.py:10 +#: assets/const/protocol.py:172 assets/models/asset/web.py:10 msgid "Username selector" msgstr "用户名选择器" -#: assets/const/protocol.py:172 assets/models/asset/web.py:11 +#: assets/const/protocol.py:177 assets/models/asset/web.py:11 msgid "Password selector" msgstr "密码选择器" -#: assets/const/protocol.py:177 assets/models/asset/web.py:12 +#: assets/const/protocol.py:182 assets/models/asset/web.py:12 msgid "Submit selector" msgstr "确认按钮选择器" -#: assets/const/types.py:222 +#: assets/const/protocol.py:200 +msgid "API mode" +msgstr "API 模式" + +#: assets/const/types.py:224 msgid "All types" msgstr "所有类型" @@ -1297,7 +1318,7 @@ msgstr "可以匹配系统用户" msgid "Cloud" msgstr "云服务" -#: assets/models/asset/common.py:92 assets/models/platform.py:14 +#: assets/models/asset/common.py:92 assets/models/platform.py:16 #: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:68 #: xpack/plugins/cloud/serializers/account_attrs.py:73 msgid "Port" @@ -1307,7 +1328,7 @@ msgstr "端口" msgid "Address" msgstr "地址" -#: assets/models/asset/common.py:151 assets/models/platform.py:112 +#: assets/models/asset/common.py:151 assets/models/platform.py:119 #: authentication/serializers/connect_token_secret.py:115 #: perms/serializers/user_permission.py:24 #: xpack/plugins/cloud/serializers/account_attrs.py:196 @@ -1369,6 +1390,10 @@ msgstr "客户端密钥" msgid "Allow invalid cert" msgstr "忽略证书校验" +#: assets/models/asset/gpt.py:8 +msgid "Proxy" +msgstr "" + #: assets/models/asset/web.py:9 assets/serializers/asset/info/spec.py:16 msgid "Autofill" msgstr "自动代填" @@ -1455,7 +1480,7 @@ msgstr "网关" msgid "Asset group" msgstr "资产组" -#: assets/models/group.py:31 assets/models/platform.py:17 +#: assets/models/group.py:31 assets/models/platform.py:19 #: assets/serializers/platform.py:112 #: xpack/plugins/cloud/providers/nutanix.py:30 msgid "Default" @@ -1515,120 +1540,120 @@ msgstr "节点" msgid "Can match node" msgstr "可以匹配节点" -#: assets/models/platform.py:15 +#: assets/models/platform.py:17 msgid "Primary" msgstr "主要的" -#: assets/models/platform.py:16 +#: assets/models/platform.py:18 msgid "Required" msgstr "必须的" -#: assets/models/platform.py:18 +#: assets/models/platform.py:20 msgid "Public" msgstr "开放的" -#: assets/models/platform.py:19 assets/serializers/platform.py:48 +#: assets/models/platform.py:21 assets/serializers/platform.py:48 #: settings/serializers/settings.py:67 #: users/templates/users/reset_password.html:29 msgid "Setting" msgstr "设置" -#: assets/models/platform.py:31 audits/const.py:48 settings/models.py:37 +#: assets/models/platform.py:38 audits/const.py:48 settings/models.py:37 #: terminal/serializers/applet_host.py:33 msgid "Enabled" msgstr "启用" -#: assets/models/platform.py:32 +#: assets/models/platform.py:39 msgid "Ansible config" msgstr "Ansible 配置" -#: assets/models/platform.py:34 assets/serializers/platform.py:32 +#: assets/models/platform.py:41 assets/serializers/platform.py:32 msgid "Ping enabled" msgstr "启用资产探活" -#: assets/models/platform.py:35 assets/serializers/platform.py:33 +#: assets/models/platform.py:42 assets/serializers/platform.py:33 msgid "Ping method" msgstr "资产探活方式" -#: assets/models/platform.py:36 +#: assets/models/platform.py:43 msgid "Ping params" msgstr "资产探活参数" -#: assets/models/platform.py:38 assets/models/platform.py:62 +#: assets/models/platform.py:45 assets/models/platform.py:69 #: assets/serializers/platform.py:34 msgid "Gather facts enabled" msgstr "启用收集资产信息" -#: assets/models/platform.py:40 assets/models/platform.py:64 +#: assets/models/platform.py:47 assets/models/platform.py:71 #: assets/serializers/platform.py:35 msgid "Gather facts method" msgstr "收集信息方式" -#: assets/models/platform.py:42 assets/models/platform.py:66 +#: assets/models/platform.py:49 assets/models/platform.py:73 msgid "Gather facts params" msgstr "收集信息参数" -#: assets/models/platform.py:44 assets/serializers/platform.py:38 +#: assets/models/platform.py:51 assets/serializers/platform.py:38 msgid "Change secret enabled" msgstr "启用改密" -#: assets/models/platform.py:46 assets/serializers/platform.py:39 +#: assets/models/platform.py:53 assets/serializers/platform.py:39 msgid "Change secret method" msgstr "改密方式" -#: assets/models/platform.py:48 +#: assets/models/platform.py:55 msgid "Change secret params" msgstr "改密参数" -#: assets/models/platform.py:50 assets/serializers/platform.py:40 +#: assets/models/platform.py:57 assets/serializers/platform.py:40 msgid "Push account enabled" msgstr "启用账号推送" -#: assets/models/platform.py:52 assets/serializers/platform.py:41 +#: assets/models/platform.py:59 assets/serializers/platform.py:41 msgid "Push account method" msgstr "账号推送方式" -#: assets/models/platform.py:54 +#: assets/models/platform.py:61 msgid "Push account params" msgstr "账号推送参数" -#: assets/models/platform.py:56 assets/serializers/platform.py:36 +#: assets/models/platform.py:63 assets/serializers/platform.py:36 msgid "Verify account enabled" msgstr "开启账号验证" -#: assets/models/platform.py:58 assets/serializers/platform.py:37 +#: assets/models/platform.py:65 assets/serializers/platform.py:37 msgid "Verify account method" msgstr "账号验证方式" -#: assets/models/platform.py:60 +#: assets/models/platform.py:67 msgid "Verify account params" msgstr "账号验证参数" -#: assets/models/platform.py:84 tickets/models/ticket/general.py:300 +#: assets/models/platform.py:91 tickets/models/ticket/general.py:300 msgid "Meta" msgstr "元数据" -#: assets/models/platform.py:85 +#: assets/models/platform.py:92 msgid "Internal" msgstr "内置" -#: assets/models/platform.py:89 assets/serializers/platform.py:125 +#: assets/models/platform.py:96 assets/serializers/platform.py:125 msgid "Charset" msgstr "编码" -#: assets/models/platform.py:91 assets/serializers/platform.py:153 +#: assets/models/platform.py:98 assets/serializers/platform.py:153 msgid "Domain enabled" msgstr "启用网域" -#: assets/models/platform.py:93 assets/serializers/platform.py:152 +#: assets/models/platform.py:100 assets/serializers/platform.py:152 msgid "Su enabled" msgstr "启用账号切换" -#: assets/models/platform.py:94 assets/serializers/platform.py:131 +#: assets/models/platform.py:101 assets/serializers/platform.py:131 msgid "Su method" msgstr "账号切换方式" -#: assets/models/platform.py:95 assets/serializers/platform.py:134 +#: assets/models/platform.py:102 assets/serializers/platform.py:134 msgid "Custom fields" msgstr "自定义属性" @@ -1685,6 +1710,16 @@ msgstr "默认数据库" msgid "This field is required." msgstr "该字段是必填项。" +#: assets/serializers/asset/gpt.py:19 +msgid "" +"If the server cannot directly connect to the API address, you need set up an " +"HTTP proxy. e.g. http(s)://host:port" +msgstr "如果服务器不能直接访问 api 地址,你需要设置一个 HTTP 代理。例如 http(s)://host:port" + +#: assets/serializers/asset/gpt.py:23 +msgid "HTTP proxy" +msgstr "HTTP 代理" + #: assets/serializers/asset/info/gathered.py:6 msgid "Vendor" msgstr "制造商" @@ -1767,6 +1802,10 @@ msgstr "启用账号收集" msgid "Gather accounts method" msgstr "收集账号方式" +#: assets/serializers/platform.py:49 +msgid "Port from addr" +msgstr "端口来自地址" + #: assets/serializers/platform.py:60 msgid "" "This protocol is primary, and it must be set when adding assets. " @@ -2923,7 +2962,7 @@ msgid "Copy success" msgstr "复制成功" #: authentication/utils.py:28 common/utils/ip/geoip/utils.py:24 -#: xpack/plugins/cloud/const.py:27 +#: xpack/plugins/cloud/const.py:29 msgid "LAN" msgstr "局域网" @@ -3078,7 +3117,7 @@ msgstr "定时触发" msgid "Ready" msgstr "准备" -#: common/const/choices.py:16 terminal/const.py:60 tickets/const.py:29 +#: common/const/choices.py:16 terminal/const.py:61 tickets/const.py:29 #: tickets/const.py:39 msgid "Pending" msgstr "待定的" @@ -5217,7 +5256,7 @@ msgstr "提示:在Luna 页面中连接图形化资产时默认使用的分辨 msgid "Periodic import ldap user" msgstr "周期导入 LDAP 用户" -#: settings/tasks/ldap.py:47 +#: settings/tasks/ldap.py:46 msgid "Registration periodic import ldap user task" msgstr "注册周期导入 LDAP 用户 任务" @@ -5403,13 +5442,13 @@ msgstr "过期。" #, python-format msgid "" "\n" -" Your password has expired, please click this link update password.\n" +" Your password has expired, please click this link update password.\n" " " msgstr "" "\n" -" 您的密码已经过期,请点击 链接 更新密码\n" +" 您的密码已经过期,请点击 链接 更新密码\n" " " #: templates/_message.html:30 @@ -5433,8 +5472,8 @@ msgstr "" #, python-format msgid "" "\n" -" Your information was incomplete. Please click this link to complete your information.\n" +" Your information was incomplete. Please click this link to complete your information.\n" " " msgstr "" "\n" @@ -5446,13 +5485,13 @@ msgstr "" #, python-format msgid "" "\n" -" Your ssh public key not set or expired. Please click this link to update\n" +" Your ssh public key not set or expired. Please click this link to update\n" " " msgstr "" "\n" -" 您的SSH密钥没有设置或已失效,请点击 链接 更新\n" +" 您的SSH密钥没有设置或已失效,请点击 链接 更新\n" " " #: templates/_mfa_login_field.html:28 @@ -5606,7 +5645,7 @@ msgstr "严重" msgid "High" msgstr "较高" -#: terminal/const.py:32 terminal/const.py:67 +#: terminal/const.py:32 terminal/const.py:68 #: users/templates/users/reset_password.html:50 msgid "Normal" msgstr "正常" @@ -5615,23 +5654,23 @@ msgstr "正常" msgid "Offline" msgstr "离线" -#: terminal/const.py:63 +#: terminal/const.py:64 msgid "Mismatch" msgstr "未匹配" -#: terminal/const.py:68 +#: terminal/const.py:69 msgid "Tunnel" msgstr "隧道" -#: terminal/const.py:70 +#: terminal/const.py:71 msgid "SFTP" msgstr "SFTP" -#: terminal/const.py:74 +#: terminal/const.py:75 msgid "Read Only" msgstr "只读" -#: terminal/const.py:75 +#: terminal/const.py:76 msgid "Writable" msgstr "读写" @@ -6663,6 +6702,7 @@ msgid "Not a valid ssh public key" msgstr "SSH密钥不合法" #: users/forms/profile.py:173 users/models/user.py:786 +#: xpack/plugins/cloud/serializers/account_attrs.py:206 msgid "Public key" msgstr "SSH公钥" @@ -6691,6 +6731,7 @@ msgid "OTP secret key" msgstr "OTP 密钥" #: users/models/user.py:783 +#: xpack/plugins/cloud/serializers/account_attrs.py:209 msgid "Private key" msgstr "ssh私钥" @@ -7157,70 +7198,76 @@ msgid "Tencent Cloud (Lighthouse)" msgstr "腾讯云(轻量服务器应用)" #: xpack/plugins/cloud/const.py:19 -msgid "VMware" -msgstr "VMware" - -#: xpack/plugins/cloud/const.py:20 xpack/plugins/cloud/providers/nutanix.py:13 -msgid "Nutanix" -msgstr "Nutanix" - -#: xpack/plugins/cloud/const.py:21 -msgid "Huawei Private Cloud" -msgstr "华为私有云" - -#: xpack/plugins/cloud/const.py:22 -msgid "Qingyun Private Cloud" -msgstr "青云私有云" - -#: xpack/plugins/cloud/const.py:23 -msgid "CTYun Private Cloud" -msgstr "天翼私有云" - -#: xpack/plugins/cloud/const.py:24 -msgid "OpenStack" -msgstr "OpenStack" - -#: xpack/plugins/cloud/const.py:25 msgid "Google Cloud Platform" msgstr "谷歌云" +#: xpack/plugins/cloud/const.py:20 +#, fuzzy +#| msgid "Cloud" +msgid "UCloud" +msgstr "云服务" + +#: xpack/plugins/cloud/const.py:22 +msgid "VMware" +msgstr "VMware" + +#: xpack/plugins/cloud/const.py:23 xpack/plugins/cloud/providers/nutanix.py:13 +msgid "Nutanix" +msgstr "Nutanix" + +#: xpack/plugins/cloud/const.py:24 +msgid "Huawei Private Cloud" +msgstr "华为私有云" + +#: xpack/plugins/cloud/const.py:25 +msgid "Qingyun Private Cloud" +msgstr "青云私有云" + #: xpack/plugins/cloud/const.py:26 +msgid "CTYun Private Cloud" +msgstr "天翼私有云" + +#: xpack/plugins/cloud/const.py:27 +msgid "OpenStack" +msgstr "OpenStack" + +#: xpack/plugins/cloud/const.py:28 msgid "Fusion Compute" msgstr "融合计算" -#: xpack/plugins/cloud/const.py:31 +#: xpack/plugins/cloud/const.py:33 msgid "Private IP" msgstr "私有IP" -#: xpack/plugins/cloud/const.py:32 +#: xpack/plugins/cloud/const.py:34 msgid "Public IP" msgstr "公网IP" -#: xpack/plugins/cloud/const.py:36 +#: xpack/plugins/cloud/const.py:38 msgid "Instance name" msgstr "实例名称" -#: xpack/plugins/cloud/const.py:37 +#: xpack/plugins/cloud/const.py:39 msgid "Instance name and Partial IP" msgstr "实例名称和部分IP" -#: xpack/plugins/cloud/const.py:42 +#: xpack/plugins/cloud/const.py:44 msgid "Succeed" msgstr "成功" -#: xpack/plugins/cloud/const.py:46 +#: xpack/plugins/cloud/const.py:48 msgid "Unsync" msgstr "未同步" -#: xpack/plugins/cloud/const.py:47 +#: xpack/plugins/cloud/const.py:49 msgid "New Sync" msgstr "新同步" -#: xpack/plugins/cloud/const.py:48 +#: xpack/plugins/cloud/const.py:50 msgid "Synced" msgstr "已同步" -#: xpack/plugins/cloud/const.py:49 +#: xpack/plugins/cloud/const.py:51 msgid "Released" msgstr "已释放" @@ -7486,11 +7533,11 @@ msgstr "华南-广州-友好用户环境" msgid "CN East-Suqian" msgstr "华东-宿迁" -#: xpack/plugins/cloud/serializers/account.py:63 +#: xpack/plugins/cloud/serializers/account.py:64 msgid "Validity display" msgstr "有效性显示" -#: xpack/plugins/cloud/serializers/account.py:64 +#: xpack/plugins/cloud/serializers/account.py:65 msgid "Provider display" msgstr "服务商显示" @@ -7510,6 +7557,7 @@ msgstr "订阅 ID" #: xpack/plugins/cloud/serializers/account_attrs.py:103 #: xpack/plugins/cloud/serializers/account_attrs.py:119 #: xpack/plugins/cloud/serializers/account_attrs.py:149 +#: xpack/plugins/cloud/serializers/account_attrs.py:202 msgid "API Endpoint" msgstr "API 端点" @@ -7574,6 +7622,12 @@ msgstr "测试端口" msgid "Test timeout" msgstr "测试超时时间" +#: xpack/plugins/cloud/serializers/account_attrs.py:212 +#, fuzzy +#| msgid "Reject" +msgid "Project" +msgstr "拒绝" + #: xpack/plugins/cloud/serializers/task.py:28 msgid "" "Only instances matching the IP range will be synced.
If the instance " @@ -7670,5 +7724,8 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" +#~ msgid "e.g. http(s)://host" +#~ msgstr "如: http(s)://host" + #~ msgid "Please enable cookies and try again." #~ msgstr "设置你的浏览器支持cookie" From 10fa122e2fec098bdf57c2e830d0f8bb2135e165 Mon Sep 17 00:00:00 2001 From: "fangfang.dong" Date: Tue, 11 Jul 2023 11:35:07 +0800 Subject: [PATCH 105/167] =?UTF-8?q?perf:=20=E6=B8=85=E7=90=86=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/api.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/jumpserver/api.py b/apps/jumpserver/api.py index 5b26a0532..6e2e49691 100644 --- a/apps/jumpserver/api.py +++ b/apps/jumpserver/api.py @@ -17,7 +17,6 @@ from audits.models import UserLoginLog, PasswordChangeLog, OperateLog, FTPLog, J from common.utils import lazyproperty from common.utils.timezone import local_now, local_zero_hour from ops.const import JobStatus -from ops.models import JobExecution from orgs.caches import OrgResourceStatisticsCache from orgs.utils import current_org from terminal.models import Session, Command @@ -130,12 +129,6 @@ class DateTimeMixin: queryset = JobLog.objects.filter(date_created__gte=t) return queryset - @lazyproperty - def jobs_executed_queryset(self): - t = self.days_to_datetime - queryset = JobExecution.objects.filter(date_created__gte=t) - return queryset - class DatesLoginMetricMixin: dates_list: list From b75d69de5d9528289a114901080a8fb2017368e6 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:06:11 +0800 Subject: [PATCH 106/167] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=8D=B1?= =?UTF-8?q?=E9=99=A9=E5=91=BD=E4=BB=A4=E5=91=8A=E8=AD=A6=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?:=20Warning=20(#10929)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 新增危险命令告警类型: Warning * feat: 新增危险命令告警类型: Warning * feat: 新增危险命令告警类型: Warning * feat: 新增危险命令告警类型: Warning * feat: 新增危险命令告警类型: Warning * perf: 优化命令告警 View 处理逻辑 --------- Co-authored-by: fangfang.dong Co-authored-by: Bai --- apps/acls/models/__init__.py | 1 + apps/acls/models/base.py | 2 + apps/acls/serializers/base.py | 1 + apps/jumpserver/api.py | 3 +- apps/locale/ja/LC_MESSAGES/django.po | 216 ++++++++++-------- apps/locale/zh/LC_MESSAGES/django.po | 216 ++++++++++-------- apps/terminal/api/session/command.py | 33 ++- apps/terminal/backends/command/models.py | 6 +- apps/terminal/const.py | 11 +- .../migrations/0023_command_risk_level.py | 2 +- apps/terminal/notifications.py | 49 +++- apps/terminal/serializers/command.py | 15 +- .../terminal/_msg_command_warning.html | 23 ++ 13 files changed, 368 insertions(+), 210 deletions(-) create mode 100644 apps/terminal/templates/terminal/_msg_command_warning.html diff --git a/apps/acls/models/__init__.py b/apps/acls/models/__init__.py index 28fe366b3..0a4cc2a6e 100644 --- a/apps/acls/models/__init__.py +++ b/apps/acls/models/__init__.py @@ -2,3 +2,4 @@ from .command_acl import * from .connect_method import * from .login_acl import * from .login_asset_acl import * +from .base import ActionChoices diff --git a/apps/acls/models/base.py b/apps/acls/models/base.py index cbc5c6e4e..c84ea3fcf 100644 --- a/apps/acls/models/base.py +++ b/apps/acls/models/base.py @@ -10,6 +10,7 @@ from orgs.mixins.models import OrgModelMixin, OrgManager __all__ = [ 'BaseACL', 'UserBaseACL', 'UserAssetAccountBaseACL', + 'ActionChoices', ] from orgs.utils import tmp_to_root_org @@ -20,6 +21,7 @@ class ActionChoices(models.TextChoices): reject = 'reject', _('Reject') accept = 'accept', _('Accept') review = 'review', _('Review') + warning = 'warning', _('Warning') class BaseACLQuerySet(models.QuerySet): diff --git a/apps/acls/serializers/base.py b/apps/acls/serializers/base.py index d8a172c93..3892553d9 100644 --- a/apps/acls/serializers/base.py +++ b/apps/acls/serializers/base.py @@ -84,6 +84,7 @@ class BaserACLSerializer(ActionAclSerializer, serializers.Serializer): extra_kwargs = { "priority": {"default": 50}, "is_active": {"default": True}, + 'reviewers': {'label': _('Recipients')}, } def validate_reviewers(self, reviewers): diff --git a/apps/jumpserver/api.py b/apps/jumpserver/api.py index 6e2e49691..10b0afa55 100644 --- a/apps/jumpserver/api.py +++ b/apps/jumpserver/api.py @@ -22,6 +22,7 @@ from orgs.utils import current_org from terminal.models import Session, Command from terminal.utils import ComponentsPrometheusMetricsUtil from users.models import User +from terminal.const import RiskLevelChoices __all__ = ['IndexApi'] @@ -248,7 +249,7 @@ class DatesLoginMetricMixin: @lazyproperty def commands_danger_amount(self): - return self.command_queryset.filter(risk_level=Command.RiskLevelChoices.dangerous).count() + return self.command_queryset.filter(risk_level=RiskLevelChoices.reject).count() @lazyproperty def job_logs_running_amount(self): diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index b45d415ff..c78b136bb 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-11 11:18+0800\n" +"POT-Creation-Date: 2023-07-11 12:03+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -50,10 +50,8 @@ msgid "Token" msgstr "トークン" #: accounts/const/account.py:10 -#, fuzzy -#| msgid "API Key" msgid "API key" -msgstr "API Key" +msgstr "" #: accounts/const/account.py:14 common/db/fields.py:244 #: settings/serializers/terminal.py:14 @@ -97,7 +95,7 @@ msgstr "更新" #: accounts/const/account.py:29 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:63 xpack/plugins/cloud/const.py:43 +#: ops/const.py:58 terminal/const.py:72 xpack/plugins/cloud/const.py:43 msgid "Failed" msgstr "失敗しました" @@ -196,13 +194,14 @@ msgstr "作成のみ" #: accounts/serializers/account/gathered_account.py:10 #: accounts/serializers/automations/change_secret.py:112 #: accounts/serializers/automations/change_secret.py:132 -#: acls/serializers/base.py:118 assets/models/asset/common.py:93 +#: acls/serializers/base.py:119 assets/models/asset/common.py:93 #: assets/models/asset/common.py:331 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:53 authentication/models/connection_token.py:36 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 -#: terminal/backends/command/models.py:20 terminal/models/session/session.py:31 -#: terminal/notifications.py:95 terminal/serializers/command.py:17 +#: terminal/backends/command/models.py:18 terminal/models/session/session.py:31 +#: terminal/notifications.py:134 terminal/serializers/command.py:18 +#: terminal/templates/terminal/_msg_command_warning.html:4 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "資産" @@ -232,10 +231,10 @@ msgstr "ソース ID" #: accounts/models/account.py:61 #: accounts/serializers/automations/change_secret.py:113 #: accounts/serializers/automations/change_secret.py:133 -#: acls/serializers/base.py:119 assets/serializers/asset/common.py:125 +#: acls/serializers/base.py:120 assets/serializers/asset/common.py:125 #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 -#: terminal/backends/command/models.py:21 terminal/models/session/session.py:33 +#: terminal/backends/command/models.py:19 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "アカウント" @@ -468,7 +467,7 @@ msgstr "アカウントのコレクション" msgid "Triggers" msgstr "トリガー方式" -#: accounts/models/automations/push_account.py:16 acls/models/base.py:46 +#: accounts/models/automations/push_account.py:16 acls/models/base.py:48 #: acls/serializers/base.py:56 assets/models/cmd_filter.py:81 #: audits/models.py:87 audits/serializers.py:82 #: authentication/serializers/connect_token_secret.py:116 @@ -484,7 +483,7 @@ msgstr "アカウントプッシュ" msgid "Verify asset account" msgstr "アカウントの確認" -#: accounts/models/base.py:33 acls/models/base.py:40 acls/models/base.py:101 +#: accounts/models/base.py:33 acls/models/base.py:42 acls/models/base.py:103 #: acls/models/command_acl.py:21 acls/serializers/base.py:34 #: applications/models.py:9 assets/models/_user.py:22 #: assets/models/asset/common.py:91 assets/models/asset/common.py:149 @@ -618,7 +617,7 @@ msgid "Changed" msgstr "編集済み" #: accounts/serializers/account/account.py:250 -#: accounts/serializers/automations/base.py:22 acls/models/base.py:102 +#: accounts/serializers/automations/base.py:22 acls/models/base.py:104 #: assets/models/automations/base.py:19 #: assets/serializers/automations/base.py:20 ops/models/base.py:17 #: ops/models/job.py:105 ops/serializers/job.py:21 @@ -646,7 +645,7 @@ msgstr "アカウントはすでに存在しています" msgid "ID" msgstr "ID" -#: accounts/serializers/account/account.py:427 acls/serializers/base.py:111 +#: accounts/serializers/account/account.py:427 acls/serializers/base.py:112 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:49 #: audits/models.py:85 audits/models.py:163 #: authentication/models/connection_token.py:32 @@ -654,10 +653,10 @@ msgstr "ID" #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 #: perms/serializers/permission.py:30 rbac/builtin.py:122 -#: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:19 +#: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:17 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:96 terminal/notifications.py:144 -#: terminal/serializers/command.py:16 tickets/models/comment.py:21 +#: terminal/notifications.py:135 terminal/notifications.py:183 +#: terminal/serializers/command.py:17 tickets/models/comment.py:21 #: users/const.py:14 users/models/user.py:947 users/models/user.py:978 #: users/serializers/group.py:18 msgid "User" @@ -665,7 +664,7 @@ msgstr "ユーザー" #: accounts/serializers/account/account.py:428 #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:98 terminal/notifications.py:146 +#: terminal/notifications.py:137 terminal/notifications.py:185 msgid "Date" msgstr "日付" @@ -744,7 +743,7 @@ msgstr "自動タスク実行履歴" #: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:40 -#: terminal/const.py:62 terminal/models/session/sharing.py:107 +#: terminal/const.py:71 terminal/models/session/sharing.py:107 #: tickets/views/approve.py:114 msgid "Success" msgstr "成功" @@ -793,35 +792,39 @@ msgstr "秘密鍵が無効またはpassphraseエラー" msgid "Acls" msgstr "Acls" -#: acls/models/base.py:20 tickets/const.py:45 +#: acls/models/base.py:21 terminal/const.py:11 tickets/const.py:45 #: tickets/templates/tickets/approve_check_password.html:49 msgid "Reject" msgstr "拒否" -#: acls/models/base.py:21 +#: acls/models/base.py:22 terminal/const.py:9 msgid "Accept" msgstr "受け入れられる" -#: acls/models/base.py:22 +#: acls/models/base.py:23 msgid "Review" msgstr "レビュー担当者" -#: acls/models/base.py:42 assets/models/_user.py:51 +#: acls/models/base.py:24 terminal/const.py:10 +msgid "Warning" +msgstr "警告" + +#: acls/models/base.py:44 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:93 msgid "Priority" msgstr "優先順位" -#: acls/models/base.py:43 assets/models/_user.py:51 +#: acls/models/base.py:45 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:94 msgid "1-100, the lower the value will be match first" msgstr "1-100、低い値は最初に一致します" -#: acls/models/base.py:47 assets/models/cmd_filter.py:86 +#: acls/models/base.py:49 assets/models/cmd_filter.py:86 #: authentication/serializers/connect_token_secret.py:88 msgid "Reviewers" msgstr "レビュー担当者" -#: acls/models/base.py:48 authentication/models/access_key.py:17 +#: acls/models/base.py:50 authentication/models/access_key.py:17 #: authentication/models/connection_token.py:53 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/asset_permission.py:76 terminal/models/session/sharing.py:27 @@ -829,21 +832,22 @@ msgstr "レビュー担当者" msgid "Active" msgstr "アクティブ" -#: acls/models/base.py:86 users/apps.py:9 +#: acls/models/base.py:88 users/apps.py:9 msgid "Users" msgstr "ユーザー" -#: acls/models/base.py:103 assets/models/automations/base.py:17 +#: acls/models/base.py:105 assets/models/automations/base.py:17 #: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:305 #: rbac/tree.py:35 msgid "Accounts" msgstr "アカウント" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:55 terminal/const.py:70 -#: terminal/models/session/session.py:42 terminal/serializers/command.py:18 +#: ops/serializers/job.py:55 terminal/const.py:79 +#: terminal/models/session/session.py:42 terminal/serializers/command.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:16 msgid "Command" msgstr "コマンド" @@ -875,6 +879,7 @@ msgid "The generated regular expression is incorrect: {}" msgstr "生成された正規表現が正しくありません: {}" #: acls/models/command_acl.py:100 +#: terminal/templates/terminal/_msg_command_warning.html:10 msgid "Command acl" msgstr "コマンドフィルタリング" @@ -929,11 +934,15 @@ msgstr "" msgid "IP/Host" msgstr "IP/ホスト" -#: acls/serializers/base.py:98 tickets/serializers/ticket/ticket.py:77 +#: acls/serializers/base.py:87 +msgid "Recipients" +msgstr "受信者" + +#: acls/serializers/base.py:99 tickets/serializers/ticket/ticket.py:77 msgid "The organization `{}` does not exist" msgstr "組織 '{}'は存在しません" -#: acls/serializers/base.py:104 +#: acls/serializers/base.py:105 msgid "None of the reviewers belong to Organization `{}`" msgstr "いずれのレビューアも組織 '{}' に属していません" @@ -1139,62 +1148,60 @@ msgstr "" msgid "Other" msgstr "その他" -#: assets/const/protocol.py:42 +#: assets/const/protocol.py:43 msgid "SFTP enabled" msgstr "SFTP が有効" -#: assets/const/protocol.py:47 +#: assets/const/protocol.py:48 msgid "SFTP home" msgstr "SFTP ルート パス" -#: assets/const/protocol.py:58 +#: assets/const/protocol.py:59 msgid "Console" msgstr "Console" -#: assets/const/protocol.py:59 +#: assets/const/protocol.py:60 msgid "Connect to console session" msgstr "コンソールセッションに接続" -#: assets/const/protocol.py:63 +#: assets/const/protocol.py:64 msgid "Any" msgstr "任意" -#: assets/const/protocol.py:65 settings/serializers/security.py:151 +#: assets/const/protocol.py:66 settings/serializers/security.py:151 msgid "Security" msgstr "セキュリティ" -#: assets/const/protocol.py:66 +#: assets/const/protocol.py:67 msgid "Security layer to use for the connection" msgstr "接続に使用するセキュリティ レイヤー" -#: assets/const/protocol.py:72 -#, fuzzy -#| msgid "Domain" +#: assets/const/protocol.py:73 msgid "AD domain" -msgstr "ドメイン" +msgstr "AD ドメイン" -#: assets/const/protocol.py:91 assets/models/asset/database.py:10 +#: assets/const/protocol.py:92 assets/models/asset/database.py:10 #: settings/serializers/email.py:37 msgid "Use SSL" msgstr "SSLの使用" -#: assets/const/protocol.py:144 +#: assets/const/protocol.py:145 msgid "Auth username" msgstr "ユーザー名で認証する" -#: assets/const/protocol.py:172 assets/models/asset/web.py:10 +#: assets/const/protocol.py:173 assets/models/asset/web.py:10 msgid "Username selector" msgstr "ユーザー名ピッカー" -#: assets/const/protocol.py:177 assets/models/asset/web.py:11 +#: assets/const/protocol.py:178 assets/models/asset/web.py:11 msgid "Password selector" msgstr "パスワードセレクター" -#: assets/const/protocol.py:182 assets/models/asset/web.py:12 +#: assets/const/protocol.py:183 assets/models/asset/web.py:12 msgid "Submit selector" msgstr "ボタンセレクターを確認する" -#: assets/const/protocol.py:200 +#: assets/const/protocol.py:201 msgid "API mode" msgstr "APIモード" @@ -1723,7 +1730,9 @@ msgstr "このフィールドは必須です。" msgid "" "If the server cannot directly connect to the API address, you need set up an " "HTTP proxy. e.g. http(s)://host:port" -msgstr "サーバーが API アドレスに直接接続できない場合は、HTTP プロキシを設定する必要があります。例: http(s)://host:port" +msgstr "" +"サーバーが API アドレスに直接接続できない場合は、HTTP プロキシを設定する必要" +"があります。例: http(s)://host:port" #: assets/serializers/asset/gpt.py:23 msgid "HTTP proxy" @@ -2058,10 +2067,11 @@ msgstr "ファイル名" msgid "File" msgstr "書類" -#: audits/models.py:62 terminal/backends/command/models.py:24 +#: audits/models.py:62 terminal/backends/command/models.py:22 #: terminal/models/session/replay.py:9 terminal/models/session/sharing.py:18 #: terminal/models/session/sharing.py:81 #: terminal/templates/terminal/_msg_command_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:7 #: tickets/models/ticket/command_confirm.py:15 msgid "Session" msgstr "セッション" @@ -2080,7 +2090,7 @@ msgid "Resource" msgstr "リソース" #: audits/models.py:96 audits/models.py:142 audits/models.py:168 -#: terminal/serializers/command.py:50 +#: terminal/serializers/command.py:61 msgid "Datetime" msgstr "時間" @@ -3157,7 +3167,7 @@ msgstr "タイミングトリガー" msgid "Ready" msgstr "の準備を" -#: common/const/choices.py:16 terminal/const.py:61 tickets/const.py:29 +#: common/const/choices.py:16 terminal/const.py:70 tickets/const.py:29 #: tickets/const.py:39 msgid "Pending" msgstr "未定" @@ -5671,7 +5681,7 @@ msgstr "テスト失敗: {}" msgid "Test successful" msgstr "テスト成功" -#: terminal/api/component/storage.py:124 terminal/notifications.py:179 +#: terminal/api/component/storage.py:124 terminal/notifications.py:218 #: terminal/tasks.py:144 msgid "Test failure: Account invalid" msgstr "テスト失敗: アカウントが無効" @@ -5700,23 +5710,15 @@ msgstr "安全なセッション共有設定が無効になっています" msgid "Terminals" msgstr "ターミナル管理" -#: terminal/backends/command/models.py:15 -msgid "Ordinary" -msgstr "普通" - -#: terminal/backends/command/models.py:16 -msgid "Dangerous" -msgstr "危険" - -#: terminal/backends/command/models.py:22 +#: terminal/backends/command/models.py:20 msgid "Input" msgstr "入力" -#: terminal/backends/command/models.py:23 terminal/serializers/command.py:48 +#: terminal/backends/command/models.py:21 terminal/serializers/command.py:59 msgid "Output" msgstr "出力" -#: terminal/backends/command/models.py:27 terminal/serializers/command.py:22 +#: terminal/backends/command/models.py:25 terminal/serializers/command.py:23 msgid "Risk level" msgstr "リスクレベル" @@ -5724,40 +5726,52 @@ msgstr "リスクレベル" msgid "DB Client" msgstr "データベース クライアント" -#: terminal/const.py:30 +#: terminal/const.py:12 +msgid "Review & Reject" +msgstr "レビューと拒否" + +#: terminal/const.py:13 +msgid "Review & Accept" +msgstr "確認して同意する" + +#: terminal/const.py:14 +msgid "Review & Cancel" +msgstr "確認してキャンセル" + +#: terminal/const.py:39 msgid "Critical" msgstr "クリティカル" -#: terminal/const.py:31 +#: terminal/const.py:40 msgid "High" msgstr "高い" -#: terminal/const.py:32 terminal/const.py:68 +#: terminal/const.py:41 terminal/const.py:77 #: users/templates/users/reset_password.html:50 msgid "Normal" msgstr "正常" -#: terminal/const.py:33 +#: terminal/const.py:42 msgid "Offline" msgstr "オフライン" -#: terminal/const.py:64 +#: terminal/const.py:73 msgid "Mismatch" msgstr "一致しない" -#: terminal/const.py:69 +#: terminal/const.py:78 msgid "Tunnel" msgstr "" -#: terminal/const.py:71 +#: terminal/const.py:80 msgid "SFTP" msgstr "SFTP" -#: terminal/const.py:75 +#: terminal/const.py:84 msgid "Read Only" msgstr "読み取り専用" -#: terminal/const.py:76 +#: terminal/const.py:85 msgid "Writable" msgstr "書き込み可能" @@ -5932,7 +5946,7 @@ msgstr "再生ストレージ" msgid "type" msgstr "タイプ" -#: terminal/models/component/terminal.py:89 terminal/serializers/command.py:51 +#: terminal/models/component/terminal.py:89 terminal/serializers/command.py:62 msgid "Remote Address" msgstr "リモートアドレス" @@ -6053,27 +6067,31 @@ msgstr "すでにこのセッションに参加しています" msgid "Sessions" msgstr "セッション" -#: terminal/notifications.py:67 +#: terminal/notifications.py:68 +msgid "Danger command warning" +msgstr "危険コマンドアラート" + +#: terminal/notifications.py:109 msgid "Danger command alert" msgstr "危険コマンドアラート" -#: terminal/notifications.py:97 terminal/notifications.py:145 +#: terminal/notifications.py:136 terminal/notifications.py:184 msgid "Level" msgstr "レベル" -#: terminal/notifications.py:115 +#: terminal/notifications.py:154 msgid "Batch danger command alert" msgstr "一括危険コマンド警告" -#: terminal/notifications.py:163 +#: terminal/notifications.py:202 msgid "Command and replay storage" msgstr "コマンド及び録画記憶" -#: terminal/notifications.py:164 +#: terminal/notifications.py:203 msgid "Connectivity alarm" msgstr "接続性アラーム" -#: terminal/notifications.py:189 +#: terminal/notifications.py:228 #: terminal/templates/terminal/_msg_check_command_replay_storage_connectivity.html:4 msgid "Invalid storage" msgstr "無効なストレージ" @@ -6145,15 +6163,23 @@ msgstr "RDS 远程应用注销时间限制" msgid "Load status" msgstr "ロードステータス" -#: terminal/serializers/command.py:19 +#: terminal/serializers/command.py:20 msgid "Session ID" msgstr "セッションID" -#: terminal/serializers/command.py:47 +#: terminal/serializers/command.py:42 +msgid "Command Filter ACL" +msgstr "コマンドフィルター" + +#: terminal/serializers/command.py:45 +msgid "Command Group" +msgstr "コマンドグループ" + +#: terminal/serializers/command.py:58 msgid "Account " msgstr "アカウント" -#: terminal/serializers/command.py:49 +#: terminal/serializers/command.py:60 msgid "Timestamp" msgstr "タイムスタンプ" @@ -6327,9 +6353,17 @@ msgid "Check command replay storage connectivity" msgstr "チェックコマンドと録画ストレージの接続性" #: terminal/templates/terminal/_msg_command_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:5 +#: terminal/templates/terminal/_msg_command_warning.html:8 +#: terminal/templates/terminal/_msg_command_warning.html:11 +#: terminal/templates/terminal/_msg_command_warning.html:14 msgid "view" msgstr "表示" +#: terminal/templates/terminal/_msg_command_warning.html:13 +msgid "Command acl group" +msgstr "コマンドフィルタリンググループ" + #: terminal/utils/db_port_mapper.py:84 msgid "" "No available port is matched. The number of databases may have exceeded the " @@ -7313,10 +7347,8 @@ msgid "Google Cloud Platform" msgstr "谷歌雲" #: xpack/plugins/cloud/const.py:20 -#, fuzzy -#| msgid "Cloud" msgid "UCloud" -msgstr "クラウド サービス" +msgstr "" #: xpack/plugins/cloud/const.py:22 msgid "VMware" @@ -7735,10 +7767,8 @@ msgid "Test timeout" msgstr "テストタイムアウト" #: xpack/plugins/cloud/serializers/account_attrs.py:212 -#, fuzzy -#| msgid "Reject" msgid "Project" -msgstr "拒否" +msgstr "" #: xpack/plugins/cloud/serializers/task.py:28 msgid "" @@ -7837,9 +7867,3 @@ msgstr "究極のエディション" #: xpack/plugins/license/models.py:86 msgid "Community edition" msgstr "コミュニティ版" - -#~ msgid "e.g. http(s)://host" -#~ msgstr "HTTP プロキシ、例えば http(s)://host" - -#~ msgid "Please enable cookies and try again." -#~ msgstr "クッキーを有効にして、もう一度お試しください。" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index f5dfcabd4..b74c0fc53 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-11 11:18+0800\n" +"POT-Creation-Date: 2023-07-11 12:03+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -49,10 +49,8 @@ msgid "Token" msgstr "Token" #: accounts/const/account.py:10 -#, fuzzy -#| msgid "API Key" msgid "API key" -msgstr "API Key" +msgstr "" #: accounts/const/account.py:14 common/db/fields.py:244 #: settings/serializers/terminal.py:14 @@ -96,7 +94,7 @@ msgstr "更新" #: accounts/const/account.py:29 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:63 xpack/plugins/cloud/const.py:43 +#: ops/const.py:58 terminal/const.py:72 xpack/plugins/cloud/const.py:43 msgid "Failed" msgstr "失败" @@ -195,13 +193,14 @@ msgstr "仅创建" #: accounts/serializers/account/gathered_account.py:10 #: accounts/serializers/automations/change_secret.py:112 #: accounts/serializers/automations/change_secret.py:132 -#: acls/serializers/base.py:118 assets/models/asset/common.py:93 +#: acls/serializers/base.py:119 assets/models/asset/common.py:93 #: assets/models/asset/common.py:331 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:53 authentication/models/connection_token.py:36 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 -#: terminal/backends/command/models.py:20 terminal/models/session/session.py:31 -#: terminal/notifications.py:95 terminal/serializers/command.py:17 +#: terminal/backends/command/models.py:18 terminal/models/session/session.py:31 +#: terminal/notifications.py:134 terminal/serializers/command.py:18 +#: terminal/templates/terminal/_msg_command_warning.html:4 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "资产" @@ -231,10 +230,10 @@ msgstr "来源 ID" #: accounts/models/account.py:61 #: accounts/serializers/automations/change_secret.py:113 #: accounts/serializers/automations/change_secret.py:133 -#: acls/serializers/base.py:119 assets/serializers/asset/common.py:125 +#: acls/serializers/base.py:120 assets/serializers/asset/common.py:125 #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 -#: terminal/backends/command/models.py:21 terminal/models/session/session.py:33 +#: terminal/backends/command/models.py:19 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "账号" @@ -467,7 +466,7 @@ msgstr "收集账号" msgid "Triggers" msgstr "触发方式" -#: accounts/models/automations/push_account.py:16 acls/models/base.py:46 +#: accounts/models/automations/push_account.py:16 acls/models/base.py:48 #: acls/serializers/base.py:56 assets/models/cmd_filter.py:81 #: audits/models.py:87 audits/serializers.py:82 #: authentication/serializers/connect_token_secret.py:116 @@ -483,7 +482,7 @@ msgstr "账号推送" msgid "Verify asset account" msgstr "账号验证" -#: accounts/models/base.py:33 acls/models/base.py:40 acls/models/base.py:101 +#: accounts/models/base.py:33 acls/models/base.py:42 acls/models/base.py:103 #: acls/models/command_acl.py:21 acls/serializers/base.py:34 #: applications/models.py:9 assets/models/_user.py:22 #: assets/models/asset/common.py:91 assets/models/asset/common.py:149 @@ -614,7 +613,7 @@ msgid "Changed" msgstr "已修改" #: accounts/serializers/account/account.py:250 -#: accounts/serializers/automations/base.py:22 acls/models/base.py:102 +#: accounts/serializers/automations/base.py:22 acls/models/base.py:104 #: assets/models/automations/base.py:19 #: assets/serializers/automations/base.py:20 ops/models/base.py:17 #: ops/models/job.py:105 ops/serializers/job.py:21 @@ -642,7 +641,7 @@ msgstr "账号已存在" msgid "ID" msgstr "ID" -#: accounts/serializers/account/account.py:427 acls/serializers/base.py:111 +#: accounts/serializers/account/account.py:427 acls/serializers/base.py:112 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:49 #: audits/models.py:85 audits/models.py:163 #: authentication/models/connection_token.py:32 @@ -650,10 +649,10 @@ msgstr "ID" #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 #: perms/serializers/permission.py:30 rbac/builtin.py:122 -#: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:19 +#: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:17 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:96 terminal/notifications.py:144 -#: terminal/serializers/command.py:16 tickets/models/comment.py:21 +#: terminal/notifications.py:135 terminal/notifications.py:183 +#: terminal/serializers/command.py:17 tickets/models/comment.py:21 #: users/const.py:14 users/models/user.py:947 users/models/user.py:978 #: users/serializers/group.py:18 msgid "User" @@ -661,7 +660,7 @@ msgstr "用户" #: accounts/serializers/account/account.py:428 #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:98 terminal/notifications.py:146 +#: terminal/notifications.py:137 terminal/notifications.py:185 msgid "Date" msgstr "日期" @@ -740,7 +739,7 @@ msgstr "自动化任务执行历史" #: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:40 -#: terminal/const.py:62 terminal/models/session/sharing.py:107 +#: terminal/const.py:71 terminal/models/session/sharing.py:107 #: tickets/views/approve.py:114 msgid "Success" msgstr "成功" @@ -789,35 +788,39 @@ msgstr "密钥不合法或密钥密码错误" msgid "Acls" msgstr "访问控制" -#: acls/models/base.py:20 tickets/const.py:45 +#: acls/models/base.py:21 terminal/const.py:11 tickets/const.py:45 #: tickets/templates/tickets/approve_check_password.html:49 msgid "Reject" msgstr "拒绝" -#: acls/models/base.py:21 +#: acls/models/base.py:22 terminal/const.py:9 msgid "Accept" msgstr "接受" -#: acls/models/base.py:22 +#: acls/models/base.py:23 msgid "Review" msgstr "审批" -#: acls/models/base.py:42 assets/models/_user.py:51 +#: acls/models/base.py:24 terminal/const.py:10 +msgid "Warning" +msgstr "告警" + +#: acls/models/base.py:44 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:93 msgid "Priority" msgstr "优先级" -#: acls/models/base.py:43 assets/models/_user.py:51 +#: acls/models/base.py:45 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:94 msgid "1-100, the lower the value will be match first" msgstr "优先级可选范围为 1-100 (数值越小越优先)" -#: acls/models/base.py:47 assets/models/cmd_filter.py:86 +#: acls/models/base.py:49 assets/models/cmd_filter.py:86 #: authentication/serializers/connect_token_secret.py:88 msgid "Reviewers" msgstr "审批人" -#: acls/models/base.py:48 authentication/models/access_key.py:17 +#: acls/models/base.py:50 authentication/models/access_key.py:17 #: authentication/models/connection_token.py:53 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/asset_permission.py:76 terminal/models/session/sharing.py:27 @@ -825,21 +828,22 @@ msgstr "审批人" msgid "Active" msgstr "激活中" -#: acls/models/base.py:86 users/apps.py:9 +#: acls/models/base.py:88 users/apps.py:9 msgid "Users" msgstr "用户管理" -#: acls/models/base.py:103 assets/models/automations/base.py:17 +#: acls/models/base.py:105 assets/models/automations/base.py:17 #: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:305 #: rbac/tree.py:35 msgid "Accounts" msgstr "账号管理" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:55 terminal/const.py:70 -#: terminal/models/session/session.py:42 terminal/serializers/command.py:18 +#: ops/serializers/job.py:55 terminal/const.py:79 +#: terminal/models/session/session.py:42 terminal/serializers/command.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:16 msgid "Command" msgstr "命令" @@ -871,6 +875,7 @@ msgid "The generated regular expression is incorrect: {}" msgstr "生成的正则表达式有误" #: acls/models/command_acl.py:100 +#: terminal/templates/terminal/_msg_command_warning.html:10 msgid "Command acl" msgstr "命令过滤" @@ -924,11 +929,15 @@ msgstr "" msgid "IP/Host" msgstr "IP/主机" -#: acls/serializers/base.py:98 tickets/serializers/ticket/ticket.py:77 +#: acls/serializers/base.py:87 +msgid "Recipients" +msgstr "接收人" + +#: acls/serializers/base.py:99 tickets/serializers/ticket/ticket.py:77 msgid "The organization `{}` does not exist" msgstr "组织 `{}` 不存在" -#: acls/serializers/base.py:104 +#: acls/serializers/base.py:105 msgid "None of the reviewers belong to Organization `{}`" msgstr "所有复核人都不属于组织 `{}`" @@ -1132,62 +1141,60 @@ msgstr "ChatGPT" msgid "Other" msgstr "其它" -#: assets/const/protocol.py:42 +#: assets/const/protocol.py:43 msgid "SFTP enabled" msgstr "SFTP 已启用" -#: assets/const/protocol.py:47 +#: assets/const/protocol.py:48 msgid "SFTP home" msgstr "SFTP 根路径" -#: assets/const/protocol.py:58 +#: assets/const/protocol.py:59 msgid "Console" msgstr "控制台" -#: assets/const/protocol.py:59 +#: assets/const/protocol.py:60 msgid "Connect to console session" msgstr "连接到控制台会话" -#: assets/const/protocol.py:63 +#: assets/const/protocol.py:64 msgid "Any" msgstr "任意" -#: assets/const/protocol.py:65 settings/serializers/security.py:151 +#: assets/const/protocol.py:66 settings/serializers/security.py:151 msgid "Security" msgstr "安全" -#: assets/const/protocol.py:66 +#: assets/const/protocol.py:67 msgid "Security layer to use for the connection" msgstr "连接 RDP 使用的安全层" -#: assets/const/protocol.py:72 -#, fuzzy -#| msgid "Domain" +#: assets/const/protocol.py:73 msgid "AD domain" -msgstr "网域" +msgstr "AD 网域" -#: assets/const/protocol.py:91 assets/models/asset/database.py:10 +#: assets/const/protocol.py:92 assets/models/asset/database.py:10 #: settings/serializers/email.py:37 msgid "Use SSL" msgstr "使用 SSL" -#: assets/const/protocol.py:144 +#: assets/const/protocol.py:145 msgid "Auth username" msgstr "使用用户名认证" -#: assets/const/protocol.py:172 assets/models/asset/web.py:10 +#: assets/const/protocol.py:173 assets/models/asset/web.py:10 msgid "Username selector" msgstr "用户名选择器" -#: assets/const/protocol.py:177 assets/models/asset/web.py:11 +#: assets/const/protocol.py:178 assets/models/asset/web.py:11 msgid "Password selector" msgstr "密码选择器" -#: assets/const/protocol.py:182 assets/models/asset/web.py:12 +#: assets/const/protocol.py:183 assets/models/asset/web.py:12 msgid "Submit selector" msgstr "确认按钮选择器" -#: assets/const/protocol.py:200 +#: assets/const/protocol.py:201 msgid "API mode" msgstr "API 模式" @@ -1714,7 +1721,9 @@ msgstr "该字段是必填项。" msgid "" "If the server cannot directly connect to the API address, you need set up an " "HTTP proxy. e.g. http(s)://host:port" -msgstr "如果服务器不能直接访问 api 地址,你需要设置一个 HTTP 代理。例如 http(s)://host:port" +msgstr "" +"如果服务器不能直接访问 api 地址,你需要设置一个 HTTP 代理。例如 http(s)://" +"host:port" #: assets/serializers/asset/gpt.py:23 msgid "HTTP proxy" @@ -2042,10 +2051,11 @@ msgstr "文件名" msgid "File" msgstr "文件" -#: audits/models.py:62 terminal/backends/command/models.py:24 +#: audits/models.py:62 terminal/backends/command/models.py:22 #: terminal/models/session/replay.py:9 terminal/models/session/sharing.py:18 #: terminal/models/session/sharing.py:81 #: terminal/templates/terminal/_msg_command_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:7 #: tickets/models/ticket/command_confirm.py:15 msgid "Session" msgstr "会话" @@ -2064,7 +2074,7 @@ msgid "Resource" msgstr "资源" #: audits/models.py:96 audits/models.py:142 audits/models.py:168 -#: terminal/serializers/command.py:50 +#: terminal/serializers/command.py:61 msgid "Datetime" msgstr "日期" @@ -3117,7 +3127,7 @@ msgstr "定时触发" msgid "Ready" msgstr "准备" -#: common/const/choices.py:16 terminal/const.py:61 tickets/const.py:29 +#: common/const/choices.py:16 terminal/const.py:70 tickets/const.py:29 #: tickets/const.py:39 msgid "Pending" msgstr "待定的" @@ -5584,7 +5594,7 @@ msgstr "测试失败: {}" msgid "Test successful" msgstr "测试成功" -#: terminal/api/component/storage.py:124 terminal/notifications.py:179 +#: terminal/api/component/storage.py:124 terminal/notifications.py:218 #: terminal/tasks.py:144 msgid "Test failure: Account invalid" msgstr "测试失败: 账号无效" @@ -5613,23 +5623,15 @@ msgstr "未开启会话共享" msgid "Terminals" msgstr "终端管理" -#: terminal/backends/command/models.py:15 -msgid "Ordinary" -msgstr "普通" - -#: terminal/backends/command/models.py:16 -msgid "Dangerous" -msgstr "危险" - -#: terminal/backends/command/models.py:22 +#: terminal/backends/command/models.py:20 msgid "Input" msgstr "输入" -#: terminal/backends/command/models.py:23 terminal/serializers/command.py:48 +#: terminal/backends/command/models.py:21 terminal/serializers/command.py:59 msgid "Output" msgstr "输出" -#: terminal/backends/command/models.py:27 terminal/serializers/command.py:22 +#: terminal/backends/command/models.py:25 terminal/serializers/command.py:23 msgid "Risk level" msgstr "风险等级" @@ -5637,40 +5639,52 @@ msgstr "风险等级" msgid "DB Client" msgstr "数据库客户端" -#: terminal/const.py:30 +#: terminal/const.py:12 +msgid "Review & Reject" +msgstr "审批 & 拒绝" + +#: terminal/const.py:13 +msgid "Review & Accept" +msgstr "审批 & 接受" + +#: terminal/const.py:14 +msgid "Review & Cancel" +msgstr "审批 & 取消" + +#: terminal/const.py:39 msgid "Critical" msgstr "严重" -#: terminal/const.py:31 +#: terminal/const.py:40 msgid "High" msgstr "较高" -#: terminal/const.py:32 terminal/const.py:68 +#: terminal/const.py:41 terminal/const.py:77 #: users/templates/users/reset_password.html:50 msgid "Normal" msgstr "正常" -#: terminal/const.py:33 +#: terminal/const.py:42 msgid "Offline" msgstr "离线" -#: terminal/const.py:64 +#: terminal/const.py:73 msgid "Mismatch" msgstr "未匹配" -#: terminal/const.py:69 +#: terminal/const.py:78 msgid "Tunnel" msgstr "隧道" -#: terminal/const.py:71 +#: terminal/const.py:80 msgid "SFTP" msgstr "SFTP" -#: terminal/const.py:75 +#: terminal/const.py:84 msgid "Read Only" msgstr "只读" -#: terminal/const.py:76 +#: terminal/const.py:85 msgid "Writable" msgstr "读写" @@ -5845,7 +5859,7 @@ msgstr "录像存储" msgid "type" msgstr "类型" -#: terminal/models/component/terminal.py:89 terminal/serializers/command.py:51 +#: terminal/models/component/terminal.py:89 terminal/serializers/command.py:62 msgid "Remote Address" msgstr "远端地址" @@ -5966,27 +5980,31 @@ msgstr "您已经加入过此会话" msgid "Sessions" msgstr "会话管理" -#: terminal/notifications.py:67 +#: terminal/notifications.py:68 +msgid "Danger command warning" +msgstr "危险命令告警" + +#: terminal/notifications.py:109 msgid "Danger command alert" msgstr "危险命令告警" -#: terminal/notifications.py:97 terminal/notifications.py:145 +#: terminal/notifications.py:136 terminal/notifications.py:184 msgid "Level" msgstr "级别" -#: terminal/notifications.py:115 +#: terminal/notifications.py:154 msgid "Batch danger command alert" msgstr "批量危险命令告警" -#: terminal/notifications.py:163 +#: terminal/notifications.py:202 msgid "Command and replay storage" msgstr "命令及录像存储" -#: terminal/notifications.py:164 +#: terminal/notifications.py:203 msgid "Connectivity alarm" msgstr "可连接性告警" -#: terminal/notifications.py:189 +#: terminal/notifications.py:228 #: terminal/templates/terminal/_msg_check_command_replay_storage_connectivity.html:4 msgid "Invalid storage" msgstr "无效的存储" @@ -6056,15 +6074,23 @@ msgstr "RDS 远程应用注销时间限制" msgid "Load status" msgstr "负载状态" -#: terminal/serializers/command.py:19 +#: terminal/serializers/command.py:20 msgid "Session ID" msgstr "会话ID" -#: terminal/serializers/command.py:47 +#: terminal/serializers/command.py:42 +msgid "Command Filter ACL" +msgstr "命令过滤器" + +#: terminal/serializers/command.py:45 +msgid "Command Group" +msgstr "命令组" + +#: terminal/serializers/command.py:58 msgid "Account " msgstr "账号" -#: terminal/serializers/command.py:49 +#: terminal/serializers/command.py:60 msgid "Timestamp" msgstr "时间戳" @@ -6235,9 +6261,17 @@ msgid "Check command replay storage connectivity" msgstr "检查命令及录像存储可连接性 " #: terminal/templates/terminal/_msg_command_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:5 +#: terminal/templates/terminal/_msg_command_warning.html:8 +#: terminal/templates/terminal/_msg_command_warning.html:11 +#: terminal/templates/terminal/_msg_command_warning.html:14 msgid "view" msgstr "查看" +#: terminal/templates/terminal/_msg_command_warning.html:13 +msgid "Command acl group" +msgstr "命令过滤组" + #: terminal/utils/db_port_mapper.py:84 msgid "" "No available port is matched. The number of databases may have exceeded the " @@ -7202,10 +7236,8 @@ msgid "Google Cloud Platform" msgstr "谷歌云" #: xpack/plugins/cloud/const.py:20 -#, fuzzy -#| msgid "Cloud" msgid "UCloud" -msgstr "云服务" +msgstr "" #: xpack/plugins/cloud/const.py:22 msgid "VMware" @@ -7623,10 +7655,8 @@ msgid "Test timeout" msgstr "测试超时时间" #: xpack/plugins/cloud/serializers/account_attrs.py:212 -#, fuzzy -#| msgid "Reject" msgid "Project" -msgstr "拒绝" +msgstr "" #: xpack/plugins/cloud/serializers/task.py:28 msgid "" @@ -7723,9 +7753,3 @@ msgstr "旗舰版" #: xpack/plugins/license/models.py:86 msgid "Community edition" msgstr "社区版" - -#~ msgid "e.g. http(s)://host" -#~ msgstr "如: http(s)://host" - -#~ msgid "Please enable cookies and try again." -#~ msgstr "设置你的浏览器支持cookie" diff --git a/apps/terminal/api/session/command.py b/apps/terminal/api/session/command.py index b855181b8..dc4778b80 100644 --- a/apps/terminal/api/session/command.py +++ b/apps/terminal/api/session/command.py @@ -6,11 +6,12 @@ from rest_framework import generics from rest_framework.fields import DateTimeField from rest_framework.response import Response +from acls.models import CommandFilterACL from terminal.models import CommandStorage, Session, Command from terminal.filters import CommandFilter from orgs.utils import current_org from common.api import JMSBulkModelViewSet -from common.utils import get_logger +from common.utils import get_logger, is_uuid from terminal.serializers import ( SessionCommandSerializer, InsecureCommandAlertSerializer ) @@ -18,7 +19,8 @@ from terminal.exceptions import StorageInvalid from terminal.backends import ( get_command_storage, get_multi_command_storage ) -from terminal.notifications import CommandAlertMessage +from terminal.notifications import CommandAlertMessage, CommandWarningMessage +from terminal.const import RiskLevelChoices logger = get_logger(__name__) __all__ = ['CommandViewSet', 'InsecureCommandAlertAPI'] @@ -199,7 +201,30 @@ class InsecureCommandAlertAPI(generics.CreateAPIView): serializer = InsecureCommandAlertSerializer(data=request.data, many=True) serializer.is_valid(raise_exception=True) commands = serializer.validated_data + + acl_ids = [] + for cmd in commands: + acl_id = cmd.get('cmd_filter_acl') + if not is_uuid(acl_id): + continue + acl_ids.append(acl_id) + + acls = CommandFilterACL.objects.filter(id__in=acl_ids) + acls_mapper = {str(acl.id): acl for acl in acls} + for command in commands: - if command['risk_level'] >= settings.SECURITY_INSECURE_COMMAND_LEVEL: + risk_level = command.get('risk_level') + + if risk_level in [RiskLevelChoices.reject, RiskLevelChoices.review_reject]: CommandAlertMessage(command).publish_async() - return Response() + elif risk_level in [RiskLevelChoices.warning]: + acl_id = command.get('cmd_filter_acl') + acl = acls_mapper.get(acl_id) + if not acl: + logger.info(f'ACL not found: {acl_id}') + continue + for reviewer in acl.reviewers.all(): + CommandWarningMessage(reviewer, command).publish_async() + else: + logger.info(f'Risk level ignore: {risk_level}') + return Response({'msg': 'ok'}) diff --git a/apps/terminal/backends/command/models.py b/apps/terminal/backends/command/models.py index da535a17c..b56f8c673 100644 --- a/apps/terminal/backends/command/models.py +++ b/apps/terminal/backends/command/models.py @@ -8,12 +8,10 @@ from django.utils.translation import ugettext_lazy as _ from common.utils.common import lazyproperty from orgs.mixins.models import OrgModelMixin +from terminal.const import RiskLevelChoices class AbstractSessionCommand(OrgModelMixin): - class RiskLevelChoices(models.IntegerChoices): - ordinary = 0, _('Ordinary') - dangerous = 5, _('Dangerous') id = models.UUIDField(default=uuid.uuid4, primary_key=True) user = models.CharField(max_length=64, db_index=True, verbose_name=_("User")) @@ -23,7 +21,7 @@ class AbstractSessionCommand(OrgModelMixin): output = models.CharField(max_length=1024, blank=True, verbose_name=_("Output")) session = models.CharField(max_length=36, db_index=True, verbose_name=_("Session")) risk_level = models.SmallIntegerField( - default=RiskLevelChoices.ordinary, choices=RiskLevelChoices.choices, db_index=True, + default=RiskLevelChoices.accept, choices=RiskLevelChoices.choices, db_index=True, verbose_name=_("Risk level") ) timestamp = models.IntegerField(db_index=True) diff --git a/apps/terminal/const.py b/apps/terminal/const.py index 16f1f0341..b05de71bb 100644 --- a/apps/terminal/const.py +++ b/apps/terminal/const.py @@ -1,10 +1,19 @@ # -*- coding: utf-8 -*- # -from django.db.models import TextChoices +from django.db.models import TextChoices, IntegerChoices from django.utils.translation import ugettext_lazy as _ +class RiskLevelChoices(IntegerChoices): + accept = 0, _('Accept') + warning = 4, _('Warning') + reject = 5, _('Reject') + review_reject = 6, _('Review & Reject') + review_accept = 7, _('Review & Accept') + review_cancel = 8, _('Review & Cancel') + + class ReplayStorageType(TextChoices): null = 'null', 'Null', server = 'server', 'Server' diff --git a/apps/terminal/migrations/0023_command_risk_level.py b/apps/terminal/migrations/0023_command_risk_level.py index 6ada1b826..0b5ed6bb6 100644 --- a/apps/terminal/migrations/0023_command_risk_level.py +++ b/apps/terminal/migrations/0023_command_risk_level.py @@ -13,6 +13,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='command', name='risk_level', - field=models.SmallIntegerField(choices=[(0, 'Ordinary'), (5, 'Dangerous')], db_index=True, default=0, verbose_name='Risk level'), + field=models.SmallIntegerField(choices=[(0, 'Accept'), (4, 'Warning'), (5, 'Reject'), (6, 'Review & Reject'), (7, 'Review & Accept'), (8, 'Review & Cancel')], db_index=True, default=0, verbose_name='Risk level'), ), ] diff --git a/apps/terminal/notifications.py b/apps/terminal/notifications.py index 919bf9c65..804f8d44b 100644 --- a/apps/terminal/notifications.py +++ b/apps/terminal/notifications.py @@ -9,7 +9,7 @@ from common.utils import lazyproperty from common.utils.timezone import local_now_display from notifications.backends import BACKEND from notifications.models import SystemMsgSubscription -from notifications.notifications import SystemMessage +from notifications.notifications import SystemMessage, UserMessage from terminal.models import Session, Command from users.models import User @@ -26,13 +26,16 @@ class CommandAlertMixin: _get_message: Callable message_type_label: str + def __str__(self): + return str(self.message_type_label) + @lazyproperty def subject(self): _input = self.command['input'] if isinstance(_input, str): _input = _input.replace('\r\n', ' ').replace('\r', ' ').replace('\n', ' ') - subject = self.message_type_label + "%(cmd)s" % { + subject = self.message_type_label + ": %(cmd)s" % { 'cmd': _input } return subject @@ -61,6 +64,45 @@ class CommandAlertMixin: subscription.save() +class CommandWarningMessage(CommandAlertMixin, UserMessage): + message_type_label = _('Danger command warning') + + def __init__(self, user, command): + super().__init__(user) + self.command = command + + def get_html_msg(self) -> dict: + session = self.command.get('session') + session_url = reverse( + 'api-terminal:session-detail', kwargs={'pk': session}, + external=True, api_to_ui=True + ) + '?oid={}'.format(self.command['org_id']) + + asset = self.command.get('asset') + asset_url = reverse( + 'assets:asset-detail', kwargs={'pk': asset}, + api_to_ui=True, external=True, is_console=True + ) + '?oid={}'.format(self.command.get('org_id')) + + cmd_filter_acl = self.command.get('cmd_filter_acl') + cmd_group = self.command.get('cmd_group') + + context = { + "command": self.command['input'], + 'asset_url': asset_url, + 'session_url': session_url.replace( + '/terminal/sessions/', '/audit/sessions/sessions/' + ), + 'cmd_filter_acl_url': settings.SITE_URL + '/ui/#/console/perms/cmd-acls/%s/' % cmd_filter_acl, + 'cmd_group_url': settings.SITE_URL + '/ui/#/console/perms/cmd-groups/%s/' % cmd_group, + } + message = render_to_string('terminal/_msg_command_warning.html', context) + return { + 'subject': self.subject, + 'message': message + } + + class CommandAlertMessage(CommandAlertMixin, SystemMessage): category = CATEGORY category_label = CATEGORY_LABEL @@ -69,9 +111,6 @@ class CommandAlertMessage(CommandAlertMixin, SystemMessage): def __init__(self, command): self.command = command - def __str__(self): - return str(self.message_type_label) - @classmethod def gen_test_msg(cls): command = Command.objects.first() diff --git a/apps/terminal/serializers/command.py b/apps/terminal/serializers/command.py index c58fd93e6..b845c6609 100644 --- a/apps/terminal/serializers/command.py +++ b/apps/terminal/serializers/command.py @@ -6,6 +6,7 @@ from common.utils import pretty_string from common.serializers.fields import LabeledChoiceField from terminal.backends.command.models import AbstractSessionCommand from terminal.models import Command +from terminal.const import RiskLevelChoices __all__ = ['SessionCommandSerializer', 'InsecureCommandAlertSerializer'] @@ -18,7 +19,7 @@ class SimpleSessionCommandSerializer(serializers.ModelSerializer): input = serializers.CharField(max_length=2048, label=_("Command")) session = serializers.CharField(max_length=36, label=_("Session ID")) risk_level = LabeledChoiceField( - choices=AbstractSessionCommand.RiskLevelChoices.choices, + choices=RiskLevelChoices.choices, required=False, label=_("Risk level"), ) org_id = serializers.CharField( @@ -37,7 +38,17 @@ class SimpleSessionCommandSerializer(serializers.ModelSerializer): class InsecureCommandAlertSerializer(SimpleSessionCommandSerializer): - pass + cmd_filter_acl = serializers.CharField( + max_length=128, required=False, label=_("Command Filter ACL") + ) + cmd_group = serializers.CharField( + max_length=128, required=True, label=_("Command Group") + ) + + class Meta(SimpleSessionCommandSerializer.Meta): + fields = SimpleSessionCommandSerializer.Meta.fields + [ + 'cmd_filter_acl', 'cmd_group' + ] class SessionCommandSerializerMixin(serializers.Serializer): diff --git a/apps/terminal/templates/terminal/_msg_command_warning.html b/apps/terminal/templates/terminal/_msg_command_warning.html new file mode 100644 index 000000000..215129dbe --- /dev/null +++ b/apps/terminal/templates/terminal/_msg_command_warning.html @@ -0,0 +1,23 @@ +{% load i18n %} + +
+ {% trans 'Asset' %}: + {% trans 'view' %} +
+ {% trans 'Session' %}: + {% trans 'view' %} +
+ {% trans 'Command acl' %}: + {% trans 'view' %} +
+ {% trans 'Command acl group' %}: + {% trans 'view' %} +
+ {% trans 'Command' %}:
+ +
 {{ command }} 
+
+
From 4caa704abe34cb9284c7ab938ce53db9bb116f01 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 11 Jul 2023 17:04:43 +0800 Subject: [PATCH 107/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/const/protocol.py | 5 +++++ apps/assets/migrations/0120_auto_20230630_1613.py | 2 +- apps/locale/zh/LC_MESSAGES/django.po | 4 ++-- apps/terminal/connect_methods.py | 6 ++++++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index 1eff23a49..b2bf254e6 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -181,6 +181,11 @@ class Protocol(ChoicesMixin, models.TextChoices): 'type': 'str', 'default': 'type=submit', 'label': _('Submit selector') + }, + 'script': { + 'type': 'text', + 'default': '', + 'label': _('Script'), } } }, diff --git a/apps/assets/migrations/0120_auto_20230630_1613.py b/apps/assets/migrations/0120_auto_20230630_1613.py index aa884a217..a5205804b 100644 --- a/apps/assets/migrations/0120_auto_20230630_1613.py +++ b/apps/assets/migrations/0120_auto_20230630_1613.py @@ -12,7 +12,7 @@ def add_chatgpt_platform(apps, schema_editor): domain_enabled=False, su_enabled=False, comment='ChatGPT', created_by='System', updated_by='System', ) - platform.protocols.create(name='chatgpt', port=443, primary=True) + platform.protocols.create(name='chatgpt', port=443, primary=True, setting={'api_mode': 'gpt-3.5-turbo'}) automation_cls.objects.create(ansible_enabled=False, platform=platform) diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index b74c0fc53..f6b13ebb4 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -1399,7 +1399,7 @@ msgstr "忽略证书校验" #: assets/models/asset/gpt.py:8 msgid "Proxy" -msgstr "" +msgstr "代理" #: assets/models/asset/web.py:9 assets/serializers/asset/info/spec.py:16 msgid "Autofill" @@ -1727,7 +1727,7 @@ msgstr "" #: assets/serializers/asset/gpt.py:23 msgid "HTTP proxy" -msgstr "HTTP 代理" +msgstr "HTTP(s) 代理" #: assets/serializers/asset/info/gathered.py:6 msgid "Vendor" diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index a4901b93c..4a85c2d01 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -214,6 +214,12 @@ class ConnectMethodUtil: 'support': [Protocol.rdp], 'match': 'map' }, + TerminalType.kael: { + 'web_methods': [WebMethod.web_gui], + 'listen': [Protocol.http], + 'support': [Protocol.chatgpt], + 'match': 'm2m' + } } return protocols From 61d83283375c0fb553aac7aee5aa2e231d46e825 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 11 Jul 2023 17:27:47 +0800 Subject: [PATCH 108/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20protocol?= =?UTF-8?q?=20=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/const/protocol.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index b2bf254e6..65fdfd2e2 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -163,6 +163,7 @@ class Protocol(ChoicesMixin, models.TextChoices): 'secret_types': ['password'], 'setting': { 'autofill': { + 'label': _('Autofill'), 'type': 'choice', 'choices': FillType.choices, 'default': 'basic', From 6096ccc30aa600c300d961f9efa9e9055bd809c0 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 11 Jul 2023 17:59:18 +0800 Subject: [PATCH 109/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20protocols?= =?UTF-8?q?=20=E9=BB=98=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/const/protocol.py | 2 +- apps/terminal/connect_methods.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index 65fdfd2e2..0b73e6c57 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -185,7 +185,7 @@ class Protocol(ChoicesMixin, models.TextChoices): }, 'script': { 'type': 'text', - 'default': '', + 'default': [], 'label': _('Script'), } } diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index 4a85c2d01..0060cf321 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -34,6 +34,7 @@ class WebMethod(TextChoices): Protocol.clickhouse: [cls.web_cli], Protocol.k8s: [cls.web_cli], + Protocol.chatgpt: [cls.web_gui], Protocol.http: [] } if not settings.XPACK_ENABLED: From dd5802316d485c925aa1d23e01d8374a12b971c5 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 11 Jul 2023 19:29:56 +0800 Subject: [PATCH 110/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20connect=20?= =?UTF-8?q?methods=20=E6=94=AF=E6=8C=81=20(#10945)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ibuler --- apps/assets/const/protocol.py | 19 +++++++++++-- apps/terminal/connect_methods.py | 48 +++++++++----------------------- 2 files changed, 29 insertions(+), 38 deletions(-) diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py index 0b73e6c57..aface581c 100644 --- a/apps/assets/const/protocol.py +++ b/apps/assets/const/protocol.py @@ -113,21 +113,25 @@ class Protocol(ChoicesMixin, models.TextChoices): 'port': 5432, 'required': True, 'secret_types': ['password'], + 'xpack': True }, cls.oracle: { 'port': 1521, 'required': True, 'secret_types': ['password'], + 'xpack': True }, cls.sqlserver: { 'port': 1433, 'required': True, 'secret_types': ['password'], + 'xpack': True, }, cls.clickhouse: { 'port': 9000, 'required': True, 'secret_types': ['password'], + 'xpack': True, }, cls.mongodb: { 'port': 27017, @@ -231,10 +235,19 @@ class Protocol(ChoicesMixin, models.TextChoices): **cls.gpt_protocols(), } + @classmethod + @cached_method(ttl=600) + def xpack_protocols(cls): + return [ + protocol + for protocol, config in cls.settings().items() + if config.get('xpack', False) + ] + @classmethod def protocol_secret_types(cls): - settings = cls.settings() + configs = cls.settings() return { - protocol: settings[protocol]['secret_types'] or ['password'] - for protocol in cls.settings() + protocol: configs[protocol]['secret_types'] or ['password'] + for protocol in configs } diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index 0060cf321..cc04da982 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -17,32 +17,10 @@ class WebMethod(TextChoices): web_sftp = 'web_sftp', 'Web SFTP' @classmethod - def get_methods(cls): + def get_spec_methods(cls): methods = { Protocol.ssh: [cls.web_cli, cls.web_sftp], - Protocol.telnet: [cls.web_cli], - Protocol.rdp: [cls.web_gui], - Protocol.vnc: [cls.web_gui], - - Protocol.mysql: [cls.web_cli], - Protocol.mariadb: [cls.web_cli], - Protocol.oracle: [cls.web_cli], - Protocol.postgresql: [cls.web_cli], - Protocol.sqlserver: [cls.web_cli], - Protocol.redis: [cls.web_cli], - Protocol.mongodb: [cls.web_cli], - Protocol.clickhouse: [cls.web_cli], - - Protocol.k8s: [cls.web_cli], - Protocol.chatgpt: [cls.web_gui], - Protocol.http: [] } - if not settings.XPACK_ENABLED: - return methods - - web_gui_dbs = [Protocol.mysql, Protocol.mariadb, Protocol.oracle, Protocol.postgresql, Protocol.sqlserver] - for db in web_gui_dbs: - methods[db].append(cls.web_gui) return methods @@ -94,15 +72,11 @@ class NativeClient(TextChoices): def xpack_methods(cls): return [cls.mstsc] - @classmethod - def xpack_protocols(cls): - return [Protocol.rdp, Protocol.oracle, Protocol.clickhouse, Protocol.sqlserver] - @classmethod def get_methods(cls, os='windows'): clients_map = cls.get_native_clients() methods = defaultdict(list) - xpack_protocols = cls.xpack_protocols() + xpack_protocols = Protocol.xpack_protocols() for protocol, _clients in clients_map.items(): if not settings.XPACK_ENABLED and protocol in xpack_protocols: @@ -170,10 +144,10 @@ class ConnectMethodUtil: _all_methods = {} @classmethod - def protocols(cls): + def components(cls): protocols = { TerminalType.koko: { - 'web_methods': [WebMethod.web_cli, WebMethod.web_sftp], + 'web_methods': [WebMethod.web_cli], 'listen': [Protocol.http, Protocol.ssh], 'support': [ Protocol.ssh, Protocol.telnet, @@ -286,16 +260,20 @@ class ConnectMethodUtil: return cls._all_methods['os'] methods = defaultdict(list) - web_methods = WebMethod.get_methods() + spec_web_methods = WebMethod.get_spec_methods() native_methods = NativeClient.get_methods(os) applet_methods = AppletMethod.get_methods() - for component, component_protocol in cls.protocols().items(): + for component, component_protocol in cls.components().items(): support = component_protocol['support'] component_web_methods = component_protocol.get('web_methods', []) for protocol in support: # Web 方式 + web_methods = spec_web_methods.get(protocol, None) + if web_methods is None: + web_methods = component_web_methods + methods[str(protocol)].extend([ { 'component': component.value, @@ -304,8 +282,7 @@ class ConnectMethodUtil: 'value': method.value, 'label': method.label, } - for method in web_methods.get(protocol, []) - if method in component_web_methods + for method in web_methods ]) # 客户端方式 @@ -313,6 +290,7 @@ class ConnectMethodUtil: listen = [protocol] else: listen = component_protocol['listen'] + for listen_protocol in listen: # Native method if component == TerminalType.koko and protocol.value != Protocol.ssh: @@ -328,7 +306,7 @@ class ConnectMethodUtil: for method in native_methods[listen_protocol] ]) - # 远程应用方式,这个只有 tinker 提供 + # 远程应用方式,这个只有 tinker 提供,并且协议可能是自定义的 for protocol, applet_methods in applet_methods.items(): for method in applet_methods: method['listen'] = 'rdp' From 68e2de81d85ed48785701e0df97ce3c1db87e962 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Wed, 12 Jul 2023 11:05:01 +0800 Subject: [PATCH 111/167] =?UTF-8?q?perf:=20windows=20winrm=E4=BD=BF?= =?UTF-8?q?=E7=94=A8ntlm=E8=AE=A4=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/ansible/inventory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index 80922859b..52f93e2b2 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -139,7 +139,7 @@ class JMSInventory: ansible_config['ansible_winrm_server_cert_validation'] = 'ignore' else: ansible_config['ansible_winrm_scheme'] = 'http' - ansible_config['ansible_winrm_transport'] = 'plaintext' + ansible_config['ansible_winrm_transport'] = 'ntlm' return ansible_config def asset_to_host(self, asset, account, automation, protocols, platform): From 2898d25bf8958d0dfe3f9c80a05d8b63ce29adc4 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 13 Jul 2023 11:45:15 +0800 Subject: [PATCH 112/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20log=20?= =?UTF-8?q?=E7=9A=84=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .dockerignore | 1 - .gitignore | 1 - apps/common/management/commands/services/hands.py | 7 ++++--- apps/jumpserver/conf.py | 2 +- apps/jumpserver/settings/logging.py | 2 +- apps/jumpserver/urls.py | 7 +++++-- apps/manage.py | 3 +-- logs/.gitkeep | 1 - 8 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 logs/.gitkeep diff --git a/.dockerignore b/.dockerignore index 81c9033ba..0ddcc29ae 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,4 @@ .git -logs/* data/* .github tmp/* diff --git a/.gitignore b/.gitignore index 9573a70b7..985f77580 100644 --- a/.gitignore +++ b/.gitignore @@ -35,7 +35,6 @@ celerybeat-schedule.db docs/_build/ xpack xpack.bak -logs/* ### Vagrant ### .vagrant/ release/* diff --git a/apps/common/management/commands/services/hands.py b/apps/common/management/commands/services/hands.py index eb6aba418..c2e625e8b 100644 --- a/apps/common/management/commands/services/hands.py +++ b/apps/common/management/commands/services/hands.py @@ -1,12 +1,14 @@ +import logging import os import sys -import logging + from django.conf import settings from apps.jumpserver.const import CONFIG try: from apps.jumpserver import const + __version__ = const.VERSION except ImportError as e: print("Not found __version__: {}".format(e)) @@ -15,12 +17,11 @@ except ImportError as e: __version__ = 'Unknown' sys.exit(1) - HTTP_HOST = CONFIG.HTTP_BIND_HOST or '127.0.0.1' HTTP_PORT = CONFIG.HTTP_LISTEN_PORT or 8080 WS_PORT = CONFIG.WS_LISTEN_PORT or 8082 DEBUG = CONFIG.DEBUG or False BASE_DIR = os.path.dirname(settings.BASE_DIR) -LOG_DIR = os.path.join(BASE_DIR, 'logs') +LOG_DIR = os.path.join(BASE_DIR, 'data', 'logs') APPS_DIR = os.path.join(BASE_DIR, 'apps') TMP_DIR = os.path.join(BASE_DIR, 'tmp') diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index a0672422a..9faf6d64b 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -187,7 +187,7 @@ class Config(dict): 'DEBUG': False, 'DEBUG_DEV': False, 'LOG_LEVEL': 'DEBUG', - 'LOG_DIR': os.path.join(PROJECT_DIR, 'logs'), + 'LOG_DIR': os.path.join(PROJECT_DIR, 'data/logs'), 'DB_ENGINE': 'mysql', 'DB_NAME': 'jumpserver', 'DB_HOST': '127.0.0.1', diff --git a/apps/jumpserver/settings/logging.py b/apps/jumpserver/settings/logging.py index 6d4498e3f..c4cf90ebb 100644 --- a/apps/jumpserver/settings/logging.py +++ b/apps/jumpserver/settings/logging.py @@ -4,7 +4,7 @@ import os from ..const import PROJECT_DIR, CONFIG -LOG_DIR = os.path.join(PROJECT_DIR, 'logs') +LOG_DIR = os.path.join(PROJECT_DIR, 'data', 'logs') JUMPSERVER_LOG_FILE = os.path.join(LOG_DIR, 'jumpserver.log') DRF_EXCEPTION_LOG_FILE = os.path.join(LOG_DIR, 'drf_exception.log') UNEXPECTED_EXCEPTION_LOG_FILE = os.path.join(LOG_DIR, 'unexpected_exception.log') diff --git a/apps/jumpserver/urls.py b/apps/jumpserver/urls.py index f005f81f0..971995ffe 100644 --- a/apps/jumpserver/urls.py +++ b/apps/jumpserver/urls.py @@ -1,12 +1,12 @@ # ~*~ coding: utf-8 ~*~ from __future__ import unicode_literals + import os import private_storage.urls - -from django.urls import path, include, re_path from django.conf import settings from django.conf.urls.static import static +from django.urls import path, include, re_path from django.views.i18n import JavaScriptCatalog from . import views, api @@ -64,6 +64,9 @@ urlpatterns += [ # Protect media path('media/', include(private_storage.urls)), ] +if settings.DEBUG: + urlpatterns += static('/luna/', document_root=(settings.DATA_DIR + '/luna')) + urlpatterns += static('/lina/', document_root=(settings.DATA_DIR + '/lina')) # js i18n 路由文件 urlpatterns += [ diff --git a/apps/manage.py b/apps/manage.py index d24c5fd38..17f2ce477 100755 --- a/apps/manage.py +++ b/apps/manage.py @@ -1,11 +1,10 @@ #!/usr/bin/env python import os import sys -import errno if __name__ == "__main__": try: - os.makedirs('../logs') + os.makedirs('../data/logs') except: pass diff --git a/logs/.gitkeep b/logs/.gitkeep deleted file mode 100644 index 1a4baf536..000000000 --- a/logs/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - From c1de9151b8d6c9f605c883f39ce71cf324f3acd0 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 13 Jul 2023 11:46:47 +0800 Subject: [PATCH 113/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E5=9C=B0?= =?UTF-8?q?=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 9faf6d64b..902f96df7 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -187,7 +187,7 @@ class Config(dict): 'DEBUG': False, 'DEBUG_DEV': False, 'LOG_LEVEL': 'DEBUG', - 'LOG_DIR': os.path.join(PROJECT_DIR, 'data/logs'), + 'LOG_DIR': os.path.join(PROJECT_DIR, 'data', 'logs'), 'DB_ENGINE': 'mysql', 'DB_NAME': 'jumpserver', 'DB_HOST': '127.0.0.1', From efc538a569e55516b5f46136ac9a64df67a0ea06 Mon Sep 17 00:00:00 2001 From: maninhill <41712985+maninhill@users.noreply.github.com> Date: Thu, 13 Jul 2023 11:55:12 +0800 Subject: [PATCH 114/167] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a2b98e8a3..56feed7e4 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,9 @@ JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运 | [KoKo](https://github.com/jumpserver/koko) | Koko release | JumpServer 字符协议 Connector 项目,替代原来 Python 版本的 [Coco](https://github.com/jumpserver/coco) | | [Lion](https://github.com/jumpserver/lion-release) | Lion release | JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/) | | [Magnus](https://github.com/jumpserver/magnus-release) | Magnus release | JumpServer 数据库代理 Connector 项目 | +| [Chen](https://github.com/jumpserver/chen-release) | Chen release | JumpServer Web DB 项目,替代原来的 OmniDB | +| [Kael](https://github.com/jumpserver/kael) | Kael release | JumpServer 连接 GPT 资产的组件项目 | +| [Wisp](https://github.com/jumpserver/wisp) | Magnus release | JumpServer 各系统终端组件和 Core Api 通信的组件项目 | | [Clients](https://github.com/jumpserver/clients) | Clients release | JumpServer 客户端 项目 | | [Installer](https://github.com/jumpserver/installer) | Installer release | JumpServer 安装包 项目 | @@ -109,10 +112,6 @@ JumpServer是一款安全产品,请参考 [基本安全建议](https://docs.ju - 邮箱:support@fit2cloud.com - 电话:400-052-0755 -## 致谢开源 - -- [Apache Guacamole](https://guacamole.apache.org/): Web 页面连接 RDP、SSH、VNC 等协议资产,JumpServer Lion 组件使用到该项目; -- [OmniDB](https://omnidb.org/): Web 页面连接使用数据库,JumpServer Web 数据库组件使用到该项目。 ## License & Copyright From c9f3e4b28d4f8094d7b16564d9d9b899b3d02782 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 13 Jul 2023 14:29:47 +0800 Subject: [PATCH 115/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 56feed7e4..93d7efe0c 100644 --- a/README.md +++ b/README.md @@ -91,18 +91,20 @@ JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运 ## 组件项目 -| 项目 | 状态 | 描述 | -|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------| -| [Lina](https://github.com/jumpserver/lina) | Lina release | JumpServer Web UI 项目 | -| [Luna](https://github.com/jumpserver/luna) | Luna release | JumpServer Web Terminal 项目 | -| [KoKo](https://github.com/jumpserver/koko) | Koko release | JumpServer 字符协议 Connector 项目,替代原来 Python 版本的 [Coco](https://github.com/jumpserver/coco) | -| [Lion](https://github.com/jumpserver/lion-release) | Lion release | JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/) | -| [Magnus](https://github.com/jumpserver/magnus-release) | Magnus release | JumpServer 数据库代理 Connector 项目 | -| [Chen](https://github.com/jumpserver/chen-release) | Chen release | JumpServer Web DB 项目,替代原来的 OmniDB | -| [Kael](https://github.com/jumpserver/kael) | Kael release | JumpServer 连接 GPT 资产的组件项目 | -| [Wisp](https://github.com/jumpserver/wisp) | Magnus release | JumpServer 各系统终端组件和 Core Api 通信的组件项目 | -| [Clients](https://github.com/jumpserver/clients) | Clients release | JumpServer 客户端 项目 | -| [Installer](https://github.com/jumpserver/installer) | Installer release | JumpServer 安装包 项目 | +| 项目 | 状态 | 描述 | +|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------| +| [Lina](https://github.com/jumpserver/lina) | Lina release | JumpServer Web UI 项目 | +| [Luna](https://github.com/jumpserver/luna) | Luna release | JumpServer Web Terminal 项目 | +| [KoKo](https://github.com/jumpserver/koko) | Koko release | JumpServer 字符协议 Connector 项目 | +| [Lion](https://github.com/jumpserver/lion-release) | Lion release | JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/) | +| [Razor](https://github.com/jumpserver/razor) | 私有 | JumpServer RDP 代理 Connector 项目 | +| [Tinker](https://github.com/jumpserver/tinker) | 私有 | JumpServer 远程应用 Connector 项目 | +| [Magnus](https://github.com/jumpserver/magnus-release) | Magnus release | JumpServer 数据库代理 Connector 项目 | +| [Chen](https://github.com/jumpserver/chen-release) | Chen release | JumpServer Web DB 项目,替代原来的 OmniDB | +| [Kael](https://github.com/jumpserver/kael) | Kael release | JumpServer 连接 GPT 资产的组件项目 | +| [Wisp](https://github.com/jumpserver/wisp) | Magnus release | JumpServer 各系统终端组件和 Core Api 通信的组件项目 | +| [Clients](https://github.com/jumpserver/clients) | Clients release | JumpServer 客户端 项目 | +| [Installer](https://github.com/jumpserver/installer) | Installer release | JumpServer 安装包 项目 | ## 安全说明 @@ -112,7 +114,6 @@ JumpServer是一款安全产品,请参考 [基本安全建议](https://docs.ju - 邮箱:support@fit2cloud.com - 电话:400-052-0755 - ## License & Copyright Copyright (c) 2014-2023 飞致云 FIT2CLOUD, All rights reserved. From a1ded0c7379ef35f6f0fb40226af496c3fc9afeb Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 13 Jul 2023 16:00:24 +0800 Subject: [PATCH 116/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=20rbac=20=E6=9D=83=E9=99=90=E4=BD=8D=EF=BC=8C?= =?UTF-8?q?=E7=9D=80=E9=87=8D=20connection=20token=20=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/connection_token.py | 26 ++-- .../migrations/0021_auto_20230713_1459.py | 24 ++++ .../authentication/models/connection_token.py | 17 ++- .../serializers/connection_token.py | 36 ++---- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 120 ++++++++++-------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 116 +++++++++-------- apps/rbac/builtin.py | 11 +- apps/rbac/const.py | 3 +- apps/rbac/tree.py | 3 +- .../migrations/0050_auto_20220606_1745.py | 4 +- 12 files changed, 209 insertions(+), 159 deletions(-) create mode 100644 apps/authentication/migrations/0021_auto_20230713_1459.py diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 7a0b38872..d6a872841 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -8,7 +8,7 @@ from django.http import HttpResponse from django.shortcuts import get_object_or_404 from django.utils import timezone from django.utils.translation import ugettext_lazy as _ -from rest_framework import status +from rest_framework import status, serializers from rest_framework.decorators import action from rest_framework.exceptions import PermissionDenied, ValidationError from rest_framework.request import Request @@ -28,7 +28,7 @@ from ..models import ConnectionToken, date_expired_default from ..serializers import ( ConnectionTokenSerializer, ConnectionTokenSecretSerializer, SuperConnectionTokenSerializer, ConnectTokenAppletOptionSerializer, - ConnectionTokenUpdateSerializer + ConnectionTokenReusableSerializer, ) __all__ = ['ConnectionTokenViewSet', 'SuperConnectionTokenViewSet'] @@ -212,6 +212,17 @@ class ExtraActionApiMixin(RDPFileClientProtocolURLMixin): instance.expire() return Response(status=status.HTTP_204_NO_CONTENT) + @action(methods=['PATCH'], detail=True, url_path='reuse') + def reuse(self, request, *args, **kwargs): + instance = self.get_object() + if not settings.CONNECTION_TOKEN_REUSABLE: + raise serializers.ValidationError(_('Reusable connection token is not allowed, global setting not enabled')) + serializer = self.get_serializer(instance, data=request.data, partial=True) + serializer.is_valid(raise_exception=True) + is_reusable = serializer.validated_data.get('is_reusable', False) + instance.set_reusable(is_reusable) + return Response(data=serializer.data) + @action(methods=['POST'], detail=False) def exchange(self, request, *args, **kwargs): pk = request.data.get('id', None) or request.data.get('pk', None) @@ -232,17 +243,16 @@ class ConnectionTokenViewSet(ExtraActionApiMixin, RootOrgViewMixin, JMSModelView search_fields = filterset_fields serializer_classes = { 'default': ConnectionTokenSerializer, - 'update': ConnectionTokenUpdateSerializer, - 'partial_update': ConnectionTokenUpdateSerializer, + 'reuse': ConnectionTokenReusableSerializer, } http_method_names = ['get', 'post', 'patch', 'head', 'options', 'trace'] rbac_perms = { 'list': 'authentication.view_connectiontoken', 'retrieve': 'authentication.view_connectiontoken', - 'update': 'authentication.change_connectiontoken', 'create': 'authentication.add_connectiontoken', 'exchange': 'authentication.add_connectiontoken', - 'expire': 'authentication.change_connectiontoken', + 'reuse': 'authentication.reuse_connectiontoken', + 'expire': 'authentication.expire_connectiontoken', 'get_rdp_file': 'authentication.add_connectiontoken', 'get_client_protocol_url': 'authentication.add_connectiontoken', } @@ -346,7 +356,7 @@ class SuperConnectionTokenViewSet(ConnectionTokenViewSet): rbac_perms = { 'create': 'authentication.add_superconnectiontoken', 'renewal': 'authentication.add_superconnectiontoken', - 'get_secret_detail': 'authentication.view_connectiontokensecret', + 'get_secret_detail': 'authentication.view_superconnectiontokensecret', 'get_applet_info': 'authentication.view_superconnectiontoken', 'release_applet_account': 'authentication.view_superconnectiontoken', } @@ -376,7 +386,7 @@ class SuperConnectionTokenViewSet(ConnectionTokenViewSet): @action(methods=['POST'], detail=False, url_path='secret') def get_secret_detail(self, request, *args, **kwargs): """ 非常重要的 api, 在逻辑层再判断一下 rbac 权限, 双重保险 """ - rbac_perm = 'authentication.view_connectiontokensecret' + rbac_perm = 'authentication.view_superconnectiontokensecret' if not request.user.has_perm(rbac_perm): raise PermissionDenied('Not allow to view secret') diff --git a/apps/authentication/migrations/0021_auto_20230713_1459.py b/apps/authentication/migrations/0021_auto_20230713_1459.py new file mode 100644 index 000000000..03913f766 --- /dev/null +++ b/apps/authentication/migrations/0021_auto_20230713_1459.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2.19 on 2023-07-13 06:59 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ('authentication', '0020_connectiontoken_connect_options'), + ] + + operations = [ + migrations.AlterModelOptions( + name='connectiontoken', + options={'ordering': ('-date_expired',), + 'permissions': [('expire_connectiontoken', 'Can expire connection token'), + ('reuse_connectiontoken', 'Can reuse connection token')], + 'verbose_name': 'Connection token'}, + ), + migrations.AlterModelOptions( + name='superconnectiontoken', + options={'permissions': [('view_superconnectiontokensecret', 'Can view super connection token secret')], + 'verbose_name': 'Super connection token'}, + ), + ] diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py index 3375df145..d6ba7e89f 100644 --- a/apps/authentication/models/connection_token.py +++ b/apps/authentication/models/connection_token.py @@ -54,10 +54,11 @@ class ConnectionToken(JMSOrgBaseModel): class Meta: ordering = ('-date_expired',) - verbose_name = _('Connection token') permissions = [ - ('view_connectiontokensecret', _('Can view connection token secret')) + ('expire_connectiontoken', _('Can expire connection token')), + ('reuse_connectiontoken', _('Can reuse connection token')), ] + verbose_name = _('Connection token') @property def is_expired(self): @@ -80,6 +81,15 @@ class ConnectionToken(JMSOrgBaseModel): self.date_expired = timezone.now() self.save(update_fields=['date_expired']) + def set_reusable(self, is_reusable): + self.is_reusable = is_reusable + if self.is_reusable: + seconds = settings.CONNECTION_TOKEN_REUSABLE_EXPIRATION + else: + seconds = settings.CONNECTION_TOKEN_ONETIME_EXPIRATION + self.date_expired = timezone.now() + timedelta(seconds=seconds) + self.save(update_fields=['is_reusable', 'date_expired']) + def renewal(self): """ 续期 Token,将来支持用户自定义创建 token 后,续期策略要修改 """ self.date_expired = date_expired_default() @@ -255,4 +265,7 @@ class ConnectionToken(JMSOrgBaseModel): class SuperConnectionToken(ConnectionToken): class Meta: proxy = True + permissions = [ + ('view_superconnectiontokensecret', _('Can view super connection token secret')) + ] verbose_name = _("Super connection token") diff --git a/apps/authentication/serializers/connection_token.py b/apps/authentication/serializers/connection_token.py index 28cf79127..bc3d051e1 100644 --- a/apps/authentication/serializers/connection_token.py +++ b/apps/authentication/serializers/connection_token.py @@ -1,20 +1,18 @@ -from django.conf import settings -from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers +from common.serializers import CommonModelSerializer from common.serializers.fields import EncryptedField -from orgs.mixins.serializers import OrgResourceModelSerializerMixin from perms.serializers.permission import ActionChoicesField from ..models import ConnectionToken __all__ = [ 'ConnectionTokenSerializer', 'SuperConnectionTokenSerializer', - 'ConnectionTokenUpdateSerializer', + 'ConnectionTokenReusableSerializer', ] -class ConnectionTokenSerializer(OrgResourceModelSerializerMixin): +class ConnectionTokenSerializer(CommonModelSerializer): expire_time = serializers.IntegerField(read_only=True, label=_('Expired time')) input_secret = EncryptedField( label=_("Input secret"), max_length=40960, required=False, allow_blank=True @@ -60,30 +58,12 @@ class ConnectionTokenSerializer(OrgResourceModelSerializerMixin): return info -class ConnectionTokenUpdateSerializer(ConnectionTokenSerializer): - class Meta(ConnectionTokenSerializer.Meta): +class ConnectionTokenReusableSerializer(CommonModelSerializer): + class Meta: + model = ConnectionToken + fields = ['id', 'date_expired', 'is_reusable'] can_update_fields = ['is_reusable'] - read_only_fields = list(set(ConnectionTokenSerializer.Meta.fields) - set(can_update_fields)) - - def _get_date_expired(self): - delta = self.instance.date_expired - self.instance.date_created - if delta.total_seconds() > 3600 * 24: - return self.instance.date_expired - - seconds = settings.CONNECTION_TOKEN_REUSABLE_EXPIRATION - return timezone.now() + timezone.timedelta(seconds=seconds) - - @staticmethod - def validate_is_reusable(value): - if value and not settings.CONNECTION_TOKEN_REUSABLE: - raise serializers.ValidationError(_('Reusable connection token is not allowed, global setting not enabled')) - return value - - def validate(self, attrs): - reusable = attrs.get('is_reusable', False) - if reusable: - attrs['date_expired'] = self._get_date_expired() - return attrs + read_only_fields = list(set(fields) - set(can_update_fields)) class SuperConnectionTokenSerializer(ConnectionTokenSerializer): diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 2d02dd7eb..820a5d1b0 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3c01e373aea806f104ae77bb4dfbeab1a9c5d4af9ca5c421f62b40f00bbf4b33 -size 147721 +oid sha256:a4463d66ad3eac6127e435d60759e1a6584f93842d959e6129c9b92d1a68de32 +size 148522 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index c78b136bb..a15110564 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-11 12:03+0800\n" +"POT-Creation-Date: 2023-07-13 15:56+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -87,7 +87,7 @@ msgstr "テンプレート" msgid "Skip" msgstr "スキップ" -#: accounts/const/account.py:28 audits/const.py:24 rbac/tree.py:229 +#: accounts/const/account.py:28 audits/const.py:24 rbac/tree.py:230 #: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 msgid "Update" msgstr "更新" @@ -652,7 +652,7 @@ msgstr "ID" #: authentication/models/sso_token.py:16 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 -#: perms/serializers/permission.py:30 rbac/builtin.py:122 +#: perms/serializers/permission.py:30 rbac/builtin.py:123 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:17 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 #: terminal/notifications.py:135 terminal/notifications.py:183 @@ -1023,7 +1023,7 @@ msgid "{} disabled" msgstr "{} 無効" #: assets/automations/ping_gateway/manager.py:33 -#: authentication/models/connection_token.py:118 +#: authentication/models/connection_token.py:128 msgid "No account" msgstr "アカウントなし" @@ -1077,7 +1077,8 @@ msgstr "無効" msgid "Basic" msgstr "基本" -#: assets/const/base.py:35 assets/models/asset/web.py:13 +#: assets/const/base.py:35 assets/const/protocol.py:193 +#: assets/models/asset/web.py:13 msgid "Script" msgstr "脚本" @@ -1185,23 +1186,28 @@ msgstr "AD ドメイン" msgid "Use SSL" msgstr "SSLの使用" -#: assets/const/protocol.py:145 +#: assets/const/protocol.py:149 msgid "Auth username" msgstr "ユーザー名で認証する" -#: assets/const/protocol.py:173 assets/models/asset/web.py:10 +#: assets/const/protocol.py:170 assets/models/asset/web.py:9 +#: assets/serializers/asset/info/spec.py:16 +msgid "Autofill" +msgstr "自動充填" + +#: assets/const/protocol.py:178 assets/models/asset/web.py:10 msgid "Username selector" msgstr "ユーザー名ピッカー" -#: assets/const/protocol.py:178 assets/models/asset/web.py:11 +#: assets/const/protocol.py:183 assets/models/asset/web.py:11 msgid "Password selector" msgstr "パスワードセレクター" -#: assets/const/protocol.py:183 assets/models/asset/web.py:12 +#: assets/const/protocol.py:188 assets/models/asset/web.py:12 msgid "Submit selector" msgstr "ボタンセレクターを確認する" -#: assets/const/protocol.py:201 +#: assets/const/protocol.py:211 msgid "API mode" msgstr "APIモード" @@ -1408,10 +1414,6 @@ msgstr "証明書チェックを無視" msgid "Proxy" msgstr "" -#: assets/models/asset/web.py:9 assets/serializers/asset/info/spec.py:16 -msgid "Autofill" -msgstr "自動充填" - #: assets/models/automations/base.py:22 ops/models/job.py:187 #: settings/serializers/auth/sms.py:99 msgid "Parameters" @@ -1963,7 +1965,7 @@ msgstr "Rmdir" #: audits/const.py:14 audits/const.py:25 #: authentication/templates/authentication/_access_key_modal.html:65 -#: perms/const.py:17 rbac/tree.py:230 +#: perms/const.py:17 rbac/tree.py:231 msgid "Delete" msgstr "削除" @@ -1987,13 +1989,13 @@ msgstr "ダウンロード" msgid "Rename dir" msgstr "マップディレクトリ" -#: audits/const.py:23 rbac/tree.py:228 +#: audits/const.py:23 rbac/tree.py:229 msgid "View" msgstr "表示" #: audits/const.py:26 #: authentication/templates/authentication/_access_key_modal.html:22 -#: rbac/tree.py:227 +#: rbac/tree.py:228 msgid "Create" msgstr "作成" @@ -2230,23 +2232,29 @@ msgstr "外部ストレージへのFTPファイルのアップロード" msgid "This action require verify your MFA" msgstr "この操作には、MFAを検証する必要があります" -#: authentication/api/connection_token.py:288 +#: authentication/api/connection_token.py:219 +msgid "Reusable connection token is not allowed, global setting not enabled" +msgstr "" +"再使用可能な接続トークンの使用は許可されていません。グローバル設定は有効に" +"なっていません" + +#: authentication/api/connection_token.py:298 msgid "Anonymous account is not supported for this asset" msgstr "匿名アカウントはこのプロパティではサポートされていません" -#: authentication/api/connection_token.py:310 +#: authentication/api/connection_token.py:320 msgid "Account not found" msgstr "アカウントが見つかりません" -#: authentication/api/connection_token.py:313 +#: authentication/api/connection_token.py:323 msgid "Permission expired" msgstr "承認の有効期限が切れています" -#: authentication/api/connection_token.py:327 +#: authentication/api/connection_token.py:337 msgid "ACL action is reject: {}({})" msgstr "ACL アクションは拒否です: {}({})" -#: authentication/api/connection_token.py:331 +#: authentication/api/connection_token.py:341 msgid "ACL action is review" msgstr "ACL アクションはレビューです" @@ -2637,7 +2645,7 @@ msgid "Input username" msgstr "カスタム ユーザー名" #: authentication/models/connection_token.py:40 -#: authentication/serializers/connection_token.py:20 +#: authentication/serializers/connection_token.py:18 msgid "Input secret" msgstr "カスタムパスワード" @@ -2674,31 +2682,39 @@ msgstr "期限切れの日付" msgid "From ticket" msgstr "チケットから" -#: authentication/models/connection_token.py:57 +#: authentication/models/connection_token.py:58 +msgid "Can expire connection token" +msgstr "接続トークンの有効期限を設定できます" + +#: authentication/models/connection_token.py:59 +msgid "Can reuse connection token" +msgstr "接続トークンを再利用できます" + +#: authentication/models/connection_token.py:61 msgid "Connection token" msgstr "接続トークン" -#: authentication/models/connection_token.py:59 -msgid "Can view connection token secret" -msgstr "接続トークンの秘密を表示できます" - -#: authentication/models/connection_token.py:106 +#: authentication/models/connection_token.py:116 msgid "Connection token inactive" msgstr "接続トークンがアクティブ化されていません" -#: authentication/models/connection_token.py:109 +#: authentication/models/connection_token.py:119 msgid "Connection token expired at: {}" msgstr "接続トークンの有効期限: {}" -#: authentication/models/connection_token.py:112 +#: authentication/models/connection_token.py:122 msgid "No user or invalid user" msgstr "ユーザーなしまたは期限切れのユーザー" -#: authentication/models/connection_token.py:115 +#: authentication/models/connection_token.py:125 msgid "No asset or inactive asset" msgstr "アセットがないか、有効化されていないアセット" -#: authentication/models/connection_token.py:258 +#: authentication/models/connection_token.py:269 +msgid "Can view super connection token secret" +msgstr "スーパー接続トークンのシークレットを表示できます" + +#: authentication/models/connection_token.py:271 msgid "Super connection token" msgstr "スーパー接続トークン" @@ -2742,15 +2758,15 @@ msgstr "コンポーネント" msgid "Expired now" msgstr "すぐに期限切れ" -#: authentication/serializers/connection_token.py:18 +#: authentication/serializers/connection_token.py:16 msgid "Expired time" msgstr "期限切れ時間" -#: authentication/serializers/connection_token.py:22 +#: authentication/serializers/connection_token.py:20 msgid "Ticket info" msgstr "作業指示情報" -#: authentication/serializers/connection_token.py:23 +#: authentication/serializers/connection_token.py:21 #: perms/models/asset_permission.py:71 perms/serializers/permission.py:36 #: perms/serializers/permission.py:56 #: tickets/models/ticket/apply_application.py:28 @@ -2758,18 +2774,12 @@ msgstr "作業指示情報" msgid "Actions" msgstr "アクション" -#: authentication/serializers/connection_token.py:44 +#: authentication/serializers/connection_token.py:42 #: perms/serializers/permission.py:38 perms/serializers/permission.py:57 #: users/serializers/user.py:96 users/serializers/user.py:172 msgid "Is expired" msgstr "期限切れです" -#: authentication/serializers/connection_token.py:79 -msgid "Reusable connection token is not allowed, global setting not enabled" -msgstr "" -"再使用可能な接続トークンの使用は許可されていません。グローバル設定は有効に" -"なっていません" - #: authentication/serializers/password_mfa.py:16 #: authentication/serializers/password_mfa.py:24 #: notifications/backends/__init__.py:10 settings/serializers/email.py:19 @@ -3899,7 +3909,7 @@ msgstr "" msgid "The organization have resource ({}) cannot be deleted" msgstr "組織のリソース ({}) は削除できません" -#: orgs/apps.py:7 rbac/tree.py:118 +#: orgs/apps.py:7 rbac/tree.py:119 msgid "App organizations" msgstr "アプリ組織" @@ -4058,27 +4068,27 @@ msgstr "{} 少なくとも1つのシステムロール" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:113 +#: rbac/builtin.py:114 msgid "SystemAdmin" msgstr "システム管理者" -#: rbac/builtin.py:116 +#: rbac/builtin.py:117 msgid "SystemAuditor" msgstr "システム監査人" -#: rbac/builtin.py:119 +#: rbac/builtin.py:120 msgid "SystemComponent" msgstr "システムコンポーネント" -#: rbac/builtin.py:125 +#: rbac/builtin.py:126 msgid "OrgAdmin" msgstr "組織管理者" -#: rbac/builtin.py:128 +#: rbac/builtin.py:129 msgid "OrgAuditor" msgstr "監査員を組織する" -#: rbac/builtin.py:131 +#: rbac/builtin.py:132 msgid "OrgUser" msgstr "組織ユーザー" @@ -4229,19 +4239,19 @@ msgstr "私の資産" msgid "Applet" msgstr "リモートアプリケーション" -#: rbac/tree.py:119 +#: rbac/tree.py:120 msgid "Ticket comment" msgstr "チケットコメント" -#: rbac/tree.py:120 tickets/models/ticket/general.py:307 +#: rbac/tree.py:121 tickets/models/ticket/general.py:307 msgid "Ticket" msgstr "チケット" -#: rbac/tree.py:121 +#: rbac/tree.py:122 msgid "Common setting" msgstr "共通設定" -#: rbac/tree.py:122 +#: rbac/tree.py:123 msgid "View permission tree" msgstr "権限ツリーの表示" @@ -5722,7 +5732,7 @@ msgstr "出力" msgid "Risk level" msgstr "リスクレベル" -#: terminal/connect_methods.py:55 +#: terminal/connect_methods.py:34 msgid "DB Client" msgstr "データベース クライアント" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index f9f875d29..043ff32f6 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d81d525d06bd1446780753e7627adbcc344144a3c0ed856d7953b9758913028 -size 120819 +oid sha256:f5261baf86de7c7c1374041d450b51ead282b6f546738c4caffd6b4d4ea22a00 +size 121562 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index f6b13ebb4..94f3ea94c 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-11 12:03+0800\n" +"POT-Creation-Date: 2023-07-13 15:56+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -86,7 +86,7 @@ msgstr "模板" msgid "Skip" msgstr "跳过" -#: accounts/const/account.py:28 audits/const.py:24 rbac/tree.py:229 +#: accounts/const/account.py:28 audits/const.py:24 rbac/tree.py:230 #: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 msgid "Update" msgstr "更新" @@ -648,7 +648,7 @@ msgstr "ID" #: authentication/models/sso_token.py:16 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 -#: perms/serializers/permission.py:30 rbac/builtin.py:122 +#: perms/serializers/permission.py:30 rbac/builtin.py:123 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:17 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 #: terminal/notifications.py:135 terminal/notifications.py:183 @@ -1016,7 +1016,7 @@ msgid "{} disabled" msgstr "{} 已禁用" #: assets/automations/ping_gateway/manager.py:33 -#: authentication/models/connection_token.py:118 +#: authentication/models/connection_token.py:128 msgid "No account" msgstr "没有账号" @@ -1070,7 +1070,8 @@ msgstr "禁用" msgid "Basic" msgstr "基本" -#: assets/const/base.py:35 assets/models/asset/web.py:13 +#: assets/const/base.py:35 assets/const/protocol.py:193 +#: assets/models/asset/web.py:13 msgid "Script" msgstr "脚本" @@ -1178,23 +1179,28 @@ msgstr "AD 网域" msgid "Use SSL" msgstr "使用 SSL" -#: assets/const/protocol.py:145 +#: assets/const/protocol.py:149 msgid "Auth username" msgstr "使用用户名认证" -#: assets/const/protocol.py:173 assets/models/asset/web.py:10 +#: assets/const/protocol.py:170 assets/models/asset/web.py:9 +#: assets/serializers/asset/info/spec.py:16 +msgid "Autofill" +msgstr "自动代填" + +#: assets/const/protocol.py:178 assets/models/asset/web.py:10 msgid "Username selector" msgstr "用户名选择器" -#: assets/const/protocol.py:178 assets/models/asset/web.py:11 +#: assets/const/protocol.py:183 assets/models/asset/web.py:11 msgid "Password selector" msgstr "密码选择器" -#: assets/const/protocol.py:183 assets/models/asset/web.py:12 +#: assets/const/protocol.py:188 assets/models/asset/web.py:12 msgid "Submit selector" msgstr "确认按钮选择器" -#: assets/const/protocol.py:201 +#: assets/const/protocol.py:211 msgid "API mode" msgstr "API 模式" @@ -1401,10 +1407,6 @@ msgstr "忽略证书校验" msgid "Proxy" msgstr "代理" -#: assets/models/asset/web.py:9 assets/serializers/asset/info/spec.py:16 -msgid "Autofill" -msgstr "自动代填" - #: assets/models/automations/base.py:22 ops/models/job.py:187 #: settings/serializers/auth/sms.py:99 msgid "Parameters" @@ -1947,7 +1949,7 @@ msgstr "删除目录" #: audits/const.py:14 audits/const.py:25 #: authentication/templates/authentication/_access_key_modal.html:65 -#: perms/const.py:17 rbac/tree.py:230 +#: perms/const.py:17 rbac/tree.py:231 msgid "Delete" msgstr "删除" @@ -1971,13 +1973,13 @@ msgstr "下载" msgid "Rename dir" msgstr "映射目录" -#: audits/const.py:23 rbac/tree.py:228 +#: audits/const.py:23 rbac/tree.py:229 msgid "View" msgstr "查看" #: audits/const.py:26 #: authentication/templates/authentication/_access_key_modal.html:22 -#: rbac/tree.py:227 +#: rbac/tree.py:228 msgid "Create" msgstr "创建" @@ -2214,23 +2216,27 @@ msgstr "上传 FTP 文件到外部存储" msgid "This action require verify your MFA" msgstr "该操作需要验证您的 MFA, 请先开启并配置" -#: authentication/api/connection_token.py:288 +#: authentication/api/connection_token.py:219 +msgid "Reusable connection token is not allowed, global setting not enabled" +msgstr "不允许使用可重复使用的连接令牌,未启用全局设置" + +#: authentication/api/connection_token.py:298 msgid "Anonymous account is not supported for this asset" msgstr "匿名账号不支持当前资产" -#: authentication/api/connection_token.py:310 +#: authentication/api/connection_token.py:320 msgid "Account not found" msgstr "账号未找到" -#: authentication/api/connection_token.py:313 +#: authentication/api/connection_token.py:323 msgid "Permission expired" msgstr "授权已过期" -#: authentication/api/connection_token.py:327 +#: authentication/api/connection_token.py:337 msgid "ACL action is reject: {}({})" msgstr "ACL 动作是拒绝: {}({})" -#: authentication/api/connection_token.py:331 +#: authentication/api/connection_token.py:341 msgid "ACL action is review" msgstr "ACL 动作是复核" @@ -2607,7 +2613,7 @@ msgid "Input username" msgstr "自定义用户名" #: authentication/models/connection_token.py:40 -#: authentication/serializers/connection_token.py:20 +#: authentication/serializers/connection_token.py:18 msgid "Input secret" msgstr "自定义密码" @@ -2644,31 +2650,39 @@ msgstr "失效日期" msgid "From ticket" msgstr "来自工单" -#: authentication/models/connection_token.py:57 +#: authentication/models/connection_token.py:58 +msgid "Can expire connection token" +msgstr "可以失效连接令牌" + +#: authentication/models/connection_token.py:59 +msgid "Can reuse connection token" +msgstr "可以复用连接令牌" + +#: authentication/models/connection_token.py:61 msgid "Connection token" msgstr "连接令牌" -#: authentication/models/connection_token.py:59 -msgid "Can view connection token secret" -msgstr "可以查看连接令牌密文" - -#: authentication/models/connection_token.py:106 +#: authentication/models/connection_token.py:116 msgid "Connection token inactive" msgstr "连接令牌未激活" -#: authentication/models/connection_token.py:109 +#: authentication/models/connection_token.py:119 msgid "Connection token expired at: {}" msgstr "连接令牌过期: {}" -#: authentication/models/connection_token.py:112 +#: authentication/models/connection_token.py:122 msgid "No user or invalid user" msgstr "没有用户或用户失效" -#: authentication/models/connection_token.py:115 +#: authentication/models/connection_token.py:125 msgid "No asset or inactive asset" msgstr "没有资产或资产未激活" -#: authentication/models/connection_token.py:258 +#: authentication/models/connection_token.py:269 +msgid "Can view super connection token secret" +msgstr "可以查看超级连接令牌密文" + +#: authentication/models/connection_token.py:271 msgid "Super connection token" msgstr "超级连接令牌" @@ -2712,15 +2726,15 @@ msgstr "组件" msgid "Expired now" msgstr "立刻过期" -#: authentication/serializers/connection_token.py:18 +#: authentication/serializers/connection_token.py:16 msgid "Expired time" msgstr "过期时间" -#: authentication/serializers/connection_token.py:22 +#: authentication/serializers/connection_token.py:20 msgid "Ticket info" msgstr "工单信息" -#: authentication/serializers/connection_token.py:23 +#: authentication/serializers/connection_token.py:21 #: perms/models/asset_permission.py:71 perms/serializers/permission.py:36 #: perms/serializers/permission.py:56 #: tickets/models/ticket/apply_application.py:28 @@ -2728,16 +2742,12 @@ msgstr "工单信息" msgid "Actions" msgstr "动作" -#: authentication/serializers/connection_token.py:44 +#: authentication/serializers/connection_token.py:42 #: perms/serializers/permission.py:38 perms/serializers/permission.py:57 #: users/serializers/user.py:96 users/serializers/user.py:172 msgid "Is expired" msgstr "已过期" -#: authentication/serializers/connection_token.py:79 -msgid "Reusable connection token is not allowed, global setting not enabled" -msgstr "不允许使用可重复使用的连接令牌,未启用全局设置" - #: authentication/serializers/password_mfa.py:16 #: authentication/serializers/password_mfa.py:24 #: notifications/backends/__init__.py:10 settings/serializers/email.py:19 @@ -3851,7 +3861,7 @@ msgstr "LDAP 同步设置组织为当前组织,请切换其他组织后再进 msgid "The organization have resource ({}) cannot be deleted" msgstr "组织存在资源 ({}) 不能被删除" -#: orgs/apps.py:7 rbac/tree.py:118 +#: orgs/apps.py:7 rbac/tree.py:119 msgid "App organizations" msgstr "组织管理" @@ -4010,27 +4020,27 @@ msgstr "{} 至少有一个系统角色" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:113 +#: rbac/builtin.py:114 msgid "SystemAdmin" msgstr "系统管理员" -#: rbac/builtin.py:116 +#: rbac/builtin.py:117 msgid "SystemAuditor" msgstr "系统审计员" -#: rbac/builtin.py:119 +#: rbac/builtin.py:120 msgid "SystemComponent" msgstr "系统组件" -#: rbac/builtin.py:125 +#: rbac/builtin.py:126 msgid "OrgAdmin" msgstr "组织管理员" -#: rbac/builtin.py:128 +#: rbac/builtin.py:129 msgid "OrgAuditor" msgstr "组织审计员" -#: rbac/builtin.py:131 +#: rbac/builtin.py:132 msgid "OrgUser" msgstr "组织用户" @@ -4180,19 +4190,19 @@ msgstr "我的资产" msgid "Applet" msgstr "远程应用" -#: rbac/tree.py:119 +#: rbac/tree.py:120 msgid "Ticket comment" msgstr "工单评论" -#: rbac/tree.py:120 tickets/models/ticket/general.py:307 +#: rbac/tree.py:121 tickets/models/ticket/general.py:307 msgid "Ticket" msgstr "工单管理" -#: rbac/tree.py:121 +#: rbac/tree.py:122 msgid "Common setting" msgstr "一般设置" -#: rbac/tree.py:122 +#: rbac/tree.py:123 msgid "View permission tree" msgstr "查看授权树" @@ -5635,7 +5645,7 @@ msgstr "输出" msgid "Risk level" msgstr "风险等级" -#: terminal/connect_methods.py:55 +#: terminal/connect_methods.py:34 msgid "DB Client" msgstr "数据库客户端" diff --git a/apps/rbac/builtin.py b/apps/rbac/builtin.py index f2dd13dae..508883446 100644 --- a/apps/rbac/builtin.py +++ b/apps/rbac/builtin.py @@ -26,11 +26,12 @@ user_perms = ( ) system_user_perms = ( - ('authentication', 'connectiontoken', 'add,change,view', 'connectiontoken'), - ('authentication', 'temptoken', 'add,change,view', 'temptoken'), - ('authentication', 'accesskey', '*', '*'), - ('tickets', 'ticket', 'view', 'ticket'), - ) + user_perms + _view_all_joined_org_perms + ('authentication', 'connectiontoken', 'add,view,reuse,expire', 'connectiontoken'), + ('authentication', 'temptoken', 'add,change,view', 'temptoken'), + ('authentication', 'accesskey', '*', '*'), + ('tickets', 'ticket', 'view', 'ticket'), +) +system_user_perms += (user_perms + _view_all_joined_org_perms) _auditor_perms = ( ('rbac', 'menupermission', 'view', 'audit'), diff --git a/apps/rbac/const.py b/apps/rbac/const.py index 91ca727eb..cd7fd642a 100644 --- a/apps/rbac/const.py +++ b/apps/rbac/const.py @@ -22,7 +22,8 @@ exclude_permissions = ( ('common', 'setting', '*', '*'), ('authentication', 'privatetoken', '*', '*'), - ('authentication', 'connectiontoken', 'delete', 'connectiontoken'), + ('authentication', 'connectiontoken', 'delete,change', 'connectiontoken'), + ('authentication', 'connectiontoken', 'view', 'connectiontokensecret'), ('authentication', 'ssotoken', '*', '*'), ('authentication', 'superconnectiontoken', 'change,delete', 'superconnectiontoken'), ('authentication', 'temptoken', 'delete', 'temptoken'), diff --git a/apps/rbac/tree.py b/apps/rbac/tree.py index 1c9673162..a586208b6 100644 --- a/apps/rbac/tree.py +++ b/apps/rbac/tree.py @@ -65,6 +65,7 @@ special_pid_mapper = { 'acls.commandgroup': 'perms', 'acls.loginacl': 'perms', 'acls.loginassetacl': 'perms', + 'acls.connectmethodacl': 'perms', 'xpack.account': 'cloud_import', 'xpack.syncinstancedetail': 'cloud_import', 'xpack.syncinstancetask': 'cloud_import', @@ -390,7 +391,7 @@ class PermissionTreeUtil: 'chkDisabled': self.check_disabled, 'checked': checked, 'meta': { - 'type': tp, + 'type': tp, }, **data } diff --git a/apps/terminal/migrations/0050_auto_20220606_1745.py b/apps/terminal/migrations/0050_auto_20220606_1745.py index a47defba9..05e15f866 100644 --- a/apps/terminal/migrations/0050_auto_20220606_1745.py +++ b/apps/terminal/migrations/0050_auto_20220606_1745.py @@ -15,7 +15,7 @@ class Migration(migrations.Migration): field=models.CharField( choices=[('koko', 'KoKo'), ('guacamole', 'Guacamole'), ('omnidb', 'OmniDB'), ('xrdp', 'Xrdp'), ('lion', 'Lion'), ('core', 'Core'), ('celery', 'Celery'), ('magnus', 'Magnus'), - ('razor', 'Razor'), ('tinker', 'Tinker'), ('video_worker', 'Video Worker'), ('chen', 'Chen')], - default='koko', max_length=64, verbose_name='type'), + ('razor', 'Razor'), ('tinker', 'Tinker'), ('video_worker', 'Video Worker'), ('chen', 'Chen'), + ('kael', 'Kael')], default='koko', max_length=64, verbose_name='type'), ), ] From d95e7c2e24c034b36e04861ec36ee2f3247d753c Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 13 Jul 2023 20:01:06 +0800 Subject: [PATCH 117/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20chrome=20?= =?UTF-8?q?=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../disable_new_tab_window_menu/background.js | 63 ++++++++++++++----- .../content_script.js | 33 +++------- 2 files changed, 56 insertions(+), 40 deletions(-) diff --git a/apps/terminal/applets/chrome/extensions/disable_new_tab_window_menu/background.js b/apps/terminal/applets/chrome/extensions/disable_new_tab_window_menu/background.js index 57b0cca1a..7f2556ab8 100644 --- a/apps/terminal/applets/chrome/extensions/disable_new_tab_window_menu/background.js +++ b/apps/terminal/applets/chrome/extensions/disable_new_tab_window_menu/background.js @@ -1,23 +1,54 @@ // background.js +const tabs = [] +const debug = console.log + // 监听标签页的创建事件 chrome.tabs.onCreated.addListener(function (tab) { // 获取当前窗口的所有标签页 - chrome.tabs.query({currentWindow: true}, function (tabs) { - // 如果当前窗口的标签页数量大于1,则关闭新创建的标签页 - if (tabs.length > 1) { - chrome.tabs.remove(tab.id); - } - }); + debug('New tab add, tabs : ', tabs) + tabs.push(tab) }); -// 监听窗口的创建事件 -chrome.windows.onCreated.addListener(function (window) { -// 获取当前所有窗口 - chrome.windows.getAll(function (windows) { - // 如果当前窗口数量大于1,则关闭新创建的窗口 - if (windows.length > 1) { - chrome.windows.remove(window.id); - } - }); -}); +chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) { + debug('Tab changed xx: ', tabId, changeInfo, tab) + if (changeInfo.status !== 'loading') { + return + } + const tabFind = tabs.findIndex(t => t.id === tabId) + if (tabFind === -1) { + debug('Tab not found: ', tabId, tabs) + return + } + Object.assign(tabs[tabFind], tab) + + const blockUrls = ['chrome://newtab/'] + if (!tab.url || blockUrls.includes(tab.url) || tab.url.startsWith('chrome://')) { + debug('Blocked url, destroy: ', tab.url) + chrome.tabs.remove(tabId); + return + } + + // 第一个 tab 不做限制 + // 修改初始 tab 的状态,因为第一个 tab 没有地址栏,可以允许它自由跳转 + if (tabs.length === 1) { + debug('First tab, pass') + return + } + + const firstUrl = tabs[0].url + const curUrl = tab.url + if (!firstUrl.startsWith('http') || !curUrl.startsWith('http')) { + debug('First tab url empty, or current empty, pass ', firstUrl, curUrl) + return + } + + const firstTabHost = new URL(firstUrl).host + const curHost = new URL(curUrl).host + const firstDomain = firstTabHost.split('.').slice(-2).join('.') + const curDomain = curHost.split('.').slice(-2).join('.') + if (firstDomain !== curDomain) { + debug('Not same domain, destroy: ', firstTabHost, ' current: ', curHost) + chrome.tabs.remove(tabId); + } +}) diff --git a/apps/terminal/applets/chrome/extensions/disable_new_tab_window_menu/content_script.js b/apps/terminal/applets/chrome/extensions/disable_new_tab_window_menu/content_script.js index 0b6162430..3b2ba828c 100644 --- a/apps/terminal/applets/chrome/extensions/disable_new_tab_window_menu/content_script.js +++ b/apps/terminal/applets/chrome/extensions/disable_new_tab_window_menu/content_script.js @@ -1,5 +1,7 @@ // content_script.js +const debug = console.log + // 创建一个 Mutation Observer 实例 const observer = new MutationObserver(function (mutationsList) { // 遍历每个发生变化的 mutation @@ -10,7 +12,7 @@ const observer = new MutationObserver(function (mutationsList) { const links = document.getElementsByTagName('a'); // 遍历 标签元素并修改链接属性 - console.log("开始替换标签") + debug("开始替换标签") for (let i = 0; i < links.length; i++) { links[i].target = '_self'; // 将 target 属性设置为 _self,当前窗口打开 } @@ -27,43 +29,26 @@ const observer = new MutationObserver(function (mutationsList) { // 开始观察 document.body 的子节点变化 observer.observe(document.body, {childList: true, subtree: true}); -chrome.runtime.onMessage.addListener( - function (request, sender, sendResponse) { - console.log(request.url); - $("iframe").attr("src", request.url); - sendResponse({farewell: "goodbye"}); - } -) - document.addEventListener("contextmenu", function (event) { - console.log('On context') + debug('On context') event.preventDefault(); }); -var AllowedKeys = ['P', 'F', 'C', 'V'] +const AllowedKeys = ['P', 'F', 'C', 'V'] window.addEventListener("keydown", function (e) { if (e.key === "F12" || (e.ctrlKey && !AllowedKeys.includes(e.key.toUpperCase()))) { e.preventDefault(); e.stopPropagation(); - console.log('Press key: ', e.ctrlKey ? 'Ctrl' : '', e.shiftKey ? ' Shift' : '', e.key) + debug('Press key: ', e.ctrlKey ? 'Ctrl' : '', e.shiftKey ? ' Shift' : '', e.key) } }, true); -// 保存原始的 window.open 函数引用 -var originalOpen = window.open; - // 修改 window.open 函数 window.open = function (url, target, features) { // 将 target 强制设置为 "_self",使得新页面在当前标签页中打开 target = "_self"; - - // 修改当前页面的 URL - location.href = url; - + debug('Open url: ', url, target, features) // 调用原始的 window.open 函数 - return originalOpen.call(this, url, target, features); + window.href = url + // return originalOpen.call(this, url, target, features); }; - - -chrome.runtime.sendMessage({greeting: "hello"}, function (response) { -}); From 9b5803f2a2ba61a11a9df5b31398bea2c9ab3846 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 13 Jul 2023 20:02:28 +0800 Subject: [PATCH 118/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/applets/chrome/manifest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/terminal/applets/chrome/manifest.yml b/apps/terminal/applets/chrome/manifest.yml index 0fd511f58..066530eef 100644 --- a/apps/terminal/applets/chrome/manifest.yml +++ b/apps/terminal/applets/chrome/manifest.yml @@ -1,6 +1,6 @@ name: chrome display_name: "{{ 'Chrome Browser' | trans }}" -version: 0.5 +version: 0.6 comment: "{{ 'Chrome Browser Open URL Page Address' | trans }}" author: JumpServer Team exec_type: python From f504413d7f9960f1b9e330412a75fd73ac73d453 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 14 Jul 2023 16:54:42 +0800 Subject: [PATCH 119/167] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0logo=20api=20?= =?UTF-8?q?(#10965)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/jumpserver/api.py | 2 +- apps/settings/api/settings.py | 19 +++++++++++++++++++ apps/settings/urls/api_urls.py | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/apps/jumpserver/api.py b/apps/jumpserver/api.py index 10b0afa55..3b72841f9 100644 --- a/apps/jumpserver/api.py +++ b/apps/jumpserver/api.py @@ -19,10 +19,10 @@ from common.utils.timezone import local_now, local_zero_hour from ops.const import JobStatus from orgs.caches import OrgResourceStatisticsCache from orgs.utils import current_org +from terminal.const import RiskLevelChoices from terminal.models import Session, Command from terminal.utils import ComponentsPrometheusMetricsUtil from users.models import User -from terminal.const import RiskLevelChoices __all__ = ['IndexApi'] diff --git a/apps/settings/api/settings.py b/apps/settings/api/settings.py index 6cc2743e2..f3893b9e6 100644 --- a/apps/settings/api/settings.py +++ b/apps/settings/api/settings.py @@ -3,6 +3,8 @@ from django.conf import settings from rest_framework import generics +from rest_framework.permissions import AllowAny +from rest_framework.views import APIView from common.utils import get_logger from jumpserver.conf import Config @@ -10,6 +12,7 @@ from rbac.permissions import RBACPermission from .. import serializers from ..models import Setting from ..signals import category_setting_updated +from ..utils import get_interface_setting_or_default logger = get_logger(__file__) @@ -139,3 +142,19 @@ class SettingsApi(generics.RetrieveUpdateAPIView): if hasattr(serializer, 'post_save'): serializer.post_save() self.send_signal(serializer) + + +class SettingsLogoApi(APIView): + permission_classes = (AllowAny,) + + def get(self, request, *args, **kwargs): + from django.views.static import serve + size = request.GET.get('size', 'small') + interface_data = get_interface_setting_or_default() + if size == 'small': + logo_path = interface_data['logo_logout'] + else: + logo_path = interface_data['logo_index'] + + logo_path = logo_path.replace('/static/', '/') + return serve(request, logo_path, document_root=settings.STATIC_ROOT) diff --git a/apps/settings/urls/api_urls.py b/apps/settings/urls/api_urls.py index ba04f2a4b..5cfc3bb36 100644 --- a/apps/settings/urls/api_urls.py +++ b/apps/settings/urls/api_urls.py @@ -20,6 +20,7 @@ urlpatterns = [ path('sms/backend/', api.SMSBackendAPI.as_view(), name='sms-backend'), path('setting/', api.SettingsApi.as_view(), name='settings-setting'), + path('logo/', api.SettingsLogoApi.as_view(), name='settings-logo'), path('public/', api.PublicSettingApi.as_view(), name='public-setting'), path('public/open/', api.OpenPublicSettingApi.as_view(), name='open-public-setting'), ] From 4da0fadcc40d0057a8ee5b3d6b0024fc0e4ee8cc Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 14 Jul 2023 19:18:13 +0800 Subject: [PATCH 120/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Ansible=20?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E8=B5=84=E4=BA=A7=E5=8F=AF=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E6=80=A7=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98(Connecti?= =?UTF-8?q?on=20to=20UNKNOWN=20port=2065535=20timed=20out)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/ansible/ansible.cfg | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/ops/ansible/ansible.cfg b/apps/ops/ansible/ansible.cfg index c51b2d733..8e0d9918e 100644 --- a/apps/ops/ansible/ansible.cfg +++ b/apps/ops/ansible/ansible.cfg @@ -1,7 +1,8 @@ [defaults] -forks = 10 +forks = 10 host_key_checking = False -library = /opt/jumpserver/apps/ops/ansible/modules:./modules +library = /opt/jumpserver/apps/ops/ansible/modules:./modules +timeout = 65 [inventory] [privilege_escalation] [paramiko_connection] From 8f6b8b5a117109bfc7642b17bc8e29427787bb70 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 14 Jul 2023 23:01:48 +0800 Subject: [PATCH 121/167] perf: settings logo (#10971) Co-authored-by: feng <1304903146@qq.com> --- apps/settings/api/settings.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/settings/api/settings.py b/apps/settings/api/settings.py index f3893b9e6..4bcef2889 100644 --- a/apps/settings/api/settings.py +++ b/apps/settings/api/settings.py @@ -2,7 +2,10 @@ # from django.conf import settings +from django.http import HttpResponse +from django.views.static import serve from rest_framework import generics +from rest_framework import status from rest_framework.permissions import AllowAny from rest_framework.views import APIView @@ -148,7 +151,6 @@ class SettingsLogoApi(APIView): permission_classes = (AllowAny,) def get(self, request, *args, **kwargs): - from django.views.static import serve size = request.GET.get('size', 'small') interface_data = get_interface_setting_or_default() if size == 'small': @@ -156,5 +158,12 @@ class SettingsLogoApi(APIView): else: logo_path = interface_data['logo_index'] - logo_path = logo_path.replace('/static/', '/') - return serve(request, logo_path, document_root=settings.STATIC_ROOT) + if logo_path.startswith('/media/'): + logo_path = logo_path.replace('/media/', '') + document_root = settings.MEDIA_ROOT + elif logo_path.startswith('/static/'): + logo_path = logo_path.replace('/static/', '/') + document_root = settings.STATIC_ROOT + else: + return HttpResponse(status=status.HTTP_404_NOT_FOUND) + return serve(request, logo_path, document_root=document_root) From 0f1d9bc3eb39fc5e1c155daa90adb9fe91ed8424 Mon Sep 17 00:00:00 2001 From: halo Date: Sat, 15 Jul 2023 16:30:45 +0800 Subject: [PATCH 122/167] =?UTF-8?q?fix:=20=E5=BF=98=E8=AE=B0=E5=AF=86?= =?UTF-8?q?=E7=A0=81token=E5=A4=B1=E6=95=88=E5=8F=91=E9=80=81=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E7=A0=81=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/password.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/authentication/api/password.py b/apps/authentication/api/password.py index da3e86510..53f47c03c 100644 --- a/apps/authentication/api/password.py +++ b/apps/authentication/api/password.py @@ -1,3 +1,4 @@ +from django.http import HttpResponseRedirect from rest_framework.generics import CreateAPIView from rest_framework.response import Response from rest_framework.permissions import AllowAny @@ -41,7 +42,7 @@ class UserResetPasswordSendCodeApi(CreateAPIView): token = request.GET.get('token') userinfo = cache.get(token) if not userinfo: - return reverse('authentication:forgot-previewing') + return HttpResponseRedirect(reverse('authentication:forgot-previewing')) serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) From 8a89ee7ac0defcee0071c05735a7102a5768db01 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 17 Jul 2023 13:53:27 +0800 Subject: [PATCH 123/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E5=88=9B=E5=BB=BA=E6=97=B6=EF=BC=8C=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=20setting=20=E5=BF=85=E5=A1=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/serializers/platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/serializers/platform.py b/apps/assets/serializers/platform.py index 8101bde23..12de700a9 100644 --- a/apps/assets/serializers/platform.py +++ b/apps/assets/serializers/platform.py @@ -74,7 +74,7 @@ class PlatformProtocolSerializer(serializers.ModelSerializer): def get_setting_serializer(self): request = self.context.get('request') - default_field = DictSerializer() + default_field = DictSerializer(required=False) if not request: return default_field From 819853eae469fea3130796ae9db7a4b29fae1df4 Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 17 Jul 2023 13:59:45 +0800 Subject: [PATCH 124/167] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20DEBUG=5FAN?= =?UTF-8?q?SIBLE=20=E9=85=8D=E7=BD=AE=E9=A1=B9=E6=94=AF=E6=8C=81=E6=89=93?= =?UTF-8?q?=E5=8D=B0=20Ansible=20=E8=AF=A6=E7=BB=86=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/conf.py | 1 + apps/jumpserver/settings/base.py | 2 ++ apps/ops/ansible/runner.py | 7 +++---- apps/ops/utils.py | 17 ++++++++++------- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 902f96df7..8990a4223 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -186,6 +186,7 @@ class Config(dict): 'BOOTSTRAP_TOKEN': '', 'DEBUG': False, 'DEBUG_DEV': False, + 'DEBUG_ANSIBLE': False, 'LOG_LEVEL': 'DEBUG', 'LOG_DIR': os.path.join(PROJECT_DIR, 'data', 'logs'), 'DB_ENGINE': 'mysql', diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index 7477f3f83..2bc547e57 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -53,6 +53,8 @@ BOOTSTRAP_TOKEN = CONFIG.BOOTSTRAP_TOKEN DEBUG = CONFIG.DEBUG # SECURITY WARNING: If you run with debug turned on, more debug msg with be log DEBUG_DEV = CONFIG.DEBUG_DEV +# SECURITY WARNING: If you run ansible task with debug turned on, more debug msg with be log +DEBUG_ANSIBLE = CONFIG.DEBUG_ANSIBLE # Absolute url for some case, for example email link SITE_URL = CONFIG.SITE_URL diff --git a/apps/ops/ansible/runner.py b/apps/ops/ansible/runner.py index 03aec1787..4610ddfd2 100644 --- a/apps/ops/ansible/runner.py +++ b/apps/ops/ansible/runner.py @@ -5,6 +5,7 @@ import ansible_runner from django.conf import settings from .callback import DefaultCallback +from ..utils import get_ansible_log_verbosity class CommandInBlackListException(Exception): @@ -37,8 +38,7 @@ class AdHocRunner: def run(self, verbosity=0, **kwargs): self.check_module() - if verbosity is None and settings.DEBUG: - verbosity = 1 + verbosity = get_ansible_log_verbosity(verbosity) if not os.path.exists(self.project_dir): os.mkdir(self.project_dir, 0o755) @@ -70,8 +70,7 @@ class PlaybookRunner: self.cb = callback def run(self, verbosity=0, **kwargs): - if verbosity is None and settings.DEBUG: - verbosity = 1 + verbosity = get_ansible_log_verbosity(verbosity) ansible_runner.run( private_data_dir=self.project_dir, diff --git a/apps/ops/utils.py b/apps/ops/utils.py index c2fb7e643..539d6b66c 100644 --- a/apps/ops/utils.py +++ b/apps/ops/utils.py @@ -1,16 +1,11 @@ # ~*~ coding: utf-8 ~*~ import os import uuid +from django.conf import settings -from django.utils.translation import ugettext_lazy as _ - -from common.utils import get_logger, get_object_or_none, make_dirs -from orgs.utils import org_aware_func +from common.utils import get_logger, make_dirs from jumpserver.const import PROJECT_DIR -from .models import AdHoc, CeleryTask -from .const import DEFAULT_PASSWORD_RULES - logger = get_logger(__file__) @@ -26,3 +21,11 @@ def get_task_log_path(base_path, task_id, level=2): make_dirs(os.path.dirname(path), exist_ok=True) return path + +def get_ansible_log_verbosity(verbosity=0): + if settings.DEBUG_ANSIBLE: + return 10 + if verbosity is None and settings.DEBUG: + return 1 + return verbosity + From 7b9c4b300d35598f9c3fce2657cda53c190cb9a6 Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 17 Jul 2023 15:53:35 +0800 Subject: [PATCH 125/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=20ACL=20Action=20Choices=20=E7=9A=84=E9=80=89?= =?UTF-8?q?=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/acls/const.py | 9 ++++++ apps/acls/models/__init__.py | 1 - apps/acls/models/base.py | 9 +----- apps/acls/serializers/base.py | 40 ++++++++++++++----------- apps/acls/serializers/command_acl.py | 2 ++ apps/acls/serializers/connect_method.py | 13 +++----- apps/acls/serializers/login_acl.py | 8 ++--- 7 files changed, 42 insertions(+), 40 deletions(-) create mode 100644 apps/acls/const.py diff --git a/apps/acls/const.py b/apps/acls/const.py new file mode 100644 index 000000000..c2d2be586 --- /dev/null +++ b/apps/acls/const.py @@ -0,0 +1,9 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +class ActionChoices(models.TextChoices): + reject = 'reject', _('Reject') + accept = 'accept', _('Accept') + review = 'review', _('Review') + warning = 'warning', _('Warning') diff --git a/apps/acls/models/__init__.py b/apps/acls/models/__init__.py index 0a4cc2a6e..28fe366b3 100644 --- a/apps/acls/models/__init__.py +++ b/apps/acls/models/__init__.py @@ -2,4 +2,3 @@ from .command_acl import * from .connect_method import * from .login_acl import * from .login_asset_acl import * -from .base import ActionChoices diff --git a/apps/acls/models/base.py b/apps/acls/models/base.py index c84ea3fcf..74782b2a3 100644 --- a/apps/acls/models/base.py +++ b/apps/acls/models/base.py @@ -7,23 +7,16 @@ from common.db.models import JMSBaseModel from common.utils import contains_ip from common.utils.time_period import contains_time_period from orgs.mixins.models import OrgModelMixin, OrgManager +from ..const import ActionChoices __all__ = [ 'BaseACL', 'UserBaseACL', 'UserAssetAccountBaseACL', - 'ActionChoices', ] from orgs.utils import tmp_to_root_org from orgs.utils import tmp_to_org -class ActionChoices(models.TextChoices): - reject = 'reject', _('Reject') - accept = 'accept', _('Accept') - review = 'review', _('Review') - warning = 'warning', _('Warning') - - class BaseACLQuerySet(models.QuerySet): def active(self): return self.filter(is_active=True) diff --git a/apps/acls/serializers/base.py b/apps/acls/serializers/base.py index 3892553d9..94c4d9fa1 100644 --- a/apps/acls/serializers/base.py +++ b/apps/acls/serializers/base.py @@ -1,10 +1,11 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers -from acls.models.base import ActionChoices, BaseACL +from acls.models.base import BaseACL from common.serializers.fields import JSONManyToManyField, LabeledChoiceField from jumpserver.utils import has_valid_xpack_license from orgs.models import Organization +from ..const import ActionChoices common_help_text = _( "With * indicating a match all. " @@ -60,18 +61,21 @@ class ActionAclSerializer(serializers.Serializer): super().__init__(*args, **kwargs) self.set_action_choices() - def set_action_choices(self): - action = self.fields.get("action") - if not action: - return - choices = action.choices - if not has_valid_xpack_license(): - choices.pop(ActionChoices.review, None) - action._choices = choices - - -class BaserACLSerializer(ActionAclSerializer, serializers.Serializer): class Meta: + action_choices_exclude = [ActionChoices.warning] + + def set_action_choices(self): + field_action = self.fields.get("action") + if not field_action: + return + if not has_valid_xpack_license(): + field_action._choices.pop(ActionChoices.review, None) + for choice in self.Meta.action_choices_exclude: + field_action._choices.pop(choice, None) + + +class BaseACLSerializer(ActionAclSerializer, serializers.Serializer): + class Meta(ActionAclSerializer.Meta): model = BaseACL fields_mini = ["id", "name"] fields_small = fields_mini + [ @@ -108,16 +112,16 @@ class BaserACLSerializer(ActionAclSerializer, serializers.Serializer): return valid_reviewers -class BaserUserACLSerializer(BaserACLSerializer): +class BaseUserACLSerializer(BaseACLSerializer): users = JSONManyToManyField(label=_('User')) - class Meta(BaserACLSerializer.Meta): - fields = BaserACLSerializer.Meta.fields + ['users'] + class Meta(BaseACLSerializer.Meta): + fields = BaseACLSerializer.Meta.fields + ['users'] -class BaseUserAssetAccountACLSerializer(BaserUserACLSerializer): +class BaseUserAssetAccountACLSerializer(BaseUserACLSerializer): assets = JSONManyToManyField(label=_('Asset')) accounts = serializers.ListField(label=_('Account')) - class Meta(BaserUserACLSerializer.Meta): - fields = BaserUserACLSerializer.Meta.fields + ['assets', 'accounts'] + class Meta(BaseUserACLSerializer.Meta): + fields = BaseUserACLSerializer.Meta.fields + ['assets', 'accounts'] diff --git a/apps/acls/serializers/command_acl.py b/apps/acls/serializers/command_acl.py index a34ea4cc4..672164012 100644 --- a/apps/acls/serializers/command_acl.py +++ b/apps/acls/serializers/command_acl.py @@ -31,6 +31,8 @@ class CommandFilterACLSerializer(BaseSerializer, BulkOrgResourceModelSerializer) class Meta(BaseSerializer.Meta): model = CommandFilterACL fields = BaseSerializer.Meta.fields + ['command_groups'] + # 默认都支持所有的 actions + action_choices_exclude = [] class CommandReviewSerializer(serializers.Serializer): diff --git a/apps/acls/serializers/connect_method.py b/apps/acls/serializers/connect_method.py index b36fde06d..b1daf56ac 100644 --- a/apps/acls/serializers/connect_method.py +++ b/apps/acls/serializers/connect_method.py @@ -1,6 +1,7 @@ from orgs.mixins.serializers import BulkOrgResourceModelSerializer from .base import BaseUserAssetAccountACLSerializer as BaseSerializer from ..models import ConnectMethodACL +from ..const import ActionChoices __all__ = ["ConnectMethodACLSerializer"] @@ -12,12 +13,6 @@ class ConnectMethodACLSerializer(BaseSerializer, BulkOrgResourceModelSerializer) i for i in BaseSerializer.Meta.fields + ['connect_methods'] if i not in ['assets', 'accounts'] ] - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - field_action = self.fields.get('action') - if not field_action: - return - # 仅支持拒绝 - for k in ['review', 'accept']: - field_action._choices.pop(k, None) + action_choices_exclude = BaseSerializer.Meta.action_choices_exclude + [ + ActionChoices.review, ActionChoices.accept + ] diff --git a/apps/acls/serializers/login_acl.py b/apps/acls/serializers/login_acl.py index 1371bc091..c86424986 100644 --- a/apps/acls/serializers/login_acl.py +++ b/apps/acls/serializers/login_acl.py @@ -2,7 +2,7 @@ from django.utils.translation import ugettext as _ from common.serializers import MethodSerializer from orgs.mixins.serializers import BulkOrgResourceModelSerializer -from .base import BaserUserACLSerializer +from .base import BaseUserACLSerializer from .rules import RuleSerializer from ..models import LoginACL @@ -11,12 +11,12 @@ __all__ = ["LoginACLSerializer"] common_help_text = _("With * indicating a match all. ") -class LoginACLSerializer(BaserUserACLSerializer, BulkOrgResourceModelSerializer): +class LoginACLSerializer(BaseUserACLSerializer, BulkOrgResourceModelSerializer): rules = MethodSerializer(label=_('Rule')) - class Meta(BaserUserACLSerializer.Meta): + class Meta(BaseUserACLSerializer.Meta): model = LoginACL - fields = BaserUserACLSerializer.Meta.fields + ['rules', ] + fields = BaseUserACLSerializer.Meta.fields + ['rules', ] def get_rules_serializer(self): return RuleSerializer() From daef154622542aa3efbbdc8707e4168f495a3766 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 17 Jul 2023 14:32:34 +0800 Subject: [PATCH 126/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20host=20api?= =?UTF-8?q?=20=E5=92=8C=20gunicorn=20=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset/asset.py | 6 +++++- .../management/commands/services/services/gunicorn.py | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index affd28f03..f1573629e 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -122,8 +122,12 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet): ] def get_queryset(self): - return super().get_queryset().prefetch_related('nodes', 'protocols')\ + queryset = super().get_queryset() \ + .prefetch_related('nodes', 'protocols') \ .select_related('platform', 'domain') + if queryset.model is not Asset: + queryset = queryset.select_related('asset_ptr') + return queryset def get_serializer_class(self): cls = super().get_serializer_class() diff --git a/apps/common/management/commands/services/services/gunicorn.py b/apps/common/management/commands/services/services/gunicorn.py index 5eab30ec3..bd14284af 100644 --- a/apps/common/management/commands/services/services/gunicorn.py +++ b/apps/common/management/commands/services/services/gunicorn.py @@ -1,5 +1,5 @@ -from ..hands import * from .base import BaseService +from ..hands import * __all__ = ['GunicornService'] @@ -22,7 +22,7 @@ class GunicornService(BaseService): '-b', bind, '-k', 'uvicorn.workers.UvicornWorker', '-w', str(self.worker), - '--max-requests', '4096', + '--max-requests', '40960', '--access-logformat', log_format, '--access-logfile', '-' ] From 22588c52a92ec8fa8142fe30da8edb7e270a58a8 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 17 Jul 2023 15:05:20 +0800 Subject: [PATCH 127/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20json=20fiel?= =?UTF-8?q?d=20value=20=E5=8F=AF=E8=83=BD=E4=B8=BA=20None=20=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/db/fields.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/common/db/fields.py b/apps/common/db/fields.py index d1695c19d..aff54c75a 100644 --- a/apps/common/db/fields.py +++ b/apps/common/db/fields.py @@ -459,7 +459,7 @@ class JSONManyToManyDescriptor: custom_q = Q() for rule in attr_rules: - value = getattr(obj, rule['name'], '') + value = getattr(obj, rule['name'], None) or '' rule_value = rule.get('value', '') rule_match = rule.get('match', 'exact') @@ -474,7 +474,7 @@ class JSONManyToManyDescriptor: elif rule_match == 'exact': res &= value == rule_value or rule_value == '*' elif rule_match == 'contains': - res &= rule_value in value + res &= (rule_value in value) elif rule_match == 'startswith': res &= str(value).startswith(str(rule_value)) elif rule_match == 'endswith': From c39041fe7bc3c2072fac47f83df9cb9eb31caee3 Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Mon, 17 Jul 2023 17:55:05 +0800 Subject: [PATCH 128/167] =?UTF-8?q?feat:=20mariadb=20=E6=94=AF=E6=8C=81=20?= =?UTF-8?q?webdb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/connect_methods.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index cc04da982..f6870344d 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -164,6 +164,7 @@ class ConnectMethodUtil: 'support': [ Protocol.mysql, Protocol.postgresql, Protocol.oracle, Protocol.sqlserver, + Protocol.mariadb ], 'match': 'm2m' }, From 0771b804d11b59a2a26428cd156c55c68c59cea8 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 17 Jul 2023 20:52:54 +0800 Subject: [PATCH 129/167] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E5=8D=B1?= =?UTF-8?q?=E9=99=A9=E5=91=BD=E4=BB=A4=E5=91=8A=E8=AD=A6=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?:=20Warning=20(#10970)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 重构危险命令告警类型: Warning * Update _msg_command_warning.html * Update _msg_command_warning.html * Update command.py * Update django.po * perf: 优化 command acl warning 的代码逻辑 * perf: 优化 command acl warning 的代码逻辑 * perf: 优化 CommandWarningMessage 逻辑 --------- Co-authored-by: fangfang.dong Co-authored-by: Bai --- apps/locale/ja/LC_MESSAGES/django.po | 166 ++++++++++-------- apps/locale/zh/LC_MESSAGES/django.po | 164 +++++++++-------- apps/ops/models/job.py | 11 ++ apps/terminal/api/session/command.py | 68 ++++--- apps/terminal/backends/command/models.py | 2 +- apps/terminal/notifications.py | 84 ++++++--- apps/terminal/serializers/command.py | 26 ++- .../terminal/_msg_command_warning.html | 97 ++++++++-- 8 files changed, 390 insertions(+), 228 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index a15110564..f0909dc3c 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-13 15:56+0800\n" +"POT-Creation-Date: 2023-07-17 17:12+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -95,7 +95,7 @@ msgstr "更新" #: accounts/const/account.py:29 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:72 xpack/plugins/cloud/const.py:43 +#: ops/const.py:58 terminal/const.py:77 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失敗しました" @@ -200,8 +200,8 @@ msgstr "作成のみ" #: audits/models.py:53 authentication/models/connection_token.py:36 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 #: terminal/backends/command/models.py:18 terminal/models/session/session.py:31 -#: terminal/notifications.py:134 terminal/serializers/command.py:18 -#: terminal/templates/terminal/_msg_command_warning.html:4 +#: terminal/notifications.py:147 terminal/serializers/command.py:18 +#: terminal/templates/terminal/_msg_command_warning.html:39 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "資産" @@ -235,6 +235,7 @@ msgstr "ソース ID" #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 #: terminal/backends/command/models.py:19 terminal/models/session/session.py:33 +#: terminal/templates/terminal/_msg_command_warning.html:45 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "アカウント" @@ -655,16 +656,17 @@ msgstr "ID" #: perms/serializers/permission.py:30 rbac/builtin.py:123 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:17 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:135 terminal/notifications.py:183 -#: terminal/serializers/command.py:17 tickets/models/comment.py:21 -#: users/const.py:14 users/models/user.py:947 users/models/user.py:978 -#: users/serializers/group.py:18 +#: terminal/notifications.py:148 terminal/notifications.py:196 +#: terminal/serializers/command.py:17 +#: terminal/templates/terminal/_msg_command_warning.html:33 +#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:947 +#: users/models/user.py:978 users/serializers/group.py:18 msgid "User" msgstr "ユーザー" #: accounts/serializers/account/account.py:428 #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:137 terminal/notifications.py:185 +#: terminal/notifications.py:150 terminal/notifications.py:198 msgid "Date" msgstr "日付" @@ -743,7 +745,7 @@ msgstr "自動タスク実行履歴" #: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:40 -#: terminal/const.py:71 terminal/models/session/sharing.py:107 +#: terminal/const.py:76 terminal/models/session/sharing.py:107 #: tickets/views/approve.py:114 msgid "Success" msgstr "成功" @@ -843,11 +845,11 @@ msgid "Accounts" msgstr "アカウント" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:55 terminal/const.py:79 +#: ops/serializers/job.py:55 terminal/const.py:84 #: terminal/models/session/session.py:42 terminal/serializers/command.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:16 +#: terminal/templates/terminal/_msg_command_warning.html:51 msgid "Command" msgstr "コマンド" @@ -879,7 +881,7 @@ msgid "The generated regular expression is incorrect: {}" msgstr "生成された正規表現が正しくありません: {}" #: acls/models/command_acl.py:100 -#: terminal/templates/terminal/_msg_command_warning.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:57 msgid "Command acl" msgstr "コマンドフィルタリング" @@ -976,7 +978,7 @@ msgid "Applications" msgstr "アプリケーション" #: applications/models.py:16 xpack/plugins/cloud/models.py:33 -#: xpack/plugins/cloud/serializers/account.py:63 +#: xpack/plugins/cloud/serializers/account.py:62 msgid "Attrs" msgstr "ツールバーの" @@ -1412,7 +1414,7 @@ msgstr "証明書チェックを無視" #: assets/models/asset/gpt.py:8 msgid "Proxy" -msgstr "" +msgstr "プロキシー" #: assets/models/automations/base.py:22 ops/models/job.py:187 #: settings/serializers/auth/sms.py:99 @@ -1990,6 +1992,7 @@ msgid "Rename dir" msgstr "マップディレクトリ" #: audits/const.py:23 rbac/tree.py:229 +#: terminal/templates/terminal/_msg_command_warning.html:71 msgid "View" msgstr "表示" @@ -2073,7 +2076,7 @@ msgstr "書類" #: terminal/models/session/replay.py:9 terminal/models/session/sharing.py:18 #: terminal/models/session/sharing.py:81 #: terminal/templates/terminal/_msg_command_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:7 +#: terminal/templates/terminal/_msg_command_warning.html:69 #: tickets/models/ticket/command_confirm.py:15 msgid "Session" msgstr "セッション" @@ -2092,7 +2095,7 @@ msgid "Resource" msgstr "リソース" #: audits/models.py:96 audits/models.py:142 audits/models.py:168 -#: terminal/serializers/command.py:61 +#: terminal/serializers/command.py:76 msgid "Datetime" msgstr "時間" @@ -3022,7 +3025,7 @@ msgid "Copy success" msgstr "コピー成功" #: authentication/utils.py:28 common/utils/ip/geoip/utils.py:24 -#: xpack/plugins/cloud/const.py:29 +#: xpack/plugins/cloud/const.py:27 msgid "LAN" msgstr "ローカルエリアネットワーク" @@ -3177,7 +3180,7 @@ msgstr "タイミングトリガー" msgid "Ready" msgstr "の準備を" -#: common/const/choices.py:16 terminal/const.py:70 tickets/const.py:29 +#: common/const/choices.py:16 terminal/const.py:75 tickets/const.py:29 #: tickets/const.py:39 msgid "Pending" msgstr "未定" @@ -3916,6 +3919,7 @@ msgstr "アプリ組織" #: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:89 #: rbac/const.py:7 rbac/models/rolebinding.py:56 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:63 +#: terminal/templates/terminal/_msg_command_warning.html:75 #: tickets/models/ticket/general.py:302 tickets/serializers/ticket/ticket.py:60 msgid "Organization" msgstr "組織" @@ -5691,7 +5695,7 @@ msgstr "テスト失敗: {}" msgid "Test successful" msgstr "テスト成功" -#: terminal/api/component/storage.py:124 terminal/notifications.py:218 +#: terminal/api/component/storage.py:124 terminal/notifications.py:231 #: terminal/tasks.py:144 msgid "Test failure: Account invalid" msgstr "テスト失敗: アカウントが無効" @@ -5724,7 +5728,7 @@ msgstr "ターミナル管理" msgid "Input" msgstr "入力" -#: terminal/backends/command/models.py:21 terminal/serializers/command.py:59 +#: terminal/backends/command/models.py:21 terminal/serializers/command.py:74 msgid "Output" msgstr "出力" @@ -5748,40 +5752,40 @@ msgstr "確認して同意する" msgid "Review & Cancel" msgstr "確認してキャンセル" -#: terminal/const.py:39 +#: terminal/const.py:44 msgid "Critical" msgstr "クリティカル" -#: terminal/const.py:40 +#: terminal/const.py:45 msgid "High" msgstr "高い" -#: terminal/const.py:41 terminal/const.py:77 +#: terminal/const.py:46 terminal/const.py:82 #: users/templates/users/reset_password.html:50 msgid "Normal" msgstr "正常" -#: terminal/const.py:42 +#: terminal/const.py:47 msgid "Offline" msgstr "オフライン" -#: terminal/const.py:73 +#: terminal/const.py:78 msgid "Mismatch" msgstr "一致しない" -#: terminal/const.py:78 +#: terminal/const.py:83 msgid "Tunnel" msgstr "" -#: terminal/const.py:80 +#: terminal/const.py:85 msgid "SFTP" msgstr "SFTP" -#: terminal/const.py:84 +#: terminal/const.py:89 msgid "Read Only" msgstr "読み取り専用" -#: terminal/const.py:85 +#: terminal/const.py:90 msgid "Writable" msgstr "書き込み可能" @@ -5956,7 +5960,7 @@ msgstr "再生ストレージ" msgid "type" msgstr "タイプ" -#: terminal/models/component/terminal.py:89 terminal/serializers/command.py:62 +#: terminal/models/component/terminal.py:89 terminal/serializers/command.py:77 msgid "Remote Address" msgstr "リモートアドレス" @@ -6073,35 +6077,36 @@ msgstr "検証コードが無効" msgid "You have already joined this session" msgstr "すでにこのセッションに参加しています" -#: terminal/notifications.py:21 +#: terminal/notifications.py:22 msgid "Sessions" msgstr "セッション" -#: terminal/notifications.py:68 +#: terminal/notifications.py:69 +#: terminal/templates/terminal/_msg_command_warning.html:5 msgid "Danger command warning" msgstr "危険コマンドアラート" -#: terminal/notifications.py:109 +#: terminal/notifications.py:122 msgid "Danger command alert" msgstr "危険コマンドアラート" -#: terminal/notifications.py:136 terminal/notifications.py:184 +#: terminal/notifications.py:149 terminal/notifications.py:197 msgid "Level" msgstr "レベル" -#: terminal/notifications.py:154 +#: terminal/notifications.py:167 msgid "Batch danger command alert" msgstr "一括危険コマンド警告" -#: terminal/notifications.py:202 +#: terminal/notifications.py:215 msgid "Command and replay storage" msgstr "コマンド及び録画記憶" -#: terminal/notifications.py:203 +#: terminal/notifications.py:216 msgid "Connectivity alarm" msgstr "接続性アラーム" -#: terminal/notifications.py:228 +#: terminal/notifications.py:241 #: terminal/templates/terminal/_msg_check_command_replay_storage_connectivity.html:4 msgid "Invalid storage" msgstr "無効なストレージ" @@ -6185,11 +6190,23 @@ msgstr "コマンドフィルター" msgid "Command Group" msgstr "コマンドグループ" -#: terminal/serializers/command.py:58 +#: terminal/serializers/command.py:56 +msgid "Invalid command filter ACL id" +msgstr "無効なコマンドフィルターID" + +#: terminal/serializers/command.py:60 +msgid "Invalid command group id" +msgstr "無効なコマンドグループID" + +#: terminal/serializers/command.py:64 +msgid "Invalid session id" +msgstr "無効なセッションID" + +#: terminal/serializers/command.py:73 msgid "Account " msgstr "アカウント" -#: terminal/serializers/command.py:60 +#: terminal/serializers/command.py:75 msgid "Timestamp" msgstr "タイムスタンプ" @@ -6363,14 +6380,18 @@ msgid "Check command replay storage connectivity" msgstr "チェックコマンドと録画ストレージの接続性" #: terminal/templates/terminal/_msg_command_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:5 -#: terminal/templates/terminal/_msg_command_warning.html:8 -#: terminal/templates/terminal/_msg_command_warning.html:11 -#: terminal/templates/terminal/_msg_command_warning.html:14 msgid "view" msgstr "表示" -#: terminal/templates/terminal/_msg_command_warning.html:13 +#: terminal/templates/terminal/_msg_command_warning.html:21 +msgid "Item" +msgstr "アイテム" + +#: terminal/templates/terminal/_msg_command_warning.html:25 +msgid "Url" +msgstr "リンク" + +#: terminal/templates/terminal/_msg_command_warning.html:63 msgid "Command acl group" msgstr "コマンドフィルタリンググループ" @@ -6844,7 +6865,6 @@ msgid "Not a valid ssh public key" msgstr "有効なssh公開鍵ではありません" #: users/forms/profile.py:173 users/models/user.py:786 -#: xpack/plugins/cloud/serializers/account_attrs.py:206 msgid "Public key" msgstr "公開キー" @@ -6873,7 +6893,6 @@ msgid "OTP secret key" msgstr "OTP 秘密" #: users/models/user.py:783 -#: xpack/plugins/cloud/serializers/account_attrs.py:209 msgid "Private key" msgstr "ssh秘密鍵" @@ -7353,74 +7372,70 @@ msgid "Tencent Cloud (Lighthouse)" msgstr "テンセント雲(軽量アプリケーション)" #: xpack/plugins/cloud/const.py:19 -msgid "Google Cloud Platform" -msgstr "谷歌雲" - -#: xpack/plugins/cloud/const.py:20 -msgid "UCloud" -msgstr "" - -#: xpack/plugins/cloud/const.py:22 msgid "VMware" msgstr "VMware" -#: xpack/plugins/cloud/const.py:23 xpack/plugins/cloud/providers/nutanix.py:13 +#: xpack/plugins/cloud/const.py:20 xpack/plugins/cloud/providers/nutanix.py:13 msgid "Nutanix" msgstr "Nutanix" -#: xpack/plugins/cloud/const.py:24 +#: xpack/plugins/cloud/const.py:21 msgid "Huawei Private Cloud" msgstr "華為私有雲" -#: xpack/plugins/cloud/const.py:25 +#: xpack/plugins/cloud/const.py:22 msgid "Qingyun Private Cloud" msgstr "青雲私有雲" -#: xpack/plugins/cloud/const.py:26 +#: xpack/plugins/cloud/const.py:23 msgid "CTYun Private Cloud" msgstr "スカイウィング私有雲" -#: xpack/plugins/cloud/const.py:27 +#: xpack/plugins/cloud/const.py:24 msgid "OpenStack" msgstr "OpenStack" -#: xpack/plugins/cloud/const.py:28 +#: xpack/plugins/cloud/const.py:25 +msgid "Google Cloud Platform" +msgstr "谷歌雲" + +#: xpack/plugins/cloud/const.py:26 msgid "Fusion Compute" msgstr "融合計算" -#: xpack/plugins/cloud/const.py:33 +#: xpack/plugins/cloud/const.py:31 msgid "Private IP" msgstr "プライベートIP" -#: xpack/plugins/cloud/const.py:34 +#: xpack/plugins/cloud/const.py:32 msgid "Public IP" msgstr "パブリックIP" -#: xpack/plugins/cloud/const.py:38 +#: xpack/plugins/cloud/const.py:36 msgid "Instance name" msgstr "インスタンス名" -#: xpack/plugins/cloud/const.py:39 +#: xpack/plugins/cloud/const.py:37 msgid "Instance name and Partial IP" msgstr "インスタンス名と部分IP" -#: xpack/plugins/cloud/const.py:44 +#: xpack/plugins/cloud/const.py:42 msgid "Succeed" msgstr "成功" -#: xpack/plugins/cloud/const.py:48 +#: xpack/plugins/cloud/const.py:46 msgid "Unsync" msgstr "同期していません" -#: xpack/plugins/cloud/const.py:49 +#: xpack/plugins/cloud/const.py:47 msgid "New Sync" msgstr "新しい同期" -#: xpack/plugins/cloud/const.py:50 +#: xpack/plugins/cloud/const.py:48 msgid "Synced" msgstr "同期済み" -#: xpack/plugins/cloud/const.py:51 +#: xpack/plugins/cloud/const.py:49 msgid "Released" msgstr "リリース済み" @@ -7686,11 +7701,11 @@ msgstr "華南-広州-友好ユーザー環境" msgid "CN East-Suqian" msgstr "華東-宿遷" -#: xpack/plugins/cloud/serializers/account.py:64 +#: xpack/plugins/cloud/serializers/account.py:63 msgid "Validity display" msgstr "有効表示" -#: xpack/plugins/cloud/serializers/account.py:65 +#: xpack/plugins/cloud/serializers/account.py:64 msgid "Provider display" msgstr "プロバイダ表示" @@ -7710,7 +7725,6 @@ msgstr "サブスクリプションID" #: xpack/plugins/cloud/serializers/account_attrs.py:103 #: xpack/plugins/cloud/serializers/account_attrs.py:119 #: xpack/plugins/cloud/serializers/account_attrs.py:149 -#: xpack/plugins/cloud/serializers/account_attrs.py:202 msgid "API Endpoint" msgstr "APIエンドポイント" @@ -7776,10 +7790,6 @@ msgstr "テストポート" msgid "Test timeout" msgstr "テストタイムアウト" -#: xpack/plugins/cloud/serializers/account_attrs.py:212 -msgid "Project" -msgstr "" - #: xpack/plugins/cloud/serializers/task.py:28 msgid "" "Only instances matching the IP range will be synced.
If the instance " diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 94f3ea94c..bd56a7e31 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-13 15:56+0800\n" +"POT-Creation-Date: 2023-07-17 17:12+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -94,7 +94,7 @@ msgstr "更新" #: accounts/const/account.py:29 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:72 xpack/plugins/cloud/const.py:43 +#: ops/const.py:58 terminal/const.py:77 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失败" @@ -199,8 +199,8 @@ msgstr "仅创建" #: audits/models.py:53 authentication/models/connection_token.py:36 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 #: terminal/backends/command/models.py:18 terminal/models/session/session.py:31 -#: terminal/notifications.py:134 terminal/serializers/command.py:18 -#: terminal/templates/terminal/_msg_command_warning.html:4 +#: terminal/notifications.py:147 terminal/serializers/command.py:18 +#: terminal/templates/terminal/_msg_command_warning.html:39 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "资产" @@ -234,6 +234,7 @@ msgstr "来源 ID" #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 #: terminal/backends/command/models.py:19 terminal/models/session/session.py:33 +#: terminal/templates/terminal/_msg_command_warning.html:45 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "账号" @@ -651,16 +652,17 @@ msgstr "ID" #: perms/serializers/permission.py:30 rbac/builtin.py:123 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:17 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:135 terminal/notifications.py:183 -#: terminal/serializers/command.py:17 tickets/models/comment.py:21 -#: users/const.py:14 users/models/user.py:947 users/models/user.py:978 -#: users/serializers/group.py:18 +#: terminal/notifications.py:148 terminal/notifications.py:196 +#: terminal/serializers/command.py:17 +#: terminal/templates/terminal/_msg_command_warning.html:33 +#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:947 +#: users/models/user.py:978 users/serializers/group.py:18 msgid "User" msgstr "用户" #: accounts/serializers/account/account.py:428 #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:137 terminal/notifications.py:185 +#: terminal/notifications.py:150 terminal/notifications.py:198 msgid "Date" msgstr "日期" @@ -739,7 +741,7 @@ msgstr "自动化任务执行历史" #: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:56 ops/serializers/celery.py:40 -#: terminal/const.py:71 terminal/models/session/sharing.py:107 +#: terminal/const.py:76 terminal/models/session/sharing.py:107 #: tickets/views/approve.py:114 msgid "Success" msgstr "成功" @@ -839,11 +841,11 @@ msgid "Accounts" msgstr "账号管理" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:55 terminal/const.py:79 +#: ops/serializers/job.py:55 terminal/const.py:84 #: terminal/models/session/session.py:42 terminal/serializers/command.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:16 +#: terminal/templates/terminal/_msg_command_warning.html:51 msgid "Command" msgstr "命令" @@ -875,7 +877,7 @@ msgid "The generated regular expression is incorrect: {}" msgstr "生成的正则表达式有误" #: acls/models/command_acl.py:100 -#: terminal/templates/terminal/_msg_command_warning.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:57 msgid "Command acl" msgstr "命令过滤" @@ -971,7 +973,7 @@ msgid "Applications" msgstr "应用管理" #: applications/models.py:16 xpack/plugins/cloud/models.py:33 -#: xpack/plugins/cloud/serializers/account.py:63 +#: xpack/plugins/cloud/serializers/account.py:62 msgid "Attrs" msgstr "属性" @@ -1974,6 +1976,7 @@ msgid "Rename dir" msgstr "映射目录" #: audits/const.py:23 rbac/tree.py:229 +#: terminal/templates/terminal/_msg_command_warning.html:71 msgid "View" msgstr "查看" @@ -2057,7 +2060,7 @@ msgstr "文件" #: terminal/models/session/replay.py:9 terminal/models/session/sharing.py:18 #: terminal/models/session/sharing.py:81 #: terminal/templates/terminal/_msg_command_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:7 +#: terminal/templates/terminal/_msg_command_warning.html:69 #: tickets/models/ticket/command_confirm.py:15 msgid "Session" msgstr "会话" @@ -2076,7 +2079,7 @@ msgid "Resource" msgstr "资源" #: audits/models.py:96 audits/models.py:142 audits/models.py:168 -#: terminal/serializers/command.py:61 +#: terminal/serializers/command.py:76 msgid "Datetime" msgstr "日期" @@ -2982,7 +2985,7 @@ msgid "Copy success" msgstr "复制成功" #: authentication/utils.py:28 common/utils/ip/geoip/utils.py:24 -#: xpack/plugins/cloud/const.py:29 +#: xpack/plugins/cloud/const.py:27 msgid "LAN" msgstr "局域网" @@ -3137,7 +3140,7 @@ msgstr "定时触发" msgid "Ready" msgstr "准备" -#: common/const/choices.py:16 terminal/const.py:70 tickets/const.py:29 +#: common/const/choices.py:16 terminal/const.py:75 tickets/const.py:29 #: tickets/const.py:39 msgid "Pending" msgstr "待定的" @@ -3868,6 +3871,7 @@ msgstr "组织管理" #: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:89 #: rbac/const.py:7 rbac/models/rolebinding.py:56 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:63 +#: terminal/templates/terminal/_msg_command_warning.html:75 #: tickets/models/ticket/general.py:302 tickets/serializers/ticket/ticket.py:60 msgid "Organization" msgstr "组织" @@ -5604,7 +5608,7 @@ msgstr "测试失败: {}" msgid "Test successful" msgstr "测试成功" -#: terminal/api/component/storage.py:124 terminal/notifications.py:218 +#: terminal/api/component/storage.py:124 terminal/notifications.py:231 #: terminal/tasks.py:144 msgid "Test failure: Account invalid" msgstr "测试失败: 账号无效" @@ -5637,7 +5641,7 @@ msgstr "终端管理" msgid "Input" msgstr "输入" -#: terminal/backends/command/models.py:21 terminal/serializers/command.py:59 +#: terminal/backends/command/models.py:21 terminal/serializers/command.py:74 msgid "Output" msgstr "输出" @@ -5661,40 +5665,40 @@ msgstr "审批 & 接受" msgid "Review & Cancel" msgstr "审批 & 取消" -#: terminal/const.py:39 +#: terminal/const.py:44 msgid "Critical" msgstr "严重" -#: terminal/const.py:40 +#: terminal/const.py:45 msgid "High" msgstr "较高" -#: terminal/const.py:41 terminal/const.py:77 +#: terminal/const.py:46 terminal/const.py:82 #: users/templates/users/reset_password.html:50 msgid "Normal" msgstr "正常" -#: terminal/const.py:42 +#: terminal/const.py:47 msgid "Offline" msgstr "离线" -#: terminal/const.py:73 +#: terminal/const.py:78 msgid "Mismatch" msgstr "未匹配" -#: terminal/const.py:78 +#: terminal/const.py:83 msgid "Tunnel" msgstr "隧道" -#: terminal/const.py:80 +#: terminal/const.py:85 msgid "SFTP" msgstr "SFTP" -#: terminal/const.py:84 +#: terminal/const.py:89 msgid "Read Only" msgstr "只读" -#: terminal/const.py:85 +#: terminal/const.py:90 msgid "Writable" msgstr "读写" @@ -5869,7 +5873,7 @@ msgstr "录像存储" msgid "type" msgstr "类型" -#: terminal/models/component/terminal.py:89 terminal/serializers/command.py:62 +#: terminal/models/component/terminal.py:89 terminal/serializers/command.py:77 msgid "Remote Address" msgstr "远端地址" @@ -5986,35 +5990,36 @@ msgstr "验证码不正确" msgid "You have already joined this session" msgstr "您已经加入过此会话" -#: terminal/notifications.py:21 +#: terminal/notifications.py:22 msgid "Sessions" msgstr "会话管理" -#: terminal/notifications.py:68 +#: terminal/notifications.py:69 +#: terminal/templates/terminal/_msg_command_warning.html:5 msgid "Danger command warning" msgstr "危险命令告警" -#: terminal/notifications.py:109 +#: terminal/notifications.py:122 msgid "Danger command alert" msgstr "危险命令告警" -#: terminal/notifications.py:136 terminal/notifications.py:184 +#: terminal/notifications.py:149 terminal/notifications.py:197 msgid "Level" msgstr "级别" -#: terminal/notifications.py:154 +#: terminal/notifications.py:167 msgid "Batch danger command alert" msgstr "批量危险命令告警" -#: terminal/notifications.py:202 +#: terminal/notifications.py:215 msgid "Command and replay storage" msgstr "命令及录像存储" -#: terminal/notifications.py:203 +#: terminal/notifications.py:216 msgid "Connectivity alarm" msgstr "可连接性告警" -#: terminal/notifications.py:228 +#: terminal/notifications.py:241 #: terminal/templates/terminal/_msg_check_command_replay_storage_connectivity.html:4 msgid "Invalid storage" msgstr "无效的存储" @@ -6096,11 +6101,23 @@ msgstr "命令过滤器" msgid "Command Group" msgstr "命令组" -#: terminal/serializers/command.py:58 +#: terminal/serializers/command.py:56 +msgid "Invalid command filter ACL id" +msgstr "无效的 命令过滤器 ID" + +#: terminal/serializers/command.py:60 +msgid "Invalid command group id" +msgstr "无效的 命令组 ID" + +#: terminal/serializers/command.py:64 +msgid "Invalid session id" +msgstr "无效的 Session ID" + +#: terminal/serializers/command.py:73 msgid "Account " msgstr "账号" -#: terminal/serializers/command.py:60 +#: terminal/serializers/command.py:75 msgid "Timestamp" msgstr "时间戳" @@ -6271,14 +6288,18 @@ msgid "Check command replay storage connectivity" msgstr "检查命令及录像存储可连接性 " #: terminal/templates/terminal/_msg_command_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:5 -#: terminal/templates/terminal/_msg_command_warning.html:8 -#: terminal/templates/terminal/_msg_command_warning.html:11 -#: terminal/templates/terminal/_msg_command_warning.html:14 msgid "view" msgstr "查看" -#: terminal/templates/terminal/_msg_command_warning.html:13 +#: terminal/templates/terminal/_msg_command_warning.html:21 +msgid "Item" +msgstr "项目" + +#: terminal/templates/terminal/_msg_command_warning.html:25 +msgid "Url" +msgstr "链接" + +#: terminal/templates/terminal/_msg_command_warning.html:63 msgid "Command acl group" msgstr "命令过滤组" @@ -6746,7 +6767,6 @@ msgid "Not a valid ssh public key" msgstr "SSH密钥不合法" #: users/forms/profile.py:173 users/models/user.py:786 -#: xpack/plugins/cloud/serializers/account_attrs.py:206 msgid "Public key" msgstr "SSH公钥" @@ -6775,7 +6795,6 @@ msgid "OTP secret key" msgstr "OTP 密钥" #: users/models/user.py:783 -#: xpack/plugins/cloud/serializers/account_attrs.py:209 msgid "Private key" msgstr "ssh私钥" @@ -7242,74 +7261,70 @@ msgid "Tencent Cloud (Lighthouse)" msgstr "腾讯云(轻量服务器应用)" #: xpack/plugins/cloud/const.py:19 -msgid "Google Cloud Platform" -msgstr "谷歌云" - -#: xpack/plugins/cloud/const.py:20 -msgid "UCloud" -msgstr "" - -#: xpack/plugins/cloud/const.py:22 msgid "VMware" msgstr "VMware" -#: xpack/plugins/cloud/const.py:23 xpack/plugins/cloud/providers/nutanix.py:13 +#: xpack/plugins/cloud/const.py:20 xpack/plugins/cloud/providers/nutanix.py:13 msgid "Nutanix" msgstr "Nutanix" -#: xpack/plugins/cloud/const.py:24 +#: xpack/plugins/cloud/const.py:21 msgid "Huawei Private Cloud" msgstr "华为私有云" -#: xpack/plugins/cloud/const.py:25 +#: xpack/plugins/cloud/const.py:22 msgid "Qingyun Private Cloud" msgstr "青云私有云" -#: xpack/plugins/cloud/const.py:26 +#: xpack/plugins/cloud/const.py:23 msgid "CTYun Private Cloud" msgstr "天翼私有云" -#: xpack/plugins/cloud/const.py:27 +#: xpack/plugins/cloud/const.py:24 msgid "OpenStack" msgstr "OpenStack" -#: xpack/plugins/cloud/const.py:28 +#: xpack/plugins/cloud/const.py:25 +msgid "Google Cloud Platform" +msgstr "谷歌云" + +#: xpack/plugins/cloud/const.py:26 msgid "Fusion Compute" msgstr "融合计算" -#: xpack/plugins/cloud/const.py:33 +#: xpack/plugins/cloud/const.py:31 msgid "Private IP" msgstr "私有IP" -#: xpack/plugins/cloud/const.py:34 +#: xpack/plugins/cloud/const.py:32 msgid "Public IP" msgstr "公网IP" -#: xpack/plugins/cloud/const.py:38 +#: xpack/plugins/cloud/const.py:36 msgid "Instance name" msgstr "实例名称" -#: xpack/plugins/cloud/const.py:39 +#: xpack/plugins/cloud/const.py:37 msgid "Instance name and Partial IP" msgstr "实例名称和部分IP" -#: xpack/plugins/cloud/const.py:44 +#: xpack/plugins/cloud/const.py:42 msgid "Succeed" msgstr "成功" -#: xpack/plugins/cloud/const.py:48 +#: xpack/plugins/cloud/const.py:46 msgid "Unsync" msgstr "未同步" -#: xpack/plugins/cloud/const.py:49 +#: xpack/plugins/cloud/const.py:47 msgid "New Sync" msgstr "新同步" -#: xpack/plugins/cloud/const.py:50 +#: xpack/plugins/cloud/const.py:48 msgid "Synced" msgstr "已同步" -#: xpack/plugins/cloud/const.py:51 +#: xpack/plugins/cloud/const.py:49 msgid "Released" msgstr "已释放" @@ -7575,11 +7590,11 @@ msgstr "华南-广州-友好用户环境" msgid "CN East-Suqian" msgstr "华东-宿迁" -#: xpack/plugins/cloud/serializers/account.py:64 +#: xpack/plugins/cloud/serializers/account.py:63 msgid "Validity display" msgstr "有效性显示" -#: xpack/plugins/cloud/serializers/account.py:65 +#: xpack/plugins/cloud/serializers/account.py:64 msgid "Provider display" msgstr "服务商显示" @@ -7599,7 +7614,6 @@ msgstr "订阅 ID" #: xpack/plugins/cloud/serializers/account_attrs.py:103 #: xpack/plugins/cloud/serializers/account_attrs.py:119 #: xpack/plugins/cloud/serializers/account_attrs.py:149 -#: xpack/plugins/cloud/serializers/account_attrs.py:202 msgid "API Endpoint" msgstr "API 端点" @@ -7664,10 +7678,6 @@ msgstr "测试端口" msgid "Test timeout" msgstr "测试超时时间" -#: xpack/plugins/cloud/serializers/account_attrs.py:212 -msgid "Project" -msgstr "" - #: xpack/plugins/cloud/serializers/task.py:28 msgid "" "Only instances matching the IP range will be synced.
If the instance " diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index 7360838d7..162ac5924 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -27,6 +27,7 @@ from orgs.mixins.models import JMSOrgBaseModel from perms.models import AssetPermission from perms.utils import UserPermAssetUtil from terminal.notifications import CommandExecutionAlert +from terminal.notifications import CommandWarningMessage def get_parent_keys(key, include_self=True): @@ -398,6 +399,16 @@ class JobExecution(JMSOrgBaseModel): "user": self.creator, }).publish_async() raise Exception("command is rejected by ACL") + elif acl.is_action(CommandFilterACL.ActionChoices.warning): + # TODO: warning message + # user = '' + # command = { + # 'user': '', + # 'user_id': '' + # } + # CommandWarningMessage(user, command).publish_async() + return True + return False def check_command_acl(self): diff --git a/apps/terminal/api/session/command.py b/apps/terminal/api/session/command.py index dc4778b80..073482551 100644 --- a/apps/terminal/api/session/command.py +++ b/apps/terminal/api/session/command.py @@ -1,17 +1,17 @@ # -*- coding: utf-8 -*- # -from django.conf import settings +from django.utils import translation from django.utils import timezone from rest_framework import generics from rest_framework.fields import DateTimeField from rest_framework.response import Response -from acls.models import CommandFilterACL +from acls.models import CommandFilterACL, CommandGroup from terminal.models import CommandStorage, Session, Command from terminal.filters import CommandFilter from orgs.utils import current_org from common.api import JMSBulkModelViewSet -from common.utils import get_logger, is_uuid +from common.utils import get_logger from terminal.serializers import ( SessionCommandSerializer, InsecureCommandAlertSerializer ) @@ -201,30 +201,44 @@ class InsecureCommandAlertAPI(generics.CreateAPIView): serializer = InsecureCommandAlertSerializer(data=request.data, many=True) serializer.is_valid(raise_exception=True) commands = serializer.validated_data - - acl_ids = [] - for cmd in commands: - acl_id = cmd.get('cmd_filter_acl') - if not is_uuid(acl_id): - continue - acl_ids.append(acl_id) - - acls = CommandFilterACL.objects.filter(id__in=acl_ids) - acls_mapper = {str(acl.id): acl for acl in acls} - + session_ids, acl_ids, cmd_group_ids = set(), set(), set() for command in commands: - risk_level = command.get('risk_level') + session_ids.add(command.get('session')) + acl_ids.add(command.get('cmd_filter_acl')) + cmd_group_ids.add(command.get('cmd_group')) + + sessions = Session.objects.filter(id__in=session_ids).only( + 'id', 'org_id', 'asset', 'asset_id', 'user', 'user_id', 'account', 'account_id' + ) + session_mapper = {str(i.id): i for i in sessions} + acls = CommandFilterACL.objects.filter(id__in=acl_ids).only('id', 'name', 'reviewers') + acl_mapper = {str(i.id): i for i in acls} + cmd_groups = CommandGroup.objects.filter(id__in=cmd_group_ids).only('id', 'name') + cmd_group_mapper = {str(i.id): i for i in cmd_groups} + + lang = request.stream.COOKIES.get('django_language', 'zh') + with translation.override(lang): + for command in commands: + cmd_acl = acl_mapper.get(command['cmd_filter_acl']) + command['_cmd_filter_acl'] = cmd_acl + cmd_group = cmd_group_mapper.get(command['cmd_group']) + command['_cmd_group'] = cmd_group + session = session_mapper.get(command['session']) + if session: + command.update({ + '_user_id': session.user_id, + '_asset_id': session.asset_id, + '_account_id': session.account_id, + '_org_name': session.org.name + }) + + risk_level = command.get('risk_level') + if risk_level in [RiskLevelChoices.reject, RiskLevelChoices.review_reject]: + CommandAlertMessage(command).publish_async() + elif risk_level in [RiskLevelChoices.warning]: + for reviewer in cmd_acl.reviewers.all(): + CommandWarningMessage(reviewer, command).publish_async() + else: + logger.info(f'Risk level ignore: {risk_level}') - if risk_level in [RiskLevelChoices.reject, RiskLevelChoices.review_reject]: - CommandAlertMessage(command).publish_async() - elif risk_level in [RiskLevelChoices.warning]: - acl_id = command.get('cmd_filter_acl') - acl = acls_mapper.get(acl_id) - if not acl: - logger.info(f'ACL not found: {acl_id}') - continue - for reviewer in acl.reviewers.all(): - CommandWarningMessage(reviewer, command).publish_async() - else: - logger.info(f'Risk level ignore: {risk_level}') return Response({'msg': 'ok'}) diff --git a/apps/terminal/backends/command/models.py b/apps/terminal/backends/command/models.py index b56f8c673..f588a177d 100644 --- a/apps/terminal/backends/command/models.py +++ b/apps/terminal/backends/command/models.py @@ -44,7 +44,7 @@ class AbstractSessionCommand(OrgModelMixin): @classmethod def get_risk_level_str(cls, risk_level): - risk_mapper = dict(cls.RiskLevelChoices.choices) + risk_mapper = dict(RiskLevelChoices.choices) return risk_mapper.get(risk_level) def to_dict(self): diff --git a/apps/terminal/notifications.py b/apps/terminal/notifications.py index 804f8d44b..fdc21fb77 100644 --- a/apps/terminal/notifications.py +++ b/apps/terminal/notifications.py @@ -11,11 +11,15 @@ from notifications.backends import BACKEND from notifications.models import SystemMsgSubscription from notifications.notifications import SystemMessage, UserMessage from terminal.models import Session, Command +from acls.models import CommandFilterACL, CommandGroup from users.models import User logger = get_logger(__name__) -__all__ = ('CommandAlertMessage', 'CommandExecutionAlert', 'StorageConnectivityMessage') +__all__ = ( + 'CommandAlertMessage', 'CommandExecutionAlert', 'StorageConnectivityMessage', + 'CommandWarningMessage' +) CATEGORY = 'terminal' CATEGORY_LABEL = _('Sessions') @@ -70,32 +74,72 @@ class CommandWarningMessage(CommandAlertMixin, UserMessage): def __init__(self, user, command): super().__init__(user) self.command = command - + def get_html_msg(self) -> dict: - session = self.command.get('session') - session_url = reverse( - 'api-terminal:session-detail', kwargs={'pk': session}, - external=True, api_to_ui=True - ) + '?oid={}'.format(self.command['org_id']) + command = self.command - asset = self.command.get('asset') - asset_url = reverse( - 'assets:asset-detail', kwargs={'pk': asset}, - api_to_ui=True, external=True, is_console=True - ) + '?oid={}'.format(self.command.get('org_id')) + command_input = command['input'] + user = command['user'] + user_id = command.get('_user_id', '') + asset = command['asset'] + asset_id = command.get('_asset_id', '') + account = command['account'] + account_id = command.get('_account_id', '') + cmd_acl = command.get('_cmd_filter_acl') + cmd_group = command.get('_cmd_group') + session_id = command['session'] + org_id = command['org_id'] + org_name = command.get('_org_name') or org_id - cmd_filter_acl = self.command.get('cmd_filter_acl') - cmd_group = self.command.get('cmd_group') + user_url = asset_url = account_url = session_url = '' + if user_id: + user_url = reverse( + 'users:user-detail', kwargs={'pk': user_id}, + api_to_ui=True, external=True, is_console=True + ) + '?oid={}'.format(org_id) + if asset_id: + asset_url = reverse( + 'assets:asset-detail', kwargs={'pk': asset_id}, + api_to_ui=True, external=True, is_console=True + ) + '?oid={}'.format(org_id) + if account_id: + account_url = reverse( + 'accounts:account-detail', kwargs={'pk': account_id}, + api_to_ui=True, external=True, is_console=True + ) + '?oid={}'.format(org_id) + if session_id: + session_url = reverse( + 'api-terminal:session-detail', kwargs={'pk': session_id}, + external=True, api_to_ui=True + ) + '?oid={}'.format(org_id) + session_url = session_url.replace('/terminal/sessions/', '/audit/sessions/sessions/') + + # Command ACL + cmd_acl_url = cmd_group_url = '' + cmd_acl_name = cmd_group_name = '' + if cmd_acl: + cmd_acl_name = cmd_acl.name + cmd_acl_url = settings.SITE_URL + f'/ui/#/console/perms/cmd-acls/{cmd_acl.id}/' + if cmd_group: + cmd_group_name = cmd_group.name + cmd_group_url = settings.SITE_URL + f'/ui/#/console/perms/cmd-groups/{cmd_group.id}/' context = { - "command": self.command['input'], + 'command': command_input, + 'user': user, + 'user_url': user_url, + 'asset': asset, 'asset_url': asset_url, - 'session_url': session_url.replace( - '/terminal/sessions/', '/audit/sessions/sessions/' - ), - 'cmd_filter_acl_url': settings.SITE_URL + '/ui/#/console/perms/cmd-acls/%s/' % cmd_filter_acl, - 'cmd_group_url': settings.SITE_URL + '/ui/#/console/perms/cmd-groups/%s/' % cmd_group, + 'account': account, + 'account_url': account_url, + 'cmd_filter_acl': cmd_acl_name, + 'cmd_filter_acl_url': cmd_acl_url, + 'cmd_group': cmd_group_name, + 'cmd_group_url': cmd_group_url, + 'session_url': session_url, + 'org': org_name, } + message = render_to_string('terminal/_msg_command_warning.html', context) return { 'subject': self.subject, diff --git a/apps/terminal/serializers/command.py b/apps/terminal/serializers/command.py index b845c6609..b8983a59c 100644 --- a/apps/terminal/serializers/command.py +++ b/apps/terminal/serializers/command.py @@ -2,12 +2,12 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers -from common.utils import pretty_string +from common.utils import pretty_string, is_uuid, get_logger from common.serializers.fields import LabeledChoiceField -from terminal.backends.command.models import AbstractSessionCommand from terminal.models import Command from terminal.const import RiskLevelChoices +logger = get_logger(__name__) __all__ = ['SessionCommandSerializer', 'InsecureCommandAlertSerializer'] @@ -39,17 +39,32 @@ class SimpleSessionCommandSerializer(serializers.ModelSerializer): class InsecureCommandAlertSerializer(SimpleSessionCommandSerializer): cmd_filter_acl = serializers.CharField( - max_length=128, required=False, label=_("Command Filter ACL") + max_length=36, required=False, label=_("Command Filter ACL") ) cmd_group = serializers.CharField( - max_length=128, required=True, label=_("Command Group") + max_length=36, required=True, label=_("Command Group") ) class Meta(SimpleSessionCommandSerializer.Meta): fields = SimpleSessionCommandSerializer.Meta.fields + [ - 'cmd_filter_acl', 'cmd_group' + 'cmd_filter_acl', 'cmd_group', ] + def validate(self, attrs): + if not is_uuid(attrs['cmd_filter_acl']): + raise serializers.ValidationError( + _("Invalid command filter ACL id") + ) + if not is_uuid(attrs['cmd_group']): + raise serializers.ValidationError( + _("Invalid command group id") + ) + if not is_uuid(attrs['session']): + raise serializers.ValidationError( + _("Invalid session id") + ) + return super().validate(attrs) + class SessionCommandSerializerMixin(serializers.Serializer): """使用这个类作为基础Command Log Serializer类, 用来序列化""" @@ -74,4 +89,3 @@ class SessionCommandSerializer(SessionCommandSerializerMixin, SimpleSessionComma fields = SimpleSessionCommandSerializer.Meta.fields + [ 'id', 'account', 'output', 'timestamp', 'timestamp_display', 'remote_addr' ] - diff --git a/apps/terminal/templates/terminal/_msg_command_warning.html b/apps/terminal/templates/terminal/_msg_command_warning.html index 215129dbe..0a7fe66a1 100644 --- a/apps/terminal/templates/terminal/_msg_command_warning.html +++ b/apps/terminal/templates/terminal/_msg_command_warning.html @@ -1,23 +1,82 @@ {% load i18n %}
- {% trans 'Asset' %}: - {% trans 'view' %} -
- {% trans 'Session' %}: - {% trans 'view' %} -
- {% trans 'Command acl' %}: - {% trans 'view' %} -
- {% trans 'Command acl group' %}: - {% trans 'view' %} -
- {% trans 'Command' %}:
- -
 {{ command }} 
-
+

+ {% blocktranslate %}Danger command warning{% endblocktranslate %} +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {% trans 'Item' %} + + {% trans 'Url' %} +
{% trans 'User' %} + {{ user }} +
{% trans 'Asset' %} + {{ asset }} +
{% trans 'Account' %} + {{ account }} +
{% trans 'Command' %} + {{ command }} +
{% trans 'Command acl' %} + {{ cmd_filter_acl }} +
{% trans 'Command acl group' %} + {{ cmd_group }} +
{% trans 'Session' %} + {% trans 'View' %} +
{% trans 'Organization' %} + {{ org }} +
From 6035241efb73c3c0e75105c429bd4cedd1527af7 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 18 Jul 2023 10:44:12 +0800 Subject: [PATCH 130/167] =?UTF-8?q?perf:=20gunicon=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=87=8D=E5=90=AF=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/management/commands/services/services/gunicorn.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/common/management/commands/services/services/gunicorn.py b/apps/common/management/commands/services/services/gunicorn.py index bd14284af..3ac6eedee 100644 --- a/apps/common/management/commands/services/services/gunicorn.py +++ b/apps/common/management/commands/services/services/gunicorn.py @@ -22,7 +22,8 @@ class GunicornService(BaseService): '-b', bind, '-k', 'uvicorn.workers.UvicornWorker', '-w', str(self.worker), - '--max-requests', '40960', + '--max-requests', '10240', + '--max-requests-jitter', '5120', '--access-logformat', log_format, '--access-logfile', '-' ] From d965ac0781752d1958b6f341140fe36275c4283f Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 18 Jul 2023 11:00:43 +0800 Subject: [PATCH 131/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/management/commands/services/services/gunicorn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/common/management/commands/services/services/gunicorn.py b/apps/common/management/commands/services/services/gunicorn.py index 3ac6eedee..66aa9f7bc 100644 --- a/apps/common/management/commands/services/services/gunicorn.py +++ b/apps/common/management/commands/services/services/gunicorn.py @@ -23,7 +23,7 @@ class GunicornService(BaseService): '-k', 'uvicorn.workers.UvicornWorker', '-w', str(self.worker), '--max-requests', '10240', - '--max-requests-jitter', '5120', + '--max-requests-jitter', '2048', '--access-logformat', log_format, '--access-logfile', '-' ] From f466904a1c655deecce3c61625fd13293b90bda9 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 18 Jul 2023 10:10:24 +0800 Subject: [PATCH 132/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20LDAP=20?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=AF=BC=E5=85=A5/=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E6=97=B6=E6=94=AF=E6=8C=81=20is=5Factive=20=E4=B8=BA=20-1=20?= =?UTF-8?q?=E7=9A=84=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/backends/ldap.py | 10 ++++++---- apps/settings/utils/ldap.py | 10 +++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/apps/authentication/backends/ldap.py b/apps/authentication/backends/ldap.py index 354d6211e..616052af2 100644 --- a/apps/authentication/backends/ldap.py +++ b/apps/authentication/backends/ldap.py @@ -9,6 +9,7 @@ from django_auth_ldap.config import _LDAPConfig, LDAPSearch, LDAPSearchUnion from users.utils import construct_user_email from common.const import LDAP_AD_ACCOUNT_DISABLE +from common.utils.http import is_true from .base import JMSBaseAuthBackend logger = _LDAPConfig.get_logger() @@ -162,10 +163,11 @@ class LDAPUser(_LDAPUser): try: value = self.attrs[attr][0] value = value.strip() - if attr.lower() == 'useraccountcontrol' \ - and field == 'is_active' and value: - value = int(value) & LDAP_AD_ACCOUNT_DISABLE \ - != LDAP_AD_ACCOUNT_DISABLE + if field == 'is_active': + if attr.lower() == 'useraccountcontrol' and value: + value = int(value) & LDAP_AD_ACCOUNT_DISABLE != LDAP_AD_ACCOUNT_DISABLE + else: + value = is_true(value) except LookupError: logger.warning("{} does not have a value for the attribute {}".format(self.dn, attr)) else: diff --git a/apps/settings/utils/ldap.py b/apps/settings/utils/ldap.py index 2d91306ad..e8ff0ab79 100644 --- a/apps/settings/utils/ldap.py +++ b/apps/settings/utils/ldap.py @@ -28,6 +28,7 @@ from authentication.backends.ldap import LDAPAuthorizationBackend, LDAPUser from common.const import LDAP_AD_ACCOUNT_DISABLE from common.db.utils import close_old_connections from common.utils import timeit, get_logger +from common.utils.http import is_true from orgs.utils import tmp_to_org from users.models import User, UserGroup from users.utils import construct_user_email @@ -185,9 +186,12 @@ class LDAPServerUtil(object): if not hasattr(entry, mapping): continue value = getattr(entry, mapping).value or '' - if attr == 'is_active' and mapping.lower() == 'useraccountcontrol' \ - and value: - value = int(value) & LDAP_AD_ACCOUNT_DISABLE != LDAP_AD_ACCOUNT_DISABLE + if attr == 'is_active': + if mapping.lower() == 'useraccountcontrol' and value: + value = int(value) & LDAP_AD_ACCOUNT_DISABLE != LDAP_AD_ACCOUNT_DISABLE + else: + value = is_true(value) + if attr == 'groups' and mapping.lower() == 'memberof': # AD: {'groups': 'memberOf'} if isinstance(value, str) and value: From 0436487bdbc3b0caaed9bb679fe355dec67ec8ab Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 18 Jul 2023 15:01:47 +0800 Subject: [PATCH 133/167] =?UTF-8?q?fix:=20=E6=9B=BF=E6=8D=A2ssh=20key=20?= =?UTF-8?q?=E7=94=9F=E6=88=90=E5=AF=86=E9=92=A5=E6=96=B9=E6=B3=95=20(#1099?= =?UTF-8?q?5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/accounts/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/accounts/utils.py b/apps/accounts/utils.py index fc13a62d4..ef0d61fe1 100644 --- a/apps/accounts/utils.py +++ b/apps/accounts/utils.py @@ -4,7 +4,7 @@ from rest_framework import serializers from accounts.const import ( SecretType, DEFAULT_PASSWORD_RULES ) -from common.utils import gen_key_pair, random_string +from common.utils import ssh_key_gen, random_string from common.utils import validate_ssh_private_key, parse_ssh_private_key_str @@ -16,7 +16,7 @@ class SecretGenerator: @staticmethod def generate_ssh_key(): - private_key, public_key = gen_key_pair() + private_key, public_key = ssh_key_gen() return private_key def generate_password(self): From 539babcc970d46076f2f706728cf05d5ea1f1f27 Mon Sep 17 00:00:00 2001 From: "fangfang.dong" Date: Tue, 18 Jul 2023 12:00:41 +0800 Subject: [PATCH 134/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E5=8F=96=E5=80=BC=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/api/session/command.py | 1 + apps/terminal/notifications.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/terminal/api/session/command.py b/apps/terminal/api/session/command.py index 073482551..44e7135f1 100644 --- a/apps/terminal/api/session/command.py +++ b/apps/terminal/api/session/command.py @@ -228,6 +228,7 @@ class InsecureCommandAlertAPI(generics.CreateAPIView): command.update({ '_user_id': session.user_id, '_asset_id': session.asset_id, + '_account': session.account, '_account_id': session.account_id, '_org_name': session.org.name }) diff --git a/apps/terminal/notifications.py b/apps/terminal/notifications.py index fdc21fb77..bd036d9bb 100644 --- a/apps/terminal/notifications.py +++ b/apps/terminal/notifications.py @@ -83,7 +83,7 @@ class CommandWarningMessage(CommandAlertMixin, UserMessage): user_id = command.get('_user_id', '') asset = command['asset'] asset_id = command.get('_asset_id', '') - account = command['account'] + account = command['_account'] account_id = command.get('_account_id', '') cmd_acl = command.get('_cmd_filter_acl') cmd_group = command.get('_cmd_group') From 27c10fcae19074cba11fc9cbd3aa2ab7189c9b08 Mon Sep 17 00:00:00 2001 From: halo Date: Thu, 13 Jul 2023 21:50:17 +0800 Subject: [PATCH 135/167] =?UTF-8?q?fix:=20=E9=82=AE=E4=BB=B6=E4=B8=BB?= =?UTF-8?q?=E9=A2=98=E5=89=8D=E7=BC=80=E8=AE=BE=E7=BD=AE=E4=B8=8D=E7=94=9F?= =?UTF-8?q?=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/tasks.py | 1 + apps/notifications/backends/email.py | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/common/tasks.py b/apps/common/tasks.py index ee4880ee7..a3130ead6 100644 --- a/apps/common/tasks.py +++ b/apps/common/tasks.py @@ -49,6 +49,7 @@ def send_mail_attachment_async(subject, message, recipient_list, attachment_list if attachment_list is None: attachment_list = [] from_email = settings.EMAIL_FROM or settings.EMAIL_HOST_USER + subject = (settings.EMAIL_SUBJECT_PREFIX or '') + subject email = EmailMultiAlternatives( subject=subject, body=message, diff --git a/apps/notifications/backends/email.py b/apps/notifications/backends/email.py index 390da151a..443d78391 100644 --- a/apps/notifications/backends/email.py +++ b/apps/notifications/backends/email.py @@ -11,6 +11,7 @@ class Email(BackendBase): def send_msg(self, users, message, subject): from_email = settings.EMAIL_FROM or settings.EMAIL_HOST_USER accounts, __, __ = self.get_accounts(users) + subject = (settings.EMAIL_SUBJECT_PREFIX or '') + subject send_mail(subject, message, from_email, accounts, html_message=message) From a18c97aec0a368d05d1db4eef5d86beda6b8f344 Mon Sep 17 00:00:00 2001 From: halo Date: Mon, 17 Jul 2023 14:54:30 +0800 Subject: [PATCH 136/167] =?UTF-8?q?perf:=20=E5=BC=82=E6=AD=A5=E5=8F=91?= =?UTF-8?q?=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/utils/verify_code.py | 21 +++++++++++---------- apps/notifications/backends/email.py | 5 ++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/apps/common/utils/verify_code.py b/apps/common/utils/verify_code.py index 0dbf810fd..8861cfe75 100644 --- a/apps/common/utils/verify_code.py +++ b/apps/common/utils/verify_code.py @@ -1,15 +1,15 @@ -from django.core.cache import cache -from django.conf import settings -from django.core.mail import send_mail from celery import shared_task - -from common.sdk.sms.exceptions import CodeError, CodeExpired, CodeSendTooFrequently -from common.sdk.sms.endpoint import SMS -from common.exceptions import JMSException -from common.utils.random import random_string -from common.utils import get_logger +from django.conf import settings +from django.core.cache import cache from django.utils.translation import gettext_lazy as _ +from common.exceptions import JMSException +from common.sdk.sms.endpoint import SMS +from common.sdk.sms.exceptions import CodeError, CodeExpired, CodeSendTooFrequently +from common.tasks import send_mail_async +from common.utils import get_logger +from common.utils.random import random_string + logger = get_logger(__file__) @@ -79,7 +79,8 @@ class SendAndVerifyCodeUtil(object): subject = self.other_args.get('subject') message = self.other_args.get('message') from_email = settings.EMAIL_FROM or settings.EMAIL_HOST_USER - send_mail(subject, message, from_email, [self.target], html_message=message) + subject = (settings.EMAIL_SUBJECT_PREFIX or '') + subject + send_mail_async.delay(subject, message, from_email, [self.target], html_message=message) def __send(self, code): """ diff --git a/apps/notifications/backends/email.py b/apps/notifications/backends/email.py index 443d78391..0d8e0ca79 100644 --- a/apps/notifications/backends/email.py +++ b/apps/notifications/backends/email.py @@ -1,6 +1,5 @@ from django.conf import settings -from django.core.mail import send_mail - +from common.tasks import send_mail_async from .base import BackendBase @@ -12,7 +11,7 @@ class Email(BackendBase): from_email = settings.EMAIL_FROM or settings.EMAIL_HOST_USER accounts, __, __ = self.get_accounts(users) subject = (settings.EMAIL_SUBJECT_PREFIX or '') + subject - send_mail(subject, message, from_email, accounts, html_message=message) + send_mail_async.delay(subject, message, from_email, accounts, html_message=message) backend = Email From be17fe6c31e70749097226d0d5b2c48a02caead9 Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 17 Jul 2023 17:08:06 +0800 Subject: [PATCH 137/167] =?UTF-8?q?perf:=20=E9=82=AE=E4=BB=B6=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/notifications/backends/email.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/notifications/backends/email.py b/apps/notifications/backends/email.py index 0d8e0ca79..ee821fbfa 100644 --- a/apps/notifications/backends/email.py +++ b/apps/notifications/backends/email.py @@ -11,7 +11,7 @@ class Email(BackendBase): from_email = settings.EMAIL_FROM or settings.EMAIL_HOST_USER accounts, __, __ = self.get_accounts(users) subject = (settings.EMAIL_SUBJECT_PREFIX or '') + subject - send_mail_async.delay(subject, message, from_email, accounts, html_message=message) + send_mail_async(subject, message, from_email, accounts, html_message=message) backend = Email From 6338ecc6fe986b063c324ba712c8ee5673910fff Mon Sep 17 00:00:00 2001 From: halo Date: Mon, 17 Jul 2023 22:13:58 +0800 Subject: [PATCH 138/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E9=82=AE?= =?UTF-8?q?=E4=BB=B6=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/utils/verify_code.py | 4 +--- apps/notifications/backends/email.py | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/apps/common/utils/verify_code.py b/apps/common/utils/verify_code.py index 8861cfe75..acd547296 100644 --- a/apps/common/utils/verify_code.py +++ b/apps/common/utils/verify_code.py @@ -78,9 +78,7 @@ class SendAndVerifyCodeUtil(object): def __send_with_email(self): subject = self.other_args.get('subject') message = self.other_args.get('message') - from_email = settings.EMAIL_FROM or settings.EMAIL_HOST_USER - subject = (settings.EMAIL_SUBJECT_PREFIX or '') + subject - send_mail_async.delay(subject, message, from_email, [self.target], html_message=message) + send_mail_async(subject, message, [self.target], html_message=message) def __send(self, code): """ diff --git a/apps/notifications/backends/email.py b/apps/notifications/backends/email.py index ee821fbfa..034557f8a 100644 --- a/apps/notifications/backends/email.py +++ b/apps/notifications/backends/email.py @@ -1,4 +1,3 @@ -from django.conf import settings from common.tasks import send_mail_async from .base import BackendBase @@ -8,10 +7,8 @@ class Email(BackendBase): is_enable_field_in_settings = 'EMAIL_HOST_USER' def send_msg(self, users, message, subject): - from_email = settings.EMAIL_FROM or settings.EMAIL_HOST_USER accounts, __, __ = self.get_accounts(users) - subject = (settings.EMAIL_SUBJECT_PREFIX or '') + subject - send_mail_async(subject, message, from_email, accounts, html_message=message) + send_mail_async(subject, message, accounts, html_message=message) backend = Email From ea5a54f9c7c095da1deca933042e4afb577bb73e Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 18 Jul 2023 15:19:54 +0800 Subject: [PATCH 139/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E5=91=8A=E8=AD=A6=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/notifications.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/terminal/notifications.py b/apps/terminal/notifications.py index bd036d9bb..77d113423 100644 --- a/apps/terminal/notifications.py +++ b/apps/terminal/notifications.py @@ -83,7 +83,7 @@ class CommandWarningMessage(CommandAlertMixin, UserMessage): user_id = command.get('_user_id', '') asset = command['asset'] asset_id = command.get('_asset_id', '') - account = command['_account'] + account = command.get('_account', '') account_id = command.get('_account_id', '') cmd_acl = command.get('_cmd_filter_acl') cmd_group = command.get('_cmd_group') From de5b501ebf9ca5b66fd5aaaf3141b69739cb5fa0 Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Tue, 18 Jul 2023 05:52:27 -0300 Subject: [PATCH 140/167] =?UTF-8?q?fix:=20=E5=B7=A5=E5=8D=95=E6=97=B6?= =?UTF-8?q?=E5=8C=BA=E9=94=99=E4=B9=B1=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/tickets/serializers/ticket/common.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/tickets/serializers/ticket/common.py b/apps/tickets/serializers/ticket/common.py index 1af361693..8ec463337 100644 --- a/apps/tickets/serializers/ticket/common.py +++ b/apps/tickets/serializers/ticket/common.py @@ -67,8 +67,6 @@ class BaseApplyAssetSerializer(serializers.Serializer): error = _('The expiration date should be greater than the start date') raise serializers.ValidationError({'apply_date_expired': error}) - attrs['apply_date_start'] = apply_date_start - attrs['apply_date_expired'] = apply_date_expired return attrs @atomic From 8ed3da85f2ae5e6a7f6770c11b0436415989d552 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 18 Jul 2023 18:05:45 +0800 Subject: [PATCH 141/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E6=89=A7=E8=A1=8C=E5=91=BD=E4=BB=A4=E6=97=B6=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E5=90=8D=E7=A7=B0=E5=8C=85=E5=90=AB=20[=20=E7=89=B9?= =?UTF-8?q?=E6=AE=8A=E5=AD=97=E7=AC=A6=E6=89=A7=E8=A1=8C=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98(issue:=2010986)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/ansible/inventory.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index 52f93e2b2..9c0d03849 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -268,6 +268,7 @@ class JMSInventory: data = {'all': {'hosts': {}}} for host in hosts: name = host.pop('name') + name = name.replace('[', '_').replace(']', '_') data['all']['hosts'][name] = host if self.exclude_localhost and data['all']['hosts'].__contains__('localhost'): data['all']['hosts'].update({'localhost': {'ansible_host': '255.255.255.255'}}) From 02d0c7e4e78a72414bc01fb7d243398311d61be4 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 18 Jul 2023 18:55:18 +0800 Subject: [PATCH 142/167] =?UTF-8?q?perf:=20ansible=20=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E4=BC=98=E5=8C=96=20(#11005)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/ops/ansible/callback.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ops/ansible/callback.py b/apps/ops/ansible/callback.py index 1ba87f575..d5fb3a35e 100644 --- a/apps/ops/ansible/callback.py +++ b/apps/ops/ansible/callback.py @@ -120,7 +120,7 @@ class DefaultCallback: for host, tasks in self.result.get('ignored', {}).items(): ignore_errors = reduce(error_func, tasks.items(), '').strip(';') if host in failures: - self.summary['failures'][host] += {ignore_errors} + self.summary['failures'][host] += ignore_errors self.summary['ok'] = list(set(self.result['ok'].keys()) - set(dark_or_failures)) self.summary['skipped'] = list(set(self.result['skipped'].keys()) - set(dark_or_failures)) From aa744c0fec747e97ace2c41e114347f3ebc4f1df Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 19 Jul 2023 10:33:12 +0800 Subject: [PATCH 143/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E6=A8=A1=E7=89=88=E5=88=87=E6=8D=A2=E6=97=B6=E6=8A=A5?= =?UTF-8?q?=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/models/account.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/accounts/models/account.py b/apps/accounts/models/account.py index 893fcccb4..5130a59c0 100644 --- a/apps/accounts/models/account.py +++ b/apps/accounts/models/account.py @@ -140,7 +140,10 @@ class AccountTemplate(BaseAccount): def get_su_from_account_templates(cls, pk=None): if pk is None: return cls.objects.all() - return cls.objects.exclude(Q(id=pk) | Q(_id=pk)) + return cls.objects.exclude(Q(id=pk) | Q(su_from_id=pk)) + + def __str__(self): + return f'{self.name}({self.username})' def get_su_from_account(self, asset): su_from = self.su_from From 02fc9a730b7e237381563af637c92c7f106860d5 Mon Sep 17 00:00:00 2001 From: "fangfang.dong" Date: Wed, 19 Jul 2023 10:11:47 +0800 Subject: [PATCH 144/167] =?UTF-8?q?feat:=20=E5=BF=AB=E9=80=9F=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E6=96=B0=E5=A2=9E=E5=91=8A=E8=AD=A6=E7=BA=A7=E5=88=AB?= =?UTF-8?q?:=20Warning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.po | 238 +++++++++--------- apps/locale/zh/LC_MESSAGES/django.po | 238 +++++++++--------- apps/ops/models/job.py | 24 +- apps/terminal/api/session/command.py | 5 +- apps/terminal/const.py | 5 + apps/terminal/notifications.py | 7 +- .../terminal/_msg_command_warning.html | 28 ++- 7 files changed, 302 insertions(+), 243 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index f0909dc3c..8d6cba4c3 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-17 17:12+0800\n" +"POT-Creation-Date: 2023-07-19 09:58+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -194,14 +194,15 @@ msgstr "作成のみ" #: accounts/serializers/account/gathered_account.py:10 #: accounts/serializers/automations/change_secret.py:112 #: accounts/serializers/automations/change_secret.py:132 -#: acls/serializers/base.py:119 assets/models/asset/common.py:93 +#: acls/serializers/base.py:123 assets/models/asset/common.py:93 #: assets/models/asset/common.py:331 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:53 authentication/models/connection_token.py:36 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 #: terminal/backends/command/models.py:18 terminal/models/session/session.py:31 -#: terminal/notifications.py:147 terminal/serializers/command.py:18 -#: terminal/templates/terminal/_msg_command_warning.html:39 +#: terminal/notifications.py:179 terminal/serializers/command.py:18 +#: terminal/templates/terminal/_msg_command_warning.html:36 +#: terminal/templates/terminal/_msg_command_warning.html:82 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "資産" @@ -231,11 +232,12 @@ msgstr "ソース ID" #: accounts/models/account.py:61 #: accounts/serializers/automations/change_secret.py:113 #: accounts/serializers/automations/change_secret.py:133 -#: acls/serializers/base.py:120 assets/serializers/asset/common.py:125 +#: acls/serializers/base.py:124 assets/serializers/asset/common.py:125 #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 #: terminal/backends/command/models.py:19 terminal/models/session/session.py:33 -#: terminal/templates/terminal/_msg_command_warning.html:45 +#: terminal/templates/terminal/_msg_command_warning.html:42 +#: terminal/templates/terminal/_msg_command_warning.html:83 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "アカウント" @@ -286,7 +288,7 @@ msgstr "アカウントバックアップ計画" #: accounts/models/automations/backup_account.py:83 #: assets/models/automations/base.py:115 audits/models.py:60 -#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:192 +#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:194 #: ops/templates/ops/celery_task_log.html:75 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:137 #: terminal/models/session/session.py:44 @@ -410,7 +412,7 @@ msgstr "開始日" #: accounts/models/automations/change_secret.py:91 #: assets/models/automations/base.py:116 ops/models/base.py:56 -#: ops/models/celery.py:64 ops/models/job.py:193 +#: ops/models/celery.py:64 ops/models/job.py:195 #: terminal/models/applet/host.py:138 msgid "Date finished" msgstr "終了日" @@ -436,7 +438,7 @@ msgstr "最終ログイン日" #: accounts/models/automations/gather_account.py:17 #: accounts/models/automations/push_account.py:15 accounts/models/base.py:34 -#: acls/serializers/base.py:18 acls/serializers/base.py:49 +#: acls/serializers/base.py:19 acls/serializers/base.py:50 #: assets/models/_user.py:23 audits/models.py:179 authentication/forms.py:25 #: authentication/forms.py:27 authentication/models/temp_token.py:9 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -468,8 +470,8 @@ msgstr "アカウントのコレクション" msgid "Triggers" msgstr "トリガー方式" -#: accounts/models/automations/push_account.py:16 acls/models/base.py:48 -#: acls/serializers/base.py:56 assets/models/cmd_filter.py:81 +#: accounts/models/automations/push_account.py:16 acls/models/base.py:41 +#: acls/serializers/base.py:57 assets/models/cmd_filter.py:81 #: audits/models.py:87 audits/serializers.py:82 #: authentication/serializers/connect_token_secret.py:116 #: authentication/templates/authentication/_access_key_modal.html:34 @@ -484,8 +486,8 @@ msgstr "アカウントプッシュ" msgid "Verify asset account" msgstr "アカウントの確認" -#: accounts/models/base.py:33 acls/models/base.py:42 acls/models/base.py:103 -#: acls/models/command_acl.py:21 acls/serializers/base.py:34 +#: accounts/models/base.py:33 acls/models/base.py:35 acls/models/base.py:96 +#: acls/models/command_acl.py:21 acls/serializers/base.py:35 #: applications/models.py:9 assets/models/_user.py:22 #: assets/models/asset/common.py:91 assets/models/asset/common.py:149 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 @@ -495,7 +497,7 @@ msgstr "アカウントの確認" #: assets/serializers/platform.py:209 #: authentication/serializers/connect_token_secret.py:110 ops/mixin.py:21 #: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:92 ops/models/playbook.py:23 ops/serializers/job.py:20 +#: ops/models/job.py:94 ops/models/playbook.py:23 ops/serializers/job.py:20 #: orgs/models.py:80 perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 #: terminal/models/applet/applet.py:32 terminal/models/component/endpoint.py:12 @@ -585,7 +587,7 @@ msgstr "カテゴリ" #: assets/models/cmd_filter.py:74 assets/models/platform.py:90 #: assets/serializers/asset/common.py:122 assets/serializers/platform.py:111 #: assets/serializers/platform.py:126 audits/serializers.py:48 -#: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:103 +#: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:105 #: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:38 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29 @@ -618,10 +620,10 @@ msgid "Changed" msgstr "編集済み" #: accounts/serializers/account/account.py:250 -#: accounts/serializers/automations/base.py:22 acls/models/base.py:104 +#: accounts/serializers/automations/base.py:22 acls/models/base.py:97 #: assets/models/automations/base.py:19 #: assets/serializers/automations/base.py:20 ops/models/base.py:17 -#: ops/models/job.py:105 ops/serializers/job.py:21 +#: ops/models/job.py:107 ops/serializers/job.py:21 #: terminal/templates/terminal/_msg_command_execute_alert.html:16 msgid "Assets" msgstr "資産" @@ -646,7 +648,7 @@ msgstr "アカウントはすでに存在しています" msgid "ID" msgstr "ID" -#: accounts/serializers/account/account.py:427 acls/serializers/base.py:112 +#: accounts/serializers/account/account.py:427 acls/serializers/base.py:116 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:49 #: audits/models.py:85 audits/models.py:163 #: authentication/models/connection_token.py:32 @@ -656,9 +658,10 @@ msgstr "ID" #: perms/serializers/permission.py:30 rbac/builtin.py:123 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:17 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:148 terminal/notifications.py:196 +#: terminal/notifications.py:180 terminal/notifications.py:228 #: terminal/serializers/command.py:17 -#: terminal/templates/terminal/_msg_command_warning.html:33 +#: terminal/templates/terminal/_msg_command_warning.html:30 +#: terminal/templates/terminal/_msg_command_warning.html:81 #: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:947 #: users/models/user.py:978 users/serializers/group.py:18 msgid "User" @@ -666,7 +669,7 @@ msgstr "ユーザー" #: accounts/serializers/account/account.py:428 #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:150 terminal/notifications.py:198 +#: terminal/notifications.py:182 terminal/notifications.py:230 msgid "Date" msgstr "日付" @@ -794,39 +797,39 @@ msgstr "秘密鍵が無効またはpassphraseエラー" msgid "Acls" msgstr "Acls" -#: acls/models/base.py:21 terminal/const.py:11 tickets/const.py:45 +#: acls/const.py:6 terminal/const.py:11 tickets/const.py:45 #: tickets/templates/tickets/approve_check_password.html:49 msgid "Reject" msgstr "拒否" -#: acls/models/base.py:22 terminal/const.py:9 +#: acls/const.py:7 terminal/const.py:9 msgid "Accept" msgstr "受け入れられる" -#: acls/models/base.py:23 +#: acls/const.py:8 msgid "Review" msgstr "レビュー担当者" -#: acls/models/base.py:24 terminal/const.py:10 +#: acls/const.py:9 terminal/const.py:10 msgid "Warning" msgstr "警告" -#: acls/models/base.py:44 assets/models/_user.py:51 +#: acls/models/base.py:37 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:93 msgid "Priority" msgstr "優先順位" -#: acls/models/base.py:45 assets/models/_user.py:51 +#: acls/models/base.py:38 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:94 msgid "1-100, the lower the value will be match first" msgstr "1-100、低い値は最初に一致します" -#: acls/models/base.py:49 assets/models/cmd_filter.py:86 +#: acls/models/base.py:42 assets/models/cmd_filter.py:86 #: authentication/serializers/connect_token_secret.py:88 msgid "Reviewers" msgstr "レビュー担当者" -#: acls/models/base.py:50 authentication/models/access_key.py:17 +#: acls/models/base.py:43 authentication/models/access_key.py:17 #: authentication/models/connection_token.py:53 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/asset_permission.py:76 terminal/models/session/sharing.py:27 @@ -834,11 +837,11 @@ msgstr "レビュー担当者" msgid "Active" msgstr "アクティブ" -#: acls/models/base.py:88 users/apps.py:9 +#: acls/models/base.py:81 users/apps.py:9 msgid "Users" msgstr "ユーザー" -#: acls/models/base.py:105 assets/models/automations/base.py:17 +#: acls/models/base.py:98 assets/models/automations/base.py:17 #: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:305 #: rbac/tree.py:35 msgid "Accounts" @@ -849,7 +852,8 @@ msgstr "アカウント" #: terminal/models/session/session.py:42 terminal/serializers/command.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:51 +#: terminal/templates/terminal/_msg_command_warning.html:48 +#: terminal/templates/terminal/_msg_command_warning.html:90 msgid "Command" msgstr "コマンド" @@ -881,7 +885,8 @@ msgid "The generated regular expression is incorrect: {}" msgstr "生成された正規表現が正しくありません: {}" #: acls/models/command_acl.py:100 -#: terminal/templates/terminal/_msg_command_warning.html:57 +#: terminal/templates/terminal/_msg_command_warning.html:54 +#: terminal/templates/terminal/_msg_command_warning.html:92 msgid "Command acl" msgstr "コマンドフィルタリング" @@ -918,11 +923,11 @@ msgstr "ログインasset acl" msgid "Login asset confirm" msgstr "ログイン資産の確認" -#: acls/serializers/base.py:10 acls/serializers/login_acl.py:11 +#: acls/serializers/base.py:11 acls/serializers/login_acl.py:11 msgid "With * indicating a match all. " msgstr "* はすべて一致することを示します。" -#: acls/serializers/base.py:25 +#: acls/serializers/base.py:26 msgid "" "With * indicating a match all. Such as: 192.168.10.1, 192.168.1.0/24, " "10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 (Domain name " @@ -932,19 +937,19 @@ msgstr "" "10.1.1.1-10.1.1.20、2001:db8:2de::e13、2001:db8:1a:1110:::/64 (ドメイン名サ" "ポート)" -#: acls/serializers/base.py:40 assets/serializers/asset/host.py:19 +#: acls/serializers/base.py:41 assets/serializers/asset/host.py:19 msgid "IP/Host" msgstr "IP/ホスト" -#: acls/serializers/base.py:87 +#: acls/serializers/base.py:91 msgid "Recipients" msgstr "受信者" -#: acls/serializers/base.py:99 tickets/serializers/ticket/ticket.py:77 +#: acls/serializers/base.py:103 tickets/serializers/ticket/ticket.py:77 msgid "The organization `{}` does not exist" msgstr "組織 '{}'は存在しません" -#: acls/serializers/base.py:105 +#: acls/serializers/base.py:109 msgid "None of the reviewers belong to Organization `{}`" msgstr "いずれのレビューアも組織 '{}' に属していません" @@ -990,7 +995,7 @@ msgstr "アプリケーション" msgid "Can match application" msgstr "アプリケーションを一致させることができます" -#: assets/api/asset/asset.py:153 +#: assets/api/asset/asset.py:157 msgid "Cannot create asset directly, you should create a host or other" msgstr "" "資産を直接作成することはできません。ホストまたはその他を作成する必要がありま" @@ -1235,7 +1240,7 @@ msgstr "SSHパブリックキー" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:20 -#: common/db/models.py:36 ops/models/adhoc.py:27 ops/models/job.py:111 +#: common/db/models.py:36 ops/models/adhoc.py:27 ops/models/job.py:113 #: ops/models/playbook.py:26 rbac/models/role.py:37 settings/models.py:38 #: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:248 #: terminal/models/applet/host.py:139 terminal/models/component/endpoint.py:24 @@ -1248,7 +1253,7 @@ msgstr "コメント" #: assets/models/_user.py:28 assets/models/automations/base.py:114 #: assets/models/cmd_filter.py:41 assets/models/group.py:19 -#: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:191 +#: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:193 #: users/models/user.py:979 msgid "Date created" msgstr "作成された日付" @@ -1416,7 +1421,7 @@ msgstr "証明書チェックを無視" msgid "Proxy" msgstr "プロキシー" -#: assets/models/automations/base.py:22 ops/models/job.py:187 +#: assets/models/automations/base.py:22 ops/models/job.py:189 #: settings/serializers/auth/sms.py:99 msgid "Parameters" msgstr "パラメータ" @@ -1430,7 +1435,7 @@ msgid "Asset automation task" msgstr "アセットの自動化タスク" #: assets/models/automations/base.py:113 audits/models.py:199 -#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:184 +#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:186 #: terminal/models/applet/applet.py:247 terminal/models/applet/host.py:136 #: terminal/models/component/status.py:30 terminal/serializers/applet.py:18 #: terminal/serializers/applet_host.py:107 tickets/models/ticket/general.py:283 @@ -1992,7 +1997,8 @@ msgid "Rename dir" msgstr "マップディレクトリ" #: audits/const.py:23 rbac/tree.py:229 -#: terminal/templates/terminal/_msg_command_warning.html:71 +#: terminal/templates/terminal/_msg_command_warning.html:68 +#: terminal/templates/terminal/_msg_command_warning.html:96 msgid "View" msgstr "表示" @@ -2076,7 +2082,8 @@ msgstr "書類" #: terminal/models/session/replay.py:9 terminal/models/session/sharing.py:18 #: terminal/models/session/sharing.py:81 #: terminal/templates/terminal/_msg_command_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:69 +#: terminal/templates/terminal/_msg_command_warning.html:66 +#: terminal/templates/terminal/_msg_command_warning.html:95 #: tickets/models/ticket/command_confirm.py:15 msgid "Session" msgstr "セッション" @@ -2265,16 +2272,16 @@ msgstr "ACL アクションはレビューです" msgid "Current user not support mfa type: {}" msgstr "現在のユーザーはmfaタイプをサポートしていません: {}" -#: authentication/api/password.py:31 terminal/api/session/session.py:259 +#: authentication/api/password.py:32 terminal/api/session/session.py:259 #: users/views/profile/reset.py:44 msgid "User does not exist: {}" msgstr "ユーザーが存在しない: {}" -#: authentication/api/password.py:31 users/views/profile/reset.py:127 +#: authentication/api/password.py:32 users/views/profile/reset.py:127 msgid "No user matched" msgstr "ユーザーにマッチしなかった" -#: authentication/api/password.py:35 +#: authentication/api/password.py:36 msgid "" "The user is from {}, please go to the corresponding system to change the " "password" @@ -2282,7 +2289,7 @@ msgstr "" "ユーザーは {}からです。対応するシステムにアクセスしてパスワードを変更してくだ" "さい。" -#: authentication/api/password.py:59 +#: authentication/api/password.py:60 #: authentication/templates/authentication/login.html:305 #: users/templates/users/forgot_password.html:27 #: users/templates/users/forgot_password.html:28 @@ -2618,7 +2625,7 @@ msgstr "電話番号を設定して有効にする" msgid "Clear phone number to disable" msgstr "無効にする電話番号をクリアする" -#: authentication/middleware.py:93 settings/utils/ldap.py:657 +#: authentication/middleware.py:93 settings/utils/ldap.py:661 msgid "Authentication failed (before login check failed): {}" msgstr "認証に失敗しました (ログインチェックが失敗する前): {}" @@ -2877,7 +2884,7 @@ msgstr "コードエラー" #: authentication/templates/authentication/_msg_reset_password_code.html:9 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:426 +#: jumpserver/conf.py:427 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -3471,11 +3478,11 @@ msgstr "検索のエクスポート: %s" msgid "User %s view/export secret" msgstr "ユーザー %s がパスワードを閲覧/導き出しました" -#: jumpserver/conf.py:425 +#: jumpserver/conf.py:426 msgid "Create account successfully" msgstr "アカウントを正常に作成" -#: jumpserver/conf.py:427 +#: jumpserver/conf.py:428 msgid "Your account has been created successfully" msgstr "アカウントが正常に作成されました" @@ -3615,7 +3622,7 @@ msgstr "VCS" msgid "Adhoc" msgstr "コマンド#コマンド#" -#: ops/const.py:39 ops/models/job.py:101 +#: ops/const.py:39 ops/models/job.py:103 msgid "Playbook" msgstr "Playbook" @@ -3672,17 +3679,17 @@ msgstr "定期的または定期的に設定を行う必要があります" msgid "Pattern" msgstr "パターン" -#: ops/models/adhoc.py:24 ops/models/job.py:96 +#: ops/models/adhoc.py:24 ops/models/job.py:98 msgid "Module" msgstr "モジュール" -#: ops/models/adhoc.py:25 ops/models/celery.py:58 ops/models/job.py:95 +#: ops/models/adhoc.py:25 ops/models/celery.py:58 ops/models/job.py:97 #: terminal/models/component/task.py:16 msgid "Args" msgstr "アルグ" #: ops/models/adhoc.py:26 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:104 ops/models/job.py:190 ops/models/playbook.py:25 +#: ops/models/job.py:106 ops/models/job.py:192 ops/models/playbook.py:25 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "作成者" @@ -3699,12 +3706,12 @@ msgstr "最後の実行" msgid "Date last run" msgstr "最終実行日" -#: ops/models/base.py:51 ops/models/job.py:188 +#: ops/models/base.py:51 ops/models/job.py:190 #: xpack/plugins/cloud/models.py:162 msgid "Result" msgstr "結果" -#: ops/models/base.py:52 ops/models/job.py:189 +#: ops/models/base.py:52 ops/models/job.py:191 msgid "Summary" msgstr "概要" @@ -3737,43 +3744,43 @@ msgstr "発売日" msgid "Celery Task Execution" msgstr "Celery タスク実行" -#: ops/models/job.py:98 +#: ops/models/job.py:100 msgid "Chdir" msgstr "実行ディレクトリ" -#: ops/models/job.py:99 +#: ops/models/job.py:101 msgid "Timeout (Seconds)" msgstr "タイムアウト(秒)" -#: ops/models/job.py:106 +#: ops/models/job.py:108 msgid "Use Parameter Define" msgstr "パラメータ定義を使用する" -#: ops/models/job.py:107 +#: ops/models/job.py:109 msgid "Parameters define" msgstr "パラメータ定義" -#: ops/models/job.py:108 +#: ops/models/job.py:110 msgid "Runas" msgstr "ユーザーとして実行" -#: ops/models/job.py:110 +#: ops/models/job.py:112 msgid "Runas policy" msgstr "ユーザー ポリシー" -#: ops/models/job.py:172 +#: ops/models/job.py:174 msgid "Job" msgstr "ジョブ#ジョブ#" -#: ops/models/job.py:195 +#: ops/models/job.py:197 msgid "Material" msgstr "Material" -#: ops/models/job.py:197 +#: ops/models/job.py:199 msgid "Material Type" msgstr "Material を選択してオプションを設定します。" -#: ops/models/job.py:461 +#: ops/models/job.py:482 msgid "Job Execution" msgstr "ジョブ実行" @@ -3919,7 +3926,8 @@ msgstr "アプリ組織" #: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:89 #: rbac/const.py:7 rbac/models/rolebinding.py:56 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:63 -#: terminal/templates/terminal/_msg_command_warning.html:75 +#: terminal/templates/terminal/_msg_command_warning.html:72 +#: terminal/templates/terminal/_msg_command_warning.html:98 #: tickets/models/ticket/general.py:302 tickets/serializers/ticket/ticket.py:60 msgid "Organization" msgstr "組織" @@ -5361,100 +5369,100 @@ msgstr "LDAP ユーザーを定期的にインポートする" msgid "Registration periodic import ldap user task" msgstr "登録サイクルLDAPユーザータスクのインポート" -#: settings/utils/ldap.py:472 +#: settings/utils/ldap.py:476 msgid "ldap:// or ldaps:// protocol is used." msgstr "ldap:// または ldaps:// プロトコルが使用されます。" -#: settings/utils/ldap.py:483 +#: settings/utils/ldap.py:487 msgid "Host or port is disconnected: {}" msgstr "ホストまたはポートが切断されました: {}" -#: settings/utils/ldap.py:485 +#: settings/utils/ldap.py:489 msgid "The port is not the port of the LDAP service: {}" msgstr "ポートはLDAPサービスのポートではありません: {}" -#: settings/utils/ldap.py:487 +#: settings/utils/ldap.py:491 msgid "Please add certificate: {}" msgstr "証明書を追加してください: {}" -#: settings/utils/ldap.py:491 settings/utils/ldap.py:518 -#: settings/utils/ldap.py:548 settings/utils/ldap.py:576 +#: settings/utils/ldap.py:495 settings/utils/ldap.py:522 +#: settings/utils/ldap.py:552 settings/utils/ldap.py:580 msgid "Unknown error: {}" msgstr "不明なエラー: {}" -#: settings/utils/ldap.py:505 +#: settings/utils/ldap.py:509 msgid "Bind DN or Password incorrect" msgstr "DNまたはパスワードのバインドが正しくありません" -#: settings/utils/ldap.py:512 +#: settings/utils/ldap.py:516 msgid "Please enter Bind DN: {}" msgstr "バインドDN: {} を入力してください" -#: settings/utils/ldap.py:514 +#: settings/utils/ldap.py:518 msgid "Please enter Password: {}" msgstr "パスワードを入力してください: {}" -#: settings/utils/ldap.py:516 +#: settings/utils/ldap.py:520 msgid "Please enter correct Bind DN and Password: {}" msgstr "正しいバインドDNとパスワードを入力してください: {}" -#: settings/utils/ldap.py:534 +#: settings/utils/ldap.py:538 msgid "Invalid User OU or User search filter: {}" msgstr "無効なユーザー OU またはユーザー検索フィルター: {}" -#: settings/utils/ldap.py:565 +#: settings/utils/ldap.py:569 msgid "LDAP User attr map not include: {}" msgstr "LDAP ユーザーattrマップは含まれません: {}" -#: settings/utils/ldap.py:572 +#: settings/utils/ldap.py:576 msgid "LDAP User attr map is not dict" msgstr "LDAPユーザーattrマップはdictではありません" -#: settings/utils/ldap.py:591 +#: settings/utils/ldap.py:595 msgid "LDAP authentication is not enabled" msgstr "LDAP 認証が有効になっていない" -#: settings/utils/ldap.py:609 +#: settings/utils/ldap.py:613 msgid "Error (Invalid LDAP server): {}" msgstr "エラー (LDAPサーバーが無効): {}" -#: settings/utils/ldap.py:611 +#: settings/utils/ldap.py:615 msgid "Error (Invalid Bind DN): {}" msgstr "エラー (DNのバインドが無効): {}" -#: settings/utils/ldap.py:613 +#: settings/utils/ldap.py:617 msgid "Error (Invalid LDAP User attr map): {}" msgstr "エラー (LDAPユーザーattrマップが無効): {}" -#: settings/utils/ldap.py:615 +#: settings/utils/ldap.py:619 msgid "Error (Invalid User OU or User search filter): {}" msgstr "エラー (ユーザーOUまたはユーザー検索フィルターが無効): {}" -#: settings/utils/ldap.py:617 +#: settings/utils/ldap.py:621 msgid "Error (Not enabled LDAP authentication): {}" msgstr "エラー (LDAP認証が有効化されていません): {}" -#: settings/utils/ldap.py:619 +#: settings/utils/ldap.py:623 msgid "Error (Unknown): {}" msgstr "エラー (不明): {}" -#: settings/utils/ldap.py:622 +#: settings/utils/ldap.py:626 msgid "Succeed: Match {} s user" msgstr "成功: {} 人のユーザーに一致" -#: settings/utils/ldap.py:655 +#: settings/utils/ldap.py:659 msgid "Authentication failed (configuration incorrect): {}" msgstr "認証に失敗しました (設定が正しくありません): {}" -#: settings/utils/ldap.py:659 +#: settings/utils/ldap.py:663 msgid "Authentication failed (username or password incorrect): {}" msgstr "認証に失敗しました (ユーザー名またはパスワードが正しくありません): {}" -#: settings/utils/ldap.py:661 +#: settings/utils/ldap.py:665 msgid "Authentication failed (Unknown): {}" msgstr "認証に失敗しました (不明): {}" -#: settings/utils/ldap.py:664 +#: settings/utils/ldap.py:668 msgid "Authentication success: {}" msgstr "認証成功: {}" @@ -5695,7 +5703,7 @@ msgstr "テスト失敗: {}" msgid "Test successful" msgstr "テスト成功" -#: terminal/api/component/storage.py:124 terminal/notifications.py:231 +#: terminal/api/component/storage.py:124 terminal/notifications.py:263 #: terminal/tasks.py:144 msgid "Test failure: Account invalid" msgstr "テスト失敗: アカウントが無効" @@ -5733,6 +5741,7 @@ msgid "Output" msgstr "出力" #: terminal/backends/command/models.py:25 terminal/serializers/command.py:23 +#: terminal/templates/terminal/_msg_command_warning.html:91 msgid "Risk level" msgstr "リスクレベル" @@ -6077,36 +6086,35 @@ msgstr "検証コードが無効" msgid "You have already joined this session" msgstr "すでにこのセッションに参加しています" -#: terminal/notifications.py:22 +#: terminal/notifications.py:24 msgid "Sessions" msgstr "セッション" -#: terminal/notifications.py:69 -#: terminal/templates/terminal/_msg_command_warning.html:5 -msgid "Danger command warning" -msgstr "危険コマンドアラート" +#: terminal/notifications.py:71 +msgid "Command warning" +msgstr "コマンド警告" -#: terminal/notifications.py:122 -msgid "Danger command alert" -msgstr "危険コマンドアラート" +#: terminal/notifications.py:154 +msgid "Command reject" +msgstr "コマンド拒否" -#: terminal/notifications.py:149 terminal/notifications.py:197 +#: terminal/notifications.py:181 terminal/notifications.py:229 msgid "Level" msgstr "レベル" -#: terminal/notifications.py:167 +#: terminal/notifications.py:199 msgid "Batch danger command alert" msgstr "一括危険コマンド警告" -#: terminal/notifications.py:215 +#: terminal/notifications.py:247 msgid "Command and replay storage" msgstr "コマンド及び録画記憶" -#: terminal/notifications.py:216 +#: terminal/notifications.py:248 msgid "Connectivity alarm" msgstr "接続性アラーム" -#: terminal/notifications.py:241 +#: terminal/notifications.py:273 #: terminal/templates/terminal/_msg_check_command_replay_storage_connectivity.html:4 msgid "Invalid storage" msgstr "無効なストレージ" @@ -6383,15 +6391,16 @@ msgstr "チェックコマンドと録画ストレージの接続性" msgid "view" msgstr "表示" -#: terminal/templates/terminal/_msg_command_warning.html:21 +#: terminal/templates/terminal/_msg_command_warning.html:18 msgid "Item" msgstr "アイテム" -#: terminal/templates/terminal/_msg_command_warning.html:25 +#: terminal/templates/terminal/_msg_command_warning.html:22 msgid "Url" msgstr "リンク" -#: terminal/templates/terminal/_msg_command_warning.html:63 +#: terminal/templates/terminal/_msg_command_warning.html:60 +#: terminal/templates/terminal/_msg_command_warning.html:93 msgid "Command acl group" msgstr "コマンドフィルタリンググループ" @@ -7887,3 +7896,6 @@ msgstr "究極のエディション" #: xpack/plugins/license/models.py:86 msgid "Community edition" msgstr "コミュニティ版" + +#~ msgid "Danger command alert" +#~ msgstr "危険コマンドアラート" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index bd56a7e31..2938bb022 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-17 17:12+0800\n" +"POT-Creation-Date: 2023-07-19 10:00+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -193,14 +193,15 @@ msgstr "仅创建" #: accounts/serializers/account/gathered_account.py:10 #: accounts/serializers/automations/change_secret.py:112 #: accounts/serializers/automations/change_secret.py:132 -#: acls/serializers/base.py:119 assets/models/asset/common.py:93 +#: acls/serializers/base.py:123 assets/models/asset/common.py:93 #: assets/models/asset/common.py:331 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:53 authentication/models/connection_token.py:36 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 #: terminal/backends/command/models.py:18 terminal/models/session/session.py:31 -#: terminal/notifications.py:147 terminal/serializers/command.py:18 -#: terminal/templates/terminal/_msg_command_warning.html:39 +#: terminal/notifications.py:179 terminal/serializers/command.py:18 +#: terminal/templates/terminal/_msg_command_warning.html:36 +#: terminal/templates/terminal/_msg_command_warning.html:82 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "资产" @@ -230,11 +231,12 @@ msgstr "来源 ID" #: accounts/models/account.py:61 #: accounts/serializers/automations/change_secret.py:113 #: accounts/serializers/automations/change_secret.py:133 -#: acls/serializers/base.py:120 assets/serializers/asset/common.py:125 +#: acls/serializers/base.py:124 assets/serializers/asset/common.py:125 #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 #: terminal/backends/command/models.py:19 terminal/models/session/session.py:33 -#: terminal/templates/terminal/_msg_command_warning.html:45 +#: terminal/templates/terminal/_msg_command_warning.html:42 +#: terminal/templates/terminal/_msg_command_warning.html:83 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "账号" @@ -285,7 +287,7 @@ msgstr "账号备份计划" #: accounts/models/automations/backup_account.py:83 #: assets/models/automations/base.py:115 audits/models.py:60 -#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:192 +#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:194 #: ops/templates/ops/celery_task_log.html:75 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:137 #: terminal/models/session/session.py:44 @@ -409,7 +411,7 @@ msgstr "开始日期" #: accounts/models/automations/change_secret.py:91 #: assets/models/automations/base.py:116 ops/models/base.py:56 -#: ops/models/celery.py:64 ops/models/job.py:193 +#: ops/models/celery.py:64 ops/models/job.py:195 #: terminal/models/applet/host.py:138 msgid "Date finished" msgstr "结束日期" @@ -435,7 +437,7 @@ msgstr "最后登录日期" #: accounts/models/automations/gather_account.py:17 #: accounts/models/automations/push_account.py:15 accounts/models/base.py:34 -#: acls/serializers/base.py:18 acls/serializers/base.py:49 +#: acls/serializers/base.py:19 acls/serializers/base.py:50 #: assets/models/_user.py:23 audits/models.py:179 authentication/forms.py:25 #: authentication/forms.py:27 authentication/models/temp_token.py:9 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -467,8 +469,8 @@ msgstr "收集账号" msgid "Triggers" msgstr "触发方式" -#: accounts/models/automations/push_account.py:16 acls/models/base.py:48 -#: acls/serializers/base.py:56 assets/models/cmd_filter.py:81 +#: accounts/models/automations/push_account.py:16 acls/models/base.py:41 +#: acls/serializers/base.py:57 assets/models/cmd_filter.py:81 #: audits/models.py:87 audits/serializers.py:82 #: authentication/serializers/connect_token_secret.py:116 #: authentication/templates/authentication/_access_key_modal.html:34 @@ -483,8 +485,8 @@ msgstr "账号推送" msgid "Verify asset account" msgstr "账号验证" -#: accounts/models/base.py:33 acls/models/base.py:42 acls/models/base.py:103 -#: acls/models/command_acl.py:21 acls/serializers/base.py:34 +#: accounts/models/base.py:33 acls/models/base.py:35 acls/models/base.py:96 +#: acls/models/command_acl.py:21 acls/serializers/base.py:35 #: applications/models.py:9 assets/models/_user.py:22 #: assets/models/asset/common.py:91 assets/models/asset/common.py:149 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 @@ -494,7 +496,7 @@ msgstr "账号验证" #: assets/serializers/platform.py:209 #: authentication/serializers/connect_token_secret.py:110 ops/mixin.py:21 #: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:92 ops/models/playbook.py:23 ops/serializers/job.py:20 +#: ops/models/job.py:94 ops/models/playbook.py:23 ops/serializers/job.py:20 #: orgs/models.py:80 perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 #: terminal/models/applet/applet.py:32 terminal/models/component/endpoint.py:12 @@ -581,7 +583,7 @@ msgstr "类别" #: assets/models/cmd_filter.py:74 assets/models/platform.py:90 #: assets/serializers/asset/common.py:122 assets/serializers/platform.py:111 #: assets/serializers/platform.py:126 audits/serializers.py:48 -#: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:103 +#: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:105 #: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:38 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29 @@ -614,10 +616,10 @@ msgid "Changed" msgstr "已修改" #: accounts/serializers/account/account.py:250 -#: accounts/serializers/automations/base.py:22 acls/models/base.py:104 +#: accounts/serializers/automations/base.py:22 acls/models/base.py:97 #: assets/models/automations/base.py:19 #: assets/serializers/automations/base.py:20 ops/models/base.py:17 -#: ops/models/job.py:105 ops/serializers/job.py:21 +#: ops/models/job.py:107 ops/serializers/job.py:21 #: terminal/templates/terminal/_msg_command_execute_alert.html:16 msgid "Assets" msgstr "资产" @@ -642,7 +644,7 @@ msgstr "账号已存在" msgid "ID" msgstr "ID" -#: accounts/serializers/account/account.py:427 acls/serializers/base.py:112 +#: accounts/serializers/account/account.py:427 acls/serializers/base.py:116 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:49 #: audits/models.py:85 audits/models.py:163 #: authentication/models/connection_token.py:32 @@ -652,9 +654,10 @@ msgstr "ID" #: perms/serializers/permission.py:30 rbac/builtin.py:123 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:17 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:148 terminal/notifications.py:196 +#: terminal/notifications.py:180 terminal/notifications.py:228 #: terminal/serializers/command.py:17 -#: terminal/templates/terminal/_msg_command_warning.html:33 +#: terminal/templates/terminal/_msg_command_warning.html:30 +#: terminal/templates/terminal/_msg_command_warning.html:81 #: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:947 #: users/models/user.py:978 users/serializers/group.py:18 msgid "User" @@ -662,7 +665,7 @@ msgstr "用户" #: accounts/serializers/account/account.py:428 #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:150 terminal/notifications.py:198 +#: terminal/notifications.py:182 terminal/notifications.py:230 msgid "Date" msgstr "日期" @@ -790,39 +793,39 @@ msgstr "密钥不合法或密钥密码错误" msgid "Acls" msgstr "访问控制" -#: acls/models/base.py:21 terminal/const.py:11 tickets/const.py:45 +#: acls/const.py:6 terminal/const.py:11 tickets/const.py:45 #: tickets/templates/tickets/approve_check_password.html:49 msgid "Reject" msgstr "拒绝" -#: acls/models/base.py:22 terminal/const.py:9 +#: acls/const.py:7 terminal/const.py:9 msgid "Accept" msgstr "接受" -#: acls/models/base.py:23 +#: acls/const.py:8 msgid "Review" msgstr "审批" -#: acls/models/base.py:24 terminal/const.py:10 +#: acls/const.py:9 terminal/const.py:10 msgid "Warning" msgstr "告警" -#: acls/models/base.py:44 assets/models/_user.py:51 +#: acls/models/base.py:37 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:93 msgid "Priority" msgstr "优先级" -#: acls/models/base.py:45 assets/models/_user.py:51 +#: acls/models/base.py:38 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:94 msgid "1-100, the lower the value will be match first" msgstr "优先级可选范围为 1-100 (数值越小越优先)" -#: acls/models/base.py:49 assets/models/cmd_filter.py:86 +#: acls/models/base.py:42 assets/models/cmd_filter.py:86 #: authentication/serializers/connect_token_secret.py:88 msgid "Reviewers" msgstr "审批人" -#: acls/models/base.py:50 authentication/models/access_key.py:17 +#: acls/models/base.py:43 authentication/models/access_key.py:17 #: authentication/models/connection_token.py:53 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/asset_permission.py:76 terminal/models/session/sharing.py:27 @@ -830,11 +833,11 @@ msgstr "审批人" msgid "Active" msgstr "激活中" -#: acls/models/base.py:88 users/apps.py:9 +#: acls/models/base.py:81 users/apps.py:9 msgid "Users" msgstr "用户管理" -#: acls/models/base.py:105 assets/models/automations/base.py:17 +#: acls/models/base.py:98 assets/models/automations/base.py:17 #: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:305 #: rbac/tree.py:35 msgid "Accounts" @@ -845,7 +848,8 @@ msgstr "账号管理" #: terminal/models/session/session.py:42 terminal/serializers/command.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:51 +#: terminal/templates/terminal/_msg_command_warning.html:48 +#: terminal/templates/terminal/_msg_command_warning.html:90 msgid "Command" msgstr "命令" @@ -877,7 +881,8 @@ msgid "The generated regular expression is incorrect: {}" msgstr "生成的正则表达式有误" #: acls/models/command_acl.py:100 -#: terminal/templates/terminal/_msg_command_warning.html:57 +#: terminal/templates/terminal/_msg_command_warning.html:54 +#: terminal/templates/terminal/_msg_command_warning.html:92 msgid "Command acl" msgstr "命令过滤" @@ -914,11 +919,11 @@ msgstr "登录资产访问控制" msgid "Login asset confirm" msgstr "登录资产复核" -#: acls/serializers/base.py:10 acls/serializers/login_acl.py:11 +#: acls/serializers/base.py:11 acls/serializers/login_acl.py:11 msgid "With * indicating a match all. " msgstr "* 表示匹配所有. " -#: acls/serializers/base.py:25 +#: acls/serializers/base.py:26 msgid "" "With * indicating a match all. Such as: 192.168.10.1, 192.168.1.0/24, " "10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 (Domain name " @@ -927,19 +932,19 @@ msgstr "" "* 表示匹配所有。例如: 192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, 2001:" "db8:2de::e13, 2001:db8:1a:1110::/64 (支持网域)" -#: acls/serializers/base.py:40 assets/serializers/asset/host.py:19 +#: acls/serializers/base.py:41 assets/serializers/asset/host.py:19 msgid "IP/Host" msgstr "IP/主机" -#: acls/serializers/base.py:87 +#: acls/serializers/base.py:91 msgid "Recipients" msgstr "接收人" -#: acls/serializers/base.py:99 tickets/serializers/ticket/ticket.py:77 +#: acls/serializers/base.py:103 tickets/serializers/ticket/ticket.py:77 msgid "The organization `{}` does not exist" msgstr "组织 `{}` 不存在" -#: acls/serializers/base.py:105 +#: acls/serializers/base.py:109 msgid "None of the reviewers belong to Organization `{}`" msgstr "所有复核人都不属于组织 `{}`" @@ -985,7 +990,7 @@ msgstr "应用程序" msgid "Can match application" msgstr "匹配应用" -#: assets/api/asset/asset.py:153 +#: assets/api/asset/asset.py:157 msgid "Cannot create asset directly, you should create a host or other" msgstr "不能直接创建资产, 你应该创建主机或其他资产" @@ -1228,7 +1233,7 @@ msgstr "SSH公钥" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:20 -#: common/db/models.py:36 ops/models/adhoc.py:27 ops/models/job.py:111 +#: common/db/models.py:36 ops/models/adhoc.py:27 ops/models/job.py:113 #: ops/models/playbook.py:26 rbac/models/role.py:37 settings/models.py:38 #: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:248 #: terminal/models/applet/host.py:139 terminal/models/component/endpoint.py:24 @@ -1241,7 +1246,7 @@ msgstr "备注" #: assets/models/_user.py:28 assets/models/automations/base.py:114 #: assets/models/cmd_filter.py:41 assets/models/group.py:19 -#: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:191 +#: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:193 #: users/models/user.py:979 msgid "Date created" msgstr "创建日期" @@ -1409,7 +1414,7 @@ msgstr "忽略证书校验" msgid "Proxy" msgstr "代理" -#: assets/models/automations/base.py:22 ops/models/job.py:187 +#: assets/models/automations/base.py:22 ops/models/job.py:189 #: settings/serializers/auth/sms.py:99 msgid "Parameters" msgstr "参数" @@ -1423,7 +1428,7 @@ msgid "Asset automation task" msgstr "资产自动化任务" #: assets/models/automations/base.py:113 audits/models.py:199 -#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:184 +#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:186 #: terminal/models/applet/applet.py:247 terminal/models/applet/host.py:136 #: terminal/models/component/status.py:30 terminal/serializers/applet.py:18 #: terminal/serializers/applet_host.py:107 tickets/models/ticket/general.py:283 @@ -1976,7 +1981,8 @@ msgid "Rename dir" msgstr "映射目录" #: audits/const.py:23 rbac/tree.py:229 -#: terminal/templates/terminal/_msg_command_warning.html:71 +#: terminal/templates/terminal/_msg_command_warning.html:68 +#: terminal/templates/terminal/_msg_command_warning.html:96 msgid "View" msgstr "查看" @@ -2060,7 +2066,8 @@ msgstr "文件" #: terminal/models/session/replay.py:9 terminal/models/session/sharing.py:18 #: terminal/models/session/sharing.py:81 #: terminal/templates/terminal/_msg_command_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:69 +#: terminal/templates/terminal/_msg_command_warning.html:66 +#: terminal/templates/terminal/_msg_command_warning.html:95 #: tickets/models/ticket/command_confirm.py:15 msgid "Session" msgstr "会话" @@ -2247,22 +2254,22 @@ msgstr "ACL 动作是复核" msgid "Current user not support mfa type: {}" msgstr "当前用户不支持 MFA 类型: {}" -#: authentication/api/password.py:31 terminal/api/session/session.py:259 +#: authentication/api/password.py:32 terminal/api/session/session.py:259 #: users/views/profile/reset.py:44 msgid "User does not exist: {}" msgstr "用户不存在: {}" -#: authentication/api/password.py:31 users/views/profile/reset.py:127 +#: authentication/api/password.py:32 users/views/profile/reset.py:127 msgid "No user matched" msgstr "没有匹配到用户" -#: authentication/api/password.py:35 +#: authentication/api/password.py:36 msgid "" "The user is from {}, please go to the corresponding system to change the " "password" msgstr "用户来自 {} 请去相应系统修改密码" -#: authentication/api/password.py:59 +#: authentication/api/password.py:60 #: authentication/templates/authentication/login.html:305 #: users/templates/users/forgot_password.html:27 #: users/templates/users/forgot_password.html:28 @@ -2588,7 +2595,7 @@ msgstr "设置手机号码启用" msgid "Clear phone number to disable" msgstr "清空手机号码禁用" -#: authentication/middleware.py:93 settings/utils/ldap.py:657 +#: authentication/middleware.py:93 settings/utils/ldap.py:661 msgid "Authentication failed (before login check failed): {}" msgstr "认证失败(登录前检查失败): {}" @@ -2845,7 +2852,7 @@ msgstr "代码错误" #: authentication/templates/authentication/_msg_reset_password_code.html:9 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:426 +#: jumpserver/conf.py:427 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -3429,11 +3436,11 @@ msgstr "导出搜素: %s" msgid "User %s view/export secret" msgstr "用户 %s 查看/导出 了密码" -#: jumpserver/conf.py:425 +#: jumpserver/conf.py:426 msgid "Create account successfully" msgstr "创建账号成功" -#: jumpserver/conf.py:427 +#: jumpserver/conf.py:428 msgid "Your account has been created successfully" msgstr "你的账号已创建成功" @@ -3568,7 +3575,7 @@ msgstr "VCS" msgid "Adhoc" msgstr "命令" -#: ops/const.py:39 ops/models/job.py:101 +#: ops/const.py:39 ops/models/job.py:103 msgid "Playbook" msgstr "Playbook" @@ -3625,17 +3632,17 @@ msgstr "需要周期或定期设置" msgid "Pattern" msgstr "模式" -#: ops/models/adhoc.py:24 ops/models/job.py:96 +#: ops/models/adhoc.py:24 ops/models/job.py:98 msgid "Module" msgstr "模块" -#: ops/models/adhoc.py:25 ops/models/celery.py:58 ops/models/job.py:95 +#: ops/models/adhoc.py:25 ops/models/celery.py:58 ops/models/job.py:97 #: terminal/models/component/task.py:16 msgid "Args" msgstr "参数" #: ops/models/adhoc.py:26 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:104 ops/models/job.py:190 ops/models/playbook.py:25 +#: ops/models/job.py:106 ops/models/job.py:192 ops/models/playbook.py:25 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "创建者" @@ -3652,12 +3659,12 @@ msgstr "最后执行" msgid "Date last run" msgstr "最后运行日期" -#: ops/models/base.py:51 ops/models/job.py:188 +#: ops/models/base.py:51 ops/models/job.py:190 #: xpack/plugins/cloud/models.py:162 msgid "Result" msgstr "结果" -#: ops/models/base.py:52 ops/models/job.py:189 +#: ops/models/base.py:52 ops/models/job.py:191 msgid "Summary" msgstr "汇总" @@ -3690,43 +3697,43 @@ msgstr "发布日期" msgid "Celery Task Execution" msgstr "Celery 任务执行" -#: ops/models/job.py:98 +#: ops/models/job.py:100 msgid "Chdir" msgstr "运行目录" -#: ops/models/job.py:99 +#: ops/models/job.py:101 msgid "Timeout (Seconds)" msgstr "超时时间(秒)" -#: ops/models/job.py:106 +#: ops/models/job.py:108 msgid "Use Parameter Define" msgstr "使用参数定义" -#: ops/models/job.py:107 +#: ops/models/job.py:109 msgid "Parameters define" msgstr "参数定义" -#: ops/models/job.py:108 +#: ops/models/job.py:110 msgid "Runas" msgstr "运行用户" -#: ops/models/job.py:110 +#: ops/models/job.py:112 msgid "Runas policy" msgstr "用户策略" -#: ops/models/job.py:172 +#: ops/models/job.py:174 msgid "Job" msgstr "作业" -#: ops/models/job.py:195 +#: ops/models/job.py:197 msgid "Material" msgstr "Material" -#: ops/models/job.py:197 +#: ops/models/job.py:199 msgid "Material Type" msgstr "Material 类型" -#: ops/models/job.py:461 +#: ops/models/job.py:482 msgid "Job Execution" msgstr "作业执行" @@ -3871,7 +3878,8 @@ msgstr "组织管理" #: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:89 #: rbac/const.py:7 rbac/models/rolebinding.py:56 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:63 -#: terminal/templates/terminal/_msg_command_warning.html:75 +#: terminal/templates/terminal/_msg_command_warning.html:72 +#: terminal/templates/terminal/_msg_command_warning.html:98 #: tickets/models/ticket/general.py:302 tickets/serializers/ticket/ticket.py:60 msgid "Organization" msgstr "组织" @@ -5284,100 +5292,100 @@ msgstr "周期导入 LDAP 用户" msgid "Registration periodic import ldap user task" msgstr "注册周期导入 LDAP 用户 任务" -#: settings/utils/ldap.py:472 +#: settings/utils/ldap.py:476 msgid "ldap:// or ldaps:// protocol is used." msgstr "使用 ldap:// 或 ldaps:// 协议" -#: settings/utils/ldap.py:483 +#: settings/utils/ldap.py:487 msgid "Host or port is disconnected: {}" msgstr "主机或端口不可连接: {}" -#: settings/utils/ldap.py:485 +#: settings/utils/ldap.py:489 msgid "The port is not the port of the LDAP service: {}" msgstr "端口不是LDAP服务端口: {}" -#: settings/utils/ldap.py:487 +#: settings/utils/ldap.py:491 msgid "Please add certificate: {}" msgstr "请添加证书" -#: settings/utils/ldap.py:491 settings/utils/ldap.py:518 -#: settings/utils/ldap.py:548 settings/utils/ldap.py:576 +#: settings/utils/ldap.py:495 settings/utils/ldap.py:522 +#: settings/utils/ldap.py:552 settings/utils/ldap.py:580 msgid "Unknown error: {}" msgstr "未知错误: {}" -#: settings/utils/ldap.py:505 +#: settings/utils/ldap.py:509 msgid "Bind DN or Password incorrect" msgstr "绑定DN或密码错误" -#: settings/utils/ldap.py:512 +#: settings/utils/ldap.py:516 msgid "Please enter Bind DN: {}" msgstr "请输入绑定DN: {}" -#: settings/utils/ldap.py:514 +#: settings/utils/ldap.py:518 msgid "Please enter Password: {}" msgstr "请输入密码: {}" -#: settings/utils/ldap.py:516 +#: settings/utils/ldap.py:520 msgid "Please enter correct Bind DN and Password: {}" msgstr "请输入正确的绑定DN和密码: {}" -#: settings/utils/ldap.py:534 +#: settings/utils/ldap.py:538 msgid "Invalid User OU or User search filter: {}" msgstr "不合法的用户OU或用户过滤器: {}" -#: settings/utils/ldap.py:565 +#: settings/utils/ldap.py:569 msgid "LDAP User attr map not include: {}" msgstr "LDAP属性映射没有包含: {}" -#: settings/utils/ldap.py:572 +#: settings/utils/ldap.py:576 msgid "LDAP User attr map is not dict" msgstr "LDAP属性映射不合法" -#: settings/utils/ldap.py:591 +#: settings/utils/ldap.py:595 msgid "LDAP authentication is not enabled" msgstr "LDAP认证没有启用" -#: settings/utils/ldap.py:609 +#: settings/utils/ldap.py:613 msgid "Error (Invalid LDAP server): {}" msgstr "错误 (不合法的LDAP服务器地址): {}" -#: settings/utils/ldap.py:611 +#: settings/utils/ldap.py:615 msgid "Error (Invalid Bind DN): {}" msgstr "错误(不合法的绑定DN): {}" -#: settings/utils/ldap.py:613 +#: settings/utils/ldap.py:617 msgid "Error (Invalid LDAP User attr map): {}" msgstr "错误(不合法的LDAP属性映射): {}" -#: settings/utils/ldap.py:615 +#: settings/utils/ldap.py:619 msgid "Error (Invalid User OU or User search filter): {}" msgstr "错误(不合法的用户OU或用户过滤器): {}" -#: settings/utils/ldap.py:617 +#: settings/utils/ldap.py:621 msgid "Error (Not enabled LDAP authentication): {}" msgstr "错误(没有启用LDAP认证): {}" -#: settings/utils/ldap.py:619 +#: settings/utils/ldap.py:623 msgid "Error (Unknown): {}" msgstr "错误(未知): {}" -#: settings/utils/ldap.py:622 +#: settings/utils/ldap.py:626 msgid "Succeed: Match {} s user" msgstr "成功匹配 {} 个用户" -#: settings/utils/ldap.py:655 +#: settings/utils/ldap.py:659 msgid "Authentication failed (configuration incorrect): {}" msgstr "认证失败(配置错误): {}" -#: settings/utils/ldap.py:659 +#: settings/utils/ldap.py:663 msgid "Authentication failed (username or password incorrect): {}" msgstr "认证失败 (用户名或密码不正确): {}" -#: settings/utils/ldap.py:661 +#: settings/utils/ldap.py:665 msgid "Authentication failed (Unknown): {}" msgstr "认证失败: (未知): {}" -#: settings/utils/ldap.py:664 +#: settings/utils/ldap.py:668 msgid "Authentication success: {}" msgstr "认证成功: {}" @@ -5608,7 +5616,7 @@ msgstr "测试失败: {}" msgid "Test successful" msgstr "测试成功" -#: terminal/api/component/storage.py:124 terminal/notifications.py:231 +#: terminal/api/component/storage.py:124 terminal/notifications.py:263 #: terminal/tasks.py:144 msgid "Test failure: Account invalid" msgstr "测试失败: 账号无效" @@ -5646,6 +5654,7 @@ msgid "Output" msgstr "输出" #: terminal/backends/command/models.py:25 terminal/serializers/command.py:23 +#: terminal/templates/terminal/_msg_command_warning.html:91 msgid "Risk level" msgstr "风险等级" @@ -5990,36 +5999,35 @@ msgstr "验证码不正确" msgid "You have already joined this session" msgstr "您已经加入过此会话" -#: terminal/notifications.py:22 +#: terminal/notifications.py:24 msgid "Sessions" msgstr "会话管理" -#: terminal/notifications.py:69 -#: terminal/templates/terminal/_msg_command_warning.html:5 -msgid "Danger command warning" -msgstr "危险命令告警" +#: terminal/notifications.py:71 +msgid "Command warning" +msgstr "命令告警" -#: terminal/notifications.py:122 -msgid "Danger command alert" -msgstr "危险命令告警" +#: terminal/notifications.py:154 +msgid "Command reject" +msgstr "命令拒绝" -#: terminal/notifications.py:149 terminal/notifications.py:197 +#: terminal/notifications.py:181 terminal/notifications.py:229 msgid "Level" msgstr "级别" -#: terminal/notifications.py:167 +#: terminal/notifications.py:199 msgid "Batch danger command alert" msgstr "批量危险命令告警" -#: terminal/notifications.py:215 +#: terminal/notifications.py:247 msgid "Command and replay storage" msgstr "命令及录像存储" -#: terminal/notifications.py:216 +#: terminal/notifications.py:248 msgid "Connectivity alarm" msgstr "可连接性告警" -#: terminal/notifications.py:241 +#: terminal/notifications.py:273 #: terminal/templates/terminal/_msg_check_command_replay_storage_connectivity.html:4 msgid "Invalid storage" msgstr "无效的存储" @@ -6291,15 +6299,16 @@ msgstr "检查命令及录像存储可连接性 " msgid "view" msgstr "查看" -#: terminal/templates/terminal/_msg_command_warning.html:21 +#: terminal/templates/terminal/_msg_command_warning.html:18 msgid "Item" msgstr "项目" -#: terminal/templates/terminal/_msg_command_warning.html:25 +#: terminal/templates/terminal/_msg_command_warning.html:22 msgid "Url" msgstr "链接" -#: terminal/templates/terminal/_msg_command_warning.html:63 +#: terminal/templates/terminal/_msg_command_warning.html:60 +#: terminal/templates/terminal/_msg_command_warning.html:93 msgid "Command acl group" msgstr "命令过滤组" @@ -7773,3 +7782,6 @@ msgstr "旗舰版" #: xpack/plugins/license/models.py:86 msgid "Community edition" msgstr "社区版" + +#~ msgid "Danger command alert" +#~ msgstr "危险命令告警" diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index 162ac5924..d3647bdc3 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -28,6 +28,7 @@ from perms.models import AssetPermission from perms.utils import UserPermAssetUtil from terminal.notifications import CommandExecutionAlert from terminal.notifications import CommandWarningMessage +from terminal.const import RiskLevelChoices def get_parent_keys(key, include_self=True): @@ -400,13 +401,22 @@ class JobExecution(JMSOrgBaseModel): }).publish_async() raise Exception("command is rejected by ACL") elif acl.is_action(CommandFilterACL.ActionChoices.warning): - # TODO: warning message - # user = '' - # command = { - # 'user': '', - # 'user_id': '' - # } - # CommandWarningMessage(user, command).publish_async() + user = self.creator + command = { + 'input': self.material, + 'user': user.name, + '_user_id': user.id, + 'asset': asset.name, + '_asset_id': asset.id, + '_account': self.current_job.runas, + '_cmd_filter_acl': acl, + '_cmd_group': cg, + 'session': '', + '_risk_level': RiskLevelChoices.warning.label, + 'org_id': self.org.id, + '_org_name': self.org.name or self.org.id, + } + CommandWarningMessage(user, command).publish_async() return True return False diff --git a/apps/terminal/api/session/command.py b/apps/terminal/api/session/command.py index 44e7135f1..c933a12ad 100644 --- a/apps/terminal/api/session/command.py +++ b/apps/terminal/api/session/command.py @@ -224,16 +224,17 @@ class InsecureCommandAlertAPI(generics.CreateAPIView): cmd_group = cmd_group_mapper.get(command['cmd_group']) command['_cmd_group'] = cmd_group session = session_mapper.get(command['session']) + risk_level = command.get('risk_level') if session: command.update({ '_user_id': session.user_id, '_asset_id': session.asset_id, '_account': session.account, '_account_id': session.account_id, - '_org_name': session.org.name + '_org_name': session.org.name, + '_risk_level': RiskLevelChoices.get_risk_level_str(risk_level), }) - risk_level = command.get('risk_level') if risk_level in [RiskLevelChoices.reject, RiskLevelChoices.review_reject]: CommandAlertMessage(command).publish_async() elif risk_level in [RiskLevelChoices.warning]: diff --git a/apps/terminal/const.py b/apps/terminal/const.py index b05de71bb..7b2284b8e 100644 --- a/apps/terminal/const.py +++ b/apps/terminal/const.py @@ -13,6 +13,11 @@ class RiskLevelChoices(IntegerChoices): review_accept = 7, _('Review & Accept') review_cancel = 8, _('Review & Cancel') + @classmethod + def get_risk_level_str(cls, risk_level): + risk_mapper = dict(cls.choices) + return risk_mapper.get(risk_level) + class ReplayStorageType(TextChoices): null = 'null', 'Null', diff --git a/apps/terminal/notifications.py b/apps/terminal/notifications.py index 77d113423..753845de1 100644 --- a/apps/terminal/notifications.py +++ b/apps/terminal/notifications.py @@ -11,7 +11,6 @@ from notifications.backends import BACKEND from notifications.models import SystemMsgSubscription from notifications.notifications import SystemMessage, UserMessage from terminal.models import Session, Command -from acls.models import CommandFilterACL, CommandGroup from users.models import User logger = get_logger(__name__) @@ -69,7 +68,7 @@ class CommandAlertMixin: class CommandWarningMessage(CommandAlertMixin, UserMessage): - message_type_label = _('Danger command warning') + message_type_label = _('Command warning') def __init__(self, user, command): super().__init__(user) @@ -88,6 +87,7 @@ class CommandWarningMessage(CommandAlertMixin, UserMessage): cmd_acl = command.get('_cmd_filter_acl') cmd_group = command.get('_cmd_group') session_id = command['session'] + risk_level = command['_risk_level'] org_id = command['org_id'] org_name = command.get('_org_name') or org_id @@ -137,6 +137,7 @@ class CommandWarningMessage(CommandAlertMixin, UserMessage): 'cmd_group': cmd_group_name, 'cmd_group_url': cmd_group_url, 'session_url': session_url, + 'risk_level': risk_level, 'org': org_name, } @@ -150,7 +151,7 @@ class CommandWarningMessage(CommandAlertMixin, UserMessage): class CommandAlertMessage(CommandAlertMixin, SystemMessage): category = CATEGORY category_label = CATEGORY_LABEL - message_type_label = _('Danger command alert') + message_type_label = _('Command reject') def __init__(self, command): self.command = command diff --git a/apps/terminal/templates/terminal/_msg_command_warning.html b/apps/terminal/templates/terminal/_msg_command_warning.html index 0a7fe66a1..814947278 100644 --- a/apps/terminal/templates/terminal/_msg_command_warning.html +++ b/apps/terminal/templates/terminal/_msg_command_warning.html @@ -1,10 +1,7 @@ {% load i18n %}
-

- {% blocktranslate %}Danger command warning{% endblocktranslate %} -

- -
+ --> + + + {% trans 'User' %}: {{ user }}
+ {% trans 'Asset' %}: {{ asset }}
+ {% trans 'Account' %}: + {% if account_url %} + {{ account }} + {% else %} + {{ account }} + {% endif %} +
+ {% trans 'Command' %}: {{ command }}
+ {% trans 'Risk level' %}: {{ risk_level }}
+ {% trans 'Command acl' %}: {{ user }}
+ {% trans 'Command acl group' %}: {{ user }}
+ {% if session_url %} + {% trans 'Session' %}: + {% trans 'View' %}
+ {% endif %} + {% trans 'Organization' %}: {{ org }}
+
From fa52e2bf5e221cb984abe97388395c526b330913 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 19 Jul 2023 11:00:58 +0800 Subject: [PATCH 145/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E5=91=BD=E4=BB=A4=E5=91=8A=E8=AD=A6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/models/job.py | 20 ++-- apps/terminal/api/session/command.py | 48 ++++---- apps/terminal/backends/command/models.py | 5 - apps/terminal/const.py | 6 +- apps/terminal/notifications.py | 12 +- .../terminal/_msg_command_warning.html | 105 +++--------------- 6 files changed, 57 insertions(+), 139 deletions(-) diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index d3647bdc3..6431780a3 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -396,29 +396,29 @@ class JobExecution(JMSOrgBaseModel): CommandExecutionAlert({ "assets": self.current_job.assets.all(), "input": self.material, - "risk_level": 5, + "risk_level": RiskLevelChoices.reject, "user": self.creator, }).publish_async() raise Exception("command is rejected by ACL") elif acl.is_action(CommandFilterACL.ActionChoices.warning): - user = self.creator command = { 'input': self.material, - 'user': user.name, - '_user_id': user.id, + 'user': self.creator.name, 'asset': asset.name, + 'cmd_filter_acl': str(acl.id), + 'cmd_group': str(cg.id), + 'risk_level': RiskLevelChoices.warning, + 'org_id': self.org_id, + '_user_id': self.creator.id, '_asset_id': asset.id, '_account': self.current_job.runas, '_cmd_filter_acl': acl, '_cmd_group': cg, - 'session': '', - '_risk_level': RiskLevelChoices.warning.label, - 'org_id': self.org.id, - '_org_name': self.org.name or self.org.id, + '_org_name': self.org_name, } - CommandWarningMessage(user, command).publish_async() + for reviewer in acl.reviewers.all(): + CommandWarningMessage(reviewer, command).publish_async() return True - return False def check_command_acl(self): diff --git a/apps/terminal/api/session/command.py b/apps/terminal/api/session/command.py index c933a12ad..f95155fd1 100644 --- a/apps/terminal/api/session/command.py +++ b/apps/terminal/api/session/command.py @@ -216,31 +216,29 @@ class InsecureCommandAlertAPI(generics.CreateAPIView): cmd_groups = CommandGroup.objects.filter(id__in=cmd_group_ids).only('id', 'name') cmd_group_mapper = {str(i.id): i for i in cmd_groups} - lang = request.stream.COOKIES.get('django_language', 'zh') - with translation.override(lang): - for command in commands: - cmd_acl = acl_mapper.get(command['cmd_filter_acl']) - command['_cmd_filter_acl'] = cmd_acl - cmd_group = cmd_group_mapper.get(command['cmd_group']) - command['_cmd_group'] = cmd_group - session = session_mapper.get(command['session']) - risk_level = command.get('risk_level') - if session: - command.update({ - '_user_id': session.user_id, - '_asset_id': session.asset_id, - '_account': session.account, - '_account_id': session.account_id, - '_org_name': session.org.name, - '_risk_level': RiskLevelChoices.get_risk_level_str(risk_level), - }) + for command in commands: + cmd_acl = acl_mapper.get(command['cmd_filter_acl']) + command['_cmd_filter_acl'] = cmd_acl + cmd_group = cmd_group_mapper.get(command['cmd_group']) + command['_cmd_group'] = cmd_group + session = session_mapper.get(command['session']) + risk_level = command.get('risk_level') - if risk_level in [RiskLevelChoices.reject, RiskLevelChoices.review_reject]: - CommandAlertMessage(command).publish_async() - elif risk_level in [RiskLevelChoices.warning]: - for reviewer in cmd_acl.reviewers.all(): - CommandWarningMessage(reviewer, command).publish_async() - else: - logger.info(f'Risk level ignore: {risk_level}') + if session: + command.update({ + '_user_id': session.user_id, + '_asset_id': session.asset_id, + '_account': session.account, + '_account_id': session.account_id, + '_org_name': session.org.name, + }) + + if risk_level in [RiskLevelChoices.reject, RiskLevelChoices.review_reject]: + CommandAlertMessage(command).publish_async() + elif risk_level in [RiskLevelChoices.warning]: + for reviewer in cmd_acl.reviewers.all(): + CommandWarningMessage(reviewer, command).publish_async() + else: + logger.info(f'Risk level ignore: {RiskLevelChoices.get_label(risk_level)}({risk_level})') return Response({'msg': 'ok'}) diff --git a/apps/terminal/backends/command/models.py b/apps/terminal/backends/command/models.py index f588a177d..801b3cdf1 100644 --- a/apps/terminal/backends/command/models.py +++ b/apps/terminal/backends/command/models.py @@ -42,11 +42,6 @@ class AbstractSessionCommand(OrgModelMixin): else: return '' - @classmethod - def get_risk_level_str(cls, risk_level): - risk_mapper = dict(RiskLevelChoices.choices) - return risk_mapper.get(risk_level) - def to_dict(self): d = {} for field in self._meta.fields: diff --git a/apps/terminal/const.py b/apps/terminal/const.py index 7b2284b8e..f34233e3a 100644 --- a/apps/terminal/const.py +++ b/apps/terminal/const.py @@ -14,9 +14,9 @@ class RiskLevelChoices(IntegerChoices): review_cancel = 8, _('Review & Cancel') @classmethod - def get_risk_level_str(cls, risk_level): - risk_mapper = dict(cls.choices) - return risk_mapper.get(risk_level) + def get_label(cls, level): + label = dict(cls.choices).get(level) + return label class ReplayStorageType(TextChoices): diff --git a/apps/terminal/notifications.py b/apps/terminal/notifications.py index 753845de1..6d49946dd 100644 --- a/apps/terminal/notifications.py +++ b/apps/terminal/notifications.py @@ -12,6 +12,7 @@ from notifications.models import SystemMsgSubscription from notifications.notifications import SystemMessage, UserMessage from terminal.models import Session, Command from users.models import User +from terminal.const import RiskLevelChoices logger = get_logger(__name__) @@ -86,8 +87,8 @@ class CommandWarningMessage(CommandAlertMixin, UserMessage): account_id = command.get('_account_id', '') cmd_acl = command.get('_cmd_filter_acl') cmd_group = command.get('_cmd_group') - session_id = command['session'] - risk_level = command['_risk_level'] + session_id = command.get('session', '') + risk_level = command['risk_level'] org_id = command['org_id'] org_name = command.get('_org_name') or org_id @@ -137,7 +138,7 @@ class CommandWarningMessage(CommandAlertMixin, UserMessage): 'cmd_group': cmd_group_name, 'cmd_group_url': cmd_group_url, 'session_url': session_url, - 'risk_level': risk_level, + 'risk_level': RiskLevelChoices.get_label(risk_level), 'org': org_name, } @@ -174,7 +175,7 @@ class CommandAlertMessage(CommandAlertMixin, SystemMessage): session_detail_url = session_detail_url.replace( '/terminal/sessions/', '/audit/sessions/sessions/' ) - level = Command.get_risk_level_str(command['risk_level']) + level = RiskLevelChoices.get_label(command['risk_level']) items = { _("Asset"): command['asset'], _("User"): command['user'], @@ -223,7 +224,8 @@ class CommandExecutionAlert(CommandAlertMixin, SystemMessage): ) + '?oid={}'.format(asset.org_id) assets_with_url.append([asset, url]) - level = Command.get_risk_level_str(command['risk_level']) + level = RiskLevelChoices.get_label(command['risk_level']) + items = { _("User"): command['user'], _("Level"): level, diff --git a/apps/terminal/templates/terminal/_msg_command_warning.html b/apps/terminal/templates/terminal/_msg_command_warning.html index 814947278..23469e3a4 100644 --- a/apps/terminal/templates/terminal/_msg_command_warning.html +++ b/apps/terminal/templates/terminal/_msg_command_warning.html @@ -1,100 +1,23 @@ {% load i18n %}
- - - - {% trans 'User' %}: {{ user }}
- {% trans 'Asset' %}: {{ asset }}
- {% trans 'Account' %}: - {% if account_url %} - {{ account }} - {% else %} - {{ account }} - {% endif %} + {% trans 'Asset' %}: {{ asset }}
+ {% trans 'User' %}: {{ user }}
+ {% trans 'Account' %}: + {% if account_url %} + {{ account }} + {% else %} + {{ account }} + {% endif %}
- {% trans 'Command' %}: {{ command }}
{% trans 'Risk level' %}: {{ risk_level }}
- {% trans 'Command acl' %}: {{ user }}
- {% trans 'Command acl group' %}: {{ user }}
+ {% trans 'Command acl' %}: {{ user }}
+ {% trans 'Command acl group' %}: {{ user }}
{% if session_url %} - {% trans 'Session' %}: - {% trans 'View' %}
+ {% trans 'Session' %}: + {% trans 'View' %}
{% endif %} - {% trans 'Organization' %}: {{ org }}
+ {% trans 'Organization' %}: {{ org }}
+ {% trans 'Command' %}: {{ command }}
From ea607c6177f86e56670ff566f388f1d8d425d5ab Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 19 Jul 2023 11:22:33 +0800 Subject: [PATCH 146/167] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E5=91=8A=E8=AD=A6=EF=BC=8C=E4=B8=8D=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.po | 5 --- apps/locale/zh/LC_MESSAGES/django.po | 5 --- apps/ops/models/job.py | 2 -- apps/terminal/api/session/command.py | 3 -- apps/terminal/notifications.py | 29 ++-------------- .../terminal/_msg_command_warning.html | 34 ++++++++++--------- 6 files changed, 20 insertions(+), 58 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 8d6cba4c3..f9a420832 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -6399,11 +6399,6 @@ msgstr "アイテム" msgid "Url" msgstr "リンク" -#: terminal/templates/terminal/_msg_command_warning.html:60 -#: terminal/templates/terminal/_msg_command_warning.html:93 -msgid "Command acl group" -msgstr "コマンドフィルタリンググループ" - #: terminal/utils/db_port_mapper.py:84 msgid "" "No available port is matched. The number of databases may have exceeded the " diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 2938bb022..46c564887 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -6307,11 +6307,6 @@ msgstr "项目" msgid "Url" msgstr "链接" -#: terminal/templates/terminal/_msg_command_warning.html:60 -#: terminal/templates/terminal/_msg_command_warning.html:93 -msgid "Command acl group" -msgstr "命令过滤组" - #: terminal/utils/db_port_mapper.py:84 msgid "" "No available port is matched. The number of databases may have exceeded the " diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index 6431780a3..06a858bd6 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -409,8 +409,6 @@ class JobExecution(JMSOrgBaseModel): 'cmd_group': str(cg.id), 'risk_level': RiskLevelChoices.warning, 'org_id': self.org_id, - '_user_id': self.creator.id, - '_asset_id': asset.id, '_account': self.current_job.runas, '_cmd_filter_acl': acl, '_cmd_group': cg, diff --git a/apps/terminal/api/session/command.py b/apps/terminal/api/session/command.py index f95155fd1..4d20d345c 100644 --- a/apps/terminal/api/session/command.py +++ b/apps/terminal/api/session/command.py @@ -226,10 +226,7 @@ class InsecureCommandAlertAPI(generics.CreateAPIView): if session: command.update({ - '_user_id': session.user_id, - '_asset_id': session.asset_id, '_account': session.account, - '_account_id': session.account_id, '_org_name': session.org.name, }) diff --git a/apps/terminal/notifications.py b/apps/terminal/notifications.py index 6d49946dd..cfcac4396 100644 --- a/apps/terminal/notifications.py +++ b/apps/terminal/notifications.py @@ -80,11 +80,8 @@ class CommandWarningMessage(CommandAlertMixin, UserMessage): command_input = command['input'] user = command['user'] - user_id = command.get('_user_id', '') asset = command['asset'] - asset_id = command.get('_asset_id', '') account = command.get('_account', '') - account_id = command.get('_account_id', '') cmd_acl = command.get('_cmd_filter_acl') cmd_group = command.get('_cmd_group') session_id = command.get('session', '') @@ -92,51 +89,29 @@ class CommandWarningMessage(CommandAlertMixin, UserMessage): org_id = command['org_id'] org_name = command.get('_org_name') or org_id - user_url = asset_url = account_url = session_url = '' - if user_id: - user_url = reverse( - 'users:user-detail', kwargs={'pk': user_id}, - api_to_ui=True, external=True, is_console=True - ) + '?oid={}'.format(org_id) - if asset_id: - asset_url = reverse( - 'assets:asset-detail', kwargs={'pk': asset_id}, - api_to_ui=True, external=True, is_console=True - ) + '?oid={}'.format(org_id) - if account_id: - account_url = reverse( - 'accounts:account-detail', kwargs={'pk': account_id}, - api_to_ui=True, external=True, is_console=True - ) + '?oid={}'.format(org_id) if session_id: session_url = reverse( 'api-terminal:session-detail', kwargs={'pk': session_id}, external=True, api_to_ui=True ) + '?oid={}'.format(org_id) session_url = session_url.replace('/terminal/sessions/', '/audit/sessions/sessions/') + else: + session_url = '' # Command ACL - cmd_acl_url = cmd_group_url = '' cmd_acl_name = cmd_group_name = '' if cmd_acl: cmd_acl_name = cmd_acl.name - cmd_acl_url = settings.SITE_URL + f'/ui/#/console/perms/cmd-acls/{cmd_acl.id}/' if cmd_group: cmd_group_name = cmd_group.name - cmd_group_url = settings.SITE_URL + f'/ui/#/console/perms/cmd-groups/{cmd_group.id}/' context = { 'command': command_input, 'user': user, - 'user_url': user_url, 'asset': asset, - 'asset_url': asset_url, 'account': account, - 'account_url': account_url, 'cmd_filter_acl': cmd_acl_name, - 'cmd_filter_acl_url': cmd_acl_url, 'cmd_group': cmd_group_name, - 'cmd_group_url': cmd_group_url, 'session_url': session_url, 'risk_level': RiskLevelChoices.get_label(risk_level), 'org': org_name, diff --git a/apps/terminal/templates/terminal/_msg_command_warning.html b/apps/terminal/templates/terminal/_msg_command_warning.html index 23469e3a4..df7315341 100644 --- a/apps/terminal/templates/terminal/_msg_command_warning.html +++ b/apps/terminal/templates/terminal/_msg_command_warning.html @@ -1,23 +1,25 @@ {% load i18n %}
- {% trans 'Asset' %}: {{ asset }}
- {% trans 'User' %}: {{ user }}
- {% trans 'Account' %}: - {% if account_url %} - {{ account }} - {% else %} - {{ account }} - {% endif %} -
- {% trans 'Risk level' %}: {{ risk_level }}
- {% trans 'Command acl' %}: {{ user }}
- {% trans 'Command acl group' %}: {{ user }}
+ {% trans 'Asset' %}: {{ asset }} +
+ {% trans 'User' %}: {{ user }} +
+ {% trans 'Account' %}: {{ account }} +
+ {% trans 'Risk level' %}: {{ risk_level }} +
+ {% trans 'Command acl' %}: {{ cmd_filter_acl }} +
+ {% trans 'Command group' %}: {{ cmd_group}} +
{% if session_url %} {% trans 'Session' %}: - {% trans 'View' %}
+ {% trans 'View' %} +
{% endif %} - {% trans 'Organization' %}: {{ org }}
- {% trans 'Command' %}: {{ command }}
- + {% trans 'Organization' %}: {{ org }} +
+ {% trans 'Command' %}: {{ command }} +
From 8ed8d6f01c0d1ad16e7e218983fce389742782b8 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 19 Jul 2023 11:36:42 +0800 Subject: [PATCH 147/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20url?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/models/account.py | 8 ++++---- apps/common/management/commands/services/command.py | 8 +++++--- apps/jumpserver/urls.py | 6 +++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/apps/accounts/models/account.py b/apps/accounts/models/account.py index 893fcccb4..8c7fd7283 100644 --- a/apps/accounts/models/account.py +++ b/apps/accounts/models/account.py @@ -106,15 +106,15 @@ class Account(AbsConnectivity, BaseAccount): def get_anonymous_account(cls): return cls(name=AliasAccount.ANON.label, username=AliasAccount.ANON.value, secret=None) - @lazyproperty - def versions(self): - return self.history.count() - @classmethod def get_user_account(cls): """ @USER 动态用户的账号(self) """ return cls(name=AliasAccount.USER.label, username=AliasAccount.USER.value, secret=None) + @lazyproperty + def versions(self): + return self.history.count() + def get_su_from_accounts(self): """ 排除自己和以自己为 su-from 的账号 """ return self.asset.accounts.exclude(id=self.id).exclude(su_from=self) diff --git a/apps/common/management/commands/services/command.py b/apps/common/management/commands/services/command.py index fcaa8f1cd..6ec38ab2b 100644 --- a/apps/common/management/commands/services/command.py +++ b/apps/common/management/commands/services/command.py @@ -1,8 +1,10 @@ import multiprocessing -from django.core.management.base import BaseCommand, CommandError + +from django.core.management.base import BaseCommand from django.db.models import TextChoices -from .utils import ServicesUtil + from .hands import * +from .utils import ServicesUtil class Services(TextChoices): @@ -97,7 +99,7 @@ class BaseActionCommand(BaseCommand): cores = multiprocessing.cpu_count() * 2 + 1 parser.add_argument( - 'services', nargs='+', choices=Services.export_services_values(), help='Service', + 'services', nargs='+', choices=Services.export_services_values(), help='Service', ) parser.add_argument('-d', '--daemon', nargs="?", const=True) parser.add_argument('-w', '--worker', type=int, nargs="?", default=cores) diff --git a/apps/jumpserver/urls.py b/apps/jumpserver/urls.py index 971995ffe..8fbea643c 100644 --- a/apps/jumpserver/urls.py +++ b/apps/jumpserver/urls.py @@ -49,13 +49,11 @@ if settings.XPACK_ENABLED: urlpatterns = [ path('', views.IndexView.as_view(), name='index'), path('api/v1/', include(api_v1)), - re_path('api/(?P\w+)/(?Pv\d)/.*', views.redirect_format_api), path('api/health/', api.HealthCheckView.as_view(), name="health"), path('api/v1/health/', api.HealthCheckView.as_view(), name="health_v1"), # External apps url path('core/auth/captcha/', include('captcha.urls')), path('core/', include(app_view_patterns)), - path('ui/', views.UIView.as_view()), ] # 静态文件处理路由 @@ -66,7 +64,9 @@ urlpatterns += [ ] if settings.DEBUG: urlpatterns += static('/luna/', document_root=(settings.DATA_DIR + '/luna')) - urlpatterns += static('/lina/', document_root=(settings.DATA_DIR + '/lina')) + urlpatterns += static('/ui/', document_root=(settings.DATA_DIR + '/lina')) +else: + urlpatterns += path('ui/', views.UIView.as_view()), # js i18n 路由文件 urlpatterns += [ From 9e8579d5b455cfc185c05491cb9224e4deaafdf2 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 19 Jul 2023 17:05:42 +0800 Subject: [PATCH 148/167] =?UTF-8?q?perf:=20proxy=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=20=E4=BF=AE=E6=94=B9=E7=BF=BB=E8=AF=91=20(#1?= =?UTF-8?q?1017)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/assets/serializers/asset/gpt.py | 9 ++ apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 168 ++++++++++++++------------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 168 ++++++++++++++------------- 5 files changed, 187 insertions(+), 166 deletions(-) diff --git a/apps/assets/serializers/asset/gpt.py b/apps/assets/serializers/asset/gpt.py index 9c79da313..4bcc16877 100644 --- a/apps/assets/serializers/asset/gpt.py +++ b/apps/assets/serializers/asset/gpt.py @@ -1,4 +1,5 @@ from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers from assets.models import GPT from .common import AssetSerializer @@ -22,3 +23,11 @@ class GPTSerializer(AssetSerializer): ), 'label': _('HTTP proxy')} } + + @staticmethod + def validate_proxy(value): + if value and not value.startswith(("http://", "https://")): + raise serializers.ValidationError( + _('Proxy must start with http:// or https://') + ) + return value diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 820a5d1b0..4a4ff2f0b 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4463d66ad3eac6127e435d60759e1a6584f93842d959e6129c9b92d1a68de32 -size 148522 +oid sha256:2d100b8957a5be7b3819b1f47bbd0e0f358c4d77112afb2aa8072f034372a412 +size 148962 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index f9a420832..7187599e4 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-19 09:58+0800\n" +"POT-Creation-Date: 2023-07-19 16:59+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -95,7 +95,7 @@ msgstr "更新" #: accounts/const/account.py:29 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:77 xpack/plugins/cloud/const.py:41 +#: ops/const.py:58 terminal/const.py:77 xpack/plugins/cloud/const.py:43 msgid "Failed" msgstr "失敗しました" @@ -200,9 +200,8 @@ msgstr "作成のみ" #: audits/models.py:53 authentication/models/connection_token.py:36 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 #: terminal/backends/command/models.py:18 terminal/models/session/session.py:31 -#: terminal/notifications.py:179 terminal/serializers/command.py:18 -#: terminal/templates/terminal/_msg_command_warning.html:36 -#: terminal/templates/terminal/_msg_command_warning.html:82 +#: terminal/notifications.py:155 terminal/serializers/command.py:18 +#: terminal/templates/terminal/_msg_command_warning.html:4 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "資産" @@ -236,8 +235,7 @@ msgstr "ソース ID" #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 #: terminal/backends/command/models.py:19 terminal/models/session/session.py:33 -#: terminal/templates/terminal/_msg_command_warning.html:42 -#: terminal/templates/terminal/_msg_command_warning.html:83 +#: terminal/templates/terminal/_msg_command_warning.html:8 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "アカウント" @@ -658,10 +656,9 @@ msgstr "ID" #: perms/serializers/permission.py:30 rbac/builtin.py:123 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:17 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:180 terminal/notifications.py:228 +#: terminal/notifications.py:156 terminal/notifications.py:205 #: terminal/serializers/command.py:17 -#: terminal/templates/terminal/_msg_command_warning.html:30 -#: terminal/templates/terminal/_msg_command_warning.html:81 +#: terminal/templates/terminal/_msg_command_warning.html:6 #: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:947 #: users/models/user.py:978 users/serializers/group.py:18 msgid "User" @@ -669,7 +666,7 @@ msgstr "ユーザー" #: accounts/serializers/account/account.py:428 #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:182 terminal/notifications.py:230 +#: terminal/notifications.py:158 terminal/notifications.py:207 msgid "Date" msgstr "日付" @@ -852,8 +849,7 @@ msgstr "アカウント" #: terminal/models/session/session.py:42 terminal/serializers/command.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:48 -#: terminal/templates/terminal/_msg_command_warning.html:90 +#: terminal/templates/terminal/_msg_command_warning.html:23 msgid "Command" msgstr "コマンド" @@ -877,6 +873,7 @@ msgstr "家を無視する" #: acls/models/command_acl.py:33 acls/models/command_acl.py:96 #: acls/serializers/command_acl.py:28 #: authentication/serializers/connect_token_secret.py:85 +#: terminal/templates/terminal/_msg_command_warning.html:14 msgid "Command group" msgstr "コマンドグループ" @@ -885,8 +882,7 @@ msgid "The generated regular expression is incorrect: {}" msgstr "生成された正規表現が正しくありません: {}" #: acls/models/command_acl.py:100 -#: terminal/templates/terminal/_msg_command_warning.html:54 -#: terminal/templates/terminal/_msg_command_warning.html:92 +#: terminal/templates/terminal/_msg_command_warning.html:12 msgid "Command acl" msgstr "コマンドフィルタリング" @@ -983,7 +979,7 @@ msgid "Applications" msgstr "アプリケーション" #: applications/models.py:16 xpack/plugins/cloud/models.py:33 -#: xpack/plugins/cloud/serializers/account.py:62 +#: xpack/plugins/cloud/serializers/account.py:63 msgid "Attrs" msgstr "ツールバーの" @@ -1735,7 +1731,7 @@ msgstr "デフォルト・データベース" msgid "This field is required." msgstr "このフィールドは必須です。" -#: assets/serializers/asset/gpt.py:19 +#: assets/serializers/asset/gpt.py:20 msgid "" "If the server cannot directly connect to the API address, you need set up an " "HTTP proxy. e.g. http(s)://host:port" @@ -1743,10 +1739,14 @@ msgstr "" "サーバーが API アドレスに直接接続できない場合は、HTTP プロキシを設定する必要" "があります。例: http(s)://host:port" -#: assets/serializers/asset/gpt.py:23 +#: assets/serializers/asset/gpt.py:24 msgid "HTTP proxy" msgstr "HTTP プロキシ" +#: assets/serializers/asset/gpt.py:31 +msgid "Proxy must start with http:// or https://" +msgstr "エージェントはhttp://またはhttps://で始まる必要があります" + #: assets/serializers/asset/info/gathered.py:6 msgid "Vendor" msgstr "ベンダー" @@ -1997,8 +1997,7 @@ msgid "Rename dir" msgstr "マップディレクトリ" #: audits/const.py:23 rbac/tree.py:229 -#: terminal/templates/terminal/_msg_command_warning.html:68 -#: terminal/templates/terminal/_msg_command_warning.html:96 +#: terminal/templates/terminal/_msg_command_warning.html:18 msgid "View" msgstr "表示" @@ -2082,8 +2081,7 @@ msgstr "書類" #: terminal/models/session/replay.py:9 terminal/models/session/sharing.py:18 #: terminal/models/session/sharing.py:81 #: terminal/templates/terminal/_msg_command_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:66 -#: terminal/templates/terminal/_msg_command_warning.html:95 +#: terminal/templates/terminal/_msg_command_warning.html:17 #: tickets/models/ticket/command_confirm.py:15 msgid "Session" msgstr "セッション" @@ -3032,7 +3030,7 @@ msgid "Copy success" msgstr "コピー成功" #: authentication/utils.py:28 common/utils/ip/geoip/utils.py:24 -#: xpack/plugins/cloud/const.py:27 +#: xpack/plugins/cloud/const.py:29 msgid "LAN" msgstr "ローカルエリアネットワーク" @@ -3780,7 +3778,7 @@ msgstr "Material" msgid "Material Type" msgstr "Material を選択してオプションを設定します。" -#: ops/models/job.py:482 +#: ops/models/job.py:480 msgid "Job Execution" msgstr "ジョブ実行" @@ -3926,8 +3924,7 @@ msgstr "アプリ組織" #: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:89 #: rbac/const.py:7 rbac/models/rolebinding.py:56 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:63 -#: terminal/templates/terminal/_msg_command_warning.html:72 -#: terminal/templates/terminal/_msg_command_warning.html:98 +#: terminal/templates/terminal/_msg_command_warning.html:21 #: tickets/models/ticket/general.py:302 tickets/serializers/ticket/ticket.py:60 msgid "Organization" msgstr "組織" @@ -5703,7 +5700,7 @@ msgstr "テスト失敗: {}" msgid "Test successful" msgstr "テスト成功" -#: terminal/api/component/storage.py:124 terminal/notifications.py:263 +#: terminal/api/component/storage.py:124 terminal/notifications.py:240 #: terminal/tasks.py:144 msgid "Test failure: Account invalid" msgstr "テスト失敗: アカウントが無効" @@ -5741,7 +5738,7 @@ msgid "Output" msgstr "出力" #: terminal/backends/command/models.py:25 terminal/serializers/command.py:23 -#: terminal/templates/terminal/_msg_command_warning.html:91 +#: terminal/templates/terminal/_msg_command_warning.html:10 msgid "Risk level" msgstr "リスクレベル" @@ -6086,35 +6083,35 @@ msgstr "検証コードが無効" msgid "You have already joined this session" msgstr "すでにこのセッションに参加しています" -#: terminal/notifications.py:24 +#: terminal/notifications.py:25 msgid "Sessions" msgstr "セッション" -#: terminal/notifications.py:71 +#: terminal/notifications.py:72 msgid "Command warning" msgstr "コマンド警告" -#: terminal/notifications.py:154 +#: terminal/notifications.py:130 msgid "Command reject" msgstr "コマンド拒否" -#: terminal/notifications.py:181 terminal/notifications.py:229 +#: terminal/notifications.py:157 terminal/notifications.py:206 msgid "Level" msgstr "レベル" -#: terminal/notifications.py:199 +#: terminal/notifications.py:175 msgid "Batch danger command alert" msgstr "一括危険コマンド警告" -#: terminal/notifications.py:247 +#: terminal/notifications.py:224 msgid "Command and replay storage" msgstr "コマンド及び録画記憶" -#: terminal/notifications.py:248 +#: terminal/notifications.py:225 msgid "Connectivity alarm" msgstr "接続性アラーム" -#: terminal/notifications.py:273 +#: terminal/notifications.py:250 #: terminal/templates/terminal/_msg_check_command_replay_storage_connectivity.html:4 msgid "Invalid storage" msgstr "無効なストレージ" @@ -6391,14 +6388,6 @@ msgstr "チェックコマンドと録画ストレージの接続性" msgid "view" msgstr "表示" -#: terminal/templates/terminal/_msg_command_warning.html:18 -msgid "Item" -msgstr "アイテム" - -#: terminal/templates/terminal/_msg_command_warning.html:22 -msgid "Url" -msgstr "リンク" - #: terminal/utils/db_port_mapper.py:84 msgid "" "No available port is matched. The number of databases may have exceeded the " @@ -6693,7 +6682,7 @@ msgid "Apply actions" msgstr "申請アクション" #: tickets/serializers/ticket/common.py:15 -#: tickets/serializers/ticket/common.py:77 +#: tickets/serializers/ticket/common.py:75 msgid "Created by ticket ({}-{})" msgstr "チケットで作成 ({}-{})" @@ -6701,7 +6690,7 @@ msgstr "チケットで作成 ({}-{})" msgid "The expiration date should be greater than the start date" msgstr "有効期限は開始日より大きくする必要があります" -#: tickets/serializers/ticket/common.py:84 +#: tickets/serializers/ticket/common.py:82 msgid "Permission named `{}` already exists" msgstr "'{}'という名前の権限は既に存在します" @@ -6869,6 +6858,7 @@ msgid "Not a valid ssh public key" msgstr "有効なssh公開鍵ではありません" #: users/forms/profile.py:173 users/models/user.py:786 +#: xpack/plugins/cloud/serializers/account_attrs.py:206 msgid "Public key" msgstr "公開キー" @@ -6897,6 +6887,7 @@ msgid "OTP secret key" msgstr "OTP 秘密" #: users/models/user.py:783 +#: xpack/plugins/cloud/serializers/account_attrs.py:209 msgid "Private key" msgstr "ssh秘密鍵" @@ -7376,70 +7367,74 @@ msgid "Tencent Cloud (Lighthouse)" msgstr "テンセント雲(軽量アプリケーション)" #: xpack/plugins/cloud/const.py:19 -msgid "VMware" -msgstr "VMware" - -#: xpack/plugins/cloud/const.py:20 xpack/plugins/cloud/providers/nutanix.py:13 -msgid "Nutanix" -msgstr "Nutanix" - -#: xpack/plugins/cloud/const.py:21 -msgid "Huawei Private Cloud" -msgstr "華為私有雲" - -#: xpack/plugins/cloud/const.py:22 -msgid "Qingyun Private Cloud" -msgstr "青雲私有雲" - -#: xpack/plugins/cloud/const.py:23 -msgid "CTYun Private Cloud" -msgstr "スカイウィング私有雲" - -#: xpack/plugins/cloud/const.py:24 -msgid "OpenStack" -msgstr "OpenStack" - -#: xpack/plugins/cloud/const.py:25 msgid "Google Cloud Platform" msgstr "谷歌雲" +#: xpack/plugins/cloud/const.py:20 +msgid "UCloud" +msgstr "ucloud" + +#: xpack/plugins/cloud/const.py:22 +msgid "VMware" +msgstr "VMware" + +#: xpack/plugins/cloud/const.py:23 xpack/plugins/cloud/providers/nutanix.py:13 +msgid "Nutanix" +msgstr "Nutanix" + +#: xpack/plugins/cloud/const.py:24 +msgid "Huawei Private Cloud" +msgstr "華為私有雲" + +#: xpack/plugins/cloud/const.py:25 +msgid "Qingyun Private Cloud" +msgstr "青雲私有雲" + #: xpack/plugins/cloud/const.py:26 +msgid "CTYun Private Cloud" +msgstr "スカイウィング私有雲" + +#: xpack/plugins/cloud/const.py:27 +msgid "OpenStack" +msgstr "OpenStack" + +#: xpack/plugins/cloud/const.py:28 msgid "Fusion Compute" msgstr "融合計算" -#: xpack/plugins/cloud/const.py:31 +#: xpack/plugins/cloud/const.py:33 msgid "Private IP" msgstr "プライベートIP" -#: xpack/plugins/cloud/const.py:32 +#: xpack/plugins/cloud/const.py:34 msgid "Public IP" msgstr "パブリックIP" -#: xpack/plugins/cloud/const.py:36 +#: xpack/plugins/cloud/const.py:38 msgid "Instance name" msgstr "インスタンス名" -#: xpack/plugins/cloud/const.py:37 +#: xpack/plugins/cloud/const.py:39 msgid "Instance name and Partial IP" msgstr "インスタンス名と部分IP" -#: xpack/plugins/cloud/const.py:42 +#: xpack/plugins/cloud/const.py:44 msgid "Succeed" msgstr "成功" -#: xpack/plugins/cloud/const.py:46 +#: xpack/plugins/cloud/const.py:48 msgid "Unsync" msgstr "同期していません" -#: xpack/plugins/cloud/const.py:47 +#: xpack/plugins/cloud/const.py:49 msgid "New Sync" msgstr "新しい同期" -#: xpack/plugins/cloud/const.py:48 +#: xpack/plugins/cloud/const.py:50 msgid "Synced" msgstr "同期済み" -#: xpack/plugins/cloud/const.py:49 +#: xpack/plugins/cloud/const.py:51 msgid "Released" msgstr "リリース済み" @@ -7705,11 +7700,11 @@ msgstr "華南-広州-友好ユーザー環境" msgid "CN East-Suqian" msgstr "華東-宿遷" -#: xpack/plugins/cloud/serializers/account.py:63 +#: xpack/plugins/cloud/serializers/account.py:64 msgid "Validity display" msgstr "有効表示" -#: xpack/plugins/cloud/serializers/account.py:64 +#: xpack/plugins/cloud/serializers/account.py:65 msgid "Provider display" msgstr "プロバイダ表示" @@ -7729,6 +7724,7 @@ msgstr "サブスクリプションID" #: xpack/plugins/cloud/serializers/account_attrs.py:103 #: xpack/plugins/cloud/serializers/account_attrs.py:119 #: xpack/plugins/cloud/serializers/account_attrs.py:149 +#: xpack/plugins/cloud/serializers/account_attrs.py:202 msgid "API Endpoint" msgstr "APIエンドポイント" @@ -7794,6 +7790,10 @@ msgstr "テストポート" msgid "Test timeout" msgstr "テストタイムアウト" +#: xpack/plugins/cloud/serializers/account_attrs.py:212 +msgid "Project" +msgstr "project" + #: xpack/plugins/cloud/serializers/task.py:28 msgid "" "Only instances matching the IP range will be synced.
If the instance " @@ -7892,5 +7892,11 @@ msgstr "究極のエディション" msgid "Community edition" msgstr "コミュニティ版" +#~ msgid "Item" +#~ msgstr "アイテム" + +#~ msgid "Url" +#~ msgstr "リンク" + #~ msgid "Danger command alert" #~ msgstr "危険コマンドアラート" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 043ff32f6..14979766a 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5261baf86de7c7c1374041d450b51ead282b6f546738c4caffd6b4d4ea22a00 -size 121562 +oid sha256:1b88bc1c5216d7cfc2b0a72d889198bcab84ddd40dd3f5a13a5662dfcf8170ee +size 121846 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 46c564887..e69b0143d 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-19 10:00+0800\n" +"POT-Creation-Date: 2023-07-19 16:59+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -94,7 +94,7 @@ msgstr "更新" #: accounts/const/account.py:29 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 -#: ops/const.py:58 terminal/const.py:77 xpack/plugins/cloud/const.py:41 +#: ops/const.py:58 terminal/const.py:77 xpack/plugins/cloud/const.py:43 msgid "Failed" msgstr "失败" @@ -199,9 +199,8 @@ msgstr "仅创建" #: audits/models.py:53 authentication/models/connection_token.py:36 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:34 #: terminal/backends/command/models.py:18 terminal/models/session/session.py:31 -#: terminal/notifications.py:179 terminal/serializers/command.py:18 -#: terminal/templates/terminal/_msg_command_warning.html:36 -#: terminal/templates/terminal/_msg_command_warning.html:82 +#: terminal/notifications.py:155 terminal/serializers/command.py:18 +#: terminal/templates/terminal/_msg_command_warning.html:4 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 msgid "Asset" msgstr "资产" @@ -235,8 +234,7 @@ msgstr "来源 ID" #: assets/serializers/gateway.py:28 audits/models.py:54 ops/models/base.py:18 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 #: terminal/backends/command/models.py:19 terminal/models/session/session.py:33 -#: terminal/templates/terminal/_msg_command_warning.html:42 -#: terminal/templates/terminal/_msg_command_warning.html:83 +#: terminal/templates/terminal/_msg_command_warning.html:8 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" msgstr "账号" @@ -654,10 +652,9 @@ msgstr "ID" #: perms/serializers/permission.py:30 rbac/builtin.py:123 #: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:17 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:180 terminal/notifications.py:228 +#: terminal/notifications.py:156 terminal/notifications.py:205 #: terminal/serializers/command.py:17 -#: terminal/templates/terminal/_msg_command_warning.html:30 -#: terminal/templates/terminal/_msg_command_warning.html:81 +#: terminal/templates/terminal/_msg_command_warning.html:6 #: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:947 #: users/models/user.py:978 users/serializers/group.py:18 msgid "User" @@ -665,7 +662,7 @@ msgstr "用户" #: accounts/serializers/account/account.py:428 #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:182 terminal/notifications.py:230 +#: terminal/notifications.py:158 terminal/notifications.py:207 msgid "Date" msgstr "日期" @@ -848,8 +845,7 @@ msgstr "账号管理" #: terminal/models/session/session.py:42 terminal/serializers/command.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:48 -#: terminal/templates/terminal/_msg_command_warning.html:90 +#: terminal/templates/terminal/_msg_command_warning.html:23 msgid "Command" msgstr "命令" @@ -873,6 +869,7 @@ msgstr "忽略大小写" #: acls/models/command_acl.py:33 acls/models/command_acl.py:96 #: acls/serializers/command_acl.py:28 #: authentication/serializers/connect_token_secret.py:85 +#: terminal/templates/terminal/_msg_command_warning.html:14 msgid "Command group" msgstr "命令组" @@ -881,8 +878,7 @@ msgid "The generated regular expression is incorrect: {}" msgstr "生成的正则表达式有误" #: acls/models/command_acl.py:100 -#: terminal/templates/terminal/_msg_command_warning.html:54 -#: terminal/templates/terminal/_msg_command_warning.html:92 +#: terminal/templates/terminal/_msg_command_warning.html:12 msgid "Command acl" msgstr "命令过滤" @@ -978,7 +974,7 @@ msgid "Applications" msgstr "应用管理" #: applications/models.py:16 xpack/plugins/cloud/models.py:33 -#: xpack/plugins/cloud/serializers/account.py:62 +#: xpack/plugins/cloud/serializers/account.py:63 msgid "Attrs" msgstr "属性" @@ -1726,7 +1722,7 @@ msgstr "默认数据库" msgid "This field is required." msgstr "该字段是必填项。" -#: assets/serializers/asset/gpt.py:19 +#: assets/serializers/asset/gpt.py:20 msgid "" "If the server cannot directly connect to the API address, you need set up an " "HTTP proxy. e.g. http(s)://host:port" @@ -1734,10 +1730,14 @@ msgstr "" "如果服务器不能直接访问 api 地址,你需要设置一个 HTTP 代理。例如 http(s)://" "host:port" -#: assets/serializers/asset/gpt.py:23 +#: assets/serializers/asset/gpt.py:24 msgid "HTTP proxy" msgstr "HTTP(s) 代理" +#: assets/serializers/asset/gpt.py:31 +msgid "Proxy must start with http:// or https://" +msgstr "代理必须以 http:// 或 https:// 开头" + #: assets/serializers/asset/info/gathered.py:6 msgid "Vendor" msgstr "制造商" @@ -1981,8 +1981,7 @@ msgid "Rename dir" msgstr "映射目录" #: audits/const.py:23 rbac/tree.py:229 -#: terminal/templates/terminal/_msg_command_warning.html:68 -#: terminal/templates/terminal/_msg_command_warning.html:96 +#: terminal/templates/terminal/_msg_command_warning.html:18 msgid "View" msgstr "查看" @@ -2066,8 +2065,7 @@ msgstr "文件" #: terminal/models/session/replay.py:9 terminal/models/session/sharing.py:18 #: terminal/models/session/sharing.py:81 #: terminal/templates/terminal/_msg_command_alert.html:10 -#: terminal/templates/terminal/_msg_command_warning.html:66 -#: terminal/templates/terminal/_msg_command_warning.html:95 +#: terminal/templates/terminal/_msg_command_warning.html:17 #: tickets/models/ticket/command_confirm.py:15 msgid "Session" msgstr "会话" @@ -2992,7 +2990,7 @@ msgid "Copy success" msgstr "复制成功" #: authentication/utils.py:28 common/utils/ip/geoip/utils.py:24 -#: xpack/plugins/cloud/const.py:27 +#: xpack/plugins/cloud/const.py:29 msgid "LAN" msgstr "局域网" @@ -3733,7 +3731,7 @@ msgstr "Material" msgid "Material Type" msgstr "Material 类型" -#: ops/models/job.py:482 +#: ops/models/job.py:480 msgid "Job Execution" msgstr "作业执行" @@ -3878,8 +3876,7 @@ msgstr "组织管理" #: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:89 #: rbac/const.py:7 rbac/models/rolebinding.py:56 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:63 -#: terminal/templates/terminal/_msg_command_warning.html:72 -#: terminal/templates/terminal/_msg_command_warning.html:98 +#: terminal/templates/terminal/_msg_command_warning.html:21 #: tickets/models/ticket/general.py:302 tickets/serializers/ticket/ticket.py:60 msgid "Organization" msgstr "组织" @@ -5616,7 +5613,7 @@ msgstr "测试失败: {}" msgid "Test successful" msgstr "测试成功" -#: terminal/api/component/storage.py:124 terminal/notifications.py:263 +#: terminal/api/component/storage.py:124 terminal/notifications.py:240 #: terminal/tasks.py:144 msgid "Test failure: Account invalid" msgstr "测试失败: 账号无效" @@ -5654,7 +5651,7 @@ msgid "Output" msgstr "输出" #: terminal/backends/command/models.py:25 terminal/serializers/command.py:23 -#: terminal/templates/terminal/_msg_command_warning.html:91 +#: terminal/templates/terminal/_msg_command_warning.html:10 msgid "Risk level" msgstr "风险等级" @@ -5999,35 +5996,35 @@ msgstr "验证码不正确" msgid "You have already joined this session" msgstr "您已经加入过此会话" -#: terminal/notifications.py:24 +#: terminal/notifications.py:25 msgid "Sessions" msgstr "会话管理" -#: terminal/notifications.py:71 +#: terminal/notifications.py:72 msgid "Command warning" msgstr "命令告警" -#: terminal/notifications.py:154 +#: terminal/notifications.py:130 msgid "Command reject" msgstr "命令拒绝" -#: terminal/notifications.py:181 terminal/notifications.py:229 +#: terminal/notifications.py:157 terminal/notifications.py:206 msgid "Level" msgstr "级别" -#: terminal/notifications.py:199 +#: terminal/notifications.py:175 msgid "Batch danger command alert" msgstr "批量危险命令告警" -#: terminal/notifications.py:247 +#: terminal/notifications.py:224 msgid "Command and replay storage" msgstr "命令及录像存储" -#: terminal/notifications.py:248 +#: terminal/notifications.py:225 msgid "Connectivity alarm" msgstr "可连接性告警" -#: terminal/notifications.py:273 +#: terminal/notifications.py:250 #: terminal/templates/terminal/_msg_check_command_replay_storage_connectivity.html:4 msgid "Invalid storage" msgstr "无效的存储" @@ -6299,14 +6296,6 @@ msgstr "检查命令及录像存储可连接性 " msgid "view" msgstr "查看" -#: terminal/templates/terminal/_msg_command_warning.html:18 -msgid "Item" -msgstr "项目" - -#: terminal/templates/terminal/_msg_command_warning.html:22 -msgid "Url" -msgstr "链接" - #: terminal/utils/db_port_mapper.py:84 msgid "" "No available port is matched. The number of databases may have exceeded the " @@ -6597,7 +6586,7 @@ msgid "Apply actions" msgstr "申请动作" #: tickets/serializers/ticket/common.py:15 -#: tickets/serializers/ticket/common.py:77 +#: tickets/serializers/ticket/common.py:75 msgid "Created by ticket ({}-{})" msgstr "通过工单创建 ({}-{})" @@ -6605,7 +6594,7 @@ msgstr "通过工单创建 ({}-{})" msgid "The expiration date should be greater than the start date" msgstr "过期时间要大于开始时间" -#: tickets/serializers/ticket/common.py:84 +#: tickets/serializers/ticket/common.py:82 msgid "Permission named `{}` already exists" msgstr "授权名称 `{}` 已存在" @@ -6771,6 +6760,7 @@ msgid "Not a valid ssh public key" msgstr "SSH密钥不合法" #: users/forms/profile.py:173 users/models/user.py:786 +#: xpack/plugins/cloud/serializers/account_attrs.py:206 msgid "Public key" msgstr "SSH公钥" @@ -6799,6 +6789,7 @@ msgid "OTP secret key" msgstr "OTP 密钥" #: users/models/user.py:783 +#: xpack/plugins/cloud/serializers/account_attrs.py:209 msgid "Private key" msgstr "ssh私钥" @@ -7265,70 +7256,74 @@ msgid "Tencent Cloud (Lighthouse)" msgstr "腾讯云(轻量服务器应用)" #: xpack/plugins/cloud/const.py:19 -msgid "VMware" -msgstr "VMware" - -#: xpack/plugins/cloud/const.py:20 xpack/plugins/cloud/providers/nutanix.py:13 -msgid "Nutanix" -msgstr "Nutanix" - -#: xpack/plugins/cloud/const.py:21 -msgid "Huawei Private Cloud" -msgstr "华为私有云" - -#: xpack/plugins/cloud/const.py:22 -msgid "Qingyun Private Cloud" -msgstr "青云私有云" - -#: xpack/plugins/cloud/const.py:23 -msgid "CTYun Private Cloud" -msgstr "天翼私有云" - -#: xpack/plugins/cloud/const.py:24 -msgid "OpenStack" -msgstr "OpenStack" - -#: xpack/plugins/cloud/const.py:25 msgid "Google Cloud Platform" msgstr "谷歌云" +#: xpack/plugins/cloud/const.py:20 +msgid "UCloud" +msgstr "ucloud" + +#: xpack/plugins/cloud/const.py:22 +msgid "VMware" +msgstr "VMware" + +#: xpack/plugins/cloud/const.py:23 xpack/plugins/cloud/providers/nutanix.py:13 +msgid "Nutanix" +msgstr "Nutanix" + +#: xpack/plugins/cloud/const.py:24 +msgid "Huawei Private Cloud" +msgstr "华为私有云" + +#: xpack/plugins/cloud/const.py:25 +msgid "Qingyun Private Cloud" +msgstr "青云私有云" + #: xpack/plugins/cloud/const.py:26 +msgid "CTYun Private Cloud" +msgstr "天翼私有云" + +#: xpack/plugins/cloud/const.py:27 +msgid "OpenStack" +msgstr "OpenStack" + +#: xpack/plugins/cloud/const.py:28 msgid "Fusion Compute" msgstr "融合计算" -#: xpack/plugins/cloud/const.py:31 +#: xpack/plugins/cloud/const.py:33 msgid "Private IP" msgstr "私有IP" -#: xpack/plugins/cloud/const.py:32 +#: xpack/plugins/cloud/const.py:34 msgid "Public IP" msgstr "公网IP" -#: xpack/plugins/cloud/const.py:36 +#: xpack/plugins/cloud/const.py:38 msgid "Instance name" msgstr "实例名称" -#: xpack/plugins/cloud/const.py:37 +#: xpack/plugins/cloud/const.py:39 msgid "Instance name and Partial IP" msgstr "实例名称和部分IP" -#: xpack/plugins/cloud/const.py:42 +#: xpack/plugins/cloud/const.py:44 msgid "Succeed" msgstr "成功" -#: xpack/plugins/cloud/const.py:46 +#: xpack/plugins/cloud/const.py:48 msgid "Unsync" msgstr "未同步" -#: xpack/plugins/cloud/const.py:47 +#: xpack/plugins/cloud/const.py:49 msgid "New Sync" msgstr "新同步" -#: xpack/plugins/cloud/const.py:48 +#: xpack/plugins/cloud/const.py:50 msgid "Synced" msgstr "已同步" -#: xpack/plugins/cloud/const.py:49 +#: xpack/plugins/cloud/const.py:51 msgid "Released" msgstr "已释放" @@ -7594,11 +7589,11 @@ msgstr "华南-广州-友好用户环境" msgid "CN East-Suqian" msgstr "华东-宿迁" -#: xpack/plugins/cloud/serializers/account.py:63 +#: xpack/plugins/cloud/serializers/account.py:64 msgid "Validity display" msgstr "有效性显示" -#: xpack/plugins/cloud/serializers/account.py:64 +#: xpack/plugins/cloud/serializers/account.py:65 msgid "Provider display" msgstr "服务商显示" @@ -7618,6 +7613,7 @@ msgstr "订阅 ID" #: xpack/plugins/cloud/serializers/account_attrs.py:103 #: xpack/plugins/cloud/serializers/account_attrs.py:119 #: xpack/plugins/cloud/serializers/account_attrs.py:149 +#: xpack/plugins/cloud/serializers/account_attrs.py:202 msgid "API Endpoint" msgstr "API 端点" @@ -7682,6 +7678,10 @@ msgstr "测试端口" msgid "Test timeout" msgstr "测试超时时间" +#: xpack/plugins/cloud/serializers/account_attrs.py:212 +msgid "Project" +msgstr "project" + #: xpack/plugins/cloud/serializers/task.py:28 msgid "" "Only instances matching the IP range will be synced.
If the instance " @@ -7778,5 +7778,11 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" +#~ msgid "Item" +#~ msgstr "项目" + +#~ msgid "Url" +#~ msgstr "链接" + #~ msgid "Danger command alert" #~ msgstr "危险命令告警" From e1af380ad5e366c5cbe7faa92519d69a42db9d96 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 19 Jul 2023 17:12:44 +0800 Subject: [PATCH 149/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20Core=20Wor?= =?UTF-8?q?ker=20=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/management/commands/services/command.py | 6 +----- jms | 8 ++++++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/common/management/commands/services/command.py b/apps/common/management/commands/services/command.py index 6ec38ab2b..487d9ce5f 100644 --- a/apps/common/management/commands/services/command.py +++ b/apps/common/management/commands/services/command.py @@ -94,15 +94,11 @@ class BaseActionCommand(BaseCommand): super().__init__(*args, **kwargs) def add_arguments(self, parser): - cores = 10 - if (multiprocessing.cpu_count() * 2 + 1) < cores: - cores = multiprocessing.cpu_count() * 2 + 1 - parser.add_argument( 'services', nargs='+', choices=Services.export_services_values(), help='Service', ) parser.add_argument('-d', '--daemon', nargs="?", const=True) - parser.add_argument('-w', '--worker', type=int, nargs="?", default=cores) + parser.add_argument('-w', '--worker', type=int, nargs="?", default=4) parser.add_argument('-f', '--force', nargs="?", const=True) def initial_util(self, *args, **options): diff --git a/jms b/jms index c75011edd..0b2cf94d0 100755 --- a/jms +++ b/jms @@ -152,10 +152,14 @@ def start_services(): start_args = [] if args.daemon: start_args.append('--daemon') - if args.worker: - start_args.extend(['--worker', str(args.worker)]) if args.force: start_args.append('--force') + if args.worker: + start_args.extend(['--worker', str(args.worker)]) + else: + worker = os.environ.get('CORE_WORKER') + if isinstance(worker, str) and worker.isdigit(): + start_args.extend(['--worker', worker]) try: management.call_command(action, *services, *start_args) From 47195e2c444ac02792079d7d808d8cbacbcd34e1 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 19 Jul 2023 18:10:40 +0800 Subject: [PATCH 150/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E7=AB=AF=E6=96=B9=E5=BC=8F=E8=AE=BF=E9=97=AE=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=20Endpoint=20=E6=A0=87=E7=AD=BE=E5=8C=B9=E9=85=8D?= =?UTF-8?q?=E7=AD=96=E7=95=A5=E4=B8=8D=E7=94=9F=E6=95=88=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/connection_token.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index d6a872841..94bed4f28 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -23,7 +23,7 @@ from common.utils.http import is_true, is_false from orgs.mixins.api import RootOrgViewMixin from perms.models import ActionChoices from terminal.connect_methods import NativeClient, ConnectMethodUtil -from terminal.models import EndpointRule +from terminal.models import EndpointRule, Endpoint from ..models import ConnectionToken, date_expired_default from ..serializers import ( ConnectionTokenSerializer, ConnectionTokenSecretSerializer, @@ -166,11 +166,13 @@ class RDPFileClientProtocolURLMixin: return data def get_smart_endpoint(self, protocol, asset=None): - target_ip = asset.get_target_ip() if asset else '' - endpoint = EndpointRule.match_endpoint( - target_instance=asset, target_ip=target_ip, - protocol=protocol, request=self.request - ) + endpoint = Endpoint.match_by_instance_label(asset, protocol) + if not endpoint: + target_ip = asset.get_target_ip() if asset else '' + endpoint = EndpointRule.match_endpoint( + target_instance=asset, target_ip=target_ip, + protocol=protocol, request=self.request + ) return endpoint From 046342ceee465a65fc89c303680753da3b337ffd Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 19 Jul 2023 16:53:09 +0800 Subject: [PATCH 151/167] =?UTF-8?q?perf:=20=E5=B9=B3=E5=8F=B0=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E8=87=AA=E5=8A=A8=E5=8C=96=E8=AE=BE=E7=BD=AE=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/serializers/platform.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/apps/assets/serializers/platform.py b/apps/assets/serializers/platform.py index 12de700a9..d42eaab19 100644 --- a/apps/assets/serializers/platform.py +++ b/apps/assets/serializers/platform.py @@ -51,8 +51,9 @@ class PlatformProtocolSerializer(serializers.ModelSerializer): class Meta: model = PlatformProtocol fields = [ - "id", "name", "port", "port_from_addr", "primary", - "required", "default", "public", "secret_types", "setting", + "id", "name", "port", "port_from_addr", + "primary", "required", "default", "public", + "secret_types", "setting", ] extra_kwargs = { "primary": { @@ -154,6 +155,18 @@ class PlatformSerializer(WritableNestedModelSerializer): "domain_default": {"label": _('Default Domain')}, } + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.set_initial_value() + + def set_initial_value(self): + if not hasattr(self, 'initial_data'): + return + if self.instance: + return + if not self.initial_data.get('automation'): + self.initial_data['automation'] = {} + @property def platform_category_type(self): if self.instance: @@ -199,8 +212,9 @@ class PlatformSerializer(WritableNestedModelSerializer): def validate_automation(self, automation): automation = automation or {} - automation = automation.get('ansible_enabled', False) \ - and self.constraints['automation'].get('ansible_enabled', False) + ansible_enabled = automation.get('ansible_enabled', False) \ + and self.constraints['automation'].get('ansible_enabled', False) + automation['ansible_enable'] = ansible_enabled return automation From de4ef7d1b55caa37807cda31ab9afb688064d703 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 19 Jul 2023 19:00:15 +0800 Subject: [PATCH 152/167] =?UTF-8?q?perf:=20GPT=E8=B5=84=E4=BA=A7=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E8=8A=82=E7=82=B9=E5=AF=BC=E8=87=B4=E8=B5=84=E4=BA=A7?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE=E5=8F=98=E5=A4=9A=20(#11021)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/assets/serializers/asset/common.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index ba642dd96..90d5c83c3 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -167,10 +167,9 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali return protocols_required, protocols_default = self._get_protocols_required_default() - protocols_data = [ - {'name': p.name, 'port': p.port} - for p in protocols_required + protocols_default - ] + protocol_map = {str(protocol.id): protocol for protocol in protocols_required + protocols_default} + protocols = list(protocol_map.values()) + protocols_data = [{'name': p.name, 'port': p.port} for p in protocols] self.initial_data['protocols'] = protocols_data def _init_field_choices(self): @@ -263,7 +262,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali error = p.get('name') + ': ' + _("port out of range (0-65535)") raise serializers.ValidationError(error) - protocols_required, protocols_default = self._get_protocols_required_default() + protocols_required, __ = self._get_protocols_required_default() protocols_not_found = [p.name for p in protocols_required if p.name not in protocols_data_map] if protocols_not_found: raise serializers.ValidationError({ From 1b0d23fbf4036d1b71d5150bf8f75192b5f10a6b Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 19 Jul 2023 19:37:55 +0800 Subject: [PATCH 153/167] =?UTF-8?q?fix:=20playbook=20=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E5=88=A0=E9=99=A4=20500=20(#11022)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/ops/api/playbook.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/ops/api/playbook.py b/apps/ops/api/playbook.py index d848e029c..9d74aa565 100644 --- a/apps/ops/api/playbook.py +++ b/apps/ops/api/playbook.py @@ -4,6 +4,7 @@ import zipfile from django.conf import settings from django.shortcuts import get_object_or_404 +from django.utils.translation import ugettext_lazy as _ from rest_framework import status from common.exceptions import JMSException @@ -12,7 +13,6 @@ from rbac.permissions import RBACPermission from ..exception import PlaybookNoValidEntry from ..models import Playbook from ..serializers.playbook import PlaybookSerializer -from django.utils.translation import ugettext_lazy as _ __all__ = ["PlaybookViewSet", "PlaybookFileBrowserAPIView"] @@ -33,7 +33,6 @@ class PlaybookViewSet(OrgBulkModelViewSet): search_fields = ('name', 'comment') def perform_destroy(self, instance): - instance = self.get_object() if instance.job_set.exists(): raise JMSException(code='playbook_has_job', detail={"msg": _("Currently playbook is being used in a job")}) instance_id = instance.id From 23361fdba9f6dc6141156decaacf9bc63f8652e2 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 19 Jul 2023 19:54:17 +0800 Subject: [PATCH 154/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E5=B9=B3=E5=8F=B0=E5=AF=BC=E5=85=A5=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98(ID=E6=B2=A1=E6=9C=89=E8=BF=94?= =?UTF-8?q?=E5=9B=9E)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/drf/parsers/base.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/common/drf/parsers/base.py b/apps/common/drf/parsers/base.py index 9ba77ca72..6d4a745df 100644 --- a/apps/common/drf/parsers/base.py +++ b/apps/common/drf/parsers/base.py @@ -52,14 +52,15 @@ class BaseFileParser(BaseParser): fields_map = {} fields = self.serializer_fields for k, v in fields.items(): - if v.read_only: + # 资产平台的 id 是只读的, 导入更新资产平台会失败 + if v.read_only and k not in ['id', 'pk']: continue fields_map.update({ v.label: k, k: k }) field_names = [ - fields_map.get(column_title.strip('*'), '') + fields_map.get(column_title.strip('*').lower(), '') for column_title in column_titles ] return field_names From cfca5191589118c445931498caf23fbaa8a38210 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 19 Jul 2023 20:16:40 +0800 Subject: [PATCH 155/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E7=9A=84=E8=B4=A6=E5=8F=B7=EF=BC=8C=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=90=8D=E7=9B=B8=E5=90=8C=E7=9A=84=EF=BC=8C=E5=8F=AA=E6=9C=89?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E7=9A=84=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/perms/utils/account.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/apps/perms/utils/account.py b/apps/perms/utils/account.py index 62c7b68d0..caef9dc30 100644 --- a/apps/perms/utils/account.py +++ b/apps/perms/utils/account.py @@ -41,7 +41,10 @@ class PermAccountUtil(AssetPermissionUtil): alias_date_expired_mapper[alias].append(perm.date_expired) asset_accounts = asset.accounts.all().active() - username_account_mapper = {account.username: account for account in asset_accounts} + # username_accounts_mapper = {account.username: account for account in asset_accounts} + username_accounts_mapper = defaultdict(list) + for account in asset_accounts: + username_accounts_mapper[account.username].append(account) cleaned_accounts_action_bit = defaultdict(int) cleaned_accounts_expired = defaultdict(list) @@ -56,9 +59,10 @@ class PermAccountUtil(AssetPermissionUtil): ) for alias, action_bit in alias_action_bit_mapper.items(): + account = None if alias == AliasAccount.USER: - if user.username in username_account_mapper: - account = username_account_mapper[user.username] + if user.username in username_accounts_mapper: + account = username_accounts_mapper[user.username] else: account = Account.get_user_account() elif alias == AliasAccount.INPUT: @@ -67,12 +71,14 @@ class PermAccountUtil(AssetPermissionUtil): account = Account.get_anonymous_account() elif alias.startswith('@'): continue - elif alias in username_account_mapper: - account = username_account_mapper[alias] - else: - account = None + accounts = [] if account: + accounts.append(account) + if alias in username_accounts_mapper: + accounts += username_accounts_mapper[alias] + + for account in accounts: cleaned_accounts_action_bit[account] |= action_bit cleaned_accounts_expired[account].extend(alias_date_expired_mapper[alias]) From 14efd9afc1c2c7fdb38c1c8baeccdfcaf00e505c Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 19 Jul 2023 20:27:06 +0800 Subject: [PATCH 156/167] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E5=AF=BC=E8=87=B4=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/perms/utils/account.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/perms/utils/account.py b/apps/perms/utils/account.py index caef9dc30..d97343372 100644 --- a/apps/perms/utils/account.py +++ b/apps/perms/utils/account.py @@ -60,25 +60,25 @@ class PermAccountUtil(AssetPermissionUtil): for alias, action_bit in alias_action_bit_mapper.items(): account = None + _accounts = [] if alias == AliasAccount.USER: if user.username in username_accounts_mapper: - account = username_accounts_mapper[user.username] + _accounts = username_accounts_mapper[user.username] else: account = Account.get_user_account() elif alias == AliasAccount.INPUT: account = Account.get_manual_account() elif alias == AliasAccount.ANON: account = Account.get_anonymous_account() + elif alias in username_accounts_mapper: + _accounts = username_accounts_mapper[alias] elif alias.startswith('@'): continue - accounts = [] if account: - accounts.append(account) - if alias in username_accounts_mapper: - accounts += username_accounts_mapper[alias] + _accounts += [account] - for account in accounts: + for account in _accounts: cleaned_accounts_action_bit[account] |= action_bit cleaned_accounts_expired[account].extend(alias_date_expired_mapper[alias]) From 2291cfeaae45f99cb3bb392af0bc4a89a0c09c84 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 20 Jul 2023 10:41:11 +0800 Subject: [PATCH 157/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20ConnectionT?= =?UTF-8?q?oken=20=E9=BB=98=E8=AE=A4=E5=80=BC=E7=B1=BB=E5=9E=8B=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E8=BD=AC=E5=8C=96=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/connection_token.py | 3 ++- apps/jumpserver/conf.py | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 94bed4f28..a98855f85 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -218,7 +218,8 @@ class ExtraActionApiMixin(RDPFileClientProtocolURLMixin): def reuse(self, request, *args, **kwargs): instance = self.get_object() if not settings.CONNECTION_TOKEN_REUSABLE: - raise serializers.ValidationError(_('Reusable connection token is not allowed, global setting not enabled')) + error = _('Reusable connection token is not allowed, global setting not enabled') + raise serializers.ValidationError(error) serializer = self.get_serializer(instance, data=request.data, partial=True) serializer.is_valid(raise_exception=True) is_reusable = serializer.validated_data.get('is_reusable', False) diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 8990a4223..33f0dbaf4 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -232,8 +232,12 @@ class Config(dict): 'SESSION_COOKIE_AGE': 3600 * 24, 'SESSION_EXPIRE_AT_BROWSER_CLOSE': False, 'LOGIN_URL': reverse_lazy('authentication:login'), - 'CONNECTION_TOKEN_ONETIME_EXPIRATION': 5 * 60, # 默认 - 'CONNECTION_TOKEN_REUSABLE_EXPIRATION': 60 * 60 * 24 * 30, # 最大 + + 'CONNECTION_TOKEN_ONETIME_EXPIRATION': 5 * 60, # 默认(new) + 'CONNECTION_TOKEN_EXPIRATION': 5 * 60, # 默认(old) + + 'CONNECTION_TOKEN_REUSABLE_EXPIRATION': 60 * 60 * 24 * 30, # 最大(new) + 'CONNECTION_TOKEN_EXPIRATION_MAX': 60 * 60 * 24 * 30, # 最大(old) 'CONNECTION_TOKEN_REUSABLE': False, # Custom Config From ffb400d70d4fdd31bc5fbe514e18e709ce262d4f Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 20 Jul 2023 11:22:08 +0800 Subject: [PATCH 158/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=20Oracle=20=E6=95=B0=E6=8D=AE=E5=BA=93=E7=AB=AF?= =?UTF-8?q?=E5=8F=A3=E8=B6=85=E8=BF=87=E8=8C=83=E5=9B=B4=E5=90=8E=E6=8A=A5?= =?UTF-8?q?=E9=94=99=20500=20=E5=B9=B6=E4=B8=94=E4=B8=8D=E5=9B=9E=E6=BB=9A?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/signal_handlers/db_port.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/terminal/signal_handlers/db_port.py b/apps/terminal/signal_handlers/db_port.py index d6118d40e..1d2a1d465 100644 --- a/apps/terminal/signal_handlers/db_port.py +++ b/apps/terminal/signal_handlers/db_port.py @@ -1,7 +1,7 @@ from django.db.models.signals import post_delete, post_save from django.dispatch import receiver -from assets.models import Asset +from assets.models import Asset, Database from common.decorators import on_transaction_commit from common.signals import django_ready from common.utils import get_logger @@ -12,16 +12,15 @@ logger = get_logger(__file__) @receiver(django_ready) def check_db_port_mapper(sender, **kwargs): - logger.info('Check oracle ports') + logger.info('Check oracle ports (MAGNUS_ORACLE_PORTS)') try: db_port_manager.check() except Exception as e: - pass + logger.error(e) -@receiver(post_save, sender=Asset) -@on_transaction_commit -def on_db_created(sender, instance: Asset, created, **kwargs): +@receiver(post_save, sender=Database) +def on_db_created(sender, instance: Database, created, **kwargs): if instance.type != 'oracle': return if not created: From f5d9dedae1208472e1bbaa6451401f92055fe777 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 20 Jul 2023 11:49:08 +0800 Subject: [PATCH 159/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Endpoint=20?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=20Oracle=20port=20=E7=9A=84=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/models/component/endpoint.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/terminal/models/component/endpoint.py b/apps/terminal/models/component/endpoint.py index d8c74e689..c68c06307 100644 --- a/apps/terminal/models/component/endpoint.py +++ b/apps/terminal/models/component/endpoint.py @@ -34,9 +34,11 @@ class Endpoint(JMSBaseModel): def get_port(self, target_instance, protocol): from terminal.utils import db_port_manager - from assets.const import DatabaseTypes + from assets.const import DatabaseTypes, Protocol + if isinstance(target_instance, Asset) and \ - target_instance.is_type(DatabaseTypes.ORACLE): + target_instance.is_type(DatabaseTypes.ORACLE) and \ + protocol == Protocol.oracle: port = db_port_manager.get_port_by_db(target_instance) else: port = getattr(self, f'{protocol}_port', 0) From c50330e05588385decda5deaed69a1f0199bcd7d Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 20 Jul 2023 11:55:59 +0800 Subject: [PATCH 160/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=88=A0?= =?UTF-8?q?=E9=99=A4Oracle=E6=95=B0=E6=8D=AE=E5=BA=93=E6=97=B6=E6=8A=A5?= =?UTF-8?q?=E9=94=99=E6=8F=90=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/signal_handlers/db_port.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/terminal/signal_handlers/db_port.py b/apps/terminal/signal_handlers/db_port.py index 1d2a1d465..5ea1c8aab 100644 --- a/apps/terminal/signal_handlers/db_port.py +++ b/apps/terminal/signal_handlers/db_port.py @@ -29,8 +29,7 @@ def on_db_created(sender, instance: Database, created, **kwargs): db_port_manager.check() -@receiver(post_delete, sender=Asset) -@on_transaction_commit +@receiver(post_delete, sender=Database) def on_db_delete(sender, instance, **kwargs): if instance.type != 'oracle': return From 19b91a6c1f8a03cdfd0c5fc2bce90f544cbd3ec6 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 20 Jul 2023 14:57:51 +0800 Subject: [PATCH 161/167] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E5=AF=BC=E5=85=A5=E8=B4=A6=E5=8F=B7=E6=A8=A1=E7=89=88?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E9=97=AE=E9=A2=98=20=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8D=E5=8C=BA=E5=88=86=E5=A4=A7=E5=B0=8F?= =?UTF-8?q?=E5=86=99=20(#11031)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/assets/serializers/asset/common.py | 14 +++++++++----- apps/common/drf/parsers/base.py | 3 ++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index 90d5c83c3..69ccf8e21 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -124,6 +124,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'), default=()) accounts = AssetAccountSerializer(many=True, required=False, allow_null=True, write_only=True, label=_('Account')) nodes_display = serializers.ListField(read_only=False, required=False, label=_("Node path")) + _accounts = None class Meta: model = Asset @@ -151,6 +152,13 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._init_field_choices() + self._extract_accounts() + + def _extract_accounts(self): + if not getattr(self, 'initial_data', None): + return + accounts = self.initial_data.pop('accounts', None) + self._accounts = accounts def _get_protocols_required_default(self): platform = self._asset_platform @@ -276,7 +284,6 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali return for data in accounts_data: data['asset'] = asset.id - s = AssetAccountSerializer(data=accounts_data, many=True) s.is_valid(raise_exception=True) s.save() @@ -284,16 +291,13 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali @atomic def create(self, validated_data): nodes_display = validated_data.pop('nodes_display', '') - accounts = validated_data.pop('accounts', []) instance = super().create(validated_data) - self.accounts_create(accounts, instance) + self.accounts_create(self._accounts, instance) self.perform_nodes_display_create(instance, nodes_display) return instance @atomic def update(self, instance, validated_data): - if not validated_data.get('accounts'): - validated_data.pop('accounts', None) nodes_display = validated_data.pop('nodes_display', '') instance = super().update(instance, validated_data) self.perform_nodes_display_create(instance, nodes_display) diff --git a/apps/common/drf/parsers/base.py b/apps/common/drf/parsers/base.py index 6d4a745df..43d736f21 100644 --- a/apps/common/drf/parsers/base.py +++ b/apps/common/drf/parsers/base.py @@ -59,8 +59,9 @@ class BaseFileParser(BaseParser): v.label: k, k: k }) + lowercase_fields_map = {k.lower(): v for k, v in fields_map.items()} field_names = [ - fields_map.get(column_title.strip('*').lower(), '') + lowercase_fields_map.get(column_title.strip('*').lower(), '') for column_title in column_titles ] return field_names From 08bc3d14aa101fa7b8ca8a36eb6a33b2682207bd Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 20 Jul 2023 14:46:56 +0800 Subject: [PATCH 162/167] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20json=20m2m?= =?UTF-8?q?=20field=20=E4=B8=AD=E6=AD=A3=E5=88=99=E6=9C=89=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E5=8C=B9=E9=85=8D=E4=B8=8D=E6=AD=A3=E7=A1=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/db/fields.py | 2 +- apps/perms/tasks.py | 21 +++++++++++---------- apps/terminal/utils/db_port_mapper.py | 1 + requirements/issues.txt | 6 +++++- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/apps/common/db/fields.py b/apps/common/db/fields.py index aff54c75a..dee051da5 100644 --- a/apps/common/db/fields.py +++ b/apps/common/db/fields.py @@ -387,7 +387,7 @@ class RelatedManager: lookup = "{}__{}".format(name, match) q = Q(**{lookup: val}) except re.error: - q = ~Q() + q = Q(pk__isnull=True) elif match == "not": q = ~Q(**{name: val}) elif match in ['m2m', 'in']: diff --git a/apps/perms/tasks.py b/apps/perms/tasks.py index 4420322d1..82f97bf8c 100644 --- a/apps/perms/tasks.py +++ b/apps/perms/tasks.py @@ -1,25 +1,25 @@ # ~*~ coding: utf-8 ~*~ from __future__ import absolute_import, unicode_literals -from datetime import timedelta + from collections import defaultdict +from datetime import timedelta -from django.db.transaction import atomic -from django.conf import settings from celery import shared_task +from django.conf import settings +from django.db.transaction import atomic +from django.utils.translation import gettext_lazy as _ -from ops.celery.decorator import register_as_period_task -from orgs.utils import tmp_to_root_org +from common.const.crontab import CRONTAB_AT_AM_TEN from common.utils import get_logger from common.utils.timezone import local_now, dt_parser -from common.const.crontab import CRONTAB_AT_AM_TEN - +from ops.celery.decorator import register_as_period_task +from orgs.utils import tmp_to_root_org from perms.models import AssetPermission -from perms.utils import UserPermTreeExpireUtil from perms.notifications import ( PermedAssetsWillExpireUserMsg, AssetPermsWillExpireForOrgAdminMsg, ) -from django.utils.translation import gettext_lazy as _ +from perms.utils import UserPermTreeExpireUtil logger = get_logger(__file__) @@ -32,7 +32,8 @@ def check_asset_permission_expired(): """ 这里的任务要足够短,不要影响周期任务 """ perms = AssetPermission.objects.get_expired_permissions() perm_ids = list(perms.distinct().values_list('id', flat=True)) - logger.info(f'Checking expired permissions: {perm_ids}') + show_perm_ids = perm_ids[:5] + logger.info(f'Checking expired permissions: {show_perm_ids} ...') UserPermTreeExpireUtil().expire_perm_tree_for_perms(perm_ids) diff --git a/apps/terminal/utils/db_port_mapper.py b/apps/terminal/utils/db_port_mapper.py index f5405f97e..9d335859a 100644 --- a/apps/terminal/utils/db_port_mapper.py +++ b/apps/terminal/utils/db_port_mapper.py @@ -79,6 +79,7 @@ class DBPortManager(object): for port, db_id in mapper.items(): if db_id == str(db.id): return port + if raise_exception: error = _( 'No available port is matched. ' diff --git a/requirements/issues.txt b/requirements/issues.txt index 5db4004a7..768d95e1e 100644 --- a/requirements/issues.txt +++ b/requirements/issues.txt @@ -1,6 +1,6 @@ # Install cryptography error: build/temp.macosx-10.13-intel-2.7/_openssl.c:483:10: fatal error: 'openssl/opensslv.h' file not found -$ pip install cryptography --global-option=build_ext --global-option="-L/usr/local/opt/openssl/lib" --global-option="-I/usr/local/opt/openssl/include" +$ pip install cryptography --global-option=build_ext --global-option="-L/opt/homebrew/Cellar/openssl@3/3.1.1_1/lib" --global-option="-I/opt/homebrew/Cellar/openssl@3/3.1.1_1/include" # Pillow zlib failed @@ -9,3 +9,7 @@ Reinstall xcode reslove $ xcode-select --install + +# libxmlsec 报错 +wget 'https://raw.githubusercontent.com/Homebrew/homebrew-core/7f35e6ede954326a10949891af2dba47bbe1fc17/Formula/libxmlsec1.rb' +brew install ./libxmlsec1.rb From 8e86173cb8ff743c47890f2e50403c3c38e1660b Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 20 Jul 2023 15:26:00 +0800 Subject: [PATCH 163/167] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=E6=89=8B?= =?UTF-8?q?=E5=8A=A8=E8=BE=93=E5=85=A5=E7=9A=84=E5=90=8C=E5=90=8D=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/models/connection_token.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py index d6ba7e89f..ce5b4829f 100644 --- a/apps/authentication/models/connection_token.py +++ b/apps/authentication/models/connection_token.py @@ -225,7 +225,7 @@ class ConnectionToken(JMSOrgBaseModel): account.asset = self.asset account.org_id = self.asset.org_id - if self.account == AliasAccount.INPUT: + if self.account in [AliasAccount.INPUT, AliasAccount.USER]: account.username = self.input_username account.secret = self.input_secret else: From 4f5e36099193304aad2387ca5675a25d38578065 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 20 Jul 2023 15:44:52 +0800 Subject: [PATCH 164/167] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E5=88=9B=E5=BB=BA=20serializer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/serializers/dynamic.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/common/serializers/dynamic.py b/apps/common/serializers/dynamic.py index e3fab256a..a42529b5a 100644 --- a/apps/common/serializers/dynamic.py +++ b/apps/common/serializers/dynamic.py @@ -52,11 +52,14 @@ def create_serializer_class(serializer_name, fields_info): # 用户定义 default 和 required 可能会冲突, 所以要处理一下 default = data.get('default', None) - if default is not None: - data['required'] = False - else: + if default is None: data.pop('default', None) data['required'] = True + elif default == '': + data['required'] = False + data['allow_blank'] = True + else: + data['required'] = False data = set_default_by_type(field_type, data, field_info) data = set_default_if_need(data, i) field_name = data.pop('name') From cee87ae4d790deea21e45b15aab415a7203eabaf Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 20 Jul 2023 17:59:58 +0800 Subject: [PATCH 165/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20README,=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20GPT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 93d7efe0c..863e78f15 100644 --- a/README.md +++ b/README.md @@ -17,18 +17,16 @@ 9 年时间,倾情投入,用心做好一款开源堡垒机。

-| :warning: 注意 :warning: | -|:-------------------------------------------------------------------------------------------------------------------------:| -| 3.0 架构上和 2.0 变化较大,建议全新安装一套环境来体验。如需升级,请务必升级前进行备份,并[查阅文档](https://kb.fit2cloud.com/?p=06638d69-f109-4333-b5bf-65b17b297ed9) | +JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。 --------------------------- - -JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型的资产,包括: +JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型的资产,包括: - **SSH**: Linux / Unix / 网络设备 等; - **Windows**: Web 方式连接 / 原生 RDP 连接; -- **数据库**: MySQL / Oracle / SQLServer / PostgreSQL 等; -- **Kubernetes**: 支持连接到 K8s 集群中的 Pods; +- **数据库**: MySQL / MariaDB / PostgreSQL / Oracle / SQLServer / ClickHouse 等; +- **NoSQL**: Redis / MongoDB 等; +- **GPT**: ChatGPT 等; +- **云服务**: Kubernetes / VMware vSphere 等; - **Web 站点**: 各类系统的 Web 管理后台; - **应用**: 通过 Remote App 连接各类应用。 From 5f8d84df664b4dc576732888c337b14ace8ddfbc Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 20 Jul 2023 18:10:28 +0800 Subject: [PATCH 166/167] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E5=9B=BE?= =?UTF-8?q?=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 863e78f15..634a8e56a 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,8 @@ JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型 | [Luna](https://github.com/jumpserver/luna) | Luna release | JumpServer Web Terminal 项目 | | [KoKo](https://github.com/jumpserver/koko) | Koko release | JumpServer 字符协议 Connector 项目 | | [Lion](https://github.com/jumpserver/lion-release) | Lion release | JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/) | -| [Razor](https://github.com/jumpserver/razor) | 私有 | JumpServer RDP 代理 Connector 项目 | -| [Tinker](https://github.com/jumpserver/tinker) | 私有 | JumpServer 远程应用 Connector 项目 | +| [Razor](https://github.com/jumpserver/razor) | Chen | JumpServer RDP 代理 Connector 项目 | +| [Tinker](https://github.com/jumpserver/tinker) | Tinker | JumpServer 远程应用 Connector 项目 | | [Magnus](https://github.com/jumpserver/magnus-release) | Magnus release | JumpServer 数据库代理 Connector 项目 | | [Chen](https://github.com/jumpserver/chen-release) | Chen release | JumpServer Web DB 项目,替代原来的 OmniDB | | [Kael](https://github.com/jumpserver/kael) | Kael release | JumpServer 连接 GPT 资产的组件项目 | From 4c48204e16802e287473514399b06ec2129d5bac Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 20 Jul 2023 18:46:34 +0800 Subject: [PATCH 167/167] perf: translate (#11036) Co-authored-by: feng <1304903146@qq.com> --- apps/locale/ja/LC_MESSAGES/django.po | 122 +++++++++++++-------------- apps/locale/zh/LC_MESSAGES/django.po | 122 +++++++++++++-------------- 2 files changed, 122 insertions(+), 122 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 7187599e4..5797de8e5 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-19 16:59+0800\n" +"POT-Creation-Date: 2023-07-20 18:40+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -491,15 +491,15 @@ msgstr "アカウントの確認" #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:17 assets/models/label.py:18 #: assets/models/platform.py:15 assets/models/platform.py:88 -#: assets/serializers/asset/common.py:145 assets/serializers/platform.py:109 -#: assets/serializers/platform.py:209 +#: assets/serializers/asset/common.py:146 assets/serializers/platform.py:110 +#: assets/serializers/platform.py:223 #: authentication/serializers/connect_token_secret.py:110 ops/mixin.py:21 #: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57 #: ops/models/job.py:94 ops/models/playbook.py:23 ops/serializers/job.py:20 #: orgs/models.py:80 perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 #: terminal/models/applet/applet.py:32 terminal/models/component/endpoint.py:12 -#: terminal/models/component/endpoint.py:90 +#: terminal/models/component/endpoint.py:92 #: terminal/models/component/storage.py:26 terminal/models/component/task.py:15 #: terminal/models/component/terminal.py:84 users/forms/profile.py:33 #: users/models/group.py:13 users/models/user.py:753 @@ -516,7 +516,7 @@ msgstr "特権アカウント" #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:114 #: terminal/models/applet/applet.py:39 -#: terminal/models/component/endpoint.py:101 users/serializers/user.py:169 +#: terminal/models/component/endpoint.py:103 users/serializers/user.py:169 msgid "Is active" msgstr "アクティブです。" @@ -572,7 +572,7 @@ msgstr "アカウントの存在ポリシー" #: accounts/serializers/account/account.py:180 applications/models.py:11 #: assets/models/label.py:21 assets/models/platform.py:89 #: assets/serializers/asset/common.py:121 assets/serializers/cagegory.py:8 -#: assets/serializers/platform.py:127 assets/serializers/platform.py:210 +#: assets/serializers/platform.py:128 assets/serializers/platform.py:224 #: perms/serializers/user_permission.py:26 settings/models.py:35 #: tickets/models/ticket/apply_application.py:13 msgid "Category" @@ -583,8 +583,8 @@ msgstr "カテゴリ" #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:90 -#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:111 -#: assets/serializers/platform.py:126 audits/serializers.py:48 +#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:112 +#: assets/serializers/platform.py:127 audits/serializers.py:48 #: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:105 #: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:38 #: terminal/models/component/storage.py:57 @@ -696,7 +696,7 @@ msgid "Key password" msgstr "キーパスワード" #: accounts/serializers/account/base.py:80 -#: assets/serializers/asset/common.py:306 +#: assets/serializers/asset/common.py:309 msgid "Spec info" msgstr "特別情報" @@ -812,12 +812,12 @@ msgid "Warning" msgstr "警告" #: acls/models/base.py:37 assets/models/_user.py:51 -#: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:93 +#: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:95 msgid "Priority" msgstr "優先順位" #: acls/models/base.py:38 assets/models/_user.py:51 -#: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:94 +#: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:96 msgid "1-100, the lower the value will be match first" msgstr "1-100、低い値は最初に一致します" @@ -839,7 +839,7 @@ msgid "Users" msgstr "ユーザー" #: acls/models/base.py:98 assets/models/automations/base.py:17 -#: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:305 +#: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:308 #: rbac/tree.py:35 msgid "Accounts" msgstr "アカウント" @@ -1240,7 +1240,7 @@ msgstr "SSHパブリックキー" #: ops/models/playbook.py:26 rbac/models/role.py:37 settings/models.py:38 #: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:248 #: terminal/models/applet/host.py:139 terminal/models/component/endpoint.py:24 -#: terminal/models/component/endpoint.py:100 +#: terminal/models/component/endpoint.py:102 #: terminal/models/session/session.py:46 tickets/models/comment.py:32 #: tickets/models/ticket/general.py:297 users/models/user.py:792 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 @@ -1347,7 +1347,7 @@ msgstr "クラウド サービス" msgid "Port" msgstr "ポート" -#: assets/models/asset/common.py:150 assets/serializers/asset/common.py:146 +#: assets/models/asset/common.py:150 assets/serializers/asset/common.py:147 msgid "Address" msgstr "アドレス" @@ -1368,7 +1368,7 @@ msgstr "ドメイン" msgid "Labels" msgstr "ラベル" -#: assets/models/asset/common.py:158 assets/serializers/asset/common.py:307 +#: assets/models/asset/common.py:158 assets/serializers/asset/common.py:310 #: assets/serializers/asset/host.py:11 msgid "Gathered info" msgstr "資産ハードウェア情報の収集" @@ -1500,7 +1500,7 @@ msgid "Asset group" msgstr "資産グループ" #: assets/models/group.py:31 assets/models/platform.py:19 -#: assets/serializers/platform.py:112 +#: assets/serializers/platform.py:113 #: xpack/plugins/cloud/providers/nutanix.py:30 msgid "Default" msgstr "デフォルト" @@ -1523,7 +1523,7 @@ msgstr "値" #: assets/models/label.py:40 assets/serializers/asset/common.py:123 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 -#: assets/serializers/platform.py:110 +#: assets/serializers/platform.py:111 #: authentication/serializers/connect_token_secret.py:121 #: common/serializers/common.py:85 perms/serializers/user_permission.py:28 #: settings/serializers/sms.py:7 @@ -1656,23 +1656,23 @@ msgstr "メタ" msgid "Internal" msgstr "ビルトイン" -#: assets/models/platform.py:96 assets/serializers/platform.py:125 +#: assets/models/platform.py:96 assets/serializers/platform.py:126 msgid "Charset" msgstr "シャーセット" -#: assets/models/platform.py:98 assets/serializers/platform.py:153 +#: assets/models/platform.py:98 assets/serializers/platform.py:154 msgid "Domain enabled" msgstr "ドメインを有効にする" -#: assets/models/platform.py:100 assets/serializers/platform.py:152 +#: assets/models/platform.py:100 assets/serializers/platform.py:153 msgid "Su enabled" msgstr "アカウントの切り替えを有効にする" -#: assets/models/platform.py:101 assets/serializers/platform.py:131 +#: assets/models/platform.py:101 assets/serializers/platform.py:132 msgid "Su method" msgstr "アカウントの切り替え方法" -#: assets/models/platform.py:102 assets/serializers/platform.py:134 +#: assets/models/platform.py:102 assets/serializers/platform.py:135 msgid "Custom fields" msgstr "カスタムフィールド" @@ -1689,7 +1689,7 @@ msgstr "" "プラットフォームタイプがスキップされた資産に合致しない、資産内の一括更新プ" "ラットフォーム" -#: assets/serializers/asset/common.py:124 assets/serializers/platform.py:128 +#: assets/serializers/asset/common.py:124 assets/serializers/platform.py:129 #: authentication/serializers/connect_token_secret.py:29 #: authentication/serializers/connect_token_secret.py:72 #: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:99 @@ -1697,24 +1697,24 @@ msgid "Protocols" msgstr "プロトコル" #: assets/serializers/asset/common.py:126 -#: assets/serializers/asset/common.py:147 +#: assets/serializers/asset/common.py:148 msgid "Node path" msgstr "ノードパスです" -#: assets/serializers/asset/common.py:144 -#: assets/serializers/asset/common.py:308 +#: assets/serializers/asset/common.py:145 +#: assets/serializers/asset/common.py:311 msgid "Auto info" msgstr "自動情報" -#: assets/serializers/asset/common.py:227 +#: assets/serializers/asset/common.py:234 msgid "Platform not exist" msgstr "プラットフォームが存在しません" -#: assets/serializers/asset/common.py:263 +#: assets/serializers/asset/common.py:270 msgid "port out of range (0-65535)" msgstr "ポート番号が範囲外です (0-65535)" -#: assets/serializers/asset/common.py:270 +#: assets/serializers/asset/common.py:277 msgid "Protocol is required: {}" msgstr "プロトコルが必要です: {}" @@ -1833,7 +1833,7 @@ msgstr "アカウントの収集方法" msgid "Port from addr" msgstr "アドレスからのポート" -#: assets/serializers/platform.py:60 +#: assets/serializers/platform.py:61 msgid "" "This protocol is primary, and it must be set when adding assets. " "Additionally, there can only be one primary protocol." @@ -1841,11 +1841,11 @@ msgstr "" "このプロトコルはプライマリであり、資産を追加するときに設定する必要がありま" "す。また、プライマリプロトコルは1つしかありません" -#: assets/serializers/platform.py:65 +#: assets/serializers/platform.py:66 msgid "This protocol is required, and it must be set when adding assets." msgstr "このプロトコルは必須であり、資産を追加するときに設定する必要があります" -#: assets/serializers/platform.py:68 +#: assets/serializers/platform.py:69 msgid "" "This protocol is default, when adding assets, it will be displayed by " "default." @@ -1853,32 +1853,32 @@ msgstr "" "このプロトコルはデフォルトです。資産を追加するときに、デフォルトで表示されま" "す" -#: assets/serializers/platform.py:71 +#: assets/serializers/platform.py:72 msgid "This protocol is public, asset will show this protocol to user" msgstr "" "このプロトコルは公開されており、資産はこのプロトコルをユーザーに表示します" -#: assets/serializers/platform.py:113 +#: assets/serializers/platform.py:114 msgid "Help text" msgstr "ヘルプ" -#: assets/serializers/platform.py:114 +#: assets/serializers/platform.py:115 msgid "Choices" msgstr "せんたく" -#: assets/serializers/platform.py:129 +#: assets/serializers/platform.py:130 msgid "Automation" msgstr "オートメーション" -#: assets/serializers/platform.py:154 +#: assets/serializers/platform.py:155 msgid "Default Domain" msgstr "デフォルト ドメイン" -#: assets/serializers/platform.py:163 +#: assets/serializers/platform.py:176 msgid "type is required" msgstr "タイプ このフィールドは必須です." -#: assets/serializers/platform.py:186 +#: assets/serializers/platform.py:199 msgid "Protocols is required" msgstr "同意が必要です" @@ -2240,29 +2240,29 @@ msgstr "外部ストレージへのFTPファイルのアップロード" msgid "This action require verify your MFA" msgstr "この操作には、MFAを検証する必要があります" -#: authentication/api/connection_token.py:219 +#: authentication/api/connection_token.py:221 msgid "Reusable connection token is not allowed, global setting not enabled" msgstr "" "再使用可能な接続トークンの使用は許可されていません。グローバル設定は有効に" "なっていません" -#: authentication/api/connection_token.py:298 +#: authentication/api/connection_token.py:301 msgid "Anonymous account is not supported for this asset" msgstr "匿名アカウントはこのプロパティではサポートされていません" -#: authentication/api/connection_token.py:320 +#: authentication/api/connection_token.py:323 msgid "Account not found" msgstr "アカウントが見つかりません" -#: authentication/api/connection_token.py:323 +#: authentication/api/connection_token.py:326 msgid "Permission expired" msgstr "承認の有効期限が切れています" -#: authentication/api/connection_token.py:337 +#: authentication/api/connection_token.py:340 msgid "ACL action is reject: {}({})" msgstr "ACL アクションは拒否です: {}({})" -#: authentication/api/connection_token.py:341 +#: authentication/api/connection_token.py:344 msgid "ACL action is review" msgstr "ACL アクションはレビューです" @@ -2882,7 +2882,7 @@ msgstr "コードエラー" #: authentication/templates/authentication/_msg_reset_password_code.html:9 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:427 +#: jumpserver/conf.py:431 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -3294,7 +3294,7 @@ msgstr "組織 ID" msgid "The file content overflowed (The maximum length `{}` bytes)" msgstr "ファイルの内容がオーバーフローしました (最大長 '{}' バイト)" -#: common/drf/parsers/base.py:193 +#: common/drf/parsers/base.py:195 msgid "Parse file error: {}" msgstr "解析ファイルエラー: {}" @@ -3476,11 +3476,11 @@ msgstr "検索のエクスポート: %s" msgid "User %s view/export secret" msgstr "ユーザー %s がパスワードを閲覧/導き出しました" -#: jumpserver/conf.py:426 +#: jumpserver/conf.py:430 msgid "Create account successfully" msgstr "アカウントを正常に作成" -#: jumpserver/conf.py:428 +#: jumpserver/conf.py:432 msgid "Your account has been created successfully" msgstr "アカウントが正常に作成されました" @@ -3572,11 +3572,11 @@ msgstr "タスクは存在しません" msgid "Task {} args or kwargs error" msgstr "タスク実行パラメータエラー" -#: ops/api/playbook.py:38 +#: ops/api/playbook.py:37 msgid "Currently playbook is being used in a job" msgstr "現在プレイブックは1つのジョブで使用されています" -#: ops/api/playbook.py:92 +#: ops/api/playbook.py:91 msgid "Unsupported file content" msgstr "サポートされていないファイルの内容" @@ -4041,7 +4041,7 @@ msgstr "組織 {} の資産権限" msgid "Check asset permission expired" msgstr "アセット認証ルールの有効期限が切れていることを確認する" -#: perms/tasks.py:39 +#: perms/tasks.py:40 msgid "Send asset permission expired notification" msgstr "アセット許可の有効期限通知を送信する" @@ -5905,18 +5905,18 @@ msgid "Redis port" msgstr "Redis ポート" #: terminal/models/component/endpoint.py:29 -#: terminal/models/component/endpoint.py:98 terminal/serializers/endpoint.py:73 -#: terminal/serializers/storage.py:38 terminal/serializers/storage.py:50 -#: terminal/serializers/storage.py:80 terminal/serializers/storage.py:90 -#: terminal/serializers/storage.py:98 +#: terminal/models/component/endpoint.py:100 +#: terminal/serializers/endpoint.py:73 terminal/serializers/storage.py:38 +#: terminal/serializers/storage.py:50 terminal/serializers/storage.py:80 +#: terminal/serializers/storage.py:90 terminal/serializers/storage.py:98 msgid "Endpoint" msgstr "エンドポイント" -#: terminal/models/component/endpoint.py:91 +#: terminal/models/component/endpoint.py:93 msgid "IP group" msgstr "IP グループ" -#: terminal/models/component/endpoint.py:104 +#: terminal/models/component/endpoint.py:106 msgid "Endpoint rule" msgstr "エンドポイントルール" @@ -6388,7 +6388,7 @@ msgstr "チェックコマンドと録画ストレージの接続性" msgid "view" msgstr "表示" -#: terminal/utils/db_port_mapper.py:84 +#: terminal/utils/db_port_mapper.py:85 msgid "" "No available port is matched. The number of databases may have exceeded the " "number of ports open to the database agent service, Contact the " @@ -6398,7 +6398,7 @@ msgstr "" "サービスによって開かれたポートの数を超えた可能性があります。さらにポートを開" "くには、管理者に連絡してください。" -#: terminal/utils/db_port_mapper.py:112 +#: terminal/utils/db_port_mapper.py:113 msgid "" "No ports can be used, check and modify the limit on the number of ports that " "Magnus listens on in the configuration file." @@ -6406,7 +6406,7 @@ msgstr "" "使用できるポートがありません。設定ファイルで Magnus がリッスンするポート数の" "制限を確認して変更してください. " -#: terminal/utils/db_port_mapper.py:114 +#: terminal/utils/db_port_mapper.py:115 msgid "All available port count: {}, Already use port count: {}" msgstr "使用可能なすべてのポート数: {}、すでに使用しているポート数: {}" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index e69b0143d..8db571768 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-07-19 16:59+0800\n" +"POT-Creation-Date: 2023-07-20 18:40+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -490,15 +490,15 @@ msgstr "账号验证" #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:17 assets/models/label.py:18 #: assets/models/platform.py:15 assets/models/platform.py:88 -#: assets/serializers/asset/common.py:145 assets/serializers/platform.py:109 -#: assets/serializers/platform.py:209 +#: assets/serializers/asset/common.py:146 assets/serializers/platform.py:110 +#: assets/serializers/platform.py:223 #: authentication/serializers/connect_token_secret.py:110 ops/mixin.py:21 #: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57 #: ops/models/job.py:94 ops/models/playbook.py:23 ops/serializers/job.py:20 #: orgs/models.py:80 perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 #: terminal/models/applet/applet.py:32 terminal/models/component/endpoint.py:12 -#: terminal/models/component/endpoint.py:90 +#: terminal/models/component/endpoint.py:92 #: terminal/models/component/storage.py:26 terminal/models/component/task.py:15 #: terminal/models/component/terminal.py:84 users/forms/profile.py:33 #: users/models/group.py:13 users/models/user.py:753 @@ -515,7 +515,7 @@ msgstr "特权账号" #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:114 #: terminal/models/applet/applet.py:39 -#: terminal/models/component/endpoint.py:101 users/serializers/user.py:169 +#: terminal/models/component/endpoint.py:103 users/serializers/user.py:169 msgid "Is active" msgstr "激活" @@ -568,7 +568,7 @@ msgstr "账号存在策略" #: accounts/serializers/account/account.py:180 applications/models.py:11 #: assets/models/label.py:21 assets/models/platform.py:89 #: assets/serializers/asset/common.py:121 assets/serializers/cagegory.py:8 -#: assets/serializers/platform.py:127 assets/serializers/platform.py:210 +#: assets/serializers/platform.py:128 assets/serializers/platform.py:224 #: perms/serializers/user_permission.py:26 settings/models.py:35 #: tickets/models/ticket/apply_application.py:13 msgid "Category" @@ -579,8 +579,8 @@ msgstr "类别" #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:90 -#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:111 -#: assets/serializers/platform.py:126 audits/serializers.py:48 +#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:112 +#: assets/serializers/platform.py:127 audits/serializers.py:48 #: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:105 #: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:38 #: terminal/models/component/storage.py:57 @@ -692,7 +692,7 @@ msgid "Key password" msgstr "密钥密码" #: accounts/serializers/account/base.py:80 -#: assets/serializers/asset/common.py:306 +#: assets/serializers/asset/common.py:309 msgid "Spec info" msgstr "特殊信息" @@ -808,12 +808,12 @@ msgid "Warning" msgstr "告警" #: acls/models/base.py:37 assets/models/_user.py:51 -#: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:93 +#: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:95 msgid "Priority" msgstr "优先级" #: acls/models/base.py:38 assets/models/_user.py:51 -#: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:94 +#: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:96 msgid "1-100, the lower the value will be match first" msgstr "优先级可选范围为 1-100 (数值越小越优先)" @@ -835,7 +835,7 @@ msgid "Users" msgstr "用户管理" #: acls/models/base.py:98 assets/models/automations/base.py:17 -#: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:305 +#: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:308 #: rbac/tree.py:35 msgid "Accounts" msgstr "账号管理" @@ -1233,7 +1233,7 @@ msgstr "SSH公钥" #: ops/models/playbook.py:26 rbac/models/role.py:37 settings/models.py:38 #: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:248 #: terminal/models/applet/host.py:139 terminal/models/component/endpoint.py:24 -#: terminal/models/component/endpoint.py:100 +#: terminal/models/component/endpoint.py:102 #: terminal/models/session/session.py:46 tickets/models/comment.py:32 #: tickets/models/ticket/general.py:297 users/models/user.py:792 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 @@ -1340,7 +1340,7 @@ msgstr "云服务" msgid "Port" msgstr "端口" -#: assets/models/asset/common.py:150 assets/serializers/asset/common.py:146 +#: assets/models/asset/common.py:150 assets/serializers/asset/common.py:147 msgid "Address" msgstr "地址" @@ -1361,7 +1361,7 @@ msgstr "网域" msgid "Labels" msgstr "标签管理" -#: assets/models/asset/common.py:158 assets/serializers/asset/common.py:307 +#: assets/models/asset/common.py:158 assets/serializers/asset/common.py:310 #: assets/serializers/asset/host.py:11 msgid "Gathered info" msgstr "收集资产硬件信息" @@ -1493,7 +1493,7 @@ msgid "Asset group" msgstr "资产组" #: assets/models/group.py:31 assets/models/platform.py:19 -#: assets/serializers/platform.py:112 +#: assets/serializers/platform.py:113 #: xpack/plugins/cloud/providers/nutanix.py:30 msgid "Default" msgstr "默认" @@ -1516,7 +1516,7 @@ msgstr "值" #: assets/models/label.py:40 assets/serializers/asset/common.py:123 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 -#: assets/serializers/platform.py:110 +#: assets/serializers/platform.py:111 #: authentication/serializers/connect_token_secret.py:121 #: common/serializers/common.py:85 perms/serializers/user_permission.py:28 #: settings/serializers/sms.py:7 @@ -1649,23 +1649,23 @@ msgstr "元数据" msgid "Internal" msgstr "内置" -#: assets/models/platform.py:96 assets/serializers/platform.py:125 +#: assets/models/platform.py:96 assets/serializers/platform.py:126 msgid "Charset" msgstr "编码" -#: assets/models/platform.py:98 assets/serializers/platform.py:153 +#: assets/models/platform.py:98 assets/serializers/platform.py:154 msgid "Domain enabled" msgstr "启用网域" -#: assets/models/platform.py:100 assets/serializers/platform.py:152 +#: assets/models/platform.py:100 assets/serializers/platform.py:153 msgid "Su enabled" msgstr "启用账号切换" -#: assets/models/platform.py:101 assets/serializers/platform.py:131 +#: assets/models/platform.py:101 assets/serializers/platform.py:132 msgid "Su method" msgstr "账号切换方式" -#: assets/models/platform.py:102 assets/serializers/platform.py:134 +#: assets/models/platform.py:102 assets/serializers/platform.py:135 msgid "Custom fields" msgstr "自定义属性" @@ -1680,7 +1680,7 @@ msgid "" "type" msgstr "资产中批量更新平台,不符合平台类型跳过的资产" -#: assets/serializers/asset/common.py:124 assets/serializers/platform.py:128 +#: assets/serializers/asset/common.py:124 assets/serializers/platform.py:129 #: authentication/serializers/connect_token_secret.py:29 #: authentication/serializers/connect_token_secret.py:72 #: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:99 @@ -1688,24 +1688,24 @@ msgid "Protocols" msgstr "协议组" #: assets/serializers/asset/common.py:126 -#: assets/serializers/asset/common.py:147 +#: assets/serializers/asset/common.py:148 msgid "Node path" msgstr "节点路径" -#: assets/serializers/asset/common.py:144 -#: assets/serializers/asset/common.py:308 +#: assets/serializers/asset/common.py:145 +#: assets/serializers/asset/common.py:311 msgid "Auto info" msgstr "自动化信息" -#: assets/serializers/asset/common.py:227 +#: assets/serializers/asset/common.py:234 msgid "Platform not exist" msgstr "平台不存在" -#: assets/serializers/asset/common.py:263 +#: assets/serializers/asset/common.py:270 msgid "port out of range (0-65535)" msgstr "端口超出范围 (0-65535)" -#: assets/serializers/asset/common.py:270 +#: assets/serializers/asset/common.py:277 msgid "Protocol is required: {}" msgstr "协议是必填的: {}" @@ -1824,47 +1824,47 @@ msgstr "收集账号方式" msgid "Port from addr" msgstr "端口来自地址" -#: assets/serializers/platform.py:60 +#: assets/serializers/platform.py:61 msgid "" "This protocol is primary, and it must be set when adding assets. " "Additionally, there can only be one primary protocol." msgstr "该协议是主要的,添加资产时必须设置。并且只能有一个主要协议" -#: assets/serializers/platform.py:65 +#: assets/serializers/platform.py:66 msgid "This protocol is required, and it must be set when adding assets." msgstr "该协议是必填的,添加资产时必须设置" -#: assets/serializers/platform.py:68 +#: assets/serializers/platform.py:69 msgid "" "This protocol is default, when adding assets, it will be displayed by " "default." msgstr "该协议是默认的,添加资产时,将默认显示" -#: assets/serializers/platform.py:71 +#: assets/serializers/platform.py:72 msgid "This protocol is public, asset will show this protocol to user" msgstr "该协议是公开的,资产将向用户显示该协议并可以连接使用" -#: assets/serializers/platform.py:113 +#: assets/serializers/platform.py:114 msgid "Help text" msgstr "帮助" -#: assets/serializers/platform.py:114 +#: assets/serializers/platform.py:115 msgid "Choices" msgstr "选择" -#: assets/serializers/platform.py:129 +#: assets/serializers/platform.py:130 msgid "Automation" msgstr "自动化" -#: assets/serializers/platform.py:154 +#: assets/serializers/platform.py:155 msgid "Default Domain" msgstr "默认网域" -#: assets/serializers/platform.py:163 +#: assets/serializers/platform.py:176 msgid "type is required" msgstr "类型 该字段是必填项。" -#: assets/serializers/platform.py:186 +#: assets/serializers/platform.py:199 msgid "Protocols is required" msgstr "协议是必填的" @@ -2224,27 +2224,27 @@ msgstr "上传 FTP 文件到外部存储" msgid "This action require verify your MFA" msgstr "该操作需要验证您的 MFA, 请先开启并配置" -#: authentication/api/connection_token.py:219 +#: authentication/api/connection_token.py:221 msgid "Reusable connection token is not allowed, global setting not enabled" msgstr "不允许使用可重复使用的连接令牌,未启用全局设置" -#: authentication/api/connection_token.py:298 +#: authentication/api/connection_token.py:301 msgid "Anonymous account is not supported for this asset" msgstr "匿名账号不支持当前资产" -#: authentication/api/connection_token.py:320 +#: authentication/api/connection_token.py:323 msgid "Account not found" msgstr "账号未找到" -#: authentication/api/connection_token.py:323 +#: authentication/api/connection_token.py:326 msgid "Permission expired" msgstr "授权已过期" -#: authentication/api/connection_token.py:337 +#: authentication/api/connection_token.py:340 msgid "ACL action is reject: {}({})" msgstr "ACL 动作是拒绝: {}({})" -#: authentication/api/connection_token.py:341 +#: authentication/api/connection_token.py:344 msgid "ACL action is review" msgstr "ACL 动作是复核" @@ -2850,7 +2850,7 @@ msgstr "代码错误" #: authentication/templates/authentication/_msg_reset_password_code.html:9 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:427 +#: jumpserver/conf.py:431 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -3254,7 +3254,7 @@ msgstr "组织 ID" msgid "The file content overflowed (The maximum length `{}` bytes)" msgstr "文件内容太大 (最大长度 `{}` 字节)" -#: common/drf/parsers/base.py:193 +#: common/drf/parsers/base.py:195 msgid "Parse file error: {}" msgstr "解析文件错误: {}" @@ -3434,11 +3434,11 @@ msgstr "导出搜素: %s" msgid "User %s view/export secret" msgstr "用户 %s 查看/导出 了密码" -#: jumpserver/conf.py:426 +#: jumpserver/conf.py:430 msgid "Create account successfully" msgstr "创建账号成功" -#: jumpserver/conf.py:428 +#: jumpserver/conf.py:432 msgid "Your account has been created successfully" msgstr "你的账号已创建成功" @@ -3525,11 +3525,11 @@ msgstr "任务 {} 不存在" msgid "Task {} args or kwargs error" msgstr "任务 {} 执行参数错误" -#: ops/api/playbook.py:38 +#: ops/api/playbook.py:37 msgid "Currently playbook is being used in a job" msgstr "当前 playbook 正在作业中使用" -#: ops/api/playbook.py:92 +#: ops/api/playbook.py:91 msgid "Unsupported file content" msgstr "不支持的文件内容" @@ -3993,7 +3993,7 @@ msgstr "组织 ({}) 的资产授权" msgid "Check asset permission expired" msgstr "校验资产授权规则已过期" -#: perms/tasks.py:39 +#: perms/tasks.py:40 msgid "Send asset permission expired notification" msgstr "发送资产权限过期通知" @@ -5818,18 +5818,18 @@ msgid "Redis port" msgstr "Redis 端口" #: terminal/models/component/endpoint.py:29 -#: terminal/models/component/endpoint.py:98 terminal/serializers/endpoint.py:73 -#: terminal/serializers/storage.py:38 terminal/serializers/storage.py:50 -#: terminal/serializers/storage.py:80 terminal/serializers/storage.py:90 -#: terminal/serializers/storage.py:98 +#: terminal/models/component/endpoint.py:100 +#: terminal/serializers/endpoint.py:73 terminal/serializers/storage.py:38 +#: terminal/serializers/storage.py:50 terminal/serializers/storage.py:80 +#: terminal/serializers/storage.py:90 terminal/serializers/storage.py:98 msgid "Endpoint" msgstr "端点" -#: terminal/models/component/endpoint.py:91 +#: terminal/models/component/endpoint.py:93 msgid "IP group" msgstr "IP 组" -#: terminal/models/component/endpoint.py:104 +#: terminal/models/component/endpoint.py:106 msgid "Endpoint rule" msgstr "端点规则" @@ -6296,7 +6296,7 @@ msgstr "检查命令及录像存储可连接性 " msgid "view" msgstr "查看" -#: terminal/utils/db_port_mapper.py:84 +#: terminal/utils/db_port_mapper.py:85 msgid "" "No available port is matched. The number of databases may have exceeded the " "number of ports open to the database agent service, Contact the " @@ -6305,13 +6305,13 @@ msgstr "" "未匹配到可用端口,数据库的数量可能已经超过数据库代理服务开放的端口数量,请联" "系管理员开放更多端口。" -#: terminal/utils/db_port_mapper.py:112 +#: terminal/utils/db_port_mapper.py:113 msgid "" "No ports can be used, check and modify the limit on the number of ports that " "Magnus listens on in the configuration file." msgstr "没有端口可以使用,检查并修改配置文件中 Magnus 监听的端口数量限制。" -#: terminal/utils/db_port_mapper.py:114 +#: terminal/utils/db_port_mapper.py:115 msgid "All available port count: {}, Already use port count: {}" msgstr "所有可用端口数量:{},已使用端口数量:{}"