From b2dab8b059297c53efdc553b34d42691cd454c75 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 10 Jun 2026 10:44:21 +0800 Subject: [PATCH 01/10] fix: update user empty ukey_sn field value --- .../backends/ukey/vendors/ji_da/sdk_config.yaml | 2 +- .../backends/ukey/vendors/long_mai/sdk_config.yaml | 2 +- apps/users/serializers/user.py | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/authentication/backends/ukey/vendors/ji_da/sdk_config.yaml b/apps/authentication/backends/ukey/vendors/ji_da/sdk_config.yaml index 77d5e5da8..2815f7ec1 100644 --- a/apps/authentication/backends/ukey/vendors/ji_da/sdk_config.yaml +++ b/apps/authentication/backends/ukey/vendors/ji_da/sdk_config.yaml @@ -297,7 +297,7 @@ operations: url_format: user_id: "{{ user.id }}" body: - ukey_sn: null + ukey_sn: "" register: user - key: issueCert diff --git a/apps/authentication/backends/ukey/vendors/long_mai/sdk_config.yaml b/apps/authentication/backends/ukey/vendors/long_mai/sdk_config.yaml index 39028feff..3cb850247 100644 --- a/apps/authentication/backends/ukey/vendors/long_mai/sdk_config.yaml +++ b/apps/authentication/backends/ukey/vendors/long_mai/sdk_config.yaml @@ -359,7 +359,7 @@ operations: url_format: user_id: "{{ user.id }}" body: - ukey_sn: null + ukey_sn: "" register: user - key: issueCert diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index 7bbf9dc6d..99803d4c2 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -325,6 +325,14 @@ class UserSerializer( attrs.pop(field, None) return attrs + @staticmethod + def clean_ukey_fields(attrs): + for field in ("ukey_sn",): + value = attrs.get(field) + if value is None: + attrs.pop(field, None) + return attrs + def check_disallow_self_update_fields(self, attrs): request = self.context.get("request") if not request or not request.user.is_authenticated: @@ -348,6 +356,7 @@ class UserSerializer( attrs = self.check_disallow_self_update_fields(attrs) attrs = self.change_password_to_raw(attrs) attrs = self.clean_auth_fields(attrs) + attrs = self.clean_ukey_fields(attrs) password_strategy = attrs.pop("password_strategy", None) request = get_current_request() if request: From 98826222f6619a7054135a45364f13bdfc5dde66 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 10 Jun 2026 10:57:19 +0800 Subject: [PATCH 02/10] fix: ukey auth user invalid alert error --- apps/authentication/backends/ukey/backends.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/authentication/backends/ukey/backends.py b/apps/authentication/backends/ukey/backends.py index c937951e5..cde2438b4 100644 --- a/apps/authentication/backends/ukey/backends.py +++ b/apps/authentication/backends/ukey/backends.py @@ -7,6 +7,7 @@ import tempfile from django.conf import settings from django.core.exceptions import PermissionDenied +from django.utils.translation import gettext_lazy as _ from users.models import User from common.utils import get_logger @@ -24,6 +25,7 @@ from .exceptions import ( UKeyCertUnsupportedAlgorithmError, ) from .utils import is_sm2_pem +from authentication.errors.const import reason_user_inactive, reason_choices __all__ = ['UKeyBackend'] @@ -45,9 +47,14 @@ class UKeyBackend(JMSBaseAuthBackend): user = self._check_user_and_ukey_sn(username, ukey_sn) cert_pem = self._load_cert_pem(cert) if self._is_sm2_cert(cert_pem): - return self._authenticate_sm2(cert_pem, username, signature, challenge, user) + user = self._authenticate_sm2(cert_pem, username, signature, challenge, user) else: - return self._authenticate_other(cert_pem, username, signature, challenge, user) + user = self._authenticate_other(cert_pem, username, signature, challenge, user) + if self.user_can_authenticate(user): + return user + else: + error = reason_choices[reason_user_inactive] + raise PermissionDenied(error) except Exception as e: if request: request.error_message = str(e) From ba6ba2356e66eb90be354289f85535271301d72d Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 10 Jun 2026 11:03:54 +0800 Subject: [PATCH 03/10] perf: use prebuild gmssl image --- Dockerfile-ee | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/Dockerfile-ee b/Dockerfile-ee index 6ac258b5d..5f4baf4c4 100644 --- a/Dockerfile-ee +++ b/Dockerfile-ee @@ -1,27 +1,5 @@ ARG VERSION=dev -FROM python:3.14-slim-trixie AS gmssl-builder -WORKDIR /app -ARG GMSSL_VERSION=3.1.1 -RUN set -ex \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - git \ - cmake \ - make \ - gcc \ - g++ \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -RUN set -ex \ - && git clone --branch v${GMSSL_VERSION} https://github.com/guanzhi/GmSSL.git \ - && cd GmSSL \ - && mkdir build \ - && cd build \ - && cmake .. \ - && make \ - && make -j"$(nproc)" \ - && make install +FROM jumpserver/gmssl:3.1.1-trixie AS gmssl-builder FROM registry.fit2cloud.com/jumpserver/xpack:${VERSION} AS build-xpack FROM jumpserver/core:${VERSION}-ce @@ -44,8 +22,6 @@ WORKDIR /opt/jumpserver ARG PIP_MIRROR=https://pypi.org/simple -ARG GMSSL_VERSION=3.1.1 - RUN set -ex \ && uv pip install -i${PIP_MIRROR} --group xpack \ && rm -rf /root/.cache/ From 3e0ece8284a315e8cc32bda6b4c96f7de0e38c8f Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 12 Jun 2026 11:19:44 +0800 Subject: [PATCH 04/10] fix: do not view change-secret by settings --- apps/accounts/serializers/automations/change_secret.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/accounts/serializers/automations/change_secret.py b/apps/accounts/serializers/automations/change_secret.py index e5510b7cc..8352affb7 100644 --- a/apps/accounts/serializers/automations/change_secret.py +++ b/apps/accounts/serializers/automations/change_secret.py @@ -133,13 +133,15 @@ class ChangeSecretRecordSerializer(serializers.ModelSerializer): def get_is_success(obj) -> bool: return obj.status == ChangeSecretRecordStatusChoice.success +from common.serializers import SecretReadableCheckMixin -class ChangeSecretRecordViewSecretSerializer(serializers.ModelSerializer): +class ChangeSecretRecordViewSecretSerializer(SecretReadableCheckMixin, serializers.ModelSerializer): class Meta: model = ChangeSecretRecord fields = [ 'id', 'old_secret', 'new_secret', ] + secret_fields = ['old_secret', 'new_secret'] read_only_fields = fields From 863f52bf5f90ce98061a86445c200a7c6b31c393 Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 12 Jun 2026 16:30:16 +0800 Subject: [PATCH 05/10] fix: do not view change-secret by settings --- apps/accounts/serializers/automations/change_secret.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/accounts/serializers/automations/change_secret.py b/apps/accounts/serializers/automations/change_secret.py index 8352affb7..288be098f 100644 --- a/apps/accounts/serializers/automations/change_secret.py +++ b/apps/accounts/serializers/automations/change_secret.py @@ -13,6 +13,7 @@ from accounts.models import ( ) from accounts.serializers import AuthValidateMixin, PasswordRulesSerializer from assets.models import Asset +from common.serializers import SecretReadableCheckMixin from common.serializers.fields import LabeledChoiceField, ObjectRelatedField from common.utils import get_logger from .base import BaseAutomationSerializer @@ -133,7 +134,6 @@ class ChangeSecretRecordSerializer(serializers.ModelSerializer): def get_is_success(obj) -> bool: return obj.status == ChangeSecretRecordStatusChoice.success -from common.serializers import SecretReadableCheckMixin class ChangeSecretRecordViewSecretSerializer(SecretReadableCheckMixin, serializers.ModelSerializer): class Meta: From f87248154bbd7a1dd43c01fd4867851846506513 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 12 Jun 2026 17:01:54 +0800 Subject: [PATCH 06/10] perf: support applet host filter --- apps/terminal/api/applet/applet.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/terminal/api/applet/applet.py b/apps/terminal/api/applet/applet.py index b86e119da..d7705ba68 100644 --- a/apps/terminal/api/applet/applet.py +++ b/apps/terminal/api/applet/applet.py @@ -6,9 +6,11 @@ from typing import Callable from django.conf import settings from django.core.files.storage import default_storage +from django.db.models import Q from django.http import HttpResponse from django.shortcuts import get_object_or_404 from django.utils.translation import gettext as _ +from django_filters import rest_framework as filters from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.request import Request @@ -16,6 +18,7 @@ from rest_framework.response import Response from rest_framework.serializers import ValidationError from common.api import JMSBulkModelViewSet +from common.drf.filters import BaseFilterSet from common.serializers import FileSerializer from common.utils import is_uuid from common.utils.http import is_true @@ -140,8 +143,22 @@ class AppletViewSet(DownloadUploadMixin, JMSBulkModelViewSet): instance.delete() +class AppletPublicationFilterSet(BaseFilterSet): + host = filters.CharFilter(method='filter_host') + + class Meta: + model = AppletPublication + fields = ['host', 'applet', 'status'] + + @staticmethod + def filter_host(queryset, name, value): + if is_uuid(value): + return queryset.filter(host_id=value) + return queryset.filter(Q(host__name=value) | Q(host__address=value)) + + class AppletPublicationViewSet(viewsets.ModelViewSet): queryset = AppletPublication.objects.all() serializer_class = serializers.AppletPublicationSerializer - filterset_fields = ['host', 'applet', 'status'] - search_fields = ['applet__name', 'applet__display_name', 'host__name'] + filterset_class = AppletPublicationFilterSet + search_fields = ['applet__name', 'applet__display_name', 'host__name', 'host__address'] From 5322bcbde8fa9be0ac9719b39c8e52d4cde2a5cd Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 15 Jun 2026 11:35:49 +0800 Subject: [PATCH 07/10] fix: ukey login user deactive error no tips --- apps/authentication/backends/ukey/views.py | 5 +++-- .../authentication/templates/authentication/login_ukey.html | 6 ++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/authentication/backends/ukey/views.py b/apps/authentication/backends/ukey/views.py index 23048f70c..e85ba9271 100644 --- a/apps/authentication/backends/ukey/views.py +++ b/apps/authentication/backends/ukey/views.py @@ -5,7 +5,6 @@ from urllib.parse import urlencode from django.conf import settings from django.contrib.auth import authenticate -from django.contrib import messages from django.core.cache import cache from django.utils.decorators import method_decorator from django.utils.translation import gettext as _ @@ -27,6 +26,7 @@ from .sdk import ukey_sdk_config __all__ = ['UKeyLoginView'] _CHALLENGE_CACHE_KEY_PREFIX = 'ukey_login_challenge' +_UKEY_ERROR_SESSION_KEY = 'ukey_login_error' @method_decorator(sensitive_post_parameters(), name='dispatch') @method_decorator(csrf_protect, name='dispatch') @@ -79,6 +79,7 @@ class UKeyLoginView(AuthMixin, FormView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['challenge'] = self._generate_and_store_challenge() + context['error_msg'] = self.request.session.pop(_UKEY_ERROR_SESSION_KEY, '') return context def form_valid(self, form): @@ -155,7 +156,7 @@ class UKeyLoginView(AuthMixin, FormView): return field_name def get_failed_response(self, form, username, error_msg): - messages.error(self.request, error_msg) + self.request.session[_UKEY_ERROR_SESSION_KEY] = str(error_msg or _('Unknown')) self.send_auth_signal(success=False, reason=error_msg, username=username) return redirect(self._build_login_redirect_url()) diff --git a/apps/authentication/templates/authentication/login_ukey.html b/apps/authentication/templates/authentication/login_ukey.html index bb21be15e..c26758a74 100644 --- a/apps/authentication/templates/authentication/login_ukey.html +++ b/apps/authentication/templates/authentication/login_ukey.html @@ -202,11 +202,9 @@
{% csrf_token %} - {% if messages %} + {% if error_msg %}
- {% for message in messages %} -

{% trans "Error" %}: {{ message }}

- {% endfor %} +

{% trans "Error" %}: {{ error_msg }}

{% endif %} From c0938a25f56f06444f2a8cecfa8b183ed92d524d Mon Sep 17 00:00:00 2001 From: zhaojisen <1301338853@qq.com> Date: Mon, 15 Jun 2026 11:38:26 +0800 Subject: [PATCH 08/10] fix: add translate --- apps/i18n/lina/en.json | 1 + apps/i18n/lina/es.json | 1 + apps/i18n/lina/ja.json | 1 + apps/i18n/lina/ko.json | 1 + apps/i18n/lina/pt_br.json | 1 + apps/i18n/lina/ru.json | 1 + apps/i18n/lina/vi.json | 1 + apps/i18n/lina/zh.json | 1 + apps/i18n/lina/zh_hant.json | 1 + 9 files changed, 9 insertions(+) diff --git a/apps/i18n/lina/en.json b/apps/i18n/lina/en.json index fef6ea2f7..2f900a488 100644 --- a/apps/i18n/lina/en.json +++ b/apps/i18n/lina/en.json @@ -198,6 +198,7 @@ "Audits": "Audits", "AuditsDashboard": "Audits dashboard", "Auth": "Authentication", + "Author": "Author", "AuthConfig": "Authentication", "AuthIntegration": "Auth Integration", "AuthLimit": "Login restriction", diff --git a/apps/i18n/lina/es.json b/apps/i18n/lina/es.json index f471fb273..5c8a748c9 100644 --- a/apps/i18n/lina/es.json +++ b/apps/i18n/lina/es.json @@ -200,6 +200,7 @@ "Audits": "panel de auditoría", "AuditsDashboard": "Panel de auditoría", "Auth": "Configuración de autenticación", + "Author": "Autor", "AuthConfig": "Configuración de autenticación", "AuthIntegration": "Integración de certificación", "AuthLimit": "Restricción de inicio de sesión", diff --git a/apps/i18n/lina/ja.json b/apps/i18n/lina/ja.json index 7d62f466e..b3666d17b 100644 --- a/apps/i18n/lina/ja.json +++ b/apps/i18n/lina/ja.json @@ -202,6 +202,7 @@ "Audits": "監査台", "AuditsDashboard": "監査ダッシュボード", "Auth": "認証設定", + "Author": "作成者", "AuthConfig": "資格認定構成", "AuthIntegration": "認証統合", "AuthLimit": "ログイン制限", diff --git a/apps/i18n/lina/ko.json b/apps/i18n/lina/ko.json index b614d70b7..c32fad9e1 100644 --- a/apps/i18n/lina/ko.json +++ b/apps/i18n/lina/ko.json @@ -200,6 +200,7 @@ "Audits": "감사 대시보드", "AuditsDashboard": "감사 대시보드", "Auth": "인증 설정", + "Author": "작성자", "AuthConfig": "인증 구성", "AuthIntegration": "인증 통합", "AuthLimit": "로그인 제한", diff --git a/apps/i18n/lina/pt_br.json b/apps/i18n/lina/pt_br.json index 1c5b1bcac..dc25cabf4 100644 --- a/apps/i18n/lina/pt_br.json +++ b/apps/i18n/lina/pt_br.json @@ -200,6 +200,7 @@ "Audits": "Auditório", "AuditsDashboard": "Painel de Auditoria", "Auth": "Configurações de autenticação", + "Author": "Autor", "AuthConfig": "Configurar Autenticação", "AuthIntegration": "Integração de Certificação", "AuthLimit": "Restrições de login", diff --git a/apps/i18n/lina/ru.json b/apps/i18n/lina/ru.json index 181ee9729..d995f53f9 100644 --- a/apps/i18n/lina/ru.json +++ b/apps/i18n/lina/ru.json @@ -200,6 +200,7 @@ "Audits": "Аудит", "AuditsDashboard": "Панель аудита", "Auth": "Аутентификация", + "Author": "Автор", "AuthConfig": "Настройка аутентификации", "AuthIntegration": "Интеграция аутентификации", "AuthLimit": "Ограничение входа", diff --git a/apps/i18n/lina/vi.json b/apps/i18n/lina/vi.json index 4f8a5b417..89fd66176 100644 --- a/apps/i18n/lina/vi.json +++ b/apps/i18n/lina/vi.json @@ -200,6 +200,7 @@ "Audits": "Bảng kiểm tra", "AuditsDashboard": "Bảng điều khiển kiểm toán", "Auth": "Cài đặt xác thực", + "Author": "Tác giả", "AuthConfig": "Cấu hình xác thực", "AuthIntegration": "Tích hợp xác thực", "AuthLimit": "Giới hạn đăng nhập", diff --git a/apps/i18n/lina/zh.json b/apps/i18n/lina/zh.json index 5c68fd079..29a55a0af 100644 --- a/apps/i18n/lina/zh.json +++ b/apps/i18n/lina/zh.json @@ -197,6 +197,7 @@ "Audits": "审计台", "AuditsDashboard": "审计台仪表盘", "Auth": "认证设置", + "Author": "作者", "AuthConfig": "配置认证", "AuthIntegration": "认证集成", "AuthLimit": "登录限制", diff --git a/apps/i18n/lina/zh_hant.json b/apps/i18n/lina/zh_hant.json index 11acf923e..7e905de6b 100644 --- a/apps/i18n/lina/zh_hant.json +++ b/apps/i18n/lina/zh_hant.json @@ -202,6 +202,7 @@ "Audits": "審計台", "AuditsDashboard": "審計台儀表盤", "Auth": "認證設置", + "Author": "作者", "AuthConfig": "配寘認證資訊", "AuthIntegration": "認證整合", "AuthLimit": "登入限制", From 378a0a5686b584306ad34d467cba95ae0a8869da Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Mon, 15 Jun 2026 11:56:45 +0800 Subject: [PATCH 09/10] perf: Logout countdown --- .../authentication/auth_fail_flash_message_standalone.html | 2 +- apps/templates/flash_message_standalone.html | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/authentication/templates/authentication/auth_fail_flash_message_standalone.html b/apps/authentication/templates/authentication/auth_fail_flash_message_standalone.html index 1ac57cd92..c3ab04d87 100644 --- a/apps/authentication/templates/authentication/auth_fail_flash_message_standalone.html +++ b/apps/authentication/templates/authentication/auth_fail_flash_message_standalone.html @@ -56,7 +56,7 @@ } function redirect_page() { - if (time >= 0) { + if (time > 0) { var msg = message + ', ' + time + ' ...'; $('#messages').html(msg); time--; diff --git a/apps/templates/flash_message_standalone.html b/apps/templates/flash_message_standalone.html index 97a75e67a..4269f71e7 100644 --- a/apps/templates/flash_message_standalone.html +++ b/apps/templates/flash_message_standalone.html @@ -44,7 +44,7 @@ {% block custom_foot_js %}