diff --git a/README.md b/README.md index 052952256..43803762c 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,28 @@ # JumpServer 多云环境下更好用的堡垒机 [![Python3](https://img.shields.io/badge/python-3.6-green.svg?style=plastic)](https://www.python.org/) -[![Django](https://img.shields.io/badge/django-2.1-brightgreen.svg?style=plastic)](https://www.djangoproject.com/) -[![Ansible](https://img.shields.io/badge/ansible-2.4.2.0-blue.svg?style=plastic)](https://www.ansible.com/) -[![Paramiko](https://img.shields.io/badge/paramiko-2.4.1-green.svg?style=plastic)](http://www.paramiko.org/) +[![Django](https://img.shields.io/badge/django-2.2-brightgreen.svg?style=plastic)](https://www.djangoproject.com/) -JumpServer 是全球首款开源的堡垒机,使用 GNU GPL v2.0 开源协议,是符合 4A 机制的运维安全审计系统。 +JumpServer 是全球首款开源的堡垒机,使用 GNU GPL v2.0 开源协议,是符合 4A 规范的运维安全审计系统。 -JumpServer 使用 Python / Django 进行开发,遵循 Web 2.0 规范,配备了业界领先的 Web Terminal 方案,交互界面美观、用户体验好。 +JumpServer 使用 Python / Django 为主进行开发,遵循 Web 2.0 规范,配备了业界领先的 Web Terminal 方案,交互界面美观、用户体验好。 JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向扩展,无资产数量及并发限制。 改变世界,从一点点开始。 -注: [KubeOperator](https://github.com/KubeOperator/KubeOperator) 是 JumpServer 团队在 Kubernetes 领域的的又一全新力作,欢迎关注和使用。 +> 注: [KubeOperator](https://github.com/KubeOperator/KubeOperator) 是 JumpServer 团队在 Kubernetes 领域的的又一全新力作,欢迎关注和使用。 -## 核心功能列表 +## 特色优势 + +- 开源: 零门槛,线上快速获取和安装; +- 分布式: 轻松支持大规模并发访问; +- 无插件: 仅需浏览器,极致的 Web Terminal 使用体验; +- 多云支持: 一套系统,同时管理不同云上面的资产; +- 云端存储: 审计录像云端存储,永不丢失; +- 多租户: 一套系统,多个子公司和部门同时使用。 + +## 功能列表 @@ -172,22 +179,26 @@ JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向
-## 安装及使用指南 - -- [Docker 快速安装文档](http://docs.jumpserver.org/zh/docs/dockerinstall.html) -- [Step by Step 安装文档](http://docs.jumpserver.org/zh/docs/step_by_step.html) -- [完整文档](http://docs.jumpserver.org) - -## 演示视频和截屏 - -我们提供了演示视频和系统截图可以让你快速了解 JumpServer: +## 快速开始 +- [极速安装](https://docs.jumpserver.org/zh/master/install/setup_by_fast/) +- [完整文档](https://docs.jumpserver.org) - [演示视频](https://jumpserver.oss-cn-hangzhou.aliyuncs.com/jms-media/%E3%80%90%E6%BC%94%E7%A4%BA%E8%A7%86%E9%A2%91%E3%80%91Jumpserver%20%E5%A0%A1%E5%9E%92%E6%9C%BA%20V1.5.0%20%E6%BC%94%E7%A4%BA%E8%A7%86%E9%A2%91%20-%20final.mp4) -- [系统截图](http://docs.JumpServer.org/zh/docs/snapshot.html) + +## 案例研究 + +- [JumpServer 堡垒机护航顺丰科技超大规模资产安全运维](https://blog.fit2cloud.com/?p=1147); +- [JumpServer 堡垒机让“大智慧”的混合 IT 运维更智慧](https://blog.fit2cloud.com/?p=882); +- [携程 JumpServer 堡垒机部署与运营实战](https://blog.fit2cloud.com/?p=851); +- [小红书的JumpServer堡垒机大规模资产跨版本迁移之路](https://blog.fit2cloud.com/?p=516); +- [JumpServer堡垒机助力中手游提升多云环境下安全运维能力](https://blog.fit2cloud.com/?p=732); +- [中通快递:JumpServer主机安全运维实践](https://blog.fit2cloud.com/?p=708); +- [东方明珠:JumpServer高效管控异构化、分布式云端资产](https://blog.fit2cloud.com/?p=687); +- [江苏农信:JumpServer堡垒机助力行业云安全运维](https://blog.fit2cloud.com/?p=666)。 ## License & Copyright -Copyright (c) 2014-2019 飞致云 FIT2CLOUD, All rights reserved. +Copyright (c) 2014-2020 飞致云 FIT2CLOUD, All rights reserved. Licensed under The GNU General Public License version 2 (GPLv2) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at diff --git a/apps/assets/filters.py b/apps/assets/filters.py index b68d9d127..94a49a3f5 100644 --- a/apps/assets/filters.py +++ b/apps/assets/filters.py @@ -58,7 +58,9 @@ class AssetByNodeFilterBackend(filters.BaseFilterBackend): if query_all: pattern = node.get_all_children_pattern(with_self=True) else: - pattern = node.get_children_key_pattern(with_self=True) + # pattern = node.get_children_key_pattern(with_self=True) + # 只显示当前节点下资产 + pattern = r"^{}$".format(node.key) return self.perform_query(pattern, queryset) diff --git a/apps/assets/templates/assets/user_asset_list.html b/apps/assets/templates/assets/user_asset_list.html index fa2c9830c..2a8c8cf64 100644 --- a/apps/assets/templates/assets/user_asset_list.html +++ b/apps/assets/templates/assets/user_asset_list.html @@ -76,8 +76,9 @@ $(document).ready(function () { 'ip': "{% trans 'IP' %}", 'protocols': "{% trans 'Protocols' %}", 'platform': "{% trans 'Platform' %}", - 'system_users_join': "{% trans 'System user' %}", + {#'system_users_join': "{% trans 'System user' %}",#} 'domain': "{% trans 'Domain' %}", + 'comment': "{% trans 'Comment' %}", }; var value; for (var i = 0; i < data.results.length; i++) { diff --git a/apps/authentication/templates/authentication/_access_key_modal.html b/apps/authentication/templates/authentication/_access_key_modal.html index f0b34cf30..71b1f67f5 100644 --- a/apps/authentication/templates/authentication/_access_key_modal.html +++ b/apps/authentication/templates/authentication/_access_key_modal.html @@ -135,6 +135,19 @@ $(document).ready(function () { } }; requestApi(data) +}).on('click', '.btn-api-keydel', function (){ + var url = "{% url "api-auth:access-key-detail" pk=DEFAULT_PK %}"; + url = url.replace("{{ DEFAULT_PK }}", $(this).data("id")) ; + var data = { + url: url, + method: "DELETE", + success: function () { + ak_table.ajax.reload(); + }, + success_message: "{% trans 'Delete success' %}" + + }; + requestApi(data) }) {% endblock %} diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index dc0e9eae6..5da97cfb7 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -173,11 +173,12 @@ class Config(dict): # OpenID 配置参数 # OpenID 公有配置参数 (version <= 1.5.8 或 version >= 1.5.8) 'AUTH_OPENID': False, + 'BASE_SITE_URL': None, 'AUTH_OPENID_CLIENT_ID': 'client-id', 'AUTH_OPENID_CLIENT_SECRET': 'client-secret', 'AUTH_OPENID_SHARE_SESSION': True, 'AUTH_OPENID_IGNORE_SSL_VERIFICATION': True, - # OpenID 新配置参数 (version >= 1.5.8) + # OpenID 新配置参数 (version >= 1.5.9) 'AUTH_OPENID_PROVIDER_ENDPOINT': 'https://op-example.com/', 'AUTH_OPENID_PROVIDER_AUTHORIZATION_ENDPOINT': 'https://op-example.com/authorize', 'AUTH_OPENID_PROVIDER_TOKEN_ENDPOINT': 'https://op-example.com/token', @@ -193,7 +194,6 @@ class Config(dict): 'AUTH_OPENID_USE_NONCE': True, 'AUTH_OPENID_ALWAYS_UPDATE_USER': True, # OpenID 旧配置参数 (version <= 1.5.8 (discarded)) - 'BASE_SITE_URL': 'http://localhost:8080', 'AUTH_OPENID_SERVER_URL': 'http://openid', 'AUTH_OPENID_REALM_NAME': None, diff --git a/apps/jumpserver/const.py b/apps/jumpserver/const.py index 2a97a00d2..b7caa6114 100644 --- a/apps/jumpserver/const.py +++ b/apps/jumpserver/const.py @@ -7,6 +7,6 @@ __all__ = ['BASE_DIR', 'PROJECT_DIR', 'VERSION', 'CONFIG', 'DYNAMIC'] BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PROJECT_DIR = os.path.dirname(BASE_DIR) -VERSION = '1.5.8' +VERSION = '1.5.9' CONFIG = ConfigManager.load_user_config() DYNAMIC = ConfigManager.get_dynamic_config(CONFIG) diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index 516671980..b7633ace7 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -48,6 +48,7 @@ AUTH_LDAP_USER_LOGIN_ONLY_IN_USERS = CONFIG.AUTH_LDAP_USER_LOGIN_ONLY_IN_USERS # 参考: https://django-oidc-rp.readthedocs.io/en/stable/settings.html # ============================================================================== AUTH_OPENID = CONFIG.AUTH_OPENID +BASE_SITE_URL = CONFIG.BASE_SITE_URL AUTH_OPENID_CLIENT_ID = CONFIG.AUTH_OPENID_CLIENT_ID AUTH_OPENID_CLIENT_SECRET = CONFIG.AUTH_OPENID_CLIENT_SECRET AUTH_OPENID_PROVIDER_ENDPOINT = CONFIG.AUTH_OPENID_PROVIDER_ENDPOINT diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 72d6cdb43..c51d13e46 100644 Binary files a/apps/locale/zh/LC_MESSAGES/django.mo and b/apps/locale/zh/LC_MESSAGES/django.mo differ diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index db84b6b14..8207c4b7a 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-05-11 16:53+0800\n" +"POT-Creation-Date: 2020-05-20 19:25+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -26,7 +26,7 @@ msgstr "自定义" #: applications/templates/applications/remote_app_list.html:27 #: applications/templates/applications/user_remote_app_list.html:18 #: assets/forms/domain.py:15 assets/forms/label.py:13 -#: assets/models/asset.py:353 assets/models/authbook.py:27 +#: assets/models/asset.py:352 assets/models/authbook.py:27 #: assets/models/gathered_user.py:14 assets/serializers/admin_user.py:32 #: assets/serializers/asset_user.py:47 assets/serializers/asset_user.py:84 #: assets/serializers/system_user.py:44 assets/serializers/system_user.py:176 @@ -112,7 +112,7 @@ msgstr "运行参数" #: applications/templates/applications/user_database_app_list.html:16 #: applications/templates/applications/user_remote_app_list.html:16 #: assets/forms/asset.py:21 assets/forms/domain.py:77 assets/forms/user.py:74 -#: assets/forms/user.py:96 assets/models/asset.py:146 assets/models/base.py:232 +#: assets/forms/user.py:96 assets/models/asset.py:145 assets/models/base.py:232 #: assets/models/cluster.py:18 assets/models/cmd_filter.py:21 #: assets/models/domain.py:20 assets/models/group.py:20 #: assets/models/label.py:18 assets/templates/assets/_node_detail_modal.html:27 @@ -204,7 +204,7 @@ msgstr "主机" #: applications/models/database_app.py:27 #: applications/templates/applications/database_app_detail.html:60 #: applications/templates/applications/database_app_list.html:26 -#: assets/forms/asset.py:25 assets/models/asset.py:192 +#: assets/forms/asset.py:25 assets/models/asset.py:191 #: assets/models/domain.py:50 #: assets/templates/assets/domain_gateway_list.html:64 msgid "Port" @@ -227,7 +227,7 @@ msgstr "数据库" #: applications/templates/applications/remote_app_list.html:28 #: applications/templates/applications/user_database_app_list.html:20 #: applications/templates/applications/user_remote_app_list.html:19 -#: assets/models/asset.py:151 assets/models/asset.py:227 +#: assets/models/asset.py:150 assets/models/asset.py:226 #: assets/models/base.py:237 assets/models/cluster.py:29 #: assets/models/cmd_filter.py:23 assets/models/cmd_filter.py:56 #: assets/models/domain.py:21 assets/models/domain.py:53 @@ -244,7 +244,8 @@ msgstr "数据库" #: assets/templates/assets/platform_detail.html:64 #: assets/templates/assets/platform_list.html:18 #: assets/templates/assets/system_user_detail.html:112 -#: assets/templates/assets/system_user_list.html:29 ops/models/adhoc.py:37 +#: assets/templates/assets/system_user_list.html:29 +#: assets/templates/assets/user_asset_list.html:81 ops/models/adhoc.py:37 #: orgs/models.py:18 perms/models/base.py:56 #: perms/templates/perms/asset_permission_detail.html:97 #: perms/templates/perms/database_app_permission_detail.html:93 @@ -309,7 +310,7 @@ msgstr "参数" #: applications/models/remote_app.py:39 #: applications/templates/applications/database_app_detail.html:72 #: applications/templates/applications/remote_app_detail.html:68 -#: assets/models/asset.py:225 assets/models/base.py:240 +#: assets/models/asset.py:224 assets/models/base.py:240 #: assets/models/cluster.py:28 assets/models/cmd_filter.py:26 #: assets/models/cmd_filter.py:59 assets/models/group.py:21 #: assets/templates/assets/admin_user_detail.html:63 @@ -335,7 +336,7 @@ msgstr "创建者" #: applications/models/remote_app.py:42 #: applications/templates/applications/database_app_detail.html:68 #: applications/templates/applications/remote_app_detail.html:64 -#: assets/models/asset.py:226 assets/models/base.py:238 +#: assets/models/asset.py:225 assets/models/base.py:238 #: assets/models/cluster.py:26 assets/models/domain.py:23 #: assets/models/gathered_user.py:19 assets/models/group.py:22 #: assets/models/label.py:25 assets/templates/assets/admin_user_detail.html:59 @@ -737,7 +738,7 @@ msgstr "不能移除资产的管理用户账号" msgid "Latest version could not be delete" msgstr "最新版本的不能被删除" -#: assets/forms/asset.py:83 assets/models/asset.py:196 +#: assets/forms/asset.py:83 assets/models/asset.py:195 #: assets/models/user.py:109 assets/templates/assets/asset_detail.html:186 #: assets/templates/assets/asset_detail.html:194 #: assets/templates/assets/system_user_assets.html:118 @@ -748,7 +749,7 @@ msgstr "最新版本的不能被删除" msgid "Nodes" msgstr "节点" -#: assets/forms/asset.py:86 assets/models/asset.py:200 +#: assets/forms/asset.py:86 assets/models/asset.py:199 #: assets/models/cluster.py:19 assets/models/user.py:65 #: assets/templates/assets/admin_user_list.html:62 #: assets/templates/assets/asset_detail.html:72 templates/_nav.html:44 @@ -766,7 +767,7 @@ msgstr "管理用户" msgid "Label" msgstr "标签" -#: assets/forms/asset.py:92 assets/models/asset.py:195 +#: assets/forms/asset.py:92 assets/models/asset.py:194 #: assets/models/domain.py:26 assets/models/domain.py:52 #: assets/templates/assets/asset_detail.html:76 #: assets/templates/assets/user_asset_list.html:80 @@ -774,8 +775,8 @@ msgstr "标签" msgid "Domain" msgstr "网域" -#: assets/forms/asset.py:95 assets/models/asset.py:170 -#: assets/models/asset.py:194 assets/serializers/asset.py:67 +#: assets/forms/asset.py:95 assets/models/asset.py:169 +#: assets/models/asset.py:193 assets/serializers/asset.py:67 #: assets/templates/assets/asset_detail.html:100 #: assets/templates/assets/user_asset_list.html:78 msgid "Platform" @@ -980,24 +981,24 @@ msgstr "SFTP的起始路径,tmp目录, 用户home目录或者自定义" msgid "Username is dynamic, When connect asset, using current user's username" msgstr "用户名是动态的,登录资产时使用当前用户的用户名登录" -#: assets/models/asset.py:147 xpack/plugins/cloud/providers/base.py:16 +#: assets/models/asset.py:146 xpack/plugins/cloud/providers/base.py:16 msgid "Base" msgstr "基础" -#: assets/models/asset.py:148 assets/templates/assets/platform_detail.html:56 +#: assets/models/asset.py:147 assets/templates/assets/platform_detail.html:56 msgid "Charset" msgstr "编码" -#: assets/models/asset.py:149 assets/templates/assets/platform_detail.html:60 +#: assets/models/asset.py:148 assets/templates/assets/platform_detail.html:60 #: tickets/models/ticket.py:38 msgid "Meta" msgstr "元数据" -#: assets/models/asset.py:150 +#: assets/models/asset.py:149 msgid "Internal" msgstr "内部的" -#: assets/models/asset.py:187 assets/models/domain.py:49 +#: assets/models/asset.py:186 assets/models/domain.py:49 #: assets/serializers/asset_user.py:46 #: assets/templates/assets/_asset_list_modal.html:47 #: assets/templates/assets/_asset_user_list.html:20 @@ -1014,7 +1015,7 @@ msgstr "内部的" msgid "IP" msgstr "IP" -#: assets/models/asset.py:188 assets/serializers/asset_user.py:45 +#: assets/models/asset.py:187 assets/serializers/asset_user.py:45 #: assets/serializers/gathered_user.py:20 #: assets/templates/assets/_asset_list_modal.html:46 #: assets/templates/assets/_asset_user_auth_update_modal.html:9 @@ -1031,7 +1032,7 @@ msgstr "IP" msgid "Hostname" msgstr "主机名" -#: assets/models/asset.py:191 assets/models/domain.py:51 +#: assets/models/asset.py:190 assets/models/domain.py:51 #: assets/models/user.py:114 assets/templates/assets/asset_detail.html:68 #: assets/templates/assets/domain_gateway_list.html:65 #: assets/templates/assets/system_user_detail.html:78 @@ -1043,84 +1044,84 @@ msgstr "主机名" msgid "Protocol" msgstr "协议" -#: assets/models/asset.py:193 assets/serializers/asset.py:69 +#: assets/models/asset.py:192 assets/serializers/asset.py:69 #: assets/templates/assets/asset_create.html:24 #: assets/templates/assets/user_asset_list.html:77 #: perms/serializers/user_permission.py:60 msgid "Protocols" msgstr "协议组" -#: assets/models/asset.py:197 assets/models/cmd_filter.py:22 +#: assets/models/asset.py:196 assets/models/cmd_filter.py:22 #: assets/models/domain.py:54 assets/models/label.py:22 #: assets/templates/assets/asset_detail.html:108 authentication/models.py:45 msgid "Is active" msgstr "激活" -#: assets/models/asset.py:203 assets/templates/assets/asset_detail.html:64 +#: assets/models/asset.py:202 assets/templates/assets/asset_detail.html:64 msgid "Public IP" msgstr "公网IP" -#: assets/models/asset.py:204 assets/templates/assets/asset_detail.html:116 +#: assets/models/asset.py:203 assets/templates/assets/asset_detail.html:116 msgid "Asset number" msgstr "资产编号" -#: assets/models/asset.py:207 assets/templates/assets/asset_detail.html:80 +#: assets/models/asset.py:206 assets/templates/assets/asset_detail.html:80 msgid "Vendor" msgstr "制造商" -#: assets/models/asset.py:208 assets/templates/assets/asset_detail.html:84 +#: assets/models/asset.py:207 assets/templates/assets/asset_detail.html:84 msgid "Model" msgstr "型号" -#: assets/models/asset.py:209 assets/templates/assets/asset_detail.html:112 +#: assets/models/asset.py:208 assets/templates/assets/asset_detail.html:112 msgid "Serial number" msgstr "序列号" -#: assets/models/asset.py:211 +#: assets/models/asset.py:210 msgid "CPU model" msgstr "CPU型号" -#: assets/models/asset.py:212 +#: assets/models/asset.py:211 msgid "CPU count" msgstr "CPU数量" -#: assets/models/asset.py:213 +#: assets/models/asset.py:212 msgid "CPU cores" msgstr "CPU核数" -#: assets/models/asset.py:214 +#: assets/models/asset.py:213 msgid "CPU vcpus" msgstr "CPU总数" -#: assets/models/asset.py:215 assets/templates/assets/asset_detail.html:92 +#: assets/models/asset.py:214 assets/templates/assets/asset_detail.html:92 msgid "Memory" msgstr "内存" -#: assets/models/asset.py:216 +#: assets/models/asset.py:215 msgid "Disk total" msgstr "硬盘大小" -#: assets/models/asset.py:217 +#: assets/models/asset.py:216 msgid "Disk info" msgstr "硬盘信息" -#: assets/models/asset.py:219 assets/templates/assets/asset_detail.html:104 +#: assets/models/asset.py:218 assets/templates/assets/asset_detail.html:104 msgid "OS" msgstr "操作系统" -#: assets/models/asset.py:220 +#: assets/models/asset.py:219 msgid "OS version" msgstr "系统版本" -#: assets/models/asset.py:221 +#: assets/models/asset.py:220 msgid "OS arch" msgstr "系统架构" -#: assets/models/asset.py:222 +#: assets/models/asset.py:221 msgid "Hostname raw" msgstr "主机名原始" -#: assets/models/asset.py:224 assets/templates/assets/asset_create.html:46 +#: assets/models/asset.py:223 assets/templates/assets/asset_create.html:46 #: assets/templates/assets/asset_detail.html:220 templates/_nav.html:46 msgid "Labels" msgstr "标签管理" @@ -1449,8 +1450,7 @@ msgid "SFTP Root" msgstr "SFTP根路径" #: assets/models/user.py:195 assets/templates/assets/system_user_list.html:73 -#: assets/templates/assets/user_asset_list.html:79 audits/models.py:21 -#: audits/templates/audits/ftp_log_list.html:53 +#: audits/models.py:21 audits/templates/audits/ftp_log_list.html:53 #: audits/templates/audits/ftp_log_list.html:76 #: perms/forms/asset_permission.py:95 perms/forms/remote_app_permission.py:49 #: perms/models/asset_permission.py:82 @@ -1671,7 +1671,7 @@ msgstr "定期测试系统用户可连接性: {}" #: assets/tasks/utils.py:17 msgid "Asset has been disabled, skipped: {}" -msgstr "资产或许不支持ansible, 跳过: {}" +msgstr "资产已经被禁用, 跳过: {}" #: assets/tasks/utils.py:21 msgid "Asset may not be support ansible, skipped: {}" @@ -1771,7 +1771,7 @@ msgstr "获取认证信息错误" #: assets/templates/assets/_asset_user_auth_view_modal.html:101 #: assets/templates/assets/_node_detail_modal.html:67 #: assets/templates/assets/_user_asset_detail_modal.html:23 -#: authentication/templates/authentication/_access_key_modal.html:142 +#: authentication/templates/authentication/_access_key_modal.html:155 #: authentication/templates/authentication/_mfa_confirm_modal.html:53 #: settings/templates/settings/_ldap_list_users_modal.html:171 #: templates/_modal.html:22 tickets/models/ticket.py:68 @@ -1817,6 +1817,7 @@ msgid "Push" msgstr "推送" #: assets/templates/assets/_asset_user_list.html:167 +#: authentication/templates/authentication/_access_key_modal.html:147 msgid "Delete success" msgstr "删除成功" @@ -2769,7 +2770,7 @@ msgid "" msgstr "账号已被锁定(请联系管理员解锁 或 {}分钟后重试)" #: authentication/errors.py:48 users/views/profile/otp.py:63 -#: users/views/profile/otp.py:100 users/views/profile/otp.py:116 +#: users/views/profile/otp.py:102 users/views/profile/otp.py:121 msgid "MFA code invalid, or ntp sync server time" msgstr "MFA验证码不正确,或者服务器端时间不对" @@ -2881,8 +2882,8 @@ msgid "More login options" msgstr "更多登录方式" #: authentication/templates/authentication/login.html:61 -msgid "Keycloak" -msgstr "" +msgid "OpenID" +msgstr "OpenID" #: authentication/templates/authentication/login_otp.html:17 msgid "One-time password" @@ -5598,7 +5599,7 @@ msgstr "上一步" #: users/templates/users/first_login_done.html:31 msgid "Welcome to use jumpserver, visit " -msgstr "欢迎使用JumpServer开源跳板机系统" +msgstr "欢迎使用 JumpServer 堡垒机" #: users/templates/users/first_login_done.html:32 msgid "Use guide" @@ -6183,19 +6184,19 @@ msgstr "首次登录" msgid "Profile setting" msgstr "个人信息设置" -#: users/views/profile/otp.py:144 +#: users/views/profile/otp.py:145 msgid "MFA enable success" msgstr "多因子认证启用成功" -#: users/views/profile/otp.py:145 +#: users/views/profile/otp.py:146 msgid "MFA enable success, return login page" msgstr "多因子认证启用成功,返回到登录页面" -#: users/views/profile/otp.py:147 +#: users/views/profile/otp.py:148 msgid "MFA disable success" msgstr "多因子认证禁用成功" -#: users/views/profile/otp.py:148 +#: users/views/profile/otp.py:149 msgid "MFA disable success, return login page" msgstr "多因子认证禁用成功,返回登录页面" @@ -6585,7 +6586,19 @@ msgstr "东北-大连" msgid "CN South-Guangzhou" msgstr "华南-广州" -#: xpack/plugins/cloud/providers/qcloud.py:14 +#: xpack/plugins/cloud/providers/huaweicloud.py:30 +msgid "CN Southwest-Guiyang1" +msgstr "西南-贵阳一" + +#: xpack/plugins/cloud/providers/huaweicloud.py:31 +msgid "EU-Paris" +msgstr "欧洲-巴黎" + +#: xpack/plugins/cloud/providers/huaweicloud.py:32 +msgid "LA-Santiago" +msgstr "拉美-圣地亚哥" + +#: xpack/plugins/cloud/providers/qcloud.py:17 msgid "Tencent Cloud" msgstr "腾讯云" @@ -6981,9 +6994,6 @@ msgstr "密码匣子" msgid "vault create" msgstr "创建" -#~ msgid "LA-Santiago" -#~ msgstr "拉美-圣地亚哥" - #~ msgid "Total hosts" #~ msgstr "主机总数" diff --git a/apps/ops/serializers/adhoc.py b/apps/ops/serializers/adhoc.py index afdd659fc..8d9e18e24 100644 --- a/apps/ops/serializers/adhoc.py +++ b/apps/ops/serializers/adhoc.py @@ -19,10 +19,13 @@ class AdHocExecutionSerializer(serializers.ModelSerializer): @staticmethod def get_stat(obj): + count_failed_hosts = len(obj.failed_hosts) + count_success_hosts = len(obj.success_hosts) + count_total = count_success_hosts + count_failed_hosts return { - "total": obj.hosts_amount, - "success": len(obj.summary.get("contacted", [])), - "failed": len(obj.summary.get("dark", [])), + "total": count_total, + "success": count_success_hosts, + "failed": count_failed_hosts } def get_field_names(self, declared_fields, info): diff --git a/apps/perms/apps.py b/apps/perms/apps.py index d40373e08..5bb7420bb 100644 --- a/apps/perms/apps.py +++ b/apps/perms/apps.py @@ -5,3 +5,7 @@ from django.apps import AppConfig class PermsConfig(AppConfig): name = 'perms' + + def ready(self): + super().ready() + from . import signals_handler diff --git a/apps/perms/templates/perms/asset_permission_user.html b/apps/perms/templates/perms/asset_permission_user.html index bb9ca375a..088d80c75 100644 --- a/apps/perms/templates/perms/asset_permission_user.html +++ b/apps/perms/templates/perms/asset_permission_user.html @@ -218,7 +218,7 @@ function addGroups(groupsId) { } function removeGroup(groupId) { - var theUrl = "{% url 'api-perms:asset-permissions-user-groups-relation-list' %}?assetpermission={{ object.id }}"; + var theUrl = "{% url 'api-perms:asset-permissions-user-groups-relation-list' %}?assetpermission={{ object.id }}&usergroup=groupId"; theUrl = theUrl.replace("groupId", groupId); var success = function(data) { location.reload(); diff --git a/apps/perms/templates/perms/database_app_permission_user.html b/apps/perms/templates/perms/database_app_permission_user.html index 603f60a6e..8b109fa1a 100644 --- a/apps/perms/templates/perms/database_app_permission_user.html +++ b/apps/perms/templates/perms/database_app_permission_user.html @@ -218,7 +218,7 @@ function addGroups(groupsId) { } function removeGroup(groupId) { - var theUrl = "{% url 'api-perms:database-app-permissions-user-groups-relation-list' %}?databaseapppermission={{ object.id }}"; + var theUrl = "{% url 'api-perms:database-app-permissions-user-groups-relation-list' %}?databaseapppermission={{ object.id }}&usergroup=groupId"; theUrl = theUrl.replace("groupId", groupId); var success = function(data) { location.reload(); diff --git a/apps/perms/templates/perms/remote_app_permission_user.html b/apps/perms/templates/perms/remote_app_permission_user.html index d222dfb7c..9fa623585 100644 --- a/apps/perms/templates/perms/remote_app_permission_user.html +++ b/apps/perms/templates/perms/remote_app_permission_user.html @@ -179,9 +179,13 @@ var body = { user_groups: groups }; + var success = function(data) { + location.reload(); + }; requestApi({ url: the_url, - body: JSON.stringify(body) + body: JSON.stringify(body), + success: success }); } $(document).ready(function () { diff --git a/apps/perms/utils/asset_permission.py b/apps/perms/utils/asset_permission.py index cd6e1805e..80b1c19e5 100644 --- a/apps/perms/utils/asset_permission.py +++ b/apps/perms/utils/asset_permission.py @@ -477,6 +477,7 @@ class ParserNode: 'platform': asset.platform_base, 'domain': asset.domain_id, 'org_name': asset.org_name, + 'org_id': asset.org_id }, } } diff --git a/apps/users/views/profile/otp.py b/apps/users/views/profile/otp.py index 2d823f5ab..83918114e 100644 --- a/apps/users/views/profile/otp.py +++ b/apps/users/views/profile/otp.py @@ -83,26 +83,12 @@ class UserOtpEnableBindView(TemplateView, FormView): return super().get_context_data(**kwargs) -class UserVerifyMFAView(FormView): +class UserDisableMFAView(FormView): template_name = 'users/user_verify_mfa.html' form_class = forms.UserCheckOtpCodeForm success_url = reverse_lazy('users:user-otp-settings-success') permission_classes = [IsValidUser] - def form_valid(self, form): - user = self.request.user - otp_code = form.cleaned_data.get('otp_code') - - valid = user.check_mfa(otp_code) - if valid: - return super().form_valid(form) - else: - error = _('MFA code invalid, or ntp sync server time') - form.add_error('otp_code', error) - return super().form_invalid(form) - - -class UserDisableMFAView(UserVerifyMFAView): def form_valid(self, form): user = self.request.user otp_code = form.cleaned_data.get('otp_code') @@ -118,8 +104,23 @@ class UserDisableMFAView(UserVerifyMFAView): return super().form_invalid(form) -class UserOtpUpdateView(UserVerifyMFAView): +class UserOtpUpdateView(FormView): + template_name = 'users/user_verify_mfa.html' + form_class = forms.UserCheckOtpCodeForm success_url = reverse_lazy('users:user-otp-enable-bind') + permission_classes = [IsValidUser] + + def form_valid(self, form): + user = self.request.user + otp_code = form.cleaned_data.get('otp_code') + + valid = user.check_mfa(otp_code) + if valid: + return super().form_valid(form) + else: + error = _('MFA code invalid, or ntp sync server time') + form.add_error('otp_code', error) + return super().form_invalid(form) class UserOtpSettingsSuccessView(TemplateView): diff --git a/apps/users/views/profile/password.py b/apps/users/views/profile/password.py index c9bb97f38..bb7caa9a1 100644 --- a/apps/users/views/profile/password.py +++ b/apps/users/views/profile/password.py @@ -67,7 +67,7 @@ class UserVerifyPasswordView(FormView): def form_valid(self, form): user = get_user_or_pre_auth_user(self.request) password = form.cleaned_data.get('password') - user = authenticate(username=user.username, password=password) + user = authenticate(request=self.request, username=user.username, password=password) if not user: form.add_error("password", _("Password invalid")) return self.form_invalid(form) diff --git a/config_example.yml b/config_example.yml index 30cfabc3e..fd8710c78 100644 --- a/config_example.yml +++ b/config_example.yml @@ -56,6 +56,7 @@ REDIS_PORT: 6379 # Use OpenID Authorization # 使用 OpenID 进行认证设置 # AUTH_OPENID: False # True or False +# BASE_SITE_URL: None # AUTH_OPENID_CLIENT_ID: client-id # AUTH_OPENID_CLIENT_SECRET: client-secret # AUTH_OPENID_PROVIDER_ENDPOINT: https://op-example.com/ diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 50e4a1862..59e86f1ac 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -96,4 +96,4 @@ ipython huaweicloud-sdk-python==1.0.21 django-redis==4.11.0 python-redis-lock==3.5.0 -jumpserver-django-oidc-rp==0.3.7.3 +jumpserver-django-oidc-rp==0.3.7.4