diff --git a/.dockerignore b/.dockerignore
index 0ddcc29ae..9537605a4 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -8,3 +8,4 @@ celerybeat.pid
.vagrant/
apps/xpack/.git
.history/
+.idea
\ No newline at end of file
diff --git a/.github/workflows/build-base-image.yml b/.github/workflows/build-base-image.yml
new file mode 100644
index 000000000..1ad366a98
--- /dev/null
+++ b/.github/workflows/build-base-image.yml
@@ -0,0 +1,60 @@
+name: Build and Push Base Image
+
+on:
+ push:
+ branches:
+ - 'pr*'
+ paths:
+ - 'poetry.lock'
+ - 'pyproject.toml'
+ - 'Dockerfile-base'
+
+jobs:
+ build-and-push:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Login to DockerHub
+ uses: docker/login-action@v2
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+ - name: Extract date
+ id: vars
+ run: echo "IMAGE_TAG=$(date +'%Y%m%d_%H%M%S')" >> $GITHUB_ENV
+
+ - name: Extract repository name
+ id: repo
+ run: echo "REPO=$(basename ${{ github.repository }})" >> $GITHUB_ENV
+
+ - name: Build and push multi-arch image
+ uses: docker/build-push-action@v6
+ with:
+ platforms: linux/amd64,linux/arm64
+ push: true
+ file: Dockerfile-base
+ tags: jumpserver/core-base:${{ env.IMAGE_TAG }}
+
+ - name: Update Dockerfile
+ run: |
+ sed -i 's|-base:.* AS stage-build|-base:${{ env.IMAGE_TAG }} AS stage-build|' Dockerfile
+
+ - name: Commit changes
+ run: |
+ git config --global user.name 'github-actions[bot]'
+ git config --global user.email 'github-actions[bot]@users.noreply.github.com'
+ git add Dockerfile
+ git commit -m "perf: Update Dockerfile with new base image tag"
+ git push
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/jms-build-test.yml b/.github/workflows/jms-build-test.yml.disabled
similarity index 100%
rename from .github/workflows/jms-build-test.yml
rename to .github/workflows/jms-build-test.yml.disabled
diff --git a/.isort.cfg b/.isort.cfg
index e59d309dc..bdefbe705 100644
--- a/.isort.cfg
+++ b/.isort.cfg
@@ -1,3 +1,4 @@
[settings]
line_length=120
known_first_party=common,users,assets,perms,authentication,jumpserver,notification,ops,orgs,rbac,settings,terminal,tickets
+
diff --git a/Dockerfile b/Dockerfile
index 3bedb6867..e487f250e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,101 +1,25 @@
-FROM debian:bullseye-slim as stage-1
-ARG TARGETARCH
-
-ARG DEPENDENCIES=" \
- ca-certificates \
- wget"
-
-ARG APT_MIRROR=http://mirrors.ustc.edu.cn
-RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \
- --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \
- set -ex \
- && rm -f /etc/apt/apt.conf.d/docker-clean \
- && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache \
- && sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
- && apt-get update \
- && apt-get -y install --no-install-recommends ${DEPENDENCIES} \
- && echo "no" | dpkg-reconfigure dash
-
-WORKDIR /opt
-
-ARG CHECK_VERSION=v1.0.2
-RUN set -ex \
- && wget https://github.com/jumpserver-dev/healthcheck/releases/download/${CHECK_VERSION}/check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz \
- && tar -xf check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz \
- && mv check /usr/local/bin/ \
- && chown root:root /usr/local/bin/check \
- && chmod 755 /usr/local/bin/check \
- && rm -f check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz
-
-ARG RECEPTOR_VERSION=v1.4.5
-RUN set -ex \
- && wget -O /opt/receptor.tar.gz https://github.com/ansible/receptor/releases/download/${RECEPTOR_VERSION}/receptor_${RECEPTOR_VERSION/v/}_linux_${TARGETARCH}.tar.gz \
- && tar -xf /opt/receptor.tar.gz -C /usr/local/bin/ \
- && chown root:root /usr/local/bin/receptor \
- && chmod 755 /usr/local/bin/receptor \
- && rm -f /opt/receptor.tar.gz
+FROM jumpserver/core-base:20240808_054051 AS stage-build
ARG VERSION
WORKDIR /opt/jumpserver
+
ADD . .
+
RUN echo > /opt/jumpserver/config.yml \
&& \
if [ -n "${VERSION}" ]; then \
sed -i "s@VERSION = .*@VERSION = '${VERSION}'@g" apps/jumpserver/const.py; \
fi
-FROM python:3.11-slim-bullseye as stage-2
-ARG TARGETARCH
-
-ARG BUILD_DEPENDENCIES=" \
- g++ \
- make \
- pkg-config"
-
-ARG DEPENDENCIES=" \
- default-libmysqlclient-dev \
- freetds-dev \
- gettext \
- libkrb5-dev \
- libldap2-dev \
- libsasl2-dev"
-
-ARG APT_MIRROR=http://mirrors.ustc.edu.cn
-RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \
- --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \
- set -ex \
- && rm -f /etc/apt/apt.conf.d/docker-clean \
- && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache \
- && sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
- && apt-get update \
- && apt-get -y install --no-install-recommends ${BUILD_DEPENDENCIES} \
- && apt-get -y install --no-install-recommends ${DEPENDENCIES} \
- && echo "no" | dpkg-reconfigure dash
-
-WORKDIR /opt/jumpserver
-
-ARG PIP_MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple
-RUN --mount=type=cache,target=/root/.cache,sharing=locked,id=core \
- --mount=type=bind,source=poetry.lock,target=poetry.lock \
- --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
- set -ex \
- && python3 -m venv /opt/py3 \
- && pip install poetry -i ${PIP_MIRROR} \
- && poetry config virtualenvs.create false \
- && . /opt/py3/bin/activate \
- && poetry install --only main
-
-COPY --from=stage-1 /opt/jumpserver /opt/jumpserver
-
RUN set -ex \
&& export SECRET_KEY=$(head -c100 < /dev/urandom | base64 | tr -dc A-Za-z0-9 | head -c 48) \
&& . /opt/py3/bin/activate \
&& cd apps \
&& python manage.py compilemessages
+
FROM python:3.11-slim-bullseye
-ARG TARGETARCH
ENV LANG=en_US.UTF-8 \
PATH=/opt/py3/bin:$PATH
@@ -110,32 +34,27 @@ ARG TOOLS=" \
sshpass \
bubblewrap"
-ARG APT_MIRROR=http://mirrors.ustc.edu.cn
-RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \
- --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \
- set -ex \
+ARG APT_MIRROR=http://deb.debian.org
+RUN set -ex \
&& rm -f /etc/apt/apt.conf.d/docker-clean \
- && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache \
&& sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
- && apt-get update \
+ && apt-get update > /dev/null \
&& apt-get -y install --no-install-recommends ${DEPENDENCIES} \
&& apt-get -y install --no-install-recommends ${TOOLS} \
+ && apt-get clean \
&& 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 "no" | dpkg-reconfigure dash \
&& sed -i "s@# export @export @g" ~/.bashrc \
&& sed -i "s@# alias @alias @g" ~/.bashrc
-COPY --from=stage-2 /opt /opt
-COPY --from=stage-1 /usr/local/bin /usr/local/bin
-COPY --from=stage-1 /opt/jumpserver/apps/libs/ansible/ansible.cfg /etc/ansible/
+COPY --from=stage-build /opt /opt
+COPY --from=stage-build /usr/local/bin /usr/local/bin
+COPY --from=stage-build /opt/jumpserver/apps/libs/ansible/ansible.cfg /etc/ansible/
WORKDIR /opt/jumpserver
-ARG VERSION
-ENV VERSION=$VERSION
-
VOLUME /opt/jumpserver/data
ENTRYPOINT ["./entrypoint.sh"]
diff --git a/Dockerfile-base b/Dockerfile-base
new file mode 100644
index 000000000..067cad40e
--- /dev/null
+++ b/Dockerfile-base
@@ -0,0 +1,54 @@
+FROM python:3.11-slim-bullseye
+ARG TARGETARCH
+
+# Install APT dependencies
+ARG DEPENDENCIES=" \
+ ca-certificates \
+ wget \
+ g++ \
+ make \
+ pkg-config \
+ default-libmysqlclient-dev \
+ freetds-dev \
+ gettext \
+ libkrb5-dev \
+ libldap2-dev \
+ libsasl2-dev"
+
+
+ARG APT_MIRROR=http://deb.debian.org
+RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \
+ --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \
+ set -ex \
+ && rm -f /etc/apt/apt.conf.d/docker-clean \
+ && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache \
+ && sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
+ && apt-get update > /dev/null \
+ && apt-get -y install --no-install-recommends ${DEPENDENCIES} \
+ && echo "no" | dpkg-reconfigure dash
+
+
+# Install bin tools
+ARG CHECK_VERSION=v1.0.3
+RUN set -ex \
+ && wget https://github.com/jumpserver-dev/healthcheck/releases/download/${CHECK_VERSION}/check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz \
+ && tar -xf check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz \
+ && mv check /usr/local/bin/ \
+ && chown root:root /usr/local/bin/check \
+ && chmod 755 /usr/local/bin/check \
+ && rm -f check-${CHECK_VERSION}-linux-${TARGETARCH}.tar.gz
+
+
+# Install Python dependencies
+WORKDIR /opt/jumpserver
+
+ARG PIP_MIRROR=https://pypi.org/simple
+RUN --mount=type=cache,target=/root/.cache,sharing=locked,id=core \
+ --mount=type=bind,source=poetry.lock,target=poetry.lock \
+ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
+ set -ex \
+ && python3 -m venv /opt/py3 \
+ && pip install poetry -i ${PIP_MIRROR} \
+ && poetry config virtualenvs.create false \
+ && . /opt/py3/bin/activate \
+ && poetry install --only main
diff --git a/Dockerfile-ee b/Dockerfile-ee
index ff29dd4d2..4a2d1ae0a 100644
--- a/Dockerfile-ee
+++ b/Dockerfile-ee
@@ -1,38 +1,12 @@
-ARG VERSION
+ARG VERSION=dev
-FROM registry.fit2cloud.com/jumpserver/xpack:${VERSION} as build-xpack
-FROM python:3.11-slim-bullseye as build-core
-ARG BUILD_DEPENDENCIES=" \
- g++"
+FROM registry.fit2cloud.com/jumpserver/xpack:${VERSION} AS build-xpack
+FROM jumpserver/core:${VERSION}-ce
-ARG APT_MIRROR=http://mirrors.ustc.edu.cn
-RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \
- --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \
- set -ex \
- && rm -f /etc/apt/apt.conf.d/docker-clean \
- && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' >/etc/apt/apt.conf.d/keep-cache \
- && sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
- && apt-get update \
- && apt-get -y install --no-install-recommends ${BUILD_DEPENDENCIES} \
- && echo "no" | dpkg-reconfigure dash
-
-WORKDIR /opt/jumpserver
-
-ARG PIP_MIRROR=https://pypi.tuna.tsinghua.edu.cn/simple
-RUN --mount=type=cache,target=/root/.cache,sharing=locked,id=core \
- --mount=type=bind,source=poetry.lock,target=/opt/jumpserver/poetry.lock \
- --mount=type=bind,source=pyproject.toml,target=/opt/jumpserver/pyproject.toml \
- set -ex \
- && python3 -m venv /opt/py3 \
- && pip install poetry -i ${PIP_MIRROR} \
- && poetry config virtualenvs.create false \
- && . /opt/py3/bin/activate \
- && poetry install --only xpack
-
-FROM registry.fit2cloud.com/jumpserver/core:${VERSION}-ce
-ARG TARGETARCH
+COPY --from=build-xpack /opt/xpack /opt/jumpserver/apps/xpack
ARG TOOLS=" \
+ g++ \
curl \
iputils-ping \
netcat-openbsd \
@@ -41,12 +15,21 @@ ARG TOOLS=" \
vim \
wget"
-ARG APT_MIRROR=http://mirrors.ustc.edu.cn
-RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=core \
- --mount=type=cache,target=/var/lib/apt,sharing=locked,id=core \
- set -ex \
+ARG APT_MIRROR=http://deb.debian.org
+RUN set -ex \
+ && rm -f /etc/apt/apt.conf.d/docker-clean \
+ && echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache \
+ && sed -i "s@http://.*.debian.org@${APT_MIRROR}@g" /etc/apt/sources.list \
&& apt-get update \
- && apt-get -y install --no-install-recommends ${TOOLS}
+ && apt-get -y install --no-install-recommends ${TOOLS} \
+ && echo "no" | dpkg-reconfigure dash
+
+WORKDIR /opt/jumpserver
+
+ARG PIP_MIRROR=https://pypi.org/simple
+COPY poetry.lock pyproject.toml ./
+RUN set -ex \
+ && . /opt/py3/bin/activate \
+ && pip install poetry -i ${PIP_MIRROR} \
+ && poetry install --only xpack
-COPY --from=build-core /opt/py3 /opt/py3
-COPY --from=build-xpack /opt/xpack /opt/jumpserver/apps/xpack
\ No newline at end of file
diff --git a/README.md b/README.md
index 192958a4c..9c10316ed 100644
--- a/README.md
+++ b/README.md
@@ -10,15 +10,27 @@
[![][github-release-shield]][github-release-link]
[![][github-stars-shield]][github-stars-link]
-**English** · [简体中文](./README.zh-CN.md) · [Documents][docs-link] · [Report Bug][github-issues-link] · [Request Feature][github-issues-link]
+**English** · [简体中文](./README.zh-CN.md)
## What is JumpServer?
-JumpServer is an open-source Privileged Access Management (PAM) tool that provides DevOps and IT teams with on-demand and secure access to SSH, RDP, Kubernetes, Database and Remote App endpoints through a web browser.
+JumpServer is an open-source Privileged Access Management (PAM) tool that provides DevOps and IT teams with on-demand and secure access to SSH, RDP, Kubernetes, Database and RemoteApp endpoints through a web browser.
-![JumpServer Overview](https://github.com/jumpserver/jumpserver/assets/41712985/eb9e6f39-3911-4d4a-bca9-aa50cc3b761d)
+![JumpServer Overview](https://github.com/jumpserver/jumpserver/assets/32935519/35a371cb-8590-40ed-88ec-f351f8cf9045)
+
+## Quickstart
+
+Prepare a clean Linux Server ( 64 bit, >= 4c8g )
+
+```sh
+curl -sSL https://github.com/jumpserver/jumpserver/releases/latest/download/quick_start.sh | bash
+```
+
+Access JumpServer in your browser at `http://your-jumpserver-ip/`
+- Username: `admin`
+- Password: `ChangeMe`
## Screenshots
@@ -43,15 +55,6 @@ JumpServer is an open-source Privileged Access Management (PAM) tool that provid
-## Quick Start
-Prepare a clean Linux Server ( 64bit, >= 4c8g )
-
-```
-curl -sSL https://github.com/jumpserver/jumpserver/releases/latest/download/quick_start.sh | bash
-```
-
-Access JumpServer in your browser at `http://your-ip/`, `admin`/`admin`
-
## Components
JumpServer consists of multiple key components, which collectively form the functional framework of JumpServer, providing users with comprehensive capabilities for operations management and security control.
@@ -63,12 +66,10 @@ JumpServer consists of multiple key components, which collectively form the func
| [KoKo](https://github.com/jumpserver/koko) | | JumpServer Character Protocol Connector |
| [Lion](https://github.com/jumpserver/lion) | | JumpServer Graphical Protocol Connector |
| [Chen](https://github.com/jumpserver/chen) | | JumpServer Web DB |
-| [Razor](https://github.com/jumpserver/razor) | | JumpServer RDP Proxy Connector |
-| [Tinker](https://github.com/jumpserver/tinker) | | JumpServer Remote Application Connector (Windows) |
-| [Panda](https://github.com/jumpserver/Panda) | | JumpServer Remote Application Connector (Linux) |
-| [Magnus](https://github.com/jumpserver/magnus) | | JumpServer Database Proxy Connector |
-
-
+| [Razor](https://github.com/jumpserver/razor) | | JumpServer EE RDP Proxy Connector |
+| [Tinker](https://github.com/jumpserver/tinker) | | JumpServer EE Remote Application Connector (Windows) |
+| [Panda](https://github.com/jumpserver/Panda) | | JumpServer EE Remote Application Connector (Linux) |
+| [Magnus](https://github.com/jumpserver/magnus) | | JumpServer EE Database Proxy Connector |
## Contributing
@@ -91,8 +92,8 @@ https://www.gnu.org/licenses/gpl-3.0.html
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an " AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-[docs-link]: https://en-docs.jumpserver.org/
-[discord-link]: https://discord.com/invite/jcM5tKWJ
+[docs-link]: https://jumpserver.com/docs
+[discord-link]: https://discord.com/invite/W6vYXmAQG2
[contributing-link]: https://github.com/jumpserver/jumpserver/blob/dev/CONTRIBUTING.md
diff --git a/README.zh-CN.md b/README.zh-CN.md
index d9e8ff444..e76610a3e 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -12,13 +12,13 @@
- 9 年时间,倾情投入,用心做好一款开源堡垒机。
+ 10 年时间,倾情投入,用心做好一款开源堡垒机。
------------------------------
-JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。
+## JumpServer 是什么?
-JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型的资产,包括:
+JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型的资产,包括:
- **SSH**: Linux / Unix / 网络设备 等;
- **Windows**: Web 方式连接 / 原生 RDP 连接;
@@ -38,6 +38,13 @@ JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型
- **多租户**: 一套系统,多个子公司或部门同时使用;
- **云端存储**: 审计录像云端存储,永不丢失;
+## 快速开始
+
+- [快速入门](https://docs.jumpserver.org/zh/v3/quick_start/)
+- [产品文档](https://docs.jumpserver.org)
+- [在线学习](https://edu.fit2cloud.com/page/2635362)
+- [知识库](https://kb.fit2cloud.com/categories/jumpserver)
+
## UI 展示
![UI展示](https://docs.jumpserver.org/zh/v3/img/dashboard.png)
@@ -52,13 +59,6 @@ JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型
| 请勿修改体验环境用户的密码! |
| 请勿在环境中添加业务生产环境地址、用户名密码等敏感信息! |
-## 快速开始
-
-- [快速入门](https://docs.jumpserver.org/zh/v3/quick_start/)
-- [产品文档](https://docs.jumpserver.org)
-- [在线学习](https://edu.fit2cloud.com/page/2635362)
-- [知识库](https://kb.fit2cloud.com/categories/jumpserver)
-
## 案例研究
- [腾讯音乐娱乐集团:基于JumpServer的安全运维审计解决方案](https://blog.fit2cloud.com/?p=a04cdf0d-6704-4d18-9b40-9180baecd0e2)
@@ -81,28 +81,24 @@ JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型
您也可以到我们的 [社区论坛](https://bbs.fit2cloud.com/c/js/5) 当中进行交流沟通。
-### 参与贡献
+## 参与贡献
欢迎提交 PR 参与贡献。 参考 [CONTRIBUTING.md](https://github.com/jumpserver/jumpserver/blob/dev/CONTRIBUTING.md)
## 组件项目
-| 项目 | 状态 | 描述 |
-|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|
-| [Lina](https://github.com/jumpserver/lina) | | JumpServer Web UI 项目 |
-| [Luna](https://github.com/jumpserver/luna) | | JumpServer Web Terminal 项目 |
-| [KoKo](https://github.com/jumpserver/koko) | | JumpServer 字符协议 Connector 项目 |
-| [Lion](https://github.com/jumpserver/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 项目 (Windows) |
-| [Panda](https://github.com/jumpserver/Panda) | | JumpServer 远程应用 Connector 项目 (Linux) |
-| [Magnus](https://github.com/jumpserver/magnus-release) | | JumpServer 数据库代理 Connector 项目 |
-| [Chen](https://github.com/jumpserver/chen-release) | | JumpServer Web DB 项目,替代原来的 OmniDB |
-| [Kael](https://github.com/jumpserver/kael) | | JumpServer 连接 GPT 资产的组件项目 |
-| [Wisp](https://github.com/jumpserver/wisp) | | JumpServer 各系统终端组件和 Core API 通信的组件项目 |
-| [Clients](https://github.com/jumpserver/clients) | | JumpServer 客户端 项目 |
-| [Installer](https://github.com/jumpserver/installer) | | JumpServer 安装包 项目 |
+| Project | Status | Description |
+|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
+| [Lina](https://github.com/jumpserver/lina) | | JumpServer Web UI |
+| [Luna](https://github.com/jumpserver/luna) | | JumpServer Web Terminal |
+| [KoKo](https://github.com/jumpserver/koko) | | JumpServer Character Protocol Connector |
+| [Lion](https://github.com/jumpserver/lion) | | JumpServer Graphical Protocol Connector |
+| [Chen](https://github.com/jumpserver/chen) | | JumpServer Web DB |
+| [Razor](https://github.com/jumpserver/razor) | | JumpServer EE RDP Proxy Connector |
+| [Tinker](https://github.com/jumpserver/tinker) | | JumpServer EE Remote Application Connector (Windows) |
+| [Panda](https://github.com/jumpserver/Panda) | | JumpServer EE Remote Application Connector (Linux) |
+| [Magnus](https://github.com/jumpserver/magnus) | | JumpServer EE Database Proxy Connector |
## 安全说明
JumpServer是一款安全产品,请参考 [基本安全建议](https://docs.jumpserver.org/zh/master/install/install_security/)
diff --git a/apps/accounts/automations/change_secret/host/aix/main.yml b/apps/accounts/automations/change_secret/host/aix/main.yml
index fa8d0f54f..761a9c2c1 100644
--- a/apps/accounts/automations/change_secret/host/aix/main.yml
+++ b/apps/accounts/automations/change_secret/host/aix/main.yml
@@ -35,6 +35,17 @@
- user_info.failed
- params.groups
+ - name: "Set {{ account.username }} 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:
+ - user_info.failed or params.modify_sudo
+ - params.sudo
+
- name: "Change {{ account.username }} password"
ansible.builtin.user:
name: "{{ account.username }}"
@@ -59,17 +70,6 @@
exclusive: "{{ ssh_params.exclusive }}"
when: account.secret_type == "ssh_key"
- - name: "Set {{ account.username }} 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:
- - user_info.failed
- - params.sudo
-
- name: Refresh connection
ansible.builtin.meta: reset_connection
diff --git a/apps/accounts/automations/change_secret/host/aix/manifest.yml b/apps/accounts/automations/change_secret/host/aix/manifest.yml
index a3df14a4d..145a4bf26 100644
--- a/apps/accounts/automations/change_secret/host/aix/manifest.yml
+++ b/apps/accounts/automations/change_secret/host/aix/manifest.yml
@@ -5,6 +5,12 @@ type:
- AIX
method: change_secret
params:
+ - name: modify_sudo
+ type: bool
+ label: "{{ 'Modify sudo label' | trans }}"
+ default: False
+ help_text: "{{ 'Modify params sudo help text' | trans }}"
+
- name: sudo
type: str
label: 'Sudo'
@@ -34,6 +40,11 @@ i18n:
ja: 'Ansible user モジュールを使用してアカウントのパスワード変更 (DES)'
en: 'Using Ansible module user to change account secret (DES)'
+ Modify params sudo help text:
+ zh: '如果用户存在,可以修改sudo权限'
+ ja: 'ユーザーが存在する場合、sudo権限を変更できます'
+ en: 'If the user exists, sudo permissions can be modified'
+
Params sudo help text:
zh: '使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig'
ja: 'コンマで区切って複数のコマンドを入力してください。例: /bin/whoami,/sbin/ifconfig'
@@ -49,6 +60,11 @@ i18n:
ja: 'グループを入力してください。複数のグループはコンマで区切ってください(既存のグループを入力してください)'
en: 'Please enter the group. Multiple groups are separated by commas (please enter the existing group)'
+ Modify sudo label:
+ zh: '修改 sudo 权限'
+ ja: 'sudo 権限を変更'
+ en: 'Modify sudo'
+
Params home label:
zh: '家目录'
ja: 'ホームディレクトリ'
diff --git a/apps/accounts/automations/change_secret/host/posix/main.yml b/apps/accounts/automations/change_secret/host/posix/main.yml
index a77347f00..d166de81f 100644
--- a/apps/accounts/automations/change_secret/host/posix/main.yml
+++ b/apps/accounts/automations/change_secret/host/posix/main.yml
@@ -35,6 +35,17 @@
- user_info.failed
- params.groups
+ - name: "Set {{ account.username }} 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:
+ - user_info.failed or params.modify_sudo
+ - params.sudo
+
- name: "Change {{ account.username }} password"
ansible.builtin.user:
name: "{{ account.username }}"
@@ -59,17 +70,6 @@
exclusive: "{{ ssh_params.exclusive }}"
when: account.secret_type == "ssh_key"
- - name: "Set {{ account.username }} 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:
- - user_info.failed
- - 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 43d1ca5fd..9ab86cdb9 100644
--- a/apps/accounts/automations/change_secret/host/posix/manifest.yml
+++ b/apps/accounts/automations/change_secret/host/posix/manifest.yml
@@ -6,6 +6,12 @@ type:
- linux
method: change_secret
params:
+ - name: modify_sudo
+ type: bool
+ label: "{{ 'Modify sudo label' | trans }}"
+ default: False
+ help_text: "{{ 'Modify params sudo help text' | trans }}"
+
- name: sudo
type: str
label: 'Sudo'
@@ -36,6 +42,11 @@ i18n:
ja: 'Ansible user モジュールを使用して アカウントのパスワード変更 (SHA512)'
en: 'Using Ansible module user to change account secret (SHA512)'
+ Modify params sudo help text:
+ zh: '如果用户存在,可以修改sudo权限'
+ ja: 'ユーザーが存在する場合、sudo権限を変更できます'
+ en: 'If the user exists, sudo permissions can be modified'
+
Params sudo help text:
zh: '使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig'
ja: 'コンマで区切って複数のコマンドを入力してください。例: /bin/whoami,/sbin/ifconfig'
@@ -51,6 +62,11 @@ i18n:
ja: 'グループを入力してください。複数のグループはコンマで区切ってください(既存のグループを入力してください)'
en: 'Please enter the group. Multiple groups are separated by commas (please enter the existing group)'
+ Modify sudo label:
+ zh: '修改 sudo 权限'
+ ja: 'sudo 権限を変更'
+ en: 'Modify sudo'
+
Params home label:
zh: '家目录'
ja: 'ホームディレクトリ'
diff --git a/apps/accounts/automations/change_secret/manager.py b/apps/accounts/automations/change_secret/manager.py
index 2a4432182..024282d82 100644
--- a/apps/accounts/automations/change_secret/manager.py
+++ b/apps/accounts/automations/change_secret/manager.py
@@ -8,7 +8,7 @@ from django.utils.translation import gettext_lazy as _
from xlsxwriter import Workbook
from accounts.const import AutomationTypes, SecretType, SSHKeyStrategy, SecretStrategy, ChangeSecretRecordStatusChoice
-from accounts.models import ChangeSecretRecord
+from accounts.models import ChangeSecretRecord, BaseAccountQuerySet
from accounts.notifications import ChangeSecretExecutionTaskMsg, ChangeSecretFailedMsg
from accounts.serializers import ChangeSecretRecordBackUpSerializer
from assets.const import HostTypes
@@ -68,10 +68,10 @@ class ChangeSecretManager(AccountBasePlaybookManager):
else:
return self.secret_generator(secret_type).get_secret()
- def get_accounts(self, privilege_account):
+ def get_accounts(self, privilege_account) -> BaseAccountQuerySet | None:
if not privilege_account:
- print(f'not privilege account')
- return []
+ print('Not privilege account')
+ return
asset = privilege_account.asset
accounts = asset.accounts.all()
@@ -108,6 +108,9 @@ class ChangeSecretManager(AccountBasePlaybookManager):
print(f'Windows {asset} does not support ssh key push')
return inventory_hosts
+ if asset.type == HostTypes.WINDOWS:
+ accounts = accounts.filter(secret_type=SecretType.PASSWORD)
+
host['ssh_params'] = {}
for account in accounts:
h = deepcopy(host)
@@ -226,6 +229,9 @@ class ChangeSecretManager(AccountBasePlaybookManager):
def run(self, *args, **kwargs):
if self.secret_type and not self.check_secret():
+ self.execution.status = 'success'
+ self.execution.date_finished = timezone.now()
+ self.execution.save()
return
super().run(*args, **kwargs)
recorders = list(self.name_recorder_mapper.values())
diff --git a/apps/accounts/automations/gather_accounts/filter.py b/apps/accounts/automations/gather_accounts/filter.py
index f3b111d36..1cca4d980 100644
--- a/apps/accounts/automations/gather_accounts/filter.py
+++ b/apps/accounts/automations/gather_accounts/filter.py
@@ -31,7 +31,7 @@ class GatherAccountsFilter:
def posix_filter(info):
username_pattern = re.compile(r'^(\S+)')
ip_pattern = re.compile(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
- login_time_pattern = re.compile(r'\w{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}')
+ login_time_pattern = re.compile(r'\w{3} \w{3}\s+\d{1,2} \d{2}:\d{2}:\d{2} \d{4}')
result = {}
for line in info:
usernames = username_pattern.findall(line)
@@ -46,7 +46,8 @@ class GatherAccountsFilter:
result[username].update({'address': ip_addr})
login_times = login_time_pattern.findall(line)
if login_times:
- date = timezone.datetime.strptime(f'{login_times[0]} +0800', '%b %d %H:%M:%S %Y %z')
+ datetime_str = login_times[0].split(' ', 1)[1] + " +0800"
+ date = timezone.datetime.strptime(datetime_str, '%b %d %H:%M:%S %Y %z')
result[username].update({'date': date})
return result
diff --git a/apps/accounts/automations/push_account/host/aix/main.yml b/apps/accounts/automations/push_account/host/aix/main.yml
index 5f76f79a8..8c03c07f3 100644
--- a/apps/accounts/automations/push_account/host/aix/main.yml
+++ b/apps/accounts/automations/push_account/host/aix/main.yml
@@ -35,6 +35,17 @@
- user_info.failed
- params.groups
+ - name: "Set {{ account.username }} 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:
+ - user_info.failed or params.modify_sudo
+ - params.sudo
+
- name: "Change {{ account.username }} password"
ansible.builtin.user:
name: "{{ account.username }}"
@@ -59,17 +70,6 @@
exclusive: "{{ ssh_params.exclusive }}"
when: account.secret_type == "ssh_key"
- - name: "Set {{ account.username }} 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:
- - user_info.failed
- - params.sudo
-
- name: Refresh connection
ansible.builtin.meta: reset_connection
diff --git a/apps/accounts/automations/push_account/host/aix/manifest.yml b/apps/accounts/automations/push_account/host/aix/manifest.yml
index ee62d7020..f00a7435d 100644
--- a/apps/accounts/automations/push_account/host/aix/manifest.yml
+++ b/apps/accounts/automations/push_account/host/aix/manifest.yml
@@ -5,6 +5,12 @@ type:
- AIX
method: push_account
params:
+ - name: modify_sudo
+ type: bool
+ label: "{{ 'Modify sudo label' | trans }}"
+ default: False
+ help_text: "{{ 'Modify params sudo help text' | trans }}"
+
- name: sudo
type: str
label: 'Sudo'
@@ -34,6 +40,11 @@ i18n:
ja: 'Ansible user モジュールを使用して Aix アカウントをプッシュする (DES)'
en: 'Using Ansible module user to push account (DES)'
+ Modify params sudo help text:
+ zh: '如果用户存在,可以修改sudo权限'
+ ja: 'ユーザーが存在する場合、sudo権限を変更できます'
+ en: 'If the user exists, sudo permissions can be modified'
+
Params sudo help text:
zh: '使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig'
ja: 'コンマで区切って複数のコマンドを入力してください。例: /bin/whoami,/sbin/ifconfig'
@@ -49,6 +60,11 @@ i18n:
ja: 'グループを入力してください。複数のグループはコンマで区切ってください(既存のグループを入力してください)'
en: 'Please enter the group. Multiple groups are separated by commas (please enter the existing group)'
+ Modify sudo label:
+ zh: '修改 sudo 权限'
+ ja: 'sudo 権限を変更'
+ en: 'Modify sudo'
+
Params home label:
zh: '家目录'
ja: 'ホームディレクトリ'
diff --git a/apps/accounts/automations/push_account/host/posix/main.yml b/apps/accounts/automations/push_account/host/posix/main.yml
index f5cb53144..8bc433f5a 100644
--- a/apps/accounts/automations/push_account/host/posix/main.yml
+++ b/apps/accounts/automations/push_account/host/posix/main.yml
@@ -35,6 +35,17 @@
- user_info.failed
- params.groups
+ - name: "Set {{ account.username }} 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:
+ - user_info.failed or params.modify_sudo
+ - params.sudo
+
- name: "Change {{ account.username }} password"
ansible.builtin.user:
name: "{{ account.username }}"
@@ -59,17 +70,6 @@
exclusive: "{{ ssh_params.exclusive }}"
when: account.secret_type == "ssh_key"
- - name: "Set {{ account.username }} 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:
- - user_info.failed
- - params.sudo
-
- name: Refresh connection
ansible.builtin.meta: reset_connection
diff --git a/apps/accounts/automations/push_account/host/posix/manifest.yml b/apps/accounts/automations/push_account/host/posix/manifest.yml
index 32964f1d6..86342b48a 100644
--- a/apps/accounts/automations/push_account/host/posix/manifest.yml
+++ b/apps/accounts/automations/push_account/host/posix/manifest.yml
@@ -6,6 +6,12 @@ type:
- linux
method: push_account
params:
+ - name: modify_sudo
+ type: bool
+ label: "{{ 'Modify sudo label' | trans }}"
+ default: False
+ help_text: "{{ 'Modify params sudo help text' | trans }}"
+
- name: sudo
type: str
label: 'Sudo'
@@ -36,6 +42,11 @@ i18n:
ja: 'Ansible user モジュールを使用してアカウントをプッシュする (sha512)'
en: 'Using Ansible module user to push account (sha512)'
+ Modify params sudo help text:
+ zh: '如果用户存在,可以修改sudo权限'
+ ja: 'ユーザーが存在する場合、sudo権限を変更できます'
+ en: 'If the user exists, sudo permissions can be modified'
+
Params sudo help text:
zh: '使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig'
ja: 'コンマで区切って複数のコマンドを入力してください。例: /bin/whoami,/sbin/ifconfig'
@@ -51,6 +62,11 @@ i18n:
ja: 'グループを入力してください。複数のグループはコンマで区切ってください(既存のグループを入力してください)'
en: 'Please enter the group. Multiple groups are separated by commas (please enter the existing group)'
+ Modify sudo label:
+ zh: '修改 sudo 权限'
+ ja: 'sudo 権限を変更'
+ en: 'Modify sudo'
+
Params home label:
zh: '家目录'
ja: 'ホームディレクトリ'
diff --git a/apps/accounts/migrations/0001_initial.py b/apps/accounts/migrations/0001_initial.py
index c1bf3bd13..dbecc94d0 100644
--- a/apps/accounts/migrations/0001_initial.py
+++ b/apps/accounts/migrations/0001_initial.py
@@ -10,7 +10,6 @@ import common.db.fields
class Migration(migrations.Migration):
-
initial = True
dependencies = [
@@ -26,13 +25,19 @@ class Migration(migrations.Migration):
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('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')),
+ ('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')),
('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')),
('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
('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'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')),
+ ('secret_type', models.CharField(
+ choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'),
+ ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16,
+ verbose_name='Secret type')),
('privileged', models.BooleanField(default=False, verbose_name='Privileged')),
('is_active', models.BooleanField(default=True, verbose_name='Is active')),
('version', models.IntegerField(default=0, verbose_name='Version')),
@@ -41,7 +46,11 @@ class Migration(migrations.Migration):
],
options={
'verbose_name': 'Account',
- 'permissions': [('view_accountsecret', 'Can view asset account secret'), ('view_historyaccount', 'Can view asset history account'), ('view_historyaccountsecret', 'Can view asset history account secret'), ('verify_account', 'Can verify account'), ('push_account', 'Can push account'), ('remove_account', 'Can remove account')],
+ 'permissions': [('view_accountsecret', 'Can view asset account secret'),
+ ('view_historyaccount', 'Can view asset history account'),
+ ('view_historyaccountsecret', 'Can view asset history account secret'),
+ ('verify_account', 'Can verify account'), ('push_account', 'Can push account'),
+ ('remove_account', 'Can remove account')],
},
),
migrations.CreateModel(
@@ -53,16 +62,21 @@ class Migration(migrations.Migration):
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('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')),
+ ('org_id',
+ models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('name', models.CharField(max_length=128, verbose_name='Name')),
('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')),
('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')),
('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')),
('types', models.JSONField(default=list)),
- ('backup_type', models.CharField(choices=[('email', 'Email'), ('object_storage', 'SFTP')], default='email', max_length=128, verbose_name='Backup type')),
+ ('backup_type',
+ models.CharField(choices=[('email', 'Email'), ('object_storage', 'SFTP')], default='email',
+ max_length=128, verbose_name='Backup type')),
('is_password_divided_by_email', models.BooleanField(default=True, verbose_name='Password divided')),
- ('is_password_divided_by_obj_storage', models.BooleanField(default=True, verbose_name='Password divided')),
- ('zip_encrypt_password', common.db.fields.EncryptCharField(blank=True, max_length=4096, null=True, verbose_name='Zip encrypt password')),
+ ('is_password_divided_by_obj_storage',
+ models.BooleanField(default=True, verbose_name='Password divided')),
+ ('zip_encrypt_password', common.db.fields.EncryptCharField(blank=True, max_length=4096, null=True,
+ verbose_name='Zip encrypt password')),
],
options={
'verbose_name': 'Account backup plan',
@@ -72,12 +86,16 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='AccountBackupExecution',
fields=[
- ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
+ ('org_id',
+ models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('date_start', models.DateTimeField(auto_now_add=True, verbose_name='Date start')),
('timedelta', models.FloatField(default=0.0, null=True, verbose_name='Time')),
- ('snapshot', models.JSONField(blank=True, default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True, verbose_name='Account backup snapshot')),
- ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')),
+ ('snapshot',
+ models.JSONField(blank=True, default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True,
+ verbose_name='Account backup snapshot')),
+ ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')],
+ default='manual', max_length=128, verbose_name='Trigger mode')),
('reason', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Reason')),
('is_success', models.BooleanField(default=False, verbose_name='Is success')),
],
@@ -95,13 +113,19 @@ class Migration(migrations.Migration):
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('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')),
+ ('org_id',
+ models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
- ('secret_strategy', models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy')),
+ ('secret_strategy',
+ models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')],
+ default='specific', max_length=16, verbose_name='Secret strategy')),
('password_rules', models.JSONField(default=dict, verbose_name='Password rules')),
('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'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')),
+ ('secret_type', models.CharField(
+ choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'),
+ ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16,
+ verbose_name='Secret type')),
('privileged', models.BooleanField(default=False, verbose_name='Privileged')),
('is_active', models.BooleanField(default=True, verbose_name='Is active')),
('auto_push', models.BooleanField(default=False, verbose_name='Auto push')),
@@ -142,7 +166,8 @@ class Migration(migrations.Migration):
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('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')),
+ ('org_id',
+ models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('present', models.BooleanField(default=True, verbose_name='Present')),
('date_last_login', models.DateTimeField(null=True, verbose_name='Date login')),
('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')),
@@ -158,12 +183,16 @@ class Migration(migrations.Migration):
fields=[
('id', models.UUIDField(db_index=True, default=uuid.uuid4)),
('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')),
- ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')),
+ ('secret_type', models.CharField(
+ choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'),
+ ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16,
+ verbose_name='Secret type')),
('version', models.IntegerField(default=0, verbose_name='Version')),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
- ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
+ ('history_type',
+ models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
],
options={
'verbose_name': 'historical Account',
@@ -181,9 +210,13 @@ class Migration(migrations.Migration):
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('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')),
- ('alias', models.CharField(choices=[('@INPUT', 'Manual input'), ('@USER', 'Dynamic user'), ('@ANON', 'Anonymous account'), ('@SPEC', 'Specified account')], max_length=128, verbose_name='Alias')),
+ ('org_id',
+ models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
+ ('alias', models.CharField(
+ choices=[('@INPUT', 'Manual input'), ('@USER', 'Dynamic user'), ('@ANON', 'Anonymous account'),
+ ('@SPEC', 'Specified account')], max_length=128, verbose_name='Alias')),
('secret_from_login', models.BooleanField(default=None, null=True, verbose_name='Secret from login')),
],
+ options={'verbose_name': 'Virtual account'},
),
]
diff --git a/apps/accounts/models/account.py b/apps/accounts/models/account.py
index 4a175609f..f99230670 100644
--- a/apps/accounts/models/account.py
+++ b/apps/accounts/models/account.py
@@ -119,7 +119,8 @@ class Account(AbsConnectivity, LabeledMixin, BaseAccount):
return auth
auth.update(self.make_account_ansible_vars(su_from))
- become_method = platform.su_method if platform.su_method else 'sudo'
+
+ become_method = platform.ansible_become_method
password = su_from.secret if become_method == 'sudo' else self.secret
auth['ansible_become'] = True
auth['ansible_become_method'] = become_method
diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py
index f3650e14b..691961f3e 100644
--- a/apps/accounts/serializers/account/account.py
+++ b/apps/accounts/serializers/account/account.py
@@ -81,21 +81,28 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer):
@staticmethod
def get_template_attr_for_account(template):
- # Set initial data from template
field_names = [
- 'name', 'username', 'secret', 'push_params',
- 'secret_type', 'privileged', 'is_active'
+ 'name', 'username',
+ 'secret_type', 'secret',
+ 'privileged', 'is_active'
]
+ field_map = {
+ 'push_params': 'params',
+ 'auto_push': 'push_now'
+ }
+
+ field_names.extend(field_map.keys())
+
attrs = {}
for name in field_names:
value = getattr(template, name, None)
if value is None:
continue
- if name == 'push_params':
- attrs['params'] = value
- else:
- attrs[name] = value
+
+ attr_name = field_map.get(name, name)
+ attrs[attr_name] = value
+
attrs['secret'] = template.get_secret()
return attrs
@@ -178,7 +185,8 @@ class AccountCreateUpdateSerializerMixin(serializers.Serializer):
params = validated_data.pop('params', None)
self.clean_auth_fields(validated_data)
instance, stat = self.do_create(validated_data)
- self.push_account_if_need(instance, push_now, params, stat)
+ if instance.source == Source.LOCAL:
+ self.push_account_if_need(instance, push_now, params, stat)
return instance
def update(self, instance, validated_data):
@@ -280,8 +288,8 @@ class AssetAccountBulkSerializer(
fields = [
'name', 'username', 'secret', 'secret_type', 'passphrase',
'privileged', 'is_active', 'comment', 'template',
- 'on_invalid', 'push_now', 'assets', 'su_from_username',
- 'source', 'source_id',
+ 'on_invalid', 'push_now', 'params', 'assets',
+ 'su_from_username', 'source', 'source_id',
]
extra_kwargs = {
'name': {'required': False},
@@ -419,16 +427,23 @@ class AssetAccountBulkSerializer(
return results
@staticmethod
- def push_accounts_if_need(results, push_now):
+ def push_accounts_if_need(results, push_now, params):
if not push_now:
return
- accounts = [str(v['instance']) for v in results if v.get('instance')]
- push_accounts_to_assets_task.delay(accounts)
+
+ account_ids = [v['instance'] for v in results if v.get('instance')]
+ accounts = Account.objects.filter(id__in=account_ids, source=Source.LOCAL)
+ if not accounts.exists():
+ return
+
+ account_ids = [str(_id) for _id in accounts.values_list('id', flat=True)]
+ push_accounts_to_assets_task.delay(account_ids, params)
def create(self, validated_data):
+ params = validated_data.pop('params', None)
push_now = validated_data.pop('push_now', False)
results = self.perform_bulk_create(validated_data)
- self.push_accounts_if_need(results, push_now)
+ self.push_accounts_if_need(results, push_now, params)
for res in results:
res['asset'] = str(res['asset'])
return results
diff --git a/apps/accounts/signal_handlers.py b/apps/accounts/signal_handlers.py
index 3ae1fba5c..ad07c9bb3 100644
--- a/apps/accounts/signal_handlers.py
+++ b/apps/accounts/signal_handlers.py
@@ -6,6 +6,7 @@ from django.dispatch import receiver
from django.utils.translation import gettext_noop
from accounts.backends import vault_client
+from accounts.const import Source
from audits.const import ActivityChoices
from audits.signal_handlers import create_activities
from common.decorators import merge_delay_run
@@ -32,7 +33,7 @@ def push_accounts_if_need(accounts=()):
template_accounts = defaultdict(list)
for ac in accounts:
# 再强调一次吧
- if ac.source != 'template':
+ if ac.source != Source.TEMPLATE:
continue
template_accounts[ac.source_id].append(ac)
@@ -61,7 +62,7 @@ def create_accounts_activities(account, action='create'):
@receiver(post_save, sender=Account)
def on_account_create_by_template(sender, instance, created=False, **kwargs):
- if not created or instance.source != 'template':
+ if not created or instance.source != Source.TEMPLATE:
return
push_accounts_if_need.delay(accounts=(instance,))
create_accounts_activities(instance, action='create')
diff --git a/apps/assets/api/__init__.py b/apps/assets/api/__init__.py
index 9eccd4977..3f49c2b62 100644
--- a/apps/assets/api/__init__.py
+++ b/apps/assets/api/__init__.py
@@ -7,3 +7,4 @@ from .node import *
from .platform import *
from .protocol import *
from .tree import *
+from .my_asset import *
diff --git a/apps/assets/api/mixin.py b/apps/assets/api/mixin.py
index af5864e4e..042c6bceb 100644
--- a/apps/assets/api/mixin.py
+++ b/apps/assets/api/mixin.py
@@ -2,7 +2,7 @@ from typing import List
from rest_framework.request import Request
-from assets.models import Node, Platform, Protocol
+from assets.models import Node, Platform, Protocol, MyAsset
from assets.utils import get_node_from_request, is_query_node_all_assets
from common.utils import lazyproperty, timeit
@@ -82,6 +82,7 @@ class SerializeToTreeNodeMixin:
data = []
root_assets_count = 0
+ MyAsset.set_asset_custom_value(assets, self.request.user)
for asset in assets:
platform = platform_map.get(asset.platform_id)
if not platform:
diff --git a/apps/assets/api/my_asset.py b/apps/assets/api/my_asset.py
new file mode 100644
index 000000000..ee02500f4
--- /dev/null
+++ b/apps/assets/api/my_asset.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+#
+from common.api import GenericViewSet
+from rest_framework.mixins import CreateModelMixin
+from common.permissions import IsValidUser
+from ..serializers import MyAssetSerializer
+
+__all__ = ['MyAssetViewSet']
+
+
+class MyAssetViewSet(CreateModelMixin, GenericViewSet):
+ serializer_class = MyAssetSerializer
+ permission_classes = (IsValidUser,)
diff --git a/apps/assets/api/platform.py b/apps/assets/api/platform.py
index 4df9cb4a3..bce8505cf 100644
--- a/apps/assets/api/platform.py
+++ b/apps/assets/api/platform.py
@@ -1,3 +1,4 @@
+from django.db.models import Count
from rest_framework import generics
from rest_framework import serializers
from rest_framework.decorators import action
@@ -5,7 +6,7 @@ from rest_framework.response import Response
from assets.const import AllTypes
from assets.models import Platform, Node, Asset, PlatformProtocol
-from assets.serializers import PlatformSerializer, PlatformProtocolSerializer
+from assets.serializers import PlatformSerializer, PlatformProtocolSerializer, PlatformListSerializer
from common.api import JMSModelViewSet
from common.permissions import IsValidUser
from common.serializers import GroupedChoiceSerializer
@@ -17,6 +18,7 @@ class AssetPlatformViewSet(JMSModelViewSet):
queryset = Platform.objects.all()
serializer_classes = {
'default': PlatformSerializer,
+ 'list': PlatformListSerializer,
'categories': GroupedChoiceSerializer,
}
filterset_fields = ['name', 'category', 'type']
@@ -31,8 +33,8 @@ class AssetPlatformViewSet(JMSModelViewSet):
def get_queryset(self):
# 因为没有走分页逻辑,所以需要这里 prefetch
- queryset = super().get_queryset().prefetch_related(
- 'protocols', 'automation', 'labels', 'labels__label',
+ queryset = super().get_queryset().annotate(assets_amount=Count('assets')).prefetch_related(
+ 'protocols', 'automation', 'labels', 'labels__label'
)
queryset = queryset.filter(type__in=AllTypes.get_types_values())
return queryset
diff --git a/apps/assets/api/tree.py b/apps/assets/api/tree.py
index f5e39b4db..32f6aed27 100644
--- a/apps/assets/api/tree.py
+++ b/apps/assets/api/tree.py
@@ -39,16 +39,16 @@ class NodeChildrenApi(generics.ListCreateAPIView):
self.instance = self.get_object()
def perform_create(self, serializer):
+ data = serializer.validated_data
+ _id = data.get("id")
+ value = data.get("value")
+ if value:
+ children = self.instance.get_children()
+ if children.filter(value=value).exists():
+ raise JMSException(_('The same level node name cannot be the same'))
+ else:
+ value = self.instance.get_next_child_preset_name()
with NodeAddChildrenLock(self.instance):
- data = serializer.validated_data
- _id = data.get("id")
- value = data.get("value")
- if value:
- children = self.instance.get_children()
- if children.filter(value=value).exists():
- raise JMSException(_('The same level node name cannot be the same'))
- else:
- value = self.instance.get_next_child_preset_name()
node = self.instance.create_child(value=value, _id=_id)
# 避免查询 full value
node._full_value = node.value
diff --git a/apps/assets/automations/base/manager.py b/apps/assets/automations/base/manager.py
index 16be2068c..c9de04baf 100644
--- a/apps/assets/automations/base/manager.py
+++ b/apps/assets/automations/base/manager.py
@@ -113,11 +113,7 @@ class BasePlaybookManager:
if not data:
data = automation_params.get(method_id, {})
params = serializer(data).data
- return {
- field_name: automation_params.get(field_name, '')
- if not params[field_name] else params[field_name]
- for field_name in params
- }
+ return params
@property
def platform_automation_methods(self):
diff --git a/apps/assets/automations/gather_facts/host/posix/main.yml b/apps/assets/automations/gather_facts/host/posix/main.yml
index ba86d9a91..0b083c94b 100644
--- a/apps/assets/automations/gather_facts/host/posix/main.yml
+++ b/apps/assets/automations/gather_facts/host/posix/main.yml
@@ -12,7 +12,12 @@
cpu_cores: "{{ ansible_processor_cores }}"
cpu_vcpus: "{{ ansible_processor_vcpus }}"
memory: "{{ ansible_memtotal_mb / 1024 | round(2) }}"
- disk_total: "{{ (ansible_mounts | map(attribute='size_total') | sum / 1024 / 1024 / 1024) | round(2) }}"
+ disk_total: |-
+ {% set ns = namespace(total=0) %}
+ {%- for name, dev in ansible_devices.items() if dev.removable == '0' and dev.host != '' -%}
+ {%- set ns.total = ns.total + ( dev.sectors | int * dev.sectorsize | int ) -%}
+ {%- endfor -%}
+ {{- (ns.total / 1024 / 1024 / 1024) | round(2) -}}
distribution: "{{ ansible_distribution }}"
distribution_version: "{{ ansible_distribution_version }}"
arch: "{{ ansible_architecture }}"
diff --git a/apps/assets/automations/gather_facts/host/windows/main.yml b/apps/assets/automations/gather_facts/host/windows/main.yml
index 377ffd10a..57e18d25f 100644
--- a/apps/assets/automations/gather_facts/host/windows/main.yml
+++ b/apps/assets/automations/gather_facts/host/windows/main.yml
@@ -11,8 +11,10 @@
vendor: "{{ ansible_system_vendor }}"
model: "{{ ansible_product_name }}"
sn: "{{ ansible_product_serial }}"
+ cpu_count: "{{ ansible_processor_count }}"
+ cpu_cores: "{{ ansible_processor_cores }}"
cpu_vcpus: "{{ ansible_processor_vcpus }}"
- memory: "{{ ansible_memtotal_mb }}"
+ memory: "{{ (ansible_memtotal_mb / 1024) | round(2) }}"
- debug:
var: info
diff --git a/apps/assets/const/__init__.py b/apps/assets/const/__init__.py
index 9e3f2cbb1..abf7e71b1 100644
--- a/apps/assets/const/__init__.py
+++ b/apps/assets/const/__init__.py
@@ -2,5 +2,6 @@ from .automation import *
from .base import *
from .category import *
from .host import *
+from .platform import *
from .protocol import *
from .types import *
diff --git a/apps/assets/const/database.py b/apps/assets/const/database.py
index 6dcd42447..9457cc427 100644
--- a/apps/assets/const/database.py
+++ b/apps/assets/const/database.py
@@ -117,5 +117,6 @@ class DatabaseTypes(BaseType):
@classmethod
def get_community_types(cls):
return [
- cls.MYSQL, cls.MARIADB, cls.MONGODB, cls.REDIS
+ cls.MYSQL, cls.MARIADB, cls.POSTGRESQL,
+ cls.MONGODB, cls.REDIS,
]
diff --git a/apps/assets/const/host.py b/apps/assets/const/host.py
index f408e5e5e..91942e294 100644
--- a/apps/assets/const/host.py
+++ b/apps/assets/const/host.py
@@ -19,7 +19,7 @@ class HostTypes(BaseType):
'charset': 'utf-8', # default
'domain_enabled': True,
'su_enabled': True,
- 'su_methods': ['sudo', 'su'],
+ 'su_methods': ['sudo', 'su', 'only_sudo', 'only_su'],
},
cls.WINDOWS: {
'su_enabled': False,
diff --git a/apps/assets/const/platform.py b/apps/assets/const/platform.py
new file mode 100644
index 000000000..f37d9fcc6
--- /dev/null
+++ b/apps/assets/const/platform.py
@@ -0,0 +1,11 @@
+from django.db.models import TextChoices
+
+
+class SuMethodChoices(TextChoices):
+ sudo = "sudo", "sudo su -"
+ su = "su", "su - "
+ only_sudo = "only_sudo", "sudo su"
+ only_su = "only_su", "su"
+ enable = "enable", "enable"
+ super = "super", "super 15"
+ super_level = "super_level", "super level 15"
diff --git a/apps/assets/const/protocol.py b/apps/assets/const/protocol.py
index 474570bab..07a60c3de 100644
--- a/apps/assets/const/protocol.py
+++ b/apps/assets/const/protocol.py
@@ -80,7 +80,18 @@ class Protocol(ChoicesMixin, models.TextChoices):
'choices': [('any', _('Any')), ('rdp', 'RDP'), ('tls', 'TLS'), ('nla', 'NLA')],
'default': 'any',
'label': _('Security'),
- 'help_text': _("Security layer to use for the connection")
+ 'help_text': _("Security layer to use for the connection:
"
+ "Any
"
+ "Automatically select the security mode based on the security protocols "
+ "supported by both the client and the server
"
+ "RDP
"
+ "Legacy RDP encryption. This mode is generally only used for older Windows "
+ "servers or in cases where a standard Windows login screen is desired
"
+ "TLS
"
+ "RDP authentication and encryption implemented via TLS.
"
+ "NLA
"
+ "This mode uses TLS encryption and requires the username and password "
+ "to be given in advance")
},
'ad_domain': {
'type': 'str',
@@ -208,6 +219,12 @@ class Protocol(ChoicesMixin, models.TextChoices):
'default': 'admin',
'label': _('Auth source'),
'help_text': _('The database to authenticate against')
+ },
+ 'connection_options': {
+ 'type': 'str',
+ 'default': '',
+ 'label': _('Connect options'),
+ 'help_text': _('The connection specific options eg. retryWrites=false&retryReads=false')
}
}
},
@@ -289,23 +306,17 @@ class Protocol(ChoicesMixin, models.TextChoices):
'setting': {
'api_mode': {
'type': 'choice',
- 'default': 'gpt-3.5-turbo',
+ 'default': 'gpt-4o-mini',
'label': _('API mode'),
'choices': [
- ('gpt-3.5-turbo', 'GPT-3.5 Turbo'),
- ('gpt-3.5-turbo-1106', 'GPT-3.5 Turbo 1106'),
+ ('gpt-4o-mini', 'GPT-4o-mini'),
+ ('gpt-4o', 'GPT-4o'),
+ ('gpt-4-turbo', 'GPT-4 Turbo'),
]
}
}
}
}
- if settings.XPACK_LICENSE_IS_VALID:
- choices = protocols[cls.chatgpt]['setting']['api_mode']['choices']
- choices.extend([
- ('gpt-4', 'GPT-4'),
- ('gpt-4-turbo', 'GPT-4 Turbo'),
- ('gpt-4o', 'GPT-4o'),
- ])
return protocols
@classmethod
diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py
index b03f22d12..41944e803 100644
--- a/apps/assets/const/types.py
+++ b/apps/assets/const/types.py
@@ -171,12 +171,9 @@ class AllTypes(ChoicesMixin):
(Category.DEVICE, DeviceTypes),
(Category.DATABASE, DatabaseTypes),
(Category.WEB, WebTypes),
+ (Category.CLOUD, CloudTypes),
+ (Category.CUSTOM, CustomTypes)
]
- if settings.XPACK_ENABLED:
- types.extend([
- (Category.CLOUD, CloudTypes),
- (Category.CUSTOM, CustomTypes),
- ])
return types
@classmethod
diff --git a/apps/assets/migrations/0004_auto_20240709_1819.py b/apps/assets/migrations/0004_auto_20240709_1819.py
new file mode 100644
index 000000000..5781dacbd
--- /dev/null
+++ b/apps/assets/migrations/0004_auto_20240709_1819.py
@@ -0,0 +1,28 @@
+# Generated by Django 4.1.13 on 2024-07-09 10:19
+
+from django.db import migrations
+
+
+def migrate_platform_protocol_primary(apps, schema_editor):
+ platform_model = apps.get_model('assets', 'Platform')
+ platforms = platform_model.objects.all()
+
+ for platform in platforms:
+ p = platform.protocols.filter(primary=True).first()
+ if p:
+ continue
+ p = platform.protocols.first()
+ if not p:
+ continue
+ p.primary = True
+ p.save()
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('assets', '0003_auto_20180109_2331'),
+ ]
+
+ operations = [
+ migrations.RunPython(migrate_platform_protocol_primary)
+ ]
diff --git a/apps/assets/migrations/0005_myasset.py b/apps/assets/migrations/0005_myasset.py
new file mode 100644
index 000000000..b2bf931ea
--- /dev/null
+++ b/apps/assets/migrations/0005_myasset.py
@@ -0,0 +1,35 @@
+# Generated by Django 4.1.13 on 2024-08-06 09:11
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+import uuid
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('assets', '0004_auto_20240709_1819'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='MyAsset',
+ fields=[
+ ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
+ ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
+ ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
+ ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
+ ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
+ ('name', models.CharField(default='', max_length=128, verbose_name='Custom Name')),
+ ('comment', models.CharField(default='', max_length=512, verbose_name='Custom Comment')),
+ ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='my_assets', to='assets.asset')),
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'My assets',
+ 'unique_together': {('user', 'asset')},
+ },
+ ),
+ ]
diff --git a/apps/assets/models/__init__.py b/apps/assets/models/__init__.py
index 74bb94517..dc6ca8e97 100644
--- a/apps/assets/models/__init__.py
+++ b/apps/assets/models/__init__.py
@@ -7,3 +7,4 @@ from .domain import *
from .node import *
from .favorite_asset import *
from .automations import *
+from .my_asset import *
diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py
index 9676c3db0..6f7df504d 100644
--- a/apps/assets/models/asset/common.py
+++ b/apps/assets/models/asset/common.py
@@ -173,7 +173,7 @@ class Asset(NodesRelationMixin, LabeledMixin, AbsConnectivity, JSONFilterMixin,
def get_labels(self):
from labels.models import Label, LabeledResource
- res_type = ContentType.objects.get_for_model(self.__class__)
+ res_type = ContentType.objects.get_for_model(self.__class__.label_model())
label_ids = LabeledResource.objects.filter(res_type=res_type, res_id=self.id) \
.values_list('label_id', flat=True)
return Label.objects.filter(id__in=label_ids)
diff --git a/apps/assets/models/domain.py b/apps/assets/models/domain.py
index 68cbb63c9..0c75e22b7 100644
--- a/apps/assets/models/domain.py
+++ b/apps/assets/models/domain.py
@@ -31,7 +31,7 @@ class Domain(LabeledMixin, JMSOrgBaseModel):
@lazyproperty
def assets_amount(self):
- return self.assets.count()
+ return self.assets.exclude(platform__name='Gateway').count()
def random_gateway(self):
gateways = [gw for gw in self.active_gateways if gw.is_connective]
diff --git a/apps/assets/models/my_asset.py b/apps/assets/models/my_asset.py
new file mode 100644
index 000000000..605962972
--- /dev/null
+++ b/apps/assets/models/my_asset.py
@@ -0,0 +1,43 @@
+from django.db import models
+from django.utils.translation import gettext_lazy as _
+
+from common.db.models import JMSBaseModel
+
+__all__ = ['MyAsset']
+
+
+class MyAsset(JMSBaseModel):
+ user = models.ForeignKey('users.User', on_delete=models.CASCADE)
+ asset = models.ForeignKey('assets.Asset', on_delete=models.CASCADE, related_name='my_assets')
+ name = models.CharField(verbose_name=_("Custom Name"), max_length=128, default='')
+ comment = models.CharField(verbose_name=_("Custom Comment"), max_length=512, default='')
+ custom_fields = ['name', 'comment']
+
+ class Meta:
+ unique_together = ('user', 'asset')
+ verbose_name = _("My assets")
+
+ def custom_to_dict(self):
+ data = {}
+ for field in self.custom_fields:
+ value = getattr(self, field)
+ if value == "":
+ continue
+ data.update({field: value})
+ return data
+
+ @staticmethod
+ def set_asset_custom_value(assets, user):
+ my_assets = MyAsset.objects.filter(asset__in=assets, user=user).all()
+ customs = {my_asset.asset.id: my_asset.custom_to_dict() for my_asset in my_assets}
+ for asset in assets:
+ custom = customs.get(asset.id)
+ if not custom:
+ continue
+ for field, value in custom.items():
+ if not hasattr(asset, field):
+ continue
+ setattr(asset, field, value)
+
+ def __str__(self):
+ return f'{self.user}-{self.asset}'
diff --git a/apps/assets/models/platform.py b/apps/assets/models/platform.py
index 442579e9f..354914834 100644
--- a/apps/assets/models/platform.py
+++ b/apps/assets/models/platform.py
@@ -1,7 +1,7 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
-from assets.const import AllTypes, Category, Protocol
+from assets.const import AllTypes, Category, Protocol, SuMethodChoices
from common.db.fields import JsonDictTextField
from common.db.models import JMSBaseModel
@@ -111,6 +111,10 @@ class Platform(LabeledMixin, JMSBaseModel):
def type_constraints(self):
return AllTypes.get_constraints(self.category, self.type)
+ @lazyproperty
+ def assets_amount(self):
+ return self.assets.count()
+
@classmethod
def default(cls):
linux, created = cls.objects.get_or_create(
@@ -127,6 +131,17 @@ class Platform(LabeledMixin, JMSBaseModel):
return True
return False
+ @property
+ def ansible_become_method(self):
+ su_method = self.su_method or SuMethodChoices.sudo
+ if su_method in [SuMethodChoices.sudo, SuMethodChoices.only_sudo]:
+ method = SuMethodChoices.sudo
+ elif su_method in [SuMethodChoices.su, SuMethodChoices.only_su]:
+ method = SuMethodChoices.su
+ else:
+ method = su_method
+ return method
+
def __str__(self):
return self.name
diff --git a/apps/assets/serializers/__init__.py b/apps/assets/serializers/__init__.py
index e071e24c0..43dbf967c 100644
--- a/apps/assets/serializers/__init__.py
+++ b/apps/assets/serializers/__init__.py
@@ -9,3 +9,4 @@ from .favorite_asset import *
from .gateway import *
from .node import *
from .platform import *
+from .my_asset import *
diff --git a/apps/assets/serializers/automations/base.py b/apps/assets/serializers/automations/base.py
index 4622c0674..522049d17 100644
--- a/apps/assets/serializers/automations/base.py
+++ b/apps/assets/serializers/automations/base.py
@@ -36,6 +36,7 @@ class BaseAutomationSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSe
class AutomationExecutionSerializer(serializers.ModelSerializer):
snapshot = serializers.SerializerMethodField(label=_('Automation snapshot'))
+ status = serializers.SerializerMethodField(label=_("Status"))
trigger = LabeledChoiceField(choices=Trigger.choices, read_only=True, label=_("Trigger mode"))
class Meta:
@@ -45,6 +46,14 @@ class AutomationExecutionSerializer(serializers.ModelSerializer):
]
fields = ['id', 'automation'] + read_only_fields
+ @staticmethod
+ def get_status(obj):
+ if obj.status == 'success':
+ return _("Success")
+ elif obj.status == 'pending':
+ return _("Pending")
+ return obj.status
+
@staticmethod
def get_snapshot(obj):
from assets.const import AutomationTypes as AssetTypes
diff --git a/apps/assets/serializers/domain.py b/apps/assets/serializers/domain.py
index 5e70282f5..bba7e7310 100644
--- a/apps/assets/serializers/domain.py
+++ b/apps/assets/serializers/domain.py
@@ -57,9 +57,7 @@ class DomainSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer):
@classmethod
def setup_eager_loading(cls, queryset):
- queryset = queryset \
- .annotate(assets_amount=Count('assets')) \
- .prefetch_related('labels', 'labels__label')
+ queryset = queryset.prefetch_related('labels', 'labels__label')
return queryset
diff --git a/apps/assets/serializers/favorite_asset.py b/apps/assets/serializers/favorite_asset.py
index 909c13506..69c916f05 100644
--- a/apps/assets/serializers/favorite_asset.py
+++ b/apps/assets/serializers/favorite_asset.py
@@ -3,7 +3,6 @@
from rest_framework import serializers
-from orgs.utils import tmp_to_root_org
from common.serializers import BulkSerializerMixin
from ..models import FavoriteAsset
diff --git a/apps/assets/serializers/my_asset.py b/apps/assets/serializers/my_asset.py
new file mode 100644
index 000000000..17ff26d4d
--- /dev/null
+++ b/apps/assets/serializers/my_asset.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+#
+
+from rest_framework import serializers
+from django.utils.translation import gettext_lazy as _
+
+from ..models import MyAsset
+
+__all__ = ['MyAssetSerializer']
+
+
+class MyAssetSerializer(serializers.ModelSerializer):
+ user = serializers.HiddenField(
+ default=serializers.CurrentUserDefault()
+ )
+ name = serializers.CharField(label=_("Custom Name"), max_length=128, allow_blank=True, required=False)
+ comment = serializers.CharField(label=_("Custom Comment"), max_length=512, allow_blank=True, required=False)
+
+ class Meta:
+ model = MyAsset
+ fields = ['user', 'asset', 'name', 'comment']
+ validators = []
+
+ def create(self, data):
+ custom_fields = MyAsset.custom_fields
+ asset = data['asset']
+ user = self.context['request'].user
+ defaults = {field: data.get(field, '') for field in custom_fields}
+ obj, created = MyAsset.objects.get_or_create(defaults=defaults, user=user, asset=asset)
+ if created:
+ return obj
+ for field in custom_fields:
+ value = data.get(field)
+ if value is None:
+ continue
+ setattr(obj, field, value)
+ obj.save()
+ return obj
diff --git a/apps/assets/serializers/platform.py b/apps/assets/serializers/platform.py
index 3441ac6f4..2eb5a44b2 100644
--- a/apps/assets/serializers/platform.py
+++ b/apps/assets/serializers/platform.py
@@ -3,16 +3,17 @@ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
+from assets.models import Asset
from common.serializers import (
WritableNestedModelSerializer, type_field_map, MethodSerializer,
DictSerializer, create_serializer_class, ResourceLabelsMixin
)
-from common.serializers.fields import LabeledChoiceField
+from common.serializers.fields import LabeledChoiceField, ObjectRelatedField
from common.utils import lazyproperty
-from ..const import Category, AllTypes, Protocol
+from ..const import Category, AllTypes, Protocol, SuMethodChoices
from ..models import Platform, PlatformProtocol, PlatformAutomation
-__all__ = ["PlatformSerializer", "PlatformOpsMethodSerializer", "PlatformProtocolSerializer"]
+__all__ = ["PlatformSerializer", "PlatformOpsMethodSerializer", "PlatformProtocolSerializer", "PlatformListSerializer"]
class PlatformAutomationSerializer(serializers.ModelSerializer):
@@ -158,13 +159,6 @@ class PlatformCustomField(serializers.Serializer):
class PlatformSerializer(ResourceLabelsMixin, WritableNestedModelSerializer):
- SU_METHOD_CHOICES = [
- ("sudo", "sudo su -"),
- ("su", "su - "),
- ("enable", "enable"),
- ("super", "super 15"),
- ("super_level", "super level 15")
- ]
id = serializers.IntegerField(
label='ID', required=False,
validators=[UniqueValidator(queryset=Platform.objects.all())]
@@ -175,10 +169,12 @@ class PlatformSerializer(ResourceLabelsMixin, WritableNestedModelSerializer):
protocols = PlatformProtocolSerializer(label=_("Protocols"), many=True, required=False)
automation = PlatformAutomationSerializer(label=_("Automation"), required=False, default=dict)
su_method = LabeledChoiceField(
- choices=SU_METHOD_CHOICES, label=_("Su method"),
- required=False, default="sudo", allow_null=True
+ choices=SuMethodChoices.choices, label=_("Su method"),
+ required=False, default=SuMethodChoices.sudo, allow_null=True
)
custom_fields = PlatformCustomField(label=_("Custom fields"), many=True, required=False)
+ assets = ObjectRelatedField(queryset=Asset.objects, many=True, required=False, label=_('Assets'))
+ assets_amount = serializers.IntegerField(label=_('Assets amount'), read_only=True)
class Meta:
model = Platform
@@ -191,7 +187,8 @@ class PlatformSerializer(ResourceLabelsMixin, WritableNestedModelSerializer):
'internal', 'date_created', 'date_updated',
'created_by', 'updated_by'
]
- fields = fields_small + [
+ fields_m2m = ['assets', 'assets_amount']
+ fields = fields_small + fields_m2m + [
"protocols", "domain_enabled", "su_enabled", "su_method",
"automation", "comment", "custom_fields", "labels"
] + read_only_fields
@@ -208,6 +205,7 @@ class PlatformSerializer(ResourceLabelsMixin, WritableNestedModelSerializer):
"help_text": _("Assets can be connected using a zone gateway")
},
"domain_default": {"label": _('Default Domain')},
+ 'assets': {'required': False, 'label': _('Assets')},
}
def __init__(self, *args, **kwargs):
@@ -265,6 +263,11 @@ class PlatformSerializer(ResourceLabelsMixin, WritableNestedModelSerializer):
return automation
+class PlatformListSerializer(PlatformSerializer):
+ class Meta(PlatformSerializer.Meta):
+ fields = list(set(PlatformSerializer.Meta.fields + ['assets_amount']) - {'assets'})
+
+
class PlatformOpsMethodSerializer(serializers.Serializer):
id = serializers.CharField(read_only=True)
name = serializers.CharField(max_length=50, label=_("Name"))
diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py
index b56458758..d19d761b3 100644
--- a/apps/assets/urls/api_urls.py
+++ b/apps/assets/urls/api_urls.py
@@ -24,6 +24,7 @@ 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')
router.register(r'labels', LabelViewSet, 'label')
+router.register(r'my-asset', api.MyAssetViewSet, 'my-asset')
urlpatterns = [
# path('assets//gateways/', api.AssetGatewayListApi.as_view(), name='asset-gateway-list'),
diff --git a/apps/audits/handler.py b/apps/audits/handler.py
index debe0a068..c64160c4c 100644
--- a/apps/audits/handler.py
+++ b/apps/audits/handler.py
@@ -5,7 +5,7 @@ from django.core.cache import cache
from django.db import transaction
from django.utils.translation import gettext_lazy as _
-from common.local import encrypted_field_set
+from common.local import similar_encrypted_pattern, exclude_encrypted_fields
from common.utils import get_request_ip, get_logger
from common.utils.encode import Singleton
from common.utils.timezone import as_current_tz
@@ -109,19 +109,31 @@ class OperatorLogHandler(metaclass=Singleton):
return ','.join(value)
return json.dumps(value)
+ @staticmethod
+ def __similar_check(key):
+ if not key or key in exclude_encrypted_fields:
+ return False
+
+ return bool(similar_encrypted_pattern.search(key))
+
def __data_processing(self, dict_item, loop=True):
encrypt_value = '******'
- for key, value in dict_item.items():
+ new_data = {}
+ for label, item in dict_item.items():
+ if not isinstance(item, (dict,)):
+ continue
+ value = item.get('value', '')
+ field_name = item.get('name', '')
if isinstance(value, bool):
value = _('Yes') if value else _('No')
elif isinstance(value, (list, tuple)):
value = self.serialized_value(value)
elif isinstance(value, dict) and loop:
self.__data_processing(value, loop=False)
- if key in encrypted_field_set:
+ if self.__similar_check(field_name):
value = encrypt_value
- dict_item[key] = value
- return dict_item
+ new_data[label] = value
+ return new_data
def data_processing(self, before, after):
if before:
diff --git a/apps/audits/tasks.py b/apps/audits/tasks.py
index 00383544a..f59d515ee 100644
--- a/apps/audits/tasks.py
+++ b/apps/audits/tasks.py
@@ -16,6 +16,7 @@ from common.storage.ftp_file import FTPFileStorageHandler
from common.utils import get_log_keep_day, get_logger
from ops.celery.decorator import register_as_period_task
from ops.models import CeleryTaskExecution
+from orgs.utils import tmp_to_root_org
from terminal.backends import server_replay_storage
from terminal.models import Session, Command
from .models import UserLoginLog, OperateLog, FTPLog, ActivityLog, PasswordChangeLog
@@ -131,13 +132,14 @@ def clean_expired_session_period():
@register_as_period_task(crontab=CRONTAB_AT_AM_TWO)
def clean_audits_log_period():
print("Start clean audit session task log")
- clean_login_log_period()
- clean_operation_log_period()
- clean_ftp_log_period()
- clean_activity_log_period()
- clean_celery_tasks_period()
- clean_expired_session_period()
- clean_password_change_log_period()
+ with tmp_to_root_org():
+ clean_login_log_period()
+ clean_operation_log_period()
+ clean_ftp_log_period()
+ clean_activity_log_period()
+ clean_celery_tasks_period()
+ clean_expired_session_period()
+ clean_password_change_log_period()
@shared_task(verbose_name=_('Upload FTP file to external storage'))
diff --git a/apps/audits/utils.py b/apps/audits/utils.py
index 1b1e4b8e6..3618978a2 100644
--- a/apps/audits/utils.py
+++ b/apps/audits/utils.py
@@ -82,7 +82,9 @@ def _get_instance_field_value(
elif isinstance(f, GenericForeignKey):
continue
try:
- data.setdefault(str(f.verbose_name), value)
+ data.setdefault(
+ str(f.verbose_name), {'name': getattr(f, 'column', ''), 'value': value}
+ )
except Exception as e:
print(f.__dict__)
raise e
@@ -106,7 +108,9 @@ def model_to_dict_for_operate_log(
return
try:
field_key = getattr(f, 'verbose_name', None) or f.related_model._meta.verbose_name
- data.setdefault(str(field_key), value)
+ data.setdefault(
+ str(field_key), {'name': getattr(f, 'column', ''), 'value': value}
+ )
except:
pass
diff --git a/apps/authentication/api/__init__.py b/apps/authentication/api/__init__.py
index 4cfc6cc4a..53d59c9a6 100644
--- a/apps/authentication/api/__init__.py
+++ b/apps/authentication/api/__init__.py
@@ -11,6 +11,7 @@ from .login_confirm import *
from .mfa import *
from .password import *
from .session import *
+from .ssh_key import *
from .sso import *
from .temp_token import *
from .token import *
diff --git a/apps/authentication/api/session.py b/apps/authentication/api/session.py
index 37d4f82b5..eff7b1678 100644
--- a/apps/authentication/api/session.py
+++ b/apps/authentication/api/session.py
@@ -55,14 +55,14 @@ class UserSessionApi(generics.RetrieveDestroyAPIView):
def retrieve(self, request, *args, **kwargs):
if isinstance(request.user, AnonymousUser):
- return Response(status=status.HTTP_200_OK)
+ return Response(status=status.HTTP_403_FORBIDDEN)
UserSessionManager(request).connect()
- return Response(status=status.HTTP_200_OK)
+ return Response(status=status.HTTP_200_OK, data={'ok': True})
def destroy(self, request, *args, **kwargs):
if isinstance(request.user, AnonymousUser):
- return Response(status=status.HTTP_200_OK)
+ return Response(status=status.HTTP_403_FORBIDDEN)
UserSessionManager(request).disconnect()
- return Response(status=status.HTTP_204_NO_CONTENT)
+ return Response(status=status.HTTP_200_OK, data={'ok': True})
diff --git a/apps/authentication/api/ssh_key.py b/apps/authentication/api/ssh_key.py
new file mode 100644
index 000000000..2da19a5b8
--- /dev/null
+++ b/apps/authentication/api/ssh_key.py
@@ -0,0 +1,19 @@
+from common.api import JMSModelViewSet
+from common.permissions import IsValidUser
+from ..serializers import SSHKeySerializer
+from users.notifications import ResetPublicKeySuccessMsg
+
+
+class SSHkeyViewSet(JMSModelViewSet):
+ serializer_class = SSHKeySerializer
+ permission_classes = [IsValidUser]
+ filterset_fields = ('name', 'is_active')
+ search_fields = ('name',)
+ ordering = ('-date_last_used', '-date_created')
+
+ def get_queryset(self):
+ return self.request.user.ssh_keys.all()
+
+ def perform_update(self, serializer):
+ super().perform_update(serializer)
+ ResetPublicKeySuccessMsg(self.request.user, self.request).publish_async()
diff --git a/apps/authentication/backends/radius/__init__.py b/apps/authentication/backends/radius/__init__.py
new file mode 100644
index 000000000..a0957e5c9
--- /dev/null
+++ b/apps/authentication/backends/radius/__init__.py
@@ -0,0 +1 @@
+from .backends import *
diff --git a/apps/authentication/backends/radius.py b/apps/authentication/backends/radius/backends.py
similarity index 91%
rename from apps/authentication/backends/radius.py
rename to apps/authentication/backends/radius/backends.py
index 84f88165a..148e9bac2 100644
--- a/apps/authentication/backends/radius.py
+++ b/apps/authentication/backends/radius/backends.py
@@ -2,12 +2,12 @@
#
import traceback
+from django.conf import settings
from django.contrib.auth import get_user_model
from radiusauth.backends import RADIUSBackend, RADIUSRealmBackend
-from django.conf import settings
-
-from .base import JMSBaseAuthBackend
+from authentication.backends.base import JMSBaseAuthBackend
+from .signals import radius_create_user
User = get_user_model()
@@ -28,8 +28,8 @@ class CreateUserMixin:
email = '{}@{}'.format(username, email_suffix)
user = User(username=username, name=username, email=email)
- user.source = user.Source.radius.value
user.save()
+ radius_create_user.send(sender=user.__class__, user=user)
return user
def _perform_radius_auth(self, client, packet):
diff --git a/apps/authentication/backends/radius/signals.py b/apps/authentication/backends/radius/signals.py
new file mode 100644
index 000000000..9e62b557d
--- /dev/null
+++ b/apps/authentication/backends/radius/signals.py
@@ -0,0 +1,3 @@
+from django.dispatch import Signal
+
+radius_create_user = Signal()
diff --git a/apps/authentication/backends/saml2/views.py b/apps/authentication/backends/saml2/views.py
index bbc3b600b..5a866cc47 100644
--- a/apps/authentication/backends/saml2/views.py
+++ b/apps/authentication/backends/saml2/views.py
@@ -1,14 +1,12 @@
import copy
-
from urllib import parse
-from django.views import View
-from django.contrib import auth
-from django.urls import reverse
from django.conf import settings
-from django.views.decorators.csrf import csrf_exempt
+from django.contrib import auth
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseServerError
-
+from django.urls import reverse
+from django.views import View
+from django.views.decorators.csrf import csrf_exempt
from onelogin.saml2.auth import OneLogin_Saml2_Auth
from onelogin.saml2.errors import OneLogin_Saml2_Error
from onelogin.saml2.idp_metadata_parser import (
@@ -16,23 +14,29 @@ from onelogin.saml2.idp_metadata_parser import (
dict_deep_merge
)
-from .settings import JmsSaml2Settings
-
from common.utils import get_logger
+from .settings import JmsSaml2Settings
logger = get_logger(__file__)
class PrepareRequestMixin:
- @staticmethod
- def is_secure():
- url_result = parse.urlparse(settings.SITE_URL)
- return 'on' if url_result.scheme == 'https' else 'off'
+
+ @property
+ def parsed_url(self):
+ return parse.urlparse(settings.SITE_URL)
+
+ def is_secure(self):
+ return 'on' if self.parsed_url.scheme == 'https' else 'off'
+
+ def http_host(self):
+ return f"{self.parsed_url.hostname}:{self.parsed_url.port}" \
+ if self.parsed_url.port else self.parsed_url.hostname
def prepare_django_request(self, request):
result = {
'https': self.is_secure(),
- 'http_host': request.META['HTTP_HOST'],
+ 'http_host': self.http_host(),
'script_name': request.META['PATH_INFO'],
'get_data': request.GET.copy(),
'post_data': request.POST.copy()
@@ -275,7 +279,7 @@ class Saml2AuthCallbackView(View, PrepareRequestMixin):
logger.debug(log_prompt.format('Redirect'))
redir = post_data.get('RelayState')
if not redir or len(redir) == 0:
- redir = "/"
+ redir = "/"
next_url = saml_instance.redirect_to(redir)
return HttpResponseRedirect(next_url)
diff --git a/apps/authentication/migrations/0003_sshkey.py b/apps/authentication/migrations/0003_sshkey.py
new file mode 100644
index 000000000..22fbc8d34
--- /dev/null
+++ b/apps/authentication/migrations/0003_sshkey.py
@@ -0,0 +1,51 @@
+# Generated by Django 4.1.13 on 2024-07-29 02:25
+
+import common.db.fields
+import common.db.models
+from django.conf import settings
+from django.db import migrations, models
+import uuid
+
+
+def migrate_user_public_and_private_key(apps, schema_editor):
+ user_model = apps.get_model('users', 'User')
+ users = user_model.objects.all()
+ ssh_key_model = apps.get_model('authentication', 'SSHKey')
+ db_alias = schema_editor.connection.alias
+ for user in users:
+ if user.public_key:
+ ssh_key_model.objects.using(db_alias).create(
+ public_key=user.public_key, private_key=user.private_key, user=user
+ )
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('authentication', '0002_auto_20190729_1423'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='SSHKey',
+ fields=[
+ ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
+ ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')),
+ ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
+ ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
+ ('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
+ ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
+ ('name', models.CharField(max_length=128, verbose_name='Name')),
+ ('is_active', models.BooleanField(default=True, verbose_name='Active')),
+ ('private_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Private key')),
+ ('public_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Public key')),
+ ('date_last_used', models.DateTimeField(blank=True, null=True, verbose_name='Date last used')),
+ ('user', models.ForeignKey(db_constraint=False, on_delete=common.db.models.CASCADE_SIGNAL_SKIP,
+ related_name='ssh_keys', to=settings.AUTH_USER_MODEL, verbose_name='User')),
+ ],
+ options={
+ 'verbose_name': 'SSH key',
+ },
+ ),
+ migrations.RunPython(migrate_user_public_and_private_key)
+ ]
diff --git a/apps/authentication/models/__init__.py b/apps/authentication/models/__init__.py
index e889e03b1..c11b5718f 100644
--- a/apps/authentication/models/__init__.py
+++ b/apps/authentication/models/__init__.py
@@ -1,5 +1,7 @@
from .access_key import *
from .connection_token import *
from .private_token import *
+from .ssh_key import *
from .sso_token import *
from .temp_token import *
+from ..backends.passkey.models import *
diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py
index 07fd6483b..fcf1d43c8 100644
--- a/apps/authentication/models/connection_token.py
+++ b/apps/authentication/models/connection_token.py
@@ -200,7 +200,7 @@ class ConnectionToken(JMSOrgBaseModel):
host_account = applet.select_host_account(self.user, self.asset)
if not host_account:
- raise JMSException({'error': 'No host account available'})
+ raise JMSException({'error': 'No host account available, please check the applet, host and account'})
host, account, lock_key = bulk_get(host_account, ('host', 'account', 'lock_key'))
gateway = host.domain.select_gateway() if host.domain else None
diff --git a/apps/authentication/models/ssh_key.py b/apps/authentication/models/ssh_key.py
new file mode 100644
index 000000000..bf2168ffc
--- /dev/null
+++ b/apps/authentication/models/ssh_key.py
@@ -0,0 +1,27 @@
+import sshpubkeys
+
+from django.db import models
+from django.utils.translation import gettext_lazy as _
+
+from common.db.models import JMSBaseModel, CASCADE_SIGNAL_SKIP
+from users.models import AuthMixin
+from common.db import fields
+
+
+class SSHKey(JMSBaseModel, AuthMixin):
+ name = models.CharField(max_length=128, verbose_name=_("Name"))
+ is_active = models.BooleanField(default=True, verbose_name=_('Active'))
+ private_key = fields.EncryptTextField(
+ blank=True, null=True, verbose_name=_("Private key")
+ )
+ public_key = fields.EncryptTextField(
+ blank=True, null=True, verbose_name=_("Public key")
+ )
+ date_last_used = models.DateTimeField(null=True, blank=True, verbose_name=_('Date last used'))
+ user = models.ForeignKey(
+ 'users.User', on_delete=CASCADE_SIGNAL_SKIP, verbose_name=_('User'), db_constraint=False,
+ related_name='ssh_keys'
+ )
+
+ class Meta:
+ verbose_name = _('SSH key')
diff --git a/apps/authentication/serializers/__init__.py b/apps/authentication/serializers/__init__.py
index d6e1671cf..9614b3efb 100644
--- a/apps/authentication/serializers/__init__.py
+++ b/apps/authentication/serializers/__init__.py
@@ -2,4 +2,5 @@ from .confirm import *
from .connect_token_secret import *
from .connection_token import *
from .password_mfa import *
+from .ssh_key import *
from .token import *
diff --git a/apps/authentication/serializers/connection_token.py b/apps/authentication/serializers/connection_token.py
index 4579e73ee..5781b020d 100644
--- a/apps/authentication/serializers/connection_token.py
+++ b/apps/authentication/serializers/connection_token.py
@@ -40,6 +40,7 @@ class ConnectionTokenSerializer(CommonModelSerializer):
'from_ticket': {'read_only': True},
'value': {'read_only': True},
'is_expired': {'read_only': True, 'label': _('Is expired')},
+ 'org_name': {'label': _("Org name")},
}
def get_request_user(self):
diff --git a/apps/authentication/serializers/ssh_key.py b/apps/authentication/serializers/ssh_key.py
new file mode 100644
index 000000000..388607903
--- /dev/null
+++ b/apps/authentication/serializers/ssh_key.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+#
+from django.db.models import TextChoices
+from django.utils.translation import gettext_lazy as _
+from rest_framework import serializers
+
+from common.serializers.fields import ReadableHiddenField, LabeledChoiceField
+
+from ..models import SSHKey
+from common.utils import validate_ssh_public_key
+from users.exceptions import CreateSSHKeyExceedLimit
+
+__all__ = ['SSHKeySerializer', 'GenerateKeyType']
+
+
+class GenerateKeyType(TextChoices):
+ auto = 'auto', _('Automatically Generate Key Pair')
+ # 目前只支持sftp方式
+ load = 'load', _('Import Existing Key Pair')
+
+
+class SSHKeySerializer(serializers.ModelSerializer):
+ user = ReadableHiddenField(default=serializers.CurrentUserDefault())
+ public_key_comment = serializers.CharField(
+ source='get_public_key_comment', required=False, read_only=True, max_length=128
+ )
+ public_key_hash_md5 = serializers.CharField(
+ source='get_public_key_hash_md5', required=False, read_only=True, max_length=128
+ )
+ generate_key_type = LabeledChoiceField(
+ choices=GenerateKeyType.choices, label=_('Create Type'), default=GenerateKeyType.auto.value, required=False,
+ help_text=_(
+ 'Please download the private key after creation. Each private key can only be downloaded once'
+ )
+ )
+
+ class Meta:
+ model = SSHKey
+ fields_mini = ['name']
+ fields_small = fields_mini + [
+ 'public_key', 'is_active', 'comment'
+ ]
+ read_only_fields = [
+ 'id', 'user', 'public_key_comment', 'public_key_hash_md5',
+ 'date_last_used', 'date_created', 'date_updated', 'generate_key_type',
+ ]
+ fields = fields_small + read_only_fields
+
+ def to_representation(self, instance):
+ data = super().to_representation(instance)
+ data.pop('public_key', None)
+ return data
+
+ @staticmethod
+ def validate_public_key(value):
+ if not validate_ssh_public_key(value):
+ raise serializers.ValidationError(_('Not a valid ssh public key'))
+ return value
+
+ def create(self, validated_data):
+ if not self.context["request"].user.can_create_ssh_key():
+ raise CreateSSHKeyExceedLimit()
+ validated_data.pop('generate_key_type', None)
+ return super().create(validated_data)
diff --git a/apps/authentication/templates/authentication/login.html b/apps/authentication/templates/authentication/login.html
index fac9974ce..47bc3fb8b 100644
--- a/apps/authentication/templates/authentication/login.html
+++ b/apps/authentication/templates/authentication/login.html
@@ -69,16 +69,21 @@
}
.login-content {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
height: 500px;
width: 1000px;
- margin-right: auto;
- margin-left: auto;
- margin-top: calc((100vh - 470px) / 3);
}
+
body {
+ position: relative;
+ width: 100vw;
+ height: 100vh;
background-color: #f3f3f3;
- height: calc(100vh - (100vh - 470px) / 3);
+ {#height: calc(100vh - (100vh - 470px) / 3);#}
}
.captcha {
@@ -99,6 +104,27 @@
border-right: 1px solid #EFF0F1;
}
+ .left-form-box .form-panel {
+ position: relative;
+ top: 50%;
+ transform: translateY(-50%);
+ }
+
+ .left-form-box .form-panel {
+ position: relative;
+ top: 50%;
+ transform: translateY(-50%);
+ }
+
+ .left-form-box .form-panel .form-mobile {
+ padding: 15px 60px;
+ text-align: left
+ }
+
+ .left-form-box .form-panel .form-mobile h2 {
+ display: inline
+ }
+
.red-fonts {
color: red;
}
@@ -112,11 +138,11 @@
}
.jms-title {
- padding: 22px 10px 10px;
+ {#padding: 22px 10px 10px;#}
}
.more-login-items {
- margin-top: 10px;
+ margin-top: 15px;
}
.more-login-item {
@@ -153,6 +179,9 @@
}
.jms-title {
+ display: flex;
+ justify-content: center;
+ align-items: center;
font-size: 21px;
font-weight: 400;
color: #151515;
@@ -252,7 +281,7 @@
.mobile-logo {
display: block;
- padding: 0 30px;
+ padding: 0 45px;
text-align: left;
}
@@ -260,6 +289,15 @@
height: revert;
width: revert;
}
+
+ .left-form-box .form-panel {
+ transform: translateY(-65%);
+ }
+
+ .left-form-box .form-panel .form-mobile h2 {
+ padding: 0;
+ margin: 0;
+ }
}
@@ -279,14 +317,15 @@
If you see this page, "
@@ -4292,7 +4383,7 @@ msgstr "タスクは存在しません"
msgid "Task {} args or kwargs error"
msgstr "タスク実行パラメータエラー"
-#: ops/api/job.py:81
+#: ops/api/job.py:83
#, python-brace-format
msgid ""
"Asset ({asset}) must have at least one of the following protocols added: "
@@ -4301,22 +4392,22 @@ msgstr ""
"資産({asset})には、少なくともSSH、SFTP、WinRMのいずれか一つのプロトコルを追加"
"する必要があります"
-#: ops/api/job.py:82
+#: ops/api/job.py:84
#, python-brace-format
msgid "Asset ({asset}) authorization is missing SSH, SFTP, or WinRM protocol"
msgstr ""
"資産({asset})の認証にはSSH、SFTP、またはWinRMプロトコルが不足しています"
-#: ops/api/job.py:83
+#: ops/api/job.py:85
#, python-brace-format
msgid "Asset ({asset}) authorization lacks upload permissions"
msgstr "資産({asset})の認証にはアップロード権限が不足しています"
-#: ops/api/job.py:168
+#: ops/api/job.py:170
msgid "Duplicate file exists"
msgstr "重複したファイルが存在する"
-#: ops/api/job.py:173
+#: ops/api/job.py:175
#, python-brace-format
msgid ""
"File size exceeds maximum limit. Please select a file smaller than {limit}MB"
@@ -4324,7 +4415,7 @@ msgstr ""
"ファイルサイズが最大制限を超えています。{limit}MB より小さいファイルを選択し"
"てください。"
-#: ops/api/job.py:237
+#: ops/api/job.py:244
msgid ""
"The task is being created and cannot be interrupted. Please try again later."
msgstr "タスクを作成中で、中断できません。後でもう一度お試しください。"
@@ -4333,27 +4424,27 @@ msgstr "タスクを作成中で、中断できません。後でもう一度お
msgid "Currently playbook is being used in a job"
msgstr "現在プレイブックは1つのジョブで使用されています"
-#: ops/api/playbook.py:96
+#: ops/api/playbook.py:97
msgid "Unsupported file content"
msgstr "サポートされていないファイルの内容"
-#: ops/api/playbook.py:98 ops/api/playbook.py:144 ops/api/playbook.py:192
+#: ops/api/playbook.py:99 ops/api/playbook.py:145 ops/api/playbook.py:193
msgid "Invalid file path"
msgstr "無効なファイルパス"
-#: ops/api/playbook.py:170
+#: ops/api/playbook.py:171
msgid "This file can not be rename"
msgstr "ファイル名を変更することはできません"
-#: ops/api/playbook.py:189
+#: ops/api/playbook.py:190
msgid "File already exists"
msgstr "ファイルは既に存在します。"
-#: ops/api/playbook.py:207
+#: ops/api/playbook.py:208
msgid "File key is required"
msgstr "ファイルキーこのフィールドは必須です"
-#: ops/api/playbook.py:210
+#: ops/api/playbook.py:211
msgid "This file can not be delete"
msgstr "このファイルを削除できません"
@@ -4393,9 +4484,9 @@ msgstr "空欄"
msgid "VCS"
msgstr "VCS"
-#: ops/const.py:38 ops/models/adhoc.py:44 settings/serializers/feature.py:135
+#: ops/const.py:38 ops/models/adhoc.py:44 settings/serializers/feature.py:120
msgid "Adhoc"
-msgstr "コマンド#コマンド#"
+msgstr "コマンド"
#: ops/const.py:39 ops/models/job.py:149 ops/models/playbook.py:88
msgid "Playbook"
@@ -4457,21 +4548,25 @@ msgstr "Oracle"
msgid "Timeout"
msgstr "タイムアウト"
+#: ops/const.py:82
+msgid "Command execution disabled"
+msgstr "コマンド実行が無効"
+
#: ops/exception.py:6
msgid "no valid program entry found."
msgstr "利用可能なプログラムポータルがありません"
-#: ops/mixin.py:23 ops/mixin.py:102 settings/serializers/auth/ldap.py:74
+#: ops/mixin.py:23 ops/mixin.py:102 settings/serializers/auth/ldap.py:72
msgid "Periodic run"
msgstr "定期的なパフォーマンス"
#: ops/mixin.py:25 ops/mixin.py:88 ops/mixin.py:108
-#: settings/serializers/auth/ldap.py:81
+#: settings/serializers/auth/ldap.py:79
msgid "Interval"
msgstr "間隔"
#: ops/mixin.py:28 ops/mixin.py:86 ops/mixin.py:105
-#: settings/serializers/auth/ldap.py:78
+#: settings/serializers/auth/ldap.py:76
msgid "Crontab"
msgstr "含む"
@@ -4517,7 +4612,7 @@ msgid "Date last run"
msgstr "最終実行日"
#: ops/models/base.py:51 ops/models/job.py:238
-#: xpack/plugins/cloud/models.py:222
+#: xpack/plugins/cloud/models.py:223
msgid "Result"
msgstr "結果"
@@ -4574,7 +4669,8 @@ msgstr "ユーザーとして実行"
msgid "Run as policy"
msgstr "ユーザー ポリシー"
-#: ops/models/job.py:222 terminal/notifications.py:174
+#: ops/models/job.py:222 ops/serializers/job.py:92
+#: terminal/notifications.py:174
msgid "Job"
msgstr "ジョブ#ジョブ#"
@@ -4586,7 +4682,7 @@ msgstr "Material"
msgid "Material Type"
msgstr "Material を選択してオプションを設定します。"
-#: ops/models/job.py:545
+#: ops/models/job.py:548
msgid "Job Execution"
msgstr "ジョブ実行"
@@ -4598,30 +4694,30 @@ msgstr "创建方式"
msgid "VCS URL"
msgstr "VCS URL"
-#: ops/notifications.py:19
+#: ops/notifications.py:20
msgid "Server performance"
msgstr "サーバーのパフォーマンス"
-#: ops/notifications.py:25
+#: ops/notifications.py:26
msgid "Component health check warning"
msgstr "コンポーネントのヘルスチェック警告"
-#: ops/notifications.py:70
+#: ops/notifications.py:71
#, python-brace-format
msgid "The component is offline: {name}"
msgstr "コンポーネントがオフラインです: {name}"
-#: ops/notifications.py:75
+#: ops/notifications.py:76
#, python-brace-format
msgid "Disk used more than {max_threshold}%: => {value}"
msgstr "{max_threshold}%: => {value} を超えるディスクを使用"
-#: ops/notifications.py:80
+#: ops/notifications.py:81
#, python-brace-format
msgid "Memory used more than {max_threshold}%: => {value}"
msgstr "{max_threshold}%: => {value} を超える使用メモリ"
-#: ops/notifications.py:85
+#: ops/notifications.py:86
#, python-brace-format
msgid "CPU load more than {max_threshold}: => {value}"
msgstr "{max_threshold} を超えるCPUロード: => {value}"
@@ -4650,7 +4746,11 @@ msgstr "タスクの種類"
msgid "Is finished"
msgstr "終了しました"
-#: ops/serializers/job.py:90
+#: ops/serializers/job.py:89
+msgid "Task id"
+msgstr "タスク ID"
+
+#: ops/serializers/job.py:98
msgid "You do not have permission for the current job."
msgstr "あなたは現在のジョブの権限を持っていません。"
@@ -4747,17 +4847,13 @@ msgstr "組織を選択してから保存してください"
#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:91
#: rbac/const.py:7 rbac/models/rolebinding.py:56
-#: rbac/serializers/rolebinding.py:44 settings/serializers/auth/ldap.py:71
+#: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:52
#: terminal/templates/terminal/_msg_command_warning.html:21
#: terminal/templates/terminal/_msg_session_sharing.html:14
-#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:60
+#: tickets/models/ticket/general.py:303 tickets/serializers/ticket/ticket.py:60
msgid "Organization"
msgstr "組織"
-#: orgs/mixins/serializers.py:26 rbac/serializers/rolebinding.py:27
-msgid "Org name"
-msgstr "組織名"
-
#: orgs/models.py:14
msgid "GLOBAL"
msgstr "グローバル組織"
@@ -4771,7 +4867,7 @@ msgid "SYSTEM"
msgstr "システム組織"
#: orgs/models.py:83 rbac/models/role.py:36 settings/models.py:185
-#: terminal/models/applet/applet.py:41
+#: terminal/models/applet/applet.py:42
msgid "Builtin"
msgstr "ビルトイン"
@@ -4787,7 +4883,7 @@ msgstr "参加しているすべての組織を表示できます"
msgid "Can not delete virtual org"
msgstr "仮想組織を削除できませんでした"
-#: orgs/serializers.py:10 perms/serializers/permission.py:38
+#: orgs/serializers.py:10 perms/serializers/permission.py:37
#: rbac/serializers/role.py:27 users/serializers/group.py:54
msgid "Users amount"
msgstr "ユーザー数"
@@ -4796,7 +4892,7 @@ msgstr "ユーザー数"
msgid "User groups amount"
msgstr "ユーザーグループの数"
-#: orgs/serializers.py:14 perms/serializers/permission.py:41
+#: orgs/serializers.py:14 perms/serializers/permission.py:40
msgid "Nodes amount"
msgstr "ノード数"
@@ -4893,7 +4989,7 @@ msgid "today"
msgstr "今日"
#: perms/notifications.py:12 perms/notifications.py:44
-#: settings/serializers/feature.py:126
+#: settings/serializers/feature.py:111
msgid "day"
msgstr "日"
@@ -4913,11 +5009,11 @@ msgstr "資産権限の有効期限が近づいています"
msgid "asset permissions of organization {}"
msgstr "組織 {} の資産権限"
-#: perms/serializers/permission.py:34 users/serializers/user.py:257
+#: perms/serializers/permission.py:33 users/serializers/user.py:257
msgid "Groups"
msgstr "ユーザーグループ"
-#: perms/serializers/permission.py:39
+#: perms/serializers/permission.py:38
msgid "Groups amount"
msgstr "ユーザーグループの数"
@@ -5022,12 +5118,12 @@ msgid "Permissions"
msgstr "権限"
#: rbac/models/role.py:31 rbac/models/rolebinding.py:46
-#: rbac/serializers/role.py:12 settings/serializers/auth/oauth2.py:36
+#: rbac/serializers/role.py:12 settings/serializers/auth/oauth2.py:37
msgid "Scope"
msgstr "スコープ"
#: rbac/models/role.py:46 rbac/models/rolebinding.py:52
-#: users/models/user.py:910
+#: users/models/user/__init__.py:66
msgid "Role"
msgstr "ロール"
@@ -5062,15 +5158,10 @@ msgstr "組織の役割バインディング"
msgid "System role binding"
msgstr "システムロールバインディング"
-#: rbac/serializers/permission.py:25 users/serializers/profile.py:103
+#: rbac/serializers/permission.py:25 users/serializers/profile.py:76
msgid "Perms"
msgstr "パーマ"
-#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:34
-#: terminal/models/virtualapp/virtualapp.py:20
-msgid "Display name"
-msgstr "表示名"
-
#: rbac/serializers/rolebinding.py:60
msgid "Has bound this role"
msgstr "この役割をバインドしました"
@@ -5115,19 +5206,15 @@ msgstr "アカウントを集める"
msgid "Account change secret"
msgstr "アカウントの秘密の変更"
-#: rbac/tree.py:54
-msgid "My assets"
-msgstr "私の資産"
-
#: rbac/tree.py:55
msgid "App ops"
msgstr "アプリ操作"
-#: rbac/tree.py:57 settings/serializers/feature.py:132
+#: rbac/tree.py:57 settings/serializers/feature.py:117
msgid "Feature"
msgstr "機能"
-#: rbac/tree.py:58 settings/serializers/auth/base.py:10
+#: rbac/tree.py:58 settings/serializers/auth/base.py:11
msgid "Authentication"
msgstr "認証"
@@ -5135,8 +5222,8 @@ msgstr "認証"
msgid "Storage"
msgstr "ストレージ"
-#: rbac/tree.py:61 terminal/models/applet/applet.py:52
-#: terminal/models/applet/applet.py:317 terminal/models/applet/host.py:30
+#: rbac/tree.py:61 terminal/models/applet/applet.py:53
+#: terminal/models/applet/applet.py:328 terminal/models/applet/host.py:30
#: terminal/serializers/applet.py:15
msgid "Applet"
msgstr "リモートアプリケーション"
@@ -5158,8 +5245,8 @@ msgstr "アプリ組織"
msgid "Ticket comment"
msgstr "チケットコメント"
-#: rbac/tree.py:159 settings/serializers/feature.py:113
-#: settings/serializers/feature.py:115 tickets/models/ticket/general.py:305
+#: rbac/tree.py:159 settings/serializers/feature.py:98
+#: settings/serializers/feature.py:100 tickets/models/ticket/general.py:308
msgid "Ticket"
msgstr "チケット"
@@ -5176,7 +5263,7 @@ msgid "Chat AI is not enabled"
msgstr "チャットAIがオンになっていない"
#: settings/api/chat.py:79 settings/api/dingtalk.py:31
-#: settings/api/feishu.py:36 settings/api/slack.py:34 settings/api/sms.py:160
+#: settings/api/feishu.py:39 settings/api/slack.py:34 settings/api/sms.py:160
#: settings/api/vault.py:40 settings/api/wecom.py:37
msgid "Test success"
msgstr "テストの成功"
@@ -5284,63 +5371,63 @@ msgstr "チャットのヒント"
msgid "Notification of Synchronized LDAP User Task Results"
msgstr "アカウントバックアップルートタスクの結果の通知"
-#: settings/serializers/auth/base.py:12
+#: settings/serializers/auth/base.py:13
msgid "LDAP Auth"
msgstr "LDAP 認証"
-#: settings/serializers/auth/base.py:13
+#: settings/serializers/auth/base.py:14
msgid "CAS Auth"
msgstr "CAS 認証"
-#: settings/serializers/auth/base.py:14
+#: settings/serializers/auth/base.py:15
msgid "OPENID Auth"
msgstr "OPENID 認証"
-#: settings/serializers/auth/base.py:15
+#: settings/serializers/auth/base.py:16
msgid "SAML2 Auth"
msgstr "SAML2 認証"
-#: settings/serializers/auth/base.py:16
+#: settings/serializers/auth/base.py:17
msgid "OAuth2 Auth"
msgstr "OAuth2 認証"
-#: settings/serializers/auth/base.py:17
+#: settings/serializers/auth/base.py:18
msgid "RADIUS Auth"
msgstr "RADIUS 認証"
-#: settings/serializers/auth/base.py:18
+#: settings/serializers/auth/base.py:19
msgid "DingTalk Auth"
msgstr "くぎ 認証"
-#: settings/serializers/auth/base.py:19
+#: settings/serializers/auth/base.py:20
msgid "FeiShu Auth"
msgstr "飛本 認証"
-#: settings/serializers/auth/base.py:20
+#: settings/serializers/auth/base.py:21
msgid "Lark Auth"
msgstr "Lark 認証"
-#: settings/serializers/auth/base.py:21
+#: settings/serializers/auth/base.py:22
msgid "Slack Auth"
msgstr "Slack 認証"
-#: settings/serializers/auth/base.py:22
+#: settings/serializers/auth/base.py:23
msgid "WeCom Auth"
msgstr "企業微信 認証"
-#: settings/serializers/auth/base.py:23
+#: settings/serializers/auth/base.py:24
msgid "SSO Auth"
msgstr "SSO Token 認証"
-#: settings/serializers/auth/base.py:24
+#: settings/serializers/auth/base.py:25
msgid "Passkey Auth"
msgstr "Passkey 認証"
-#: settings/serializers/auth/base.py:26
+#: settings/serializers/auth/base.py:27
msgid "Email suffix"
msgstr "メールのサフィックス"
-#: settings/serializers/auth/base.py:28
+#: settings/serializers/auth/base.py:29
msgid ""
"After third-party user authentication is successful, if the third-party "
"authentication service platform does not return the user's email "
@@ -5351,19 +5438,19 @@ msgstr ""
"ザーのメール情報を返さなかった場合、システムは自動的にこのメールのサフィック"
"スでユーザーを作成します"
-#: settings/serializers/auth/base.py:35
-msgid "Forgot Password"
-msgstr "パスワードを忘れた"
-
#: settings/serializers/auth/base.py:36
+msgid "Forgot Password URL"
+msgstr "パスワードを忘れた場合のリンク"
+
+#: settings/serializers/auth/base.py:37
msgid "The URL for Forgotten Password on the user login page"
msgstr "ユーザーログイン画面のパスワードを忘れた URL"
-#: settings/serializers/auth/base.py:39
+#: settings/serializers/auth/base.py:40
msgid "Login redirection"
msgstr "ログインリダイレクトの有効化msg"
-#: settings/serializers/auth/base.py:41
+#: settings/serializers/auth/base.py:42
msgid ""
"Should an flash page be displayed before the user is redirected to third-"
"party authentication when the administrator enables third-party redirect "
@@ -5372,43 +5459,53 @@ msgstr ""
"管理者が第三者へのリダイレクトの認証を有効にした場合、ユーザーが第三者の認証"
"にリダイレクトされる前に Flash ページを表示するかどうか"
-#: settings/serializers/auth/cas.py:10 settings/serializers/auth/cas.py:12
+#: settings/serializers/auth/base.py:54
+msgid ""
+"When you create a user, you associate the user to the organization of your "
+"choice. Users always belong to the Default organization."
+msgstr ""
+"ユーザーを作成するときは、そのユーザーを選択した組織に関連付けます。ユーザー"
+"は常にデフォルト組織に属します。"
+
+#: settings/serializers/auth/cas.py:12 settings/serializers/auth/cas.py:14
msgid "CAS"
msgstr "CAS"
-#: settings/serializers/auth/cas.py:13 settings/serializers/auth/ldap.py:42
-#: settings/serializers/auth/oidc.py:60
+#: settings/serializers/auth/cas.py:15 settings/serializers/auth/ldap.py:43
+#: settings/serializers/auth/oidc.py:61
msgid "Server"
msgstr "LDAPサーバー"
-#: settings/serializers/auth/cas.py:16
+#: settings/serializers/auth/cas.py:18
msgid "Proxy Server"
msgstr "コールバックアドレス"
-#: settings/serializers/auth/cas.py:19 settings/serializers/auth/oauth2.py:55
-#: settings/serializers/auth/saml2.py:40
+#: settings/serializers/auth/cas.py:21 settings/serializers/auth/oauth2.py:56
+#: settings/serializers/auth/saml2.py:42
msgid "Logout completely"
msgstr "同期ログアウト"
-#: settings/serializers/auth/cas.py:20
+#: settings/serializers/auth/cas.py:22
msgid "When the user signs out, they also be logged out from the CAS server"
msgstr "ユーザーがログアウトすると、CAS サーバからもログアウトします"
-#: settings/serializers/auth/cas.py:26
+#: settings/serializers/auth/cas.py:28
msgid "Username attr"
msgstr "ユーザー名のプロパティ"
-#: settings/serializers/auth/cas.py:29
+#: settings/serializers/auth/cas.py:31
msgid "Enable attributes map"
msgstr "属性マップの有効化"
-#: settings/serializers/auth/cas.py:32 settings/serializers/auth/ldap.py:64
-#: settings/serializers/auth/oauth2.py:59 settings/serializers/auth/oidc.py:38
-#: settings/serializers/auth/saml2.py:33
+#: settings/serializers/auth/cas.py:34 settings/serializers/auth/dingtalk.py:18
+#: settings/serializers/auth/feishu.py:18 settings/serializers/auth/lark.py:17
+#: settings/serializers/auth/ldap.py:65 settings/serializers/auth/oauth2.py:60
+#: settings/serializers/auth/oidc.py:39 settings/serializers/auth/saml2.py:35
+#: settings/serializers/auth/slack.py:18 settings/serializers/auth/wecom.py:18
msgid "User attribute"
msgstr "マッピングのプロパティ"
-#: settings/serializers/auth/cas.py:34
+#: settings/serializers/auth/cas.py:36
msgid ""
"User attribute mapping, where the `key` is the CAS service user attribute "
"name and the `value` is the JumpServer user attribute name"
@@ -5416,11 +5513,11 @@ msgstr ""
"ユーザー属性のマッピング、ここで `key` は CAS サービスのユーザー属性名で、"
"`value` は JumpServer のユーザー属性名です"
-#: settings/serializers/auth/cas.py:39
+#: settings/serializers/auth/cas.py:41
msgid "Create user"
msgstr "そうでない場合はユーザーを作成"
-#: settings/serializers/auth/cas.py:41
+#: settings/serializers/auth/cas.py:43
msgid ""
"After successful user authentication, if the user does not exist, "
"automatically create the user"
@@ -5428,55 +5525,79 @@ msgstr ""
"ユーザー認証が成功した後、ユーザーが存在しない場合、自動的にユーザーが作成さ"
"れます"
-#: settings/serializers/auth/dingtalk.py:15
+#: settings/serializers/auth/dingtalk.py:16
msgid "Dingtalk"
msgstr "ピン認証の有効化"
-#: settings/serializers/auth/lark.py:12 users/models/user.py:801
-msgid "Lark"
-msgstr "Lark認証を有効にする"
+#: settings/serializers/auth/dingtalk.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the DingTalk service user attribute name"
+msgstr ""
+"ユーザー属性のマッピング、ここで `key` は JumpServer のユーザー属性名で、"
+"`value` は ディントーク サービスのユーザー属性名です"
-#: settings/serializers/auth/ldap.py:39 settings/serializers/auth/ldap.py:104
+#: settings/serializers/auth/feishu.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the FeiShu service user attribute name"
+msgstr ""
+"ユーザー属性のマッピング、ここで `key` は JumpServer のユーザー属性名で、"
+"`value` は フェイシュ サービスのユーザー属性名です"
+
+#: settings/serializers/auth/lark.py:13 users/models/user/_source.py:21
+msgid "Lark"
+msgstr ""
+
+#: settings/serializers/auth/lark.py:19
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the Lark service user attribute name"
+msgstr ""
+"ユーザー属性のマッピング、ここで `key` は JumpServer のユーザー属性名で、"
+"`value` は Lark サービスのユーザー属性名です"
+
+#: settings/serializers/auth/ldap.py:40 settings/serializers/auth/ldap.py:102
msgid "LDAP"
msgstr "LDAP"
-#: settings/serializers/auth/ldap.py:43
+#: settings/serializers/auth/ldap.py:44
msgid "LDAP server URI"
msgstr "FIDOサーバーID"
-#: settings/serializers/auth/ldap.py:46
+#: settings/serializers/auth/ldap.py:47
msgid "Bind DN"
msgstr "DN のバインド"
-#: settings/serializers/auth/ldap.py:47
+#: settings/serializers/auth/ldap.py:48
msgid "Binding Distinguished Name"
-msgstr "専有名のバインド"
+msgstr "バインドディレクトリ管理者"
-#: settings/serializers/auth/ldap.py:51
+#: settings/serializers/auth/ldap.py:52
msgid "Binding password"
msgstr "古いパスワード"
-#: settings/serializers/auth/ldap.py:54
+#: settings/serializers/auth/ldap.py:55
msgid "Search OU"
msgstr "システムアーキテクチャ"
-#: settings/serializers/auth/ldap.py:56
+#: settings/serializers/auth/ldap.py:57
msgid ""
"User Search Base, if there are multiple OUs, you can separate them with the "
"`|` symbol"
msgstr ""
"ユーザー検索ライブラリ、複数のOUがある場合は`|`の記号で分けることができます"
-#: settings/serializers/auth/ldap.py:60
+#: settings/serializers/auth/ldap.py:61
msgid "Search filter"
msgstr "ユーザー検索フィルター"
-#: settings/serializers/auth/ldap.py:61
+#: settings/serializers/auth/ldap.py:62
#, python-format
msgid "Selection could include (cn|uid|sAMAccountName=%(user)s)"
msgstr "選択は (cnまたはuidまたはsAMAccountName)=%(user)s)"
-#: settings/serializers/auth/ldap.py:66
+#: settings/serializers/auth/ldap.py:67
msgid ""
"User attribute mapping, where the `key` is the JumpServer user attribute "
"name and the `value` is the LDAP service user attribute name"
@@ -5484,15 +5605,15 @@ msgstr ""
"ユーザー属性のマッピング、ここで `key` は JumpServer のユーザー属性名で、"
"`value` は LDAP サービスのユーザー属性名です"
-#: settings/serializers/auth/ldap.py:85
+#: settings/serializers/auth/ldap.py:83
msgid "Connect timeout (s)"
msgstr "接続タイムアウト (秒)"
-#: settings/serializers/auth/ldap.py:90
+#: settings/serializers/auth/ldap.py:88
msgid "User DN cache timeout (s)"
msgstr "User DN キャッシュの有効期限 (秒)"
-#: settings/serializers/auth/ldap.py:92
+#: settings/serializers/auth/ldap.py:90
msgid ""
"Caching the User DN obtained during user login authentication can "
"effectivelyimprove the speed of user authentication., 0 means no cache
If "
@@ -5503,59 +5624,59 @@ msgstr ""
"認証の速度を効果的に向上させることができます
ユーザー OU 構造が調整された"
"場合、送信をクリックしてユーザー DN キャッシュをクリアします"
-#: settings/serializers/auth/ldap.py:98
+#: settings/serializers/auth/ldap.py:96
msgid "Search paged size (piece)"
msgstr "ページサイズを検索 (じょう)"
-#: settings/serializers/auth/oauth2.py:18
-#: settings/serializers/auth/oauth2.py:21
+#: settings/serializers/auth/oauth2.py:19
+#: settings/serializers/auth/oauth2.py:22
msgid "OAuth2"
msgstr "OAuth2"
-#: settings/serializers/auth/oauth2.py:24
+#: settings/serializers/auth/oauth2.py:25
msgid "Logo"
msgstr "アイコン"
-#: settings/serializers/auth/oauth2.py:27
+#: settings/serializers/auth/oauth2.py:28
msgid "Service provider"
msgstr "サービスプロバイダー"
-#: settings/serializers/auth/oauth2.py:30
+#: settings/serializers/auth/oauth2.py:31
#: xpack/plugins/cloud/serializers/account_attrs.py:35
msgid "Client ID"
msgstr "クライアントID"
-#: settings/serializers/auth/oauth2.py:33 settings/serializers/auth/oidc.py:23
+#: settings/serializers/auth/oauth2.py:34 settings/serializers/auth/oidc.py:24
#: xpack/plugins/cloud/serializers/account_attrs.py:38
msgid "Client Secret"
msgstr "クライアント秘密"
-#: settings/serializers/auth/oauth2.py:39 settings/serializers/auth/oidc.py:76
+#: settings/serializers/auth/oauth2.py:40 settings/serializers/auth/oidc.py:77
msgid "Authorization endpoint"
msgstr "認証エンドポイントアドレス"
-#: settings/serializers/auth/oauth2.py:42 settings/serializers/auth/oidc.py:79
+#: settings/serializers/auth/oauth2.py:43 settings/serializers/auth/oidc.py:80
msgid "Token endpoint"
msgstr "プロバイダートークンエンドポイント"
-#: settings/serializers/auth/oauth2.py:45 settings/serializers/auth/oidc.py:31
+#: settings/serializers/auth/oauth2.py:46 settings/serializers/auth/oidc.py:32
#: settings/serializers/auth/sms.py:111
msgid "Request method"
msgstr "クライアント認証方式"
-#: settings/serializers/auth/oauth2.py:49 settings/serializers/auth/oidc.py:85
+#: settings/serializers/auth/oauth2.py:50 settings/serializers/auth/oidc.py:86
msgid "Userinfo endpoint"
msgstr "プロバイダーuserinfoエンドポイント"
-#: settings/serializers/auth/oauth2.py:52 settings/serializers/auth/oidc.py:88
+#: settings/serializers/auth/oauth2.py:53 settings/serializers/auth/oidc.py:89
msgid "End session endpoint"
msgstr "プロバイダーのセッション終了エンドポイント"
-#: settings/serializers/auth/oauth2.py:56
+#: settings/serializers/auth/oauth2.py:57
msgid "When the user signs out, they also be logged out from the OAuth2 server"
msgstr "ユーザーがログアウトすると、OAuth2 サーバからもログアウトします"
-#: settings/serializers/auth/oauth2.py:61
+#: settings/serializers/auth/oauth2.py:62
msgid ""
"User attribute mapping, where the `key` is the JumpServer user attribute "
"name and the `value` is the OAuth2 service user attribute name"
@@ -5563,36 +5684,36 @@ msgstr ""
"ユーザー属性のマッピング、ここで `key` は JumpServer のユーザー属性名で、"
"`value` は OAuth2 サービスのユーザー属性名です"
-#: settings/serializers/auth/oauth2.py:66 settings/serializers/auth/oidc.py:112
-#: settings/serializers/auth/saml2.py:43
+#: settings/serializers/auth/oauth2.py:67 settings/serializers/auth/oidc.py:113
+#: settings/serializers/auth/saml2.py:45
msgid "Always update user"
msgstr "常にユーザーを更新"
-#: settings/serializers/auth/oidc.py:12 settings/serializers/auth/oidc.py:70
+#: settings/serializers/auth/oidc.py:13 settings/serializers/auth/oidc.py:71
msgid "OIDC"
-msgstr "OIDC"
+msgstr ""
-#: settings/serializers/auth/oidc.py:16
+#: settings/serializers/auth/oidc.py:17
msgid "Base site URL"
msgstr "ベースサイトのアドレス"
-#: settings/serializers/auth/oidc.py:17
+#: settings/serializers/auth/oidc.py:18
msgid "The current site's URL is used to construct the callback address"
msgstr "現在のサイトのURLはコールバックアドレスを構築するために使用されます"
-#: settings/serializers/auth/oidc.py:20
+#: settings/serializers/auth/oidc.py:21
msgid "Client Id"
msgstr "クライアントID"
-#: settings/serializers/auth/oidc.py:33
+#: settings/serializers/auth/oidc.py:34
msgid "Share session"
msgstr "セッションの共有"
-#: settings/serializers/auth/oidc.py:35
+#: settings/serializers/auth/oidc.py:36
msgid "Ignore SSL verification"
msgstr "Ssl検証を無視する"
-#: settings/serializers/auth/oidc.py:40
+#: settings/serializers/auth/oidc.py:41
msgid ""
"User attribute mapping, where the `key` is the JumpServer user attribute "
"name and the `value` is the OIDC service user attribute name"
@@ -5600,19 +5721,19 @@ msgstr ""
"ユーザー属性のマッピング、ここで `key` は JumpServer のユーザー属性名で、"
"`value` は OIDC サービスのユーザー属性名です"
-#: settings/serializers/auth/oidc.py:44
+#: settings/serializers/auth/oidc.py:45
msgid "Enable PKCE"
msgstr "有効 PKCE"
-#: settings/serializers/auth/oidc.py:46
+#: settings/serializers/auth/oidc.py:47
msgid "Code challenge method"
msgstr "検証コード方式"
-#: settings/serializers/auth/oidc.py:54
+#: settings/serializers/auth/oidc.py:55
msgid "Use Keycloak"
msgstr "Keycloakを使用する"
-#: settings/serializers/auth/oidc.py:56
+#: settings/serializers/auth/oidc.py:57
msgid ""
"Use Keycloak as the OpenID Connect server, or use standard OpenID Connect "
"Protocol"
@@ -5620,47 +5741,47 @@ msgstr ""
"Keycloak を OpenID Connect サーバとして使用するか、標準的な OpenID Connect プ"
"ロトコルを使用する"
-#: settings/serializers/auth/oidc.py:63
+#: settings/serializers/auth/oidc.py:64
msgid "Realm name"
msgstr "レルム名"
-#: settings/serializers/auth/oidc.py:70
+#: settings/serializers/auth/oidc.py:71
msgid "OpenID Connect"
-msgstr "接続"
+msgstr "OpenID 接続する"
-#: settings/serializers/auth/oidc.py:73
+#: settings/serializers/auth/oidc.py:74
msgid "Provider endpoint"
msgstr "プロバイダーエンドポイント"
-#: settings/serializers/auth/oidc.py:82
+#: settings/serializers/auth/oidc.py:83
msgid "JWKS endpoint"
msgstr "プロバイダーjwksエンドポイント"
-#: settings/serializers/auth/oidc.py:91
+#: settings/serializers/auth/oidc.py:92
msgid "Signature algorithm"
msgstr "プロビダーサインalg"
-#: settings/serializers/auth/oidc.py:94
+#: settings/serializers/auth/oidc.py:95
msgid "Signing key"
msgstr "プロバイダ署名キー"
-#: settings/serializers/auth/oidc.py:97
+#: settings/serializers/auth/oidc.py:98
msgid "Scopes"
msgstr "スコープ"
-#: settings/serializers/auth/oidc.py:100
+#: settings/serializers/auth/oidc.py:101
msgid "ID Token max age (s)"
msgstr "IDトークンの最大年齢 (秒)"
-#: settings/serializers/auth/oidc.py:103
+#: settings/serializers/auth/oidc.py:104
msgid "ID Token include claims"
msgstr "IDトークンにはクレームが含まれます"
-#: settings/serializers/auth/oidc.py:106
+#: settings/serializers/auth/oidc.py:107
msgid "Use state"
msgstr "使用状態"
-#: settings/serializers/auth/oidc.py:109
+#: settings/serializers/auth/oidc.py:110
msgid "Use nonce"
msgstr "Nonceを使用"
@@ -5685,46 +5806,46 @@ msgstr ""
msgid "FIDO Server name"
msgstr "FIDOサーバー名"
-#: settings/serializers/auth/radius.py:13
-#: settings/serializers/auth/radius.py:15
+#: settings/serializers/auth/radius.py:14
+#: settings/serializers/auth/radius.py:16
msgid "Radius"
msgstr "Radius"
-#: settings/serializers/auth/radius.py:22
+#: settings/serializers/auth/radius.py:23
msgid "OTP in RADIUS"
msgstr "Radius のOTP"
-#: settings/serializers/auth/radius.py:23
+#: settings/serializers/auth/radius.py:24
msgid "* Using OTP in RADIUS means users can employ RADIUS as a method for MFA"
msgstr ""
"* RADIUSでOTPを使用するということは、ユーザーはRADIUSをMFAの方法として使用す"
"ることができる"
-#: settings/serializers/auth/saml2.py:10 settings/serializers/auth/saml2.py:13
+#: settings/serializers/auth/saml2.py:12 settings/serializers/auth/saml2.py:15
msgid "SAML2"
msgstr "SAML2"
-#: settings/serializers/auth/saml2.py:16
+#: settings/serializers/auth/saml2.py:18
msgid "IDP Metadata URL"
msgstr "IDP Metadataアドレス"
-#: settings/serializers/auth/saml2.py:19
+#: settings/serializers/auth/saml2.py:21
msgid "IDP Metadata XML"
msgstr "IDP Metadata XML"
-#: settings/serializers/auth/saml2.py:22
+#: settings/serializers/auth/saml2.py:24
msgid "SP advanced settings"
msgstr "詳細設定"
-#: settings/serializers/auth/saml2.py:26
+#: settings/serializers/auth/saml2.py:28
msgid "SP private key"
msgstr "SP プライベートキー"
-#: settings/serializers/auth/saml2.py:30
+#: settings/serializers/auth/saml2.py:32
msgid "SP cert"
msgstr "SP 証明書"
-#: settings/serializers/auth/saml2.py:35
+#: settings/serializers/auth/saml2.py:37
msgid ""
"User attribute mapping, where the `key` is the SAML2 service user attribute "
"name and the `value` is the JumpServer user attribute name"
@@ -5732,15 +5853,23 @@ msgstr ""
"ユーザー属性マッピング(`key`はSAML2サービスのユーザー属性名、`value`は"
"JumpServerのユーザー属性名)"
-#: settings/serializers/auth/saml2.py:41
+#: settings/serializers/auth/saml2.py:43
msgid "When the user signs out, they also be logged out from the SAML2 server"
msgstr "ユーザーがログアウトすると、SAML2サーバーからもログアウトされます"
+#: settings/serializers/auth/slack.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the Slack service user attribute name"
+msgstr ""
+"ユーザー属性のマッピング、ここで `key` は JumpServer のユーザー属性名で、"
+"`value` は Slack サービスのユーザー属性名です"
+
#: settings/serializers/auth/sms.py:18
msgid "Enable Short Message Service (SMS)"
msgstr "短信サービス(SMS)を有効にする"
-#: settings/serializers/auth/sms.py:21 xpack/plugins/cloud/models.py:35
+#: settings/serializers/auth/sms.py:21 xpack/plugins/cloud/models.py:36
msgid "Provider"
msgstr "プロバイダー"
@@ -5754,11 +5883,11 @@ msgstr "認証コード長"
#: settings/serializers/auth/sms.py:26
msgid "Length of the sent verification code"
-msgstr "確認コードを送信"
+msgstr "送信された認証コードの長さ"
#: settings/serializers/auth/sms.py:31 settings/serializers/auth/sms.py:54
#: settings/serializers/auth/sms.py:62 settings/serializers/auth/sms.py:71
-#: settings/serializers/auth/sms.py:82 settings/serializers/msg.py:80
+#: settings/serializers/auth/sms.py:82 settings/serializers/msg.py:83
msgid "Signature"
msgstr "署名"
@@ -5767,7 +5896,7 @@ msgstr "署名"
msgid "Template code"
msgstr "テンプレートコード"
-#: settings/serializers/auth/sms.py:40 users/models/user.py:920
+#: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:76
#: users/serializers/user.py:155
msgid "Phone"
msgstr "電話"
@@ -5838,6 +5967,14 @@ msgstr "Token有効期間"
msgid "Unit: second"
msgstr "単位: 秒"
+#: settings/serializers/auth/wecom.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the WeCom service user attribute name"
+msgstr ""
+"ユーザー属性のマッピング、ここで `key` は JumpServer のユーザー属性名で、"
+"`value` は エンタープライズ WeChat サービスのユーザー属性名です"
+
#: settings/serializers/basic.py:11
msgid "Site URL"
msgstr "サイトURL"
@@ -5939,7 +6076,7 @@ msgstr ""
"この期間を超えるセッション、録音、およびコマンド レコードは削除されます (デー"
"タベースのバックアップに影響し、OSS などには影響しません)"
-#: settings/serializers/feature.py:18 settings/serializers/msg.py:65
+#: settings/serializers/feature.py:18 settings/serializers/msg.py:68
msgid "Subject"
msgstr "件名"
@@ -5975,76 +6112,76 @@ msgstr ""
"所定の数を超える履歴アカウントを確認して削除します。 値が 999 以上の場合、履"
"歴アカウントの削除は実行されません。"
-#: settings/serializers/feature.py:73 settings/serializers/feature.py:77
+#: settings/serializers/feature.py:73 settings/serializers/feature.py:79
msgid "Chat AI"
msgstr "チャットAI"
-#: settings/serializers/feature.py:80
-msgid "Base URL"
-msgstr "ベースサイトのアドレス"
+#: settings/serializers/feature.py:82
+msgid "GPT Base URL"
+msgstr "GPTアドレス"
-#: settings/serializers/feature.py:81
+#: settings/serializers/feature.py:83
msgid "The base URL of the GPT service. For example: https://api.openai.com/v1"
msgstr "GPTサービスの基本のURL。例えば:https://api.openai.com/v1"
-#: settings/serializers/feature.py:84 templates/_header_bar.html:96
+#: settings/serializers/feature.py:86 templates/_header_bar.html:96
msgid "API Key"
msgstr "API Key"
-#: settings/serializers/feature.py:88
+#: settings/serializers/feature.py:90
msgid ""
"The proxy server address of the GPT service. For example: http://ip:port"
msgstr "GPTサービスのプロキシサーバーのアドレス。例えば:http://ip:port"
-#: settings/serializers/feature.py:91
+#: settings/serializers/feature.py:93
msgid "GPT Model"
msgstr "GPTモデル"
-#: settings/serializers/feature.py:117
+#: settings/serializers/feature.py:102
msgid "Approval without login"
msgstr "ログイン承認なし"
-#: settings/serializers/feature.py:118
+#: settings/serializers/feature.py:103
msgid "Allow direct approval ticket without login"
msgstr "ログインせずに直接承認チケットを許可します"
-#: settings/serializers/feature.py:122
+#: settings/serializers/feature.py:107
msgid "Period"
msgstr "期間"
-#: settings/serializers/feature.py:123
+#: settings/serializers/feature.py:108
msgid ""
"The default authorization time period when applying for assets via a ticket"
msgstr "ワークオーダーの資産申請に対するデフォルトの承認時間帯"
-#: settings/serializers/feature.py:126
+#: settings/serializers/feature.py:111
msgid "hour"
msgstr "時"
-#: settings/serializers/feature.py:127
+#: settings/serializers/feature.py:112
msgid "Unit"
msgstr "単位"
-#: settings/serializers/feature.py:127
+#: settings/serializers/feature.py:112
msgid "The unit of period"
msgstr "ユーザーの実行"
-#: settings/serializers/feature.py:136
+#: settings/serializers/feature.py:121
msgid ""
"Allow users to execute batch commands in the Workbench - Job Center - Adhoc"
msgstr ""
"ユーザーがワークベンチ - ジョブセンター - Adhocでバッチコマンドを実行すること"
"を許可します"
-#: settings/serializers/feature.py:140
+#: settings/serializers/feature.py:125
msgid "Command blacklist"
msgstr "コマンドフィルタリング"
-#: settings/serializers/feature.py:141
+#: settings/serializers/feature.py:126
msgid "Command blacklist in Adhoc"
msgstr "コマンドフィルタリング"
-#: settings/serializers/feature.py:146
+#: settings/serializers/feature.py:131
#: terminal/models/virtualapp/provider.py:17
#: terminal/models/virtualapp/virtualapp.py:36
#: terminal/models/virtualapp/virtualapp.py:97
@@ -6052,11 +6189,11 @@ msgstr "コマンドフィルタリング"
msgid "Virtual app"
msgstr "仮想アプリケーション"
-#: settings/serializers/feature.py:149
+#: settings/serializers/feature.py:134
msgid "Virtual App"
msgstr "仮想アプリケーション"
-#: settings/serializers/feature.py:151
+#: settings/serializers/feature.py:136
msgid ""
"Virtual applications, you can use the Linux operating system as an "
"application server in remote applications."
@@ -6072,31 +6209,31 @@ msgstr "SMTPホスト"
msgid "EXCHANGE"
msgstr ""
-#: settings/serializers/msg.py:33
+#: settings/serializers/msg.py:34
msgid "The user to be used for email server authentication"
-msgstr "これは、SSO認証中にメールが返されない場合にデフォルトで使用されます。"
+msgstr ""
+"メールサーバーにログインするためのユーザー名。通常、これはあなたのメールアド"
+"レスです"
-#: settings/serializers/msg.py:37
+#: settings/serializers/msg.py:38
msgid ""
"Password to use for the email server. It is used in conjunction with `User` "
"when authenticating to the email server"
-msgstr ""
-"メールサーバーに対するパスワード。メールサーバーに対する認証時に、これがユー"
-"ザーとともに使用されます"
+msgstr "メールサーバーにログインするためのパスワード"
-#: settings/serializers/msg.py:40
+#: settings/serializers/msg.py:41
msgid "Sender"
msgstr "送信者"
-#: settings/serializers/msg.py:41
+#: settings/serializers/msg.py:42
msgid "Sender email address (default to using the `User`)"
msgstr "送信者のメールアドレス(デフォルトでは“ユーザー”が使用されます)"
-#: settings/serializers/msg.py:45
+#: settings/serializers/msg.py:46
msgid "The recipient is used for testing the email server's connectivity"
msgstr "受信者はメールサーバーの接続性をテストするために使用されます"
-#: settings/serializers/msg.py:49
+#: settings/serializers/msg.py:51
msgid ""
"Whether to use an implicit TLS (secure) connection when talking to the SMTP "
"server. In most email documentation this type of TLS connection is referred "
@@ -6106,11 +6243,11 @@ msgstr ""
"メール文書では、このタイプのTLS接続はSSLと呼ばれます。通常、ポート465を使用し"
"ます"
-#: settings/serializers/msg.py:52
+#: settings/serializers/msg.py:54
msgid "Use TLS"
msgstr "TLSの使用"
-#: settings/serializers/msg.py:53
+#: settings/serializers/msg.py:56
msgid ""
"Whether to use a TLS (secure) connection when talking to the SMTP server. "
"This is used for explicit TLS connections, generally on port 587"
@@ -6118,11 +6255,11 @@ msgstr ""
"SMTPサーバーとの通信時に、TLS(安全)接続を使用するかどうか。これは明示的な"
"TLS接続を使用します、通常ポート587を使用します"
-#: settings/serializers/msg.py:61
+#: settings/serializers/msg.py:64
msgid "Subject prefix"
msgstr "件名プレフィックス"
-#: settings/serializers/msg.py:66
+#: settings/serializers/msg.py:69
msgid ""
"Tips: When creating a user, send the subject of the email (eg:Create account "
"successfully)"
@@ -6130,16 +6267,16 @@ msgstr ""
"ヒント: ユーザーを作成するときに、メールの件名を送信します (例: アカウントを"
"正常に作成)"
-#: settings/serializers/msg.py:70
+#: settings/serializers/msg.py:73
msgid "Honorific"
msgstr "ユーザー敬語の作成"
-#: settings/serializers/msg.py:71
+#: settings/serializers/msg.py:74
msgid "Tips: When creating a user, send the honorific of the email (eg:Hello)"
msgstr ""
"ヒント: ユーザーを作成するときは、メールの敬語を送信します (例: こんにちは)"
-#: settings/serializers/msg.py:77
+#: settings/serializers/msg.py:80
#, python-brace-format
msgid ""
"Tips: When creating a user, send the content of the email, support "
@@ -6148,7 +6285,7 @@ msgstr ""
"ヒント:ユーザーの作成時にパスワード設定メールの内容を送信し、{username}{name}"
"{email}ラベルをサポートします。"
-#: settings/serializers/msg.py:81
+#: settings/serializers/msg.py:84
msgid "Tips: Email signature (eg:jumpserver)"
msgstr "ヒント: メール署名 (例: jumpserver)"
@@ -6468,12 +6605,6 @@ msgstr ""
"* パスワード認証を通じてユーザがKoKoコンポーネントにログインできるように許可"
"する"
-#: settings/serializers/terminal.py:34 users/forms/profile.py:172
-#: users/models/user.py:933
-#: xpack/plugins/cloud/serializers/account_attrs.py:210
-msgid "Public key"
-msgstr "公開キー"
-
#: settings/serializers/terminal.py:36
msgid ""
"* Allow users to log in to the KoKo component via Public key "
@@ -6669,13 +6800,13 @@ msgstr "認証に失敗しました (不明): {}"
msgid "Authentication success: {}"
msgstr "認証成功: {}"
-#: settings/ws.py:195
-msgid "Get ldap users is None"
-msgstr "Ldapユーザーを取得するにはNone"
+#: settings/ws.py:198
+msgid "No LDAP user was found"
+msgstr "LDAPユーザーが取得されませんでした"
-#: settings/ws.py:205
-msgid "Imported {} users successfully (Organization: {})"
-msgstr "{} 人のユーザーを正常にインポートしました (組織: {})"
+#: settings/ws.py:204
+msgid "Total {}, success {}, failure {}"
+msgstr "合計 {},成功 {},失敗 {}"
#: templates/_csv_import_export.html:8
msgid "Export"
@@ -6835,12 +6966,12 @@ msgstr "確認コードが送信されました"
msgid "Home page"
msgstr "ホームページ"
-#: templates/resource_download.html:18 templates/resource_download.html:33
+#: templates/resource_download.html:20 templates/resource_download.html:35
#: users/const.py:65
msgid "Client"
msgstr "クライアント"
-#: templates/resource_download.html:20
+#: templates/resource_download.html:22
msgid ""
"JumpServer Client, currently used to launch the client, now only support "
"launch RDP SSH client, The Telnet client will next"
@@ -6849,15 +6980,15 @@ msgstr ""
"るために使用されており、現在はRDP SSHクライアントのみをサポートしています。"
"「Telnetは将来的にサポートする"
-#: templates/resource_download.html:33
+#: templates/resource_download.html:35
msgid "Microsoft"
msgstr "マイクロソフト"
-#: templates/resource_download.html:33
+#: templates/resource_download.html:35
msgid "Official"
msgstr "公式"
-#: templates/resource_download.html:35
+#: templates/resource_download.html:37
msgid ""
"macOS needs to download the client to connect RDP asset, which comes with "
"Windows"
@@ -6865,11 +6996,11 @@ msgstr ""
"MacOSは、Windowsに付属のRDPアセットを接続するためにクライアントをダウンロード"
"する必要があります"
-#: templates/resource_download.html:44
+#: templates/resource_download.html:45
msgid "Windows Remote application publisher tools"
msgstr "Windowsリモートアプリケーション発行者ツール"
-#: templates/resource_download.html:45
+#: templates/resource_download.html:46
msgid ""
"OpenSSH is a program used to connect remote applications in the Windows "
"Remote Application Publisher"
@@ -7022,7 +7153,7 @@ msgid "High"
msgstr "高い"
#: terminal/const.py:47 terminal/const.py:84
-#: users/templates/users/reset_password.html:53
+#: users/templates/users/reset_password.html:54
msgid "Normal"
msgstr "正常"
@@ -7082,55 +7213,60 @@ msgstr "一括作成非サポート"
msgid "Storage is invalid"
msgstr "ストレージが無効です"
-#: terminal/models/applet/applet.py:30 xpack/plugins/license/models.py:88
+#: terminal/models/applet/applet.py:31 xpack/plugins/license/models.py:88
msgid "Community edition"
msgstr "コミュニティ版"
-#: terminal/models/applet/applet.py:31
+#: terminal/models/applet/applet.py:32
msgid "Enterprise"
msgstr "エンタープライズ版"
-#: terminal/models/applet/applet.py:36
+#: terminal/models/applet/applet.py:35
+#: terminal/models/virtualapp/virtualapp.py:20
+msgid "Display name"
+msgstr "表示名"
+
+#: terminal/models/applet/applet.py:37
#: terminal/models/virtualapp/virtualapp.py:22
msgid "Author"
msgstr "著者"
-#: terminal/models/applet/applet.py:38 terminal/serializers/applet.py:31
+#: terminal/models/applet/applet.py:39 terminal/serializers/applet.py:31
msgid "Edition"
msgstr "バージョン"
-#: terminal/models/applet/applet.py:43
+#: terminal/models/applet/applet.py:44
msgid "Can concurrent"
msgstr "同時実行可能"
-#: terminal/models/applet/applet.py:48 terminal/serializers/applet_host.py:167
+#: terminal/models/applet/applet.py:49 terminal/serializers/applet_host.py:167
#: terminal/serializers/storage.py:193
msgid "Hosts"
msgstr "ホスト"
-#: terminal/models/applet/applet.py:93
+#: terminal/models/applet/applet.py:94
#: terminal/models/virtualapp/virtualapp.py:66
msgid "Applet pkg not valid, Missing file {}"
msgstr "無効なアプレット パッケージ、ファイル {} がありません"
-#: terminal/models/applet/applet.py:112
+#: terminal/models/applet/applet.py:113
msgid "Load platform.yml failed: {}"
msgstr "platform.ymlのロードに失敗しました:{}"
-#: terminal/models/applet/applet.py:115
+#: terminal/models/applet/applet.py:116
msgid "Only support custom platform"
msgstr "カスタムプラットフォームのみをサポート"
-#: terminal/models/applet/applet.py:120
+#: terminal/models/applet/applet.py:121
msgid "Missing type in platform.yml"
msgstr "platform.ymlにタイプがありません"
-#: terminal/models/applet/applet.py:319 terminal/models/applet/host.py:36
+#: terminal/models/applet/applet.py:330 terminal/models/applet/host.py:36
#: terminal/models/applet/host.py:138
msgid "Hosting"
msgstr "ホスト マシン"
-#: terminal/models/applet/applet.py:325
+#: terminal/models/applet/applet.py:336
msgid "Applet Publication"
msgstr "アプリケーションのリリース"
@@ -7425,7 +7561,7 @@ msgid "Command and replay storage"
msgstr "コマンド及び録画記憶"
#: terminal/notifications.py:240 terminal/tasks.py:153
-#: xpack/plugins/cloud/api.py:154
+#: xpack/plugins/cloud/api.py:160
#: xpack/plugins/cloud/serializers/account.py:121
#: xpack/plugins/cloud/serializers/account.py:123
msgid "Test failure: Account invalid"
@@ -7673,7 +7809,7 @@ msgid "Access key secret"
msgstr "アクセスキーシークレット"
#: terminal/serializers/storage.py:68 xpack/plugins/cloud/manager.py:100
-#: xpack/plugins/cloud/models.py:273
+#: xpack/plugins/cloud/models.py:285
msgid "Region"
msgstr "リージョン"
@@ -7693,11 +7829,6 @@ msgstr "エンドポイントサフィックス"
msgid "HOST"
msgstr "ホスト"
-#: terminal/serializers/storage.py:146 users/models/user.py:930
-#: xpack/plugins/cloud/serializers/account_attrs.py:213
-msgid "Private key"
-msgstr "ssh秘密鍵"
-
#: terminal/serializers/storage.py:152
msgid "SFTP Root"
msgstr "SFTPルート"
@@ -7742,7 +7873,15 @@ msgstr "インデックス"
msgid "Doc type"
msgstr "Docタイプ"
-#: terminal/serializers/storage.py:263
+#: terminal/serializers/storage.py:257
+msgid "Store locally"
+msgstr "ローカルに保存する"
+
+#: terminal/serializers/storage.py:258
+msgid "Do not save"
+msgstr "保存しない"
+
+#: terminal/serializers/storage.py:273
msgid ""
"set as the default storage, will make new Component use the current storage "
"by default, without affecting existing Component"
@@ -7938,7 +8077,7 @@ msgstr ""
msgid "All available port count: {}, Already use port count: {}"
msgstr "使用可能なすべてのポート数: {}、すでに使用しているポート数: {}"
-#: tickets/api/ticket.py:88 tickets/models/ticket/general.py:286
+#: tickets/api/ticket.py:88 tickets/models/ticket/general.py:289
msgid "Applicant"
msgstr "応募者"
@@ -7975,30 +8114,14 @@ msgid "Two level"
msgstr "2つのレベル"
#: tickets/const.py:54
-msgid "Org admin"
-msgstr "Org admin"
-
-#: tickets/const.py:55
-msgid "Custom user"
-msgstr "カスタムユーザー"
-
-#: tickets/const.py:56
-msgid "Super admin"
-msgstr "スーパー管理者"
-
-#: tickets/const.py:57
-msgid "Super admin and org admin"
-msgstr "スーパーadminとorg admin"
-
-#: tickets/const.py:61
msgid "All assets"
msgstr "すべての資産"
-#: tickets/const.py:62
+#: tickets/const.py:55
msgid "Permed assets"
msgstr "許可された資産"
-#: tickets/const.py:63
+#: tickets/const.py:56
msgid "Permed valid assets"
msgstr "有効な許可を受けた資産"
@@ -8042,24 +8165,16 @@ msgstr "ユーザー表示名"
msgid "Body"
msgstr "ボディ"
-#: tickets/models/flow.py:19 tickets/models/flow.py:61
-#: tickets/models/ticket/general.py:42
+#: tickets/models/flow.py:21 tickets/models/flow.py:47
+#: tickets/models/ticket/general.py:45
msgid "Approve level"
msgstr "レベルを承認する"
-#: tickets/models/flow.py:24 tickets/serializers/flow.py:17
-msgid "Approve strategy"
-msgstr "戦略を承認する"
-
-#: tickets/models/flow.py:29 tickets/serializers/flow.py:19
-msgid "Assignees"
-msgstr "アシニーズ"
-
-#: tickets/models/flow.py:33
+#: tickets/models/flow.py:26
msgid "Ticket flow approval rule"
msgstr "チケットフロー承認ルール"
-#: tickets/models/flow.py:66
+#: tickets/models/flow.py:52
msgid "Ticket flow"
msgstr "チケットの流れ"
@@ -8113,35 +8228,35 @@ msgstr "コマンド フィルタ"
msgid "Apply Command Ticket"
msgstr "製造オーダの検討を命令"
-#: tickets/models/ticket/general.py:77
+#: tickets/models/ticket/general.py:80
msgid "Ticket step"
msgstr "チケットステップ"
-#: tickets/models/ticket/general.py:95
+#: tickets/models/ticket/general.py:98
msgid "Ticket assignee"
msgstr "割り当てられたチケット"
-#: tickets/models/ticket/general.py:270
+#: tickets/models/ticket/general.py:273
msgid "Title"
msgstr "タイトル"
-#: tickets/models/ticket/general.py:290
+#: tickets/models/ticket/general.py:293
msgid "TicketFlow"
msgstr "作業指示プロセス"
-#: tickets/models/ticket/general.py:293
+#: tickets/models/ticket/general.py:296
msgid "Approval step"
msgstr "承認ステップ"
-#: tickets/models/ticket/general.py:296
+#: tickets/models/ticket/general.py:299
msgid "Relation snapshot"
msgstr "製造オーダスナップショット"
-#: tickets/models/ticket/general.py:399
+#: tickets/models/ticket/general.py:405
msgid "Please try again"
msgstr "もう一度お試しください"
-#: tickets/models/ticket/general.py:475
+#: tickets/models/ticket/general.py:481
msgid "Super ticket"
msgstr "スーパーチケット"
@@ -8189,15 +8304,7 @@ msgstr "チケットが処理されました。プロセッサー- {}"
msgid "Ticket has processed - {} ({})"
msgstr "チケットが処理済み- {} ({})"
-#: tickets/serializers/flow.py:20
-msgid "Assignees display"
-msgstr "受付者名"
-
-#: tickets/serializers/flow.py:46
-msgid "Please select the Assignees"
-msgstr "受付をお選びください"
-
-#: tickets/serializers/flow.py:74
+#: tickets/serializers/flow.py:45
msgid "The current organization type already exists"
msgstr "現在の組織タイプは既に存在します。"
@@ -8358,14 +8465,18 @@ msgstr "置換"
msgid "Suffix"
msgstr "接尾辞を付ける"
-#: users/exceptions.py:10
+#: users/exceptions.py:9
msgid "MFA not enabled"
msgstr "MFAが有効化されていません"
-#: users/exceptions.py:20
+#: users/exceptions.py:19
msgid "Unable to delete all users"
msgstr "すべてのユーザーを削除できません"
+#: users/exceptions.py:24
+msgid "Create failed. The number of SSH keys has reached the limit"
+msgstr "作成に失敗しました。SSHキーの数が上限に達しました"
+
#: users/forms/profile.py:48
msgid ""
"When enabled, you will enter the MFA binding process the next time you log "
@@ -8432,82 +8543,69 @@ msgstr "ここにid_rsa.pubを貼り付けます。"
msgid "Public key should not be the same as your old one."
msgstr "公開鍵は古いものと同じであってはなりません。"
-#: users/forms/profile.py:161 users/serializers/profile.py:76
-#: users/serializers/profile.py:160 users/serializers/profile.py:187
-msgid "Not a valid ssh public key"
-msgstr "有効なssh公開鍵ではありません"
-
#: users/models/preference.py:38 users/serializers/preference/preference.py:19
msgid "Preference"
msgstr "ユーザー設定"
-#: users/models/user.py:690
-msgid "Force enabled"
-msgstr "強制有効"
-
-#: users/models/user.py:913 users/serializers/user.py:271
+#: users/models/user/__init__.py:69 users/serializers/user.py:271
msgid "Is service account"
msgstr "サービスアカウントです"
-#: users/models/user.py:915
+#: users/models/user/__init__.py:71
msgid "Avatar"
msgstr "アバター"
-#: users/models/user.py:917
+#: users/models/user/__init__.py:73
msgid "Wechat"
msgstr "微信"
-#: users/models/user.py:926
+#: users/models/user/__init__.py:82
msgid "OTP secret key"
msgstr "OTP 秘密"
# msgid "Private key"
# msgstr "ssh秘密鍵"
-#: users/models/user.py:936 users/serializers/profile.py:124
+#: users/models/user/__init__.py:92 users/serializers/profile.py:97
#: users/serializers/user.py:268
msgid "Is first login"
msgstr "最初のログインです"
-#: users/models/user.py:954
+#: users/models/user/__init__.py:110
msgid "Date password last updated"
msgstr "最終更新日パスワード"
-#: users/models/user.py:957
+#: users/models/user/__init__.py:113
msgid "Need update password"
msgstr "更新パスワードが必要"
-#: users/models/user.py:981
+#: users/models/user/__init__.py:137
msgid "Date api key used"
msgstr "API key 最後に使用した日付"
-#: users/models/user.py:1119
+#: users/models/user/__init__.py:276
msgid "Can not delete admin user"
msgstr "管理者ユーザーを削除できませんでした"
-#: users/models/user.py:1133
+#: users/models/user/__init__.py:290
msgid "Can invite user"
msgstr "ユーザーを招待できます"
-#: users/models/user.py:1134
+#: users/models/user/__init__.py:291
msgid "Can remove user"
msgstr "ユーザーを削除できます"
-#: users/models/user.py:1135
+#: users/models/user/__init__.py:292
msgid "Can match user"
msgstr "ユーザーに一致できます"
-#: users/models/user.py:1146
-msgid "Administrator"
-msgstr "管理者"
-
-#: users/models/user.py:1149
-msgid "Administrator is the super user of system"
-msgstr "管理者はシステムのスーパーユーザーです"
-
-#: users/models/user.py:1181
+#: users/models/user/__init__.py:321
msgid "User password history"
msgstr "ユーザーパスワード履歴"
+#: users/models/user/_auth.py:34
+msgid "Force enabled"
+msgstr "強制有効"
+
#: users/notifications.py:55
#: users/templates/users/_msg_password_expire_reminder.html:17
#: users/templates/users/reset_password.html:5
@@ -8645,7 +8743,7 @@ msgstr "コマンドライン"
msgid "The old password is incorrect"
msgstr "古いパスワードが正しくありません"
-#: users/serializers/profile.py:36 users/serializers/profile.py:174
+#: users/serializers/profile.py:36 users/serializers/profile.py:147
msgid "Password does not match security rules"
msgstr "パスワードがセキュリティルールと一致しない"
@@ -8767,7 +8865,7 @@ msgstr ""
msgid "name not unique"
msgstr "名前が一意ではない"
-#: users/signal_handlers.py:35
+#: users/signal_handlers.py:39
msgid ""
"The administrator has enabled \"Only allow existing users to log in\", \n"
" and the current user is not in the user list. Please contact the "
@@ -8776,7 +8874,7 @@ msgstr ""
"管理者は「既存のユーザーのみログインを許可」をオンにしており、現在のユーザー"
"はユーザーリストにありません。管理者に連絡してください。"
-#: users/signal_handlers.py:171
+#: users/signal_handlers.py:183
msgid "Clean up expired user sessions"
msgstr "期限切れのユーザー・セッションのパージ"
@@ -8904,23 +9002,23 @@ msgstr "パスワードを満たす必要があります"
msgid "Password strength"
msgstr "パスワードの強さ"
-#: users/templates/users/reset_password.html:51
+#: users/templates/users/reset_password.html:52
msgid "Very weak"
msgstr "非常に弱い"
-#: users/templates/users/reset_password.html:52
+#: users/templates/users/reset_password.html:53
msgid "Weak"
msgstr "弱い"
-#: users/templates/users/reset_password.html:54
+#: users/templates/users/reset_password.html:55
msgid "Medium"
msgstr "中"
-#: users/templates/users/reset_password.html:55
+#: users/templates/users/reset_password.html:56
msgid "Strong"
msgstr "強い"
-#: users/templates/users/reset_password.html:56
+#: users/templates/users/reset_password.html:57
msgid "Very strong"
msgstr "非常に強い"
@@ -9064,15 +9162,15 @@ msgid ""
"strategy will skipped."
msgstr "現在のタスク構成に基づいて、未一致ポリシーの資産はスキップされます"
-#: xpack/plugins/cloud/api.py:66
+#: xpack/plugins/cloud/api.py:72
msgid "Test connection successful"
msgstr "テスト接続成功"
-#: xpack/plugins/cloud/api.py:68
+#: xpack/plugins/cloud/api.py:74
msgid "Test connection failed: {}"
msgstr "テスト接続に失敗しました: {}"
-#: xpack/plugins/cloud/api.py:165
+#: xpack/plugins/cloud/api.py:171
msgid "User {} deleted the current resource and released the assets"
msgstr "ユーザー {} が現在のリソースを削除し、アセットを解放しました"
@@ -9176,7 +9274,7 @@ msgstr "プライベートIP"
msgid "Public IP"
msgstr "パブリックIP"
-#: xpack/plugins/cloud/const.py:42 xpack/plugins/cloud/models.py:347
+#: xpack/plugins/cloud/const.py:42 xpack/plugins/cloud/models.py:359
msgid "Instance name"
msgstr "インスタンス名"
@@ -9247,7 +9345,7 @@ msgstr "タスク実行完了"
#: xpack/plugins/cloud/manager.py:97
msgid "Synchronization regions"
-msgstr "同期地域"
+msgstr "地域を同期する"
#: xpack/plugins/cloud/manager.py:115
#, python-format
@@ -9259,7 +9357,7 @@ msgstr "地域 \"%s\" のインスタンスを取得できませんでした、
msgid "Failed to synchronize the instance \"%s\""
msgstr "インスタンス \"%s\" の同期に失敗しました"
-#: xpack/plugins/cloud/manager.py:334
+#: xpack/plugins/cloud/manager.py:337
#, python-format
msgid ""
"The updated platform of asset \"%s\" is inconsistent with the original "
@@ -9268,42 +9366,42 @@ msgstr ""
"更新された資産 \"%s\" のプラットフォームタイプと元のタイプは一致しません。プ"
"ラットフォームとプロトコルの更新をスキップ"
-#: xpack/plugins/cloud/manager.py:390
+#: xpack/plugins/cloud/manager.py:393
#, python-format
msgid "The asset \"%s\" already exists"
msgstr "資産 \"%s\" はすでに存在します"
-#: xpack/plugins/cloud/manager.py:392
+#: xpack/plugins/cloud/manager.py:395
#, python-format
msgid "Update asset \"%s\""
msgstr "資産の更新 \"%s\""
-#: xpack/plugins/cloud/manager.py:395
+#: xpack/plugins/cloud/manager.py:398
#, python-format
msgid "Asset \"%s\" has been updated"
msgstr "資産 \"%s\" が更新されました"
-#: xpack/plugins/cloud/manager.py:405
+#: xpack/plugins/cloud/manager.py:408
#, python-format
msgid "Prepare to create asset \"%s\""
msgstr "資産 \"%s\" の作成準備"
-#: xpack/plugins/cloud/manager.py:426
+#: xpack/plugins/cloud/manager.py:429
#, python-format
msgid "Set nodes \"%s\""
msgstr "ノード \"%s\" の設定"
-#: xpack/plugins/cloud/manager.py:452
+#: xpack/plugins/cloud/manager.py:455
#, python-format
msgid "Set accounts \"%s\""
msgstr "アカウント \"%s\" の設定"
-#: xpack/plugins/cloud/manager.py:468
+#: xpack/plugins/cloud/manager.py:471
#, python-format
msgid "Set protocols \"%s\""
msgstr "プロトコル \"%s\" の設定"
-#: xpack/plugins/cloud/manager.py:482 xpack/plugins/cloud/tasks.py:27
+#: xpack/plugins/cloud/manager.py:485 xpack/plugins/cloud/tasks.py:30
msgid "Run sync instance task"
msgstr "同期インスタンス タスクを実行する"
@@ -9311,164 +9409,165 @@ msgstr "同期インスタンス タスクを実行する"
msgid "Cloud center"
msgstr "クラウドセンター"
-#: xpack/plugins/cloud/models.py:38
+#: xpack/plugins/cloud/models.py:39
#: xpack/plugins/cloud/serializers/account.py:94
msgid "Attrs"
msgstr "ツールバーの"
-#: xpack/plugins/cloud/models.py:39
+#: xpack/plugins/cloud/models.py:40
msgid "Validity"
msgstr "有効性"
-#: xpack/plugins/cloud/models.py:44
+#: xpack/plugins/cloud/models.py:45
msgid "Cloud account"
msgstr "クラウドアカウント"
-#: xpack/plugins/cloud/models.py:46
+#: xpack/plugins/cloud/models.py:47
msgid "Test cloud account"
msgstr "クラウドアカウントのテスト"
-#: xpack/plugins/cloud/models.py:103
+#: xpack/plugins/cloud/models.py:104
#: xpack/plugins/cloud/serializers/account.py:76
-#: xpack/plugins/cloud/serializers/task.py:156
+#: xpack/plugins/cloud/serializers/task.py:157
+#: xpack/plugins/cloud/serializers/task.py:158
msgid "Regions"
msgstr "リージョン"
-#: xpack/plugins/cloud/models.py:106
+#: xpack/plugins/cloud/models.py:107
msgid "Hostname strategy"
msgstr "ホスト名戦略"
-#: xpack/plugins/cloud/models.py:111
+#: xpack/plugins/cloud/models.py:112
msgid "IP network segment group"
msgstr "IPネットワークセグメントグループ"
-#: xpack/plugins/cloud/models.py:114
-#: xpack/plugins/cloud/serializers/task.py:159
+#: xpack/plugins/cloud/models.py:115
+#: xpack/plugins/cloud/serializers/task.py:161
msgid "Sync IP type"
msgstr "同期IPタイプ"
-#: xpack/plugins/cloud/models.py:117
+#: xpack/plugins/cloud/models.py:118
msgid "Always update"
msgstr "常に更新"
-#: xpack/plugins/cloud/models.py:119
+#: xpack/plugins/cloud/models.py:120
msgid "Fully synchronous"
msgstr "完全同期"
-#: xpack/plugins/cloud/models.py:124
+#: xpack/plugins/cloud/models.py:125
msgid "Date last sync"
msgstr "最終同期日"
-#: xpack/plugins/cloud/models.py:127 xpack/plugins/cloud/models.py:365
-#: xpack/plugins/cloud/models.py:391
+#: xpack/plugins/cloud/models.py:128 xpack/plugins/cloud/models.py:377
+#: xpack/plugins/cloud/models.py:403
msgid "Strategy"
msgstr "戦略"
-#: xpack/plugins/cloud/models.py:132 xpack/plugins/cloud/models.py:220
+#: xpack/plugins/cloud/models.py:133 xpack/plugins/cloud/models.py:221
msgid "Sync instance task"
msgstr "インスタンスの同期タスク"
-#: xpack/plugins/cloud/models.py:231 xpack/plugins/cloud/models.py:283
+#: xpack/plugins/cloud/models.py:232 xpack/plugins/cloud/models.py:295
msgid "Date sync"
msgstr "日付の同期"
-#: xpack/plugins/cloud/models.py:235
+#: xpack/plugins/cloud/models.py:236
msgid "Sync instance snapshot"
msgstr "インスタンススナップショットの同期"
-#: xpack/plugins/cloud/models.py:239
+#: xpack/plugins/cloud/models.py:244
msgid "Sync instance task execution"
msgstr "インスタンスタスクの同期実行"
-#: xpack/plugins/cloud/models.py:263
+#: xpack/plugins/cloud/models.py:275
msgid "Sync task"
msgstr "同期タスク"
-#: xpack/plugins/cloud/models.py:267
+#: xpack/plugins/cloud/models.py:279
msgid "Sync instance task history"
msgstr "インスタンスタスク履歴の同期"
-#: xpack/plugins/cloud/models.py:270
+#: xpack/plugins/cloud/models.py:282
msgid "Instance"
msgstr "インスタンス"
-#: xpack/plugins/cloud/models.py:287
+#: xpack/plugins/cloud/models.py:299
msgid "Sync instance detail"
msgstr "同期インスタンスの詳細"
-#: xpack/plugins/cloud/models.py:299 xpack/plugins/cloud/serializers/task.py:76
+#: xpack/plugins/cloud/models.py:311 xpack/plugins/cloud/serializers/task.py:77
msgid "Rule relation"
msgstr "条件関係"
-#: xpack/plugins/cloud/models.py:309
+#: xpack/plugins/cloud/models.py:321
msgid "Task strategy"
msgstr "ミッション戦略です"
-#: xpack/plugins/cloud/models.py:336
+#: xpack/plugins/cloud/models.py:348
msgid "Equal"
msgstr "等しい"
-#: xpack/plugins/cloud/models.py:337
+#: xpack/plugins/cloud/models.py:349
msgid "Not Equal"
msgstr "不等于"
-#: xpack/plugins/cloud/models.py:338
+#: xpack/plugins/cloud/models.py:350
msgid "In"
msgstr "で..."
-#: xpack/plugins/cloud/models.py:339
+#: xpack/plugins/cloud/models.py:351
msgid "Contains"
msgstr "含む"
-#: xpack/plugins/cloud/models.py:340
+#: xpack/plugins/cloud/models.py:352
msgid "Exclude"
msgstr "除外"
-#: xpack/plugins/cloud/models.py:341
+#: xpack/plugins/cloud/models.py:353
msgid "Startswith"
msgstr "始まる..."
-#: xpack/plugins/cloud/models.py:342
+#: xpack/plugins/cloud/models.py:354
msgid "Endswith"
msgstr "終わる..."
-#: xpack/plugins/cloud/models.py:348
+#: xpack/plugins/cloud/models.py:360
msgid "Instance platform"
msgstr "インスタンス名"
-#: xpack/plugins/cloud/models.py:349
+#: xpack/plugins/cloud/models.py:361
msgid "Instance address"
msgstr "インスタンスアドレス"
-#: xpack/plugins/cloud/models.py:356
+#: xpack/plugins/cloud/models.py:368
msgid "Rule attr"
msgstr "ルール属性"
-#: xpack/plugins/cloud/models.py:360
+#: xpack/plugins/cloud/models.py:372
msgid "Rule match"
msgstr "ルール一致"
-#: xpack/plugins/cloud/models.py:362
+#: xpack/plugins/cloud/models.py:374
msgid "Rule value"
msgstr "ルール値"
-#: xpack/plugins/cloud/models.py:369 xpack/plugins/cloud/serializers/task.py:79
+#: xpack/plugins/cloud/models.py:381 xpack/plugins/cloud/serializers/task.py:80
msgid "Strategy rule"
msgstr "戦略ルール"
-#: xpack/plugins/cloud/models.py:379
+#: xpack/plugins/cloud/models.py:391
msgid "Name strategy"
msgstr "ホスト名戦略"
-#: xpack/plugins/cloud/models.py:386
+#: xpack/plugins/cloud/models.py:398
msgid "Action attr"
msgstr "アクション属性"
-#: xpack/plugins/cloud/models.py:388
+#: xpack/plugins/cloud/models.py:400
msgid "Action value"
msgstr "アクション値"
-#: xpack/plugins/cloud/models.py:395 xpack/plugins/cloud/serializers/task.py:82
+#: xpack/plugins/cloud/models.py:407 xpack/plugins/cloud/serializers/task.py:83
msgid "Strategy action"
msgstr "戦略アクション"
@@ -9770,15 +9869,15 @@ msgstr "テストタイムアウト"
msgid "Project"
msgstr "project"
-#: xpack/plugins/cloud/serializers/task.py:154
+#: xpack/plugins/cloud/serializers/task.py:155
msgid "History count"
msgstr "実行回数"
-#: xpack/plugins/cloud/serializers/task.py:155
+#: xpack/plugins/cloud/serializers/task.py:156
msgid "Instance count"
msgstr "インスタンス数"
-#: xpack/plugins/cloud/tasks.py:41
+#: xpack/plugins/cloud/tasks.py:44
msgid "Period clean sync instance task execution"
msgstr "同期インスタンス タスクの実行記録を定期的にクリアする"
diff --git a/apps/i18n/core/zh/LC_MESSAGES/django.po b/apps/i18n/core/zh/LC_MESSAGES/django.po
index 2b69fe5a5..bca835822 100644
--- a/apps/i18n/core/zh/LC_MESSAGES/django.po
+++ b/apps/i18n/core/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: 2024-07-03 16:39+0800\n"
+"POT-Creation-Date: 2024-08-15 14:04+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler \n"
"Language-Team: JumpServer team\n"
@@ -63,9 +63,10 @@ msgstr "完成"
#: accounts/automations/backup_account/handlers.py:219
#: accounts/const/automation.py:110
-#: accounts/serializers/automations/change_secret.py:166 audits/const.py:64
+#: accounts/serializers/automations/change_secret.py:166
+#: assets/serializers/automations/base.py:52 audits/const.py:64
#: audits/models.py:64 audits/signal_handlers/activity_log.py:33
-#: common/const/choices.py:18 ops/const.py:74 ops/serializers/celery.py:48
+#: common/const/choices.py:65 ops/const.py:74 ops/serializers/celery.py:48
#: terminal/const.py:78 terminal/models/session/sharing.py:121
#: tickets/views/approve.py:128
msgid "Success"
@@ -74,7 +75,7 @@ msgstr "成功"
#: accounts/automations/backup_account/handlers.py:221
#: accounts/const/account.py:34 accounts/const/automation.py:109
#: accounts/serializers/automations/change_secret.py:167 audits/const.py:65
-#: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19
+#: audits/signal_handlers/activity_log.py:33 common/const/choices.py:66
#: ops/const.py:76 terminal/const.py:79 xpack/plugins/cloud/const.py:47
msgid "Failed"
msgstr "失败"
@@ -111,7 +112,7 @@ msgstr "计划执行结束"
msgid "No pending accounts found"
msgstr "未找到待处理帐户"
-#: accounts/automations/change_secret/manager.py:224
+#: accounts/automations/change_secret/manager.py:227
#, python-format
msgid "Success: %s, Failed: %s, Total: %s"
msgstr "成功: %s, 失败: %s, 总数: %s"
@@ -121,9 +122,9 @@ msgstr "成功: %s, 失败: %s, 总数: %s"
#: audits/signal_handlers/login_log.py:34 authentication/confirm/password.py:9
#: authentication/confirm/password.py:24 authentication/confirm/password.py:26
#: authentication/forms.py:28
-#: authentication/templates/authentication/login.html:323
-#: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:50
-#: settings/serializers/msg.py:36 settings/serializers/terminal.py:28
+#: authentication/templates/authentication/login.html:362
+#: settings/serializers/auth/ldap.py:26 settings/serializers/auth/ldap.py:51
+#: settings/serializers/msg.py:37 settings/serializers/terminal.py:28
#: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142
#: users/forms/profile.py:21 users/serializers/user.py:144
#: users/templates/users/_msg_user_created.html:13
@@ -134,7 +135,7 @@ msgstr "密码"
#: accounts/const/account.py:7
#: accounts/serializers/automations/change_secret.py:35
-#: terminal/serializers/storage.py:124
+#: authentication/models/ssh_key.py:27 terminal/serializers/storage.py:124
msgid "SSH key"
msgstr "SSH 密钥"
@@ -145,13 +146,13 @@ msgstr "Access key"
#: accounts/const/account.py:9 authentication/backends/passkey/models.py:16
#: authentication/models/sso_token.py:14 settings/serializers/feature.py:52
msgid "Token"
-msgstr "Token"
+msgstr "令牌"
#: accounts/const/account.py:10
msgid "API key"
msgstr "API key"
-#: accounts/const/account.py:14 common/db/fields.py:235
+#: accounts/const/account.py:14 common/db/fields.py:230
#: settings/serializers/terminal.py:14
msgid "All"
msgstr "全部"
@@ -172,7 +173,7 @@ msgstr "匿名账号"
msgid "Specified account"
msgstr "指定账号"
-#: accounts/const/account.py:26 users/models/user.py:791
+#: accounts/const/account.py:26 users/models/user/_source.py:11
msgid "Local"
msgstr "数据库"
@@ -291,8 +292,8 @@ msgstr "仅创建"
#: authentication/serializers/password_mfa.py:16
#: authentication/serializers/password_mfa.py:24
#: notifications/backends/__init__.py:10 settings/serializers/msg.py:21
-#: settings/serializers/msg.py:58 users/forms/profile.py:100
-#: users/forms/profile.py:108 users/models/user.py:902
+#: settings/serializers/msg.py:61 users/forms/profile.py:100
+#: users/forms/profile.py:108 users/models/user/__init__.py:58
#: users/templates/users/forgot_password.html:162
#: users/views/profile/reset.py:94
msgid "Email"
@@ -302,8 +303,9 @@ msgstr "邮箱"
msgid "SFTP"
msgstr "SFTP"
-#: accounts/const/automation.py:111 common/const/choices.py:16
-#: terminal/const.py:77 tickets/const.py:29 tickets/const.py:38
+#: accounts/const/automation.py:111 assets/serializers/automations/base.py:54
+#: common/const/choices.py:63 terminal/const.py:77 tickets/const.py:29
+#: tickets/const.py:38
msgid "Pending"
msgstr "待定的"
@@ -336,8 +338,8 @@ msgstr "用户 %s 查看/导出 了密码"
#: accounts/models/account.py:49
#: accounts/models/automations/gather_account.py:16
-#: accounts/serializers/account/account.py:218
-#: accounts/serializers/account/account.py:263
+#: accounts/serializers/account/account.py:226
+#: accounts/serializers/account/account.py:271
#: accounts/serializers/account/gathered_account.py:10
#: accounts/serializers/automations/change_secret.py:111
#: accounts/serializers/automations/change_secret.py:143
@@ -351,26 +353,26 @@ msgstr "用户 %s 查看/导出 了密码"
#: terminal/serializers/command.py:17 terminal/serializers/session.py:28
#: terminal/templates/terminal/_msg_command_warning.html:4
#: terminal/templates/terminal/_msg_session_sharing.html:4
-#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:276
+#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:288
msgid "Asset"
msgstr "资产"
#: accounts/models/account.py:53 accounts/models/template.py:16
-#: accounts/serializers/account/account.py:225
-#: accounts/serializers/account/account.py:273
+#: accounts/serializers/account/account.py:233
+#: accounts/serializers/account/account.py:281
#: accounts/serializers/account/template.py:27
#: authentication/serializers/connect_token_secret.py:50
msgid "Su from"
msgstr "切换自"
-#: accounts/models/account.py:55 assets/const/protocol.py:178
-#: settings/serializers/auth/cas.py:23 terminal/models/applet/applet.py:35
+#: accounts/models/account.py:55 assets/const/protocol.py:189
+#: settings/serializers/auth/cas.py:25 terminal/models/applet/applet.py:36
#: terminal/models/virtualapp/virtualapp.py:21
msgid "Version"
msgstr "版本"
-#: accounts/models/account.py:57 accounts/serializers/account/account.py:220
-#: users/models/user.py:963
+#: accounts/models/account.py:57 accounts/serializers/account/account.py:228
+#: users/models/user/__init__.py:119
msgid "Source"
msgstr "来源"
@@ -392,7 +394,7 @@ msgstr "来源 ID"
#: terminal/templates/terminal/_msg_command_warning.html:8
#: terminal/templates/terminal/_msg_session_sharing.html:8
#: tickets/models/ticket/command_confirm.py:13
-#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/ws.py:38
+#: xpack/plugins/cloud/models.py:101 xpack/plugins/cloud/ws.py:37
msgid "Account"
msgstr "账号"
@@ -468,7 +470,7 @@ msgstr "开始日期"
#: accounts/models/automations/backup_account.py:123
#: authentication/templates/authentication/_msg_oauth_bind.html:11
-#: notifications/notifications.py:186
+#: notifications/notifications.py:194
#: settings/templates/ldap/_msg_import_ldap_user.html:3
msgid "Time"
msgstr "时间"
@@ -481,13 +483,14 @@ msgstr "账号备份快照"
#: accounts/serializers/account/backup.py:48
#: accounts/serializers/automations/base.py:56
#: assets/models/automations/base.py:122
-#: assets/serializers/automations/base.py:39
+#: assets/serializers/automations/base.py:40 xpack/plugins/cloud/models.py:240
+#: xpack/plugins/cloud/serializers/task.py:243
msgid "Trigger mode"
msgstr "触发模式"
#: accounts/models/automations/backup_account.py:134 audits/models.py:203
#: terminal/models/session/sharing.py:125 xpack/plugins/cloud/manager.py:158
-#: xpack/plugins/cloud/models.py:228
+#: xpack/plugins/cloud/models.py:229
msgid "Reason"
msgstr "原因"
@@ -546,7 +549,7 @@ msgstr "SSH 密钥推送方式"
#: accounts/models/automations/gather_account.py:58
#: accounts/serializers/account/backup.py:40
#: accounts/serializers/automations/change_secret.py:58
-#: settings/serializers/auth/ldap.py:101 settings/serializers/msg.py:44
+#: settings/serializers/auth/ldap.py:99 settings/serializers/msg.py:45
msgid "Recipient"
msgstr "收件人"
@@ -574,26 +577,27 @@ msgid "Date finished"
msgstr "结束日期"
#: accounts/models/automations/change_secret.py:44
-#: assets/models/automations/base.py:113 audits/models.py:208
+#: assets/models/automations/base.py:113
+#: assets/serializers/automations/base.py:39 audits/models.py:208
#: audits/serializers.py:54 ops/models/base.py:49 ops/models/job.py:234
-#: terminal/models/applet/applet.py:320 terminal/models/applet/host.py:140
+#: terminal/models/applet/applet.py:331 terminal/models/applet/host.py:140
#: terminal/models/component/status.py:30
#: terminal/models/virtualapp/virtualapp.py:99
#: terminal/serializers/applet.py:18 terminal/serializers/applet_host.py:136
-#: terminal/serializers/virtualapp.py:35 tickets/models/ticket/general.py:281
+#: terminal/serializers/virtualapp.py:35 tickets/models/ticket/general.py:284
#: tickets/serializers/super_ticket.py:13
-#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:224
-#: xpack/plugins/cloud/models.py:280
+#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:225
+#: xpack/plugins/cloud/models.py:292
msgid "Status"
msgstr "状态"
#: accounts/models/automations/change_secret.py:47
-#: accounts/serializers/account/account.py:265
+#: accounts/serializers/account/account.py:273
#: accounts/templates/accounts/change_secret_failed_info.html:13
#: assets/const/automation.py:8
#: authentication/templates/authentication/passkey.html:173
#: authentication/views/base.py:42 authentication/views/base.py:43
-#: authentication/views/base.py:44 common/const/choices.py:20
+#: authentication/views/base.py:44 common/const/choices.py:67
#: settings/templates/ldap/_msg_import_ldap_user.html:26
msgid "Error"
msgstr "错误"
@@ -618,7 +622,7 @@ msgstr "最后登录日期"
#: authentication/templates/authentication/_msg_different_city.html:9
#: authentication/templates/authentication/_msg_oauth_bind.html:9
#: terminal/serializers/storage.py:136 users/forms/profile.py:31
-#: users/forms/profile.py:114 users/models/user.py:900
+#: users/forms/profile.py:114 users/models/user/__init__.py:56
#: users/templates/users/_msg_user_created.html:12
#: xpack/plugins/cloud/serializers/account_attrs.py:26
msgid "Username"
@@ -650,7 +654,7 @@ msgstr "触发方式"
#: audits/models.py:92 audits/serializers.py:84
#: authentication/serializers/connect_token_secret.py:119
#: authentication/templates/authentication/_access_key_modal.html:34
-#: perms/serializers/permission.py:42 perms/serializers/permission.py:64
+#: perms/serializers/permission.py:41 perms/serializers/permission.py:63
#: tickets/serializers/ticket/ticket.py:21
msgid "Action"
msgstr "动作"
@@ -664,7 +668,7 @@ msgid "Verify asset account"
msgstr "账号验证"
#: accounts/models/base.py:37 accounts/models/base.py:67
-#: accounts/serializers/account/account.py:448
+#: accounts/serializers/account/account.py:463
#: accounts/serializers/account/base.py:17
#: accounts/serializers/automations/change_secret.py:47
#: authentication/serializers/connect_token_secret.py:42
@@ -677,9 +681,9 @@ msgstr "密文类型"
#: accounts/serializers/account/base.py:20
#: authentication/models/temp_token.py:10
#: authentication/templates/authentication/_access_key_modal.html:31
-#: settings/serializers/auth/radius.py:19
+#: settings/serializers/auth/radius.py:20
msgid "Secret"
-msgstr "密钥"
+msgstr "密文"
#: accounts/models/base.py:42
#: accounts/serializers/automations/change_secret.py:41
@@ -697,27 +701,28 @@ msgstr "密码规则"
#: assets/models/asset/common.py:159 assets/models/cmd_filter.py:21
#: assets/models/domain.py:19 assets/models/label.py:18
#: assets/models/platform.py:15 assets/models/platform.py:94
-#: assets/serializers/asset/common.py:149 assets/serializers/platform.py:152
-#: assets/serializers/platform.py:270
+#: assets/serializers/asset/common.py:149 assets/serializers/platform.py:153
+#: assets/serializers/platform.py:273
#: authentication/backends/passkey/models.py:10
+#: authentication/models/ssh_key.py:12
#: authentication/serializers/connect_token_secret.py:113
#: authentication/serializers/connect_token_secret.py:169 labels/models.py:11
#: ops/mixin.py:21 ops/models/adhoc.py:20 ops/models/celery.py:15
#: ops/models/celery.py:80 ops/models/job.py:142 ops/models/playbook.py:28
#: ops/serializers/job.py:18 orgs/models.py:82
#: perms/models/asset_permission.py:61 rbac/models/role.py:29
-#: settings/models.py:34 settings/models.py:183 settings/serializers/msg.py:86
-#: settings/serializers/terminal.py:9 terminal/models/applet/applet.py:33
-#: terminal/models/component/endpoint.py:12
+#: rbac/serializers/role.py:28 settings/models.py:34 settings/models.py:183
+#: settings/serializers/msg.py:89 settings/serializers/terminal.py:9
+#: terminal/models/applet/applet.py:34 terminal/models/component/endpoint.py:12
#: terminal/models/component/endpoint.py:109
#: terminal/models/component/storage.py:26 terminal/models/component/task.py:13
#: terminal/models/component/terminal.py:85
#: terminal/models/virtualapp/provider.py:10
#: terminal/models/virtualapp/virtualapp.py:19 tickets/api/ticket.py:87
#: users/forms/profile.py:32 users/models/group.py:13
-#: users/models/preference.py:11 users/models/user.py:901
-#: xpack/plugins/cloud/models.py:33 xpack/plugins/cloud/models.py:296
-#: xpack/plugins/cloud/serializers/task.py:74
+#: users/models/preference.py:11 users/models/user/__init__.py:57
+#: xpack/plugins/cloud/models.py:34 xpack/plugins/cloud/models.py:308
+#: xpack/plugins/cloud/serializers/task.py:75
msgid "Name"
msgstr "名称"
@@ -728,7 +733,7 @@ msgstr "特权账号"
#: accounts/models/base.py:70 assets/models/automations/base.py:21
#: assets/models/cmd_filter.py:39 assets/models/label.py:22
#: authentication/serializers/connect_token_secret.py:117
-#: terminal/models/applet/applet.py:40
+#: terminal/models/applet/applet.py:41
#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:269
msgid "Is active"
msgstr "激活"
@@ -745,7 +750,7 @@ msgstr "平台"
msgid "Push params"
msgstr "账号推送参数"
-#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:377
+#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:389
msgid "Account template"
msgstr "账号模板"
@@ -847,99 +852,100 @@ msgstr "参数"
msgid "Exist policy"
msgstr "账号存在策略"
-#: accounts/serializers/account/account.py:198 assets/models/label.py:21
+#: accounts/serializers/account/account.py:206 assets/models/label.py:21
#: assets/models/platform.py:95 assets/serializers/asset/common.py:125
-#: assets/serializers/cagegory.py:12 assets/serializers/platform.py:174
-#: assets/serializers/platform.py:271 perms/serializers/user_permission.py:26
+#: assets/serializers/cagegory.py:12 assets/serializers/platform.py:168
+#: assets/serializers/platform.py:274 perms/serializers/user_permission.py:26
#: settings/models.py:36 tickets/models/ticket/apply_application.py:13
#: users/models/preference.py:12
msgid "Category"
msgstr "类别"
-#: accounts/serializers/account/account.py:199
+#: accounts/serializers/account/account.py:207
#: accounts/serializers/automations/base.py:55 acls/models/command_acl.py:24
#: acls/serializers/command_acl.py:19 assets/models/automations/base.py:20
#: assets/models/cmd_filter.py:74 assets/models/platform.py:96
-#: assets/serializers/asset/common.py:126 assets/serializers/platform.py:154
-#: assets/serializers/platform.py:173 audits/serializers.py:53
+#: assets/serializers/asset/common.py:126 assets/serializers/platform.py:155
+#: assets/serializers/platform.py:167 audits/serializers.py:53
#: audits/serializers.py:170
#: authentication/serializers/connect_token_secret.py:126 ops/models/job.py:150
-#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:39
+#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:40
#: terminal/models/component/storage.py:58
#: terminal/models/component/storage.py:154 terminal/serializers/applet.py:29
-#: terminal/serializers/session.py:23 terminal/serializers/storage.py:271
-#: terminal/serializers/storage.py:284 tickets/models/comment.py:26
-#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16
-#: tickets/models/ticket/general.py:273 tickets/serializers/flow.py:53
+#: terminal/serializers/session.py:23 terminal/serializers/storage.py:281
+#: terminal/serializers/storage.py:294 tickets/models/comment.py:26
+#: tickets/models/flow.py:42 tickets/models/ticket/apply_application.py:16
+#: tickets/models/ticket/general.py:276 tickets/serializers/flow.py:25
#: tickets/serializers/ticket/ticket.py:19
msgid "Type"
msgstr "类型"
-#: accounts/serializers/account/account.py:214
+#: accounts/serializers/account/account.py:222
msgid "Asset not found"
msgstr "资产不存在"
-#: accounts/serializers/account/account.py:254
+#: accounts/serializers/account/account.py:262
msgid "Has secret"
msgstr "已托管密码"
-#: accounts/serializers/account/account.py:264 ops/models/celery.py:83
-#: tickets/models/comment.py:13 tickets/models/ticket/general.py:46
-#: tickets/models/ticket/general.py:277 tickets/serializers/super_ticket.py:14
+#: accounts/serializers/account/account.py:272 ops/models/celery.py:83
+#: tickets/models/comment.py:13 tickets/models/ticket/general.py:49
+#: tickets/models/ticket/general.py:280 tickets/serializers/super_ticket.py:14
msgid "State"
msgstr "状态"
-#: accounts/serializers/account/account.py:266
+#: accounts/serializers/account/account.py:274
msgid "Changed"
msgstr "已修改"
-#: accounts/serializers/account/account.py:276
+#: accounts/serializers/account/account.py:284
#: accounts/serializers/automations/base.py:22 acls/models/base.py:97
#: acls/templates/acls/asset_login_reminder.html:9
#: assets/models/automations/base.py:19
#: assets/serializers/automations/base.py:20 assets/serializers/domain.py:34
+#: assets/serializers/platform.py:176 assets/serializers/platform.py:208
#: authentication/api/connection_token.py:410 ops/models/base.py:17
#: ops/models/job.py:152 ops/serializers/job.py:19
-#: perms/serializers/permission.py:36
+#: perms/serializers/permission.py:35
#: terminal/templates/terminal/_msg_command_execute_alert.html:16
#: xpack/plugins/cloud/manager.py:83
msgid "Assets"
msgstr "资产"
-#: accounts/serializers/account/account.py:331
+#: accounts/serializers/account/account.py:339
msgid "Account already exists"
msgstr "账号已存在"
-#: accounts/serializers/account/account.py:381
+#: accounts/serializers/account/account.py:389
#, python-format
msgid "Asset does not support this secret type: %s"
msgstr "资产不支持账号类型: %s"
-#: accounts/serializers/account/account.py:413
+#: accounts/serializers/account/account.py:421
msgid "Account has exist"
msgstr "账号已存在"
-#: accounts/serializers/account/account.py:443
+#: accounts/serializers/account/account.py:458
#: accounts/serializers/account/base.py:93
#: accounts/serializers/account/template.py:72
#: assets/serializers/asset/common.py:387
msgid "Spec info"
msgstr "特殊信息"
-#: accounts/serializers/account/account.py:449
+#: accounts/serializers/account/account.py:464
#: authentication/serializers/connect_token_secret.py:159
#: authentication/templates/authentication/_access_key_modal.html:30
#: perms/models/perm_node.py:21 users/serializers/group.py:33
msgid "ID"
msgstr "ID"
-#: accounts/serializers/account/account.py:459 acls/serializers/base.py:116
+#: accounts/serializers/account/account.py:474 acls/serializers/base.py:116
#: acls/templates/acls/asset_login_reminder.html:8
#: acls/templates/acls/user_login_reminder.html:8
#: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:54
#: audits/models.py:90 audits/models.py:172 audits/models.py:271
#: audits/serializers.py:171 authentication/models/connection_token.py:32
-#: authentication/models/sso_token.py:16
+#: authentication/models/ssh_key.py:22 authentication/models/sso_token.py:16
#: notifications/models/notification.py:12
#: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:63
#: rbac/builtin.py:124 rbac/models/rolebinding.py:49
@@ -949,12 +955,13 @@ msgstr "ID"
#: terminal/serializers/command.py:16
#: terminal/templates/terminal/_msg_command_warning.html:6
#: terminal/templates/terminal/_msg_session_sharing.html:6
-#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:1124
-#: users/models/user.py:1168
+#: tickets/models/comment.py:21 tickets/serializers/flow.py:15
+#: users/const.py:14 users/models/user/__init__.py:281
+#: users/models/user/__init__.py:308
msgid "User"
msgstr "用户"
-#: accounts/serializers/account/account.py:460
+#: accounts/serializers/account/account.py:475
#: authentication/templates/authentication/_access_key_modal.html:33
#: terminal/notifications.py:158 terminal/notifications.py:207
msgid "Date"
@@ -980,7 +987,7 @@ msgstr "资产类型"
#: accounts/serializers/account/base.py:33 terminal/serializers/storage.py:149
msgid "Passphrase"
-msgstr "密码"
+msgstr "密钥密码"
#: accounts/serializers/account/base.py:96
msgid ""
@@ -1033,14 +1040,14 @@ msgstr "关联平台,可配置推送参数,如果不关联,将使用默认
#: accounts/serializers/account/virtual.py:19 assets/models/cmd_filter.py:40
#: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:26
#: ops/models/job.py:158 ops/models/playbook.py:31 rbac/models/role.py:37
-#: settings/models.py:39 terminal/models/applet/applet.py:45
-#: terminal/models/applet/applet.py:321 terminal/models/applet/host.py:143
+#: settings/models.py:39 terminal/models/applet/applet.py:46
+#: terminal/models/applet/applet.py:332 terminal/models/applet/host.py:143
#: terminal/models/component/endpoint.py:25
#: terminal/models/component/endpoint.py:119
#: terminal/models/session/session.py:47
#: terminal/models/virtualapp/virtualapp.py:28 tickets/models/comment.py:32
-#: tickets/models/ticket/general.py:295 users/models/user.py:935
-#: xpack/plugins/cloud/models.py:40 xpack/plugins/cloud/models.py:121
+#: tickets/models/ticket/general.py:298 users/models/user/__init__.py:91
+#: xpack/plugins/cloud/models.py:41 xpack/plugins/cloud/models.py:122
msgid "Comment"
msgstr "备注"
@@ -1056,7 +1063,7 @@ msgstr ""
#: accounts/serializers/automations/base.py:23
#: assets/models/asset/common.py:164 assets/serializers/asset/common.py:152
-#: assets/serializers/automations/base.py:21 perms/serializers/permission.py:37
+#: assets/serializers/automations/base.py:21 perms/serializers/permission.py:36
msgid "Nodes"
msgstr "节点"
@@ -1080,13 +1087,13 @@ msgstr "SSH 密钥更改方式"
#: accounts/serializers/automations/change_secret.py:57
msgid "Please enter your account username"
-msgstr "请输入 MFA 验证码"
+msgstr "请输入您的账户用户名"
#: accounts/serializers/automations/change_secret.py:62
msgid ""
"Secret parameter settings, currently only effective for assets of the host "
"type."
-msgstr "秘文参数设置,目前只对宿主类型的资产有效。"
+msgstr "参数设置,目前只对 AIX LINUX UNIX 类型的资产有效。"
#: accounts/serializers/automations/change_secret.py:84
msgid "* Please enter the correct password length"
@@ -1101,17 +1108,17 @@ msgstr "* 密码长度范围 6-30 位"
msgid "Automation task execution"
msgstr "自动化任务执行历史"
-#: accounts/signal_handlers.py:47
+#: accounts/signal_handlers.py:48
#, python-format
msgid "Push related accounts to assets: %s, by system"
msgstr "推送账号到资产: %s, 由系统执行"
-#: accounts/signal_handlers.py:56
+#: accounts/signal_handlers.py:57
#, python-format
msgid "Add account: %s"
msgstr "添加账号: %s"
-#: accounts/signal_handlers.py:58
+#: accounts/signal_handlers.py:59
#, python-format
msgid "Delete account: %s"
msgstr "删除账号: %s"
@@ -1223,12 +1230,12 @@ msgid "Notify"
msgstr "通知"
#: acls/models/base.py:37 assets/models/cmd_filter.py:76
-#: terminal/models/component/endpoint.py:112 xpack/plugins/cloud/models.py:302
+#: terminal/models/component/endpoint.py:112 xpack/plugins/cloud/models.py:314
msgid "Priority"
msgstr "优先级"
#: acls/models/base.py:38 assets/models/cmd_filter.py:76
-#: terminal/models/component/endpoint.py:113 xpack/plugins/cloud/models.py:303
+#: terminal/models/component/endpoint.py:113 xpack/plugins/cloud/models.py:315
msgid "1-100, the lower the value will be match first"
msgstr "优先级可选范围为 1-100 (数值越小越优先)"
@@ -1240,22 +1247,24 @@ msgstr "审批人"
#: acls/models/base.py:43 assets/models/asset/common.py:165
#: authentication/models/access_key.py:25
#: authentication/models/connection_token.py:53
+#: authentication/models/ssh_key.py:13
#: authentication/templates/authentication/_access_key_modal.html:32
#: perms/models/asset_permission.py:82
#: terminal/models/component/endpoint.py:120
-#: terminal/models/session/sharing.py:29 tickets/const.py:36
+#: terminal/models/session/sharing.py:29 terminal/serializers/terminal.py:44
+#: tickets/const.py:36
msgid "Active"
msgstr "激活中"
-#: acls/models/base.py:81 perms/serializers/permission.py:32
-#: users/models/preference.py:16 users/serializers/group.py:21
-#: users/serializers/user.py:424
+#: acls/models/base.py:81 perms/serializers/permission.py:31
+#: tickets/models/flow.py:23 users/models/preference.py:16
+#: users/serializers/group.py:21 users/serializers/user.py:424
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:128
-#: assets/serializers/asset/common.py:386 perms/serializers/permission.py:45
+#: assets/serializers/asset/common.py:386 perms/serializers/permission.py:44
#: perms/serializers/user_permission.py:75 rbac/tree.py:35
msgid "Accounts"
msgstr "账号"
@@ -1270,13 +1279,13 @@ msgid "Command"
msgstr "命令"
#: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59
-#: xpack/plugins/cloud/models.py:343
+#: xpack/plugins/cloud/models.py:355
msgid "Regex"
msgstr "正则表达式"
#: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79
#: settings/models.py:184 settings/serializers/feature.py:19
-#: settings/serializers/msg.py:75 xpack/plugins/license/models.py:30
+#: settings/serializers/msg.py:78 xpack/plugins/license/models.py:30
msgid "Content"
msgstr "内容"
@@ -1375,7 +1384,7 @@ msgid "None of the reviewers belong to Organization `{}`"
msgstr "所有复核人都不属于组织 `{}`"
#: acls/serializers/rules/rules.py:20
-#: xpack/plugins/cloud/serializers/task.py:149
+#: xpack/plugins/cloud/serializers/task.py:150
msgid "IP address invalid: `{}`"
msgstr "IP 地址无效: `{}`"
@@ -1391,7 +1400,7 @@ msgstr ""
#: authentication/templates/authentication/_msg_oauth_bind.html:12
#: authentication/templates/authentication/_msg_rest_password_success.html:8
#: authentication/templates/authentication/_msg_rest_public_key_success.html:8
-#: xpack/plugins/cloud/models.py:378
+#: xpack/plugins/cloud/models.py:390
msgid "IP"
msgstr "IP"
@@ -1477,7 +1486,7 @@ msgstr "不能删除根节点 ({})"
msgid "Deletion failed and the node contains assets"
msgstr "删除失败,节点包含资产"
-#: assets/api/tree.py:49 assets/serializers/node.py:42
+#: assets/api/tree.py:48 assets/serializers/node.py:42
msgid "The same level node name cannot be the same"
msgstr "同级别节点名字不能重复"
@@ -1485,32 +1494,32 @@ msgstr "同级别节点名字不能重复"
msgid "App Assets"
msgstr "资产管理"
-#: assets/automations/base/manager.py:191
+#: assets/automations/base/manager.py:187
msgid "{} disabled"
msgstr "{} 已禁用"
-#: assets/automations/base/manager.py:254
+#: assets/automations/base/manager.py:250
msgid " - Platform {} ansible disabled"
msgstr " - 平台 {} Ansible 已禁用, 无法执行任务"
-#: assets/automations/base/manager.py:327
+#: assets/automations/base/manager.py:323
msgid ">>> Task preparation phase"
msgstr ">>> 任务准备阶段"
-#: assets/automations/base/manager.py:330
+#: assets/automations/base/manager.py:326
#, python-brace-format
msgid ">>> Executing tasks in batches, total {runner_count}"
msgstr ">>> 分次执行任务,总共 {runner_count}"
-#: assets/automations/base/manager.py:332
+#: assets/automations/base/manager.py:328
msgid ">>> Start executing tasks"
msgstr ">>> 开始执行任务"
-#: assets/automations/base/manager.py:334
+#: assets/automations/base/manager.py:330
msgid ">>> No tasks need to be executed"
msgstr ">>> 没有需要执行的任务"
-#: assets/automations/base/manager.py:339
+#: assets/automations/base/manager.py:335
#, python-brace-format
msgid ">>> Begin executing batch {index} of tasks"
msgstr ">>> 开始执行第 {index} 批任务"
@@ -1547,7 +1556,7 @@ msgstr "未知"
#: assets/const/automation.py:7
msgid "OK"
-msgstr ""
+msgstr "成功"
#: assets/const/automation.py:12
msgid "Ping"
@@ -1562,7 +1571,7 @@ msgid "Gather facts"
msgstr "收集资产信息"
#: assets/const/base.py:32 audits/const.py:58
-#: terminal/serializers/applet_host.py:32 users/models/user.py:688
+#: terminal/serializers/applet_host.py:32 users/models/user/_auth.py:32
msgid "Disabled"
msgstr "禁用"
@@ -1572,13 +1581,13 @@ msgstr "禁用"
msgid "Basic"
msgstr "基本"
-#: assets/const/base.py:34 assets/const/protocol.py:275
+#: assets/const/base.py:34 assets/const/protocol.py:292
#: 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:76
+#: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:76
#: settings/serializers/feature.py:49 settings/serializers/msg.py:30
#: terminal/models/component/endpoint.py:13 terminal/serializers/applet.py:17
#: xpack/plugins/cloud/manager.py:83
@@ -1596,7 +1605,7 @@ msgstr "云服务"
#: assets/const/category.py:14 assets/models/asset/gpt.py:11
#: assets/models/asset/web.py:16 audits/const.py:45
-#: terminal/models/applet/applet.py:27 users/const.py:64
+#: terminal/models/applet/applet.py:28 users/const.py:64
msgid "Web"
msgstr "Web"
@@ -1616,7 +1625,7 @@ msgstr "私有云"
msgid "Kubernetes"
msgstr "Kubernetes"
-#: assets/const/device.py:7 terminal/models/applet/applet.py:26
+#: assets/const/device.py:7 terminal/models/applet/applet.py:27
#: tickets/const.py:9
msgid "General"
msgstr "一般"
@@ -1682,100 +1691,119 @@ msgid "Security"
msgstr "安全"
#: assets/const/protocol.py:83
-msgid "Security layer to use for the connection"
-msgstr "连接 RDP 使用的安全层"
+msgid ""
+"Security layer to use for the connection:
Any
Automatically select the "
+"security mode based on the security protocols supported by both the client "
+"and the server
RDP
Legacy RDP encryption. This mode is generally only "
+"used for older Windows servers or in cases where a standard Windows login "
+"screen is desired
TLS
RDP authentication and encryption implemented "
+"via TLS.
NLA
This mode uses TLS encryption and requires the username "
+"and password to be given in advance"
+msgstr ""
+"连接的安全层:
Any
根据客户端和服务器支持的安全协议自动选择安全模式"
+"
RDP
传统的 RDP 加密模式。通常仅用于较旧的 Windows 服务器或需要标准 "
+"Windows 登录屏幕的情况
TLS
通过 TLS 实现的 RDP 认证和加密
NLA
该"
+"模式使用 TLS 加密,并要求提前提供用户名和密码"
-#: assets/const/protocol.py:89
+#: assets/const/protocol.py:100
msgid "AD domain"
msgstr "AD 网域"
-#: assets/const/protocol.py:104
+#: assets/const/protocol.py:115
msgid "Username prompt"
msgstr "用户名提示"
-#: assets/const/protocol.py:105
+#: assets/const/protocol.py:116
msgid "We will send username when we see this prompt"
msgstr "当我们看到这个提示时,我们将发送用户名"
-#: assets/const/protocol.py:110
+#: assets/const/protocol.py:121
msgid "Password prompt"
msgstr "密码提示"
-#: assets/const/protocol.py:111
+#: assets/const/protocol.py:122
msgid "We will send password when we see this prompt"
msgstr "当我们看到这个提示时,我们将发送密码"
-#: assets/const/protocol.py:116
+#: assets/const/protocol.py:127
msgid "Success prompt"
msgstr "成功提示"
-#: assets/const/protocol.py:117
+#: assets/const/protocol.py:128
msgid "We will consider login success when we see this prompt"
msgstr "当我们看到这个提示时,我们将认为登录成功"
-#: assets/const/protocol.py:128 assets/models/asset/database.py:10
-#: settings/serializers/msg.py:48
+#: assets/const/protocol.py:139 assets/models/asset/database.py:10
+#: settings/serializers/msg.py:49
msgid "Use SSL"
msgstr "使用 SSL"
-#: assets/const/protocol.py:163
+#: assets/const/protocol.py:174
msgid "SYSDBA"
msgstr "SYSDBA"
-#: assets/const/protocol.py:164
+#: assets/const/protocol.py:175
msgid "Connect as SYSDBA"
msgstr "以 SYSDBA 角色连接"
-#: assets/const/protocol.py:179
+#: assets/const/protocol.py:190
msgid ""
"SQL Server version, Different versions have different connection drivers"
msgstr "SQL Server 版本,不同版本有不同的连接驱动"
-#: assets/const/protocol.py:209
+#: assets/const/protocol.py:220
msgid "Auth source"
msgstr "认证数据库"
-#: assets/const/protocol.py:210
+#: assets/const/protocol.py:221
msgid "The database to authenticate against"
msgstr "要进行身份验证的数据库"
-#: assets/const/protocol.py:222
+#: assets/const/protocol.py:226 authentication/models/connection_token.py:43
+msgid "Connect options"
+msgstr "连接项"
+
+#: assets/const/protocol.py:227
+msgid "The connection specific options eg. retryWrites=false&retryReads=false"
+msgstr "连接特定选项,例如 retryWrites=false&retryReads=false"
+
+#: assets/const/protocol.py:239
msgid "Auth username"
msgstr "使用用户名认证"
-#: assets/const/protocol.py:245
+#: assets/const/protocol.py:262
msgid "Safe mode"
msgstr "安全模式"
-#: assets/const/protocol.py:247
+#: assets/const/protocol.py:264
msgid ""
"When safe mode is enabled, some operations will be disabled, such as: New "
"tab, right click, visit other website, etc."
msgstr ""
"当安全模式启用时,一些操作将被禁用,例如:新建标签页、右键、访问其它网站 等"
-#: assets/const/protocol.py:252 assets/models/asset/web.py:9
+#: assets/const/protocol.py:269 assets/models/asset/web.py:9
#: assets/serializers/asset/info/spec.py:16
msgid "Autofill"
msgstr "自动代填"
-#: assets/const/protocol.py:260 assets/models/asset/web.py:10
+#: assets/const/protocol.py:277 assets/models/asset/web.py:10
msgid "Username selector"
msgstr "用户名选择器"
-#: assets/const/protocol.py:265 assets/models/asset/web.py:11
+#: assets/const/protocol.py:282 assets/models/asset/web.py:11
msgid "Password selector"
msgstr "密码选择器"
-#: assets/const/protocol.py:270 assets/models/asset/web.py:12
+#: assets/const/protocol.py:287 assets/models/asset/web.py:12
msgid "Submit selector"
msgstr "确认按钮选择器"
-#: assets/const/protocol.py:293
+#: assets/const/protocol.py:310
msgid "API mode"
msgstr "API 模式"
-#: assets/const/types.py:251
+#: assets/const/types.py:248
msgid "All types"
msgstr "所有类型"
@@ -1792,7 +1820,7 @@ msgid "Cloud"
msgstr "云服务"
#: assets/models/asset/common.py:94 assets/models/platform.py:16
-#: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:77
+#: settings/serializers/auth/radius.py:18 settings/serializers/auth/sms.py:77
#: settings/serializers/msg.py:31 terminal/serializers/storage.py:133
#: xpack/plugins/cloud/serializers/account_attrs.py:73
msgid "Port"
@@ -1803,10 +1831,10 @@ msgstr "端口"
msgid "Address"
msgstr "地址"
-#: assets/models/asset/common.py:161 assets/models/platform.py:134
+#: assets/models/asset/common.py:161 assets/models/platform.py:149
#: authentication/backends/passkey/models.py:12
#: authentication/serializers/connect_token_secret.py:118
-#: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:373
+#: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:385
msgid "Platform"
msgstr "平台"
@@ -1859,13 +1887,13 @@ msgstr "客户端密钥"
msgid "Allow invalid cert"
msgstr "忽略证书校验"
-#: assets/models/asset/gpt.py:8 settings/serializers/feature.py:87
+#: assets/models/asset/gpt.py:8 settings/serializers/feature.py:89
msgid "Proxy"
msgstr "代理"
#: assets/models/automations/base.py:18 assets/models/cmd_filter.py:32
#: assets/models/node.py:553 perms/models/asset_permission.py:72
-#: tickets/models/ticket/apply_asset.py:14 xpack/plugins/cloud/models.py:374
+#: tickets/models/ticket/apply_asset.py:14 xpack/plugins/cloud/models.py:386
msgid "Node"
msgstr "节点"
@@ -1886,7 +1914,7 @@ msgstr "资产自动化任务"
# msgstr "备注"
#: assets/models/automations/base.py:114 assets/models/cmd_filter.py:41
#: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:241
-#: users/models/user.py:1171
+#: users/models/user/__init__.py:311
msgid "Date created"
msgstr "创建日期"
@@ -1907,17 +1935,17 @@ msgid "Date verified"
msgstr "校验日期"
#: assets/models/cmd_filter.py:28 perms/models/asset_permission.py:66
-#: users/models/group.py:25 users/models/user.py:907
+#: users/models/group.py:25 users/models/user/__init__.py:63
msgid "User group"
msgstr "用户组"
#: assets/models/cmd_filter.py:42 common/db/models.py:35
-#: users/models/user.py:983
+#: users/models/user/__init__.py:139
msgid "Date updated"
msgstr "更新日期"
#: assets/models/cmd_filter.py:44 assets/models/cmd_filter.py:91
-#: common/db/models.py:32 users/models/user.py:945
+#: common/db/models.py:32 users/models/user/__init__.py:101
#: users/serializers/group.py:32
msgid "Created by"
msgstr "创建者"
@@ -1954,7 +1982,7 @@ msgstr "收藏的资产"
msgid "Gateway"
msgstr "网关"
-#: assets/models/label.py:15 rbac/const.py:6 users/models/user.py:1150
+#: assets/models/label.py:15 rbac/const.py:6
msgid "System"
msgstr "系统"
@@ -1970,13 +1998,25 @@ msgstr "值"
#: assets/models/label.py:40 assets/serializers/cagegory.py:10
#: assets/serializers/cagegory.py:17 assets/serializers/cagegory.py:23
-#: assets/serializers/platform.py:153
+#: assets/serializers/platform.py:154
#: authentication/serializers/connect_token_secret.py:124
#: common/serializers/common.py:85 labels/serializers.py:45
-#: settings/serializers/msg.py:87
+#: settings/serializers/msg.py:90
msgid "Label"
msgstr "标签"
+#: assets/models/my_asset.py:12 assets/serializers/my_asset.py:16
+msgid "Custom Name"
+msgstr "自定义名称"
+
+#: assets/models/my_asset.py:13 assets/serializers/my_asset.py:17
+msgid "Custom Comment"
+msgstr "自定义备注"
+
+#: assets/models/my_asset.py:18 rbac/tree.py:54
+msgid "My assets"
+msgstr "我的资产"
+
#: assets/models/node.py:168
msgid "New node"
msgstr "新节点"
@@ -2009,7 +2049,7 @@ msgstr "主要的"
msgid "Required"
msgstr "必须的"
-#: assets/models/platform.py:19 assets/serializers/platform.py:155
+#: assets/models/platform.py:19 assets/serializers/platform.py:156
#: terminal/models/component/storage.py:28
#: xpack/plugins/cloud/providers/nutanix.py:30
msgid "Default"
@@ -2019,7 +2059,7 @@ msgstr "默认"
msgid "Public"
msgstr "开放的"
-#: assets/models/platform.py:21 assets/serializers/platform.py:83
+#: assets/models/platform.py:21 assets/serializers/platform.py:84
#: settings/serializers/settings.py:95
#: users/templates/users/reset_password.html:29
msgid "Setting"
@@ -2027,7 +2067,7 @@ msgstr "设置"
#: assets/models/platform.py:38 audits/const.py:59
#: authentication/backends/passkey/models.py:11 settings/models.py:38
-#: terminal/serializers/applet_host.py:33 users/models/user.py:689
+#: terminal/serializers/applet_host.py:33 users/models/user/_auth.py:33
msgid "Enabled"
msgstr "启用"
@@ -2035,11 +2075,11 @@ msgstr "启用"
msgid "Ansible config"
msgstr "Ansible 配置"
-#: assets/models/platform.py:41 assets/serializers/platform.py:34
+#: assets/models/platform.py:41 assets/serializers/platform.py:35
msgid "Ping enabled"
msgstr "启用资产探活"
-#: assets/models/platform.py:42 assets/serializers/platform.py:35
+#: assets/models/platform.py:42 assets/serializers/platform.py:36
msgid "Ping method"
msgstr "资产探活方式"
@@ -2048,12 +2088,12 @@ msgid "Ping params"
msgstr "资产探活参数"
#: assets/models/platform.py:45 assets/models/platform.py:69
-#: assets/serializers/platform.py:37
+#: assets/serializers/platform.py:38
msgid "Gather facts enabled"
msgstr "启用收集资产信息"
#: assets/models/platform.py:47 assets/models/platform.py:71
-#: assets/serializers/platform.py:41
+#: assets/serializers/platform.py:42
msgid "Gather facts method"
msgstr "收集信息方式"
@@ -2061,11 +2101,11 @@ msgstr "收集信息方式"
msgid "Gather facts params"
msgstr "收集信息参数"
-#: assets/models/platform.py:51 assets/serializers/platform.py:51
+#: assets/models/platform.py:51 assets/serializers/platform.py:52
msgid "Change secret enabled"
msgstr "启用改密"
-#: assets/models/platform.py:53 assets/serializers/platform.py:55
+#: assets/models/platform.py:53 assets/serializers/platform.py:56
msgid "Change secret method"
msgstr "改密方式"
@@ -2073,11 +2113,11 @@ msgstr "改密方式"
msgid "Change secret params"
msgstr "改密参数"
-#: assets/models/platform.py:57 assets/serializers/platform.py:58
+#: assets/models/platform.py:57 assets/serializers/platform.py:59
msgid "Push account enabled"
msgstr "启用账号推送"
-#: assets/models/platform.py:59 assets/serializers/platform.py:62
+#: assets/models/platform.py:59 assets/serializers/platform.py:63
msgid "Push account method"
msgstr "账号推送方式"
@@ -2085,11 +2125,11 @@ msgstr "账号推送方式"
msgid "Push account params"
msgstr "账号推送参数"
-#: assets/models/platform.py:63 assets/serializers/platform.py:44
+#: assets/models/platform.py:63 assets/serializers/platform.py:45
msgid "Verify account enabled"
msgstr "开启账号验证"
-#: assets/models/platform.py:65 assets/serializers/platform.py:48
+#: assets/models/platform.py:65 assets/serializers/platform.py:49
msgid "Verify account method"
msgstr "账号验证方式"
@@ -2101,7 +2141,7 @@ msgstr "账号验证参数"
msgid "Remove account enabled"
msgstr "开启账号移除"
-#: assets/models/platform.py:77 assets/serializers/platform.py:72
+#: assets/models/platform.py:77 assets/serializers/platform.py:73
msgid "Remove account method"
msgstr "账号移除方式"
@@ -2109,7 +2149,7 @@ msgstr "账号移除方式"
msgid "Remove account params"
msgstr "账号移除参数"
-#: assets/models/platform.py:97 tickets/models/ticket/general.py:298
+#: assets/models/platform.py:97 tickets/models/ticket/general.py:301
msgid "Meta"
msgstr "元数据"
@@ -2117,23 +2157,23 @@ msgstr "元数据"
msgid "Internal"
msgstr "内置"
-#: assets/models/platform.py:102 assets/serializers/platform.py:172
+#: assets/models/platform.py:102 assets/serializers/platform.py:166
msgid "Charset"
msgstr "编码"
-#: assets/models/platform.py:104 assets/serializers/platform.py:207
+#: assets/models/platform.py:104 assets/serializers/platform.py:204
msgid "Gateway enabled"
msgstr "启用网域"
-#: assets/models/platform.py:106 assets/serializers/platform.py:200
+#: assets/models/platform.py:106 assets/serializers/platform.py:197
msgid "Su enabled"
msgstr "启用账号切换"
-#: assets/models/platform.py:107 assets/serializers/platform.py:178
+#: assets/models/platform.py:107 assets/serializers/platform.py:172
msgid "Su method"
msgstr "账号切换方式"
-#: assets/models/platform.py:108 assets/serializers/platform.py:181
+#: assets/models/platform.py:108 assets/serializers/platform.py:175
msgid "Custom fields"
msgstr "自定义属性"
@@ -2148,12 +2188,12 @@ msgid ""
"type"
msgstr "资产中批量更新平台,不符合平台类型跳过的资产"
-#: assets/serializers/asset/common.py:127 assets/serializers/platform.py:175
+#: assets/serializers/asset/common.py:127 assets/serializers/platform.py:169
#: authentication/serializers/connect_token_secret.py:30
#: authentication/serializers/connect_token_secret.py:75
-#: perms/models/asset_permission.py:76 perms/serializers/permission.py:46
-#: perms/serializers/user_permission.py:74 xpack/plugins/cloud/models.py:376
-#: xpack/plugins/cloud/serializers/task.py:34
+#: perms/models/asset_permission.py:76 perms/serializers/permission.py:45
+#: perms/serializers/user_permission.py:74 xpack/plugins/cloud/models.py:388
+#: xpack/plugins/cloud/serializers/task.py:35
msgid "Protocols"
msgstr "协议组"
@@ -2212,7 +2252,7 @@ msgid "Model"
msgstr "型号"
#: assets/serializers/asset/info/gathered.py:8
-#: tickets/models/ticket/general.py:297
+#: tickets/models/ticket/general.py:300
msgid "Serial number"
msgstr "序列号"
@@ -2267,8 +2307,8 @@ msgid ""
"the zone, the connection is routed through the gateway."
msgstr "网关是网域的网络代理,当连接网域内的资产时,连接将通过网关进行路由。"
-#: assets/serializers/domain.py:24 orgs/serializers.py:13
-#: perms/serializers/permission.py:40
+#: assets/serializers/domain.py:24 assets/serializers/platform.py:177
+#: orgs/serializers.py:13 perms/serializers/permission.py:39
msgid "Assets amount"
msgstr "资产数量"
@@ -2284,83 +2324,83 @@ msgstr "值"
msgid "Can't contains: /"
msgstr "不能包含: /"
-#: assets/serializers/platform.py:34
+#: assets/serializers/platform.py:35
msgid "Enable asset detection"
msgstr "启用资产探活"
-#: assets/serializers/platform.py:38
+#: assets/serializers/platform.py:39
msgid "Enable asset information collection"
msgstr "启用收集资产信息"
-#: assets/serializers/platform.py:45
+#: assets/serializers/platform.py:46
msgid "Enable account verification"
msgstr "开启账号验证"
-#: assets/serializers/platform.py:52
+#: assets/serializers/platform.py:53
msgid "Enable account secret auto change"
msgstr "启用改密"
-#: assets/serializers/platform.py:59
+#: assets/serializers/platform.py:60
msgid "Enable account auto push"
msgstr "启用账号推送"
-#: assets/serializers/platform.py:65
+#: assets/serializers/platform.py:66
msgid "Gather accounts enabled"
msgstr "启用账号收集"
-#: assets/serializers/platform.py:66
+#: assets/serializers/platform.py:67
msgid "Enable account collection"
msgstr "自动化收集账号"
-#: assets/serializers/platform.py:69
+#: assets/serializers/platform.py:70
msgid "Gather accounts method"
msgstr "收集账号方式"
-#: assets/serializers/platform.py:75
+#: assets/serializers/platform.py:76
msgid "Remove accounts enabled"
msgstr "开启账号移除"
-#: assets/serializers/platform.py:76
+#: assets/serializers/platform.py:77
msgid "Enable account remove"
msgstr "启动账号移除"
-#: assets/serializers/platform.py:84
+#: assets/serializers/platform.py:85
msgid "Port from addr"
msgstr "端口来自地址"
-#: assets/serializers/platform.py:96
+#: assets/serializers/platform.py:97
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:101
+#: assets/serializers/platform.py:102
msgid "This protocol is required, and it must be set when adding assets."
msgstr "该协议是必填的,添加资产时必须设置"
-#: assets/serializers/platform.py:104
+#: assets/serializers/platform.py:105
msgid ""
"This protocol is default, when adding assets, it will be displayed by "
"default."
msgstr "该协议是默认的,添加资产时,将默认显示"
-#: assets/serializers/platform.py:107
+#: assets/serializers/platform.py:108
msgid "This protocol is public, asset will show this protocol to user"
msgstr "该协议是公开的,资产将向用户显示该协议并可以连接使用"
-#: assets/serializers/platform.py:156
+#: assets/serializers/platform.py:157
msgid "Help text"
msgstr "帮助"
-#: assets/serializers/platform.py:157
+#: assets/serializers/platform.py:158
msgid "Choices"
msgstr "选择"
-#: assets/serializers/platform.py:176
+#: assets/serializers/platform.py:170
msgid "Automation"
msgstr "自动化"
-#: assets/serializers/platform.py:202
+#: assets/serializers/platform.py:199
msgid ""
"Login with account when accessing assets, then automatically switch to "
"another, similar to logging in with a regular account and then switching to "
@@ -2369,19 +2409,19 @@ msgstr ""
"在访问资产时使用账户登录,然后自动切换到另一个账户,就像用普通账户登录然后切"
"换到 root 一样"
-#: assets/serializers/platform.py:208
+#: assets/serializers/platform.py:205
msgid "Assets can be connected using a zone gateway"
msgstr "资产可以使用区域网关进行连接"
-#: assets/serializers/platform.py:210
+#: assets/serializers/platform.py:207
msgid "Default Domain"
msgstr "默认网域"
-#: assets/serializers/platform.py:231
+#: assets/serializers/platform.py:229
msgid "type is required"
msgstr "类型 该字段是必填项。"
-#: assets/serializers/platform.py:246
+#: assets/serializers/platform.py:244
msgid "Protocols is required"
msgstr "协议是必填的"
@@ -2516,8 +2556,8 @@ msgstr "创建"
msgid "Connect"
msgstr "连接"
-#: audits/const.py:30 authentication/templates/authentication/login.html:290
-#: authentication/templates/authentication/login.html:362
+#: audits/const.py:30 authentication/templates/authentication/login.html:329
+#: authentication/templates/authentication/login.html:401
#: templates/_header_bar.html:101
msgid "Login"
msgstr "登录"
@@ -2576,11 +2616,11 @@ msgstr "任务"
msgid "-"
msgstr "-"
-#: audits/handler.py:116
+#: audits/handler.py:128
msgid "Yes"
msgstr "是"
-#: audits/handler.py:116
+#: audits/handler.py:128
msgid "No"
msgstr "否"
@@ -2667,8 +2707,8 @@ msgstr "登录 IP"
#: audits/models.py:200 audits/serializers.py:52
#: authentication/templates/authentication/_mfa_confirm_modal.html:14
-#: users/forms/profile.py:63 users/models/user.py:923
-#: users/serializers/profile.py:97
+#: users/forms/profile.py:63 users/models/user/__init__.py:79
+#: users/serializers/profile.py:70
msgid "MFA"
msgstr "MFA"
@@ -2715,7 +2755,7 @@ msgstr "原因描述"
#: audits/serializers.py:70 audits/serializers.py:184
msgid "Auth backend display"
-msgstr "没有匹配到认证后端"
+msgstr "认证方式"
#: audits/serializers.py:134
#, python-format
@@ -2725,7 +2765,7 @@ msgstr "用户 %s %s 了当前资源"
#: audits/serializers.py:172 authentication/models/connection_token.py:47
#: authentication/models/temp_token.py:13 perms/models/asset_permission.py:80
#: tickets/models/ticket/apply_application.py:31
-#: tickets/models/ticket/apply_asset.py:20 users/models/user.py:942
+#: tickets/models/ticket/apply_asset.py:20 users/models/user/__init__.py:98
msgid "Date expired"
msgstr "失效日期"
@@ -2758,30 +2798,30 @@ msgstr "认证令牌"
#: audits/signal_handlers/login_log.py:37 authentication/notifications.py:73
#: authentication/views/login.py:78 notifications/backends/__init__.py:11
-#: settings/serializers/auth/wecom.py:10 settings/serializers/auth/wecom.py:15
-#: users/models/user.py:798 users/models/user.py:966
+#: settings/serializers/auth/wecom.py:11 settings/serializers/auth/wecom.py:16
+#: users/models/user/__init__.py:122 users/models/user/_source.py:18
msgid "WeCom"
msgstr "企业微信"
-#: audits/signal_handlers/login_log.py:38 authentication/views/feishu.py:105
+#: audits/signal_handlers/login_log.py:38 authentication/views/feishu.py:97
#: authentication/views/login.py:90 notifications/backends/__init__.py:14
-#: settings/serializers/auth/feishu.py:10
-#: settings/serializers/auth/feishu.py:12 users/models/user.py:800
-#: users/models/user.py:972
+#: settings/serializers/auth/feishu.py:12
+#: settings/serializers/auth/feishu.py:14 users/models/user/__init__.py:128
+#: users/models/user/_source.py:20
msgid "FeiShu"
msgstr "飞书"
#: audits/signal_handlers/login_log.py:40 authentication/views/login.py:102
-#: authentication/views/slack.py:87 notifications/backends/__init__.py:16
-#: settings/serializers/auth/slack.py:10 settings/serializers/auth/slack.py:12
-#: users/models/user.py:802 users/models/user.py:978
+#: authentication/views/slack.py:79 notifications/backends/__init__.py:16
+#: settings/serializers/auth/slack.py:11 settings/serializers/auth/slack.py:13
+#: users/models/user/__init__.py:134 users/models/user/_source.py:22
msgid "Slack"
msgstr "Slack"
-#: audits/signal_handlers/login_log.py:41 authentication/views/dingtalk.py:159
+#: audits/signal_handlers/login_log.py:41 authentication/views/dingtalk.py:151
#: authentication/views/login.py:84 notifications/backends/__init__.py:12
-#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:799
-#: users/models/user.py:969
+#: settings/serializers/auth/dingtalk.py:11 users/models/user/__init__.py:125
+#: users/models/user/_source.py:19
msgid "DingTalk"
msgstr "钉钉"
@@ -2796,11 +2836,11 @@ msgstr "临时密码"
msgid "Passkey"
msgstr "Passkey"
-#: audits/tasks.py:130
+#: audits/tasks.py:131
msgid "Clean audits session task log"
msgstr "清理资产审计会话任务日志"
-#: audits/tasks.py:143
+#: audits/tasks.py:145
msgid "Upload FTP file to external storage"
msgstr "上传 FTP 文件到外部存储"
@@ -2861,7 +2901,7 @@ msgid ""
msgstr "用户来自 {} 请去相应系统修改密码"
#: authentication/api/password.py:65
-#: authentication/templates/authentication/login.html:354
+#: authentication/templates/authentication/login.html:393
#: users/templates/users/forgot_password.html:41
#: users/templates/users/forgot_password.html:42
#: users/templates/users/forgot_password_previewing.html:13
@@ -2913,7 +2953,7 @@ msgstr "附加"
#: authentication/backends/passkey/models.py:14
#: authentication/models/access_key.py:26
-#: authentication/models/private_token.py:8
+#: authentication/models/private_token.py:8 authentication/models/ssh_key.py:20
msgid "Date last used"
msgstr "最后使用日期"
@@ -3043,7 +3083,7 @@ msgstr "请输入 MFA 验证码"
msgid "Please enter SMS code"
msgstr "请输入短信验证码"
-#: authentication/errors/failed.py:164 users/exceptions.py:15
+#: authentication/errors/failed.py:164 users/exceptions.py:14
msgid "Phone not set"
msgstr "手机号没有设置"
@@ -3051,21 +3091,21 @@ msgstr "手机号没有设置"
msgid "SSO auth closed"
msgstr "SSO 认证关闭了"
-#: authentication/errors/mfa.py:18 authentication/views/wecom.py:59
+#: authentication/errors/mfa.py:18 authentication/views/wecom.py:51
msgid "WeCom is already bound"
msgstr "企业微信已经绑定"
-#: authentication/errors/mfa.py:23 authentication/views/wecom.py:159
-#: authentication/views/wecom.py:201
+#: authentication/errors/mfa.py:23 authentication/views/wecom.py:151
+#: authentication/views/wecom.py:193
msgid "WeCom is not bound"
msgstr "没有绑定企业微信"
-#: authentication/errors/mfa.py:28 authentication/views/dingtalk.py:211
-#: authentication/views/dingtalk.py:253
+#: authentication/errors/mfa.py:28 authentication/views/dingtalk.py:203
+#: authentication/views/dingtalk.py:245
msgid "DingTalk is not bound"
msgstr "钉钉没有绑定"
-#: authentication/errors/mfa.py:33 authentication/views/feishu.py:138
+#: authentication/errors/mfa.py:33 authentication/views/feishu.py:130
msgid "FeiShu is not bound"
msgstr "没有绑定飞书"
@@ -3073,7 +3113,7 @@ msgstr "没有绑定飞书"
msgid "Lark is not bound"
msgstr "Lark 没有绑定"
-#: authentication/errors/mfa.py:43 authentication/views/slack.py:127
+#: authentication/errors/mfa.py:43 authentication/views/slack.py:119
msgid "Slack is not bound"
msgstr "Slack 没有绑定"
@@ -3235,7 +3275,7 @@ msgstr "自定义密码"
#: authentication/models/connection_token.py:41
#: authentication/serializers/connect_token_secret.py:114
-#: settings/serializers/msg.py:28 terminal/models/applet/applet.py:42
+#: settings/serializers/msg.py:28 terminal/models/applet/applet.py:43
#: terminal/models/virtualapp/virtualapp.py:24
#: terminal/serializers/session.py:21 terminal/serializers/session.py:48
#: terminal/serializers/storage.py:71
@@ -3246,10 +3286,6 @@ msgstr "协议"
msgid "Connect method"
msgstr "连接方式"
-#: authentication/models/connection_token.py:43
-msgid "Connect options"
-msgstr "连接项"
-
#: authentication/models/connection_token.py:44
msgid "User display"
msgstr "用户名称"
@@ -3307,6 +3343,18 @@ msgstr "超级连接令牌"
msgid "Private Token"
msgstr "私有令牌"
+#: authentication/models/ssh_key.py:15 terminal/serializers/storage.py:146
+#: users/models/user/__init__.py:86
+#: xpack/plugins/cloud/serializers/account_attrs.py:213
+msgid "Private key"
+msgstr "ssh私钥"
+
+#: authentication/models/ssh_key.py:18 settings/serializers/terminal.py:34
+#: users/forms/profile.py:172 users/models/user/__init__.py:89
+#: xpack/plugins/cloud/serializers/account_attrs.py:210
+msgid "Public key"
+msgstr "SSH公钥"
+
#: authentication/models/sso_token.py:15
msgid "Expired"
msgstr "过期时间"
@@ -3336,12 +3384,12 @@ msgid "Options"
msgstr "选项"
#: authentication/serializers/connect_token_secret.py:127
-#: ops/notifications.py:18 rbac/tree.py:60
+#: ops/notifications.py:19 rbac/tree.py:60
msgid "Component"
msgstr "组件"
#: authentication/serializers/connect_token_secret.py:136
-#: perms/serializers/user_permission.py:28 xpack/plugins/cloud/models.py:375
+#: perms/serializers/user_permission.py:28 xpack/plugins/cloud/models.py:387
msgid "Domain"
msgstr "网域"
@@ -3380,22 +3428,50 @@ msgid "Actions"
msgstr "动作"
#: authentication/serializers/connection_token.py:42
-#: perms/serializers/permission.py:44 perms/serializers/permission.py:65
+#: perms/serializers/permission.py:43 perms/serializers/permission.py:64
#: users/serializers/user.py:127 users/serializers/user.py:273
msgid "Is expired"
msgstr "已过期"
+#: authentication/serializers/connection_token.py:43
+#: orgs/mixins/serializers.py:26 rbac/serializers/rolebinding.py:27
+msgid "Org name"
+msgstr "组织名称"
+
#: authentication/serializers/password_mfa.py:29
#: users/templates/users/forgot_password.html:153
msgid "The {} cannot be empty"
msgstr "{} 不能为空"
+#: authentication/serializers/ssh_key.py:17
+msgid "Automatically Generate Key Pair"
+msgstr "自动创建密钥对"
+
+#: authentication/serializers/ssh_key.py:19
+msgid "Import Existing Key Pair"
+msgstr "导入已有密钥对"
+
+#: authentication/serializers/ssh_key.py:31
+msgid "Create Type"
+msgstr "创建类型"
+
+#: authentication/serializers/ssh_key.py:33
+msgid ""
+"Please download the private key after creation. Each private key can only be "
+"downloaded once"
+msgstr "创建完成后请下载私钥,每个私钥只有一次下载机会"
+
+#: authentication/serializers/ssh_key.py:57 users/forms/profile.py:161
+#: users/serializers/profile.py:133 users/serializers/profile.py:160
+msgid "Not a valid ssh public key"
+msgstr "SSH密钥不合法"
+
#: authentication/serializers/token.py:22
msgid "Access IP"
msgstr "IP 白名单"
-#: authentication/serializers/token.py:92 perms/serializers/permission.py:43
-#: perms/serializers/permission.py:66 users/serializers/user.py:128
+#: authentication/serializers/token.py:92 perms/serializers/permission.py:42
+#: perms/serializers/permission.py:65 users/serializers/user.py:128
#: users/serializers/user.py:270
msgid "Is valid"
msgstr "是否有效"
@@ -3463,7 +3539,7 @@ msgstr "代码错误"
#: authentication/templates/authentication/_msg_oauth_bind.html:3
#: authentication/templates/authentication/_msg_reset_password.html:3
#: authentication/templates/authentication/_msg_reset_password_code.html:9
-#: jumpserver/conf.py:465
+#: jumpserver/conf.py:502
#: perms/templates/perms/_msg_item_permissions_expire.html:3
#: tickets/templates/tickets/approve_check_password.html:32
#: users/templates/users/_msg_account_expire_reminder.html:4
@@ -3561,17 +3637,17 @@ msgstr "如果这次公钥更新不是由你发起的,那么你的账号可能
msgid "Cancel"
msgstr "取消"
-#: authentication/templates/authentication/login.html:270
+#: authentication/templates/authentication/login.html:308
msgid ""
"Configuration file has problems and cannot be logged in. Please contact the "
"administrator or view latest docs"
msgstr "配置文件有问题,无法登录,请联系管理员或查看最新文档"
-#: authentication/templates/authentication/login.html:271
+#: authentication/templates/authentication/login.html:309
msgid "If you are administrator, you can update the config resolve it, set"
msgstr "如果你是管理员,可以更新配置文件解决,设置配置项"
-#: authentication/templates/authentication/login.html:369
+#: authentication/templates/authentication/login.html:408
msgid "More login options"
msgstr "其他方式登录"
@@ -3622,22 +3698,22 @@ msgstr "是否重试 ?"
msgid "LAN"
msgstr "局域网"
-#: authentication/views/base.py:73
+#: authentication/views/base.py:71
#: perms/templates/perms/_msg_permed_items_expire.html:21
msgid "If you have any question, please contact the administrator"
msgstr "如果有疑问或需求,请联系系统管理员"
-#: authentication/views/base.py:146
+#: authentication/views/base.py:141
#, python-format
msgid "%s query user failed"
msgstr "%s 查询用户失败"
-#: authentication/views/base.py:155
+#: authentication/views/base.py:149
#, python-format
msgid "The %s is already bound to another user"
msgstr "%s 已绑定到另一个用户"
-#: authentication/views/base.py:162
+#: authentication/views/base.py:155
#, python-format
msgid "Binding %s successfully"
msgstr "绑定 %s 成功"
@@ -3646,45 +3722,39 @@ msgstr "绑定 %s 成功"
msgid "DingTalk Error, Please contact your system administrator"
msgstr "钉钉错误,请联系系统管理员"
-#: authentication/views/dingtalk.py:45 authentication/views/dingtalk.py:210
+#: authentication/views/dingtalk.py:45 authentication/views/dingtalk.py:202
msgid "DingTalk Error"
msgstr "钉钉错误"
-#: authentication/views/dingtalk.py:57 authentication/views/feishu.py:68
-#: authentication/views/slack.py:47 authentication/views/wecom.py:55
-msgid ""
-"The system configuration is incorrect. Please contact your administrator"
-msgstr "企业配置错误,请联系系统管理员"
-
-#: authentication/views/dingtalk.py:61
+#: authentication/views/dingtalk.py:53
msgid "DingTalk is already bound"
msgstr "钉钉已经绑定"
-#: authentication/views/dingtalk.py:130
+#: authentication/views/dingtalk.py:122
msgid "Invalid user_id"
msgstr "无效的 user_id"
-#: authentication/views/dingtalk.py:146
+#: authentication/views/dingtalk.py:138
msgid "DingTalk query user failed"
msgstr "钉钉查询用户失败"
-#: authentication/views/dingtalk.py:154
+#: authentication/views/dingtalk.py:146
msgid "The DingTalk is already bound to another user"
msgstr "该钉钉已经绑定其他用户"
-#: authentication/views/dingtalk.py:160
+#: authentication/views/dingtalk.py:152
msgid "Binding DingTalk successfully"
msgstr "绑定 钉钉 成功"
-#: authentication/views/dingtalk.py:212 authentication/views/dingtalk.py:247
+#: authentication/views/dingtalk.py:204 authentication/views/dingtalk.py:239
msgid "Failed to get user from DingTalk"
msgstr "从钉钉获取用户失败"
-#: authentication/views/dingtalk.py:254
+#: authentication/views/dingtalk.py:246
msgid "Please login with a password and then bind the DingTalk"
msgstr "请使用密码登录,然后绑定钉钉"
-#: authentication/views/feishu.py:43 authentication/views/feishu.py:137
+#: authentication/views/feishu.py:43 authentication/views/feishu.py:129
msgid "FeiShu Error"
msgstr "飞书错误"
@@ -3692,7 +3762,7 @@ msgstr "飞书错误"
msgid "FeiShu is already bound"
msgstr "飞书已经绑定"
-#: authentication/views/feishu.py:139
+#: authentication/views/feishu.py:131
msgid "Failed to get user from FeiShu"
msgstr "从飞书获取用户失败"
@@ -3708,23 +3778,23 @@ msgstr "Lark 已经绑定"
msgid "Failed to get user from Lark"
msgstr "从 Lark 获取用户失败"
-#: authentication/views/login.py:221
+#: authentication/views/login.py:218
msgid "Redirecting"
msgstr "跳转中"
-#: authentication/views/login.py:222
+#: authentication/views/login.py:219
msgid "Redirecting to {} authentication"
msgstr "正在跳转到 {} 认证"
-#: authentication/views/login.py:245
+#: authentication/views/login.py:242
msgid "Login timeout, please try again."
msgstr "登录超时,请重新登录"
-#: authentication/views/login.py:290
+#: authentication/views/login.py:287
msgid "User email already exists ({})"
msgstr "用户邮箱已存在 ({})"
-#: authentication/views/login.py:367
+#: authentication/views/login.py:364
msgid ""
"Wait for {} confirm, You also can copy link to her/him
\n"
" Don't close this page"
@@ -3732,27 +3802,34 @@ msgstr ""
"等待 {} 确认, 你也可以复制链接发给他/她
\n"
" 不要关闭本页面"
-#: authentication/views/login.py:372
+#: authentication/views/login.py:369
msgid "No ticket found"
msgstr "没有发现工单"
-#: authentication/views/login.py:408
+#: authentication/views/login.py:405
msgid "Logout success"
msgstr "退出登录成功"
-#: authentication/views/login.py:409
+#: authentication/views/login.py:406
msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面"
-#: authentication/views/slack.py:35 authentication/views/slack.py:126
+#: authentication/views/mixins.py:39
+msgid ""
+"For your safety, automatic redirection login is not supported on the client. "
+"If you need to open it in the client, please log in again"
+msgstr ""
+"为了您的安全,客户端不支持自动跳转登录。如果需要在客户端中打开,请重新登录"
+
+#: authentication/views/slack.py:35 authentication/views/slack.py:118
msgid "Slack Error"
msgstr "Slack 错误"
-#: authentication/views/slack.py:63
+#: authentication/views/slack.py:55
msgid "Slack is already bound"
msgstr "Slack 已经绑定"
-#: authentication/views/slack.py:128
+#: authentication/views/slack.py:120
msgid "Failed to get user from Slack"
msgstr "从 Slack 获取用户失败"
@@ -3760,19 +3837,19 @@ msgstr "从 Slack 获取用户失败"
msgid "WeCom Error, Please contact your system administrator"
msgstr "企业微信错误,请联系系统管理员"
-#: authentication/views/wecom.py:43 authentication/views/wecom.py:158
+#: authentication/views/wecom.py:43 authentication/views/wecom.py:150
msgid "WeCom Error"
msgstr "企业微信错误"
-#: authentication/views/wecom.py:118
+#: authentication/views/wecom.py:110
msgid "Wecom"
msgstr "企业微信"
-#: authentication/views/wecom.py:160 authentication/views/wecom.py:195
+#: authentication/views/wecom.py:152 authentication/views/wecom.py:187
msgid "Failed to get user from WeCom"
msgstr "从企业微信获取用户失败"
-#: authentication/views/wecom.py:202
+#: authentication/views/wecom.py:194
msgid "Please login with a password and then bind the WeCom"
msgstr "请使用密码登录,然后绑定企业微信"
@@ -3780,27 +3857,31 @@ msgstr "请使用密码登录,然后绑定企业微信"
msgid "Request file format may be wrong"
msgstr "上传的文件格式错误 或 其它类型资源的文件"
-#: common/const/choices.py:10
+#: common/const/choices.py:40
+msgid "China"
+msgstr "中国"
+
+#: common/const/choices.py:57
msgid "Manual trigger"
msgstr "手动触发"
-#: common/const/choices.py:11
+#: common/const/choices.py:58
msgid "Timing trigger"
msgstr "定时触发"
-#: common/const/choices.py:15
+#: common/const/choices.py:62
msgid "Ready"
msgstr "准备"
-#: common/const/choices.py:17 ops/const.py:73
+#: common/const/choices.py:64 ops/const.py:73
msgid "Running"
msgstr "运行中"
-#: common/const/choices.py:21
+#: common/const/choices.py:68
msgid "Canceled"
msgstr "取消"
-#: common/const/common.py:5 xpack/plugins/cloud/manager.py:409
+#: common/const/common.py:5 xpack/plugins/cloud/manager.py:412
#, python-format
msgid "%(name)s was created successfully"
msgstr "%(name)s 创建成功"
@@ -3814,35 +3895,35 @@ msgstr "%(name)s 更新成功"
msgid "gettext_lazy"
msgstr "gettext_lazy"
-#: common/db/fields.py:106
+#: common/db/fields.py:105
msgid "Marshal dict data to char field"
msgstr "编码 dict 为 char"
-#: common/db/fields.py:110
+#: common/db/fields.py:109
msgid "Marshal dict data to text field"
msgstr "编码 dict 为 text"
-#: common/db/fields.py:122
+#: common/db/fields.py:121
msgid "Marshal list data to char field"
msgstr "编码 list 为 char"
-#: common/db/fields.py:126
+#: common/db/fields.py:125
msgid "Marshal list data to text field"
msgstr "编码 list 为 text"
-#: common/db/fields.py:130
+#: common/db/fields.py:129
msgid "Marshal data to char field"
msgstr "编码数据为 char"
-#: common/db/fields.py:134
+#: common/db/fields.py:133
msgid "Marshal data to text field"
msgstr "编码数据为 text"
-#: common/db/fields.py:167
+#: common/db/fields.py:166
msgid "Encrypt field using Secret Key"
msgstr "加密的字段"
-#: common/db/fields.py:582
+#: common/db/fields.py:577
msgid ""
"Invalid JSON data for JSONManyToManyField, should be like {'type': 'all'} or "
"{'type': 'ids', 'ids': []} or {'type': 'attrs', 'attrs': [{'name': 'ip', "
@@ -3852,27 +3933,27 @@ msgstr ""
"{'type': 'attrs', 'attrs': [{'name': 'ip', 'match': 'exact', 'value': "
"'1.1.1.1'}}"
-#: common/db/fields.py:589
+#: common/db/fields.py:584
msgid "Invalid type, should be \"all\", \"ids\" or \"attrs\""
msgstr "无效类型,应为 all、ids 或 attrs"
-#: common/db/fields.py:592
+#: common/db/fields.py:587
msgid "Invalid ids for ids, should be a list"
msgstr "无效的ID,应为列表"
-#: common/db/fields.py:594 common/db/fields.py:599
-#: common/serializers/fields.py:147 tickets/serializers/ticket/common.py:58
+#: common/db/fields.py:589 common/db/fields.py:594
+#: common/serializers/fields.py:144 tickets/serializers/ticket/common.py:58
#: xpack/plugins/cloud/serializers/account_attrs.py:56
#: xpack/plugins/cloud/serializers/account_attrs.py:79
#: xpack/plugins/cloud/serializers/account_attrs.py:150
msgid "This field is required."
msgstr "该字段是必填项。"
-#: common/db/fields.py:597 common/db/fields.py:602
+#: common/db/fields.py:592 common/db/fields.py:597
msgid "Invalid attrs, should be a list of dict"
msgstr "无效的属性,应为dict列表"
-#: common/db/fields.py:604
+#: common/db/fields.py:599
msgid "Invalid attrs, should be has name and value"
msgstr "无效属性,应具有名称和值"
@@ -3884,7 +3965,7 @@ msgstr "忽略的"
msgid "discard time"
msgstr "忽略时间"
-#: common/db/models.py:33 users/models/user.py:948
+#: common/db/models.py:33 users/models/user/__init__.py:104
msgid "Updated by"
msgstr "最后更新者"
@@ -3918,7 +3999,7 @@ msgid ""
"information -> file encryption password to set the encryption password"
msgstr "{} - 未设置加密密码 - 请前往个人信息 -> 文件加密密码中设置加密密码"
-#: common/exceptions.py:15 xpack/plugins/cloud/ws.py:38
+#: common/exceptions.py:15 xpack/plugins/cloud/ws.py:37
#, python-format
msgid "%s object does not exist."
msgstr "%s对象不存在"
@@ -3965,11 +4046,11 @@ msgstr "连接失败:使用了自签名证书,请检查服务器证书配置
msgid "Network error, please contact system administrator"
msgstr "网络错误,请联系系统管理员"
-#: common/sdk/im/slack/__init__.py:77
+#: common/sdk/im/slack/__init__.py:78
msgid "Unknown error occur"
msgstr "发生未知错误"
-#: common/sdk/im/wecom/__init__.py:16
+#: common/sdk/im/wecom/__init__.py:17
msgid "WeCom error, please contact system administrator"
msgstr "企业微信错误,请联系系统管理员"
@@ -4042,36 +4123,36 @@ msgstr "节点"
msgid "File"
msgstr "文件"
-#: common/serializers/fields.py:140
+#: common/serializers/fields.py:137
msgid "Invalid data type"
msgstr "无效的数据"
-#: common/serializers/fields.py:148
+#: common/serializers/fields.py:145
#, python-brace-format
msgid "Invalid pk \"{pk_value}\" - object does not exist."
msgstr "错误的 pk \"{pk_value}\" - 对象不存在"
-#: common/serializers/fields.py:149
+#: common/serializers/fields.py:146
#, python-brace-format
msgid "Incorrect type. Expected pk value, received {data_type}."
msgstr "错误类型。期望 pk 值,收到 {data_type}。"
-#: common/serializers/fields.py:223
+#: common/serializers/fields.py:220
msgid "Invalid data type, should be list"
msgstr "错误的数据类型,应该是列表"
-#: common/serializers/fields.py:238
+#: common/serializers/fields.py:235
msgid "Invalid choice: {}"
msgstr "无效选项: {}"
-#: common/serializers/mixin.py:452 terminal/models/applet/applet.py:44
+#: common/serializers/mixin.py:452 terminal/models/applet/applet.py:45
#: terminal/models/virtualapp/virtualapp.py:29
msgid "Tags"
msgstr "标签"
# msgid "Labels"
# msgstr "标签管理"
-#: common/tasks.py:31 common/utils/verify_code.py:16
+#: common/tasks.py:31
msgid "Send email"
msgstr "发件邮件"
@@ -4091,11 +4172,15 @@ msgstr "无效 IP"
msgid "Invalid address"
msgstr "无效地址"
-#: common/utils/translate.py:45
+#: common/utils/translate.py:46
#, python-format
msgid "Hello %s"
msgstr "你好 %s"
+#: common/utils/verify_code.py:16
+msgid "Send SMS code"
+msgstr "发送短信验证码"
+
#: common/validators.py:16
msgid "Special char not allowed"
msgstr "不能包含特殊字符"
@@ -4108,16 +4193,16 @@ msgstr "不能包含特殊字符"
msgid "The mobile phone number format is incorrect"
msgstr "手机号格式不正确"
-#: jumpserver/conf.py:459
+#: jumpserver/conf.py:496
#, python-brace-format
msgid "The verification code is: {code}"
msgstr "验证码为: {code}"
-#: jumpserver/conf.py:464
+#: jumpserver/conf.py:501
msgid "Create account successfully"
msgstr "创建账号成功"
-#: jumpserver/conf.py:466
+#: jumpserver/conf.py:503
msgid "Your account has been created successfully"
msgstr "你的账号已创建成功"
@@ -4129,7 +4214,7 @@ msgstr "JumpServer 开源堡垒机"
msgid "Flower service unavailable, check it
"
msgstr "Flower 服务不可用,请检查"
-#: jumpserver/views/other.py:27
+#: jumpserver/views/other.py:28
msgid ""
"Luna is a separately deployed program, you need to deploy Luna, koko, "
"configure nginx for url distribution,
If you see this page, "
@@ -4138,11 +4223,11 @@ msgstr ""
"Luna是单独部署的一个程序,你需要部署luna,koko,
如果你看到了"
"这个页面,证明你访问的不是nginx监听的端口,祝你好运
"
-#: jumpserver/views/other.py:75
+#: jumpserver/views/other.py:76
msgid "Websocket server run on port: {}, you should proxy it on nginx"
msgstr "Websocket 服务运行在端口: {}, 请检查nginx是否代理是否设置"
-#: jumpserver/views/other.py:89
+#: jumpserver/views/other.py:90
msgid ""
"Koko is a separately deployed program, you need to deploy Koko, "
"configure nginx for url distribution,
If you see this page, "
@@ -4236,34 +4321,34 @@ msgstr "任务 {} 不存在"
msgid "Task {} args or kwargs error"
msgstr "任务 {} 执行参数错误"
-#: ops/api/job.py:81
+#: ops/api/job.py:83
#, python-brace-format
msgid ""
"Asset ({asset}) must have at least one of the following protocols added: "
"SSH, SFTP, or WinRM"
msgstr "资产({asset})至少要添加ssh,sftp,winrm其中一种协议"
-#: ops/api/job.py:82
+#: ops/api/job.py:84
#, python-brace-format
msgid "Asset ({asset}) authorization is missing SSH, SFTP, or WinRM protocol"
msgstr "资产({asset})授权缺少ssh,sftp或winrm协议"
-#: ops/api/job.py:83
+#: ops/api/job.py:85
#, python-brace-format
msgid "Asset ({asset}) authorization lacks upload permissions"
msgstr "资产({asset})授权缺少上传权限"
-#: ops/api/job.py:168
+#: ops/api/job.py:170
msgid "Duplicate file exists"
msgstr "存在同名文件"
-#: ops/api/job.py:173
+#: ops/api/job.py:175
#, python-brace-format
msgid ""
"File size exceeds maximum limit. Please select a file smaller than {limit}MB"
msgstr "文件大小超过最大限制。请选择小于 {limit}MB 的文件。"
-#: ops/api/job.py:237
+#: ops/api/job.py:244
msgid ""
"The task is being created and cannot be interrupted. Please try again later."
msgstr "正在创建任务,无法中断,请稍后重试。"
@@ -4272,27 +4357,27 @@ msgstr "正在创建任务,无法中断,请稍后重试。"
msgid "Currently playbook is being used in a job"
msgstr "当前 playbook 正在作业中使用"
-#: ops/api/playbook.py:96
+#: ops/api/playbook.py:97
msgid "Unsupported file content"
msgstr "不支持的文件内容"
-#: ops/api/playbook.py:98 ops/api/playbook.py:144 ops/api/playbook.py:192
+#: ops/api/playbook.py:99 ops/api/playbook.py:145 ops/api/playbook.py:193
msgid "Invalid file path"
msgstr "无效的文件路径"
-#: ops/api/playbook.py:170
+#: ops/api/playbook.py:171
msgid "This file can not be rename"
msgstr "该文件不能重命名"
-#: ops/api/playbook.py:189
+#: ops/api/playbook.py:190
msgid "File already exists"
msgstr "文件已存在"
-#: ops/api/playbook.py:207
+#: ops/api/playbook.py:208
msgid "File key is required"
msgstr "文件密钥该字段是必填项。"
-#: ops/api/playbook.py:210
+#: ops/api/playbook.py:211
msgid "This file can not be delete"
msgstr "无法删除此文件"
@@ -4332,7 +4417,7 @@ msgstr "空白"
msgid "VCS"
msgstr "VCS"
-#: ops/const.py:38 ops/models/adhoc.py:44 settings/serializers/feature.py:135
+#: ops/const.py:38 ops/models/adhoc.py:44 settings/serializers/feature.py:120
msgid "Adhoc"
msgstr "命令"
@@ -4396,21 +4481,25 @@ msgstr "Oracle"
msgid "Timeout"
msgstr "超时"
+#: ops/const.py:82
+msgid "Command execution disabled"
+msgstr "命令执行已禁用"
+
#: ops/exception.py:6
msgid "no valid program entry found."
msgstr "没有可用程序入口"
-#: ops/mixin.py:23 ops/mixin.py:102 settings/serializers/auth/ldap.py:74
+#: ops/mixin.py:23 ops/mixin.py:102 settings/serializers/auth/ldap.py:72
msgid "Periodic run"
msgstr "周期执行"
#: ops/mixin.py:25 ops/mixin.py:88 ops/mixin.py:108
-#: settings/serializers/auth/ldap.py:81
+#: settings/serializers/auth/ldap.py:79
msgid "Interval"
msgstr "间隔"
#: ops/mixin.py:28 ops/mixin.py:86 ops/mixin.py:105
-#: settings/serializers/auth/ldap.py:78
+#: settings/serializers/auth/ldap.py:76
msgid "Crontab"
msgstr "Crontab"
@@ -4456,7 +4545,7 @@ msgid "Date last run"
msgstr "最后运行日期"
#: ops/models/base.py:51 ops/models/job.py:238
-#: xpack/plugins/cloud/models.py:222
+#: xpack/plugins/cloud/models.py:223
msgid "Result"
msgstr "结果"
@@ -4513,7 +4602,8 @@ msgstr "运行用户"
msgid "Run as policy"
msgstr "用户策略"
-#: ops/models/job.py:222 terminal/notifications.py:174
+#: ops/models/job.py:222 ops/serializers/job.py:92
+#: terminal/notifications.py:174
msgid "Job"
msgstr "作业"
@@ -4525,7 +4615,7 @@ msgstr "Material"
msgid "Material Type"
msgstr "Material 类型"
-#: ops/models/job.py:545
+#: ops/models/job.py:548
msgid "Job Execution"
msgstr "作业执行"
@@ -4537,30 +4627,30 @@ msgstr "创建方式"
msgid "VCS URL"
msgstr "VCS URL"
-#: ops/notifications.py:19
+#: ops/notifications.py:20
msgid "Server performance"
msgstr "监控告警"
-#: ops/notifications.py:25
+#: ops/notifications.py:26
msgid "Component health check warning"
msgstr "组件健康状况检查警告"
-#: ops/notifications.py:70
+#: ops/notifications.py:71
#, python-brace-format
msgid "The component is offline: {name}"
msgstr "组件已离线: {name}"
-#: ops/notifications.py:75
+#: ops/notifications.py:76
#, python-brace-format
msgid "Disk used more than {max_threshold}%: => {value}"
msgstr "硬盘使用率超过 {max_threshold}%: => {value}"
-#: ops/notifications.py:80
+#: ops/notifications.py:81
#, python-brace-format
msgid "Memory used more than {max_threshold}%: => {value}"
msgstr "内存使用率超过 {max_threshold}%: => {value}"
-#: ops/notifications.py:85
+#: ops/notifications.py:86
#, python-brace-format
msgid "CPU load more than {max_threshold}: => {value}"
msgstr "CPU 使用率超过 {max_threshold}: => {value}"
@@ -4589,7 +4679,11 @@ msgstr "任务类型"
msgid "Is finished"
msgstr "是否完成"
-#: ops/serializers/job.py:90
+#: ops/serializers/job.py:89
+msgid "Task id"
+msgstr "任务 ID"
+
+#: ops/serializers/job.py:98
msgid "You do not have permission for the current job."
msgstr "你没有当前作业的权限。"
@@ -4685,17 +4779,13 @@ msgstr "请选择一个组织后再保存"
#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:91
#: rbac/const.py:7 rbac/models/rolebinding.py:56
-#: rbac/serializers/rolebinding.py:44 settings/serializers/auth/ldap.py:71
+#: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:52
#: terminal/templates/terminal/_msg_command_warning.html:21
#: terminal/templates/terminal/_msg_session_sharing.html:14
-#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:60
+#: tickets/models/ticket/general.py:303 tickets/serializers/ticket/ticket.py:60
msgid "Organization"
msgstr "组织"
-#: orgs/mixins/serializers.py:26 rbac/serializers/rolebinding.py:27
-msgid "Org name"
-msgstr "组织名称"
-
#: orgs/models.py:14
msgid "GLOBAL"
msgstr "全局组织"
@@ -4709,7 +4799,7 @@ msgid "SYSTEM"
msgstr "系统组织"
#: orgs/models.py:83 rbac/models/role.py:36 settings/models.py:185
-#: terminal/models/applet/applet.py:41
+#: terminal/models/applet/applet.py:42
msgid "Builtin"
msgstr "内置的"
@@ -4725,7 +4815,7 @@ msgstr "可以查看所有加入的组织"
msgid "Can not delete virtual org"
msgstr "无法删除虚拟组织"
-#: orgs/serializers.py:10 perms/serializers/permission.py:38
+#: orgs/serializers.py:10 perms/serializers/permission.py:37
#: rbac/serializers/role.py:27 users/serializers/group.py:54
msgid "Users amount"
msgstr "用户数量"
@@ -4734,7 +4824,7 @@ msgstr "用户数量"
msgid "User groups amount"
msgstr "用户组数量"
-#: orgs/serializers.py:14 perms/serializers/permission.py:41
+#: orgs/serializers.py:14 perms/serializers/permission.py:40
msgid "Nodes amount"
msgstr "节点数量"
@@ -4831,7 +4921,7 @@ msgid "today"
msgstr "今天"
#: perms/notifications.py:12 perms/notifications.py:44
-#: settings/serializers/feature.py:126
+#: settings/serializers/feature.py:111
msgid "day"
msgstr "天"
@@ -4851,11 +4941,11 @@ msgstr "资产授权规则将要过期"
msgid "asset permissions of organization {}"
msgstr "组织 ({}) 的资产授权"
-#: perms/serializers/permission.py:34 users/serializers/user.py:257
+#: perms/serializers/permission.py:33 users/serializers/user.py:257
msgid "Groups"
msgstr "用户组"
-#: perms/serializers/permission.py:39
+#: perms/serializers/permission.py:38
msgid "Groups amount"
msgstr "用户组数量"
@@ -4960,12 +5050,12 @@ msgid "Permissions"
msgstr "授权"
#: rbac/models/role.py:31 rbac/models/rolebinding.py:46
-#: rbac/serializers/role.py:12 settings/serializers/auth/oauth2.py:36
+#: rbac/serializers/role.py:12 settings/serializers/auth/oauth2.py:37
msgid "Scope"
msgstr "范围"
#: rbac/models/role.py:46 rbac/models/rolebinding.py:52
-#: users/models/user.py:910
+#: users/models/user/__init__.py:66
msgid "Role"
msgstr "角色"
@@ -4999,15 +5089,10 @@ msgstr "组织角色绑定"
msgid "System role binding"
msgstr "系统角色绑定"
-#: rbac/serializers/permission.py:25 users/serializers/profile.py:103
+#: rbac/serializers/permission.py:25 users/serializers/profile.py:76
msgid "Perms"
msgstr "权限"
-#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:34
-#: terminal/models/virtualapp/virtualapp.py:20
-msgid "Display name"
-msgstr "显示名称"
-
#: rbac/serializers/rolebinding.py:60
msgid "Has bound this role"
msgstr "已经绑定"
@@ -5052,19 +5137,15 @@ msgstr "收集账号"
msgid "Account change secret"
msgstr "账号改密"
-#: rbac/tree.py:54
-msgid "My assets"
-msgstr "我的资产"
-
#: rbac/tree.py:55
msgid "App ops"
msgstr "作业中心"
-#: rbac/tree.py:57 settings/serializers/feature.py:132
+#: rbac/tree.py:57 settings/serializers/feature.py:117
msgid "Feature"
msgstr "功能"
-#: rbac/tree.py:58 settings/serializers/auth/base.py:10
+#: rbac/tree.py:58 settings/serializers/auth/base.py:11
msgid "Authentication"
msgstr "认证"
@@ -5072,8 +5153,8 @@ msgstr "认证"
msgid "Storage"
msgstr "存储"
-#: rbac/tree.py:61 terminal/models/applet/applet.py:52
-#: terminal/models/applet/applet.py:317 terminal/models/applet/host.py:30
+#: rbac/tree.py:61 terminal/models/applet/applet.py:53
+#: terminal/models/applet/applet.py:328 terminal/models/applet/host.py:30
#: terminal/serializers/applet.py:15
msgid "Applet"
msgstr "远程应用"
@@ -5095,8 +5176,8 @@ msgstr "组织管理"
msgid "Ticket comment"
msgstr "工单评论"
-#: rbac/tree.py:159 settings/serializers/feature.py:113
-#: settings/serializers/feature.py:115 tickets/models/ticket/general.py:305
+#: rbac/tree.py:159 settings/serializers/feature.py:98
+#: settings/serializers/feature.py:100 tickets/models/ticket/general.py:308
msgid "Ticket"
msgstr "工单"
@@ -5113,7 +5194,7 @@ msgid "Chat AI is not enabled"
msgstr "聊天 AI 没有开启"
#: settings/api/chat.py:79 settings/api/dingtalk.py:31
-#: settings/api/feishu.py:36 settings/api/slack.py:34 settings/api/sms.py:160
+#: settings/api/feishu.py:39 settings/api/slack.py:34 settings/api/sms.py:160
#: settings/api/vault.py:40 settings/api/wecom.py:37
msgid "Test success"
msgstr "测试成功"
@@ -5219,63 +5300,63 @@ msgstr "聊天提示"
msgid "Notification of Synchronized LDAP User Task Results"
msgstr "同步 LDAP 用户任务结果的通知"
-#: settings/serializers/auth/base.py:12
+#: settings/serializers/auth/base.py:13
msgid "LDAP Auth"
msgstr "LDAP 认证"
-#: settings/serializers/auth/base.py:13
+#: settings/serializers/auth/base.py:14
msgid "CAS Auth"
msgstr "CAS 认证"
-#: settings/serializers/auth/base.py:14
+#: settings/serializers/auth/base.py:15
msgid "OPENID Auth"
msgstr "OIDC 认证"
-#: settings/serializers/auth/base.py:15
+#: settings/serializers/auth/base.py:16
msgid "SAML2 Auth"
msgstr "SAML2 认证"
-#: settings/serializers/auth/base.py:16
+#: settings/serializers/auth/base.py:17
msgid "OAuth2 Auth"
msgstr "OAuth2 认证"
-#: settings/serializers/auth/base.py:17
+#: settings/serializers/auth/base.py:18
msgid "RADIUS Auth"
msgstr "RADIUS 认证"
-#: settings/serializers/auth/base.py:18
+#: settings/serializers/auth/base.py:19
msgid "DingTalk Auth"
msgstr "钉钉 认证"
-#: settings/serializers/auth/base.py:19
+#: settings/serializers/auth/base.py:20
msgid "FeiShu Auth"
msgstr "飞书 认证"
-#: settings/serializers/auth/base.py:20
+#: settings/serializers/auth/base.py:21
msgid "Lark Auth"
msgstr "Lark 认证"
-#: settings/serializers/auth/base.py:21
+#: settings/serializers/auth/base.py:22
msgid "Slack Auth"
msgstr "Slack 认证"
-#: settings/serializers/auth/base.py:22
+#: settings/serializers/auth/base.py:23
msgid "WeCom Auth"
msgstr "企业微信 认证"
-#: settings/serializers/auth/base.py:23
+#: settings/serializers/auth/base.py:24
msgid "SSO Auth"
msgstr "SSO 令牌认证"
-#: settings/serializers/auth/base.py:24
+#: settings/serializers/auth/base.py:25
msgid "Passkey Auth"
msgstr "Passkey 认证"
-#: settings/serializers/auth/base.py:26
+#: settings/serializers/auth/base.py:27
msgid "Email suffix"
msgstr "邮件后缀"
-#: settings/serializers/auth/base.py:28
+#: settings/serializers/auth/base.py:29
msgid ""
"After third-party user authentication is successful, if the third-party "
"authentication service platform does not return the user's email "
@@ -5285,19 +5366,19 @@ msgstr ""
"第三方用户认证成功后,若第三方认证服务平台未返回该用户的邮箱信息,系统将自动"
"以此邮箱后缀创建用户"
-#: settings/serializers/auth/base.py:35
-msgid "Forgot Password"
-msgstr "忘记密码"
-
#: settings/serializers/auth/base.py:36
+msgid "Forgot Password URL"
+msgstr "忘记密码链接"
+
+#: settings/serializers/auth/base.py:37
msgid "The URL for Forgotten Password on the user login page"
msgstr "用户登录页面忘记密码的 URL"
-#: settings/serializers/auth/base.py:39
+#: settings/serializers/auth/base.py:40
msgid "Login redirection"
msgstr "启用登录跳转提示"
-#: settings/serializers/auth/base.py:41
+#: settings/serializers/auth/base.py:42
msgid ""
"Should an flash page be displayed before the user is redirected to third-"
"party authentication when the administrator enables third-party redirect "
@@ -5306,43 +5387,52 @@ msgstr ""
"当管理员启用第三方重定向身份验证时,在用户重定向到第三方身份验证之前是否显示 "
"Flash 页面"
-#: settings/serializers/auth/cas.py:10 settings/serializers/auth/cas.py:12
+#: settings/serializers/auth/base.py:54
+msgid ""
+"When you create a user, you associate the user to the organization of your "
+"choice. Users always belong to the Default organization."
+msgstr ""
+"创建用户时,您会将该用户与您选择的组织关联。用户始终属于 Default 组织。"
+
+#: settings/serializers/auth/cas.py:12 settings/serializers/auth/cas.py:14
msgid "CAS"
msgstr "CAS"
-#: settings/serializers/auth/cas.py:13 settings/serializers/auth/ldap.py:42
-#: settings/serializers/auth/oidc.py:60
+#: settings/serializers/auth/cas.py:15 settings/serializers/auth/ldap.py:43
+#: settings/serializers/auth/oidc.py:61
msgid "Server"
msgstr "服务端地址"
-#: settings/serializers/auth/cas.py:16
+#: settings/serializers/auth/cas.py:18
msgid "Proxy Server"
msgstr "回调地址"
-#: settings/serializers/auth/cas.py:19 settings/serializers/auth/oauth2.py:55
-#: settings/serializers/auth/saml2.py:40
+#: settings/serializers/auth/cas.py:21 settings/serializers/auth/oauth2.py:56
+#: settings/serializers/auth/saml2.py:42
msgid "Logout completely"
msgstr "同步注销"
-#: settings/serializers/auth/cas.py:20
+#: settings/serializers/auth/cas.py:22
msgid "When the user signs out, they also be logged out from the CAS server"
msgstr "当用户退出时,他们也会从 CAS 服务器注销"
-#: settings/serializers/auth/cas.py:26
+#: settings/serializers/auth/cas.py:28
msgid "Username attr"
msgstr "用户名属性"
-#: settings/serializers/auth/cas.py:29
+#: settings/serializers/auth/cas.py:31
msgid "Enable attributes map"
msgstr "启用属性映射"
-#: settings/serializers/auth/cas.py:32 settings/serializers/auth/ldap.py:64
-#: settings/serializers/auth/oauth2.py:59 settings/serializers/auth/oidc.py:38
-#: settings/serializers/auth/saml2.py:33
+#: settings/serializers/auth/cas.py:34 settings/serializers/auth/dingtalk.py:18
+#: settings/serializers/auth/feishu.py:18 settings/serializers/auth/lark.py:17
+#: settings/serializers/auth/ldap.py:65 settings/serializers/auth/oauth2.py:60
+#: settings/serializers/auth/oidc.py:39 settings/serializers/auth/saml2.py:35
+#: settings/serializers/auth/slack.py:18 settings/serializers/auth/wecom.py:18
msgid "User attribute"
msgstr "映射属性"
-#: settings/serializers/auth/cas.py:34
+#: settings/serializers/auth/cas.py:36
msgid ""
"User attribute mapping, where the `key` is the CAS service user attribute "
"name and the `value` is the JumpServer user attribute name"
@@ -5350,64 +5440,88 @@ msgstr ""
"用户属性映射,其中 `key` 是 CAS 服务用户属性名称,`value` 是 JumpServer 用户"
"属性名称"
-#: settings/serializers/auth/cas.py:39
+#: settings/serializers/auth/cas.py:41
msgid "Create user"
msgstr "创建用户(如果不存在)"
-#: settings/serializers/auth/cas.py:41
+#: settings/serializers/auth/cas.py:43
msgid ""
"After successful user authentication, if the user does not exist, "
"automatically create the user"
msgstr "用户认证成功后,若用户不存在,则自动创建用户"
-#: settings/serializers/auth/dingtalk.py:15
+#: settings/serializers/auth/dingtalk.py:16
msgid "Dingtalk"
msgstr "启用钉钉认证"
-#: settings/serializers/auth/lark.py:12 users/models/user.py:801
-msgid "Lark"
-msgstr "启用Lark认证"
+#: settings/serializers/auth/dingtalk.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the DingTalk service user attribute name"
+msgstr ""
+"用户属性映射,其中 `key` 是 JumpServer 用户属性名称,`value` 是钉钉服务用户属"
+"性名称"
-#: settings/serializers/auth/ldap.py:39 settings/serializers/auth/ldap.py:104
+#: settings/serializers/auth/feishu.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the FeiShu service user attribute name"
+msgstr ""
+"用户属性映射,其中 `key` 是 JumpServer 用户属性名称,`value` 是飞书服务用户属"
+"性名称"
+
+#: settings/serializers/auth/lark.py:13 users/models/user/_source.py:21
+msgid "Lark"
+msgstr ""
+
+#: settings/serializers/auth/lark.py:19
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the Lark service user attribute name"
+msgstr ""
+"用户属性映射,其中 `key` 是 JumpServer 用户属性名称,`value` 是 Lark 服务用户"
+"属性名称"
+
+#: settings/serializers/auth/ldap.py:40 settings/serializers/auth/ldap.py:102
msgid "LDAP"
msgstr "LDAP"
-#: settings/serializers/auth/ldap.py:43
+#: settings/serializers/auth/ldap.py:44
msgid "LDAP server URI"
msgstr "LDAP 服务域名"
-#: settings/serializers/auth/ldap.py:46
+#: settings/serializers/auth/ldap.py:47
msgid "Bind DN"
msgstr "绑定 DN"
-#: settings/serializers/auth/ldap.py:47
+#: settings/serializers/auth/ldap.py:48
msgid "Binding Distinguished Name"
-msgstr "绑定专有名称"
+msgstr "绑定目录管理员"
-#: settings/serializers/auth/ldap.py:51
+#: settings/serializers/auth/ldap.py:52
msgid "Binding password"
-msgstr "原来密码"
+msgstr "绑定密码"
-#: settings/serializers/auth/ldap.py:54
+#: settings/serializers/auth/ldap.py:55
msgid "Search OU"
-msgstr "系统架构"
+msgstr "用户 OU"
-#: settings/serializers/auth/ldap.py:56
+#: settings/serializers/auth/ldap.py:57
msgid ""
"User Search Base, if there are multiple OUs, you can separate them with the "
"`|` symbol"
msgstr "用户搜索库,如果有多个OU,可以用`|`符号分隔"
-#: settings/serializers/auth/ldap.py:60
+#: settings/serializers/auth/ldap.py:61
msgid "Search filter"
msgstr "用户过滤器"
-#: settings/serializers/auth/ldap.py:61
+#: settings/serializers/auth/ldap.py:62
#, python-format
msgid "Selection could include (cn|uid|sAMAccountName=%(user)s)"
msgstr "可能的选项是(cn或uid或sAMAccountName=%(user)s)"
-#: settings/serializers/auth/ldap.py:66
+#: settings/serializers/auth/ldap.py:67
msgid ""
"User attribute mapping, where the `key` is the JumpServer user attribute "
"name and the `value` is the LDAP service user attribute name"
@@ -5415,15 +5529,15 @@ msgstr ""
"用户属性映射,其中 `key` 是 JumpServer 用户属性名称,`value` 是 LDAP 服务用户"
"属性名称"
-#: settings/serializers/auth/ldap.py:85
+#: settings/serializers/auth/ldap.py:83
msgid "Connect timeout (s)"
msgstr "连接超时时间 (秒)"
-#: settings/serializers/auth/ldap.py:90
+#: settings/serializers/auth/ldap.py:88
msgid "User DN cache timeout (s)"
msgstr "User DN 缓存超时时间 (秒)"
-#: settings/serializers/auth/ldap.py:92
+#: settings/serializers/auth/ldap.py:90
msgid ""
"Caching the User DN obtained during user login authentication can "
"effectivelyimprove the speed of user authentication., 0 means no cache
If "
@@ -5433,59 +5547,59 @@ msgstr ""
"对用户登录认证时查询出的 User DN 进行缓存,可以有效提高用户认证的速度
如果"
"用户 OU 架构有调整,点击提交即可清除用户 DN 缓存"
-#: settings/serializers/auth/ldap.py:98
+#: settings/serializers/auth/ldap.py:96
msgid "Search paged size (piece)"
msgstr "搜索分页数量 (条)"
-#: settings/serializers/auth/oauth2.py:18
-#: settings/serializers/auth/oauth2.py:21
+#: settings/serializers/auth/oauth2.py:19
+#: settings/serializers/auth/oauth2.py:22
msgid "OAuth2"
msgstr "OAuth2"
-#: settings/serializers/auth/oauth2.py:24
+#: settings/serializers/auth/oauth2.py:25
msgid "Logo"
msgstr "图标"
-#: settings/serializers/auth/oauth2.py:27
+#: settings/serializers/auth/oauth2.py:28
msgid "Service provider"
msgstr "服务提供商"
-#: settings/serializers/auth/oauth2.py:30
+#: settings/serializers/auth/oauth2.py:31
#: xpack/plugins/cloud/serializers/account_attrs.py:35
msgid "Client ID"
msgstr "客户端 ID"
-#: settings/serializers/auth/oauth2.py:33 settings/serializers/auth/oidc.py:23
+#: settings/serializers/auth/oauth2.py:34 settings/serializers/auth/oidc.py:24
#: xpack/plugins/cloud/serializers/account_attrs.py:38
msgid "Client Secret"
msgstr "客户端密钥"
-#: settings/serializers/auth/oauth2.py:39 settings/serializers/auth/oidc.py:76
+#: settings/serializers/auth/oauth2.py:40 settings/serializers/auth/oidc.py:77
msgid "Authorization endpoint"
msgstr "授权端点地址"
-#: settings/serializers/auth/oauth2.py:42 settings/serializers/auth/oidc.py:79
+#: settings/serializers/auth/oauth2.py:43 settings/serializers/auth/oidc.py:80
msgid "Token endpoint"
msgstr "token 端点地址"
-#: settings/serializers/auth/oauth2.py:45 settings/serializers/auth/oidc.py:31
+#: settings/serializers/auth/oauth2.py:46 settings/serializers/auth/oidc.py:32
#: settings/serializers/auth/sms.py:111
msgid "Request method"
msgstr "客户端认证方式"
-#: settings/serializers/auth/oauth2.py:49 settings/serializers/auth/oidc.py:85
+#: settings/serializers/auth/oauth2.py:50 settings/serializers/auth/oidc.py:86
msgid "Userinfo endpoint"
msgstr "用户信息端点地址"
-#: settings/serializers/auth/oauth2.py:52 settings/serializers/auth/oidc.py:88
+#: settings/serializers/auth/oauth2.py:53 settings/serializers/auth/oidc.py:89
msgid "End session endpoint"
msgstr "注销会话端点地址"
-#: settings/serializers/auth/oauth2.py:56
+#: settings/serializers/auth/oauth2.py:57
msgid "When the user signs out, they also be logged out from the OAuth2 server"
msgstr "当用户退出时,他们也会从 OAuth2 服务器退出"
-#: settings/serializers/auth/oauth2.py:61
+#: settings/serializers/auth/oauth2.py:62
msgid ""
"User attribute mapping, where the `key` is the JumpServer user attribute "
"name and the `value` is the OAuth2 service user attribute name"
@@ -5493,36 +5607,36 @@ msgstr ""
"用户属性映射,其中 `key` 是 JumpServer 用户属性名称,`value` 是 OAuth2 服务用"
"户属性名称"
-#: settings/serializers/auth/oauth2.py:66 settings/serializers/auth/oidc.py:112
-#: settings/serializers/auth/saml2.py:43
+#: settings/serializers/auth/oauth2.py:67 settings/serializers/auth/oidc.py:113
+#: settings/serializers/auth/saml2.py:45
msgid "Always update user"
msgstr "总是更新用户信息"
-#: settings/serializers/auth/oidc.py:12 settings/serializers/auth/oidc.py:70
+#: settings/serializers/auth/oidc.py:13 settings/serializers/auth/oidc.py:71
msgid "OIDC"
-msgstr "启用 OIDC 认证"
+msgstr ""
-#: settings/serializers/auth/oidc.py:16
+#: settings/serializers/auth/oidc.py:17
msgid "Base site URL"
msgstr "JumpServer 地址"
-#: settings/serializers/auth/oidc.py:17
+#: settings/serializers/auth/oidc.py:18
msgid "The current site's URL is used to construct the callback address"
msgstr "当前站点的URL用于构造回调地址"
-#: settings/serializers/auth/oidc.py:20
+#: settings/serializers/auth/oidc.py:21
msgid "Client Id"
msgstr "客户端 ID"
-#: settings/serializers/auth/oidc.py:33
+#: settings/serializers/auth/oidc.py:34
msgid "Share session"
msgstr "共享会话"
-#: settings/serializers/auth/oidc.py:35
+#: settings/serializers/auth/oidc.py:36
msgid "Ignore SSL verification"
msgstr "忽略 SSL 证书验证"
-#: settings/serializers/auth/oidc.py:40
+#: settings/serializers/auth/oidc.py:41
msgid ""
"User attribute mapping, where the `key` is the JumpServer user attribute "
"name and the `value` is the OIDC service user attribute name"
@@ -5530,66 +5644,66 @@ msgstr ""
"用户属性映射,其中 `key` 是 JumpServer 用户属性名称,`value` 是 OIDC 服务用户"
"属性名称"
-#: settings/serializers/auth/oidc.py:44
+#: settings/serializers/auth/oidc.py:45
msgid "Enable PKCE"
msgstr "启用 PKCE"
-#: settings/serializers/auth/oidc.py:46
+#: settings/serializers/auth/oidc.py:47
msgid "Code challenge method"
msgstr "验证校验码方式"
-#: settings/serializers/auth/oidc.py:54
+#: settings/serializers/auth/oidc.py:55
msgid "Use Keycloak"
msgstr "使用 Keycloak"
-#: settings/serializers/auth/oidc.py:56
+#: settings/serializers/auth/oidc.py:57
msgid ""
"Use Keycloak as the OpenID Connect server, or use standard OpenID Connect "
"Protocol"
msgstr ""
"使用 Keycloak 作为 OpenID Connect 服务器,或者使用标准 OpenID Connect 协议"
-#: settings/serializers/auth/oidc.py:63
+#: settings/serializers/auth/oidc.py:64
msgid "Realm name"
msgstr "域"
-#: settings/serializers/auth/oidc.py:70
+#: settings/serializers/auth/oidc.py:71
msgid "OpenID Connect"
-msgstr "连接"
+msgstr "OpenID 连接"
-#: settings/serializers/auth/oidc.py:73
+#: settings/serializers/auth/oidc.py:74
msgid "Provider endpoint"
msgstr "端点地址"
-#: settings/serializers/auth/oidc.py:82
+#: settings/serializers/auth/oidc.py:83
msgid "JWKS endpoint"
msgstr "jwks 端点地址"
-#: settings/serializers/auth/oidc.py:91
+#: settings/serializers/auth/oidc.py:92
msgid "Signature algorithm"
msgstr "签名算法"
-#: settings/serializers/auth/oidc.py:94
+#: settings/serializers/auth/oidc.py:95
msgid "Signing key"
msgstr "签名 Key"
-#: settings/serializers/auth/oidc.py:97
+#: settings/serializers/auth/oidc.py:98
msgid "Scopes"
msgstr "连接范围"
-#: settings/serializers/auth/oidc.py:100
+#: settings/serializers/auth/oidc.py:101
msgid "ID Token max age (s)"
msgstr "令牌有效时间 (秒)"
-#: settings/serializers/auth/oidc.py:103
+#: settings/serializers/auth/oidc.py:104
msgid "ID Token include claims"
msgstr "声明"
-#: settings/serializers/auth/oidc.py:106
+#: settings/serializers/auth/oidc.py:107
msgid "Use state"
msgstr "使用状态"
-#: settings/serializers/auth/oidc.py:109
+#: settings/serializers/auth/oidc.py:110
msgid "Use nonce"
msgstr "临时使用"
@@ -5613,44 +5727,44 @@ msgstr ""
msgid "FIDO Server name"
msgstr "Passkey 服务名称"
-#: settings/serializers/auth/radius.py:13
-#: settings/serializers/auth/radius.py:15
+#: settings/serializers/auth/radius.py:14
+#: settings/serializers/auth/radius.py:16
msgid "Radius"
msgstr "Radius"
-#: settings/serializers/auth/radius.py:22
+#: settings/serializers/auth/radius.py:23
msgid "OTP in RADIUS"
msgstr "使用 Radius OTP"
-#: settings/serializers/auth/radius.py:23
+#: settings/serializers/auth/radius.py:24
msgid "* Using OTP in RADIUS means users can employ RADIUS as a method for MFA"
msgstr "* 在 RADIUS 中使用 OTP 意味着用户可以使用 RADIUS 作为 MFA 的方法"
-#: settings/serializers/auth/saml2.py:10 settings/serializers/auth/saml2.py:13
+#: settings/serializers/auth/saml2.py:12 settings/serializers/auth/saml2.py:15
msgid "SAML2"
msgstr "SAML2"
-#: settings/serializers/auth/saml2.py:16
+#: settings/serializers/auth/saml2.py:18
msgid "IDP Metadata URL"
msgstr "IDP Metadata 地址"
-#: settings/serializers/auth/saml2.py:19
+#: settings/serializers/auth/saml2.py:21
msgid "IDP Metadata XML"
msgstr "IDP Metadata XML"
-#: settings/serializers/auth/saml2.py:22
+#: settings/serializers/auth/saml2.py:24
msgid "SP advanced settings"
msgstr "高级设置"
-#: settings/serializers/auth/saml2.py:26
+#: settings/serializers/auth/saml2.py:28
msgid "SP private key"
msgstr "SP 密钥"
-#: settings/serializers/auth/saml2.py:30
+#: settings/serializers/auth/saml2.py:32
msgid "SP cert"
msgstr "SP 证书"
-#: settings/serializers/auth/saml2.py:35
+#: settings/serializers/auth/saml2.py:37
msgid ""
"User attribute mapping, where the `key` is the SAML2 service user attribute "
"name and the `value` is the JumpServer user attribute name"
@@ -5658,15 +5772,23 @@ msgstr ""
"用户属性映射,其中 `key` 是 SAML2 服务用户属性名称,`value` 是 JumpServer 用"
"户属性名称"
-#: settings/serializers/auth/saml2.py:41
+#: settings/serializers/auth/saml2.py:43
msgid "When the user signs out, they also be logged out from the SAML2 server"
msgstr "当用户退出时,他们也会从 SAML2 服务器注销"
+#: settings/serializers/auth/slack.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the Slack service user attribute name"
+msgstr ""
+"用户属性映射,其中 `key` 是 JumpServer 用户属性名称,`value` 是 Slack 服务用"
+"户属性名称"
+
#: settings/serializers/auth/sms.py:18
msgid "Enable Short Message Service (SMS)"
msgstr "启用短信服务 (SMS)"
-#: settings/serializers/auth/sms.py:21 xpack/plugins/cloud/models.py:35
+#: settings/serializers/auth/sms.py:21 xpack/plugins/cloud/models.py:36
msgid "Provider"
msgstr "云服务商"
@@ -5680,11 +5802,11 @@ msgstr "验证码长度"
#: settings/serializers/auth/sms.py:26
msgid "Length of the sent verification code"
-msgstr "发送验证码"
+msgstr "发送验证码的长度"
#: settings/serializers/auth/sms.py:31 settings/serializers/auth/sms.py:54
#: settings/serializers/auth/sms.py:62 settings/serializers/auth/sms.py:71
-#: settings/serializers/auth/sms.py:82 settings/serializers/msg.py:80
+#: settings/serializers/auth/sms.py:82 settings/serializers/msg.py:83
msgid "Signature"
msgstr "签名"
@@ -5693,7 +5815,7 @@ msgstr "签名"
msgid "Template code"
msgstr "模板"
-#: settings/serializers/auth/sms.py:40 users/models/user.py:920
+#: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:76
#: users/serializers/user.py:155
msgid "Phone"
msgstr "手机"
@@ -5762,6 +5884,14 @@ msgstr "令牌有效期"
msgid "Unit: second"
msgstr "单位: 秒"
+#: settings/serializers/auth/wecom.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the WeCom service user attribute name"
+msgstr ""
+"用户属性映射,其中 `key` 是 JumpServer 用户属性名称,`value` 是企业微信服务用"
+"户属性名称"
+
#: settings/serializers/basic.py:11
msgid "Site URL"
msgstr "当前站点 URL"
@@ -5857,7 +5987,7 @@ msgid ""
msgstr ""
"会话、录像,命令记录超过该时长将会被清除 (影响数据库存储,OSS 等不受影响)"
-#: settings/serializers/feature.py:18 settings/serializers/msg.py:65
+#: settings/serializers/feature.py:18 settings/serializers/msg.py:68
msgid "Subject"
msgstr "主题"
@@ -5892,74 +6022,74 @@ msgstr ""
"若特定数值小于999,系统将在每日晚间自动执行任务:检查并删除超出预定数量的历史"
"账号。如果该数值达到或超过999,则不进行任何历史账号的删除操作。"
-#: settings/serializers/feature.py:73 settings/serializers/feature.py:77
+#: settings/serializers/feature.py:73 settings/serializers/feature.py:79
msgid "Chat AI"
msgstr "聊天 AI"
-#: settings/serializers/feature.py:80
-msgid "Base URL"
-msgstr "JumpServer 地址"
+#: settings/serializers/feature.py:82
+msgid "GPT Base URL"
+msgstr "GPT 地址"
-#: settings/serializers/feature.py:81
+#: settings/serializers/feature.py:83
msgid "The base URL of the GPT service. For example: https://api.openai.com/v1"
msgstr "GPT 服务的基本 URL。例如:https://api.openai.com/v1"
-#: settings/serializers/feature.py:84 templates/_header_bar.html:96
+#: settings/serializers/feature.py:86 templates/_header_bar.html:96
msgid "API Key"
msgstr "API Key"
-#: settings/serializers/feature.py:88
+#: settings/serializers/feature.py:90
msgid ""
"The proxy server address of the GPT service. For example: http://ip:port"
msgstr "GPT 服务的代理服务器地址。例如:http://ip:port"
-#: settings/serializers/feature.py:91
+#: settings/serializers/feature.py:93
msgid "GPT Model"
msgstr "GPT 模型"
-#: settings/serializers/feature.py:117
+#: settings/serializers/feature.py:102
msgid "Approval without login"
msgstr "免登录审批"
-#: settings/serializers/feature.py:118
+#: settings/serializers/feature.py:103
msgid "Allow direct approval ticket without login"
msgstr "允许无需登录直接批准工单"
-#: settings/serializers/feature.py:122
+#: settings/serializers/feature.py:107
msgid "Period"
msgstr "时段"
-#: settings/serializers/feature.py:123
+#: settings/serializers/feature.py:108
msgid ""
"The default authorization time period when applying for assets via a ticket"
msgstr "工单申请资产的默认授权时间段"
-#: settings/serializers/feature.py:126
+#: settings/serializers/feature.py:111
msgid "hour"
msgstr "时"
-#: settings/serializers/feature.py:127
+#: settings/serializers/feature.py:112
msgid "Unit"
msgstr "单位"
-#: settings/serializers/feature.py:127
+#: settings/serializers/feature.py:112
msgid "The unit of period"
msgstr "执行周期"
-#: settings/serializers/feature.py:136
+#: settings/serializers/feature.py:121
msgid ""
"Allow users to execute batch commands in the Workbench - Job Center - Adhoc"
msgstr "允许用户在工作台 - 作业中心 - Adhoc 中执行批量命令"
-#: settings/serializers/feature.py:140
+#: settings/serializers/feature.py:125
msgid "Command blacklist"
msgstr "作业中心命令黑名单"
-#: settings/serializers/feature.py:141
+#: settings/serializers/feature.py:126
msgid "Command blacklist in Adhoc"
msgstr "作业中心命令黑名单"
-#: settings/serializers/feature.py:146
+#: settings/serializers/feature.py:131
#: terminal/models/virtualapp/provider.py:17
#: terminal/models/virtualapp/virtualapp.py:36
#: terminal/models/virtualapp/virtualapp.py:97
@@ -5967,11 +6097,11 @@ msgstr "作业中心命令黑名单"
msgid "Virtual app"
msgstr "虚拟应用"
-#: settings/serializers/feature.py:149
+#: settings/serializers/feature.py:134
msgid "Virtual App"
msgstr "虚拟应用"
-#: settings/serializers/feature.py:151
+#: settings/serializers/feature.py:136
msgid ""
"Virtual applications, you can use the Linux operating system as an "
"application server in remote applications."
@@ -5985,30 +6115,29 @@ msgstr "SMTP"
msgid "EXCHANGE"
msgstr ""
-#: settings/serializers/msg.py:33
+#: settings/serializers/msg.py:34
msgid "The user to be used for email server authentication"
-msgstr "SSO认证时,如果没有返回邮件地址,将使用该后缀"
+msgstr "登录到邮件服务器的用户名。这通常是你的邮件地址"
-#: settings/serializers/msg.py:37
+#: settings/serializers/msg.py:38
msgid ""
"Password to use for the email server. It is used in conjunction with `User` "
"when authenticating to the email server"
-msgstr ""
-"用于电子邮件服务器的密码。在向电子邮件服务器进行身份验证时,它与用户一起使用"
+msgstr "登录到邮件服务器的密码"
-#: settings/serializers/msg.py:40
+#: settings/serializers/msg.py:41
msgid "Sender"
msgstr "发件人"
-#: settings/serializers/msg.py:41
+#: settings/serializers/msg.py:42
msgid "Sender email address (default to using the `User`)"
msgstr "发件人电子邮件地址(默认使用“用户”)"
-#: settings/serializers/msg.py:45
+#: settings/serializers/msg.py:46
msgid "The recipient is used for testing the email server's connectivity"
msgstr "收件人用于测试电子邮件服务器的连通性"
-#: settings/serializers/msg.py:49
+#: settings/serializers/msg.py:51
msgid ""
"Whether to use an implicit TLS (secure) connection when talking to the SMTP "
"server. In most email documentation this type of TLS connection is referred "
@@ -6017,11 +6146,11 @@ msgstr ""
"与 SMTP 服务器通信时是否使用隐式 TLS(安全)连接。在大多数电子邮件文档中,这"
"种类型的 TLS 连接称为 SSL。它通常在端口 465 上使用"
-#: settings/serializers/msg.py:52
+#: settings/serializers/msg.py:54
msgid "Use TLS"
msgstr "使用 TLS"
-#: settings/serializers/msg.py:53
+#: settings/serializers/msg.py:56
msgid ""
"Whether to use a TLS (secure) connection when talking to the SMTP server. "
"This is used for explicit TLS connections, generally on port 587"
@@ -6029,25 +6158,25 @@ msgstr ""
"与 SMTP 服务器通信时是否使用 TLS(安全)连接。这用于显式 TLS 连接,通常在端"
"口 587 上"
-#: settings/serializers/msg.py:61
+#: settings/serializers/msg.py:64
msgid "Subject prefix"
msgstr "主题前缀"
-#: settings/serializers/msg.py:66
+#: settings/serializers/msg.py:69
msgid ""
"Tips: When creating a user, send the subject of the email (eg:Create account "
"successfully)"
msgstr "提示: 创建用户时,发送设置密码邮件的主题 (例如: 创建用户成功)"
-#: settings/serializers/msg.py:70
+#: settings/serializers/msg.py:73
msgid "Honorific"
msgstr "邮件问候语"
-#: settings/serializers/msg.py:71
+#: settings/serializers/msg.py:74
msgid "Tips: When creating a user, send the honorific of the email (eg:Hello)"
msgstr "提示: 创建用户时,发送设置密码邮件的敬语 (例如: 你好)"
-#: settings/serializers/msg.py:77
+#: settings/serializers/msg.py:80
#, python-brace-format
msgid ""
"Tips: When creating a user, send the content of the email, support "
@@ -6055,7 +6184,7 @@ msgid ""
msgstr ""
"提示: 创建用户时,发送设置密码邮件的内容, 支持 {username} {name} {email} 标签"
-#: settings/serializers/msg.py:81
+#: settings/serializers/msg.py:84
msgid "Tips: Email signature (eg:jumpserver)"
msgstr "邮件署名 (如:jumpserver)"
@@ -6355,12 +6484,6 @@ msgid ""
"* Allow users to log in to the KoKo component via password authentication"
msgstr "* 允许用户通过密码验证登录KoKo组件"
-#: settings/serializers/terminal.py:34 users/forms/profile.py:172
-#: users/models/user.py:933
-#: xpack/plugins/cloud/serializers/account_attrs.py:210
-msgid "Public key"
-msgstr "SSH公钥"
-
#: settings/serializers/terminal.py:36
msgid ""
"* Allow users to log in to the KoKo component via Public key "
@@ -6549,13 +6672,13 @@ msgstr "认证失败: (未知): {}"
msgid "Authentication success: {}"
msgstr "认证成功: {}"
-#: settings/ws.py:195
-msgid "Get ldap users is None"
-msgstr "获取 LDAP 用户为 None"
+#: settings/ws.py:198
+msgid "No LDAP user was found"
+msgstr "没有获取到 LDAP 用户"
-#: settings/ws.py:205
-msgid "Imported {} users successfully (Organization: {})"
-msgstr "成功导入 {} 个用户 ( 组织: {} )"
+#: settings/ws.py:204
+msgid "Total {}, success {}, failure {}"
+msgstr "总共 {},成功 {},失败 {}"
#: templates/_csv_import_export.html:8
msgid "Export"
@@ -6710,12 +6833,12 @@ msgstr "验证码已发送"
msgid "Home page"
msgstr "首页"
-#: templates/resource_download.html:18 templates/resource_download.html:33
+#: templates/resource_download.html:20 templates/resource_download.html:35
#: users/const.py:65
msgid "Client"
msgstr "客户端"
-#: templates/resource_download.html:20
+#: templates/resource_download.html:22
msgid ""
"JumpServer Client, currently used to launch the client, now only support "
"launch RDP SSH client, The Telnet client will next"
@@ -6723,25 +6846,25 @@ msgstr ""
"JumpServer 客户端,目前用来唤起 特定客户端程序 连接资产, 目前仅支持 RDP SSH "
"客户端,Telnet 会在未来支持"
-#: templates/resource_download.html:33
+#: templates/resource_download.html:35
msgid "Microsoft"
msgstr "微软"
-#: templates/resource_download.html:33
+#: templates/resource_download.html:35
msgid "Official"
msgstr "官方"
-#: templates/resource_download.html:35
+#: templates/resource_download.html:37
msgid ""
"macOS needs to download the client to connect RDP asset, which comes with "
"Windows"
msgstr "macOS 需要下载客户端来连接 RDP 资产,Windows 系统默认安装了该程序"
-#: templates/resource_download.html:44
+#: templates/resource_download.html:45
msgid "Windows Remote application publisher tools"
msgstr "Windows 远程应用发布服务器工具"
-#: templates/resource_download.html:45
+#: templates/resource_download.html:46
msgid ""
"OpenSSH is a program used to connect remote applications in the Windows "
"Remote Application Publisher"
@@ -6892,7 +7015,7 @@ msgid "High"
msgstr "较高"
#: terminal/const.py:47 terminal/const.py:84
-#: users/templates/users/reset_password.html:53
+#: users/templates/users/reset_password.html:54
msgid "Normal"
msgstr "正常"
@@ -6952,55 +7075,60 @@ msgstr "不支持批量创建"
msgid "Storage is invalid"
msgstr "存储无效"
-#: terminal/models/applet/applet.py:30 xpack/plugins/license/models.py:88
+#: terminal/models/applet/applet.py:31 xpack/plugins/license/models.py:88
msgid "Community edition"
msgstr "社区版"
-#: terminal/models/applet/applet.py:31
+#: terminal/models/applet/applet.py:32
msgid "Enterprise"
msgstr "企业版"
-#: terminal/models/applet/applet.py:36
+#: terminal/models/applet/applet.py:35
+#: terminal/models/virtualapp/virtualapp.py:20
+msgid "Display name"
+msgstr "显示名称"
+
+#: terminal/models/applet/applet.py:37
#: terminal/models/virtualapp/virtualapp.py:22
msgid "Author"
msgstr "作者"
-#: terminal/models/applet/applet.py:38 terminal/serializers/applet.py:31
+#: terminal/models/applet/applet.py:39 terminal/serializers/applet.py:31
msgid "Edition"
msgstr "版本"
-#: terminal/models/applet/applet.py:43
+#: terminal/models/applet/applet.py:44
msgid "Can concurrent"
msgstr "可以并发"
-#: terminal/models/applet/applet.py:48 terminal/serializers/applet_host.py:167
+#: terminal/models/applet/applet.py:49 terminal/serializers/applet_host.py:167
#: terminal/serializers/storage.py:193
msgid "Hosts"
msgstr "主机"
-#: terminal/models/applet/applet.py:93
+#: terminal/models/applet/applet.py:94
#: terminal/models/virtualapp/virtualapp.py:66
msgid "Applet pkg not valid, Missing file {}"
msgstr "Applet pkg 无效,缺少文件 {}"
-#: terminal/models/applet/applet.py:112
+#: terminal/models/applet/applet.py:113
msgid "Load platform.yml failed: {}"
msgstr "加载 platform.yml 失败: {}"
-#: terminal/models/applet/applet.py:115
+#: terminal/models/applet/applet.py:116
msgid "Only support custom platform"
msgstr "只支持自定义平台"
-#: terminal/models/applet/applet.py:120
+#: terminal/models/applet/applet.py:121
msgid "Missing type in platform.yml"
msgstr "在 platform.yml 中缺少类型"
-#: terminal/models/applet/applet.py:319 terminal/models/applet/host.py:36
+#: terminal/models/applet/applet.py:330 terminal/models/applet/host.py:36
#: terminal/models/applet/host.py:138
msgid "Hosting"
msgstr "宿主机"
-#: terminal/models/applet/applet.py:325
+#: terminal/models/applet/applet.py:336
msgid "Applet Publication"
msgstr "应用发布"
@@ -7295,7 +7423,7 @@ msgid "Command and replay storage"
msgstr "命令及录像存储"
#: terminal/notifications.py:240 terminal/tasks.py:153
-#: xpack/plugins/cloud/api.py:154
+#: xpack/plugins/cloud/api.py:160
#: xpack/plugins/cloud/serializers/account.py:121
#: xpack/plugins/cloud/serializers/account.py:123
msgid "Test failure: Account invalid"
@@ -7536,7 +7664,7 @@ msgid "Access key secret"
msgstr "Access key secret(SK)"
#: terminal/serializers/storage.py:68 xpack/plugins/cloud/manager.py:100
-#: xpack/plugins/cloud/models.py:273
+#: xpack/plugins/cloud/models.py:285
msgid "Region"
msgstr "地域"
@@ -7556,11 +7684,6 @@ msgstr "端点后缀"
msgid "HOST"
msgstr "主机"
-#: terminal/serializers/storage.py:146 users/models/user.py:930
-#: xpack/plugins/cloud/serializers/account_attrs.py:213
-msgid "Private key"
-msgstr "ssh私钥"
-
#: terminal/serializers/storage.py:152
msgid "SFTP Root"
msgstr "SFTP根路径"
@@ -7605,7 +7728,15 @@ msgstr "索引"
msgid "Doc type"
msgstr "文档类型"
-#: terminal/serializers/storage.py:263
+#: terminal/serializers/storage.py:257
+msgid "Store locally"
+msgstr "本地存储"
+
+#: terminal/serializers/storage.py:258
+msgid "Do not save"
+msgstr "不保存"
+
+#: terminal/serializers/storage.py:273
msgid ""
"set as the default storage, will make new Component use the current storage "
"by default, without affecting existing Component"
@@ -7795,7 +7926,7 @@ msgstr "没有端口可以使用,检查并修改配置文件中 Magnus 监听
msgid "All available port count: {}, Already use port count: {}"
msgstr "所有可用端口数量:{},已使用端口数量:{}"
-#: tickets/api/ticket.py:88 tickets/models/ticket/general.py:286
+#: tickets/api/ticket.py:88 tickets/models/ticket/general.py:289
msgid "Applicant"
msgstr "申请人"
@@ -7832,30 +7963,14 @@ msgid "Two level"
msgstr "2 级"
#: tickets/const.py:54
-msgid "Org admin"
-msgstr "组织管理员"
-
-#: tickets/const.py:55
-msgid "Custom user"
-msgstr "自定义用户"
-
-#: tickets/const.py:56
-msgid "Super admin"
-msgstr "超级管理员"
-
-#: tickets/const.py:57
-msgid "Super admin and org admin"
-msgstr "组织管理员或超级管理员"
-
-#: tickets/const.py:61
msgid "All assets"
msgstr "所有资产"
-#: tickets/const.py:62
+#: tickets/const.py:55
msgid "Permed assets"
msgstr "授权的资产"
-#: tickets/const.py:63
+#: tickets/const.py:56
msgid "Permed valid assets"
msgstr "有效授权的资产"
@@ -7898,24 +8013,16 @@ msgstr "用户显示名称"
msgid "Body"
msgstr "内容"
-#: tickets/models/flow.py:19 tickets/models/flow.py:61
-#: tickets/models/ticket/general.py:42
+#: tickets/models/flow.py:21 tickets/models/flow.py:47
+#: tickets/models/ticket/general.py:45
msgid "Approve level"
msgstr "审批级别"
-#: tickets/models/flow.py:24 tickets/serializers/flow.py:17
-msgid "Approve strategy"
-msgstr "审批策略"
-
-#: tickets/models/flow.py:29 tickets/serializers/flow.py:19
-msgid "Assignees"
-msgstr "受理人"
-
-#: tickets/models/flow.py:33
+#: tickets/models/flow.py:26
msgid "Ticket flow approval rule"
msgstr "工单批准信息"
-#: tickets/models/flow.py:66
+#: tickets/models/flow.py:52
msgid "Ticket flow"
msgstr "工单流程"
@@ -7969,35 +8076,35 @@ msgstr "命令过滤器"
msgid "Apply Command Ticket"
msgstr "命令复核工单"
-#: tickets/models/ticket/general.py:77
+#: tickets/models/ticket/general.py:80
msgid "Ticket step"
msgstr "工单步骤"
-#: tickets/models/ticket/general.py:95
+#: tickets/models/ticket/general.py:98
msgid "Ticket assignee"
msgstr "工单受理人"
-#: tickets/models/ticket/general.py:270
+#: tickets/models/ticket/general.py:273
msgid "Title"
msgstr "标题"
-#: tickets/models/ticket/general.py:290
+#: tickets/models/ticket/general.py:293
msgid "TicketFlow"
msgstr "工单流程"
-#: tickets/models/ticket/general.py:293
+#: tickets/models/ticket/general.py:296
msgid "Approval step"
msgstr "审批步骤"
-#: tickets/models/ticket/general.py:296
+#: tickets/models/ticket/general.py:299
msgid "Relation snapshot"
msgstr "工单快照"
-#: tickets/models/ticket/general.py:399
+#: tickets/models/ticket/general.py:405
msgid "Please try again"
msgstr "请再次尝试"
-#: tickets/models/ticket/general.py:475
+#: tickets/models/ticket/general.py:481
msgid "Super ticket"
msgstr "超级工单"
@@ -8045,15 +8152,7 @@ msgstr "你的工单已被处理, 处理人 - {}"
msgid "Ticket has processed - {} ({})"
msgstr "你的工单已被处理, 处理人 - {} ({})"
-#: tickets/serializers/flow.py:20
-msgid "Assignees display"
-msgstr "受理人名称"
-
-#: tickets/serializers/flow.py:46
-msgid "Please select the Assignees"
-msgstr "请选择受理人"
-
-#: tickets/serializers/flow.py:74
+#: tickets/serializers/flow.py:45
msgid "The current organization type already exists"
msgstr "当前组织已存在该类型"
@@ -8212,14 +8311,18 @@ msgstr "替换"
msgid "Suffix"
msgstr "加后缀"
-#: users/exceptions.py:10
+#: users/exceptions.py:9
msgid "MFA not enabled"
msgstr "MFA 多因子认证没有开启"
-#: users/exceptions.py:20
+#: users/exceptions.py:19
msgid "Unable to delete all users"
msgstr "无法删除全部用户"
+#: users/exceptions.py:24
+msgid "Create failed. The number of SSH keys has reached the limit"
+msgstr "创建失败,SSH密钥数量已达到上限"
+
#: users/forms/profile.py:48
msgid ""
"When enabled, you will enter the MFA binding process the next time you log "
@@ -8286,82 +8389,69 @@ msgstr "复制你的公钥到这里"
msgid "Public key should not be the same as your old one."
msgstr "不能和原来的密钥相同"
-#: users/forms/profile.py:161 users/serializers/profile.py:76
-#: users/serializers/profile.py:160 users/serializers/profile.py:187
-msgid "Not a valid ssh public key"
-msgstr "SSH密钥不合法"
-
#: users/models/preference.py:38 users/serializers/preference/preference.py:19
msgid "Preference"
msgstr "用户设置"
-#: users/models/user.py:690
-msgid "Force enabled"
-msgstr "强制启用"
-
-#: users/models/user.py:913 users/serializers/user.py:271
+#: users/models/user/__init__.py:69 users/serializers/user.py:271
msgid "Is service account"
msgstr "服务账号"
-#: users/models/user.py:915
+#: users/models/user/__init__.py:71
msgid "Avatar"
msgstr "头像"
-#: users/models/user.py:917
+#: users/models/user/__init__.py:73
msgid "Wechat"
msgstr "微信"
-#: users/models/user.py:926
+#: users/models/user/__init__.py:82
msgid "OTP secret key"
msgstr "OTP 密钥"
# msgid "Private key"
# msgstr "ssh私钥"
-#: users/models/user.py:936 users/serializers/profile.py:124
+#: users/models/user/__init__.py:92 users/serializers/profile.py:97
#: users/serializers/user.py:268
msgid "Is first login"
msgstr "首次登录"
-#: users/models/user.py:954
+#: users/models/user/__init__.py:110
msgid "Date password last updated"
msgstr "最后更新密码日期"
-#: users/models/user.py:957
+#: users/models/user/__init__.py:113
msgid "Need update password"
msgstr "需要更新密码"
-#: users/models/user.py:981
+#: users/models/user/__init__.py:137
msgid "Date api key used"
msgstr "API key 最后使用日期"
-#: users/models/user.py:1119
+#: users/models/user/__init__.py:276
msgid "Can not delete admin user"
msgstr "无法删除管理员用户"
-#: users/models/user.py:1133
+#: users/models/user/__init__.py:290
msgid "Can invite user"
msgstr "可以邀请用户"
-#: users/models/user.py:1134
+#: users/models/user/__init__.py:291
msgid "Can remove user"
msgstr "可以移除用户"
-#: users/models/user.py:1135
+#: users/models/user/__init__.py:292
msgid "Can match user"
msgstr "可以匹配用户"
-#: users/models/user.py:1146
-msgid "Administrator"
-msgstr "管理员"
-
-#: users/models/user.py:1149
-msgid "Administrator is the super user of system"
-msgstr "Administrator是初始的超级管理员"
-
-#: users/models/user.py:1181
+#: users/models/user/__init__.py:321
msgid "User password history"
msgstr "用户密码历史"
+#: users/models/user/_auth.py:34
+msgid "Force enabled"
+msgstr "强制启用"
+
#: users/notifications.py:55
#: users/templates/users/_msg_password_expire_reminder.html:17
#: users/templates/users/reset_password.html:5
@@ -8491,7 +8581,7 @@ msgstr "命令行"
msgid "The old password is incorrect"
msgstr "旧密码错误"
-#: users/serializers/profile.py:36 users/serializers/profile.py:174
+#: users/serializers/profile.py:36 users/serializers/profile.py:147
msgid "Password does not match security rules"
msgstr "密码不满足安全规则"
@@ -8553,7 +8643,7 @@ msgstr "组织管理员"
#: users/serializers/user.py:140
msgid "Can public key authentication"
-msgstr "可以公钥认证吗"
+msgstr "可以使用公钥认证"
#: users/serializers/user.py:242
msgid "Full name"
@@ -8609,7 +8699,7 @@ msgstr "* 为安全起见,只显示部分用户。您可以搜索更多"
msgid "name not unique"
msgstr "名称重复"
-#: users/signal_handlers.py:35
+#: users/signal_handlers.py:39
msgid ""
"The administrator has enabled \"Only allow existing users to log in\", \n"
" and the current user is not in the user list. Please contact the "
@@ -8617,7 +8707,7 @@ msgid ""
msgstr ""
"管理员已开启'仅允许已存在用户登录',当前用户不在用户列表中,请联系管理员。"
-#: users/signal_handlers.py:171
+#: users/signal_handlers.py:183
msgid "Clean up expired user sessions"
msgstr "清除过期的用户会话"
@@ -8743,23 +8833,23 @@ msgstr "您的密码必须满足:"
msgid "Password strength"
msgstr "密码强度:"
-#: users/templates/users/reset_password.html:51
+#: users/templates/users/reset_password.html:52
msgid "Very weak"
msgstr "很弱"
-#: users/templates/users/reset_password.html:52
+#: users/templates/users/reset_password.html:53
msgid "Weak"
msgstr "弱"
-#: users/templates/users/reset_password.html:54
+#: users/templates/users/reset_password.html:55
msgid "Medium"
msgstr "一般"
-#: users/templates/users/reset_password.html:55
+#: users/templates/users/reset_password.html:56
msgid "Strong"
msgstr "强"
-#: users/templates/users/reset_password.html:56
+#: users/templates/users/reset_password.html:57
msgid "Very strong"
msgstr "很强"
@@ -8893,15 +8983,15 @@ msgid ""
"strategy will skipped."
msgstr "根据当前任务配置,不符合“”策略的资产将被跳过。"
-#: xpack/plugins/cloud/api.py:66
+#: xpack/plugins/cloud/api.py:72
msgid "Test connection successful"
msgstr "测试成功"
-#: xpack/plugins/cloud/api.py:68
+#: xpack/plugins/cloud/api.py:74
msgid "Test connection failed: {}"
msgstr "测试连接失败:{}"
-#: xpack/plugins/cloud/api.py:165
+#: xpack/plugins/cloud/api.py:171
msgid "User {} deleted the current resource and released the assets"
msgstr "用户 {} 删除了当前资源已释放的资产"
@@ -9005,7 +9095,7 @@ msgstr "私有IP"
msgid "Public IP"
msgstr "公网IP"
-#: xpack/plugins/cloud/const.py:42 xpack/plugins/cloud/models.py:347
+#: xpack/plugins/cloud/const.py:42 xpack/plugins/cloud/models.py:359
msgid "Instance name"
msgstr "实例名称"
@@ -9076,7 +9166,7 @@ msgstr "任务执行 ID"
#: xpack/plugins/cloud/manager.py:97
msgid "Synchronization regions"
-msgstr "没有用户需要同步"
+msgstr "同步地区"
#: xpack/plugins/cloud/manager.py:115
#, python-format
@@ -9088,49 +9178,49 @@ msgstr "获取区域 \"%s\" 的实例错误,错误:%s"
msgid "Failed to synchronize the instance \"%s\""
msgstr "无法同步实例 %s"
-#: xpack/plugins/cloud/manager.py:334
+#: xpack/plugins/cloud/manager.py:337
#, python-format
msgid ""
"The updated platform of asset \"%s\" is inconsistent with the original "
"platform type. Skip platform and protocol updates"
msgstr "资产“%s”的更新平台与原平台类型不一致。跳过平台和协议更新"
-#: xpack/plugins/cloud/manager.py:390
+#: xpack/plugins/cloud/manager.py:393
#, python-format
msgid "The asset \"%s\" already exists"
msgstr "资产 \"%s\" 已存在"
-#: xpack/plugins/cloud/manager.py:392
+#: xpack/plugins/cloud/manager.py:395
#, python-format
msgid "Update asset \"%s\""
msgstr "更新资产 \"%s\""
-#: xpack/plugins/cloud/manager.py:395
+#: xpack/plugins/cloud/manager.py:398
#, python-format
msgid "Asset \"%s\" has been updated"
msgstr "资产 \"%s\" 已更新"
-#: xpack/plugins/cloud/manager.py:405
+#: xpack/plugins/cloud/manager.py:408
#, python-format
msgid "Prepare to create asset \"%s\""
msgstr "准备创建资产 %s"
-#: xpack/plugins/cloud/manager.py:426
+#: xpack/plugins/cloud/manager.py:429
#, python-format
msgid "Set nodes \"%s\""
msgstr "删除节点: \"%s\""
-#: xpack/plugins/cloud/manager.py:452
+#: xpack/plugins/cloud/manager.py:455
#, python-format
msgid "Set accounts \"%s\""
msgstr "删除账号: %s"
-#: xpack/plugins/cloud/manager.py:468
+#: xpack/plugins/cloud/manager.py:471
#, python-format
msgid "Set protocols \"%s\""
msgstr "设置协议 \"%s\""
-#: xpack/plugins/cloud/manager.py:482 xpack/plugins/cloud/tasks.py:27
+#: xpack/plugins/cloud/manager.py:485 xpack/plugins/cloud/tasks.py:30
msgid "Run sync instance task"
msgstr "执行同步实例任务"
@@ -9138,164 +9228,165 @@ msgstr "执行同步实例任务"
msgid "Cloud center"
msgstr "云管中心"
-#: xpack/plugins/cloud/models.py:38
+#: xpack/plugins/cloud/models.py:39
#: xpack/plugins/cloud/serializers/account.py:94
msgid "Attrs"
msgstr "属性"
-#: xpack/plugins/cloud/models.py:39
+#: xpack/plugins/cloud/models.py:40
msgid "Validity"
msgstr "有效"
-#: xpack/plugins/cloud/models.py:44
+#: xpack/plugins/cloud/models.py:45
msgid "Cloud account"
msgstr "云账号"
-#: xpack/plugins/cloud/models.py:46
+#: xpack/plugins/cloud/models.py:47
msgid "Test cloud account"
msgstr "测试云账号"
-#: xpack/plugins/cloud/models.py:103
+#: xpack/plugins/cloud/models.py:104
#: xpack/plugins/cloud/serializers/account.py:76
-#: xpack/plugins/cloud/serializers/task.py:156
+#: xpack/plugins/cloud/serializers/task.py:157
+#: xpack/plugins/cloud/serializers/task.py:158
msgid "Regions"
msgstr "地域"
-#: xpack/plugins/cloud/models.py:106
+#: xpack/plugins/cloud/models.py:107
msgid "Hostname strategy"
msgstr "主机名策略"
-#: xpack/plugins/cloud/models.py:111
+#: xpack/plugins/cloud/models.py:112
msgid "IP network segment group"
msgstr "IP网段组"
-#: xpack/plugins/cloud/models.py:114
-#: xpack/plugins/cloud/serializers/task.py:159
+#: xpack/plugins/cloud/models.py:115
+#: xpack/plugins/cloud/serializers/task.py:161
msgid "Sync IP type"
msgstr "同步IP类型"
-#: xpack/plugins/cloud/models.py:117
+#: xpack/plugins/cloud/models.py:118
msgid "Always update"
msgstr "总是更新"
-#: xpack/plugins/cloud/models.py:119
+#: xpack/plugins/cloud/models.py:120
msgid "Fully synchronous"
msgstr "完全同步"
-#: xpack/plugins/cloud/models.py:124
+#: xpack/plugins/cloud/models.py:125
msgid "Date last sync"
msgstr "最后同步日期"
-#: xpack/plugins/cloud/models.py:127 xpack/plugins/cloud/models.py:365
-#: xpack/plugins/cloud/models.py:391
+#: xpack/plugins/cloud/models.py:128 xpack/plugins/cloud/models.py:377
+#: xpack/plugins/cloud/models.py:403
msgid "Strategy"
msgstr "策略"
-#: xpack/plugins/cloud/models.py:132 xpack/plugins/cloud/models.py:220
+#: xpack/plugins/cloud/models.py:133 xpack/plugins/cloud/models.py:221
msgid "Sync instance task"
msgstr "同步实例任务"
-#: xpack/plugins/cloud/models.py:231 xpack/plugins/cloud/models.py:283
+#: xpack/plugins/cloud/models.py:232 xpack/plugins/cloud/models.py:295
msgid "Date sync"
msgstr "同步日期"
-#: xpack/plugins/cloud/models.py:235
+#: xpack/plugins/cloud/models.py:236
msgid "Sync instance snapshot"
msgstr "同步实例快照"
-#: xpack/plugins/cloud/models.py:239
+#: xpack/plugins/cloud/models.py:244
msgid "Sync instance task execution"
msgstr "同步实例任务执行"
-#: xpack/plugins/cloud/models.py:263
+#: xpack/plugins/cloud/models.py:275
msgid "Sync task"
msgstr "同步任务"
-#: xpack/plugins/cloud/models.py:267
+#: xpack/plugins/cloud/models.py:279
msgid "Sync instance task history"
msgstr "同步实例任务历史"
-#: xpack/plugins/cloud/models.py:270
+#: xpack/plugins/cloud/models.py:282
msgid "Instance"
msgstr "实例"
-#: xpack/plugins/cloud/models.py:287
+#: xpack/plugins/cloud/models.py:299
msgid "Sync instance detail"
msgstr "同步实例详情"
-#: xpack/plugins/cloud/models.py:299 xpack/plugins/cloud/serializers/task.py:76
+#: xpack/plugins/cloud/models.py:311 xpack/plugins/cloud/serializers/task.py:77
msgid "Rule relation"
msgstr "条件关系"
-#: xpack/plugins/cloud/models.py:309
+#: xpack/plugins/cloud/models.py:321
msgid "Task strategy"
msgstr "任务策略"
-#: xpack/plugins/cloud/models.py:336
+#: xpack/plugins/cloud/models.py:348
msgid "Equal"
msgstr "等于"
-#: xpack/plugins/cloud/models.py:337
+#: xpack/plugins/cloud/models.py:349
msgid "Not Equal"
msgstr "不等于"
-#: xpack/plugins/cloud/models.py:338
+#: xpack/plugins/cloud/models.py:350
msgid "In"
msgstr "在...中"
-#: xpack/plugins/cloud/models.py:339
+#: xpack/plugins/cloud/models.py:351
msgid "Contains"
msgstr "包含"
-#: xpack/plugins/cloud/models.py:340
+#: xpack/plugins/cloud/models.py:352
msgid "Exclude"
msgstr "排除"
-#: xpack/plugins/cloud/models.py:341
+#: xpack/plugins/cloud/models.py:353
msgid "Startswith"
msgstr "以...开头"
-#: xpack/plugins/cloud/models.py:342
+#: xpack/plugins/cloud/models.py:354
msgid "Endswith"
msgstr "以...结尾"
-#: xpack/plugins/cloud/models.py:348
+#: xpack/plugins/cloud/models.py:360
msgid "Instance platform"
msgstr "实例平台"
-#: xpack/plugins/cloud/models.py:349
+#: xpack/plugins/cloud/models.py:361
msgid "Instance address"
msgstr "实例地址"
-#: xpack/plugins/cloud/models.py:356
+#: xpack/plugins/cloud/models.py:368
msgid "Rule attr"
msgstr "规则属性"
-#: xpack/plugins/cloud/models.py:360
+#: xpack/plugins/cloud/models.py:372
msgid "Rule match"
msgstr "规则匹配"
-#: xpack/plugins/cloud/models.py:362
+#: xpack/plugins/cloud/models.py:374
msgid "Rule value"
msgstr "规则值"
-#: xpack/plugins/cloud/models.py:369 xpack/plugins/cloud/serializers/task.py:79
+#: xpack/plugins/cloud/models.py:381 xpack/plugins/cloud/serializers/task.py:80
msgid "Strategy rule"
msgstr "条件"
-#: xpack/plugins/cloud/models.py:379
+#: xpack/plugins/cloud/models.py:391
msgid "Name strategy"
msgstr "主机名策略"
-#: xpack/plugins/cloud/models.py:386
+#: xpack/plugins/cloud/models.py:398
msgid "Action attr"
msgstr "动作属性"
-#: xpack/plugins/cloud/models.py:388
+#: xpack/plugins/cloud/models.py:400
msgid "Action value"
msgstr "动作值"
-#: xpack/plugins/cloud/models.py:395 xpack/plugins/cloud/serializers/task.py:82
+#: xpack/plugins/cloud/models.py:407 xpack/plugins/cloud/serializers/task.py:83
msgid "Strategy action"
msgstr "动作"
@@ -9596,15 +9687,15 @@ msgstr "测试超时时间"
msgid "Project"
msgstr "project"
-#: xpack/plugins/cloud/serializers/task.py:154
+#: xpack/plugins/cloud/serializers/task.py:155
msgid "History count"
msgstr "执行次数"
-#: xpack/plugins/cloud/serializers/task.py:155
+#: xpack/plugins/cloud/serializers/task.py:156
msgid "Instance count"
msgstr "实例个数"
-#: xpack/plugins/cloud/tasks.py:41
+#: xpack/plugins/cloud/tasks.py:44
msgid "Period clean sync instance task execution"
msgstr "定期清除同步实例任务执行记录"
diff --git a/apps/i18n/core/zh_Hant/LC_MESSAGES/django.po b/apps/i18n/core/zh_Hant/LC_MESSAGES/django.po
index ec419a190..e2de97732 100644
--- a/apps/i18n/core/zh_Hant/LC_MESSAGES/django.po
+++ b/apps/i18n/core/zh_Hant/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: 2024-07-03 16:39+0800\n"
+"POT-Creation-Date: 2024-08-15 14:04+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler \n"
"Language-Team: JumpServer team\n"
@@ -65,9 +65,10 @@ msgstr "完成"
#: accounts/automations/backup_account/handlers.py:219
#: accounts/const/automation.py:110
-#: accounts/serializers/automations/change_secret.py:166 audits/const.py:64
+#: accounts/serializers/automations/change_secret.py:166
+#: assets/serializers/automations/base.py:52 audits/const.py:64
#: audits/models.py:64 audits/signal_handlers/activity_log.py:33
-#: common/const/choices.py:18 ops/const.py:74 ops/serializers/celery.py:48
+#: common/const/choices.py:65 ops/const.py:74 ops/serializers/celery.py:48
#: terminal/const.py:78 terminal/models/session/sharing.py:121
#: tickets/views/approve.py:128
msgid "Success"
@@ -76,7 +77,7 @@ msgstr "成功"
#: accounts/automations/backup_account/handlers.py:221
#: accounts/const/account.py:34 accounts/const/automation.py:109
#: accounts/serializers/automations/change_secret.py:167 audits/const.py:65
-#: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19
+#: audits/signal_handlers/activity_log.py:33 common/const/choices.py:66
#: ops/const.py:76 terminal/const.py:79 xpack/plugins/cloud/const.py:47
msgid "Failed"
msgstr "失敗"
@@ -113,7 +114,7 @@ msgstr "計劃執行結束"
msgid "No pending accounts found"
msgstr "未找到待處理帳戶"
-#: accounts/automations/change_secret/manager.py:224
+#: accounts/automations/change_secret/manager.py:227
#, python-format
msgid "Success: %s, Failed: %s, Total: %s"
msgstr "成功: %s, 失敗: %s, 總數: %s"
@@ -123,9 +124,9 @@ msgstr "成功: %s, 失敗: %s, 總數: %s"
#: audits/signal_handlers/login_log.py:34 authentication/confirm/password.py:9
#: authentication/confirm/password.py:24 authentication/confirm/password.py:26
#: authentication/forms.py:28
-#: authentication/templates/authentication/login.html:323
-#: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:50
-#: settings/serializers/msg.py:36 settings/serializers/terminal.py:28
+#: authentication/templates/authentication/login.html:362
+#: settings/serializers/auth/ldap.py:26 settings/serializers/auth/ldap.py:51
+#: settings/serializers/msg.py:37 settings/serializers/terminal.py:28
#: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142
#: users/forms/profile.py:21 users/serializers/user.py:144
#: users/templates/users/_msg_user_created.html:13
@@ -136,7 +137,7 @@ msgstr "密碼"
#: accounts/const/account.py:7
#: accounts/serializers/automations/change_secret.py:35
-#: terminal/serializers/storage.py:124
+#: authentication/models/ssh_key.py:27 terminal/serializers/storage.py:124
msgid "SSH key"
msgstr "SSH 金鑰"
@@ -153,7 +154,7 @@ msgstr "Token"
msgid "API key"
msgstr "API key"
-#: accounts/const/account.py:14 common/db/fields.py:235
+#: accounts/const/account.py:14 common/db/fields.py:230
#: settings/serializers/terminal.py:14
msgid "All"
msgstr "全部"
@@ -174,7 +175,7 @@ msgstr "匿名帳號"
msgid "Specified account"
msgstr "指定帳號"
-#: accounts/const/account.py:26 users/models/user.py:791
+#: accounts/const/account.py:26 users/models/user/_source.py:11
msgid "Local"
msgstr "資料庫"
@@ -293,8 +294,8 @@ msgstr "僅創建"
#: authentication/serializers/password_mfa.py:16
#: authentication/serializers/password_mfa.py:24
#: notifications/backends/__init__.py:10 settings/serializers/msg.py:21
-#: settings/serializers/msg.py:58 users/forms/profile.py:100
-#: users/forms/profile.py:108 users/models/user.py:902
+#: settings/serializers/msg.py:61 users/forms/profile.py:100
+#: users/forms/profile.py:108 users/models/user/__init__.py:58
#: users/templates/users/forgot_password.html:162
#: users/views/profile/reset.py:94
msgid "Email"
@@ -304,8 +305,9 @@ msgstr "信箱"
msgid "SFTP"
msgstr "SFTP"
-#: accounts/const/automation.py:111 common/const/choices.py:16
-#: terminal/const.py:77 tickets/const.py:29 tickets/const.py:38
+#: accounts/const/automation.py:111 assets/serializers/automations/base.py:54
+#: common/const/choices.py:63 terminal/const.py:77 tickets/const.py:29
+#: tickets/const.py:38
msgid "Pending"
msgstr "待定的"
@@ -338,8 +340,8 @@ msgstr "用戶 %s 查看/匯出 了密碼"
#: accounts/models/account.py:49
#: accounts/models/automations/gather_account.py:16
-#: accounts/serializers/account/account.py:218
-#: accounts/serializers/account/account.py:263
+#: accounts/serializers/account/account.py:226
+#: accounts/serializers/account/account.py:271
#: accounts/serializers/account/gathered_account.py:10
#: accounts/serializers/automations/change_secret.py:111
#: accounts/serializers/automations/change_secret.py:143
@@ -353,26 +355,26 @@ msgstr "用戶 %s 查看/匯出 了密碼"
#: terminal/serializers/command.py:17 terminal/serializers/session.py:28
#: terminal/templates/terminal/_msg_command_warning.html:4
#: terminal/templates/terminal/_msg_session_sharing.html:4
-#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:276
+#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:288
msgid "Asset"
msgstr "資產"
#: accounts/models/account.py:53 accounts/models/template.py:16
-#: accounts/serializers/account/account.py:225
-#: accounts/serializers/account/account.py:273
+#: accounts/serializers/account/account.py:233
+#: accounts/serializers/account/account.py:281
#: accounts/serializers/account/template.py:27
#: authentication/serializers/connect_token_secret.py:50
msgid "Su from"
msgstr "切換自"
-#: accounts/models/account.py:55 assets/const/protocol.py:178
-#: settings/serializers/auth/cas.py:23 terminal/models/applet/applet.py:35
+#: accounts/models/account.py:55 assets/const/protocol.py:189
+#: settings/serializers/auth/cas.py:25 terminal/models/applet/applet.py:36
#: terminal/models/virtualapp/virtualapp.py:21
msgid "Version"
msgstr "版本"
-#: accounts/models/account.py:57 accounts/serializers/account/account.py:220
-#: users/models/user.py:963
+#: accounts/models/account.py:57 accounts/serializers/account/account.py:228
+#: users/models/user/__init__.py:119
msgid "Source"
msgstr "來源"
@@ -394,7 +396,7 @@ msgstr "來源 ID"
#: terminal/templates/terminal/_msg_command_warning.html:8
#: terminal/templates/terminal/_msg_session_sharing.html:8
#: tickets/models/ticket/command_confirm.py:13
-#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/ws.py:38
+#: xpack/plugins/cloud/models.py:101 xpack/plugins/cloud/ws.py:37
msgid "Account"
msgstr "帳號"
@@ -470,7 +472,7 @@ msgstr "開始日期"
#: accounts/models/automations/backup_account.py:123
#: authentication/templates/authentication/_msg_oauth_bind.html:11
-#: notifications/notifications.py:186
+#: notifications/notifications.py:194
#: settings/templates/ldap/_msg_import_ldap_user.html:3
msgid "Time"
msgstr "時間"
@@ -483,13 +485,14 @@ msgstr "帳號備份快照"
#: accounts/serializers/account/backup.py:48
#: accounts/serializers/automations/base.py:56
#: assets/models/automations/base.py:122
-#: assets/serializers/automations/base.py:39
+#: assets/serializers/automations/base.py:40 xpack/plugins/cloud/models.py:240
+#: xpack/plugins/cloud/serializers/task.py:243
msgid "Trigger mode"
msgstr "觸發模式"
#: accounts/models/automations/backup_account.py:134 audits/models.py:203
#: terminal/models/session/sharing.py:125 xpack/plugins/cloud/manager.py:158
-#: xpack/plugins/cloud/models.py:228
+#: xpack/plugins/cloud/models.py:229
msgid "Reason"
msgstr "原因"
@@ -548,7 +551,7 @@ msgstr "SSH 金鑰推送方式"
#: accounts/models/automations/gather_account.py:58
#: accounts/serializers/account/backup.py:40
#: accounts/serializers/automations/change_secret.py:58
-#: settings/serializers/auth/ldap.py:101 settings/serializers/msg.py:44
+#: settings/serializers/auth/ldap.py:99 settings/serializers/msg.py:45
msgid "Recipient"
msgstr "收件人"
@@ -576,26 +579,27 @@ msgid "Date finished"
msgstr "結束日期"
#: accounts/models/automations/change_secret.py:44
-#: assets/models/automations/base.py:113 audits/models.py:208
+#: assets/models/automations/base.py:113
+#: assets/serializers/automations/base.py:39 audits/models.py:208
#: audits/serializers.py:54 ops/models/base.py:49 ops/models/job.py:234
-#: terminal/models/applet/applet.py:320 terminal/models/applet/host.py:140
+#: terminal/models/applet/applet.py:331 terminal/models/applet/host.py:140
#: terminal/models/component/status.py:30
#: terminal/models/virtualapp/virtualapp.py:99
#: terminal/serializers/applet.py:18 terminal/serializers/applet_host.py:136
-#: terminal/serializers/virtualapp.py:35 tickets/models/ticket/general.py:281
+#: terminal/serializers/virtualapp.py:35 tickets/models/ticket/general.py:284
#: tickets/serializers/super_ticket.py:13
-#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:224
-#: xpack/plugins/cloud/models.py:280
+#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:225
+#: xpack/plugins/cloud/models.py:292
msgid "Status"
msgstr "狀態"
#: accounts/models/automations/change_secret.py:47
-#: accounts/serializers/account/account.py:265
+#: accounts/serializers/account/account.py:273
#: accounts/templates/accounts/change_secret_failed_info.html:13
#: assets/const/automation.py:8
#: authentication/templates/authentication/passkey.html:173
#: authentication/views/base.py:42 authentication/views/base.py:43
-#: authentication/views/base.py:44 common/const/choices.py:20
+#: authentication/views/base.py:44 common/const/choices.py:67
#: settings/templates/ldap/_msg_import_ldap_user.html:26
msgid "Error"
msgstr "錯誤"
@@ -620,7 +624,7 @@ msgstr "登錄日期"
#: authentication/templates/authentication/_msg_different_city.html:9
#: authentication/templates/authentication/_msg_oauth_bind.html:9
#: terminal/serializers/storage.py:136 users/forms/profile.py:31
-#: users/forms/profile.py:114 users/models/user.py:900
+#: users/forms/profile.py:114 users/models/user/__init__.py:56
#: users/templates/users/_msg_user_created.html:12
#: xpack/plugins/cloud/serializers/account_attrs.py:26
msgid "Username"
@@ -652,7 +656,7 @@ msgstr "觸發方式"
#: audits/models.py:92 audits/serializers.py:84
#: authentication/serializers/connect_token_secret.py:119
#: authentication/templates/authentication/_access_key_modal.html:34
-#: perms/serializers/permission.py:42 perms/serializers/permission.py:64
+#: perms/serializers/permission.py:41 perms/serializers/permission.py:63
#: tickets/serializers/ticket/ticket.py:21
msgid "Action"
msgstr "動作"
@@ -666,7 +670,7 @@ msgid "Verify asset account"
msgstr "帳號驗證"
#: accounts/models/base.py:37 accounts/models/base.py:67
-#: accounts/serializers/account/account.py:448
+#: accounts/serializers/account/account.py:463
#: accounts/serializers/account/base.py:17
#: accounts/serializers/automations/change_secret.py:47
#: authentication/serializers/connect_token_secret.py:42
@@ -679,7 +683,7 @@ msgstr "密文類型"
#: accounts/serializers/account/base.py:20
#: authentication/models/temp_token.py:10
#: authentication/templates/authentication/_access_key_modal.html:31
-#: settings/serializers/auth/radius.py:19
+#: settings/serializers/auth/radius.py:20
msgid "Secret"
msgstr "金鑰"
@@ -699,27 +703,28 @@ msgstr "密碼規則"
#: assets/models/asset/common.py:159 assets/models/cmd_filter.py:21
#: assets/models/domain.py:19 assets/models/label.py:18
#: assets/models/platform.py:15 assets/models/platform.py:94
-#: assets/serializers/asset/common.py:149 assets/serializers/platform.py:152
-#: assets/serializers/platform.py:270
+#: assets/serializers/asset/common.py:149 assets/serializers/platform.py:153
+#: assets/serializers/platform.py:273
#: authentication/backends/passkey/models.py:10
+#: authentication/models/ssh_key.py:12
#: authentication/serializers/connect_token_secret.py:113
#: authentication/serializers/connect_token_secret.py:169 labels/models.py:11
#: ops/mixin.py:21 ops/models/adhoc.py:20 ops/models/celery.py:15
#: ops/models/celery.py:80 ops/models/job.py:142 ops/models/playbook.py:28
#: ops/serializers/job.py:18 orgs/models.py:82
#: perms/models/asset_permission.py:61 rbac/models/role.py:29
-#: settings/models.py:34 settings/models.py:183 settings/serializers/msg.py:86
-#: settings/serializers/terminal.py:9 terminal/models/applet/applet.py:33
-#: terminal/models/component/endpoint.py:12
+#: rbac/serializers/role.py:28 settings/models.py:34 settings/models.py:183
+#: settings/serializers/msg.py:89 settings/serializers/terminal.py:9
+#: terminal/models/applet/applet.py:34 terminal/models/component/endpoint.py:12
#: terminal/models/component/endpoint.py:109
#: terminal/models/component/storage.py:26 terminal/models/component/task.py:13
#: terminal/models/component/terminal.py:85
#: terminal/models/virtualapp/provider.py:10
#: terminal/models/virtualapp/virtualapp.py:19 tickets/api/ticket.py:87
#: users/forms/profile.py:32 users/models/group.py:13
-#: users/models/preference.py:11 users/models/user.py:901
-#: xpack/plugins/cloud/models.py:33 xpack/plugins/cloud/models.py:296
-#: xpack/plugins/cloud/serializers/task.py:74
+#: users/models/preference.py:11 users/models/user/__init__.py:57
+#: xpack/plugins/cloud/models.py:34 xpack/plugins/cloud/models.py:308
+#: xpack/plugins/cloud/serializers/task.py:75
msgid "Name"
msgstr "名稱"
@@ -730,7 +735,7 @@ msgstr "特權帳號"
#: accounts/models/base.py:70 assets/models/automations/base.py:21
#: assets/models/cmd_filter.py:39 assets/models/label.py:22
#: authentication/serializers/connect_token_secret.py:117
-#: terminal/models/applet/applet.py:40
+#: terminal/models/applet/applet.py:41
#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:269
msgid "Is active"
msgstr "啟用"
@@ -747,7 +752,7 @@ msgstr "系統平台"
msgid "Push params"
msgstr "帳號推送參數"
-#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:377
+#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:389
msgid "Account template"
msgstr "帳號模板"
@@ -768,10 +773,8 @@ msgid "Secret from login"
msgstr "與用戶登錄時相同"
#: accounts/models/virtual.py:18
-#, fuzzy
-#| msgid "Email account"
msgid "Virtual account"
-msgstr "信箱帳號"
+msgstr "虚拟账号"
#: accounts/models/virtual.py:28
msgid "Same with user"
@@ -851,99 +854,100 @@ msgstr "參數"
msgid "Exist policy"
msgstr "帳號存在策略"
-#: accounts/serializers/account/account.py:198 assets/models/label.py:21
+#: accounts/serializers/account/account.py:206 assets/models/label.py:21
#: assets/models/platform.py:95 assets/serializers/asset/common.py:125
-#: assets/serializers/cagegory.py:12 assets/serializers/platform.py:174
-#: assets/serializers/platform.py:271 perms/serializers/user_permission.py:26
+#: assets/serializers/cagegory.py:12 assets/serializers/platform.py:168
+#: assets/serializers/platform.py:274 perms/serializers/user_permission.py:26
#: settings/models.py:36 tickets/models/ticket/apply_application.py:13
#: users/models/preference.py:12
msgid "Category"
msgstr "類別"
-#: accounts/serializers/account/account.py:199
+#: accounts/serializers/account/account.py:207
#: accounts/serializers/automations/base.py:55 acls/models/command_acl.py:24
#: acls/serializers/command_acl.py:19 assets/models/automations/base.py:20
#: assets/models/cmd_filter.py:74 assets/models/platform.py:96
-#: assets/serializers/asset/common.py:126 assets/serializers/platform.py:154
-#: assets/serializers/platform.py:173 audits/serializers.py:53
+#: assets/serializers/asset/common.py:126 assets/serializers/platform.py:155
+#: assets/serializers/platform.py:167 audits/serializers.py:53
#: audits/serializers.py:170
#: authentication/serializers/connect_token_secret.py:126 ops/models/job.py:150
-#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:39
+#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:40
#: terminal/models/component/storage.py:58
#: terminal/models/component/storage.py:154 terminal/serializers/applet.py:29
-#: terminal/serializers/session.py:23 terminal/serializers/storage.py:271
-#: terminal/serializers/storage.py:284 tickets/models/comment.py:26
-#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16
-#: tickets/models/ticket/general.py:273 tickets/serializers/flow.py:53
+#: terminal/serializers/session.py:23 terminal/serializers/storage.py:281
+#: terminal/serializers/storage.py:294 tickets/models/comment.py:26
+#: tickets/models/flow.py:42 tickets/models/ticket/apply_application.py:16
+#: tickets/models/ticket/general.py:276 tickets/serializers/flow.py:25
#: tickets/serializers/ticket/ticket.py:19
msgid "Type"
msgstr "類型"
-#: accounts/serializers/account/account.py:214
+#: accounts/serializers/account/account.py:222
msgid "Asset not found"
msgstr "資產不存在"
-#: accounts/serializers/account/account.py:254
+#: accounts/serializers/account/account.py:262
msgid "Has secret"
msgstr "已託管密碼"
-#: accounts/serializers/account/account.py:264 ops/models/celery.py:83
-#: tickets/models/comment.py:13 tickets/models/ticket/general.py:46
-#: tickets/models/ticket/general.py:277 tickets/serializers/super_ticket.py:14
+#: accounts/serializers/account/account.py:272 ops/models/celery.py:83
+#: tickets/models/comment.py:13 tickets/models/ticket/general.py:49
+#: tickets/models/ticket/general.py:280 tickets/serializers/super_ticket.py:14
msgid "State"
msgstr "狀態"
-#: accounts/serializers/account/account.py:266
+#: accounts/serializers/account/account.py:274
msgid "Changed"
msgstr "已修改"
-#: accounts/serializers/account/account.py:276
+#: accounts/serializers/account/account.py:284
#: accounts/serializers/automations/base.py:22 acls/models/base.py:97
#: acls/templates/acls/asset_login_reminder.html:9
#: assets/models/automations/base.py:19
#: assets/serializers/automations/base.py:20 assets/serializers/domain.py:34
+#: assets/serializers/platform.py:176 assets/serializers/platform.py:208
#: authentication/api/connection_token.py:410 ops/models/base.py:17
#: ops/models/job.py:152 ops/serializers/job.py:19
-#: perms/serializers/permission.py:36
+#: perms/serializers/permission.py:35
#: terminal/templates/terminal/_msg_command_execute_alert.html:16
#: xpack/plugins/cloud/manager.py:83
msgid "Assets"
msgstr "資產"
-#: accounts/serializers/account/account.py:331
+#: accounts/serializers/account/account.py:339
msgid "Account already exists"
msgstr "帳號已存在"
-#: accounts/serializers/account/account.py:381
+#: accounts/serializers/account/account.py:389
#, python-format
msgid "Asset does not support this secret type: %s"
msgstr "資產不支持帳號類型: %s"
-#: accounts/serializers/account/account.py:413
+#: accounts/serializers/account/account.py:421
msgid "Account has exist"
msgstr "帳號已存在"
-#: accounts/serializers/account/account.py:443
+#: accounts/serializers/account/account.py:458
#: accounts/serializers/account/base.py:93
#: accounts/serializers/account/template.py:72
#: assets/serializers/asset/common.py:387
msgid "Spec info"
msgstr "特殊資訊"
-#: accounts/serializers/account/account.py:449
+#: accounts/serializers/account/account.py:464
#: authentication/serializers/connect_token_secret.py:159
#: authentication/templates/authentication/_access_key_modal.html:30
#: perms/models/perm_node.py:21 users/serializers/group.py:33
msgid "ID"
msgstr "ID"
-#: accounts/serializers/account/account.py:459 acls/serializers/base.py:116
+#: accounts/serializers/account/account.py:474 acls/serializers/base.py:116
#: acls/templates/acls/asset_login_reminder.html:8
#: acls/templates/acls/user_login_reminder.html:8
#: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:54
#: audits/models.py:90 audits/models.py:172 audits/models.py:271
#: audits/serializers.py:171 authentication/models/connection_token.py:32
-#: authentication/models/sso_token.py:16
+#: authentication/models/ssh_key.py:22 authentication/models/sso_token.py:16
#: notifications/models/notification.py:12
#: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:63
#: rbac/builtin.py:124 rbac/models/rolebinding.py:49
@@ -953,12 +957,13 @@ msgstr "ID"
#: terminal/serializers/command.py:16
#: terminal/templates/terminal/_msg_command_warning.html:6
#: terminal/templates/terminal/_msg_session_sharing.html:6
-#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:1124
-#: users/models/user.py:1168
+#: tickets/models/comment.py:21 tickets/serializers/flow.py:15
+#: users/const.py:14 users/models/user/__init__.py:281
+#: users/models/user/__init__.py:308
msgid "User"
msgstr "用戶"
-#: accounts/serializers/account/account.py:460
+#: accounts/serializers/account/account.py:475
#: authentication/templates/authentication/_access_key_modal.html:33
#: terminal/notifications.py:158 terminal/notifications.py:207
msgid "Date"
@@ -984,7 +989,7 @@ msgstr "資產類型"
#: accounts/serializers/account/base.py:33 terminal/serializers/storage.py:149
msgid "Passphrase"
-msgstr "密碼"
+msgstr "密鑰密碼"
#: accounts/serializers/account/base.py:96
msgid ""
@@ -1037,14 +1042,14 @@ msgstr "關聯平台,可配置推送參數,如果不關聯,將使用默認
#: accounts/serializers/account/virtual.py:19 assets/models/cmd_filter.py:40
#: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:26
#: ops/models/job.py:158 ops/models/playbook.py:31 rbac/models/role.py:37
-#: settings/models.py:39 terminal/models/applet/applet.py:45
-#: terminal/models/applet/applet.py:321 terminal/models/applet/host.py:143
+#: settings/models.py:39 terminal/models/applet/applet.py:46
+#: terminal/models/applet/applet.py:332 terminal/models/applet/host.py:143
#: terminal/models/component/endpoint.py:25
#: terminal/models/component/endpoint.py:119
#: terminal/models/session/session.py:47
#: terminal/models/virtualapp/virtualapp.py:28 tickets/models/comment.py:32
-#: tickets/models/ticket/general.py:295 users/models/user.py:935
-#: xpack/plugins/cloud/models.py:40 xpack/plugins/cloud/models.py:121
+#: tickets/models/ticket/general.py:298 users/models/user/__init__.py:91
+#: xpack/plugins/cloud/models.py:41 xpack/plugins/cloud/models.py:122
msgid "Comment"
msgstr "備註"
@@ -1060,7 +1065,7 @@ msgstr ""
#: accounts/serializers/automations/base.py:23
#: assets/models/asset/common.py:164 assets/serializers/asset/common.py:152
-#: assets/serializers/automations/base.py:21 perms/serializers/permission.py:37
+#: assets/serializers/automations/base.py:21 perms/serializers/permission.py:36
msgid "Nodes"
msgstr "節點"
@@ -1084,13 +1089,13 @@ msgstr "SSH 金鑰更改方式"
#: accounts/serializers/automations/change_secret.py:57
msgid "Please enter your account username"
-msgstr "請輸入 MFA 驗證碼"
+msgstr "請輸入您的帳戶使用者名稱"
#: accounts/serializers/automations/change_secret.py:62
msgid ""
"Secret parameter settings, currently only effective for assets of the host "
"type."
-msgstr "密文參數設定, 目前只對宿主型的資產有效。"
+msgstr "參數設置,目前只對 AIX LINUX UNIX 類型的資產有效。"
#: accounts/serializers/automations/change_secret.py:84
msgid "* Please enter the correct password length"
@@ -1105,17 +1110,17 @@ msgstr "* 密碼長度範圍 6-30 位"
msgid "Automation task execution"
msgstr "自動化任務執行歷史"
-#: accounts/signal_handlers.py:47
+#: accounts/signal_handlers.py:48
#, python-format
msgid "Push related accounts to assets: %s, by system"
msgstr "推送帳號到資產: %s, 由系統執行"
-#: accounts/signal_handlers.py:56
+#: accounts/signal_handlers.py:57
#, python-format
msgid "Add account: %s"
msgstr "添加帳號: %s"
-#: accounts/signal_handlers.py:58
+#: accounts/signal_handlers.py:59
#, python-format
msgid "Delete account: %s"
msgstr "刪除帳號: %s"
@@ -1227,12 +1232,12 @@ msgid "Notify"
msgstr "通知"
#: acls/models/base.py:37 assets/models/cmd_filter.py:76
-#: terminal/models/component/endpoint.py:112 xpack/plugins/cloud/models.py:302
+#: terminal/models/component/endpoint.py:112 xpack/plugins/cloud/models.py:314
msgid "Priority"
msgstr "優先度"
#: acls/models/base.py:38 assets/models/cmd_filter.py:76
-#: terminal/models/component/endpoint.py:113 xpack/plugins/cloud/models.py:303
+#: terminal/models/component/endpoint.py:113 xpack/plugins/cloud/models.py:315
msgid "1-100, the lower the value will be match first"
msgstr "優先度可選範圍為 1-100 (數值越小越優先)"
@@ -1244,22 +1249,24 @@ msgstr "審批人"
#: acls/models/base.py:43 assets/models/asset/common.py:165
#: authentication/models/access_key.py:25
#: authentication/models/connection_token.py:53
+#: authentication/models/ssh_key.py:13
#: authentication/templates/authentication/_access_key_modal.html:32
#: perms/models/asset_permission.py:82
#: terminal/models/component/endpoint.py:120
-#: terminal/models/session/sharing.py:29 tickets/const.py:36
+#: terminal/models/session/sharing.py:29 terminal/serializers/terminal.py:44
+#: tickets/const.py:36
msgid "Active"
msgstr "啟用中"
-#: acls/models/base.py:81 perms/serializers/permission.py:32
-#: users/models/preference.py:16 users/serializers/group.py:21
-#: users/serializers/user.py:424
+#: acls/models/base.py:81 perms/serializers/permission.py:31
+#: tickets/models/flow.py:23 users/models/preference.py:16
+#: users/serializers/group.py:21 users/serializers/user.py:424
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:128
-#: assets/serializers/asset/common.py:386 perms/serializers/permission.py:45
+#: assets/serializers/asset/common.py:386 perms/serializers/permission.py:44
#: perms/serializers/user_permission.py:75 rbac/tree.py:35
msgid "Accounts"
msgstr "帳號管理"
@@ -1274,13 +1281,13 @@ msgid "Command"
msgstr "命令"
#: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59
-#: xpack/plugins/cloud/models.py:343
+#: xpack/plugins/cloud/models.py:355
msgid "Regex"
msgstr "正則表達式"
#: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79
#: settings/models.py:184 settings/serializers/feature.py:19
-#: settings/serializers/msg.py:75 xpack/plugins/license/models.py:30
+#: settings/serializers/msg.py:78 xpack/plugins/license/models.py:30
msgid "Content"
msgstr "內容"
@@ -1379,7 +1386,7 @@ msgid "None of the reviewers belong to Organization `{}`"
msgstr "所有覆核人都不屬於組織 `{}`"
#: acls/serializers/rules/rules.py:20
-#: xpack/plugins/cloud/serializers/task.py:149
+#: xpack/plugins/cloud/serializers/task.py:150
msgid "IP address invalid: `{}`"
msgstr "IP 地址無效: `{}`"
@@ -1395,7 +1402,7 @@ msgstr ""
#: authentication/templates/authentication/_msg_oauth_bind.html:12
#: authentication/templates/authentication/_msg_rest_password_success.html:8
#: authentication/templates/authentication/_msg_rest_public_key_success.html:8
-#: xpack/plugins/cloud/models.py:378
+#: xpack/plugins/cloud/models.py:390
msgid "IP"
msgstr "IP"
@@ -1481,7 +1488,7 @@ msgstr "不能刪除根節點 ({})"
msgid "Deletion failed and the node contains assets"
msgstr "刪除失敗,節點包含資產"
-#: assets/api/tree.py:49 assets/serializers/node.py:42
+#: assets/api/tree.py:48 assets/serializers/node.py:42
msgid "The same level node name cannot be the same"
msgstr "同級別節點名字不能重複"
@@ -1489,32 +1496,32 @@ msgstr "同級別節點名字不能重複"
msgid "App Assets"
msgstr "資產管理"
-#: assets/automations/base/manager.py:191
+#: assets/automations/base/manager.py:187
msgid "{} disabled"
msgstr "{} 已禁用"
-#: assets/automations/base/manager.py:254
+#: assets/automations/base/manager.py:250
msgid " - Platform {} ansible disabled"
msgstr " - 平台 {} Ansible 已禁用, 無法執行任務"
-#: assets/automations/base/manager.py:327
+#: assets/automations/base/manager.py:323
msgid ">>> Task preparation phase"
msgstr ">>> 任務準備階段"
-#: assets/automations/base/manager.py:330
+#: assets/automations/base/manager.py:326
#, python-brace-format
msgid ">>> Executing tasks in batches, total {runner_count}"
msgstr ">>> 分次執行任務,總共 {runner_count}"
-#: assets/automations/base/manager.py:332
+#: assets/automations/base/manager.py:328
msgid ">>> Start executing tasks"
msgstr ">>> 開始執行任務"
-#: assets/automations/base/manager.py:334
+#: assets/automations/base/manager.py:330
msgid ">>> No tasks need to be executed"
msgstr ">>> 沒有需要執行的任務"
-#: assets/automations/base/manager.py:339
+#: assets/automations/base/manager.py:335
#, python-brace-format
msgid ">>> Begin executing batch {index} of tasks"
msgstr ">>> 開始執行第 {index} 批任務"
@@ -1566,7 +1573,7 @@ msgid "Gather facts"
msgstr "收集資產資訊"
#: assets/const/base.py:32 audits/const.py:58
-#: terminal/serializers/applet_host.py:32 users/models/user.py:688
+#: terminal/serializers/applet_host.py:32 users/models/user/_auth.py:32
msgid "Disabled"
msgstr "禁用"
@@ -1576,13 +1583,13 @@ msgstr "禁用"
msgid "Basic"
msgstr "基本"
-#: assets/const/base.py:34 assets/const/protocol.py:275
+#: assets/const/base.py:34 assets/const/protocol.py:292
#: 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:76
+#: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:76
#: settings/serializers/feature.py:49 settings/serializers/msg.py:30
#: terminal/models/component/endpoint.py:13 terminal/serializers/applet.py:17
#: xpack/plugins/cloud/manager.py:83
@@ -1600,7 +1607,7 @@ msgstr "雲服務"
#: assets/const/category.py:14 assets/models/asset/gpt.py:11
#: assets/models/asset/web.py:16 audits/const.py:45
-#: terminal/models/applet/applet.py:27 users/const.py:64
+#: terminal/models/applet/applet.py:28 users/const.py:64
msgid "Web"
msgstr "Web"
@@ -1620,7 +1627,7 @@ msgstr "私有雲"
msgid "Kubernetes"
msgstr "Kubernetes"
-#: assets/const/device.py:7 terminal/models/applet/applet.py:26
+#: assets/const/device.py:7 terminal/models/applet/applet.py:27
#: tickets/const.py:9
msgid "General"
msgstr "一般"
@@ -1686,100 +1693,119 @@ msgid "Security"
msgstr "安全"
#: assets/const/protocol.py:83
-msgid "Security layer to use for the connection"
-msgstr "連接 RDP 使用的安全層"
+msgid ""
+"Security layer to use for the connection:
Any
Automatically select the "
+"security mode based on the security protocols supported by both the client "
+"and the server
RDP
Legacy RDP encryption. This mode is generally only "
+"used for older Windows servers or in cases where a standard Windows login "
+"screen is desired
TLS
RDP authentication and encryption implemented "
+"via TLS.
NLA
This mode uses TLS encryption and requires the username "
+"and password to be given in advance"
+msgstr ""
+"連接的安全層:
Any
根據客戶端和伺服器支援的安全協議自動選擇安全模式"
+"
RDP
傳統的 RDP 加密模式。通常僅用於較舊的 Windows 伺服器或需要標準 "
+"Windows 登入螢幕的情況
TLS
通過 TLS 實現的 RDP 認證和加密
NLA
此"
+"模式使用 TLS 加密,並要求提前提供用戶名和密碼
"
-#: assets/const/protocol.py:89
+#: assets/const/protocol.py:100
msgid "AD domain"
msgstr "AD 網域"
-#: assets/const/protocol.py:104
+#: assets/const/protocol.py:115
msgid "Username prompt"
msgstr "使用者名稱提示"
-#: assets/const/protocol.py:105
+#: assets/const/protocol.py:116
msgid "We will send username when we see this prompt"
msgstr "當我們看到這個提示時,我們將發送使用者名稱"
-#: assets/const/protocol.py:110
+#: assets/const/protocol.py:121
msgid "Password prompt"
msgstr "密碼提示"
-#: assets/const/protocol.py:111
+#: assets/const/protocol.py:122
msgid "We will send password when we see this prompt"
msgstr "當我們看到這個提示時,我們將發送密碼"
-#: assets/const/protocol.py:116
+#: assets/const/protocol.py:127
msgid "Success prompt"
msgstr "成功提示"
-#: assets/const/protocol.py:117
+#: assets/const/protocol.py:128
msgid "We will consider login success when we see this prompt"
msgstr "當我們看到這個提示時,我們將認為登錄成功"
-#: assets/const/protocol.py:128 assets/models/asset/database.py:10
-#: settings/serializers/msg.py:48
+#: assets/const/protocol.py:139 assets/models/asset/database.py:10
+#: settings/serializers/msg.py:49
msgid "Use SSL"
msgstr "使用 SSL"
-#: assets/const/protocol.py:163
+#: assets/const/protocol.py:174
msgid "SYSDBA"
msgstr "SYSDBA"
-#: assets/const/protocol.py:164
+#: assets/const/protocol.py:175
msgid "Connect as SYSDBA"
msgstr "以 SYSDBA 角色連接"
-#: assets/const/protocol.py:179
+#: assets/const/protocol.py:190
msgid ""
"SQL Server version, Different versions have different connection drivers"
msgstr "SQL Server 版本,不同版本有不同的連接驅動"
-#: assets/const/protocol.py:209
+#: assets/const/protocol.py:220
msgid "Auth source"
msgstr "認證資料庫"
-#: assets/const/protocol.py:210
+#: assets/const/protocol.py:221
msgid "The database to authenticate against"
msgstr "要進行身份驗證的資料庫"
-#: assets/const/protocol.py:222
+#: assets/const/protocol.py:226 authentication/models/connection_token.py:43
+msgid "Connect options"
+msgstr "連接項"
+
+#: assets/const/protocol.py:227
+msgid "The connection specific options eg. retryWrites=false&retryReads=false"
+msgstr "連接特定選項,例如。重試寫入=假&重試讀取=假"
+
+#: assets/const/protocol.py:239
msgid "Auth username"
msgstr "使用使用者名稱認證"
-#: assets/const/protocol.py:245
+#: assets/const/protocol.py:262
msgid "Safe mode"
msgstr "安全模式"
-#: assets/const/protocol.py:247
+#: assets/const/protocol.py:264
msgid ""
"When safe mode is enabled, some operations will be disabled, such as: New "
"tab, right click, visit other website, etc."
msgstr ""
"當安全模式啟用時,一些操作將被禁用,例如:新建標籤頁、右鍵、訪問其它網站 等"
-#: assets/const/protocol.py:252 assets/models/asset/web.py:9
+#: assets/const/protocol.py:269 assets/models/asset/web.py:9
#: assets/serializers/asset/info/spec.py:16
msgid "Autofill"
msgstr "自動代填"
-#: assets/const/protocol.py:260 assets/models/asset/web.py:10
+#: assets/const/protocol.py:277 assets/models/asset/web.py:10
msgid "Username selector"
msgstr "使用者名稱選擇器"
-#: assets/const/protocol.py:265 assets/models/asset/web.py:11
+#: assets/const/protocol.py:282 assets/models/asset/web.py:11
msgid "Password selector"
msgstr "密碼選擇器"
-#: assets/const/protocol.py:270 assets/models/asset/web.py:12
+#: assets/const/protocol.py:287 assets/models/asset/web.py:12
msgid "Submit selector"
msgstr "確認按鈕選擇器"
-#: assets/const/protocol.py:293
+#: assets/const/protocol.py:310
msgid "API mode"
msgstr "API 模式"
-#: assets/const/types.py:251
+#: assets/const/types.py:248
msgid "All types"
msgstr "所有類型"
@@ -1796,7 +1822,7 @@ msgid "Cloud"
msgstr "雲服務"
#: assets/models/asset/common.py:94 assets/models/platform.py:16
-#: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:77
+#: settings/serializers/auth/radius.py:18 settings/serializers/auth/sms.py:77
#: settings/serializers/msg.py:31 terminal/serializers/storage.py:133
#: xpack/plugins/cloud/serializers/account_attrs.py:73
msgid "Port"
@@ -1807,10 +1833,10 @@ msgstr "埠"
msgid "Address"
msgstr "地址"
-#: assets/models/asset/common.py:161 assets/models/platform.py:134
+#: assets/models/asset/common.py:161 assets/models/platform.py:149
#: authentication/backends/passkey/models.py:12
#: authentication/serializers/connect_token_secret.py:118
-#: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:373
+#: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:385
msgid "Platform"
msgstr "系統平台"
@@ -1863,13 +1889,13 @@ msgstr "用戶端金鑰"
msgid "Allow invalid cert"
msgstr "忽略證書校驗"
-#: assets/models/asset/gpt.py:8 settings/serializers/feature.py:87
+#: assets/models/asset/gpt.py:8 settings/serializers/feature.py:89
msgid "Proxy"
msgstr "代理"
#: assets/models/automations/base.py:18 assets/models/cmd_filter.py:32
#: assets/models/node.py:553 perms/models/asset_permission.py:72
-#: tickets/models/ticket/apply_asset.py:14 xpack/plugins/cloud/models.py:374
+#: tickets/models/ticket/apply_asset.py:14 xpack/plugins/cloud/models.py:386
msgid "Node"
msgstr "節點"
@@ -1890,7 +1916,7 @@ msgstr "資產自動化任務"
# msgstr "備註"
#: assets/models/automations/base.py:114 assets/models/cmd_filter.py:41
#: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:241
-#: users/models/user.py:1171
+#: users/models/user/__init__.py:311
msgid "Date created"
msgstr "創建日期"
@@ -1911,17 +1937,17 @@ msgid "Date verified"
msgstr "校驗日期"
#: assets/models/cmd_filter.py:28 perms/models/asset_permission.py:66
-#: users/models/group.py:25 users/models/user.py:907
+#: users/models/group.py:25 users/models/user/__init__.py:63
msgid "User group"
msgstr "用戶組"
#: assets/models/cmd_filter.py:42 common/db/models.py:35
-#: users/models/user.py:983
+#: users/models/user/__init__.py:139
msgid "Date updated"
msgstr "更新日期"
#: assets/models/cmd_filter.py:44 assets/models/cmd_filter.py:91
-#: common/db/models.py:32 users/models/user.py:945
+#: common/db/models.py:32 users/models/user/__init__.py:101
#: users/serializers/group.py:32
msgid "Created by"
msgstr "創建者"
@@ -1958,7 +1984,7 @@ msgstr "收藏的資產"
msgid "Gateway"
msgstr "網關"
-#: assets/models/label.py:15 rbac/const.py:6 users/models/user.py:1150
+#: assets/models/label.py:15 rbac/const.py:6
msgid "System"
msgstr "系統"
@@ -1974,13 +2000,25 @@ msgstr "值"
#: assets/models/label.py:40 assets/serializers/cagegory.py:10
#: assets/serializers/cagegory.py:17 assets/serializers/cagegory.py:23
-#: assets/serializers/platform.py:153
+#: assets/serializers/platform.py:154
#: authentication/serializers/connect_token_secret.py:124
#: common/serializers/common.py:85 labels/serializers.py:45
-#: settings/serializers/msg.py:87
+#: settings/serializers/msg.py:90
msgid "Label"
msgstr "標籤"
+#: assets/models/my_asset.py:12 assets/serializers/my_asset.py:16
+msgid "Custom Name"
+msgstr "自訂名稱"
+
+#: assets/models/my_asset.py:13 assets/serializers/my_asset.py:17
+msgid "Custom Comment"
+msgstr "自訂備註"
+
+#: assets/models/my_asset.py:18 rbac/tree.py:54
+msgid "My assets"
+msgstr "我的資產"
+
#: assets/models/node.py:168
msgid "New node"
msgstr "新節點"
@@ -2013,7 +2051,7 @@ msgstr "主要的"
msgid "Required"
msgstr "必須的"
-#: assets/models/platform.py:19 assets/serializers/platform.py:155
+#: assets/models/platform.py:19 assets/serializers/platform.py:156
#: terminal/models/component/storage.py:28
#: xpack/plugins/cloud/providers/nutanix.py:30
msgid "Default"
@@ -2023,7 +2061,7 @@ msgstr "默認"
msgid "Public"
msgstr "開放的"
-#: assets/models/platform.py:21 assets/serializers/platform.py:83
+#: assets/models/platform.py:21 assets/serializers/platform.py:84
#: settings/serializers/settings.py:95
#: users/templates/users/reset_password.html:29
msgid "Setting"
@@ -2031,7 +2069,7 @@ msgstr "設置"
#: assets/models/platform.py:38 audits/const.py:59
#: authentication/backends/passkey/models.py:11 settings/models.py:38
-#: terminal/serializers/applet_host.py:33 users/models/user.py:689
+#: terminal/serializers/applet_host.py:33 users/models/user/_auth.py:33
msgid "Enabled"
msgstr "啟用"
@@ -2039,11 +2077,11 @@ msgstr "啟用"
msgid "Ansible config"
msgstr "Ansible 配置"
-#: assets/models/platform.py:41 assets/serializers/platform.py:34
+#: assets/models/platform.py:41 assets/serializers/platform.py:35
msgid "Ping enabled"
msgstr "啟用資產探活"
-#: assets/models/platform.py:42 assets/serializers/platform.py:35
+#: assets/models/platform.py:42 assets/serializers/platform.py:36
msgid "Ping method"
msgstr "資產探活方式"
@@ -2052,12 +2090,12 @@ msgid "Ping params"
msgstr "資產探活參數"
#: assets/models/platform.py:45 assets/models/platform.py:69
-#: assets/serializers/platform.py:37
+#: assets/serializers/platform.py:38
msgid "Gather facts enabled"
msgstr "啟用收集資產資訊"
#: assets/models/platform.py:47 assets/models/platform.py:71
-#: assets/serializers/platform.py:41
+#: assets/serializers/platform.py:42
msgid "Gather facts method"
msgstr "收集資訊方式"
@@ -2065,11 +2103,11 @@ msgstr "收集資訊方式"
msgid "Gather facts params"
msgstr "收集資訊參數"
-#: assets/models/platform.py:51 assets/serializers/platform.py:51
+#: assets/models/platform.py:51 assets/serializers/platform.py:52
msgid "Change secret enabled"
msgstr "啟用改密"
-#: assets/models/platform.py:53 assets/serializers/platform.py:55
+#: assets/models/platform.py:53 assets/serializers/platform.py:56
msgid "Change secret method"
msgstr "改密方式"
@@ -2077,11 +2115,11 @@ msgstr "改密方式"
msgid "Change secret params"
msgstr "改密參數"
-#: assets/models/platform.py:57 assets/serializers/platform.py:58
+#: assets/models/platform.py:57 assets/serializers/platform.py:59
msgid "Push account enabled"
msgstr "啟用帳號推送"
-#: assets/models/platform.py:59 assets/serializers/platform.py:62
+#: assets/models/platform.py:59 assets/serializers/platform.py:63
msgid "Push account method"
msgstr "帳號推送方式"
@@ -2089,11 +2127,11 @@ msgstr "帳號推送方式"
msgid "Push account params"
msgstr "帳號推送參數"
-#: assets/models/platform.py:63 assets/serializers/platform.py:44
+#: assets/models/platform.py:63 assets/serializers/platform.py:45
msgid "Verify account enabled"
msgstr "開啟帳號驗證"
-#: assets/models/platform.py:65 assets/serializers/platform.py:48
+#: assets/models/platform.py:65 assets/serializers/platform.py:49
msgid "Verify account method"
msgstr "帳號驗證方式"
@@ -2105,7 +2143,7 @@ msgstr "帳號驗證參數"
msgid "Remove account enabled"
msgstr "開啟帳號移除"
-#: assets/models/platform.py:77 assets/serializers/platform.py:72
+#: assets/models/platform.py:77 assets/serializers/platform.py:73
msgid "Remove account method"
msgstr "帳號移除方式"
@@ -2113,7 +2151,7 @@ msgstr "帳號移除方式"
msgid "Remove account params"
msgstr "帳號移除參數"
-#: assets/models/platform.py:97 tickets/models/ticket/general.py:298
+#: assets/models/platform.py:97 tickets/models/ticket/general.py:301
msgid "Meta"
msgstr "元數據"
@@ -2121,23 +2159,23 @@ msgstr "元數據"
msgid "Internal"
msgstr "內建"
-#: assets/models/platform.py:102 assets/serializers/platform.py:172
+#: assets/models/platform.py:102 assets/serializers/platform.py:166
msgid "Charset"
msgstr "編碼"
-#: assets/models/platform.py:104 assets/serializers/platform.py:207
+#: assets/models/platform.py:104 assets/serializers/platform.py:204
msgid "Gateway enabled"
msgstr "啟用網域"
-#: assets/models/platform.py:106 assets/serializers/platform.py:200
+#: assets/models/platform.py:106 assets/serializers/platform.py:197
msgid "Su enabled"
msgstr "啟用帳號切換"
-#: assets/models/platform.py:107 assets/serializers/platform.py:178
+#: assets/models/platform.py:107 assets/serializers/platform.py:172
msgid "Su method"
msgstr "帳號切換方式"
-#: assets/models/platform.py:108 assets/serializers/platform.py:181
+#: assets/models/platform.py:108 assets/serializers/platform.py:175
msgid "Custom fields"
msgstr "自訂屬性"
@@ -2152,12 +2190,12 @@ msgid ""
"type"
msgstr "資產中批次更新平台,不符合平台類型跳過的資產"
-#: assets/serializers/asset/common.py:127 assets/serializers/platform.py:175
+#: assets/serializers/asset/common.py:127 assets/serializers/platform.py:169
#: authentication/serializers/connect_token_secret.py:30
#: authentication/serializers/connect_token_secret.py:75
-#: perms/models/asset_permission.py:76 perms/serializers/permission.py:46
-#: perms/serializers/user_permission.py:74 xpack/plugins/cloud/models.py:376
-#: xpack/plugins/cloud/serializers/task.py:34
+#: perms/models/asset_permission.py:76 perms/serializers/permission.py:45
+#: perms/serializers/user_permission.py:74 xpack/plugins/cloud/models.py:388
+#: xpack/plugins/cloud/serializers/task.py:35
msgid "Protocols"
msgstr "協議組"
@@ -2216,7 +2254,7 @@ msgid "Model"
msgstr "型號"
#: assets/serializers/asset/info/gathered.py:8
-#: tickets/models/ticket/general.py:297
+#: tickets/models/ticket/general.py:300
msgid "Serial number"
msgstr "序號"
@@ -2271,8 +2309,8 @@ msgid ""
"the zone, the connection is routed through the gateway."
msgstr "網關是網域的網路代理,當連接網域內的資產時,連接將由網關進行路由。"
-#: assets/serializers/domain.py:24 orgs/serializers.py:13
-#: perms/serializers/permission.py:40
+#: assets/serializers/domain.py:24 assets/serializers/platform.py:177
+#: orgs/serializers.py:13 perms/serializers/permission.py:39
msgid "Assets amount"
msgstr "資產數量"
@@ -2288,83 +2326,83 @@ msgstr "值"
msgid "Can't contains: /"
msgstr "不能包含: /"
-#: assets/serializers/platform.py:34
+#: assets/serializers/platform.py:35
msgid "Enable asset detection"
msgstr "啟用資產探活"
-#: assets/serializers/platform.py:38
+#: assets/serializers/platform.py:39
msgid "Enable asset information collection"
msgstr "啟用蒐集資產資訊"
-#: assets/serializers/platform.py:45
+#: assets/serializers/platform.py:46
msgid "Enable account verification"
msgstr "開啟帳號驗證"
-#: assets/serializers/platform.py:52
+#: assets/serializers/platform.py:53
msgid "Enable account secret auto change"
msgstr "启用更改密码"
-#: assets/serializers/platform.py:59
+#: assets/serializers/platform.py:60
msgid "Enable account auto push"
msgstr "启用账号推送"
-#: assets/serializers/platform.py:65
+#: assets/serializers/platform.py:66
msgid "Gather accounts enabled"
msgstr "啟用帳號收集"
-#: assets/serializers/platform.py:66
+#: assets/serializers/platform.py:67
msgid "Enable account collection"
msgstr "自动收集账号"
-#: assets/serializers/platform.py:69
+#: assets/serializers/platform.py:70
msgid "Gather accounts method"
msgstr "收集帳號方式"
-#: assets/serializers/platform.py:75
+#: assets/serializers/platform.py:76
msgid "Remove accounts enabled"
msgstr "开启账号移除"
-#: assets/serializers/platform.py:76
+#: assets/serializers/platform.py:77
msgid "Enable account remove"
msgstr "启动账号移除"
-#: assets/serializers/platform.py:84
+#: assets/serializers/platform.py:85
msgid "Port from addr"
msgstr "埠來自地址"
-#: assets/serializers/platform.py:96
+#: assets/serializers/platform.py:97
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:101
+#: assets/serializers/platform.py:102
msgid "This protocol is required, and it must be set when adding assets."
msgstr "該協議是必填的,添加資產時必須設置"
-#: assets/serializers/platform.py:104
+#: assets/serializers/platform.py:105
msgid ""
"This protocol is default, when adding assets, it will be displayed by "
"default."
msgstr "該協議是預設的,添加資產時,將默認顯示"
-#: assets/serializers/platform.py:107
+#: assets/serializers/platform.py:108
msgid "This protocol is public, asset will show this protocol to user"
msgstr "該協議是公開的,資產將向用戶顯示該協議並可以連接使用"
-#: assets/serializers/platform.py:156
+#: assets/serializers/platform.py:157
msgid "Help text"
msgstr "幫助"
-#: assets/serializers/platform.py:157
+#: assets/serializers/platform.py:158
msgid "Choices"
msgstr "選擇"
-#: assets/serializers/platform.py:176
+#: assets/serializers/platform.py:170
msgid "Automation"
msgstr "自動化"
-#: assets/serializers/platform.py:202
+#: assets/serializers/platform.py:199
msgid ""
"Login with account when accessing assets, then automatically switch to "
"another, similar to logging in with a regular account and then switching to "
@@ -2373,19 +2411,19 @@ msgstr ""
"在訪問資產時使用帳戶登入,然後自動切換到另一個帳戶,就像用普通帳戶登入然後切"
"換到 root 一樣"
-#: assets/serializers/platform.py:208
+#: assets/serializers/platform.py:205
msgid "Assets can be connected using a zone gateway"
msgstr "資產可以使用區域網關進行連接"
-#: assets/serializers/platform.py:210
+#: assets/serializers/platform.py:207
msgid "Default Domain"
msgstr "默認網域"
-#: assets/serializers/platform.py:231
+#: assets/serializers/platform.py:229
msgid "type is required"
msgstr "類型 該欄位是必填項。"
-#: assets/serializers/platform.py:246
+#: assets/serializers/platform.py:244
msgid "Protocols is required"
msgstr "協議是必填的"
@@ -2520,8 +2558,8 @@ msgstr "創建"
msgid "Connect"
msgstr "連接"
-#: audits/const.py:30 authentication/templates/authentication/login.html:290
-#: authentication/templates/authentication/login.html:362
+#: audits/const.py:30 authentication/templates/authentication/login.html:329
+#: authentication/templates/authentication/login.html:401
#: templates/_header_bar.html:101
msgid "Login"
msgstr "登錄"
@@ -2580,11 +2618,11 @@ msgstr "任務"
msgid "-"
msgstr "-"
-#: audits/handler.py:116
+#: audits/handler.py:128
msgid "Yes"
msgstr "是"
-#: audits/handler.py:116
+#: audits/handler.py:128
msgid "No"
msgstr "否"
@@ -2671,8 +2709,8 @@ msgstr "登錄 IP"
#: audits/models.py:200 audits/serializers.py:52
#: authentication/templates/authentication/_mfa_confirm_modal.html:14
-#: users/forms/profile.py:63 users/models/user.py:923
-#: users/serializers/profile.py:97
+#: users/forms/profile.py:63 users/models/user/__init__.py:79
+#: users/serializers/profile.py:70
msgid "MFA"
msgstr "MFA"
@@ -2719,7 +2757,7 @@ msgstr "原因描述"
#: audits/serializers.py:70 audits/serializers.py:184
msgid "Auth backend display"
-msgstr "没有匹配到认证后端"
+msgstr "认证代币描述"
#: audits/serializers.py:134
#, python-format
@@ -2729,7 +2767,7 @@ msgstr "用户 %s %s 了当前资源"
#: audits/serializers.py:172 authentication/models/connection_token.py:47
#: authentication/models/temp_token.py:13 perms/models/asset_permission.py:80
#: tickets/models/ticket/apply_application.py:31
-#: tickets/models/ticket/apply_asset.py:20 users/models/user.py:942
+#: tickets/models/ticket/apply_asset.py:20 users/models/user/__init__.py:98
msgid "Date expired"
msgstr "失效日期"
@@ -2762,30 +2800,30 @@ msgstr "認證令牌"
#: audits/signal_handlers/login_log.py:37 authentication/notifications.py:73
#: authentication/views/login.py:78 notifications/backends/__init__.py:11
-#: settings/serializers/auth/wecom.py:10 settings/serializers/auth/wecom.py:15
-#: users/models/user.py:798 users/models/user.py:966
+#: settings/serializers/auth/wecom.py:11 settings/serializers/auth/wecom.py:16
+#: users/models/user/__init__.py:122 users/models/user/_source.py:18
msgid "WeCom"
msgstr "企業微信"
-#: audits/signal_handlers/login_log.py:38 authentication/views/feishu.py:105
+#: audits/signal_handlers/login_log.py:38 authentication/views/feishu.py:97
#: authentication/views/login.py:90 notifications/backends/__init__.py:14
-#: settings/serializers/auth/feishu.py:10
-#: settings/serializers/auth/feishu.py:12 users/models/user.py:800
-#: users/models/user.py:972
+#: settings/serializers/auth/feishu.py:12
+#: settings/serializers/auth/feishu.py:14 users/models/user/__init__.py:128
+#: users/models/user/_source.py:20
msgid "FeiShu"
msgstr "飛書"
#: audits/signal_handlers/login_log.py:40 authentication/views/login.py:102
-#: authentication/views/slack.py:87 notifications/backends/__init__.py:16
-#: settings/serializers/auth/slack.py:10 settings/serializers/auth/slack.py:12
-#: users/models/user.py:802 users/models/user.py:978
+#: authentication/views/slack.py:79 notifications/backends/__init__.py:16
+#: settings/serializers/auth/slack.py:11 settings/serializers/auth/slack.py:13
+#: users/models/user/__init__.py:134 users/models/user/_source.py:22
msgid "Slack"
msgstr "Slack"
-#: audits/signal_handlers/login_log.py:41 authentication/views/dingtalk.py:159
+#: audits/signal_handlers/login_log.py:41 authentication/views/dingtalk.py:151
#: authentication/views/login.py:84 notifications/backends/__init__.py:12
-#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:799
-#: users/models/user.py:969
+#: settings/serializers/auth/dingtalk.py:11 users/models/user/__init__.py:125
+#: users/models/user/_source.py:19
msgid "DingTalk"
msgstr "釘釘"
@@ -2800,11 +2838,11 @@ msgstr "臨時密碼"
msgid "Passkey"
msgstr "Passkey"
-#: audits/tasks.py:130
+#: audits/tasks.py:131
msgid "Clean audits session task log"
msgstr "清理資產審計會話任務日誌"
-#: audits/tasks.py:143
+#: audits/tasks.py:145
msgid "Upload FTP file to external storage"
msgstr "上傳 FTP 文件到外部儲存"
@@ -2865,7 +2903,7 @@ msgid ""
msgstr "用戶來自 {} 請去相應系統修改密碼"
#: authentication/api/password.py:65
-#: authentication/templates/authentication/login.html:354
+#: authentication/templates/authentication/login.html:393
#: users/templates/users/forgot_password.html:41
#: users/templates/users/forgot_password.html:42
#: users/templates/users/forgot_password_previewing.html:13
@@ -2917,7 +2955,7 @@ msgstr "附加"
#: authentication/backends/passkey/models.py:14
#: authentication/models/access_key.py:26
-#: authentication/models/private_token.py:8
+#: authentication/models/private_token.py:8 authentication/models/ssh_key.py:20
msgid "Date last used"
msgstr "最後使用日期"
@@ -3047,7 +3085,7 @@ msgstr "請輸入 MFA 驗證碼"
msgid "Please enter SMS code"
msgstr "請輸入簡訊驗證碼"
-#: authentication/errors/failed.py:164 users/exceptions.py:15
+#: authentication/errors/failed.py:164 users/exceptions.py:14
msgid "Phone not set"
msgstr "手機號碼沒有設置"
@@ -3055,21 +3093,21 @@ msgstr "手機號碼沒有設置"
msgid "SSO auth closed"
msgstr "SSO 認證關閉了"
-#: authentication/errors/mfa.py:18 authentication/views/wecom.py:59
+#: authentication/errors/mfa.py:18 authentication/views/wecom.py:51
msgid "WeCom is already bound"
msgstr "企業微信已經綁定"
-#: authentication/errors/mfa.py:23 authentication/views/wecom.py:159
-#: authentication/views/wecom.py:201
+#: authentication/errors/mfa.py:23 authentication/views/wecom.py:151
+#: authentication/views/wecom.py:193
msgid "WeCom is not bound"
msgstr "沒有綁定企業微信"
-#: authentication/errors/mfa.py:28 authentication/views/dingtalk.py:211
-#: authentication/views/dingtalk.py:253
+#: authentication/errors/mfa.py:28 authentication/views/dingtalk.py:203
+#: authentication/views/dingtalk.py:245
msgid "DingTalk is not bound"
msgstr "釘釘沒有綁定"
-#: authentication/errors/mfa.py:33 authentication/views/feishu.py:138
+#: authentication/errors/mfa.py:33 authentication/views/feishu.py:130
msgid "FeiShu is not bound"
msgstr "沒有綁定飛書"
@@ -3077,7 +3115,7 @@ msgstr "沒有綁定飛書"
msgid "Lark is not bound"
msgstr "Lark 沒有綁定"
-#: authentication/errors/mfa.py:43 authentication/views/slack.py:127
+#: authentication/errors/mfa.py:43 authentication/views/slack.py:119
msgid "Slack is not bound"
msgstr "Slack 沒有綁定"
@@ -3239,7 +3277,7 @@ msgstr "自訂密碼"
#: authentication/models/connection_token.py:41
#: authentication/serializers/connect_token_secret.py:114
-#: settings/serializers/msg.py:28 terminal/models/applet/applet.py:42
+#: settings/serializers/msg.py:28 terminal/models/applet/applet.py:43
#: terminal/models/virtualapp/virtualapp.py:24
#: terminal/serializers/session.py:21 terminal/serializers/session.py:48
#: terminal/serializers/storage.py:71
@@ -3250,10 +3288,6 @@ msgstr "協議"
msgid "Connect method"
msgstr "連接方式"
-#: authentication/models/connection_token.py:43
-msgid "Connect options"
-msgstr "連接項"
-
#: authentication/models/connection_token.py:44
msgid "User display"
msgstr "使用者名稱"
@@ -3311,6 +3345,18 @@ msgstr "超級連接令牌"
msgid "Private Token"
msgstr "私有令牌"
+#: authentication/models/ssh_key.py:15 terminal/serializers/storage.py:146
+#: users/models/user/__init__.py:86
+#: xpack/plugins/cloud/serializers/account_attrs.py:213
+msgid "Private key"
+msgstr "ssh私鑰"
+
+#: authentication/models/ssh_key.py:18 settings/serializers/terminal.py:34
+#: users/forms/profile.py:172 users/models/user/__init__.py:89
+#: xpack/plugins/cloud/serializers/account_attrs.py:210
+msgid "Public key"
+msgstr "SSH公鑰"
+
#: authentication/models/sso_token.py:15
msgid "Expired"
msgstr "過期時間"
@@ -3340,12 +3386,12 @@ msgid "Options"
msgstr "選項"
#: authentication/serializers/connect_token_secret.py:127
-#: ops/notifications.py:18 rbac/tree.py:60
+#: ops/notifications.py:19 rbac/tree.py:60
msgid "Component"
msgstr "組件"
#: authentication/serializers/connect_token_secret.py:136
-#: perms/serializers/user_permission.py:28 xpack/plugins/cloud/models.py:375
+#: perms/serializers/user_permission.py:28 xpack/plugins/cloud/models.py:387
msgid "Domain"
msgstr "網域"
@@ -3384,22 +3430,50 @@ msgid "Actions"
msgstr "動作"
#: authentication/serializers/connection_token.py:42
-#: perms/serializers/permission.py:44 perms/serializers/permission.py:65
+#: perms/serializers/permission.py:43 perms/serializers/permission.py:64
#: users/serializers/user.py:127 users/serializers/user.py:273
msgid "Is expired"
msgstr "已過期"
+#: authentication/serializers/connection_token.py:43
+#: orgs/mixins/serializers.py:26 rbac/serializers/rolebinding.py:27
+msgid "Org name"
+msgstr "組織名稱"
+
#: authentication/serializers/password_mfa.py:29
#: users/templates/users/forgot_password.html:153
msgid "The {} cannot be empty"
msgstr "{} 不能為空"
+#: authentication/serializers/ssh_key.py:17
+msgid "Automatically Generate Key Pair"
+msgstr "自動創建密鑰對"
+
+#: authentication/serializers/ssh_key.py:19
+msgid "Import Existing Key Pair"
+msgstr "導入已有密鑰對"
+
+#: authentication/serializers/ssh_key.py:31
+msgid "Create Type"
+msgstr "創建類型"
+
+#: authentication/serializers/ssh_key.py:33
+msgid ""
+"Please download the private key after creation. Each private key can only be "
+"downloaded once"
+msgstr "創建完成後請下載私鑰,每個私鑰僅有一次下載機會"
+
+#: authentication/serializers/ssh_key.py:57 users/forms/profile.py:161
+#: users/serializers/profile.py:133 users/serializers/profile.py:160
+msgid "Not a valid ssh public key"
+msgstr "SSH金鑰不合法"
+
#: authentication/serializers/token.py:22
msgid "Access IP"
msgstr "IP 白名單"
-#: authentication/serializers/token.py:92 perms/serializers/permission.py:43
-#: perms/serializers/permission.py:66 users/serializers/user.py:128
+#: authentication/serializers/token.py:92 perms/serializers/permission.py:42
+#: perms/serializers/permission.py:65 users/serializers/user.py:128
#: users/serializers/user.py:270
msgid "Is valid"
msgstr "是否有效"
@@ -3467,7 +3541,7 @@ msgstr "代碼錯誤"
#: authentication/templates/authentication/_msg_oauth_bind.html:3
#: authentication/templates/authentication/_msg_reset_password.html:3
#: authentication/templates/authentication/_msg_reset_password_code.html:9
-#: jumpserver/conf.py:465
+#: jumpserver/conf.py:502
#: perms/templates/perms/_msg_item_permissions_expire.html:3
#: tickets/templates/tickets/approve_check_password.html:32
#: users/templates/users/_msg_account_expire_reminder.html:4
@@ -3565,17 +3639,17 @@ msgstr "如果這次公鑰更新不是由你發起的,那麼你的帳號可能
msgid "Cancel"
msgstr "取消"
-#: authentication/templates/authentication/login.html:270
+#: authentication/templates/authentication/login.html:308
msgid ""
"Configuration file has problems and cannot be logged in. Please contact the "
"administrator or view latest docs"
msgstr "配置文件有問題,無法登錄,請聯絡管理員或查看最新文件"
-#: authentication/templates/authentication/login.html:271
+#: authentication/templates/authentication/login.html:309
msgid "If you are administrator, you can update the config resolve it, set"
msgstr "如果你是管理員,可以更新配置文件解決,設置配置項"
-#: authentication/templates/authentication/login.html:369
+#: authentication/templates/authentication/login.html:408
msgid "More login options"
msgstr "其他方式登錄"
@@ -3626,22 +3700,22 @@ msgstr "是否重試 ?"
msgid "LAN"
msgstr "區域網路"
-#: authentication/views/base.py:73
+#: authentication/views/base.py:71
#: perms/templates/perms/_msg_permed_items_expire.html:21
msgid "If you have any question, please contact the administrator"
msgstr "如果有疑問或需求,請聯絡系統管理員"
-#: authentication/views/base.py:146
+#: authentication/views/base.py:141
#, python-format
msgid "%s query user failed"
msgstr "%s 查詢用戶失敗"
-#: authentication/views/base.py:155
+#: authentication/views/base.py:149
#, python-format
msgid "The %s is already bound to another user"
msgstr "%s 已綁定到另一個用戶"
-#: authentication/views/base.py:162
+#: authentication/views/base.py:155
#, python-format
msgid "Binding %s successfully"
msgstr "綁定 %s 成功"
@@ -3650,45 +3724,39 @@ msgstr "綁定 %s 成功"
msgid "DingTalk Error, Please contact your system administrator"
msgstr "釘釘錯誤,請聯絡系統管理員"
-#: authentication/views/dingtalk.py:45 authentication/views/dingtalk.py:210
+#: authentication/views/dingtalk.py:45 authentication/views/dingtalk.py:202
msgid "DingTalk Error"
msgstr "釘釘錯誤"
-#: authentication/views/dingtalk.py:57 authentication/views/feishu.py:68
-#: authentication/views/slack.py:47 authentication/views/wecom.py:55
-msgid ""
-"The system configuration is incorrect. Please contact your administrator"
-msgstr "企業配置錯誤,請聯絡系統管理員"
-
-#: authentication/views/dingtalk.py:61
+#: authentication/views/dingtalk.py:53
msgid "DingTalk is already bound"
msgstr "釘釘已經綁定"
-#: authentication/views/dingtalk.py:130
+#: authentication/views/dingtalk.py:122
msgid "Invalid user_id"
msgstr "無效的 user_id"
-#: authentication/views/dingtalk.py:146
+#: authentication/views/dingtalk.py:138
msgid "DingTalk query user failed"
msgstr "釘釘查詢用戶失敗"
-#: authentication/views/dingtalk.py:154
+#: authentication/views/dingtalk.py:146
msgid "The DingTalk is already bound to another user"
msgstr "該釘釘已經綁定其他用戶"
-#: authentication/views/dingtalk.py:160
+#: authentication/views/dingtalk.py:152
msgid "Binding DingTalk successfully"
msgstr "綁定 釘釘 成功"
-#: authentication/views/dingtalk.py:212 authentication/views/dingtalk.py:247
+#: authentication/views/dingtalk.py:204 authentication/views/dingtalk.py:239
msgid "Failed to get user from DingTalk"
msgstr "從釘釘獲取用戶失敗"
-#: authentication/views/dingtalk.py:254
+#: authentication/views/dingtalk.py:246
msgid "Please login with a password and then bind the DingTalk"
msgstr "請使用密碼登錄,然後綁定釘釘"
-#: authentication/views/feishu.py:43 authentication/views/feishu.py:137
+#: authentication/views/feishu.py:43 authentication/views/feishu.py:129
msgid "FeiShu Error"
msgstr "飛書錯誤"
@@ -3696,7 +3764,7 @@ msgstr "飛書錯誤"
msgid "FeiShu is already bound"
msgstr "飛書已經綁定"
-#: authentication/views/feishu.py:139
+#: authentication/views/feishu.py:131
msgid "Failed to get user from FeiShu"
msgstr "從飛書獲取用戶失敗"
@@ -3712,23 +3780,23 @@ msgstr "Lark 已經綁定"
msgid "Failed to get user from Lark"
msgstr "從 Lark 獲取用戶失敗"
-#: authentication/views/login.py:221
+#: authentication/views/login.py:218
msgid "Redirecting"
msgstr "跳轉中"
-#: authentication/views/login.py:222
+#: authentication/views/login.py:219
msgid "Redirecting to {} authentication"
msgstr "正在跳轉到 {} 認證"
-#: authentication/views/login.py:245
+#: authentication/views/login.py:242
msgid "Login timeout, please try again."
msgstr "登錄超時,請重新登入"
-#: authentication/views/login.py:290
+#: authentication/views/login.py:287
msgid "User email already exists ({})"
msgstr "用戶信箱已存在 ({})"
-#: authentication/views/login.py:367
+#: authentication/views/login.py:364
msgid ""
"Wait for {} confirm, You also can copy link to her/him
\n"
" Don't close this page"
@@ -3736,27 +3804,34 @@ msgstr ""
"等待 {} 確認, 你也可以複製連結發給他/她
\n"
" 不要關閉本頁面"
-#: authentication/views/login.py:372
+#: authentication/views/login.py:369
msgid "No ticket found"
msgstr "沒有發現工單"
-#: authentication/views/login.py:408
+#: authentication/views/login.py:405
msgid "Logout success"
msgstr "退出登錄成功"
-#: authentication/views/login.py:409
+#: authentication/views/login.py:406
msgid "Logout success, return login page"
msgstr "退出登錄成功,返回到登入頁面"
-#: authentication/views/slack.py:35 authentication/views/slack.py:126
+#: authentication/views/mixins.py:39
+msgid ""
+"For your safety, automatic redirection login is not supported on the client. "
+"If you need to open it in the client, please log in again"
+msgstr ""
+"為了您的安全,客戶端不支持自動跳轉登錄。如果需要在客戶端中打開,請重新登錄"
+
+#: authentication/views/slack.py:35 authentication/views/slack.py:118
msgid "Slack Error"
msgstr "Slack 錯誤"
-#: authentication/views/slack.py:63
+#: authentication/views/slack.py:55
msgid "Slack is already bound"
msgstr "Slack 已經綁定"
-#: authentication/views/slack.py:128
+#: authentication/views/slack.py:120
msgid "Failed to get user from Slack"
msgstr "從 Slack 獲取用戶失敗"
@@ -3764,19 +3839,19 @@ msgstr "從 Slack 獲取用戶失敗"
msgid "WeCom Error, Please contact your system administrator"
msgstr "企業微信錯誤,請聯絡系統管理員"
-#: authentication/views/wecom.py:43 authentication/views/wecom.py:158
+#: authentication/views/wecom.py:43 authentication/views/wecom.py:150
msgid "WeCom Error"
msgstr "企業微信錯誤"
-#: authentication/views/wecom.py:118
+#: authentication/views/wecom.py:110
msgid "Wecom"
msgstr "企業微信"
-#: authentication/views/wecom.py:160 authentication/views/wecom.py:195
+#: authentication/views/wecom.py:152 authentication/views/wecom.py:187
msgid "Failed to get user from WeCom"
msgstr "從企業微信獲取用戶失敗"
-#: authentication/views/wecom.py:202
+#: authentication/views/wecom.py:194
msgid "Please login with a password and then bind the WeCom"
msgstr "請使用密碼登錄,然後綁定企業微信"
@@ -3784,27 +3859,31 @@ msgstr "請使用密碼登錄,然後綁定企業微信"
msgid "Request file format may be wrong"
msgstr "上傳的檔案格式錯誤 或 其它類型資源的文件"
-#: common/const/choices.py:10
+#: common/const/choices.py:40
+msgid "China"
+msgstr "中國"
+
+#: common/const/choices.py:57
msgid "Manual trigger"
msgstr "手動觸發"
-#: common/const/choices.py:11
+#: common/const/choices.py:58
msgid "Timing trigger"
msgstr "定時觸發"
-#: common/const/choices.py:15
+#: common/const/choices.py:62
msgid "Ready"
msgstr "準備"
-#: common/const/choices.py:17 ops/const.py:73
+#: common/const/choices.py:64 ops/const.py:73
msgid "Running"
msgstr "運行中"
-#: common/const/choices.py:21
+#: common/const/choices.py:68
msgid "Canceled"
msgstr "取消"
-#: common/const/common.py:5 xpack/plugins/cloud/manager.py:409
+#: common/const/common.py:5 xpack/plugins/cloud/manager.py:412
#, python-format
msgid "%(name)s was created successfully"
msgstr "%(name)s 創建成功"
@@ -3818,35 +3897,35 @@ msgstr "%(name)s 更新成功"
msgid "gettext_lazy"
msgstr "gettext_lazy"
-#: common/db/fields.py:106
+#: common/db/fields.py:105
msgid "Marshal dict data to char field"
msgstr "編碼 dict 為 char"
-#: common/db/fields.py:110
+#: common/db/fields.py:109
msgid "Marshal dict data to text field"
msgstr "編碼 dict 為 text"
-#: common/db/fields.py:122
+#: common/db/fields.py:121
msgid "Marshal list data to char field"
msgstr "編碼 list 為 char"
-#: common/db/fields.py:126
+#: common/db/fields.py:125
msgid "Marshal list data to text field"
msgstr "編碼 list 為 text"
-#: common/db/fields.py:130
+#: common/db/fields.py:129
msgid "Marshal data to char field"
msgstr "編碼數據為 char"
-#: common/db/fields.py:134
+#: common/db/fields.py:133
msgid "Marshal data to text field"
msgstr "編碼數據為 text"
-#: common/db/fields.py:167
+#: common/db/fields.py:166
msgid "Encrypt field using Secret Key"
msgstr "加密的欄位"
-#: common/db/fields.py:582
+#: common/db/fields.py:577
msgid ""
"Invalid JSON data for JSONManyToManyField, should be like {'type': 'all'} or "
"{'type': 'ids', 'ids': []} or {'type': 'attrs', 'attrs': [{'name': 'ip', "
@@ -3856,27 +3935,27 @@ msgstr ""
"{'type': 'attrs', 'attrs': [{'name': 'ip', 'match': 'exact', 'value': "
"'1.1.1.1'}}"
-#: common/db/fields.py:589
+#: common/db/fields.py:584
msgid "Invalid type, should be \"all\", \"ids\" or \"attrs\""
msgstr "無效類型,應為 all、ids 或 attrs"
-#: common/db/fields.py:592
+#: common/db/fields.py:587
msgid "Invalid ids for ids, should be a list"
msgstr "無效的ID,應為列表"
-#: common/db/fields.py:594 common/db/fields.py:599
-#: common/serializers/fields.py:147 tickets/serializers/ticket/common.py:58
+#: common/db/fields.py:589 common/db/fields.py:594
+#: common/serializers/fields.py:144 tickets/serializers/ticket/common.py:58
#: xpack/plugins/cloud/serializers/account_attrs.py:56
#: xpack/plugins/cloud/serializers/account_attrs.py:79
#: xpack/plugins/cloud/serializers/account_attrs.py:150
msgid "This field is required."
msgstr "該欄位是必填項。"
-#: common/db/fields.py:597 common/db/fields.py:602
+#: common/db/fields.py:592 common/db/fields.py:597
msgid "Invalid attrs, should be a list of dict"
msgstr "無效的屬性,應為dict列表"
-#: common/db/fields.py:604
+#: common/db/fields.py:599
msgid "Invalid attrs, should be has name and value"
msgstr "無效屬性,應具有名稱和值"
@@ -3888,7 +3967,7 @@ msgstr "忽略的"
msgid "discard time"
msgstr "忽略時間"
-#: common/db/models.py:33 users/models/user.py:948
+#: common/db/models.py:33 users/models/user/__init__.py:104
msgid "Updated by"
msgstr "最後更新者"
@@ -3922,7 +4001,7 @@ msgid ""
"information -> file encryption password to set the encryption password"
msgstr "{} - 未設置加密密碼 - 請前往個人資訊 -> 文件加密密碼中設置加密密碼"
-#: common/exceptions.py:15 xpack/plugins/cloud/ws.py:38
+#: common/exceptions.py:15 xpack/plugins/cloud/ws.py:37
#, python-format
msgid "%s object does not exist."
msgstr "%s對象不存在"
@@ -3969,11 +4048,11 @@ msgstr "連接失敗:使用了自簽名證書,請檢查伺服器證書配置
msgid "Network error, please contact system administrator"
msgstr "網路錯誤,請聯絡系統管理員"
-#: common/sdk/im/slack/__init__.py:77
+#: common/sdk/im/slack/__init__.py:78
msgid "Unknown error occur"
msgstr "發生未知錯誤"
-#: common/sdk/im/wecom/__init__.py:16
+#: common/sdk/im/wecom/__init__.py:17
msgid "WeCom error, please contact system administrator"
msgstr "企業微信錯誤,請聯絡系統管理員"
@@ -4046,36 +4125,36 @@ msgstr "節點"
msgid "File"
msgstr "文件"
-#: common/serializers/fields.py:140
+#: common/serializers/fields.py:137
msgid "Invalid data type"
msgstr "无效的数据"
-#: common/serializers/fields.py:148
+#: common/serializers/fields.py:145
#, python-brace-format
msgid "Invalid pk \"{pk_value}\" - object does not exist."
msgstr "錯誤的 pk \"{pk_value}\" - 對象不存在"
-#: common/serializers/fields.py:149
+#: common/serializers/fields.py:146
#, python-brace-format
msgid "Incorrect type. Expected pk value, received {data_type}."
msgstr "錯誤類型。期望 pk 值,收到 {data_type}。"
-#: common/serializers/fields.py:223
+#: common/serializers/fields.py:220
msgid "Invalid data type, should be list"
msgstr "錯誤的數據類型,應該是列表"
-#: common/serializers/fields.py:238
+#: common/serializers/fields.py:235
msgid "Invalid choice: {}"
msgstr "無效選項: {}"
-#: common/serializers/mixin.py:452 terminal/models/applet/applet.py:44
+#: common/serializers/mixin.py:452 terminal/models/applet/applet.py:45
#: terminal/models/virtualapp/virtualapp.py:29
msgid "Tags"
msgstr "標籤"
# msgid "Labels"
# msgstr "標籤管理"
-#: common/tasks.py:31 common/utils/verify_code.py:16
+#: common/tasks.py:31
msgid "Send email"
msgstr "發件郵件"
@@ -4095,11 +4174,15 @@ msgstr "無效 IP"
msgid "Invalid address"
msgstr "無效地址"
-#: common/utils/translate.py:45
+#: common/utils/translate.py:46
#, python-format
msgid "Hello %s"
msgstr "你好 %s"
+#: common/utils/verify_code.py:16
+msgid "Send SMS code"
+msgstr "傳簡訊驗證碼"
+
#: common/validators.py:16
msgid "Special char not allowed"
msgstr "不能包含特殊字元"
@@ -4112,16 +4195,16 @@ msgstr "不能包含特殊字元"
msgid "The mobile phone number format is incorrect"
msgstr "手機號碼格式不正確"
-#: jumpserver/conf.py:459
+#: jumpserver/conf.py:496
#, python-brace-format
msgid "The verification code is: {code}"
msgstr "驗證碼為: {code}"
-#: jumpserver/conf.py:464
+#: jumpserver/conf.py:501
msgid "Create account successfully"
msgstr "創建帳號成功"
-#: jumpserver/conf.py:466
+#: jumpserver/conf.py:503
msgid "Your account has been created successfully"
msgstr "你的帳號已創建成功"
@@ -4133,7 +4216,7 @@ msgstr "JumpServer 開源堡壘機"
msgid "Flower service unavailable, check it
"
msgstr "Flower 服務不可用,請檢查"
-#: jumpserver/views/other.py:27
+#: jumpserver/views/other.py:28
msgid ""
"Luna is a separately deployed program, you need to deploy Luna, koko, "
"configure nginx for url distribution,
If you see this page, "
@@ -4142,11 +4225,11 @@ msgstr ""
"Luna是單獨部署的一個程序,你需要部署luna,koko,
如果你看到了"
"這個頁面,證明你訪問的不是nginx監聽的埠,祝你好運
"
-#: jumpserver/views/other.py:75
+#: jumpserver/views/other.py:76
msgid "Websocket server run on port: {}, you should proxy it on nginx"
msgstr "Websocket 服務運行在埠: {}, 請檢查nginx是否代理是否設置"
-#: jumpserver/views/other.py:89
+#: jumpserver/views/other.py:90
msgid ""
"Koko is a separately deployed program, you need to deploy Koko, "
"configure nginx for url distribution,
If you see this page, "
@@ -4239,34 +4322,34 @@ msgstr "任務 {} 不存在"
msgid "Task {} args or kwargs error"
msgstr "任務 {} 執行參數錯誤"
-#: ops/api/job.py:81
+#: ops/api/job.py:83
#, python-brace-format
msgid ""
"Asset ({asset}) must have at least one of the following protocols added: "
"SSH, SFTP, or WinRM"
msgstr "资产({asset})至少要添加ssh,sftp,winrm其中一种协议"
-#: ops/api/job.py:82
+#: ops/api/job.py:84
#, python-brace-format
msgid "Asset ({asset}) authorization is missing SSH, SFTP, or WinRM protocol"
msgstr "资产({asset})授权缺少ssh,sftp或winrm协议"
-#: ops/api/job.py:83
+#: ops/api/job.py:85
#, python-brace-format
msgid "Asset ({asset}) authorization lacks upload permissions"
msgstr "资产({asset})授权缺少上传权限"
-#: ops/api/job.py:168
+#: ops/api/job.py:170
msgid "Duplicate file exists"
msgstr "存在同名文件"
-#: ops/api/job.py:173
+#: ops/api/job.py:175
#, python-brace-format
msgid ""
"File size exceeds maximum limit. Please select a file smaller than {limit}MB"
msgstr "檔案大小超過最大限制。請選擇小於 {limit}MB 的文件。"
-#: ops/api/job.py:237
+#: ops/api/job.py:244
msgid ""
"The task is being created and cannot be interrupted. Please try again later."
msgstr "正在創建任務,無法中斷,請稍後重試。"
@@ -4275,27 +4358,27 @@ msgstr "正在創建任務,無法中斷,請稍後重試。"
msgid "Currently playbook is being used in a job"
msgstr "當前 playbook 正在作業中使用"
-#: ops/api/playbook.py:96
+#: ops/api/playbook.py:97
msgid "Unsupported file content"
msgstr "不支持的文件內容"
-#: ops/api/playbook.py:98 ops/api/playbook.py:144 ops/api/playbook.py:192
+#: ops/api/playbook.py:99 ops/api/playbook.py:145 ops/api/playbook.py:193
msgid "Invalid file path"
msgstr "無效的文件路徑"
-#: ops/api/playbook.py:170
+#: ops/api/playbook.py:171
msgid "This file can not be rename"
msgstr "該文件不能重命名"
-#: ops/api/playbook.py:189
+#: ops/api/playbook.py:190
msgid "File already exists"
msgstr "文件已存在"
-#: ops/api/playbook.py:207
+#: ops/api/playbook.py:208
msgid "File key is required"
msgstr "文件金鑰該欄位是必填項。"
-#: ops/api/playbook.py:210
+#: ops/api/playbook.py:211
msgid "This file can not be delete"
msgstr "無法刪除此文件"
@@ -4335,7 +4418,7 @@ msgstr "空白"
msgid "VCS"
msgstr "VCS"
-#: ops/const.py:38 ops/models/adhoc.py:44 settings/serializers/feature.py:135
+#: ops/const.py:38 ops/models/adhoc.py:44 settings/serializers/feature.py:120
msgid "Adhoc"
msgstr "命令"
@@ -4399,21 +4482,25 @@ msgstr "Oracle"
msgid "Timeout"
msgstr "超時"
+#: ops/const.py:82
+msgid "Command execution disabled"
+msgstr "命令執行禁用"
+
#: ops/exception.py:6
msgid "no valid program entry found."
msgstr "沒有可用程序入口"
-#: ops/mixin.py:23 ops/mixin.py:102 settings/serializers/auth/ldap.py:74
+#: ops/mixin.py:23 ops/mixin.py:102 settings/serializers/auth/ldap.py:72
msgid "Periodic run"
msgstr "週期性執行"
#: ops/mixin.py:25 ops/mixin.py:88 ops/mixin.py:108
-#: settings/serializers/auth/ldap.py:81
+#: settings/serializers/auth/ldap.py:79
msgid "Interval"
msgstr "間隔"
#: ops/mixin.py:28 ops/mixin.py:86 ops/mixin.py:105
-#: settings/serializers/auth/ldap.py:78
+#: settings/serializers/auth/ldap.py:76
msgid "Crontab"
msgstr "Crontab"
@@ -4461,7 +4548,7 @@ msgid "Date last run"
msgstr "最後運行日期"
#: ops/models/base.py:51 ops/models/job.py:238
-#: xpack/plugins/cloud/models.py:222
+#: xpack/plugins/cloud/models.py:223
msgid "Result"
msgstr "結果"
@@ -4518,7 +4605,8 @@ msgstr "執行使用者"
msgid "Run as policy"
msgstr "使用者策略"
-#: ops/models/job.py:222 terminal/notifications.py:174
+#: ops/models/job.py:222 ops/serializers/job.py:92
+#: terminal/notifications.py:174
msgid "Job"
msgstr "作業"
@@ -4530,7 +4618,7 @@ msgstr "Material"
msgid "Material Type"
msgstr "Material 類型"
-#: ops/models/job.py:545
+#: ops/models/job.py:548
msgid "Job Execution"
msgstr "作業執行"
@@ -4542,30 +4630,30 @@ msgstr "創建方式"
msgid "VCS URL"
msgstr "VCS URL"
-#: ops/notifications.py:19
+#: ops/notifications.py:20
msgid "Server performance"
msgstr "監控告警"
-#: ops/notifications.py:25
+#: ops/notifications.py:26
msgid "Component health check warning"
msgstr "組件健康狀態檢查警告"
-#: ops/notifications.py:70
+#: ops/notifications.py:71
#, python-brace-format
msgid "The component is offline: {name}"
msgstr "組件已離線: {name}"
-#: ops/notifications.py:75
+#: ops/notifications.py:76
#, python-brace-format
msgid "Disk used more than {max_threshold}%: => {value}"
msgstr "硬碟使用率超過 {max_threshold}%: => {value}"
-#: ops/notifications.py:80
+#: ops/notifications.py:81
#, python-brace-format
msgid "Memory used more than {max_threshold}%: => {value}"
msgstr "記憶體使用率超過 {max_threshold}%: => {value}"
-#: ops/notifications.py:85
+#: ops/notifications.py:86
#, python-brace-format
msgid "CPU load more than {max_threshold}: => {value}"
msgstr "CPU 使用率超過 {max_threshold}: => {value}"
@@ -4594,7 +4682,11 @@ msgstr "任務類型"
msgid "Is finished"
msgstr "是否完成"
-#: ops/serializers/job.py:90
+#: ops/serializers/job.py:89
+msgid "Task id"
+msgstr "任務 ID"
+
+#: ops/serializers/job.py:98
msgid "You do not have permission for the current job."
msgstr "你沒有當前作業的權限。"
@@ -4690,17 +4782,13 @@ msgstr "請選擇一個組織後再保存"
#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:91
#: rbac/const.py:7 rbac/models/rolebinding.py:56
-#: rbac/serializers/rolebinding.py:44 settings/serializers/auth/ldap.py:71
+#: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:52
#: terminal/templates/terminal/_msg_command_warning.html:21
#: terminal/templates/terminal/_msg_session_sharing.html:14
-#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:60
+#: tickets/models/ticket/general.py:303 tickets/serializers/ticket/ticket.py:60
msgid "Organization"
msgstr "組織"
-#: orgs/mixins/serializers.py:26 rbac/serializers/rolebinding.py:27
-msgid "Org name"
-msgstr "組織名稱"
-
#: orgs/models.py:14
msgid "GLOBAL"
msgstr "全局組織"
@@ -4714,7 +4802,7 @@ msgid "SYSTEM"
msgstr "系統組織"
#: orgs/models.py:83 rbac/models/role.py:36 settings/models.py:185
-#: terminal/models/applet/applet.py:41
+#: terminal/models/applet/applet.py:42
msgid "Builtin"
msgstr "內建的"
@@ -4730,7 +4818,7 @@ msgstr "可以查看所有加入的組織"
msgid "Can not delete virtual org"
msgstr "無法刪除虛擬組織"
-#: orgs/serializers.py:10 perms/serializers/permission.py:38
+#: orgs/serializers.py:10 perms/serializers/permission.py:37
#: rbac/serializers/role.py:27 users/serializers/group.py:54
msgid "Users amount"
msgstr "用戶數量"
@@ -4739,7 +4827,7 @@ msgstr "用戶數量"
msgid "User groups amount"
msgstr "用戶組數量"
-#: orgs/serializers.py:14 perms/serializers/permission.py:41
+#: orgs/serializers.py:14 perms/serializers/permission.py:40
msgid "Nodes amount"
msgstr "節點數量"
@@ -4836,7 +4924,7 @@ msgid "today"
msgstr "今天"
#: perms/notifications.py:12 perms/notifications.py:44
-#: settings/serializers/feature.py:126
+#: settings/serializers/feature.py:111
msgid "day"
msgstr "天"
@@ -4856,11 +4944,11 @@ msgstr "資產授權規則將要過期"
msgid "asset permissions of organization {}"
msgstr "組織 ({}) 的資產授權"
-#: perms/serializers/permission.py:34 users/serializers/user.py:257
+#: perms/serializers/permission.py:33 users/serializers/user.py:257
msgid "Groups"
msgstr "使用者群組"
-#: perms/serializers/permission.py:39
+#: perms/serializers/permission.py:38
msgid "Groups amount"
msgstr "使用者組數量"
@@ -4957,22 +5045,20 @@ msgid "Can view System Tools"
msgstr "可以查看系統工具"
#: rbac/models/permission.py:18
-#, fuzzy
-#| msgid "Content"
msgid "ContentType"
-msgstr "內容"
+msgstr "內容類型"
#: rbac/models/permission.py:79 rbac/models/role.py:34
msgid "Permissions"
msgstr "授權"
#: rbac/models/role.py:31 rbac/models/rolebinding.py:46
-#: rbac/serializers/role.py:12 settings/serializers/auth/oauth2.py:36
+#: rbac/serializers/role.py:12 settings/serializers/auth/oauth2.py:37
msgid "Scope"
msgstr "範圍"
#: rbac/models/role.py:46 rbac/models/rolebinding.py:52
-#: users/models/user.py:910
+#: users/models/user/__init__.py:66
msgid "Role"
msgstr "角色"
@@ -5006,15 +5092,10 @@ msgstr "組織角色綁定"
msgid "System role binding"
msgstr "系統角色綁定"
-#: rbac/serializers/permission.py:25 users/serializers/profile.py:103
+#: rbac/serializers/permission.py:25 users/serializers/profile.py:76
msgid "Perms"
msgstr "權限"
-#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:34
-#: terminal/models/virtualapp/virtualapp.py:20
-msgid "Display name"
-msgstr "顯示名稱"
-
#: rbac/serializers/rolebinding.py:60
msgid "Has bound this role"
msgstr "已經綁定"
@@ -5059,19 +5140,15 @@ msgstr "收集帳號"
msgid "Account change secret"
msgstr "帳號改密"
-#: rbac/tree.py:54
-msgid "My assets"
-msgstr "我的資產"
-
#: rbac/tree.py:55
msgid "App ops"
msgstr "作業中心"
-#: rbac/tree.py:57 settings/serializers/feature.py:132
+#: rbac/tree.py:57 settings/serializers/feature.py:117
msgid "Feature"
msgstr "功能"
-#: rbac/tree.py:58 settings/serializers/auth/base.py:10
+#: rbac/tree.py:58 settings/serializers/auth/base.py:11
msgid "Authentication"
msgstr "認證"
@@ -5079,8 +5156,8 @@ msgstr "認證"
msgid "Storage"
msgstr "儲存"
-#: rbac/tree.py:61 terminal/models/applet/applet.py:52
-#: terminal/models/applet/applet.py:317 terminal/models/applet/host.py:30
+#: rbac/tree.py:61 terminal/models/applet/applet.py:53
+#: terminal/models/applet/applet.py:328 terminal/models/applet/host.py:30
#: terminal/serializers/applet.py:15
msgid "Applet"
msgstr "遠程應用"
@@ -5102,8 +5179,8 @@ msgstr "組織管理"
msgid "Ticket comment"
msgstr "工單評論"
-#: rbac/tree.py:159 settings/serializers/feature.py:113
-#: settings/serializers/feature.py:115 tickets/models/ticket/general.py:305
+#: rbac/tree.py:159 settings/serializers/feature.py:98
+#: settings/serializers/feature.py:100 tickets/models/ticket/general.py:308
msgid "Ticket"
msgstr "工單管理"
@@ -5120,7 +5197,7 @@ msgid "Chat AI is not enabled"
msgstr "聊天 AI 沒有開啟"
#: settings/api/chat.py:79 settings/api/dingtalk.py:31
-#: settings/api/feishu.py:36 settings/api/slack.py:34 settings/api/sms.py:160
+#: settings/api/feishu.py:39 settings/api/slack.py:34 settings/api/sms.py:160
#: settings/api/vault.py:40 settings/api/wecom.py:37
msgid "Test success"
msgstr "測試成功"
@@ -5226,63 +5303,63 @@ msgstr "聊天提示"
msgid "Notification of Synchronized LDAP User Task Results"
msgstr "同步LDAP用戶任務結果通知"
-#: settings/serializers/auth/base.py:12
+#: settings/serializers/auth/base.py:13
msgid "LDAP Auth"
msgstr "LDAP 認證"
-#: settings/serializers/auth/base.py:13
+#: settings/serializers/auth/base.py:14
msgid "CAS Auth"
msgstr "CAS 認證"
-#: settings/serializers/auth/base.py:14
+#: settings/serializers/auth/base.py:15
msgid "OPENID Auth"
msgstr "OIDC 認證"
-#: settings/serializers/auth/base.py:15
+#: settings/serializers/auth/base.py:16
msgid "SAML2 Auth"
msgstr "SAML2 認證"
-#: settings/serializers/auth/base.py:16
+#: settings/serializers/auth/base.py:17
msgid "OAuth2 Auth"
msgstr "OAuth2 認證"
-#: settings/serializers/auth/base.py:17
+#: settings/serializers/auth/base.py:18
msgid "RADIUS Auth"
msgstr "RADIUS 認證"
-#: settings/serializers/auth/base.py:18
+#: settings/serializers/auth/base.py:19
msgid "DingTalk Auth"
msgstr "釘釘 認證"
-#: settings/serializers/auth/base.py:19
+#: settings/serializers/auth/base.py:20
msgid "FeiShu Auth"
msgstr "飛書 認證"
-#: settings/serializers/auth/base.py:20
+#: settings/serializers/auth/base.py:21
msgid "Lark Auth"
msgstr "Lark 認證"
-#: settings/serializers/auth/base.py:21
+#: settings/serializers/auth/base.py:22
msgid "Slack Auth"
msgstr "Slack 認證"
-#: settings/serializers/auth/base.py:22
+#: settings/serializers/auth/base.py:23
msgid "WeCom Auth"
msgstr "企業微信 認證"
-#: settings/serializers/auth/base.py:23
+#: settings/serializers/auth/base.py:24
msgid "SSO Auth"
msgstr "SSO 令牌認證"
-#: settings/serializers/auth/base.py:24
+#: settings/serializers/auth/base.py:25
msgid "Passkey Auth"
msgstr "Passkey 認證"
-#: settings/serializers/auth/base.py:26
+#: settings/serializers/auth/base.py:27
msgid "Email suffix"
msgstr "郵件後綴"
-#: settings/serializers/auth/base.py:28
+#: settings/serializers/auth/base.py:29
msgid ""
"After third-party user authentication is successful, if the third-party "
"authentication service platform does not return the user's email "
@@ -5292,19 +5369,19 @@ msgstr ""
"第三方使用者認證成功後,若第三方認證服務平台未回傳該使用者的電子信箱資訊,系"
"統將自動以此電子信箱後綴建立使用者"
-#: settings/serializers/auth/base.py:35
-msgid "Forgot Password"
-msgstr "忘記密碼"
-
#: settings/serializers/auth/base.py:36
+msgid "Forgot Password URL"
+msgstr "忘記密碼連結"
+
+#: settings/serializers/auth/base.py:37
msgid "The URL for Forgotten Password on the user login page"
msgstr "使用者登入頁面忘記密碼的 URL"
-#: settings/serializers/auth/base.py:39
+#: settings/serializers/auth/base.py:40
msgid "Login redirection"
msgstr "啟用登入跳轉提示"
-#: settings/serializers/auth/base.py:41
+#: settings/serializers/auth/base.py:42
msgid ""
"Should an flash page be displayed before the user is redirected to third-"
"party authentication when the administrator enables third-party redirect "
@@ -5313,43 +5390,52 @@ msgstr ""
"Action管理員啟用第三方重新定向身份驗證時,在使用者重定向到第三方身份驗證之前"
"是否顯示 Flash 頁面"
-#: settings/serializers/auth/cas.py:10 settings/serializers/auth/cas.py:12
+#: settings/serializers/auth/base.py:54
+msgid ""
+"When you create a user, you associate the user to the organization of your "
+"choice. Users always belong to the Default organization."
+msgstr ""
+"建立使用者時,您會將該使用者與您選擇的組織關聯。使用者始終屬於 Default 組織。"
+
+#: settings/serializers/auth/cas.py:12 settings/serializers/auth/cas.py:14
msgid "CAS"
msgstr "CAS"
-#: settings/serializers/auth/cas.py:13 settings/serializers/auth/ldap.py:42
-#: settings/serializers/auth/oidc.py:60
+#: settings/serializers/auth/cas.py:15 settings/serializers/auth/ldap.py:43
+#: settings/serializers/auth/oidc.py:61
msgid "Server"
msgstr "服務端地址"
-#: settings/serializers/auth/cas.py:16
+#: settings/serializers/auth/cas.py:18
msgid "Proxy Server"
msgstr "回撥地址"
-#: settings/serializers/auth/cas.py:19 settings/serializers/auth/oauth2.py:55
-#: settings/serializers/auth/saml2.py:40
+#: settings/serializers/auth/cas.py:21 settings/serializers/auth/oauth2.py:56
+#: settings/serializers/auth/saml2.py:42
msgid "Logout completely"
msgstr "同步註銷"
-#: settings/serializers/auth/cas.py:20
+#: settings/serializers/auth/cas.py:22
msgid "When the user signs out, they also be logged out from the CAS server"
msgstr "當使用者退出時,他們也會從 CAS 伺服器登出"
-#: settings/serializers/auth/cas.py:26
+#: settings/serializers/auth/cas.py:28
msgid "Username attr"
msgstr "使用者名稱屬性"
-#: settings/serializers/auth/cas.py:29
+#: settings/serializers/auth/cas.py:31
msgid "Enable attributes map"
msgstr "啟用屬性映射"
-#: settings/serializers/auth/cas.py:32 settings/serializers/auth/ldap.py:64
-#: settings/serializers/auth/oauth2.py:59 settings/serializers/auth/oidc.py:38
-#: settings/serializers/auth/saml2.py:33
+#: settings/serializers/auth/cas.py:34 settings/serializers/auth/dingtalk.py:18
+#: settings/serializers/auth/feishu.py:18 settings/serializers/auth/lark.py:17
+#: settings/serializers/auth/ldap.py:65 settings/serializers/auth/oauth2.py:60
+#: settings/serializers/auth/oidc.py:39 settings/serializers/auth/saml2.py:35
+#: settings/serializers/auth/slack.py:18 settings/serializers/auth/wecom.py:18
msgid "User attribute"
msgstr "映射屬性"
-#: settings/serializers/auth/cas.py:34
+#: settings/serializers/auth/cas.py:36
msgid ""
"User attribute mapping, where the `key` is the CAS service user attribute "
"name and the `value` is the JumpServer user attribute name"
@@ -5357,64 +5443,88 @@ msgstr ""
"使用者屬性對照,其中 `key` 是 CAS 服務使用者屬性名稱,`value` 是 JumpServer "
"使用者屬性名稱"
-#: settings/serializers/auth/cas.py:39
+#: settings/serializers/auth/cas.py:41
msgid "Create user"
msgstr "創建使用者(如不存在)"
-#: settings/serializers/auth/cas.py:41
+#: settings/serializers/auth/cas.py:43
msgid ""
"After successful user authentication, if the user does not exist, "
"automatically create the user"
msgstr "使用者認證成功後,若使用者不存在,則自動創建使用者"
-#: settings/serializers/auth/dingtalk.py:15
+#: settings/serializers/auth/dingtalk.py:16
msgid "Dingtalk"
msgstr "啟用釘釘認證"
-#: settings/serializers/auth/lark.py:12 users/models/user.py:801
-msgid "Lark"
-msgstr "啟用Lark認證"
+#: settings/serializers/auth/dingtalk.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the DingTalk service user attribute name"
+msgstr ""
+"使用者屬性對照,其中 `key` 是 JumpServer 使用者屬性名稱,`value` 是釘釘服務使"
+"用者屬性名稱"
-#: settings/serializers/auth/ldap.py:39 settings/serializers/auth/ldap.py:104
+#: settings/serializers/auth/feishu.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the FeiShu service user attribute name"
+msgstr ""
+"使用者屬性對照,其中 `key` 是 JumpServer 使用者屬性名稱,`value` 是飛書服務使"
+"用者屬性名稱"
+
+#: settings/serializers/auth/lark.py:13 users/models/user/_source.py:21
+msgid "Lark"
+msgstr ""
+
+#: settings/serializers/auth/lark.py:19
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the Lark service user attribute name"
+msgstr ""
+"使用者屬性對照,其中 `key` 是 JumpServer 使用者屬性名稱,`value` 是 Lark 服務"
+"使用者屬性名稱"
+
+#: settings/serializers/auth/ldap.py:40 settings/serializers/auth/ldap.py:102
msgid "LDAP"
msgstr "LDAP"
-#: settings/serializers/auth/ldap.py:43
+#: settings/serializers/auth/ldap.py:44
msgid "LDAP server URI"
msgstr "LDAP 服務域名"
-#: settings/serializers/auth/ldap.py:46
+#: settings/serializers/auth/ldap.py:47
msgid "Bind DN"
msgstr "綁定 DN"
-#: settings/serializers/auth/ldap.py:47
+#: settings/serializers/auth/ldap.py:48
msgid "Binding Distinguished Name"
-msgstr "綁定專有名稱"
+msgstr "綁定的 DN"
-#: settings/serializers/auth/ldap.py:51
+#: settings/serializers/auth/ldap.py:52
msgid "Binding password"
msgstr "原來的密碼"
-#: settings/serializers/auth/ldap.py:54
+#: settings/serializers/auth/ldap.py:55
msgid "Search OU"
msgstr "系統架構"
-#: settings/serializers/auth/ldap.py:56
+#: settings/serializers/auth/ldap.py:57
msgid ""
"User Search Base, if there are multiple OUs, you can separate them with the "
"`|` symbol"
msgstr "使用者搜尋庫,如果有多個OU,可以用`|`符號分隔"
-#: settings/serializers/auth/ldap.py:60
+#: settings/serializers/auth/ldap.py:61
msgid "Search filter"
msgstr "用戶過濾器"
-#: settings/serializers/auth/ldap.py:61
+#: settings/serializers/auth/ldap.py:62
#, python-format
msgid "Selection could include (cn|uid|sAMAccountName=%(user)s)"
msgstr "可能的選項是(cn或uid或sAMAccountName=%(user)s)"
-#: settings/serializers/auth/ldap.py:66
+#: settings/serializers/auth/ldap.py:67
msgid ""
"User attribute mapping, where the `key` is the JumpServer user attribute "
"name and the `value` is the LDAP service user attribute name"
@@ -5422,15 +5532,15 @@ msgstr ""
"使用者屬性對照,其中 `key` 是 JumpServer 使用者屬性名稱,`value` 是 LDAP 服務"
"使用者屬性名稱"
-#: settings/serializers/auth/ldap.py:85
+#: settings/serializers/auth/ldap.py:83
msgid "Connect timeout (s)"
msgstr "連接超時時間 (秒)"
-#: settings/serializers/auth/ldap.py:90
+#: settings/serializers/auth/ldap.py:88
msgid "User DN cache timeout (s)"
msgstr "快取逾時時間 (秒)"
-#: settings/serializers/auth/ldap.py:92
+#: settings/serializers/auth/ldap.py:90
msgid ""
"Caching the User DN obtained during user login authentication can "
"effectivelyimprove the speed of user authentication., 0 means no cache
If "
@@ -5440,59 +5550,59 @@ msgstr ""
"對於使用者登錄認證時查詢的使用者 DN 進行快取,可以有效提高使用者認證的速度"
"
如果使用者 OU 架構已調整,請點擊提交以清除使用者 DN 快取"
-#: settings/serializers/auth/ldap.py:98
+#: settings/serializers/auth/ldap.py:96
msgid "Search paged size (piece)"
msgstr "搜索分頁數量 (條)"
-#: settings/serializers/auth/oauth2.py:18
-#: settings/serializers/auth/oauth2.py:21
+#: settings/serializers/auth/oauth2.py:19
+#: settings/serializers/auth/oauth2.py:22
msgid "OAuth2"
msgstr "OAuth2"
-#: settings/serializers/auth/oauth2.py:24
+#: settings/serializers/auth/oauth2.py:25
msgid "Logo"
msgstr "圖示"
-#: settings/serializers/auth/oauth2.py:27
+#: settings/serializers/auth/oauth2.py:28
msgid "Service provider"
msgstr "服務提供商"
-#: settings/serializers/auth/oauth2.py:30
+#: settings/serializers/auth/oauth2.py:31
#: xpack/plugins/cloud/serializers/account_attrs.py:35
msgid "Client ID"
msgstr "用戶端 ID"
-#: settings/serializers/auth/oauth2.py:33 settings/serializers/auth/oidc.py:23
+#: settings/serializers/auth/oauth2.py:34 settings/serializers/auth/oidc.py:24
#: xpack/plugins/cloud/serializers/account_attrs.py:38
msgid "Client Secret"
msgstr "用戶端金鑰"
-#: settings/serializers/auth/oauth2.py:39 settings/serializers/auth/oidc.py:76
+#: settings/serializers/auth/oauth2.py:40 settings/serializers/auth/oidc.py:77
msgid "Authorization endpoint"
msgstr "授權端點地址"
-#: settings/serializers/auth/oauth2.py:42 settings/serializers/auth/oidc.py:79
+#: settings/serializers/auth/oauth2.py:43 settings/serializers/auth/oidc.py:80
msgid "Token endpoint"
msgstr "token 端點地址"
-#: settings/serializers/auth/oauth2.py:45 settings/serializers/auth/oidc.py:31
+#: settings/serializers/auth/oauth2.py:46 settings/serializers/auth/oidc.py:32
#: settings/serializers/auth/sms.py:111
msgid "Request method"
msgstr "請求方式"
-#: settings/serializers/auth/oauth2.py:49 settings/serializers/auth/oidc.py:85
+#: settings/serializers/auth/oauth2.py:50 settings/serializers/auth/oidc.py:86
msgid "Userinfo endpoint"
msgstr "User information endpoint address"
-#: settings/serializers/auth/oauth2.py:52 settings/serializers/auth/oidc.py:88
+#: settings/serializers/auth/oauth2.py:53 settings/serializers/auth/oidc.py:89
msgid "End session endpoint"
msgstr "Logout session endpoint address"
-#: settings/serializers/auth/oauth2.py:56
+#: settings/serializers/auth/oauth2.py:57
msgid "When the user signs out, they also be logged out from the OAuth2 server"
msgstr "當使用者退出時,他們也會從 OAuth2 伺服器退出"
-#: settings/serializers/auth/oauth2.py:61
+#: settings/serializers/auth/oauth2.py:62
msgid ""
"User attribute mapping, where the `key` is the JumpServer user attribute "
"name and the `value` is the OAuth2 service user attribute name"
@@ -5500,36 +5610,36 @@ msgstr ""
"使用者屬性對照,其中 `key` 是 JumpServer 使用者屬性名稱,`value` 是 OAuth2 服"
"務使用者屬性名稱"
-#: settings/serializers/auth/oauth2.py:66 settings/serializers/auth/oidc.py:112
-#: settings/serializers/auth/saml2.py:43
+#: settings/serializers/auth/oauth2.py:67 settings/serializers/auth/oidc.py:113
+#: settings/serializers/auth/saml2.py:45
msgid "Always update user"
msgstr "總是更新用戶資訊"
-#: settings/serializers/auth/oidc.py:12 settings/serializers/auth/oidc.py:70
+#: settings/serializers/auth/oidc.py:13 settings/serializers/auth/oidc.py:71
msgid "OIDC"
msgstr "OIDC"
-#: settings/serializers/auth/oidc.py:16
+#: settings/serializers/auth/oidc.py:17
msgid "Base site URL"
msgstr "JumpServer address"
-#: settings/serializers/auth/oidc.py:17
+#: settings/serializers/auth/oidc.py:18
msgid "The current site's URL is used to construct the callback address"
msgstr "目前網站的URL用於建構回撥地址"
-#: settings/serializers/auth/oidc.py:20
+#: settings/serializers/auth/oidc.py:21
msgid "Client Id"
msgstr "用戶端 ID"
-#: settings/serializers/auth/oidc.py:33
+#: settings/serializers/auth/oidc.py:34
msgid "Share session"
msgstr "共享會話"
-#: settings/serializers/auth/oidc.py:35
+#: settings/serializers/auth/oidc.py:36
msgid "Ignore SSL verification"
msgstr "Ignore SSL certificate verification"
-#: settings/serializers/auth/oidc.py:40
+#: settings/serializers/auth/oidc.py:41
msgid ""
"User attribute mapping, where the `key` is the JumpServer user attribute "
"name and the `value` is the OIDC service user attribute name"
@@ -5537,66 +5647,66 @@ msgstr ""
"使用者屬性映射,其中 `key` 是 JumpServer 使用者屬性名稱,`value` 是 OIDC 服務"
"使用者屬性名稱"
-#: settings/serializers/auth/oidc.py:44
+#: settings/serializers/auth/oidc.py:45
msgid "Enable PKCE"
msgstr "啟用 PKCE"
-#: settings/serializers/auth/oidc.py:46
+#: settings/serializers/auth/oidc.py:47
msgid "Code challenge method"
msgstr "驗證校驗碼方式"
-#: settings/serializers/auth/oidc.py:54
+#: settings/serializers/auth/oidc.py:55
msgid "Use Keycloak"
msgstr "使用 Keycloak"
-#: settings/serializers/auth/oidc.py:56
+#: settings/serializers/auth/oidc.py:57
msgid ""
"Use Keycloak as the OpenID Connect server, or use standard OpenID Connect "
"Protocol"
msgstr ""
"使用 Keycloak 作為 OpenID Connect 伺服器,或者使用標準 OpenID Connect 協議"
-#: settings/serializers/auth/oidc.py:63
+#: settings/serializers/auth/oidc.py:64
msgid "Realm name"
msgstr "域"
-#: settings/serializers/auth/oidc.py:70
+#: settings/serializers/auth/oidc.py:71
msgid "OpenID Connect"
-msgstr "Connect"
+msgstr "OpenID 連接"
-#: settings/serializers/auth/oidc.py:73
+#: settings/serializers/auth/oidc.py:74
msgid "Provider endpoint"
msgstr "端點地址"
-#: settings/serializers/auth/oidc.py:82
+#: settings/serializers/auth/oidc.py:83
msgid "JWKS endpoint"
msgstr "jwks endpoint address"
-#: settings/serializers/auth/oidc.py:91
+#: settings/serializers/auth/oidc.py:92
msgid "Signature algorithm"
msgstr "Signature algorithm"
-#: settings/serializers/auth/oidc.py:94
+#: settings/serializers/auth/oidc.py:95
msgid "Signing key"
msgstr "Signature Key"
-#: settings/serializers/auth/oidc.py:97
+#: settings/serializers/auth/oidc.py:98
msgid "Scopes"
msgstr "連接範圍"
-#: settings/serializers/auth/oidc.py:100
+#: settings/serializers/auth/oidc.py:101
msgid "ID Token max age (s)"
msgstr "Token validity time (seconds)"
-#: settings/serializers/auth/oidc.py:103
+#: settings/serializers/auth/oidc.py:104
msgid "ID Token include claims"
msgstr "Claims"
-#: settings/serializers/auth/oidc.py:106
+#: settings/serializers/auth/oidc.py:107
msgid "Use state"
msgstr "使用狀態"
-#: settings/serializers/auth/oidc.py:109
+#: settings/serializers/auth/oidc.py:110
msgid "Use nonce"
msgstr "臨時使用"
@@ -5620,44 +5730,44 @@ msgstr ""
msgid "FIDO Server name"
msgstr "Passkey Service Name"
-#: settings/serializers/auth/radius.py:13
-#: settings/serializers/auth/radius.py:15
+#: settings/serializers/auth/radius.py:14
+#: settings/serializers/auth/radius.py:16
msgid "Radius"
msgstr "Radius"
-#: settings/serializers/auth/radius.py:22
+#: settings/serializers/auth/radius.py:23
msgid "OTP in RADIUS"
msgstr "Use Radius OTP"
-#: settings/serializers/auth/radius.py:23
+#: settings/serializers/auth/radius.py:24
msgid "* Using OTP in RADIUS means users can employ RADIUS as a method for MFA"
msgstr "* 在 RADIUS 中使用 OTP 意味著使用者可以利用 RADIUS 作為 MFA 的方法 "
-#: settings/serializers/auth/saml2.py:10 settings/serializers/auth/saml2.py:13
+#: settings/serializers/auth/saml2.py:12 settings/serializers/auth/saml2.py:15
msgid "SAML2"
msgstr "SAML2"
-#: settings/serializers/auth/saml2.py:16
+#: settings/serializers/auth/saml2.py:18
msgid "IDP Metadata URL"
msgstr "IDP Metadata Address"
-#: settings/serializers/auth/saml2.py:19
+#: settings/serializers/auth/saml2.py:21
msgid "IDP Metadata XML"
msgstr "IDP Metadata XML"
-#: settings/serializers/auth/saml2.py:22
+#: settings/serializers/auth/saml2.py:24
msgid "SP advanced settings"
msgstr "進階設定"
-#: settings/serializers/auth/saml2.py:26
+#: settings/serializers/auth/saml2.py:28
msgid "SP private key"
msgstr "SP 金鑰"
-#: settings/serializers/auth/saml2.py:30
+#: settings/serializers/auth/saml2.py:32
msgid "SP cert"
msgstr "SP 證書"
-#: settings/serializers/auth/saml2.py:35
+#: settings/serializers/auth/saml2.py:37
msgid ""
"User attribute mapping, where the `key` is the SAML2 service user attribute "
"name and the `value` is the JumpServer user attribute name"
@@ -5665,15 +5775,23 @@ msgstr ""
" 使用者屬性映射,其中 `key` 是 SAML2 服務使用者屬性名稱,`value` 是 "
"JumpServer 使用者屬性名稱"
-#: settings/serializers/auth/saml2.py:41
+#: settings/serializers/auth/saml2.py:43
msgid "When the user signs out, they also be logged out from the SAML2 server"
msgstr "當使用者登出時,他們也會從 SAML2 伺服器登出"
+#: settings/serializers/auth/slack.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the Slack service user attribute name"
+msgstr ""
+"使用者屬性對照,其中 `key` 是 JumpServer 使用者屬性名稱,`value` 是 Slack 服"
+"務使用者屬性名稱"
+
#: settings/serializers/auth/sms.py:18
msgid "Enable Short Message Service (SMS)"
msgstr "啟用簡訊服務 (SMS)"
-#: settings/serializers/auth/sms.py:21 xpack/plugins/cloud/models.py:35
+#: settings/serializers/auth/sms.py:21 xpack/plugins/cloud/models.py:36
msgid "Provider"
msgstr "雲服務商"
@@ -5687,11 +5805,11 @@ msgstr "驗證碼長度"
#: settings/serializers/auth/sms.py:26
msgid "Length of the sent verification code"
-msgstr "發送驗證碼"
+msgstr "發送的驗證碼長度"
#: settings/serializers/auth/sms.py:31 settings/serializers/auth/sms.py:54
#: settings/serializers/auth/sms.py:62 settings/serializers/auth/sms.py:71
-#: settings/serializers/auth/sms.py:82 settings/serializers/msg.py:80
+#: settings/serializers/auth/sms.py:82 settings/serializers/msg.py:83
msgid "Signature"
msgstr "簽名"
@@ -5700,7 +5818,7 @@ msgstr "簽名"
msgid "Template code"
msgstr "模板"
-#: settings/serializers/auth/sms.py:40 users/models/user.py:920
+#: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:76
#: users/serializers/user.py:155
msgid "Phone"
msgstr "手機"
@@ -5769,6 +5887,14 @@ msgstr "令牌有效期"
msgid "Unit: second"
msgstr "單位: 秒"
+#: settings/serializers/auth/wecom.py:20
+msgid ""
+"User attribute mapping, where the `key` is the JumpServer user attribute "
+"name and the `value` is the WeCom service user attribute name"
+msgstr ""
+"使用者屬性映射,其中 `key` 是 JumpServer 使用者屬性名稱,`value` 是企業微信服"
+"務使用者屬性名稱"
+
#: settings/serializers/basic.py:11
msgid "Site URL"
msgstr "目前網站 URL"
@@ -5864,7 +5990,7 @@ msgid ""
msgstr ""
"會話、錄影,命令記錄超過該時長將會被清除 (影響資料庫儲存,OSS 等不受影響)"
-#: settings/serializers/feature.py:18 settings/serializers/msg.py:65
+#: settings/serializers/feature.py:18 settings/serializers/msg.py:68
msgid "Subject"
msgstr "主題"
@@ -5899,74 +6025,74 @@ msgstr ""
"如果特定數值小於999,系統將在每日晚間自動執行任務:檢查並刪除超出預定數量的歷"
"史帳號。如果該數值達到或超過999,則不進行任何歷史帳號的刪除操作。"
-#: settings/serializers/feature.py:73 settings/serializers/feature.py:77
+#: settings/serializers/feature.py:73 settings/serializers/feature.py:79
msgid "Chat AI"
msgstr "聊天 AI"
-#: settings/serializers/feature.py:80
-msgid "Base URL"
-msgstr "JumpServer 地址"
+#: settings/serializers/feature.py:82
+msgid "GPT Base URL"
+msgstr "GPT 地址"
-#: settings/serializers/feature.py:81
+#: settings/serializers/feature.py:83
msgid "The base URL of the GPT service. For example: https://api.openai.com/v1"
msgstr "GPT 服務的基礎 URL。例如:https://api.openai.com/v1"
-#: settings/serializers/feature.py:84 templates/_header_bar.html:96
+#: settings/serializers/feature.py:86 templates/_header_bar.html:96
msgid "API Key"
msgstr "API Key"
-#: settings/serializers/feature.py:88
+#: settings/serializers/feature.py:90
msgid ""
"The proxy server address of the GPT service. For example: http://ip:port"
msgstr "GPT 服務的代理伺服器地址。例如:http://ip:port"
-#: settings/serializers/feature.py:91
+#: settings/serializers/feature.py:93
msgid "GPT Model"
msgstr "GPT 模型"
-#: settings/serializers/feature.py:117
+#: settings/serializers/feature.py:102
msgid "Approval without login"
msgstr "免登入審核"
-#: settings/serializers/feature.py:118
+#: settings/serializers/feature.py:103
msgid "Allow direct approval ticket without login"
msgstr "允許無需登入直接批准工單"
-#: settings/serializers/feature.py:122
+#: settings/serializers/feature.py:107
msgid "Period"
msgstr "時段"
-#: settings/serializers/feature.py:123
+#: settings/serializers/feature.py:108
msgid ""
"The default authorization time period when applying for assets via a ticket"
msgstr "工單申請資產的預設授權時間段"
-#: settings/serializers/feature.py:126
+#: settings/serializers/feature.py:111
msgid "hour"
msgstr "時"
-#: settings/serializers/feature.py:127
+#: settings/serializers/feature.py:112
msgid "Unit"
msgstr "單位"
-#: settings/serializers/feature.py:127
+#: settings/serializers/feature.py:112
msgid "The unit of period"
msgstr "執行週期"
-#: settings/serializers/feature.py:136
+#: settings/serializers/feature.py:121
msgid ""
"Allow users to execute batch commands in the Workbench - Job Center - Adhoc"
msgstr "允許使用者在工作台 - 作業中心 - Adhoc 中執行批量指令"
-#: settings/serializers/feature.py:140
+#: settings/serializers/feature.py:125
msgid "Command blacklist"
msgstr "作業中心命令黑名單"
-#: settings/serializers/feature.py:141
+#: settings/serializers/feature.py:126
msgid "Command blacklist in Adhoc"
msgstr "作業中心指令黑名單"
-#: settings/serializers/feature.py:146
+#: settings/serializers/feature.py:131
#: terminal/models/virtualapp/provider.py:17
#: terminal/models/virtualapp/virtualapp.py:36
#: terminal/models/virtualapp/virtualapp.py:97
@@ -5974,11 +6100,11 @@ msgstr "作業中心指令黑名單"
msgid "Virtual app"
msgstr "虛擬應用"
-#: settings/serializers/feature.py:149
+#: settings/serializers/feature.py:134
msgid "Virtual App"
msgstr "虛擬應用"
-#: settings/serializers/feature.py:151
+#: settings/serializers/feature.py:136
msgid ""
"Virtual applications, you can use the Linux operating system as an "
"application server in remote applications."
@@ -5992,31 +6118,29 @@ msgstr "SMTP"
msgid "EXCHANGE"
msgstr ""
-#: settings/serializers/msg.py:33
+#: settings/serializers/msg.py:34
msgid "The user to be used for email server authentication"
-msgstr "SSO認證時,如果沒有返回郵件地址,將使用該後綴"
+msgstr "登入郵件伺服器的使用者名稱。這通常是你的郵件地址"
-#: settings/serializers/msg.py:37
+#: settings/serializers/msg.py:38
msgid ""
"Password to use for the email server. It is used in conjunction with `User` "
"when authenticating to the email server"
-msgstr ""
-"用於電子郵件伺服器的密碼。在向電子郵件伺服器進行身份驗證時,它與使用者一起使"
-"用"
+msgstr "登入郵件伺服器的密碼"
-#: settings/serializers/msg.py:40
+#: settings/serializers/msg.py:41
msgid "Sender"
msgstr "發件人"
-#: settings/serializers/msg.py:41
+#: settings/serializers/msg.py:42
msgid "Sender email address (default to using the `User`)"
msgstr "寄件人電子郵件地址(預設使用“使用者”)"
-#: settings/serializers/msg.py:45
+#: settings/serializers/msg.py:46
msgid "The recipient is used for testing the email server's connectivity"
msgstr "收件人用於測試電子郵件伺服器的連通性"
-#: settings/serializers/msg.py:49
+#: settings/serializers/msg.py:51
msgid ""
"Whether to use an implicit TLS (secure) connection when talking to the SMTP "
"server. In most email documentation this type of TLS connection is referred "
@@ -6025,11 +6149,11 @@ msgstr ""
"與 SMTP 伺服器通信時是否使用隱式 TLS(安全)連接。在大多數電子郵件文檔中,這"
"種類型的 TLS 連接稱為 SSL。它通常在埠 465 上使用"
-#: settings/serializers/msg.py:52
+#: settings/serializers/msg.py:54
msgid "Use TLS"
msgstr "使用 TLS"
-#: settings/serializers/msg.py:53
+#: settings/serializers/msg.py:56
msgid ""
"Whether to use a TLS (secure) connection when talking to the SMTP server. "
"This is used for explicit TLS connections, generally on port 587"
@@ -6037,25 +6161,25 @@ msgstr ""
"與 SMTP 伺服器通信時是否使用 TLS(安全)連接。這用於顯式 TLS 連接,通常在埠 "
"587 上"
-#: settings/serializers/msg.py:61
+#: settings/serializers/msg.py:64
msgid "Subject prefix"
msgstr "主題前綴"
-#: settings/serializers/msg.py:66
+#: settings/serializers/msg.py:69
msgid ""
"Tips: When creating a user, send the subject of the email (eg:Create account "
"successfully)"
msgstr "提示: 創建用戶時,發送設置密碼郵件的主題 (例如: 創建用戶成功)"
-#: settings/serializers/msg.py:70
+#: settings/serializers/msg.py:73
msgid "Honorific"
msgstr "郵件問候語"
-#: settings/serializers/msg.py:71
+#: settings/serializers/msg.py:74
msgid "Tips: When creating a user, send the honorific of the email (eg:Hello)"
msgstr "提示: 創建用戶時,發送設置密碼郵件的敬語 (例如: 你好)"
-#: settings/serializers/msg.py:77
+#: settings/serializers/msg.py:80
#, python-brace-format
msgid ""
"Tips: When creating a user, send the content of the email, support "
@@ -6063,7 +6187,7 @@ msgid ""
msgstr ""
"提示: 創建用戶時,發送設置密碼郵件的內容, 支持 {username} {name} {email} 標籤"
-#: settings/serializers/msg.py:81
+#: settings/serializers/msg.py:84
msgid "Tips: Email signature (eg:jumpserver)"
msgstr "郵件署名 (如:jumpserver)"
@@ -6363,12 +6487,6 @@ msgid ""
"* Allow users to log in to the KoKo component via password authentication"
msgstr "* 允許用戶透過密碼驗證登入KoKo元件"
-#: settings/serializers/terminal.py:34 users/forms/profile.py:172
-#: users/models/user.py:933
-#: xpack/plugins/cloud/serializers/account_attrs.py:210
-msgid "Public key"
-msgstr "SSH公鑰"
-
#: settings/serializers/terminal.py:36
msgid ""
"* Allow users to log in to the KoKo component via Public key "
@@ -6557,13 +6675,13 @@ msgstr "認證失敗: (未知): {}"
msgid "Authentication success: {}"
msgstr "認證成功: {}"
-#: settings/ws.py:195
-msgid "Get ldap users is None"
-msgstr "獲取 LDAP 用戶為 None"
+#: settings/ws.py:198
+msgid "No LDAP user was found"
+msgstr "沒有取得到 LDAP 用戶"
-#: settings/ws.py:205
-msgid "Imported {} users successfully (Organization: {})"
-msgstr "成功匯入 {} 個用戶 ( 組織: {} )"
+#: settings/ws.py:204
+msgid "Total {}, success {}, failure {}"
+msgstr "總共 {},成功 {},失敗 {}"
#: templates/_csv_import_export.html:8
msgid "Export"
@@ -6718,12 +6836,12 @@ msgstr "驗證碼已發送"
msgid "Home page"
msgstr "首頁"
-#: templates/resource_download.html:18 templates/resource_download.html:33
+#: templates/resource_download.html:20 templates/resource_download.html:35
#: users/const.py:65
msgid "Client"
msgstr "用戶端"
-#: templates/resource_download.html:20
+#: templates/resource_download.html:22
msgid ""
"JumpServer Client, currently used to launch the client, now only support "
"launch RDP SSH client, The Telnet client will next"
@@ -6731,25 +6849,25 @@ msgstr ""
"JumpServer 用戶端,目前用來喚起 特定用戶端程序 連接資產, 目前僅支持 RDP SSH "
"用戶端,Telnet 會在未來支持"
-#: templates/resource_download.html:33
+#: templates/resource_download.html:35
msgid "Microsoft"
msgstr "微軟"
-#: templates/resource_download.html:33
+#: templates/resource_download.html:35
msgid "Official"
msgstr "官方"
-#: templates/resource_download.html:35
+#: templates/resource_download.html:37
msgid ""
"macOS needs to download the client to connect RDP asset, which comes with "
"Windows"
msgstr "macOS 需要下載用戶端來連接 RDP 資產,Windows 系統默認安裝了該程序"
-#: templates/resource_download.html:44
+#: templates/resource_download.html:45
msgid "Windows Remote application publisher tools"
msgstr "Windows 遠程應用發布伺服器工具"
-#: templates/resource_download.html:45
+#: templates/resource_download.html:46
msgid ""
"OpenSSH is a program used to connect remote applications in the Windows "
"Remote Application Publisher"
@@ -6900,7 +7018,7 @@ msgid "High"
msgstr "較高"
#: terminal/const.py:47 terminal/const.py:84
-#: users/templates/users/reset_password.html:53
+#: users/templates/users/reset_password.html:54
msgid "Normal"
msgstr "正常"
@@ -6960,55 +7078,60 @@ msgstr "不支持批次創建"
msgid "Storage is invalid"
msgstr "儲存無效"
-#: terminal/models/applet/applet.py:30 xpack/plugins/license/models.py:88
+#: terminal/models/applet/applet.py:31 xpack/plugins/license/models.py:88
msgid "Community edition"
msgstr "社區版"
-#: terminal/models/applet/applet.py:31
+#: terminal/models/applet/applet.py:32
msgid "Enterprise"
msgstr "企業版"
-#: terminal/models/applet/applet.py:36
+#: terminal/models/applet/applet.py:35
+#: terminal/models/virtualapp/virtualapp.py:20
+msgid "Display name"
+msgstr "顯示名稱"
+
+#: terminal/models/applet/applet.py:37
#: terminal/models/virtualapp/virtualapp.py:22
msgid "Author"
msgstr "作者"
-#: terminal/models/applet/applet.py:38 terminal/serializers/applet.py:31
+#: terminal/models/applet/applet.py:39 terminal/serializers/applet.py:31
msgid "Edition"
msgstr "版本"
-#: terminal/models/applet/applet.py:43
+#: terminal/models/applet/applet.py:44
msgid "Can concurrent"
msgstr "可以並發"
-#: terminal/models/applet/applet.py:48 terminal/serializers/applet_host.py:167
+#: terminal/models/applet/applet.py:49 terminal/serializers/applet_host.py:167
#: terminal/serializers/storage.py:193
msgid "Hosts"
msgstr "主機"
-#: terminal/models/applet/applet.py:93
+#: terminal/models/applet/applet.py:94
#: terminal/models/virtualapp/virtualapp.py:66
msgid "Applet pkg not valid, Missing file {}"
msgstr "Applet pkg 無效,缺少文件 {}"
-#: terminal/models/applet/applet.py:112
+#: terminal/models/applet/applet.py:113
msgid "Load platform.yml failed: {}"
msgstr "載入 platform.yml 失敗: {}"
-#: terminal/models/applet/applet.py:115
+#: terminal/models/applet/applet.py:116
msgid "Only support custom platform"
msgstr "只支持自訂平台"
-#: terminal/models/applet/applet.py:120
+#: terminal/models/applet/applet.py:121
msgid "Missing type in platform.yml"
msgstr "在 platform.yml 中缺少類型"
-#: terminal/models/applet/applet.py:319 terminal/models/applet/host.py:36
+#: terminal/models/applet/applet.py:330 terminal/models/applet/host.py:36
#: terminal/models/applet/host.py:138
msgid "Hosting"
msgstr "宿主機"
-#: terminal/models/applet/applet.py:325
+#: terminal/models/applet/applet.py:336
msgid "Applet Publication"
msgstr "應用發布"
@@ -7303,7 +7426,7 @@ msgid "Command and replay storage"
msgstr "命令及錄影儲存"
#: terminal/notifications.py:240 terminal/tasks.py:153
-#: xpack/plugins/cloud/api.py:154
+#: xpack/plugins/cloud/api.py:160
#: xpack/plugins/cloud/serializers/account.py:121
#: xpack/plugins/cloud/serializers/account.py:123
msgid "Test failure: Account invalid"
@@ -7544,7 +7667,7 @@ msgid "Access key secret"
msgstr "Access key secret(SK)"
#: terminal/serializers/storage.py:68 xpack/plugins/cloud/manager.py:100
-#: xpack/plugins/cloud/models.py:273
+#: xpack/plugins/cloud/models.py:285
msgid "Region"
msgstr "地域"
@@ -7564,11 +7687,6 @@ msgstr "端點後綴"
msgid "HOST"
msgstr "主機"
-#: terminal/serializers/storage.py:146 users/models/user.py:930
-#: xpack/plugins/cloud/serializers/account_attrs.py:213
-msgid "Private key"
-msgstr "ssh私鑰"
-
#: terminal/serializers/storage.py:152
msgid "SFTP Root"
msgstr "SFTP根路徑"
@@ -7613,7 +7731,15 @@ msgstr "索引"
msgid "Doc type"
msgstr "文件類型"
-#: terminal/serializers/storage.py:263
+#: terminal/serializers/storage.py:257
+msgid "Store locally"
+msgstr "本地儲存"
+
+#: terminal/serializers/storage.py:258
+msgid "Do not save"
+msgstr "不儲存"
+
+#: terminal/serializers/storage.py:273
msgid ""
"set as the default storage, will make new Component use the current storage "
"by default, without affecting existing Component"
@@ -7803,7 +7929,7 @@ msgstr "沒有埠可以使用,檢查並修改配置文件中 Magnus 監聽的
msgid "All available port count: {}, Already use port count: {}"
msgstr "所有可用埠數量:{},已使用埠數量:{}"
-#: tickets/api/ticket.py:88 tickets/models/ticket/general.py:286
+#: tickets/api/ticket.py:88 tickets/models/ticket/general.py:289
msgid "Applicant"
msgstr "申請人"
@@ -7840,30 +7966,14 @@ msgid "Two level"
msgstr "2 級"
#: tickets/const.py:54
-msgid "Org admin"
-msgstr "組織管理員"
-
-#: tickets/const.py:55
-msgid "Custom user"
-msgstr "自訂用戶"
-
-#: tickets/const.py:56
-msgid "Super admin"
-msgstr "超級管理員"
-
-#: tickets/const.py:57
-msgid "Super admin and org admin"
-msgstr "組織管理員或超級管理員"
-
-#: tickets/const.py:61
msgid "All assets"
msgstr "所有資產"
-#: tickets/const.py:62
+#: tickets/const.py:55
msgid "Permed assets"
msgstr "授權的資產"
-#: tickets/const.py:63
+#: tickets/const.py:56
msgid "Permed valid assets"
msgstr "有效授權的資產"
@@ -7906,24 +8016,16 @@ msgstr "用戶顯示名稱"
msgid "Body"
msgstr "內容"
-#: tickets/models/flow.py:19 tickets/models/flow.py:61
-#: tickets/models/ticket/general.py:42
+#: tickets/models/flow.py:21 tickets/models/flow.py:47
+#: tickets/models/ticket/general.py:45
msgid "Approve level"
msgstr "審批級別"
-#: tickets/models/flow.py:24 tickets/serializers/flow.py:17
-msgid "Approve strategy"
-msgstr "審批策略"
-
-#: tickets/models/flow.py:29 tickets/serializers/flow.py:19
-msgid "Assignees"
-msgstr "受理人"
-
-#: tickets/models/flow.py:33
+#: tickets/models/flow.py:26
msgid "Ticket flow approval rule"
msgstr "工單批准資訊"
-#: tickets/models/flow.py:66
+#: tickets/models/flow.py:52
msgid "Ticket flow"
msgstr "工單流程"
@@ -7977,35 +8079,35 @@ msgstr "命令過濾器"
msgid "Apply Command Ticket"
msgstr "命令覆核工單"
-#: tickets/models/ticket/general.py:77
+#: tickets/models/ticket/general.py:80
msgid "Ticket step"
msgstr "工單步驟"
-#: tickets/models/ticket/general.py:95
+#: tickets/models/ticket/general.py:98
msgid "Ticket assignee"
msgstr "工單受理人"
-#: tickets/models/ticket/general.py:270
+#: tickets/models/ticket/general.py:273
msgid "Title"
msgstr "標題"
-#: tickets/models/ticket/general.py:290
+#: tickets/models/ticket/general.py:293
msgid "TicketFlow"
msgstr "工單流程"
-#: tickets/models/ticket/general.py:293
+#: tickets/models/ticket/general.py:296
msgid "Approval step"
msgstr "審批步驟"
-#: tickets/models/ticket/general.py:296
+#: tickets/models/ticket/general.py:299
msgid "Relation snapshot"
msgstr "工單快照"
-#: tickets/models/ticket/general.py:399
+#: tickets/models/ticket/general.py:405
msgid "Please try again"
msgstr "請再次嘗試"
-#: tickets/models/ticket/general.py:475
+#: tickets/models/ticket/general.py:481
msgid "Super ticket"
msgstr "超級工單"
@@ -8053,15 +8155,7 @@ msgstr "你的工單已被處理, 處理人 - {}"
msgid "Ticket has processed - {} ({})"
msgstr "你的工單已被處理, 處理人 - {} ({})"
-#: tickets/serializers/flow.py:20
-msgid "Assignees display"
-msgstr "受理人名稱"
-
-#: tickets/serializers/flow.py:46
-msgid "Please select the Assignees"
-msgstr "請選擇受理人"
-
-#: tickets/serializers/flow.py:74
+#: tickets/serializers/flow.py:45
msgid "The current organization type already exists"
msgstr "當前組織已存在該類型"
@@ -8220,14 +8314,18 @@ msgstr "替換"
msgid "Suffix"
msgstr "加後綴"
-#: users/exceptions.py:10
+#: users/exceptions.py:9
msgid "MFA not enabled"
msgstr "MFA 多因子認證沒有開啟"
-#: users/exceptions.py:20
+#: users/exceptions.py:19
msgid "Unable to delete all users"
msgstr "無法刪除全部用戶"
+#: users/exceptions.py:24
+msgid "Create failed. The number of SSH keys has reached the limit"
+msgstr "創建失敗,SSH密鑰數量已達到上限"
+
#: users/forms/profile.py:48
msgid ""
"When enabled, you will enter the MFA binding process the next time you log "
@@ -8294,82 +8392,69 @@ msgstr "複製你的公鑰到這裡"
msgid "Public key should not be the same as your old one."
msgstr "不能和原來的金鑰相同"
-#: users/forms/profile.py:161 users/serializers/profile.py:76
-#: users/serializers/profile.py:160 users/serializers/profile.py:187
-msgid "Not a valid ssh public key"
-msgstr "SSH金鑰不合法"
-
#: users/models/preference.py:38 users/serializers/preference/preference.py:19
msgid "Preference"
msgstr "用戶設置"
-#: users/models/user.py:690
-msgid "Force enabled"
-msgstr "強制啟用"
-
-#: users/models/user.py:913 users/serializers/user.py:271
+#: users/models/user/__init__.py:69 users/serializers/user.py:271
msgid "Is service account"
msgstr "服務帳號"
-#: users/models/user.py:915
+#: users/models/user/__init__.py:71
msgid "Avatar"
msgstr "頭像"
-#: users/models/user.py:917
+#: users/models/user/__init__.py:73
msgid "Wechat"
msgstr "微信"
-#: users/models/user.py:926
+#: users/models/user/__init__.py:82
msgid "OTP secret key"
msgstr "OTP 金鑰"
# msgid "Private key"
# msgstr "ssh私鑰"
-#: users/models/user.py:936 users/serializers/profile.py:124
+#: users/models/user/__init__.py:92 users/serializers/profile.py:97
#: users/serializers/user.py:268
msgid "Is first login"
msgstr "首次登錄"
-#: users/models/user.py:954
+#: users/models/user/__init__.py:110
msgid "Date password last updated"
msgstr "最後更新密碼日期"
-#: users/models/user.py:957
+#: users/models/user/__init__.py:113
msgid "Need update password"
msgstr "需要更新密碼"
-#: users/models/user.py:981
+#: users/models/user/__init__.py:137
msgid "Date api key used"
msgstr "Api key 最後使用日期"
-#: users/models/user.py:1119
+#: users/models/user/__init__.py:276
msgid "Can not delete admin user"
msgstr "無法刪除管理員用戶"
-#: users/models/user.py:1133
+#: users/models/user/__init__.py:290
msgid "Can invite user"
msgstr "可以邀請用戶"
-#: users/models/user.py:1134
+#: users/models/user/__init__.py:291
msgid "Can remove user"
msgstr "可以移除用戶"
-#: users/models/user.py:1135
+#: users/models/user/__init__.py:292
msgid "Can match user"
msgstr "可以匹配用戶"
-#: users/models/user.py:1146
-msgid "Administrator"
-msgstr "管理員"
-
-#: users/models/user.py:1149
-msgid "Administrator is the super user of system"
-msgstr "Administrator是初始的超級管理員"
-
-#: users/models/user.py:1181
+#: users/models/user/__init__.py:321
msgid "User password history"
msgstr "用戶密碼歷史"
+#: users/models/user/_auth.py:34
+msgid "Force enabled"
+msgstr "強制啟用"
+
#: users/notifications.py:55
#: users/templates/users/_msg_password_expire_reminder.html:17
#: users/templates/users/reset_password.html:5
@@ -8500,7 +8585,7 @@ msgstr "命令行"
msgid "The old password is incorrect"
msgstr "舊密碼錯誤"
-#: users/serializers/profile.py:36 users/serializers/profile.py:174
+#: users/serializers/profile.py:36 users/serializers/profile.py:147
msgid "Password does not match security rules"
msgstr "密碼不滿足安全規則"
@@ -8624,7 +8709,7 @@ msgstr ""
msgid "name not unique"
msgstr "名稱重複"
-#: users/signal_handlers.py:35
+#: users/signal_handlers.py:39
msgid ""
"The administrator has enabled \"Only allow existing users to log in\", \n"
" and the current user is not in the user list. Please contact the "
@@ -8632,7 +8717,7 @@ msgid ""
msgstr ""
"管理員已開啟'僅允許已存在用戶登錄',當前用戶不在用戶列表中,請聯絡管理員。"
-#: users/signal_handlers.py:171
+#: users/signal_handlers.py:183
msgid "Clean up expired user sessions"
msgstr "清除過期的用戶會話"
@@ -8758,23 +8843,23 @@ msgstr "您的密碼必須滿足:"
msgid "Password strength"
msgstr "密碼強度:"
-#: users/templates/users/reset_password.html:51
+#: users/templates/users/reset_password.html:52
msgid "Very weak"
msgstr "很弱"
-#: users/templates/users/reset_password.html:52
+#: users/templates/users/reset_password.html:53
msgid "Weak"
msgstr "弱"
-#: users/templates/users/reset_password.html:54
+#: users/templates/users/reset_password.html:55
msgid "Medium"
msgstr "一般"
-#: users/templates/users/reset_password.html:55
+#: users/templates/users/reset_password.html:56
msgid "Strong"
msgstr "強"
-#: users/templates/users/reset_password.html:56
+#: users/templates/users/reset_password.html:57
msgid "Very strong"
msgstr "很強"
@@ -8910,15 +8995,15 @@ msgstr ""
"According to the current task configuration, assets that do not conform to "
"the \"\" policy will be skipped."
-#: xpack/plugins/cloud/api.py:66
+#: xpack/plugins/cloud/api.py:72
msgid "Test connection successful"
msgstr "測試成功"
-#: xpack/plugins/cloud/api.py:68
+#: xpack/plugins/cloud/api.py:74
msgid "Test connection failed: {}"
msgstr "測試連接失敗:{}"
-#: xpack/plugins/cloud/api.py:165
+#: xpack/plugins/cloud/api.py:171
msgid "User {} deleted the current resource and released the assets"
msgstr ""
"User {} deleted the assets that have been released by the current resource"
@@ -9023,7 +9108,7 @@ msgstr "私有IP"
msgid "Public IP"
msgstr "公網IP"
-#: xpack/plugins/cloud/const.py:42 xpack/plugins/cloud/models.py:347
+#: xpack/plugins/cloud/const.py:42 xpack/plugins/cloud/models.py:359
msgid "Instance name"
msgstr "實例名稱"
@@ -9094,7 +9179,7 @@ msgstr "Action 執行 ID"
#: xpack/plugins/cloud/manager.py:97
msgid "Synchronization regions"
-msgstr "沒有需要同步的使用者"
+msgstr "同步地區"
#: xpack/plugins/cloud/manager.py:115
#, python-format
@@ -9107,7 +9192,7 @@ msgstr ""
msgid "Failed to synchronize the instance \"%s\""
msgstr "Unable to synchronize instance %s"
-#: xpack/plugins/cloud/manager.py:334
+#: xpack/plugins/cloud/manager.py:337
#, python-format
msgid ""
"The updated platform of asset \"%s\" is inconsistent with the original "
@@ -9116,42 +9201,42 @@ msgstr ""
"The update platform of asset \"%s\" is not consistent with the original "
"platform type. Skip platform and protocol updates"
-#: xpack/plugins/cloud/manager.py:390
+#: xpack/plugins/cloud/manager.py:393
#, python-format
msgid "The asset \"%s\" already exists"
msgstr "\"資產 \"%s\" 已存在"
-#: xpack/plugins/cloud/manager.py:392
+#: xpack/plugins/cloud/manager.py:395
#, python-format
msgid "Update asset \"%s\""
msgstr "更新資產 \"%s\""
-#: xpack/plugins/cloud/manager.py:395
+#: xpack/plugins/cloud/manager.py:398
#, python-format
msgid "Asset \"%s\" has been updated"
msgstr "資產 \"%s\" 已更新"
-#: xpack/plugins/cloud/manager.py:405
+#: xpack/plugins/cloud/manager.py:408
#, python-format
msgid "Prepare to create asset \"%s\""
msgstr "Preparing to create asset %s"
-#: xpack/plugins/cloud/manager.py:426
+#: xpack/plugins/cloud/manager.py:429
#, python-format
msgid "Set nodes \"%s\""
msgstr "Delete Node: \"%s\""
-#: xpack/plugins/cloud/manager.py:452
+#: xpack/plugins/cloud/manager.py:455
#, python-format
msgid "Set accounts \"%s\""
msgstr "刪除帳號: %s"
-#: xpack/plugins/cloud/manager.py:468
+#: xpack/plugins/cloud/manager.py:471
#, python-format
msgid "Set protocols \"%s\""
msgstr "設定協議 \"%s\""
-#: xpack/plugins/cloud/manager.py:482 xpack/plugins/cloud/tasks.py:27
+#: xpack/plugins/cloud/manager.py:485 xpack/plugins/cloud/tasks.py:30
msgid "Run sync instance task"
msgstr "執行同步實例任務"
@@ -9159,164 +9244,165 @@ msgstr "執行同步實例任務"
msgid "Cloud center"
msgstr "雲管中心"
-#: xpack/plugins/cloud/models.py:38
+#: xpack/plugins/cloud/models.py:39
#: xpack/plugins/cloud/serializers/account.py:94
msgid "Attrs"
msgstr "屬性"
-#: xpack/plugins/cloud/models.py:39
+#: xpack/plugins/cloud/models.py:40
msgid "Validity"
msgstr "有效"
-#: xpack/plugins/cloud/models.py:44
+#: xpack/plugins/cloud/models.py:45
msgid "Cloud account"
msgstr "雲帳號"
-#: xpack/plugins/cloud/models.py:46
+#: xpack/plugins/cloud/models.py:47
msgid "Test cloud account"
msgstr "測試雲帳號"
-#: xpack/plugins/cloud/models.py:103
+#: xpack/plugins/cloud/models.py:104
#: xpack/plugins/cloud/serializers/account.py:76
-#: xpack/plugins/cloud/serializers/task.py:156
+#: xpack/plugins/cloud/serializers/task.py:157
+#: xpack/plugins/cloud/serializers/task.py:158
msgid "Regions"
msgstr "地域"
-#: xpack/plugins/cloud/models.py:106
+#: xpack/plugins/cloud/models.py:107
msgid "Hostname strategy"
msgstr "主機名策略"
-#: xpack/plugins/cloud/models.py:111
+#: xpack/plugins/cloud/models.py:112
msgid "IP network segment group"
msgstr "IP網段組"
-#: xpack/plugins/cloud/models.py:114
-#: xpack/plugins/cloud/serializers/task.py:159
+#: xpack/plugins/cloud/models.py:115
+#: xpack/plugins/cloud/serializers/task.py:161
msgid "Sync IP type"
msgstr "同步IP類型"
-#: xpack/plugins/cloud/models.py:117
+#: xpack/plugins/cloud/models.py:118
msgid "Always update"
msgstr "總是更新"
-#: xpack/plugins/cloud/models.py:119
+#: xpack/plugins/cloud/models.py:120
msgid "Fully synchronous"
msgstr "完全同步"
-#: xpack/plugins/cloud/models.py:124
+#: xpack/plugins/cloud/models.py:125
msgid "Date last sync"
msgstr "最後同步日期"
-#: xpack/plugins/cloud/models.py:127 xpack/plugins/cloud/models.py:365
-#: xpack/plugins/cloud/models.py:391
+#: xpack/plugins/cloud/models.py:128 xpack/plugins/cloud/models.py:377
+#: xpack/plugins/cloud/models.py:403
msgid "Strategy"
msgstr "策略"
-#: xpack/plugins/cloud/models.py:132 xpack/plugins/cloud/models.py:220
+#: xpack/plugins/cloud/models.py:133 xpack/plugins/cloud/models.py:221
msgid "Sync instance task"
msgstr "同步實例任務"
-#: xpack/plugins/cloud/models.py:231 xpack/plugins/cloud/models.py:283
+#: xpack/plugins/cloud/models.py:232 xpack/plugins/cloud/models.py:295
msgid "Date sync"
msgstr "同步日期"
-#: xpack/plugins/cloud/models.py:235
+#: xpack/plugins/cloud/models.py:236
msgid "Sync instance snapshot"
msgstr "同步實例快照"
-#: xpack/plugins/cloud/models.py:239
+#: xpack/plugins/cloud/models.py:244
msgid "Sync instance task execution"
msgstr "同步實例任務執行"
-#: xpack/plugins/cloud/models.py:263
+#: xpack/plugins/cloud/models.py:275
msgid "Sync task"
msgstr "同步任務"
-#: xpack/plugins/cloud/models.py:267
+#: xpack/plugins/cloud/models.py:279
msgid "Sync instance task history"
msgstr "同步實例任務歷史"
-#: xpack/plugins/cloud/models.py:270
+#: xpack/plugins/cloud/models.py:282
msgid "Instance"
msgstr "實例"
-#: xpack/plugins/cloud/models.py:287
+#: xpack/plugins/cloud/models.py:299
msgid "Sync instance detail"
msgstr "同步實例詳情"
-#: xpack/plugins/cloud/models.py:299 xpack/plugins/cloud/serializers/task.py:76
+#: xpack/plugins/cloud/models.py:311 xpack/plugins/cloud/serializers/task.py:77
msgid "Rule relation"
msgstr "條件關係"
-#: xpack/plugins/cloud/models.py:309
+#: xpack/plugins/cloud/models.py:321
msgid "Task strategy"
msgstr "任務策略"
-#: xpack/plugins/cloud/models.py:336
+#: xpack/plugins/cloud/models.py:348
msgid "Equal"
msgstr "等於"
-#: xpack/plugins/cloud/models.py:337
+#: xpack/plugins/cloud/models.py:349
msgid "Not Equal"
msgstr "不等於"
-#: xpack/plugins/cloud/models.py:338
+#: xpack/plugins/cloud/models.py:350
msgid "In"
msgstr "在...中"
-#: xpack/plugins/cloud/models.py:339
+#: xpack/plugins/cloud/models.py:351
msgid "Contains"
msgstr "包含"
-#: xpack/plugins/cloud/models.py:340
+#: xpack/plugins/cloud/models.py:352
msgid "Exclude"
msgstr "排除"
-#: xpack/plugins/cloud/models.py:341
+#: xpack/plugins/cloud/models.py:353
msgid "Startswith"
msgstr "以...開頭"
-#: xpack/plugins/cloud/models.py:342
+#: xpack/plugins/cloud/models.py:354
msgid "Endswith"
msgstr "以...結尾"
-#: xpack/plugins/cloud/models.py:348
+#: xpack/plugins/cloud/models.py:360
msgid "Instance platform"
msgstr "實例平台"
-#: xpack/plugins/cloud/models.py:349
+#: xpack/plugins/cloud/models.py:361
msgid "Instance address"
msgstr "實例地址"
-#: xpack/plugins/cloud/models.py:356
+#: xpack/plugins/cloud/models.py:368
msgid "Rule attr"
msgstr "規則屬性"
-#: xpack/plugins/cloud/models.py:360
+#: xpack/plugins/cloud/models.py:372
msgid "Rule match"
msgstr "規則匹配"
-#: xpack/plugins/cloud/models.py:362
+#: xpack/plugins/cloud/models.py:374
msgid "Rule value"
msgstr "規則值"
-#: xpack/plugins/cloud/models.py:369 xpack/plugins/cloud/serializers/task.py:79
+#: xpack/plugins/cloud/models.py:381 xpack/plugins/cloud/serializers/task.py:80
msgid "Strategy rule"
msgstr "條件"
-#: xpack/plugins/cloud/models.py:379
+#: xpack/plugins/cloud/models.py:391
msgid "Name strategy"
msgstr "主機名稱策略"
-#: xpack/plugins/cloud/models.py:386
+#: xpack/plugins/cloud/models.py:398
msgid "Action attr"
msgstr "動作屬性"
-#: xpack/plugins/cloud/models.py:388
+#: xpack/plugins/cloud/models.py:400
msgid "Action value"
msgstr "動作值"
-#: xpack/plugins/cloud/models.py:395 xpack/plugins/cloud/serializers/task.py:82
+#: xpack/plugins/cloud/models.py:407 xpack/plugins/cloud/serializers/task.py:83
msgid "Strategy action"
msgstr "動作"
@@ -9617,15 +9703,15 @@ msgstr "測試超時時間"
msgid "Project"
msgstr "project"
-#: xpack/plugins/cloud/serializers/task.py:154
+#: xpack/plugins/cloud/serializers/task.py:155
msgid "History count"
msgstr "執行次數"
-#: xpack/plugins/cloud/serializers/task.py:155
+#: xpack/plugins/cloud/serializers/task.py:156
msgid "Instance count"
msgstr "實例個數"
-#: xpack/plugins/cloud/tasks.py:41
+#: xpack/plugins/cloud/tasks.py:44
msgid "Period clean sync instance task execution"
msgstr "定期清除同步實例任務執行記錄"
diff --git a/apps/i18n/koko/en.json b/apps/i18n/koko/en.json
index c5d9cabd1..136efdb4b 100644
--- a/apps/i18n/koko/en.json
+++ b/apps/i18n/koko/en.json
@@ -25,6 +25,7 @@
"PauseSession": "Pause Session",
"ReadOnly": "Read-Only",
"Remove": "Remove",
+ "Confirm": "Confirm",
"RemoveShareUser": "You have been removed from the shared session.",
"RemoveShareUserConfirm": "Are you sure to remove the user from the shared session?",
"ResumeSession": "Resume Session",
@@ -49,4 +50,4 @@
"VerifyCode": "Verify Code",
"WaitFileTransfer": "Wait file transfer to finish",
"Writable": "Writable"
-}
\ No newline at end of file
+}
diff --git a/apps/i18n/koko/zh.json b/apps/i18n/koko/zh.json
index 1db0ca567..072b524ad 100644
--- a/apps/i18n/koko/zh.json
+++ b/apps/i18n/koko/zh.json
@@ -6,6 +6,7 @@
"CopyShareURLSuccess": "复制分享地址成功",
"CreateLink": "创建分享链接",
"CreateSuccess": "创建成功",
+ "Confirm": "确认",
"Download": "下载",
"DownloadSuccess": "下载成功",
"EndFileTransfer": "文件传输结束",
@@ -49,4 +50,4 @@
"VerifyCode": "验证码",
"WaitFileTransfer": "等待文件传输结束",
"Writable": "读写"
-}
\ No newline at end of file
+}
diff --git a/apps/i18n/lina/en.json b/apps/i18n/lina/en.json
index 043fd06b0..ce4363af4 100644
--- a/apps/i18n/lina/en.json
+++ b/apps/i18n/lina/en.json
@@ -173,6 +173,7 @@
"AverageTimeCost": "Average spend time",
"AwaitingMyApproval": "Assigned",
"Azure": "Azure (China)",
+ "Azure_Int": "Azure (International)",
"Backup": "Backup",
"BackupAccountsHelpText": "Backup account information externally. it can be stored in an external system or sent via email, supporting segmented delivery.",
"BadConflictErrorMsg": "Refreshing, please try again later",
@@ -241,6 +242,7 @@
"CanDragSelect": "Select time period by dragging mouse;No selection means all selected",
"Cancel": "Cancel",
"CancelCollection": "Cancel favorite",
+ "CancelTicket": "Cancel Ticket",
"CannotAccess": "Can't access the current page",
"Category": "Category",
"CeleryTaskLog": "Celery task log",
@@ -756,6 +758,7 @@
"NewSyncCount": "New sync",
"Next": "Next",
"No": "No",
+ "NoAccountFound": "No account found",
"NoContent": "No content",
"NoData": "No data available",
"NoFiles": "No file, upload on the left",
@@ -883,7 +886,7 @@
"PrivateKey": "Private key",
"Privileged": "Privileged",
"PrivilegedFirst": "Privileged first",
- "PrivilegedOnly": "Privileged accounts only",
+ "PrivilegedOnly": "Privileged only",
"PrivilegedTemplate": "Privileged",
"Product": "Product",
"ProfileSetting": "Profile info",
@@ -924,7 +927,7 @@
"RecentSession": "Recent sessions",
"RecentlyUsed": "Recently",
"Recipient": "Recipient",
- "RecipientHelpText": "If both recipient a and b are set, the account's key will be split into two parts",
+ "RecipientHelpText": "If both recipients A and B are set, the account's ciphertext will be split into two parts; if only one recipient is set, the key will not be split.",
"RecipientServer": "Receiving server",
"Reconnect": "Reconnect",
"Refresh": "Refresh",
@@ -963,7 +966,7 @@
"RequiredAssetOrNode": "Please select at least one asset or node",
"RequiredContent": "Please input command",
"RequiredEntryFile": "This file acts as the entry point for running and must be present",
- "RequiredRunas": "Please enter the execution user",
+ "RequiredRunas": "Enter exec user",
"RequiredSystemUserErrMsg": "Please select account",
"RequiredUploadFile": "Please upload the file!",
"Reset": "Reset",
@@ -1031,6 +1034,7 @@
"SameAccount": "Same account",
"SameAccountTip": "Account with the same username as authorized users",
"SameTypeAccountTip": "An account with the same username and key type already exists",
+ "Share": "Share",
"Saturday": "Sat",
"Save": "Save",
"SaveAdhoc": "Save command",
@@ -1101,7 +1105,6 @@
"Setting": "Setting",
"SettingInEndpointHelpText": "Configure service address and port in system settings / component settings / server endpoints",
"Settings": "System settings",
- "Settings...": "Settings...",
"Show": "Display",
"ShowAssetAllChildrenNode": "Show all sub-nodes assets",
"ShowAssetOnlyCurrentNode": "Only show current node assets",
@@ -1309,7 +1312,7 @@
"UserAclLists": "Login ACLs",
"UserAssetActivity": "User/Asset activity",
"UserCreate": "Create user",
- "UserData": "User",
+ "UserData": "User data",
"UserDetail": "User details",
"UserGroupCreate": "Create user group",
"UserGroupDetail": "User group details",
@@ -1334,7 +1337,7 @@
"Users": "User",
"UsersAmount": "User",
"UsersAndUserGroups": "Users/groups",
- "UsersTotal": "Total accounts",
+ "UsersTotal": "Total users",
"Valid": "Valid",
"Variable": "Variable",
"VariableHelpText": "You can use {{ key }} to read built-in variables in commands",
@@ -1384,5 +1387,11 @@
"ZoneList": "Zones",
"ZoneUpdate": "Update the zone",
"forceEnableMFAHelpText": "If force enable, user can not disable by themselves",
- "removeWarningMsg": "Are you sure you want to remove"
-}
\ No newline at end of file
+ "removeWarningMsg": "Are you sure you want to remove",
+ "RetrySelected": "Retry selected",
+ "Running": "Running",
+ "AdhocCreate": "Create the command",
+ "UploadHelpText": "Please upload a .zip file containing the following sample directory structure",
+ "SessionJoinRecords": "collaboration records",
+ "ApprovalSelected": "Batch approval"
+}
diff --git a/apps/i18n/lina/ja.json b/apps/i18n/lina/ja.json
index 6f79704bd..d1527e0fa 100644
--- a/apps/i18n/lina/ja.json
+++ b/apps/i18n/lina/ja.json
@@ -173,6 +173,7 @@
"AverageTimeCost": "平均所要時間",
"AwaitingMyApproval": "私の承認待ち",
"Azure": "Azure(中国)",
+ "Azure_Int": "アジュール(インターナショナル)",
"Backup": "バックアップ",
"BackupAccountsHelpText": "アカウント情報を外部にバックアップする。外部システムに保存するかメールを送信することもできます、セクション方式をサポートしています",
"BadConflictErrorMsg": "更新中です、しばらくお待ちください",
@@ -254,6 +255,7 @@
"CanDragSelect": "マウスドラッグで時間帯を選択可能;未選択は全選択と同じです",
"Cancel": "キャンセル",
"CancelCollection": "お気に入りキャンセル",
+ "CancelTicket": "作業指示をキャンセルする",
"CannotAccess": "現在のページへのアクセスができません",
"Category": "カテゴリ",
"CeleryTaskLog": "セロリタスクノログ",
@@ -599,6 +601,7 @@
"IPLoginLimit": "IPログイン制限",
"IPMatch": "IPマッチング",
"IPNetworkSegment": "IP範囲",
+ "IPType": "IPタイプ",
"Id": "ID",
"IdeaContent": "あなたがLinuxターミナルとして機能することを望んでいます。私はコマンドを入力し、あなたはターミナルが表示すべき内容を回答します。ターミナルの出力はユニークなコードブロック内でだけ応答してほしい、その他ではない。説明を書かないでください。何かをあなたに伝える必要があるとき、私はテキストを大括弧{備考テキスト}の中に置きます。",
"IdeaTitle": "🌱 Linux 端末",
@@ -699,7 +702,7 @@
"LoginAssetToday": "本日のアクティブな資産数",
"LoginAssets": "アクティブな資産",
"LoginConfirm": "ログインレビュー",
- "LoginConfirmUser": "確認方法",
+ "LoginConfirmUser": "ログインレビュー担当者",
"LoginCount": "ログイン回数",
"LoginDate": "ログイン日",
"LoginFailed": "ログイン失敗",
@@ -714,7 +717,7 @@
"LoginSucceeded": "ログイン成功",
"LoginTitleTip": "ヒント:企業版ユーザーのSSHログイン KoKo ログインページに表示されます(例:JumpServerオープンソースバスチオンへようこそ)",
"LoginUserRanking": "ログインアカウントランキング",
- "LoginUserToday": "本日のログインアカウント数",
+ "LoginUserToday": "今日のログインユーザー数",
"LoginUsers": "アクティブなアカウント",
"LogoIndexTip": "ヒント:管理ページの左上に表示されます(推奨画像サイズ:185px*55px)",
"LogoLogoutTip": "ヒント:これは、エンタープライズ版ユーザーのWebターミナルページに表示されます(推奨画像サイズ:82px*82px)",
@@ -781,6 +784,7 @@
"NewSyncCount": "新規同期",
"Next": "次へ",
"No": "いいえ",
+ "NoAccountFound": "アカウントが見つかりません",
"NoContent": "内容がありません",
"NoData": "データなし",
"NoFiles": "ファイルなし",
@@ -957,7 +961,7 @@
"RecentSession": "最近の会話",
"RecentlyUsed": "最近使用",
"Recipient": "受取人",
- "RecipientHelpText": "A B受信者が設定されている場合、アカウントの鍵は前後二つに分割されます",
+ "RecipientHelpText": "受信者 A と B が同時に設定されている場合、アカウントの暗号文は 2 つの部分に分割されます。受信者が 1 つだけ設定されている場合、キーは分割されません。",
"RecipientServer": "受信サーバー",
"Reconnect": "再接続",
"Refresh": "更新",
@@ -996,7 +1000,7 @@
"RequiredAssetOrNode": "少なくとも一つの資産またはノードを選択してください",
"RequiredContent": "コマンドを入力してください",
"RequiredEntryFile": "このファイルは実行のエントリポイントとして存在する必要があります",
- "RequiredRunas": "実行ユーザーを入力してください",
+ "RequiredRunas": "実行ユーザーを入力",
"RequiredSystemUserErrMsg": "アカウントを選択してください",
"RequiredUploadFile": "ファイルをアップロードしてください!",
"Reset": "復元",
@@ -1064,6 +1068,7 @@
"SameAccount": "同名アカウント",
"SameAccountTip": "権限を持つユーザーのユーザー名と同じアカウント",
"SameTypeAccountTip": "同じユーザー名、鍵の種類のアカウントがすでに存在しています",
+ "Share": "共有",
"Saturday": "土曜日",
"Save": "保存",
"SaveAdhoc": "コマンドを保存する",
@@ -1135,7 +1140,6 @@
"Setting": "設定",
"SettingInEndpointHelpText": "システム設定/コンポーネント設定/サーバーエンドポイントでサービスのアドレスとポートを設定してください",
"Settings": "システム設定",
- "Settings...": "設定...",
"Show": "表示",
"ShowAssetAllChildrenNode": "すべての子ノードの資産を表示",
"ShowAssetOnlyCurrentNode": "現在のノードアセットのみを表示",
@@ -1253,7 +1257,7 @@
"TemplateManagement": "テンプレート管理",
"TencentCloud": "テンセントクラウド",
"Terminal": "コンポーネント設定",
- "TerminalDetail": "端末の詳細",
+ "TerminalDetail": "コンポーネントの詳細",
"TerminalUpdate": "端末の更新",
"TerminalUpdateStorage": "ターミナルストレージの更新",
"Terminate": "終了",
@@ -1349,7 +1353,7 @@
"UserAclLists": "ユーザーログインルール",
"UserAssetActivity": "アカウント/アクティブアセット状況",
"UserCreate": "ユーザーを作成する",
- "UserData": "アカウントデータ",
+ "UserData": "ユーザーデータ",
"UserDetail": "ユーザーの詳細",
"UserGroupCreate": "ユーザーグループの作成",
"UserGroupDetail": "ユーザーグループ詳細",
@@ -1374,7 +1378,7 @@
"Users": "ユーザー",
"UsersAmount": "ユーザー",
"UsersAndUserGroups": "ユーザー/ユーザーグループ",
- "UsersTotal": "アカウントの総数",
+ "UsersTotal": "総ユーザー数",
"Valid": "有効",
"Variable": "変数",
"VariableHelpText": "コマンド中で {{ key }} を使用して内蔵変数を読み取ることができます",
@@ -1423,5 +1427,9 @@
"ZoneList": "地域リスト",
"ZoneUpdate": "更新エリア",
"forceEnableMFAHelpText": "強制的に有効化すると、ユーザーは自分で無効化することができません。",
- "removeWarningMsg": "削除してもよろしいですか"
-}
\ No newline at end of file
+ "removeWarningMsg": "削除してもよろしいですか",
+ "AdhocCreate": "アドホックコマンドを作成",
+ "UploadHelpText": "次のサンプル構造ディレクトリを含む .zip ファイルをアップロードしてください。",
+ "SessionJoinRecords": "協力記録",
+ "ApprovalSelected": "大量承認です"
+}
diff --git a/apps/i18n/lina/zh.json b/apps/i18n/lina/zh.json
index 6c773cc7d..f73ba2b88 100644
--- a/apps/i18n/lina/zh.json
+++ b/apps/i18n/lina/zh.json
@@ -172,7 +172,8 @@
"Automations": "自动化",
"AverageTimeCost": "平均花费时间",
"AwaitingMyApproval": "待我审批",
- "Azure": "Azure(中国)",
+ "Azure": "Azure (中国)",
+ "Azure_Int": "Azure (国际)",
"Backup": "备份",
"BackupAccountsHelpText": "备份账号信息到外部。可以存储到外部系统或发送邮件,支持分段方式",
"BadConflictErrorMsg": "正在刷新中,请稍后再试",
@@ -241,12 +242,13 @@
"CanDragSelect": "可拖动鼠标选择时间段;未选择等同全选",
"Cancel": "取消",
"CancelCollection": "取消收藏",
+ "CancelTicket": "取消工单",
"CannotAccess": "无法访问当前页面",
"Category": "类别",
"CeleryTaskLog": "Celery任务日志",
"Certificate": "证书",
"CertificateKey": "客户端密钥",
- "ChangeCredentials": "改密",
+ "ChangeCredentials": "账号改密",
"ChangeCredentialsHelpText": "定时修改账号密钥密码。账号随机生成密码,并同步到目标资产,如果同步成功,更新该账号的密码",
"ChangeField": "变更字段",
"ChangeOrganization": "更改组织",
@@ -508,7 +510,7 @@
"FeiShuOAuth": "飞书认证",
"FeiShuTest": "测试",
"FieldRequiredError": "此字段是必填项",
- "FileExplorer": "文件浏览",
+ "FileExplorer": "文件管理",
"FileManagement": "文件管理",
"FileNameTooLong": "文件名太长",
"FileSizeExceedsLimit": "文件大小超出限制",
@@ -581,6 +583,7 @@
"IPLoginLimit": "IP 登录限制",
"IPMatch": "IP 匹配",
"IPNetworkSegment": "IP网段",
+ "IPType": "IP 类型",
"Id": "ID",
"IdeaContent": "我想让你充当一个 Linux 终端。我将输入命令,你将回答终端应该显示的内容。我希望你只在一个独特的代码块内回复终端输出,而不是其他。不要写解释。当我需要告诉你一些事情时,我会把文字放在大括号里{备注文本}。",
"IdeaTitle": "🌱 Linux 终端",
@@ -676,7 +679,7 @@
"LoginAssetToday": "今日活跃资产数",
"LoginAssets": "活跃资产",
"LoginConfirm": "登录复核",
- "LoginConfirmUser": "确认方式",
+ "LoginConfirmUser": "登录复核 受理人",
"LoginCount": "登录次数",
"LoginDate": "登录日期",
"LoginFailed": "登录失败",
@@ -691,7 +694,7 @@
"LoginSucceeded": "登录成功",
"LoginTitleTip": "提示:将会显示在企业版用户 SSH 登录 KoKo 登录页面(eg: 欢迎使用JumpServer开源堡垒机)",
"LoginUserRanking": "登录账号排名",
- "LoginUserToday": "今日登录账号数",
+ "LoginUserToday": "今日登录用户数",
"LoginUsers": "活跃账号",
"LogoIndexTip": "提示:将会显示在管理页面左上方(建议图片大小为: 185px*55px)",
"LogoLogoutTip": "提示:将会显示在企业版用户的 Web 终端页面(建议图片大小为:82px*82px)",
@@ -757,6 +760,7 @@
"NewSyncCount": "新同步",
"Next": "下一步",
"No": "否",
+ "NoAccountFound": "未找到帐户",
"NoContent": "暂无内容",
"NoData": "暂无数据",
"NoFiles": "暂无文件",
@@ -926,7 +930,7 @@
"RecentSession": "最近会话",
"RecentlyUsed": "最近使用",
"Recipient": "接收人",
- "RecipientHelpText": "若收件人 A B 都设置,账号的密钥将被拆分成前后两部分",
+ "RecipientHelpText": "如果同时设置了收件人A和B,账号的密文将被拆分为两部分;如果只设置了一个收件人,密钥则不会被拆分。",
"RecipientServer": "接收服务器",
"Reconnect": "重新连接",
"Refresh": "刷新",
@@ -1033,6 +1037,7 @@
"SameAccount": "同名账号",
"SameAccountTip": "与被授权人用户名相同的账号",
"SameTypeAccountTip": "相同用户名、密钥类型的账号已存在",
+ "Share": "分享",
"Saturday": "周六",
"Save": "保存",
"SaveAdhoc": "保存命令",
@@ -1103,7 +1108,6 @@
"Setting": "设置",
"SettingInEndpointHelpText": "在 系统设置 / 组件设置 / 服务端点 中配置服务地址和端口",
"Settings": "系统设置",
- "Settings...": "设置...",
"Show": "显示",
"ShowAssetAllChildrenNode": "显示所有子节点资产",
"ShowAssetOnlyCurrentNode": "仅显示当前节点资产",
@@ -1216,7 +1220,7 @@
"TemplateManagement": "模版管理",
"TencentCloud": "腾讯云",
"Terminal": "组件设置",
- "TerminalDetail": "终端详情",
+ "TerminalDetail": "组件详情",
"TerminalUpdate": "更新终端",
"TerminalUpdateStorage": "更新终端存储",
"Terminate": "终断",
@@ -1311,7 +1315,7 @@
"UserAclLists": "用户登录规则",
"UserAssetActivity": "账号/资产活跃情况",
"UserCreate": "创建用户",
- "UserData": "账号数据",
+ "UserData": "用户数据",
"UserDetail": "用户详情",
"UserGroupCreate": "创建用户组",
"UserGroupDetail": "用户组详情",
@@ -1336,7 +1340,7 @@
"Users": "用户",
"UsersAmount": "用户",
"UsersAndUserGroups": "用户/用户组",
- "UsersTotal": "账号总数",
+ "UsersTotal": "用户总数",
"Valid": "有效",
"Variable": "变量",
"VariableHelpText": "您可以在命令中使用 {{ key }} 读取内置变量",
@@ -1385,5 +1389,12 @@
"ZoneList": "网域列表",
"ZoneUpdate": "更新网域",
"forceEnableMFAHelpText": "如果强制启用,用户无法自行禁用",
- "removeWarningMsg": "你确定要移除"
-}
\ No newline at end of file
+ "removeWarningMsg": "你确定要移除",
+ "VaultHCPMountPoint": "Vault 服务器的挂载点,默认为 jumpserver",
+ "RetrySelected": "重试所选",
+ "Running": "运行中",
+ "AdhocCreate": "创建命令",
+ "UploadHelpText": "请上传包含以下示例结构目录的 .zip 压缩文件",
+ "SessionJoinRecords": "协作记录",
+ "ApprovalSelected": "批量审批"
+}
diff --git a/apps/i18n/lina/zh_hant.json b/apps/i18n/lina/zh_hant.json
index 3f88abb1b..f38256e0c 100644
--- a/apps/i18n/lina/zh_hant.json
+++ b/apps/i18n/lina/zh_hant.json
@@ -233,8 +233,8 @@
"Automations": "自動化",
"AverageTimeCost": "平均花費時間",
"AwaitingMyApproval": "待我審批",
- "Azure": "Azure(中國)",
- "Azure_Int": "Azure(國際)",
+ "Azure": "Azure (中國)",
+ "Azure_Int": "Azure (國際)",
"Backup": "備份",
"BackupAccountsHelpText": "備份帳號資訊至外部。可以儲存到外部系統或寄送郵件,支援分段方式",
"BadConflictErrorMsg": "正在刷新中,請稍後再試",
@@ -326,13 +326,14 @@
"CanDragSelect": "可拖動滑鼠選擇時間段;未選擇等同全選",
"Cancel": "取消",
"CancelCollection": "取消收藏",
+ "CancelTicket": "取消工單",
"CannotAccess": "無法訪問當前頁面",
"Cas": "CAS設置",
"Category": "類別",
"CeleryTaskLog": "Celery任務日誌",
"Certificate": "證書",
"CertificateKey": "用戶端金鑰",
- "ChangeCredentials": "改密",
+ "ChangeCredentials": "帳號改密",
"ChangeCredentialsHelpText": "定時修改帳號密鑰密碼。帳號隨機生成密碼,並同步到目標資產,如果同步成功,更新該帳號的密碼",
"ChangeField": "變更欄位",
"ChangeOrganization": "更改組織",
@@ -766,6 +767,7 @@
"IPMatch": "IP 匹配",
"IPNetworkSegment": "IP網段",
"Icon": "圖示",
+ "IPType": "IP 類型",
"Id": "ID",
"IdeaContent": "我想讓你充當一個 Linux 終端。我將輸入命令,你將回答終端應該顯示的內容。我希望你只在一個獨特的代碼塊內回復終端輸出,而不是其他。不要寫解釋。當我需要告訴你一些事情時,我會把文字放在大括號裡{備註文本}。",
"IdeaTitle": "🌱 Linux 終端",
@@ -903,7 +905,7 @@
"LoginCity": "登入城市",
"LoginConfig": "登入配置",
"LoginConfirm": "登入覆核",
- "LoginConfirmUser": "確認方式",
+ "LoginConfirmUser": "登錄複核 受理人",
"LoginCount": "登入次數",
"LoginDate": "登入日期",
"LoginFailed": "登入失敗",
@@ -1009,6 +1011,7 @@
"NewSyncCount": "新同步",
"Next": "下一步",
"No": "否",
+ "NoAccountFound": "沒有找到帳戶",
"NoContent": "暫無內容",
"NoData": "暫無數據",
"NoFiles": "暫無文件",
@@ -1239,7 +1242,7 @@
"RecentSession": "最近會話",
"RecentlyUsed": "最近使用",
"Recipient": "接收人",
- "RecipientHelpText": "若收件人 A B 都設置,帳號的金鑰將被拆分成前後兩部分。如用戶未設置加密密碼 - 請前往個人資訊 -> 偏好設置中設置加密密碼",
+ "RecipientHelpText": "如果同時設定了收件人A和B,帳號的密文將被拆分為兩部分;如果只設定了一個收件人,密鑰則不會被拆分。",
"RecipientServer": "接收伺服器",
"Reconnect": "重新連接",
"Refresh": "刷新",
@@ -1375,6 +1378,7 @@
"SameAccount": "同名帳號",
"SameAccountTip": "與被授權人使用者名稱相同的帳號",
"SameTypeAccountTip": "相同使用者名稱、金鑰類型的帳號已存在",
+ "Share": "分享",
"Saturday": "週六",
"Save": "保存",
"SaveAdhoc": "保存命令",
@@ -1459,7 +1463,6 @@
"Setting": "設置",
"SettingInEndpointHelpText": "在 系統設置 / 組件設置 / 服務端點 中配置服務地址和埠",
"Settings": "系統設置",
- "Settings...": " Settings...",
"Show": "顯示",
"ShowAssetAllChildrenNode": "顯示所有子節點資產",
"ShowAssetOnlyCurrentNode": "僅顯示當前節點資產",
@@ -1605,7 +1608,7 @@
"Templates": "模板管理",
"TencentCloud": "騰訊雲",
"Terminal": "組件設置",
- "TerminalDetail": "終端詳情",
+ "TerminalDetail": "組件詳情",
"TerminalStat": "CPU/記憶體/磁碟",
"TerminalUpdate": "更新終端機",
"TerminalUpdateStorage": "更新終端儲存",
@@ -1727,7 +1730,7 @@
"UserAclLists": "用戶登入規則",
"UserAssetActivity": "用戶/資產活躍情況",
"UserCreate": "創建用戶",
- "UserData": "用戶數據",
+ "UserData": "使用者資料",
"UserDetail": "用戶詳情",
"UserFirstLogin": "首次登入",
"UserGroupCreate": "創建用戶組",
@@ -1909,7 +1912,7 @@
"consult": "諮詢",
"containerName": "容器名稱",
"contents": "內容",
- "createAdhoc": "創建命令",
+ "AdhocCreate": "創建命令",
"createBy": "創建者",
"createErrorMsg": "創建失敗",
"createSuccessMsg": "導入創建成功,總共:{count}",
@@ -2268,5 +2271,8 @@
"weComTest": "測試",
"week": "周",
"weekOf": "周的星期",
- "wildcardsAllowed": "允許的通配符"
-}
\ No newline at end of file
+ "wildcardsAllowed": "允許的通配符",
+ "UploadHelpText": "請上傳包含以下範例結構目錄的 .zip 壓縮文件",
+ "SessionJoinRecords": "協作記錄",
+ "ApprovalSelected": "批次審批"
+}
diff --git a/apps/i18n/luna/en.json b/apps/i18n/luna/en.json
index 1d09fc62d..dffcf3f0d 100644
--- a/apps/i18n/luna/en.json
+++ b/apps/i18n/luna/en.json
@@ -104,7 +104,7 @@
"Log out": "Log out",
"Login reminder": "Login reminder",
"Login review approved": "Login review has been approved, connecting assets...",
- "LoginExpireMsg": "Login session expired, please re-login",
+ "LoginExpireMsg": "Your session has timed out. Please log in through a new window and return to this page to continue your operations.",
"Manual accounts": "Manual accounts",
"Module": "Module",
"Multi Screen": "Multi Screen",
@@ -209,11 +209,16 @@
"asset": "asset",
"cols": "cols",
"confirm": "confirm",
+ "connectDisabledTipsNoAccount": "Tips: No valid authorization account found, current resource cannot be connected. Please contact the administrator for assistance",
+ "connectDisabledTipsNoConnectMethod": "Tips: No valid connection method found, current resource cannot be connected. Please contact the administrator for assistance",
+ "connectDisabledTipsMethodDisabled": "Tips: No valid remote application deployment machine found, current resource cannot be connected. Please contact the administrator for assistance",
"connect info": "connect info",
"download": "download",
"rows": "rows",
"start time": "start time",
"success": "success",
"system user": "system user",
- "user": "user"
-}
\ No newline at end of file
+ "user": "user",
+ "Viewer": "Viewer",
+ "Operator": "Operator"
+}
diff --git a/apps/i18n/luna/ja.json b/apps/i18n/luna/ja.json
index 9574002d3..53e24ddc2 100644
--- a/apps/i18n/luna/ja.json
+++ b/apps/i18n/luna/ja.json
@@ -103,7 +103,7 @@
"Log out": "ログインを終了",
"Login reminder": "ログインリマインダー",
"Login review approved": "ログイン監査に合格し、アセットを接続しています...",
- "LoginExpireMsg": "ログインが期限切れになりました。ログインし直してください",
+ "LoginExpireMsg": "現在のログインはタイムアウトしました。ウィンドウを閉じないでください。新しいウィンドウでログインすると現在のページが復元されます。復元されない場合は、ページを更新してください。",
"Manual accounts": "手動アカウント",
"MenuAccountTemplates": "アカウントテンプレート",
"Module": "ユニット",
@@ -222,5 +222,7 @@
"start time": "開始時間",
"success": "成功",
"system user": "システムユーザー",
- "user": "ユーザー"
-}
\ No newline at end of file
+ "user": "ユーザー",
+ "Viewer": "ビューア",
+ "Operator": "オペレーター"
+}
diff --git a/apps/i18n/luna/zh.json b/apps/i18n/luna/zh.json
index 180d66016..a761a7713 100644
--- a/apps/i18n/luna/zh.json
+++ b/apps/i18n/luna/zh.json
@@ -102,7 +102,7 @@
"Log out": "退出登录",
"Login reminder": "登录提醒",
"Login review approved": "登录审核已通过, 正在连接资产...",
- "LoginExpireMsg": "登录已过期,请重新登录",
+ "LoginExpireMsg": "当前登录已超时,请不要关闭窗口。在新的窗口登录后即可恢复当前页面,如未恢复请刷新页面。",
"Manual accounts": "手动账号",
"MenuAccountTemplates": "账号模版",
"Module": "模块",
@@ -207,11 +207,16 @@
"asset": "资产",
"cols": "列数",
"confirm": "确认",
+ "connectDisabledTipsNoAccount": "提示:未找到有效的授权账号,当前资源无法连接,请联系管理员进行处理",
+ "connectDisabledTipsNoConnectMethod": "提示:未找到有效的连接方式,当前资源无法连接,请联系管理员进行处理",
+ "connectDisabledTipsMethodDisabled": "提示:未找到有效的远程应用发布机,当前资源无法连接,请联系管理员进行处理",
"connect info": "连接信息",
"download": "下载",
"rows": "行数",
"start time": "开始时间",
"success": "成功",
"system user": "系统用户",
- "user": "用户"
-}
\ No newline at end of file
+ "user": "用户",
+ "Viewer": "查看人",
+ "Operator": "操作人"
+}
diff --git a/apps/i18n/luna/zh_hant.json b/apps/i18n/luna/zh_hant.json
index ce4820314..be0659e66 100644
--- a/apps/i18n/luna/zh_hant.json
+++ b/apps/i18n/luna/zh_hant.json
@@ -103,7 +103,7 @@
"Log out": "退出登入",
"Login reminder": "登入提醒",
"Login review approved": "登入審核已通過, 正在連接資產...",
- "LoginExpireMsg": "登入已過期,請重新登入",
+ "LoginExpireMsg": "目前登入已逾時,請不要關閉視窗。在新的視窗登入後即可恢復目前頁面,如未恢復請重新整理頁面。",
"Manual accounts": "手動帳號",
"MenuAccountTemplates": "帳號範本",
"Module": "模組",
@@ -220,5 +220,7 @@
"start time": "開始時間",
"success": "成功",
"system user": "系統用戶",
- "user": "用戶"
-}
\ No newline at end of file
+ "user": "用戶",
+ "Viewer": "查看人",
+ "Operator": "操作人"
+}
diff --git a/apps/jumpserver/api.py b/apps/jumpserver/api.py
index f50e52d2e..eb7bbd9e0 100644
--- a/apps/jumpserver/api.py
+++ b/apps/jumpserver/api.py
@@ -106,7 +106,7 @@ class DateTimeMixin:
@lazyproperty
def user_login_logs_on_the_system_queryset(self):
- qs = UserLoginLog.objects.all()
+ qs = UserLoginLog.objects.filter(status=LoginStatusChoices.success)
qs = self.get_logs_queryset_filter(qs, 'datetime')
queryset = qs.filter(username__in=construct_userlogin_usernames(self.users))
return queryset
diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py
index 6b97c35ea..2642c1da0 100644
--- a/apps/jumpserver/conf.py
+++ b/apps/jumpserver/conf.py
@@ -28,6 +28,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_DIR = os.path.dirname(BASE_DIR)
XPACK_DIR = os.path.join(BASE_DIR, 'xpack')
HAS_XPACK = os.path.isdir(XPACK_DIR)
+DEFAULT_ID = '00000000-0000-0000-0000-000000000002'
logger = logging.getLogger('jumpserver.conf')
@@ -282,7 +283,7 @@ class Config(dict):
'AUTH_LDAP_SYNC_IS_PERIODIC': False,
'AUTH_LDAP_SYNC_INTERVAL': None,
'AUTH_LDAP_SYNC_CRONTAB': None,
- 'AUTH_LDAP_SYNC_ORG_IDS': ['00000000-0000-0000-0000-000000000002'],
+ 'AUTH_LDAP_SYNC_ORG_IDS': [DEFAULT_ID],
'AUTH_LDAP_SYNC_RECEIVERS': [],
'AUTH_LDAP_USER_LOGIN_ONLY_IN_USERS': False,
'AUTH_LDAP_OPTIONS_OPT_REFERRALS': -1,
@@ -323,6 +324,7 @@ class Config(dict):
'AUTH_OPENID_KEYCLOAK': True,
'AUTH_OPENID_SERVER_URL': 'https://keycloak.example.com',
'AUTH_OPENID_REALM_NAME': None,
+ 'OPENID_ORG_IDS': [DEFAULT_ID],
# Raidus 认证
'AUTH_RADIUS': False,
@@ -332,6 +334,7 @@ class Config(dict):
'RADIUS_ATTRIBUTES': {},
'RADIUS_ENCRYPT_PASSWORD': True,
'OTP_IN_RADIUS': False,
+ 'RADIUS_ORG_IDS': [DEFAULT_ID],
# Cas 认证
'AUTH_CAS': False,
@@ -343,6 +346,7 @@ class Config(dict):
'CAS_APPLY_ATTRIBUTES_TO_USER': False,
'CAS_RENAME_ATTRIBUTES': {'cas:user': 'username'},
'CAS_CREATE_USER': True,
+ 'CAS_ORG_IDS': [DEFAULT_ID],
'AUTH_SSO': False,
'AUTH_SSO_AUTHKEY_TTL': 60 * 15,
@@ -370,6 +374,7 @@ class Config(dict):
'SAML2_SP_CERT_CONTENT': '',
'AUTH_SAML2_PROVIDER_AUTHORIZATION_ENDPOINT': '/',
'AUTH_SAML2_AUTHENTICATION_FAILURE_REDIRECT_URI': '/',
+ 'SAML2_ORG_IDS': [DEFAULT_ID],
# OAuth2 认证
'AUTH_OAUTH2': False,
@@ -388,6 +393,8 @@ class Config(dict):
'AUTH_OAUTH2_USER_ATTR_MAP': {
'name': 'name', 'username': 'username', 'email': 'email'
},
+ 'OAUTH2_ORG_IDS': [DEFAULT_ID],
+
'AUTH_PASSKEY': False,
'FIDO_SERVER_ID': '',
'FIDO_SERVER_NAME': 'JumpServer',
@@ -397,28 +404,58 @@ class Config(dict):
'WECOM_CORPID': '',
'WECOM_AGENTID': '',
'WECOM_SECRET': '',
+ 'WECOM_RENAME_ATTRIBUTES': {
+ 'name': 'name',
+ 'username': 'userid',
+ 'email': 'email'
+ },
+ 'WECOM_ORG_IDS': [DEFAULT_ID],
# 钉钉
'AUTH_DINGTALK': False,
'DINGTALK_AGENTID': '',
'DINGTALK_APPKEY': '',
'DINGTALK_APPSECRET': '',
+ 'DINGTALK_RENAME_ATTRIBUTES': {
+ 'name': 'name',
+ 'username': 'user_id',
+ 'email': 'email'
+ },
+ 'DINGTALK_ORG_IDS': [DEFAULT_ID],
# 飞书
'AUTH_FEISHU': False,
'FEISHU_APP_ID': '',
'FEISHU_APP_SECRET': '',
+ 'FEISHU_RENAME_ATTRIBUTES': {
+ 'name': 'name',
+ 'username': 'user_id',
+ 'email': 'enterprise_email'
+ },
+ 'FEISHU_ORG_IDS': [DEFAULT_ID],
# Lark
'AUTH_LARK': False,
'LARK_APP_ID': '',
'LARK_APP_SECRET': '',
+ 'LARK_RENAME_ATTRIBUTES': {
+ 'name': 'en_name',
+ 'username': 'user_id',
+ 'email': 'enterprise_email'
+ },
+ 'LARK_ORG_IDS': [DEFAULT_ID],
# Slack
'AUTH_SLACK': False,
'SLACK_CLIENT_ID': '',
'SLACK_CLIENT_SECRET': '',
'SLACK_BOT_TOKEN': '',
+ 'SLACK_RENAME_ATTRIBUTES': {
+ 'name': 'real_name',
+ 'username': 'name',
+ 'email': 'profile.email'
+ },
+ 'SLACK_ORG_IDS': [DEFAULT_ID],
'LOGIN_REDIRECT_TO_BACKEND': '', # 'OPENID / CAS / SAML2
'LOGIN_REDIRECT_MSG_ENABLED': True,
@@ -472,6 +509,7 @@ class Config(dict):
# Terminal配置
'TERMINAL_PASSWORD_AUTH': True,
'TERMINAL_PUBLIC_KEY_AUTH': True,
+ 'TERMINAL_SSH_KEY_LIMIT_COUNT': 10,
'TERMINAL_HEARTBEAT_INTERVAL': 20,
'TERMINAL_ASSET_LIST_SORT_BY': 'name',
'TERMINAL_ASSET_LIST_PAGE_SIZE': 'auto',
diff --git a/apps/jumpserver/settings/_xpack.py b/apps/jumpserver/settings/_xpack.py
index 6e43c7501..497e2c45d 100644
--- a/apps/jumpserver/settings/_xpack.py
+++ b/apps/jumpserver/settings/_xpack.py
@@ -11,7 +11,10 @@ current_year = datetime.datetime.now().year
corporation = f'FIT2CLOUD 飞致云 © 2014-{current_year}'
XPACK_DIR = os.path.join(const.BASE_DIR, 'xpack')
-XPACK_ENABLED = os.path.isdir(XPACK_DIR)
+XPACK_DISABLED = os.environ.get('XPACK_ENABLED') in ['0', 'false', 'False', 'no', 'No']
+XPACK_ENABLED = False
+if not XPACK_DISABLED:
+ XPACK_ENABLED = os.path.isdir(XPACK_DIR)
XPACK_TEMPLATES_DIR = []
XPACK_CONTEXT_PROCESSOR = []
XPACK_LICENSE_IS_VALID = False
diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py
index 60d2aeab8..c75a2f275 100644
--- a/apps/jumpserver/settings/auth.py
+++ b/apps/jumpserver/settings/auth.py
@@ -130,27 +130,32 @@ AUTH_WECOM = CONFIG.AUTH_WECOM
WECOM_CORPID = CONFIG.WECOM_CORPID
WECOM_AGENTID = CONFIG.WECOM_AGENTID
WECOM_SECRET = CONFIG.WECOM_SECRET
+WECOM_RENAME_ATTRIBUTES = CONFIG.WECOM_RENAME_ATTRIBUTES
# DingDing auth
AUTH_DINGTALK = CONFIG.AUTH_DINGTALK
DINGTALK_AGENTID = CONFIG.DINGTALK_AGENTID
DINGTALK_APPKEY = CONFIG.DINGTALK_APPKEY
DINGTALK_APPSECRET = CONFIG.DINGTALK_APPSECRET
+DINGTALK_RENAME_ATTRIBUTES = CONFIG.DINGTALK_RENAME_ATTRIBUTES
# FeiShu auth
AUTH_FEISHU = CONFIG.AUTH_FEISHU
FEISHU_APP_ID = CONFIG.FEISHU_APP_ID
FEISHU_APP_SECRET = CONFIG.FEISHU_APP_SECRET
+FEISHU_RENAME_ATTRIBUTES = CONFIG.FEISHU_RENAME_ATTRIBUTES
AUTH_LARK = CONFIG.AUTH_LARK
LARK_APP_ID = CONFIG.LARK_APP_ID
LARK_APP_SECRET = CONFIG.LARK_APP_SECRET
+LARK_RENAME_ATTRIBUTES = CONFIG.LARK_RENAME_ATTRIBUTES
# Slack auth
AUTH_SLACK = CONFIG.AUTH_SLACK
SLACK_CLIENT_ID = CONFIG.SLACK_CLIENT_ID
SLACK_CLIENT_SECRET = CONFIG.SLACK_CLIENT_SECRET
SLACK_BOT_TOKEN = CONFIG.SLACK_BOT_TOKEN
+SLACK_RENAME_ATTRIBUTES = CONFIG.SLACK_RENAME_ATTRIBUTES
# Saml2 auth
AUTH_SAML2 = CONFIG.AUTH_SAML2
diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py
index c79f17222..30b73c71d 100644
--- a/apps/jumpserver/settings/base.py
+++ b/apps/jumpserver/settings/base.py
@@ -83,9 +83,9 @@ if DEBUG:
DEBUG_HOST_PORTS = ['{}:{}'.format(host, port) for host in DEBUG_HOSTS for port in DEBUG_PORT]
ALLOWED_DOMAINS.extend(DEBUG_HOST_PORTS)
-print("ALLOWED_HOSTS: ", )
-for host in ALLOWED_DOMAINS:
- print(' - ' + host.lstrip('.'))
+# print("ALLOWED_HOSTS: ", )
+# for host in ALLOWED_DOMAINS:
+# print(' - ' + host.lstrip('.'))
ALLOWED_HOSTS = ['*']
diff --git a/apps/jumpserver/settings/custom.py b/apps/jumpserver/settings/custom.py
index 35e6f246c..821c209e1 100644
--- a/apps/jumpserver/settings/custom.py
+++ b/apps/jumpserver/settings/custom.py
@@ -83,6 +83,7 @@ CACHE_LOGIN_PASSWORD_TTL = CONFIG.CACHE_LOGIN_PASSWORD_TTL
# Terminal other setting
TERMINAL_PASSWORD_AUTH = CONFIG.TERMINAL_PASSWORD_AUTH
TERMINAL_PUBLIC_KEY_AUTH = CONFIG.TERMINAL_PUBLIC_KEY_AUTH
+TERMINAL_SSH_KEY_LIMIT_COUNT = CONFIG.TERMINAL_SSH_KEY_LIMIT_COUNT
TERMINAL_HEARTBEAT_INTERVAL = CONFIG.TERMINAL_HEARTBEAT_INTERVAL
TERMINAL_ASSET_LIST_SORT_BY = CONFIG.TERMINAL_ASSET_LIST_SORT_BY
TERMINAL_ASSET_LIST_PAGE_SIZE = CONFIG.TERMINAL_ASSET_LIST_PAGE_SIZE
@@ -239,4 +240,4 @@ ANSIBLE_RECEPTOR_TCP_LISTEN_ADDRESS = CONFIG.ANSIBLE_RECEPTOR_TCP_LISTEN_ADDRESS
LOKI_LOG_ENABLED = CONFIG.LOKI_LOG_ENABLED
LOKI_BASE_URL = CONFIG.LOKI_BASE_URL
-TOOL_USER_ENABLED = CONFIG.TOOL_USER_ENABLED
\ No newline at end of file
+TOOL_USER_ENABLED = CONFIG.TOOL_USER_ENABLED
diff --git a/apps/jumpserver/views/other.py b/apps/jumpserver/views/other.py
index 32b35ab1e..0d38a4f87 100644
--- a/apps/jumpserver/views/other.py
+++ b/apps/jumpserver/views/other.py
@@ -12,6 +12,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View, TemplateView
from rest_framework.views import APIView
+from common.utils import lazyproperty
from common.views.http import HttpResponseTemporaryRedirect
__all__ = [
@@ -94,6 +95,34 @@ class KokoView(View):
class ResourceDownload(TemplateView):
template_name = 'resource_download.html'
+ @lazyproperty
+ def versions_content(self):
+ return """
+ MRD_VERSION=10.6.7
+ OPENSSH_VERSION=v9.4.0.0
+ TINKER_VERSION=v0.1.6
+ VIDEO_PLAYER_VERSION=0.1.9
+ CLIENT_VERSION=v2.1.3
+ """
+
+ def get_meta_json(self):
+ content = self.versions_content
+ lines = content.splitlines()
+ meta = {}
+ for line in lines:
+ line = line.strip()
+ if not line or line.startswith('#') or '=' not in line:
+ continue
+ key, value = line.split('=')
+ meta[key] = value
+ return meta
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ meta = self.get_meta_json()
+ context.update(meta)
+ return context
+
def csrf_failure(request, reason=""):
from django.shortcuts import reverse
diff --git a/apps/libs/ansible/modules_utils/custom_common.py b/apps/libs/ansible/modules_utils/custom_common.py
index 235a65588..f27446e9e 100644
--- a/apps/libs/ansible/modules_utils/custom_common.py
+++ b/apps/libs/ansible/modules_utils/custom_common.py
@@ -121,7 +121,7 @@ class SSHClient:
def local_gateway_prepare(self):
gateway_args = self.module.params['gateway_args'] or ''
- pattern = r"(?:sshpass -p ([\w@]+))?\s*ssh -o Port=(\d+)\s+-o StrictHostKeyChecking=no\s+([\w@]+)@([" \
+ pattern = r"(?:sshpass -p ([^ ]+))?\s*ssh -o Port=(\d+)\s+-o StrictHostKeyChecking=no\s+([\w@]+)@([" \
r"\d.]+)\s+-W %h:%p -q(?: -i (.+))?'"
match = re.search(pattern, gateway_args)
diff --git a/apps/libs/process/ssh.py b/apps/libs/process/ssh.py
index baf0f776f..edb3558e1 100644
--- a/apps/libs/process/ssh.py
+++ b/apps/libs/process/ssh.py
@@ -19,7 +19,7 @@ def kill_ansible_ssh_process(pid):
for child in process.children(recursive=True):
if not _should_kill(child):
- return
+ continue
try:
child.kill()
except Exception as e:
diff --git a/apps/notifications/backends/dingtalk.py b/apps/notifications/backends/dingtalk.py
index 52d11d041..aaba790d0 100644
--- a/apps/notifications/backends/dingtalk.py
+++ b/apps/notifications/backends/dingtalk.py
@@ -16,6 +16,8 @@ class DingTalk(BackendBase):
def send_msg(self, users, message, subject=None):
accounts, __, __ = self.get_accounts(users)
+ if not accounts:
+ return
return self.dingtalk.send_markdown(accounts, subject, message)
diff --git a/apps/notifications/backends/email.py b/apps/notifications/backends/email.py
index 034557f8a..1f5934450 100644
--- a/apps/notifications/backends/email.py
+++ b/apps/notifications/backends/email.py
@@ -8,6 +8,8 @@ class Email(BackendBase):
def send_msg(self, users, message, subject):
accounts, __, __ = self.get_accounts(users)
+ if not accounts:
+ return
send_mail_async(subject, message, accounts, html_message=message)
diff --git a/apps/notifications/backends/feishu.py b/apps/notifications/backends/feishu.py
index 659c77591..7d577d7cb 100644
--- a/apps/notifications/backends/feishu.py
+++ b/apps/notifications/backends/feishu.py
@@ -16,6 +16,8 @@ class FeiShu(BackendBase):
def send_msg(self, users, message, subject=None):
accounts, __, __ = self.get_accounts(users)
+ if not accounts:
+ return
return self.client.send_text(accounts, message)
diff --git a/apps/notifications/backends/lark.py b/apps/notifications/backends/lark.py
index e6e37218a..9e5b71c57 100644
--- a/apps/notifications/backends/lark.py
+++ b/apps/notifications/backends/lark.py
@@ -17,6 +17,8 @@ class Lark(BackendBase):
def send_msg(self, users, message, subject=None):
accounts, __, __ = self.get_accounts(users)
print('lark', message)
+ if not accounts:
+ return
return self.client.send_text(accounts, message)
diff --git a/apps/notifications/backends/slack.py b/apps/notifications/backends/slack.py
index 95e0bde60..9897f4085 100644
--- a/apps/notifications/backends/slack.py
+++ b/apps/notifications/backends/slack.py
@@ -15,6 +15,8 @@ class Slack(BackendBase):
def send_msg(self, users, message, subject=None):
accounts, __, __ = self.get_accounts(users)
+ if not accounts:
+ return
return self.client.send_text(accounts, message)
diff --git a/apps/notifications/backends/sms.py b/apps/notifications/backends/sms.py
index 18836f421..2adcacfa3 100644
--- a/apps/notifications/backends/sms.py
+++ b/apps/notifications/backends/sms.py
@@ -11,6 +11,8 @@ class SMS(BackendBase):
def send_msg(self, users, sign_name: str, template_code: str, template_param: dict):
accounts, __, __ = self.get_accounts(users)
+ if not accounts:
+ return
return self.client.send_sms(accounts, sign_name, template_code, template_param)
diff --git a/apps/notifications/backends/wecom.py b/apps/notifications/backends/wecom.py
index fa615b7e7..ba4047d2d 100644
--- a/apps/notifications/backends/wecom.py
+++ b/apps/notifications/backends/wecom.py
@@ -17,6 +17,8 @@ class WeCom(BackendBase):
def send_msg(self, users, message, subject=None):
accounts, __, __ = self.get_accounts(users)
+ if not accounts:
+ return
return self.wecom.send_text(accounts, message, markdown=True)
diff --git a/apps/notifications/migrations/0002_auto_20210909_1946.py b/apps/notifications/migrations/0002_auto_20210909_1946.py
index 6145b3471..04fc6f14a 100644
--- a/apps/notifications/migrations/0002_auto_20210909_1946.py
+++ b/apps/notifications/migrations/0002_auto_20210909_1946.py
@@ -6,6 +6,20 @@ from django.db import migrations, models
import django.db.models.deletion
+def init_user_msg_subscription(apps, schema_editor):
+ User = apps.get_model('users', 'User')
+ UserMsgSubscription = apps.get_model('notifications', 'UserMsgSubscription')
+
+ receive_backends = ['site_msg', 'email']
+ user = User.objects.filter(username='admin').first()
+ if not user:
+ return
+ UserMsgSubscription.objects.update_or_create(
+ defaults={'receive_backends': receive_backends}, user=user
+ )
+
+
+
class Migration(migrations.Migration):
initial = True
@@ -57,4 +71,5 @@ class Migration(migrations.Migration):
name='users',
field=models.ManyToManyField(related_name='recv_site_messages', through='notifications.SiteMessage', to=settings.AUTH_USER_MODEL),
),
+ migrations.RunPython(init_user_msg_subscription)
]
diff --git a/apps/notifications/migrations/0003_initial_admin_msg.py b/apps/notifications/migrations/0003_initial_admin_msg.py
deleted file mode 100644
index 5a5a55e16..000000000
--- a/apps/notifications/migrations/0003_initial_admin_msg.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Generated by Django 4.1.13 on 2024-05-21 11:04
-
-from django.db import migrations
-
-
-def init_user_msg_subscription(apps, schema_editor):
- User = apps.get_model('users', 'User')
- UserMsgSubscription = apps.get_model('notifications', 'UserMsgSubscription')
-
- receive_backends = ['site_msg', 'email']
- user = User.objects.get(username='admin')
- UserMsgSubscription.objects.update_or_create(
- defaults={'receive_backends': receive_backends}, user=user
- )
-
-
-class Migration(migrations.Migration):
- dependencies = [
- ('notifications', '0002_auto_20210909_1946'),
- ]
-
- operations = [
- migrations.RunPython(init_user_msg_subscription),
- ]
diff --git a/apps/notifications/notifications.py b/apps/notifications/notifications.py
index ba2b69343..11db34f98 100644
--- a/apps/notifications/notifications.py
+++ b/apps/notifications/notifications.py
@@ -44,8 +44,8 @@ class MessageType(type):
@shared_task(verbose_name=_('Publish the station message'))
-def publish_task(msg):
- msg.publish()
+def publish_task(receive_user_ids, backends_msg_mapper):
+ Message.send_msg(receive_user_ids, backends_msg_mapper)
class Message(metaclass=MessageType):
@@ -65,27 +65,35 @@ class Message(metaclass=MessageType):
return cls.__name__
def publish_async(self):
- return publish_task.delay(self)
+ self.publish(is_async=True)
@classmethod
def gen_test_msg(cls):
raise NotImplementedError
- def publish(self):
+ def publish(self, is_async=False):
raise NotImplementedError
- def send_msg(self, users: Iterable, backends: Iterable = BACKEND):
+ def get_backend_msg_mapper(self, backends):
backends = set(backends)
backends.add(BACKEND.SITE_MSG) # 站内信必须发
-
+ backends_msg_mapper = {}
for backend in backends:
+ backend = BACKEND(backend)
+ if not backend.is_enable:
+ continue
+ get_msg_method = getattr(self, f'get_{backend}_msg', self.get_common_msg)
+ msg = get_msg_method()
+ backends_msg_mapper[backend] = msg
+ return backends_msg_mapper
+
+ @staticmethod
+ def send_msg(receive_user_ids, backends_msg_mapper):
+ for backend, msg in backends_msg_mapper.items():
try:
backend = BACKEND(backend)
- if not backend.is_enable:
- continue
- get_msg_method = getattr(self, f'get_{backend}_msg', self.get_common_msg)
- msg = get_msg_method()
client = backend.client()
+ users = User.objects.filter(id__in=receive_user_ids).all()
client.send_msg(users, **msg)
except NotImplementedError:
continue
@@ -238,7 +246,7 @@ class Message(metaclass=MessageType):
class SystemMessage(Message):
- def publish(self):
+ def publish(self, is_async=False):
subscription = SystemMsgSubscription.objects.get(
message_type=self.get_message_type()
)
@@ -251,7 +259,13 @@ class SystemMessage(Message):
*subscription.users.all(),
*chain(*[g.users.all() for g in subscription.groups.all()])
]
- self.send_msg(users, receive_backends)
+
+ receive_user_ids = [u.id for u in users]
+ backends_msg_mapper = self.get_backend_msg_mapper(receive_backends)
+ if is_async:
+ publish_task.delay(receive_user_ids, backends_msg_mapper)
+ else:
+ self.send_msg(receive_user_ids, backends_msg_mapper)
@classmethod
def post_insert_to_db(cls, subscription: SystemMsgSubscription):
@@ -268,12 +282,17 @@ class UserMessage(Message):
def __init__(self, user):
self.user = user
- def publish(self):
+ def publish(self, is_async=False):
"""
发送消息到每个用户配置的接收方式上
"""
sub = UserMsgSubscription.objects.get(user=self.user)
- self.send_msg([self.user], sub.receive_backends)
+ backends_msg_mapper = self.get_backend_msg_mapper(sub.receive_backends)
+ receive_user_ids = [self.user.id]
+ if is_async:
+ publish_task.delay(receive_user_ids, backends_msg_mapper)
+ else:
+ self.send_msg(receive_user_ids, backends_msg_mapper)
@classmethod
def get_test_user(cls):
diff --git a/apps/ops/ansible/runner.py b/apps/ops/ansible/runner.py
index d5e6c8379..53ab5e89e 100644
--- a/apps/ops/ansible/runner.py
+++ b/apps/ops/ansible/runner.py
@@ -105,7 +105,7 @@ class PlaybookRunner:
shutil.rmtree(private_env)
kwargs = dict(kwargs)
- if self.isolate and not is_macos:
+ if self.isolate and not is_macos():
kwargs['process_isolation'] = True
kwargs['process_isolation_executable'] = 'bwrap'
diff --git a/apps/ops/api/job.py b/apps/ops/api/job.py
index f67c886c4..dcb7ee85f 100644
--- a/apps/ops/api/job.py
+++ b/apps/ops/api/job.py
@@ -29,6 +29,7 @@ __all__ = [
from ops.tasks import run_ops_job_execution
from ops.variables import JMS_JOB_VARIABLE_HELP
+from ops.const import COMMAND_EXECUTION_DISABLED
from orgs.mixins.api import OrgBulkModelViewSet
from orgs.utils import tmp_to_org, get_current_org
from accounts.models import Account
@@ -63,6 +64,7 @@ def merge_nodes_and_assets(nodes, assets, user):
class JobViewSet(OrgBulkModelViewSet):
serializer_class = JobSerializer
+ filterset_fields = ('name', 'type')
search_fields = ('name', 'comment')
model = Job
@@ -72,7 +74,7 @@ class JobViewSet(OrgBulkModelViewSet):
return super().check_permissions(request)
# job: adhoc, playbook
if not settings.SECURITY_COMMAND_EXECUTION:
- return self.permission_denied(request, "Command execution disabled")
+ return self.permission_denied(request, COMMAND_EXECUTION_DISABLED)
return super().check_permissions(request)
def check_upload_permission(self, assets, account_name):
@@ -201,6 +203,11 @@ class JobExecutionViewSet(OrgBulkModelViewSet):
search_fields = ('material',)
filterset_fields = ['status', 'job_id']
+ def check_permissions(self, request):
+ if not settings.SECURITY_COMMAND_EXECUTION:
+ return self.permission_denied(request, COMMAND_EXECUTION_DISABLED)
+ return super().check_permissions(request)
+
@staticmethod
def start_deploy(instance, serializer):
run_ops_job_execution.apply_async((str(instance.id),), task_id=str(instance.id))
@@ -270,7 +277,10 @@ class JobExecutionTaskDetail(APIView):
execution = get_object_or_404(JobExecution, pk=task_id, creator=request.user)
return Response(data={
- 'status': execution.status,
+ 'status': {
+ 'value': execution.status,
+ 'label': execution.get_status_display()
+ },
'is_finished': execution.is_finished,
'is_success': execution.is_success,
'time_cost': execution.time_cost,
diff --git a/apps/ops/const.py b/apps/ops/const.py
index ee4e90a91..5676da4de 100644
--- a/apps/ops/const.py
+++ b/apps/ops/const.py
@@ -78,3 +78,5 @@ class JobStatus(models.TextChoices):
# celery 日志完成之后,写入的魔法字符,作为结束标记
CELERY_LOG_MAGIC_MARK = b'\x00\x00\x00\x00\x00'
+
+COMMAND_EXECUTION_DISABLED = _('Command execution disabled')
diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py
index f8aedd209..9b203fc05 100644
--- a/apps/ops/models/job.py
+++ b/apps/ops/models/job.py
@@ -247,6 +247,8 @@ class JobExecution(JMSOrgBaseModel):
verbose_name=_("Material Type"))
# clean up zombie execution
+ def get_status_display(self):
+ return dict(JobStatus.choices).get(self.status, self.status)
@classmethod
def clean_unexpected_execution(cls):
@@ -420,6 +422,7 @@ class JobExecution(JMSOrgBaseModel):
this.result.update(cb.result)
else:
this.result = cb.result
+ this.result = json.loads(json.dumps(this.result).replace('\\u0000', ''))
this.finish_task()
def finish_task(self):
diff --git a/apps/ops/notifications.py b/apps/ops/notifications.py
index d3018d929..46e9a5aa5 100644
--- a/apps/ops/notifications.py
+++ b/apps/ops/notifications.py
@@ -1,3 +1,4 @@
+from django.conf import settings
from django.template.loader import render_to_string
from django.utils.translation import gettext
from django.utils.translation import gettext_lazy as _
@@ -134,9 +135,10 @@ class ServerPerformanceCheckUtil(object):
def initial_terminals(self):
terminals = []
- for terminal in Terminal.objects.filter(is_deleted=False).exclude(
- type__in=[TerminalType.core, TerminalType.celery]
- ):
+ exclude_types = [TerminalType.core, TerminalType.celery, TerminalType.kael]
+ if not settings.XPACK_LICENSE_IS_VALID:
+ exclude_types.append(TerminalType.magnus)
+ for terminal in Terminal.objects.filter(is_deleted=False).exclude(type__in=exclude_types):
if not terminal.is_active:
continue
terminal.stat = Status.get_terminal_latest_stat(terminal)
diff --git a/apps/ops/serializers/job.py b/apps/ops/serializers/job.py
index b66ab4202..431b062d0 100644
--- a/apps/ops/serializers/job.py
+++ b/apps/ops/serializers/job.py
@@ -84,6 +84,14 @@ class JobExecutionSerializer(BulkOrgResourceModelSerializer):
fields = read_only_fields + [
"job", "parameters", "creator"
]
+ extra_kwargs = {
+ "task_id": {
+ "label": _("Task id"),
+ },
+ "job": {
+ "label": _("Job"),
+ }
+ }
def validate_job(self, job_obj):
if job_obj.creator != self.context['request'].user:
diff --git a/apps/ops/signal_handlers.py b/apps/ops/signal_handlers.py
index 38b10f326..3fe956bf0 100644
--- a/apps/ops/signal_handlers.py
+++ b/apps/ops/signal_handlers.py
@@ -60,7 +60,7 @@ def check_registered_tasks(*args, **kwargs):
'perms.tasks.check_asset_permission_will_expired',
'ops.tasks.create_or_update_registered_periodic_tasks', 'perms.tasks.check_asset_permission_expired',
'settings.tasks.ldap.import_ldap_user_periodic', 'users.tasks.check_password_expired_periodic',
- 'common.utils.verify_code.send_async', 'assets.tasks.nodes_amount.check_node_assets_amount_period_task',
+ 'common.utils.verify_code.send_sms_async', 'assets.tasks.nodes_amount.check_node_assets_amount_period_task',
'users.tasks.check_user_expired', 'orgs.tasks.refresh_org_cache_task',
'terminal.tasks.upload_session_replay_to_external_storage', 'terminal.tasks.clean_orphan_session',
'audits.tasks.clean_audits_log_period', 'authentication.tasks.clean_django_sessions'
@@ -136,6 +136,7 @@ def task_sent_handler(headers=None, body=None, **kwargs):
args = json.loads(json.dumps(list(args), cls=JSONEncoder))
kwargs = json.loads(json.dumps(kwargs, cls=JSONEncoder))
except Exception as e:
+ logger.warn('Parse task args or kwargs error (Need handle): {}'.format(e))
args = []
kwargs = {}
diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py
index 6292df69d..2d6bcb375 100644
--- a/apps/ops/tasks.py
+++ b/apps/ops/tasks.py
@@ -34,6 +34,18 @@ def job_task_activity_callback(self, job_id, *args, **kwargs):
return resource_ids, org_id
+def _run_ops_job_execution(execution):
+ try:
+ with tmp_to_org(execution.org):
+ execution.start()
+ except SoftTimeLimitExceeded:
+ execution.set_error('Run timeout')
+ logger.error("Run adhoc timeout")
+ except Exception as e:
+ execution.set_error(e)
+ logger.error("Start adhoc execution error: {}".format(e))
+
+
@shared_task(
soft_time_limit=60, queue="ansible", verbose_name=_("Run ansible task"),
activity_callback=job_task_activity_callback
@@ -48,15 +60,7 @@ def run_ops_job(job_id):
with tmp_to_org(job.org):
execution = job.create_execution()
execution.creator = job.creator
- run_ops_job_execution(execution.id)
- try:
- execution.start()
- except SoftTimeLimitExceeded:
- execution.set_error('Run timeout')
- logger.error("Run adhoc timeout")
- except Exception as e:
- execution.set_error(e)
- logger.error("Start adhoc execution error: {}".format(e))
+ _run_ops_job_execution(execution)
def job_execution_task_activity_callback(self, execution_id, *args, **kwargs):
@@ -79,16 +83,7 @@ def run_ops_job_execution(execution_id, **kwargs):
if not execution:
logger.error("Did not get the execution: {}".format(execution_id))
return
-
- try:
- with tmp_to_org(execution.org):
- execution.start()
- except SoftTimeLimitExceeded:
- execution.set_error('Run timeout')
- logger.error("Run adhoc timeout")
- except Exception as e:
- execution.set_error(e)
- logger.error("Start adhoc execution error: {}".format(e))
+ _run_ops_job_execution(execution)
@shared_task(verbose_name=_('Clear celery periodic tasks'))
diff --git a/apps/perms/api/user_permission/assets.py b/apps/perms/api/user_permission/assets.py
index 22c187e3e..1e541eb8d 100644
--- a/apps/perms/api/user_permission/assets.py
+++ b/apps/perms/api/user_permission/assets.py
@@ -4,7 +4,7 @@ from django.conf import settings
from rest_framework.generics import ListAPIView, RetrieveAPIView
from assets.api.asset.asset import AssetFilterSet
-from assets.models import Asset, Node
+from assets.models import Asset, Node, MyAsset
from common.api.mixin import ExtraFilterFieldsMixin
from common.utils import get_logger, lazyproperty, is_uuid
from orgs.utils import tmp_to_root_org
@@ -55,6 +55,11 @@ class BaseUserPermedAssetsApi(SelfOrPKUserMixin, ExtraFilterFieldsMixin, ListAPI
assets = self.serializer_class.setup_eager_loading(assets)
return assets
+ def get_serializer(self, *args, **kwargs):
+ if len(args) == 1 and kwargs.get('many', False) and self.request_user_is_self():
+ MyAsset.set_asset_custom_value(args[0], self.request.user)
+ return super().get_serializer(*args, **kwargs)
+
@abc.abstractmethod
def get_assets(self):
return Asset.objects.none()
diff --git a/apps/perms/serializers/permission.py b/apps/perms/serializers/permission.py
index e4bf33364..38a32a29d 100644
--- a/apps/perms/serializers/permission.py
+++ b/apps/perms/serializers/permission.py
@@ -6,7 +6,6 @@ from rest_framework import serializers
from accounts.const import Source
from accounts.models import AccountTemplate, Account
-from accounts.tasks import push_accounts_to_assets_task
from assets.models import Asset, Node
from common.serializers import ResourceLabelsMixin
from common.serializers.fields import BitChoicesField, ObjectRelatedField
@@ -84,44 +83,35 @@ class AssetPermissionSerializer(ResourceLabelsMixin, BulkOrgResourceModelSeriali
return Asset.objects.filter(id__in=asset_ids)
def create_accounts(self, assets):
- need_create_accounts = []
+ account_objs = []
account_attribute = [
'name', 'username', 'secret_type', 'secret',
'privileged', 'is_active', 'org_id'
]
for asset in assets:
- asset_exist_accounts = Account.objects.none()
- asset_exist_account_names = asset.accounts.values_list('name', flat=True)
+ asset_exist_account_names = set(asset.accounts.values_list('name', flat=True))
+
+ asset_exist_accounts = asset.accounts.values('username', 'secret_type')
+ username_secret_type_set = {(acc['username'], acc['secret_type']) for acc in asset_exist_accounts}
for template in self.template_accounts:
- asset_exist_accounts |= asset.accounts.filter(
- username=template.username,
- secret_type=template.secret_type,
- )
- username_secret_type_dict = asset_exist_accounts.values('username', 'secret_type')
- for template in self.template_accounts:
- condition = {
- 'username': template.username,
- 'secret_type': template.secret_type
- }
- if condition in username_secret_type_dict or \
- template.name in asset_exist_account_names:
+ condition = (template.username, template.secret_type)
+ if condition in username_secret_type_set or template.name in asset_exist_account_names:
continue
+
account_data = {key: getattr(template, key) for key in account_attribute}
account_data['su_from'] = template.get_su_from_account(asset)
account_data['source'] = Source.TEMPLATE
account_data['source_id'] = str(template.id)
- need_create_accounts.append(Account(**{'asset_id': asset.id, **account_data}))
- return Account.objects.bulk_create(need_create_accounts)
+ account_objs.append(Account(asset=asset, **account_data))
- def create_and_push_account(self, nodes, assets):
+ if account_objs:
+ Account.objects.bulk_create(account_objs)
+
+ def create_account_through_template(self, nodes, assets):
if not self.template_accounts:
return
assets = self.get_all_assets(nodes, assets)
- accounts = self.create_accounts(assets)
- account_ids = [str(account.id) for account in accounts]
- slice_count = 20
- for i in range(0, len(account_ids), slice_count):
- push_accounts_to_assets_task.delay(account_ids[i:i + slice_count])
+ self.create_accounts(assets)
def validate_accounts(self, usernames):
template_ids = []
@@ -169,7 +159,7 @@ class AssetPermissionSerializer(ResourceLabelsMixin, BulkOrgResourceModelSeriali
instance.nodes.add(*nodes_to_set)
def validate(self, attrs):
- self.create_and_push_account(
+ self.create_account_through_template(
attrs.get("nodes", []),
attrs.get("assets", [])
)
diff --git a/apps/perms/utils/asset_perm.py b/apps/perms/utils/asset_perm.py
index 6de84121f..d368e0286 100644
--- a/apps/perms/utils/asset_perm.py
+++ b/apps/perms/utils/asset_perm.py
@@ -2,7 +2,7 @@ from collections import defaultdict
from accounts.const import AliasAccount
from accounts.models import VirtualAccount
-from assets.models import Asset
+from assets.models import Asset, MyAsset
from common.utils import lazyproperty
from orgs.utils import tmp_to_org, tmp_to_root_org
from .permission import AssetPermissionUtil
@@ -26,7 +26,9 @@ class PermAssetDetailUtil:
@lazyproperty
def asset(self):
if self.user_asset_perms:
- return self._asset
+ asset = self._asset
+ MyAsset.set_asset_custom_value([asset], self.user)
+ return asset
raise Asset.DoesNotExist()
@lazyproperty
diff --git a/apps/rbac/migrations/0001_initial.py b/apps/rbac/migrations/0001_initial.py
index 9e56fda5f..d6724868b 100644
--- a/apps/rbac/migrations/0001_initial.py
+++ b/apps/rbac/migrations/0001_initial.py
@@ -8,7 +8,6 @@ import uuid
class Migration(migrations.Migration):
-
initial = True
dependencies = [
@@ -25,7 +24,11 @@ class Migration(migrations.Migration):
],
options={
'verbose_name': 'Menu permission',
- 'permissions': [('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'), ('view_workbench', 'Can view workbench view'), ('view_webterminal', 'Can view web terminal'), ('view_filemanager', 'Can view file manager'), ('view_systemtools', 'Can view System Tools')],
+ 'permissions': [('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'),
+ ('view_workbench', 'Can view workbench view'),
+ ('view_webterminal', 'Can view web terminal'),
+ ('view_filemanager', 'Can view file manager'),
+ ('view_systemtools', 'Can view System Tools')],
'default_permissions': [],
},
),
@@ -38,7 +41,8 @@ class Migration(migrations.Migration):
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('name', models.CharField(max_length=128, verbose_name='Name')),
- ('scope', models.CharField(choices=[('system', 'System'), ('org', 'Organization')], default='system', max_length=128, verbose_name='Scope')),
+ ('scope', models.CharField(choices=[('system', 'System'), ('org', 'Organization')], default='system',
+ max_length=128, verbose_name='Scope')),
('builtin', models.BooleanField(default=False, verbose_name='Builtin')),
('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')),
],
@@ -54,6 +58,7 @@ class Migration(migrations.Migration):
'proxy': True,
'indexes': [],
'constraints': [],
+ 'verbose_name': 'ContentType'
},
bases=('contenttypes.contenttype',),
managers=[
@@ -84,9 +89,13 @@ class Migration(migrations.Migration):
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('comment', models.TextField(blank=True, default='', verbose_name='Comment')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
- ('scope', models.CharField(choices=[('system', 'System'), ('org', 'Organization')], default='system', max_length=128, verbose_name='Scope')),
- ('org', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='role_bindings', to='orgs.organization', verbose_name='Organization')),
- ('role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='role_bindings', to='rbac.role', verbose_name='Role')),
+ ('scope', models.CharField(choices=[('system', 'System'), ('org', 'Organization')], default='system',
+ max_length=128, verbose_name='Scope')),
+ ('org', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
+ related_name='role_bindings', to='orgs.organization',
+ verbose_name='Organization')),
+ ('role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='role_bindings',
+ to='rbac.role', verbose_name='Role')),
],
options={
'verbose_name': 'Role binding',
diff --git a/apps/rbac/serializers/role.py b/apps/rbac/serializers/role.py
index 84c597396..37e814e4f 100644
--- a/apps/rbac/serializers/role.py
+++ b/apps/rbac/serializers/role.py
@@ -25,8 +25,9 @@ class RoleSerializer(serializers.ModelSerializer):
extra_kwargs = {
'permissions': {'write_only': True},
'users_amount': {'label': _('Users amount')},
- 'display_name': {'label': _('Display name')}
+ 'display_name': {'label': _('Name')}
}
+ fields_unexport = ['permissions']
class RoleUserSerializer(serializers.ModelSerializer):
diff --git a/apps/settings/api/feishu.py b/apps/settings/api/feishu.py
index 1f639f66c..31afc194c 100644
--- a/apps/settings/api/feishu.py
+++ b/apps/settings/api/feishu.py
@@ -5,6 +5,7 @@ from rest_framework.generics import GenericAPIView
from rest_framework.views import Response
from common.sdk.im.feishu import FeiShu
+from common.sdk.im.lark import Lark
from settings.models import Setting
from .. import serializers
@@ -30,8 +31,10 @@ class FeiShuTestingAPI(GenericAPIView):
app_secret = app_secret or ''
+ auth_cls = FeiShu if self.category == 'FEISHU' else Lark
+
try:
- feishu = FeiShu(app_id=app_id, app_secret=app_secret)
+ feishu = auth_cls(app_id=app_id, app_secret=app_secret)
feishu.send_text(['test'], 'test')
return Response(status=status.HTTP_200_OK, data={'msg': _('Test success')})
except APIException as e:
@@ -40,8 +43,3 @@ class FeiShuTestingAPI(GenericAPIView):
except:
error = e.detail
return Response(status=status.HTTP_400_BAD_REQUEST, data={'error': error})
-
-
-class LarkTestingAPI(FeiShuTestingAPI):
- category = 'LARK'
- serializer_class = serializers.LarkSettingSerializer
diff --git a/apps/settings/api/public.py b/apps/settings/api/public.py
index 804ac470b..0c2568a39 100644
--- a/apps/settings/api/public.py
+++ b/apps/settings/api/public.py
@@ -3,7 +3,7 @@ from rest_framework import generics
from rest_framework.permissions import AllowAny
from authentication.permissions import IsValidUserOrConnectionToken
-from common.const.choices import COUNTRY_CALLING_CODES, Language
+from common.const.choices import Language
from common.utils import get_logger, lazyproperty
from common.utils.timezone import local_now
from .. import serializers
@@ -26,7 +26,6 @@ class OpenPublicSettingApi(generics.RetrieveAPIView):
return {
"XPACK_ENABLED": settings.XPACK_ENABLED,
"INTERFACE": self.interface_setting,
- "COUNTRY_CALLING_CODES": COUNTRY_CALLING_CODES,
"LANGUAGES": [
{
'name': title,
diff --git a/apps/settings/serializers/auth/base.py b/apps/settings/serializers/auth/base.py
index a9292acfc..abfbf79b4 100644
--- a/apps/settings/serializers/auth/base.py
+++ b/apps/settings/serializers/auth/base.py
@@ -3,6 +3,7 @@ from rest_framework import serializers
__all__ = [
'AuthSettingSerializer',
+ 'OrgListField'
]
@@ -32,7 +33,7 @@ class AuthSettingSerializer(serializers.Serializer):
)
FORGOT_PASSWORD_URL = serializers.CharField(
required=False, allow_blank=True, max_length=1024,
- label=_("Forgot Password"),
+ label=_("Forgot Password URL"),
help_text=_("The URL for Forgotten Password on the user login page")
)
LOGIN_REDIRECT_MSG_ENABLED = serializers.BooleanField(
@@ -42,3 +43,17 @@ class AuthSettingSerializer(serializers.Serializer):
"authentication when the administrator enables third-party redirect authentication"
)
)
+
+
+class OrgListField(serializers.ListField):
+ def __init__(self, **kwargs):
+ defaults = {
+ 'required': False,
+ 'label': _('Organization'),
+ 'help_text': _(
+ 'When you create a user, you associate the user to the organization of your choice. '
+ 'Users always belong to the Default organization.'
+ )
+ }
+ defaults.update(kwargs)
+ super().__init__(**defaults)
diff --git a/apps/settings/serializers/auth/cas.py b/apps/settings/serializers/auth/cas.py
index 73b3f4736..2a9e44377 100644
--- a/apps/settings/serializers/auth/cas.py
+++ b/apps/settings/serializers/auth/cas.py
@@ -1,6 +1,8 @@
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
+from .base import OrgListField
+
__all__ = [
'CASSettingSerializer',
]
@@ -16,7 +18,7 @@ class CASSettingSerializer(serializers.Serializer):
max_length=1024, label=_('Proxy Server')
)
CAS_LOGOUT_COMPLETELY = serializers.BooleanField(
- required=False, label=_('Logout completely'),
+ required=False, label=_('Logout completely'),
help_text=_('When the user signs out, they also be logged out from the CAS server')
)
CAS_VERSION = serializers.IntegerField(
@@ -36,9 +38,10 @@ class CASSettingSerializer(serializers.Serializer):
)
)
CAS_CREATE_USER = serializers.BooleanField(
- required=False, label=_('Create user'),
+ required=False, label=_('Create user'),
help_text=_(
'After successful user authentication, if the user does not exist, '
'automatically create the user'
)
)
+ CAS_ORG_IDS = OrgListField()
\ No newline at end of file
diff --git a/apps/settings/serializers/auth/dingtalk.py b/apps/settings/serializers/auth/dingtalk.py
index d4d4b34d7..c5a30572c 100644
--- a/apps/settings/serializers/auth/dingtalk.py
+++ b/apps/settings/serializers/auth/dingtalk.py
@@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from common.serializers.fields import EncryptedField
+from .base import OrgListField
__all__ = ['DingTalkSettingSerializer']
@@ -13,3 +14,11 @@ class DingTalkSettingSerializer(serializers.Serializer):
DINGTALK_APPKEY = serializers.CharField(max_length=256, required=True, label='App Key')
DINGTALK_APPSECRET = EncryptedField(max_length=256, required=False, label='App Secret')
AUTH_DINGTALK = serializers.BooleanField(default=False, label=_('Dingtalk'))
+ DINGTALK_RENAME_ATTRIBUTES = serializers.JSONField(
+ required=False, label=_('User attribute'),
+ help_text=_(
+ 'User attribute mapping, where the `key` is the JumpServer user attribute name and the '
+ '`value` is the DingTalk service user attribute name'
+ )
+ )
+ DINGTALK_ORG_IDS = OrgListField()
diff --git a/apps/settings/serializers/auth/feishu.py b/apps/settings/serializers/auth/feishu.py
index 771a7997c..5d06e5b22 100644
--- a/apps/settings/serializers/auth/feishu.py
+++ b/apps/settings/serializers/auth/feishu.py
@@ -5,6 +5,8 @@ from common.serializers.fields import EncryptedField
__all__ = ['FeiShuSettingSerializer']
+from .base import OrgListField
+
class FeiShuSettingSerializer(serializers.Serializer):
PREFIX_TITLE = _('FeiShu')
@@ -12,3 +14,11 @@ class FeiShuSettingSerializer(serializers.Serializer):
AUTH_FEISHU = serializers.BooleanField(default=False, label=_('FeiShu'))
FEISHU_APP_ID = serializers.CharField(max_length=256, required=True, label='App ID')
FEISHU_APP_SECRET = EncryptedField(max_length=256, required=False, label='App Secret')
+ FEISHU_RENAME_ATTRIBUTES = serializers.JSONField(
+ required=False, label=_('User attribute'),
+ help_text=_(
+ 'User attribute mapping, where the `key` is the JumpServer user attribute name and the '
+ '`value` is the FeiShu service user attribute name'
+ )
+ )
+ FEISHU_ORG_IDS = OrgListField()
diff --git a/apps/settings/serializers/auth/lark.py b/apps/settings/serializers/auth/lark.py
index 36b493ab0..7d6e58c20 100644
--- a/apps/settings/serializers/auth/lark.py
+++ b/apps/settings/serializers/auth/lark.py
@@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from common.serializers.fields import EncryptedField
+from .base import OrgListField
__all__ = ['LarkSettingSerializer']
@@ -12,3 +13,11 @@ class LarkSettingSerializer(serializers.Serializer):
AUTH_LARK = serializers.BooleanField(default=False, label=_('Lark'))
LARK_APP_ID = serializers.CharField(max_length=256, required=True, label='App ID')
LARK_APP_SECRET = EncryptedField(max_length=256, required=False, label='App Secret')
+ LARK_RENAME_ATTRIBUTES = serializers.JSONField(
+ required=False, label=_('User attribute'),
+ help_text=_(
+ 'User attribute mapping, where the `key` is the JumpServer user attribute name and the '
+ '`value` is the Lark service user attribute name'
+ )
+ )
+ LARK_ORG_IDS = OrgListField()
diff --git a/apps/settings/serializers/auth/ldap.py b/apps/settings/serializers/auth/ldap.py
index 6952f074b..e0bd51389 100644
--- a/apps/settings/serializers/auth/ldap.py
+++ b/apps/settings/serializers/auth/ldap.py
@@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from common.serializers.fields import EncryptedField
+from .base import OrgListField
__all__ = [
'LDAPTestConfigSerializer', 'LDAPUserSerializer', 'LDAPTestLoginSerializer',
@@ -67,9 +68,6 @@ class LDAPSettingSerializer(serializers.Serializer):
'`value` is the LDAP service user attribute name'
)
)
- AUTH_LDAP_SYNC_ORG_IDS = serializers.ListField(
- required=False, label=_('Organization'), max_length=36
- )
AUTH_LDAP_SYNC_IS_PERIODIC = serializers.BooleanField(
required=False, label=_('Periodic run')
)
@@ -102,6 +100,7 @@ class LDAPSettingSerializer(serializers.Serializer):
)
AUTH_LDAP = serializers.BooleanField(required=False, label=_('LDAP'))
+ AUTH_LDAP_SYNC_ORG_IDS = OrgListField()
def post_save(self):
keys = ['AUTH_LDAP_SYNC_IS_PERIODIC', 'AUTH_LDAP_SYNC_INTERVAL', 'AUTH_LDAP_SYNC_CRONTAB']
diff --git a/apps/settings/serializers/auth/oauth2.py b/apps/settings/serializers/auth/oauth2.py
index 997bfc4a3..6d23e742f 100644
--- a/apps/settings/serializers/auth/oauth2.py
+++ b/apps/settings/serializers/auth/oauth2.py
@@ -3,6 +3,7 @@ from rest_framework import serializers
from common.serializers.fields import EncryptedField
from common.utils import static_or_direct
+from .base import OrgListField
__all__ = [
'OAuth2SettingSerializer',
@@ -65,3 +66,4 @@ class OAuth2SettingSerializer(serializers.Serializer):
AUTH_OAUTH2_ALWAYS_UPDATE_USER = serializers.BooleanField(
default=True, label=_('Always update user')
)
+ OAUTH2_ORG_IDS = OrgListField()
diff --git a/apps/settings/serializers/auth/oidc.py b/apps/settings/serializers/auth/oidc.py
index 2f974286e..31c2790a3 100644
--- a/apps/settings/serializers/auth/oidc.py
+++ b/apps/settings/serializers/auth/oidc.py
@@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from common.serializers.fields import EncryptedField
+from .base import OrgListField
__all__ = [
'OIDCSettingSerializer', 'KeycloakSettingSerializer',
@@ -13,7 +14,7 @@ class CommonSettingSerializer(serializers.Serializer):
# OpenID 公有配置参数 (version <= 1.5.8 或 version >= 1.5.8)
BASE_SITE_URL = serializers.CharField(
required=False, allow_null=True, allow_blank=True,
- max_length=1024, label=_('Base site URL'),
+ max_length=1024, label=_('Base site URL'),
help_text=_("The current site's URL is used to construct the callback address")
)
AUTH_OPENID_CLIENT_ID = serializers.CharField(
@@ -107,7 +108,8 @@ class OIDCSettingSerializer(KeycloakSettingSerializer):
)
AUTH_OPENID_USE_NONCE = serializers.BooleanField(
required=False, label=_('Use nonce')
- )
+ )
AUTH_OPENID_ALWAYS_UPDATE_USER = serializers.BooleanField(
required=False, label=_('Always update user')
)
+ OPENID_ORG_IDS = OrgListField()
diff --git a/apps/settings/serializers/auth/radius.py b/apps/settings/serializers/auth/radius.py
index 56746f65a..ec6f8fd32 100644
--- a/apps/settings/serializers/auth/radius.py
+++ b/apps/settings/serializers/auth/radius.py
@@ -5,6 +5,7 @@ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from common.serializers.fields import EncryptedField
+from .base import OrgListField
__all__ = ['RadiusSettingSerializer']
@@ -19,6 +20,7 @@ class RadiusSettingSerializer(serializers.Serializer):
required=False, max_length=1024, allow_null=True, label=_('Secret'),
)
OTP_IN_RADIUS = serializers.BooleanField(
- required=False, label=_('OTP in RADIUS'),
+ required=False, label=_('OTP in RADIUS'),
help_text=_('* Using OTP in RADIUS means users can employ RADIUS as a method for MFA')
)
+ RADIUS_ORG_IDS = OrgListField()
diff --git a/apps/settings/serializers/auth/saml2.py b/apps/settings/serializers/auth/saml2.py
index b54118b16..46f185916 100644
--- a/apps/settings/serializers/auth/saml2.py
+++ b/apps/settings/serializers/auth/saml2.py
@@ -1,6 +1,8 @@
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
+from .base import OrgListField
+
__all__ = [
'SAML2SettingSerializer',
]
@@ -41,3 +43,4 @@ class SAML2SettingSerializer(serializers.Serializer):
help_text=_('When the user signs out, they also be logged out from the SAML2 server')
)
AUTH_SAML2_ALWAYS_UPDATE_USER = serializers.BooleanField(required=False, label=_('Always update user'))
+ SAML2_ORG_IDS = OrgListField()
diff --git a/apps/settings/serializers/auth/slack.py b/apps/settings/serializers/auth/slack.py
index 244fd2cbd..f3bf5ad5e 100644
--- a/apps/settings/serializers/auth/slack.py
+++ b/apps/settings/serializers/auth/slack.py
@@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from common.serializers.fields import EncryptedField
+from .base import OrgListField
__all__ = ['SlackSettingSerializer']
@@ -13,3 +14,11 @@ class SlackSettingSerializer(serializers.Serializer):
SLACK_CLIENT_ID = serializers.CharField(max_length=256, required=True, label='Client ID')
SLACK_CLIENT_SECRET = EncryptedField(max_length=256, required=False, label='Client Secret')
SLACK_BOT_TOKEN = EncryptedField(max_length=256, required=False, label='Client bot Token')
+ SLACK_RENAME_ATTRIBUTES = serializers.JSONField(
+ required=False, label=_('User attribute'),
+ help_text=_(
+ 'User attribute mapping, where the `key` is the JumpServer user attribute name and the '
+ '`value` is the Slack service user attribute name'
+ )
+ )
+ SLACK_ORG_IDS = OrgListField()
diff --git a/apps/settings/serializers/auth/wecom.py b/apps/settings/serializers/auth/wecom.py
index 72c315c24..b398721f6 100644
--- a/apps/settings/serializers/auth/wecom.py
+++ b/apps/settings/serializers/auth/wecom.py
@@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from common.serializers.fields import EncryptedField
+from .base import OrgListField
__all__ = ['WeComSettingSerializer']
@@ -13,3 +14,11 @@ class WeComSettingSerializer(serializers.Serializer):
WECOM_AGENTID = serializers.CharField(max_length=256, required=True, label='App Agent ID')
WECOM_SECRET = EncryptedField(max_length=256, required=False, label='App Secret')
AUTH_WECOM = serializers.BooleanField(default=False, label=_('WeCom'))
+ WECOM_RENAME_ATTRIBUTES = serializers.JSONField(
+ required=False, label=_('User attribute'),
+ help_text=_(
+ 'User attribute mapping, where the `key` is the JumpServer user attribute name and the '
+ '`value` is the WeCom service user attribute name'
+ )
+ )
+ WECOM_ORG_IDS = OrgListField()
diff --git a/apps/settings/serializers/feature.py b/apps/settings/serializers/feature.py
index d88a42af6..4b219373d 100644
--- a/apps/settings/serializers/feature.py
+++ b/apps/settings/serializers/feature.py
@@ -71,13 +71,15 @@ class VaultSettingSerializer(serializers.Serializer):
class ChatAISettingSerializer(serializers.Serializer):
PREFIX_TITLE = _('Chat AI')
- GPT_MODEL_CHOICES = []
+ API_MODEL = Protocol.gpt_protocols()[Protocol.chatgpt]['setting']['api_mode']
+ GPT_MODEL_CHOICES = API_MODEL['choices']
+ GPT_MODEL_DEFAULT = API_MODEL['default']
CHAT_AI_ENABLED = serializers.BooleanField(
required=False, label=_('Chat AI')
)
GPT_BASE_URL = serializers.CharField(
- allow_blank=True, required=False, label=_('Base URL'),
+ allow_blank=True, required=False, label=_('GPT Base URL'),
help_text=_('The base URL of the GPT service. For example: https://api.openai.com/v1')
)
GPT_API_KEY = EncryptedField(
@@ -88,38 +90,21 @@ class ChatAISettingSerializer(serializers.Serializer):
help_text=_('The proxy server address of the GPT service. For example: http://ip:port')
)
GPT_MODEL = serializers.ChoiceField(
- default='', choices=GPT_MODEL_CHOICES, label=_("GPT Model"), required=False,
+ default=GPT_MODEL_DEFAULT, choices=GPT_MODEL_CHOICES, label=_("GPT Model"), required=False,
)
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.set_GPT_MODEL_choices()
-
- def set_GPT_MODEL_choices(self):
- field_gpt_model = self.fields.get("GPT_MODEL")
- if not field_gpt_model:
- return
- gpt_api_model = Protocol.gpt_protocols()[Protocol.chatgpt]['setting']['api_mode']
- choices = gpt_api_model['choices']
- field_gpt_model.choices = choices
- field_gpt_model.default = gpt_api_model['default']
- cls = self.__class__
- if cls.GPT_MODEL_CHOICES:
- return
- cls.GPT_MODEL_CHOICES.extend(choices)
-
class TicketSettingSerializer(serializers.Serializer):
PREFIX_TITLE = _('Ticket')
TICKETS_ENABLED = serializers.BooleanField(required=False, default=True, label=_("Ticket"))
TICKETS_DIRECT_APPROVE = serializers.BooleanField(
- required=False, default=False, label=_("Approval without login"),
+ required=False, default=False, label=_("Approval without login"),
help_text=_('Allow direct approval ticket without login')
)
TICKET_AUTHORIZE_DEFAULT_TIME = serializers.IntegerField(
min_value=1, max_value=999999, required=False,
- label=_("Period"),
+ label=_("Period"),
help_text=_("The default authorization time period when applying for assets via a ticket")
)
TICKET_AUTHORIZE_DEFAULT_TIME_UNIT = serializers.ChoiceField(
@@ -146,7 +131,7 @@ class VirtualAppSerializer(serializers.Serializer):
PREFIX_TITLE = _('Virtual app')
VIRTUAL_APP_ENABLED = serializers.BooleanField(
- required=False, label=_('Virtual App'),
+ required=False, label=_('Virtual App'),
help_text=_(
'Virtual applications, you can use the Linux operating system as an application server '
'in remote applications.'
diff --git a/apps/settings/serializers/msg.py b/apps/settings/serializers/msg.py
index 813d2400c..c121e7686 100644
--- a/apps/settings/serializers/msg.py
+++ b/apps/settings/serializers/msg.py
@@ -21,7 +21,7 @@ class EmailSettingSerializer(serializers.Serializer):
PREFIX_TITLE = _('Email')
class EmailProtocol(models.TextChoices):
- smtp = 'smtp', _('SMTP')
+ smtp = 'smtp', _('SMTP')
exchange = 'exchange', _('EXCHANGE')
EMAIL_PROTOCOL = serializers.ChoiceField(
@@ -30,7 +30,8 @@ class EmailSettingSerializer(serializers.Serializer):
EMAIL_HOST = serializers.CharField(max_length=1024, required=True, label=_("Host"))
EMAIL_PORT = serializers.CharField(max_length=5, required=True, label=_("Port"))
EMAIL_HOST_USER = serializers.CharField(
- max_length=128, required=True, label=_("Account"), help_text=_("The user to be used for email server authentication")
+ max_length=128, required=False, allow_blank=True, label=_("Account"),
+ help_text=_("The user to be used for email server authentication")
)
EMAIL_HOST_PASSWORD = EncryptedField(
max_length=1024, required=False, label=_("Password"),
@@ -46,11 +47,13 @@ class EmailSettingSerializer(serializers.Serializer):
)
EMAIL_USE_SSL = serializers.BooleanField(
required=False, label=_('Use SSL'),
- help_text=_('Whether to use an implicit TLS (secure) connection when talking to the SMTP server. In most email documentation this type of TLS connection is referred to as SSL. It is generally used on port 465')
+ help_text=_(
+ 'Whether to use an implicit TLS (secure) connection when talking to the SMTP server. In most email documentation this type of TLS connection is referred to as SSL. It is generally used on port 465')
)
EMAIL_USE_TLS = serializers.BooleanField(
required=False, label=_("Use TLS"),
- help_text=_('Whether to use a TLS (secure) connection when talking to the SMTP server. This is used for explicit TLS connections, generally on port 587')
+ help_text=_(
+ 'Whether to use a TLS (secure) connection when talking to the SMTP server. This is used for explicit TLS connections, generally on port 587')
)
diff --git a/apps/settings/serializers/public.py b/apps/settings/serializers/public.py
index 8c0031b29..32ab1e61c 100644
--- a/apps/settings/serializers/public.py
+++ b/apps/settings/serializers/public.py
@@ -11,7 +11,6 @@ __all__ = [
class PublicSettingSerializer(serializers.Serializer):
XPACK_ENABLED = serializers.BooleanField()
INTERFACE = serializers.DictField()
- COUNTRY_CALLING_CODES = serializers.ListField()
LANGUAGES = serializers.ListField()
diff --git a/apps/settings/utils/__init__.py b/apps/settings/utils/__init__.py
index 91d05860e..f2215e770 100644
--- a/apps/settings/utils/__init__.py
+++ b/apps/settings/utils/__init__.py
@@ -3,3 +3,4 @@
from .ldap import *
from .common import *
+from .db import *
diff --git a/apps/settings/utils/db.py b/apps/settings/utils/db.py
new file mode 100644
index 000000000..8c2fca321
--- /dev/null
+++ b/apps/settings/utils/db.py
@@ -0,0 +1,55 @@
+from django.apps import apps
+from orgs.utils import tmp_to_root_org
+
+__all__ = ['DBTableDataAnalyzer']
+
+
+class DBTableDataAnalyzer(object):
+
+ def get_tables_info(self):
+ table_models = self.get_all_table_models()
+ with tmp_to_root_org():
+ table_info = self._fetch_tables_info(table_models)
+ return table_info
+
+ def get_all_table_models(self):
+ # construct tables models
+ table_models = set()
+ for model in apps.get_models():
+ table_models.add(model)
+ for m2m_field in model._meta.many_to_many:
+ table_models.add(m2m_field.remote_field.through)
+ return table_models
+
+ def _fetch_tables_info(self, table_models):
+ """
+ return:
+ info = {
+ 'table_name': {
+ 'count': 100
+ }
+ ...
+ }
+ """
+ info = {}
+ for table_model in table_models:
+ if table_model._meta.proxy == True:
+ # skip proxy model
+ continue
+ count = self._fetch_row_count(table_model)
+ data = {
+ "count": count
+ }
+ table_name = table_model._meta.db_table
+ info.update({f"{table_name}": data})
+ return info
+
+ def _fetch_row_count(self, table_model):
+ # fetch table row count
+ if hasattr(table_model, 'objects_raw'):
+ # use objects_raw to count
+ count = table_model.objects_raw.count()
+ else:
+ count = table_model.objects.count()
+ return count
+
\ No newline at end of file
diff --git a/apps/settings/ws.py b/apps/settings/ws.py
index dd0d16af4..22fcb137a 100644
--- a/apps/settings/ws.py
+++ b/apps/settings/ws.py
@@ -3,10 +3,12 @@
import json
import asyncio
+from asgiref.sync import sync_to_async
from channels.generic.websocket import AsyncJsonWebsocketConsumer
from django.core.cache import cache
from django.conf import settings
-from django.utils.translation import gettext_lazy as _
+from django.utils.translation import gettext_lazy as _, activate
+from django.utils import translation
from common.db.utils import close_old_connections
from common.utils import get_logger
@@ -185,6 +187,11 @@ class LdapWebsocket(AsyncJsonWebsocketConsumer):
return ok, msg
def run_import_user(self, data):
+ lang = getattr(self.scope['user'], 'lang', settings.LANGUAGE_CODE)
+ with translation.override(lang):
+ return self._run_import_user(data)
+
+ def _run_import_user(self, data):
ok = False
org_ids = data.get('org_ids')
username_list = data.get('username_list', [])
@@ -192,17 +199,15 @@ class LdapWebsocket(AsyncJsonWebsocketConsumer):
try:
users = self.get_ldap_users(username_list, cache_police)
if users is None:
- msg = _('Get ldap users is None')
-
- orgs = self.get_orgs(org_ids)
- new_users, error_msg = LDAPImportUtil().perform_import(users, orgs)
- if error_msg:
- msg = error_msg
-
- count = users if users is None else len(users)
- orgs_name = ', '.join([str(org) for org in orgs])
- ok = True
- msg = _('Imported {} users successfully (Organization: {})').format(count, orgs_name)
+ msg = _('No LDAP user was found')
+ else:
+ orgs = self.get_orgs(org_ids)
+ new_users, error_msg = LDAPImportUtil().perform_import(users, orgs)
+ ok = True
+ success_count = len(users) - len(error_msg)
+ msg = _('Total {}, success {}, failure {}').format(
+ len(users), success_count, len(error_msg)
+ )
except Exception as e:
msg = str(e)
return ok, msg
diff --git a/apps/static/img/logo_text_green.png b/apps/static/img/logo_text_green.png
deleted file mode 100644
index 3d7ae3fb4..000000000
Binary files a/apps/static/img/logo_text_green.png and /dev/null differ
diff --git a/apps/templates/_copyright.html b/apps/templates/_copyright.html
index d231d1e95..5e2c475c2 100644
--- a/apps/templates/_copyright.html
+++ b/apps/templates/_copyright.html
@@ -1,3 +1,3 @@
-{% if not USE_XPACK %}
+{% if not XPACK_ENABLED %}
Copyright {{ COPYRIGHT }}
{% endif %}
diff --git a/apps/templates/_foot_js.html b/apps/templates/_foot_js.html
index b01be189d..180903863 100644
--- a/apps/templates/_foot_js.html
+++ b/apps/templates/_foot_js.html
@@ -19,12 +19,19 @@
.markdown-footer {
position: absolute;
+ bottom: 0;
left: 50%;
+ width: 285px;
transform: translate(-50%, -50%);
@media (min-width: 768px) {
top: 97%;
}
}
+
+ .markdown-footer p {
+ padding: 0;
+ margin: 0;
+ }
{% endif %}
diff --git a/apps/templates/resource_download.html b/apps/templates/resource_download.html
index 50d3f7594..808b32d59 100644
--- a/apps/templates/resource_download.html
+++ b/apps/templates/resource_download.html
@@ -1,31 +1,33 @@
{% extends '_without_nav_base.html' %}
{% load i18n %}
{% block body %}
-
-
+
-
JumpServer {% trans 'Client' %} v2.1.3
+
JumpServer {% trans 'Client' %} {{ CLIENT_VERSION }}
{% trans 'JumpServer Client, currently used to launch the client, now only support launch RDP SSH client, The Telnet client will next' %}
@@ -35,33 +37,32 @@ p {
{% trans 'macOS needs to download the client to connect RDP asset, which comes with Windows' %}
-
-
-
{% trans 'Windows Remote application publisher tools' %}
-
{% trans 'OpenSSH is a program used to connect remote applications in the Windows Remote Application Publisher' %}
-
-
-
+
+
{% trans 'Windows Remote application publisher tools' %}
+
{% trans 'OpenSSH is a program used to connect remote applications in the Windows Remote Application Publisher' %}
+
+
JumpServer {% trans 'Offline video player' %} v0.1.9
-