From 7c35e75586c098cab51b457a0d4d7f54c17718ba Mon Sep 17 00:00:00 2001 From: wojiushixiaobai <296015668@qq.com> Date: Wed, 25 Apr 2018 19:49:22 +0800 Subject: [PATCH 01/26] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8D=87=E7=BA=A7=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/upgrade.sh | 49 +++++++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/utils/upgrade.sh b/utils/upgrade.sh index 878bf770a..e1cdabb76 100644 --- a/utils/upgrade.sh +++ b/utils/upgrade.sh @@ -1,24 +1,14 @@ #!/bin/bash -if [ ! -d "/opt/py3" ]; then -echo -e "\033[31m python3虚拟环境不是默认路径 \033[0m" -ps -ef | grep jumpserver/tmp/beat.pid | grep -v grep -if [ $? -ne 0 ] -then -echo -e "\033[31m jumpserver未运行,请到jumpserver目录使用 ./jms start all -d 启动 \033[0m" -exit 0 -else -echo -e "\033[31m 正在计算python3虚拟环境路径 \033[0m" -fi -py3pid=`ps -ef | grep jumpserver/tmp/beat.pid | grep -v grep | awk '{print $2}'` -py3file=`cat /proc/$py3pid/cmdline` -py3even=`echo ${py3file%/bin/python3*}` -echo -e "\033[31m python3虚拟环境路径为$py3even \033[0m" -source $py3even/bin/activate +if grep -q 'source ~/.autoenv/activate.sh' ~/.bashrc; then + echo -e "\033[31m 正在自动载入 python 环境 \033[0m" else -source /opt/py3/bin/activate + echo -e "\033[31m 不支持自动升级,请参考 http://docs.jumpserver.org/zh/docs/upgrade.html 手动升级 \033[0m" + exit 0 fi +source ~/.bashrc + cd `dirname $0`/ && cd .. && ./jms stop jumpserver_backup=/tmp/jumpserver_backup$(date -d "today" +"%Y%m%d_%H%M%S") @@ -29,21 +19,20 @@ echo -e "\033[31m 是否需要备份Jumpserver数据库 \033[0m" stty erase ^H read -p "确认备份请按Y,否则按其他键跳过备份 " a if [ "$a" == y -o "$a" == Y ];then -echo -e "\033[31m 正在备份数据库 \033[0m" -echo -e "\033[31m 请手动输入数据库信息 \033[0m" -read -p '请输入Jumpserver数据库ip:' DB_HOST -read -p '请输入Jumpserver数据库端口:' DB_PORT -read -p '请输入Jumpserver数据库名称:' DB_NAME -read -p '请输入有权限导出数据库的用户:' DB_USER -read -p '请输入该用户的密码:' DB_PASSWORD -mysqldump -h$DB_HOST -P$DB_PORT -u$DB_USER -p$DB_PASSWORD $DB_NAME > /$jumpserver_backup/$DB_NAME$(date -d "today" +"%Y%m%d_%H%M%S").sql || { -echo -e "\033[31m 备份数据库失败,请检查输入是否有误 \033[0m" -exit 1 -} -echo -e "\033[31m 备份数据库完成 \033[0m" - + echo -e "\033[31m 正在备份数据库 \033[0m" + echo -e "\033[31m 请手动输入数据库信息 \033[0m" + read -p '请输入Jumpserver数据库ip:' DB_HOST + read -p '请输入Jumpserver数据库端口:' DB_PORT + read -p '请输入Jumpserver数据库名称:' DB_NAME + read -p '请输入有权限导出数据库的用户:' DB_USER + read -p '请输入该用户的密码:' DB_PASSWORD + mysqldump -h$DB_HOST -P$DB_PORT -u$DB_USER -p$DB_PASSWORD $DB_NAME > /$jumpserver_backup/$DB_NAME$(date -d "today" +"%Y%m%d_%H%M%S").sql || { + echo -e "\033[31m 备份数据库失败,请检查输入是否有误 \033[0m" + exit 1 + } + echo -e "\033[31m 备份数据库完成 \033[0m" else -echo -e "\033[31m 已取消备份数据库操作 \033[0m" + echo -e "\033[31m 已取消备份数据库操作 \033[0m" fi git pull && pip install -r requirements/requirements.txt && cd utils && sh make_migrations.sh From 0d8a600277fcadefb374a7d23857c522ce2b7a44 Mon Sep 17 00:00:00 2001 From: oldseven Date: Fri, 27 Apr 2018 15:17:32 +0800 Subject: [PATCH 02/26] =?UTF-8?q?#1258=20bug=20fix:=20=E9=98=BF=E9=87=8C?= =?UTF-8?q?=E4=BA=91OSS=E5=BD=95=E5=83=8F=E6=97=A0=E6=B3=95=E5=9B=9E?= =?UTF-8?q?=E6=94=BE=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/api.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/terminal/api.py b/apps/terminal/api.py index a964e9729..a5f7847ab 100644 --- a/apps/terminal/api.py +++ b/apps/terminal/api.py @@ -297,6 +297,10 @@ class SessionReplayViewSet(viewsets.ViewSet): date = self.session.date_start.strftime('%Y-%m-%d') file_path = os.path.join(date, str(self.session.id) + '.replay.gz') target_path = default_storage.base_location + '/' + path + folder_path = default_storage.base_location + date + + if not default_storage.exists(folder_path): + os.mkdir(folder_path) if client and client.has_file(file_path) and \ client.download_file(file_path, target_path): From 4f28f854103dec498440e960575305a29230acac Mon Sep 17 00:00:00 2001 From: oldseven Date: Tue, 29 May 2018 09:51:55 +0800 Subject: [PATCH 03/26] #1368 --- apps/terminal/api.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/terminal/api.py b/apps/terminal/api.py index fbbae5e22..28d8d6c02 100644 --- a/apps/terminal/api.py +++ b/apps/terminal/api.py @@ -4,6 +4,7 @@ from collections import OrderedDict import logging import os import uuid +import copy from django.core.cache import cache from django.shortcuts import get_object_or_404, redirect @@ -291,8 +292,12 @@ class SessionReplayViewSet(viewsets.ViewSet): url = default_storage.url(path) return redirect(url) else: - configs = settings.TERMINAL_REPLAY_STORAGE - configs = [cfg for cfg in configs if cfg['TYPE'] != 'server'] + config = settings.TERMINAL_REPLAY_STORAGE + configs = copy.deepcopy(config) + for cfg in config: + if config[cfg]['TYPE'] == 'server': + configs.__delitem__(cfg) + if not configs: return HttpResponseNotFound() From 7a7c6d40dffdf8ce82c59e1e92af3114a365a523 Mon Sep 17 00:00:00 2001 From: Nevss <85764621@qq.com> Date: Thu, 5 Jul 2018 19:08:35 +0800 Subject: [PATCH 04/26] update docker-guacamole version to latest update docker-guacamole version to latest --- docs/step_by_step.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/step_by_step.rst b/docs/step_by_step.rst index 484013e1b..300e1a3a2 100644 --- a/docs/step_by_step.rst +++ b/docs/step_by_step.rst @@ -228,7 +228,7 @@ Luna 已改为纯前端,需要 Nginx 来运行访问 -p 8081:8080 -v /opt/guacamole/key:/config/guacamole/key \ -e JUMPSERVER_KEY_DIR=/config/guacamole/key \ -e JUMPSERVER_SERVER=http://<填写本机的IP地址>:8080 \ - registry.jumpserver.org/public/guacamole:1.0.0 + registry.jumpserver.org/public/guacamole:latest 这里所需要注意的是 guacamole 暴露出来的端口是 8081,若与主机上其他端口冲突请自定义一下。 From 0ddb9476ba68f03ea6507af1ebe3535ec202fd30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=B3=B0=E4=BB=BB1049851?= Date: Mon, 9 Jul 2018 15:55:07 +0800 Subject: [PATCH 05/26] =?UTF-8?q?=E8=B5=84=E4=BA=A7=E6=8E=88=E6=9D=83?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=A2=9E=E5=8A=A0=E5=88=86=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 资产授权页面增加分页 --- apps/perms/api.py | 2 ++ apps/perms/templates/perms/asset_permission_list.html | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/perms/api.py b/apps/perms/api.py index 33a027064..ece7c1011 100644 --- a/apps/perms/api.py +++ b/apps/perms/api.py @@ -5,6 +5,7 @@ from django.shortcuts import get_object_or_404 from rest_framework.views import APIView, Response from rest_framework.generics import ListAPIView, get_object_or_404, RetrieveUpdateAPIView from rest_framework import viewsets +from rest_framework.pagination import LimitOffsetPagination from common.utils import set_or_append_attr_bulk, get_object_or_none from users.permissions import IsValidUser, IsSuperUser, IsSuperUserOrAppUser @@ -22,6 +23,7 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): queryset = AssetPermission.objects.all() serializer_class = serializers.AssetPermissionCreateUpdateSerializer permission_classes = (IsSuperUser,) + pagination_class = LimitOffsetPagination def get_serializer_class(self): if self.action in ("list", 'retrieve'): diff --git a/apps/perms/templates/perms/asset_permission_list.html b/apps/perms/templates/perms/asset_permission_list.html index c18f12224..2f0f74312 100644 --- a/apps/perms/templates/perms/asset_permission_list.html +++ b/apps/perms/templates/perms/asset_permission_list.html @@ -208,7 +208,7 @@ function initTable() { select: {}, op_html: $('#actions').html() }; - table = jumpserver.initDataTable(options); + table = jumpserver.initServerSideDataTable(options); return table } From eaefb5c669bce925062c6fa65bbf96250e0984fa Mon Sep 17 00:00:00 2001 From: ycfuck Date: Mon, 9 Jul 2018 16:00:02 +0800 Subject: [PATCH 06/26] =?UTF-8?q?Revert=20"=E8=B5=84=E4=BA=A7=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E9=A1=B5=E9=9D=A2=E5=A2=9E=E5=8A=A0=E5=88=86=E9=A1=B5?= =?UTF-8?q?"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 0ddb9476ba68f03ea6507af1ebe3535ec202fd30. --- apps/perms/api.py | 2 -- apps/perms/templates/perms/asset_permission_list.html | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/perms/api.py b/apps/perms/api.py index ece7c1011..33a027064 100644 --- a/apps/perms/api.py +++ b/apps/perms/api.py @@ -5,7 +5,6 @@ from django.shortcuts import get_object_or_404 from rest_framework.views import APIView, Response from rest_framework.generics import ListAPIView, get_object_or_404, RetrieveUpdateAPIView from rest_framework import viewsets -from rest_framework.pagination import LimitOffsetPagination from common.utils import set_or_append_attr_bulk, get_object_or_none from users.permissions import IsValidUser, IsSuperUser, IsSuperUserOrAppUser @@ -23,7 +22,6 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): queryset = AssetPermission.objects.all() serializer_class = serializers.AssetPermissionCreateUpdateSerializer permission_classes = (IsSuperUser,) - pagination_class = LimitOffsetPagination def get_serializer_class(self): if self.action in ("list", 'retrieve'): diff --git a/apps/perms/templates/perms/asset_permission_list.html b/apps/perms/templates/perms/asset_permission_list.html index 2f0f74312..c18f12224 100644 --- a/apps/perms/templates/perms/asset_permission_list.html +++ b/apps/perms/templates/perms/asset_permission_list.html @@ -208,7 +208,7 @@ function initTable() { select: {}, op_html: $('#actions').html() }; - table = jumpserver.initServerSideDataTable(options); + table = jumpserver.initDataTable(options); return table } From 72517a2c724388d0244196e074c34d7e51571564 Mon Sep 17 00:00:00 2001 From: ycfuck Date: Tue, 10 Jul 2018 16:33:28 +0800 Subject: [PATCH 07/26] =?UTF-8?q?=E6=8E=88=E6=9D=83=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=88=86=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 授权页面分页 --- apps/perms/api.py | 4 ++++ apps/perms/templates/perms/asset_permission_list.html | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/perms/api.py b/apps/perms/api.py index 33a027064..d9863d2a2 100644 --- a/apps/perms/api.py +++ b/apps/perms/api.py @@ -5,6 +5,7 @@ from django.shortcuts import get_object_or_404 from rest_framework.views import APIView, Response from rest_framework.generics import ListAPIView, get_object_or_404, RetrieveUpdateAPIView from rest_framework import viewsets +from rest_framework.pagination import LimitOffsetPagination from common.utils import set_or_append_attr_bulk, get_object_or_none from users.permissions import IsValidUser, IsSuperUser, IsSuperUserOrAppUser @@ -19,9 +20,12 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): """ 资产授权列表的增删改查api """ + filter_fields = ("name",) + search_fields = filter_fields queryset = AssetPermission.objects.all() serializer_class = serializers.AssetPermissionCreateUpdateSerializer permission_classes = (IsSuperUser,) + pagination_class = LimitOffsetPagination def get_serializer_class(self): if self.action in ("list", 'retrieve'): diff --git a/apps/perms/templates/perms/asset_permission_list.html b/apps/perms/templates/perms/asset_permission_list.html index c18f12224..2f0f74312 100644 --- a/apps/perms/templates/perms/asset_permission_list.html +++ b/apps/perms/templates/perms/asset_permission_list.html @@ -208,7 +208,7 @@ function initTable() { select: {}, op_html: $('#actions').html() }; - table = jumpserver.initDataTable(options); + table = jumpserver.initServerSideDataTable(options); return table } From fd3df81a64dd2e51d942ba1517df675667b9a840 Mon Sep 17 00:00:00 2001 From: wstart <371475305@qq.com> Date: Tue, 10 Jul 2018 17:03:31 +0800 Subject: [PATCH 08/26] Update api.py --- apps/perms/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/perms/api.py b/apps/perms/api.py index d9863d2a2..d990d4db4 100644 --- a/apps/perms/api.py +++ b/apps/perms/api.py @@ -25,7 +25,7 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): queryset = AssetPermission.objects.all() serializer_class = serializers.AssetPermissionCreateUpdateSerializer permission_classes = (IsSuperUser,) - pagination_class = LimitOffsetPagination + pagination_class = LimitOffsetPagination def get_serializer_class(self): if self.action in ("list", 'retrieve'): From d3e22a2a90cdfe6a9f971fda0d4d5d83716d28ad Mon Sep 17 00:00:00 2001 From: wojiushixiaobai <296015668@qq.com> Date: Thu, 12 Jul 2018 10:53:39 +0800 Subject: [PATCH 09/26] =?UTF-8?q?=E4=BF=AE=E6=94=B9url=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index df8324761..f0bceec9b 100644 --- a/README.md +++ b/README.md @@ -19,25 +19,25 @@ Jumpserver采纳分布式架构,支持多机房跨区域部署,中心节点 ---- ### 功能 - + ![Jumpserver功能](https://jumpserver-release.oss-cn-hangzhou.aliyuncs.com/Jumpserver13.jpg "Jumpserver功能") ### 开始使用 -快速开始文档 [Docker安装](http://docs.jumpserver.org/zh/latest/quickstart.html) +快速开始文档 [Docker安装](http://docs.jumpserver.org/zh/docs/dockerinstall.html) -一步一步安装文档 [详细部署](http://docs.jumpserver.org/zh/latest/step_by_step.html) +一步一步安装文档 [详细部署](http://docs.jumpserver.org/zh/docs/step_by_step.html) 也可以查看我们完整文档包括了使用和开发 [文档](http://docs.jumpserver.org) -### Demo 和 截图 +### Demo 和 截图 我们提供了DEMO和截图可以让你快速了解Jumpserver [DEMO](http://demo.jumpserver.org) [截图](http://docs.jumpserver.org/zh/docs/snapshot.html) -### SDK +### SDK 我们还编写了一些SDK,供你其它系统快速和Jumpserver APi交互, From 9004351ad1f430a9a69e044bc2c5acf9744ea7d3 Mon Sep 17 00:00:00 2001 From: wojiushixiaobai <296015668@qq.com> Date: Thu, 12 Jul 2018 16:47:35 +0800 Subject: [PATCH 10/26] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/make_migrations.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/make_migrations.sh b/utils/make_migrations.sh index fbe3e577c..4fb8fdacf 100755 --- a/utils/make_migrations.sh +++ b/utils/make_migrations.sh @@ -5,4 +5,4 @@ python3 ../apps/manage.py makemigrations python3 ../apps/manage.py migrate -python3 ../apps/manage.py makemigrations –-merge +python3 ../apps/manage.py makemigrations --merge From 1182313c1a6bee4d36edaf9165c56101e2b6448e Mon Sep 17 00:00:00 2001 From: BaiJiangJie Date: Fri, 13 Jul 2018 19:30:48 +0800 Subject: [PATCH 11/26] =?UTF-8?q?[Update]=20=E5=8F=96=E6=B6=88=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=94=A8=E6=88=B7-=E6=B8=85=E9=99=A4=E8=AE=A4?= =?UTF-8?q?=E8=AF=81=E4=BF=A1=E6=81=AF=EF=BC=8C=E5=8F=96=E6=B6=88-?= =?UTF-8?q?=E7=BD=91=E5=85=B3rdp=E5=8D=8F=E8=AE=AE=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=EF=BC=8C=E6=B7=BB=E5=8A=A0=E7=94=A8=E6=88=B7?= =?UTF-8?q?unblock=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assets/gateway_create_update.html | 15 ++- .../templates/assets/system_user_detail.html | 17 ++- apps/i18n/zh/LC_MESSAGES/django.mo | Bin 36764 -> 36926 bytes apps/i18n/zh/LC_MESSAGES/django.po | 103 ++++++++++-------- apps/users/api.py | 15 ++- apps/users/templates/users/user_detail.html | 35 ++++++ apps/users/urls/api_urls.py | 2 + apps/users/views/login.py | 4 +- 8 files changed, 133 insertions(+), 58 deletions(-) diff --git a/apps/assets/templates/assets/gateway_create_update.html b/apps/assets/templates/assets/gateway_create_update.html index 7c1bf14b2..fea540385 100644 --- a/apps/assets/templates/assets/gateway_create_update.html +++ b/apps/assets/templates/assets/gateway_create_update.html @@ -42,7 +42,7 @@ {% bootstrap_field form.domain layout="horizontal" %} {% block auth %} -

{% trans 'Auth' %}

+

{% trans 'Auth' %}

{% bootstrap_field form.username layout="horizontal" %} {% bootstrap_field form.password layout="horizontal" %} @@ -72,14 +72,23 @@ var protocol_id = '#' + '{{ form.protocol.id_for_label }}'; var private_key_id = '#' + '{{ form.private_key_file.id_for_label }}'; var port = '#' + '{{ form.port.id_for_label }}'; +var username = '#' + '{{ form.username.id_for_label }}'; +var password = '#' + '{{ form.password.id_for_label }}'; +var auth_title = '#auth_title'; function protocolChange() { if ($(protocol_id + " option:selected").text() === 'rdp') { {#$(port).val(3389);#} - $(private_key_id).closest('.form-group').addClass('hidden') + $(private_key_id).closest('.form-group').addClass('hidden'); + $(username).closest('.form-group').addClass('hidden'); + $(password).closest('.form-group').addClass('hidden'); + $(auth_title).addClass('hidden'); } else { {#$(port).val(22);#} - $(private_key_id).closest('.form-group').removeClass('hidden') + $(private_key_id).closest('.form-group').removeClass('hidden'); + $(username).closest('.form-group').removeClass('hidden'); + $(password).closest('.form-group').removeClass('hidden'); + $(auth_title).removeClass('hidden'); } } diff --git a/apps/assets/templates/assets/system_user_detail.html b/apps/assets/templates/assets/system_user_detail.html index f0ed6030c..dd188bdab 100644 --- a/apps/assets/templates/assets/system_user_detail.html +++ b/apps/assets/templates/assets/system_user_detail.html @@ -152,15 +152,14 @@ - - - {% trans 'Clear auth' %}: - - - - - - +{# #} +{# {% trans 'Clear auth' %}:#} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} {# #} {# {% trans 'Change auth period' %}:#} diff --git a/apps/i18n/zh/LC_MESSAGES/django.mo b/apps/i18n/zh/LC_MESSAGES/django.mo index 78d56177ea093bf518cc027eff07aab406c1a7c5..182ca35ceb4330dca81cc003be9451c796084219 100644 GIT binary patch delta 10828 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 delta 10638 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 v<(|U)q{>Uf2L=T\n" "Language-Team: Jumpserver team\n" @@ -32,7 +32,7 @@ msgstr "" #: assets/forms/asset.py:24 assets/models/asset.py:89 assets/models/user.py:112 #: assets/templates/assets/asset_detail.html:183 #: assets/templates/assets/asset_detail.html:191 -#: assets/templates/assets/system_user_detail.html:179 perms/models.py:33 +#: assets/templates/assets/system_user_detail.html:178 perms/models.py:33 msgid "Nodes" msgstr "节点管理" @@ -101,7 +101,7 @@ msgstr "端口" #: assets/forms/domain.py:14 assets/forms/label.py:13 #: assets/models/asset.py:237 assets/templates/assets/admin_user_list.html:25 #: assets/templates/assets/domain_detail.html:60 -#: assets/templates/assets/domain_list.html:15 +#: assets/templates/assets/domain_list.html:23 #: assets/templates/assets/label_list.html:16 #: assets/templates/assets/system_user_list.html:30 audits/models.py:11 #: audits/templates/audits/ftp_log_list.html:41 @@ -125,7 +125,7 @@ msgstr "资产" #: assets/templates/assets/admin_user_list.html:23 #: assets/templates/assets/domain_detail.html:56 #: assets/templates/assets/domain_gateway_list.html:56 -#: assets/templates/assets/domain_list.html:14 +#: assets/templates/assets/domain_list.html:22 #: assets/templates/assets/label_list.html:14 #: assets/templates/assets/system_user_detail.html:58 #: assets/templates/assets/system_user_list.html:26 common/models.py:26 @@ -356,7 +356,7 @@ msgstr "创建日期" #: assets/templates/assets/asset_detail.html:125 #: assets/templates/assets/domain_detail.html:76 #: assets/templates/assets/domain_gateway_list.html:61 -#: assets/templates/assets/domain_list.html:17 +#: assets/templates/assets/domain_list.html:25 #: assets/templates/assets/system_user_detail.html:104 #: assets/templates/assets/system_user_list.html:34 common/models.py:30 #: ops/models/adhoc.py:42 perms/models.py:40 perms/models.py:83 @@ -756,7 +756,7 @@ msgstr "测试" #: assets/templates/assets/domain_detail.html:24 #: assets/templates/assets/domain_detail.html:103 #: assets/templates/assets/domain_gateway_list.html:85 -#: assets/templates/assets/domain_list.html:42 +#: assets/templates/assets/domain_list.html:50 #: assets/templates/assets/label_list.html:38 #: assets/templates/assets/system_user_detail.html:26 #: assets/templates/assets/system_user_list.html:89 @@ -780,7 +780,7 @@ msgstr "更新" #: assets/templates/assets/domain_detail.html:28 #: assets/templates/assets/domain_detail.html:104 #: assets/templates/assets/domain_gateway_list.html:86 -#: assets/templates/assets/domain_list.html:43 +#: assets/templates/assets/domain_list.html:51 #: assets/templates/assets/label_list.html:39 #: assets/templates/assets/system_user_detail.html:30 #: assets/templates/assets/system_user_list.html:90 @@ -808,12 +808,13 @@ msgstr "选择节点" #: assets/templates/assets/admin_user_detail.html:100 #: assets/templates/assets/asset_detail.html:200 #: assets/templates/assets/asset_list.html:638 -#: assets/templates/assets/system_user_detail.html:196 +#: assets/templates/assets/system_user_detail.html:195 #: assets/templates/assets/system_user_list.html:139 templates/_modal.html:22 #: terminal/templates/terminal/session_detail.html:108 -#: users/templates/users/user_detail.html:366 -#: users/templates/users/user_detail.html:391 -#: users/templates/users/user_detail.html:414 +#: users/templates/users/user_detail.html:374 +#: users/templates/users/user_detail.html:399 +#: users/templates/users/user_detail.html:422 +#: users/templates/users/user_detail.html:458 #: users/templates/users/user_group_create_update.html:32 #: users/templates/users/user_group_list.html:86 #: users/templates/users/user_list.html:200 @@ -841,7 +842,7 @@ msgstr "比例" #: assets/templates/assets/admin_user_list.html:30 #: assets/templates/assets/asset_list.html:91 #: assets/templates/assets/domain_gateway_list.html:62 -#: assets/templates/assets/domain_list.html:18 +#: assets/templates/assets/domain_list.html:26 #: assets/templates/assets/label_list.html:17 #: assets/templates/assets/system_user_list.html:35 #: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64 @@ -905,8 +906,8 @@ msgid "Refresh" msgstr "刷新" #: assets/templates/assets/asset_detail.html:300 -#: users/templates/users/user_detail.html:286 -#: users/templates/users/user_detail.html:313 +#: users/templates/users/user_detail.html:294 +#: users/templates/users/user_detail.html:321 msgid "Update successfully!" msgstr "更新成功" @@ -1002,8 +1003,9 @@ msgstr "存在资产,不能删除" #: assets/templates/assets/asset_list.html:633 #: assets/templates/assets/system_user_list.html:134 -#: users/templates/users/user_detail.html:361 -#: users/templates/users/user_detail.html:386 +#: users/templates/users/user_detail.html:369 +#: users/templates/users/user_detail.html:394 +#: users/templates/users/user_detail.html:453 #: users/templates/users/user_group_list.html:81 #: users/templates/users/user_list.html:195 msgid "Are you sure?" @@ -1043,7 +1045,7 @@ msgstr "您确定删除吗?" #: assets/templates/assets/domain_detail.html:21 #: assets/templates/assets/domain_detail.html:64 #: assets/templates/assets/domain_gateway_list.html:21 -#: assets/templates/assets/domain_list.html:16 +#: assets/templates/assets/domain_list.html:24 msgid "Gateway" msgstr "网关" @@ -1063,7 +1065,7 @@ msgstr "创建网关" msgid "Test connection" msgstr "测试连接" -#: assets/templates/assets/domain_list.html:6 assets/views/domain.py:46 +#: assets/templates/assets/domain_list.html:14 assets/views/domain.py:46 msgid "Create domain" msgstr "创建网域" @@ -1106,20 +1108,15 @@ msgstr "家目录" msgid "Uid" msgstr "Uid" -#: assets/templates/assets/system_user_detail.html:157 -#: assets/templates/assets/system_user_detail.html:343 -msgid "Clear auth" -msgstr "清除认证信息" - -#: assets/templates/assets/system_user_detail.html:160 -msgid "Clear" -msgstr "清除" - -#: assets/templates/assets/system_user_detail.html:187 +#: assets/templates/assets/system_user_detail.html:186 msgid "Add to node" msgstr "添加到节点" -#: assets/templates/assets/system_user_detail.html:343 +#: assets/templates/assets/system_user_detail.html:353 +msgid "Clear auth" +msgstr "清除认证信息" + +#: assets/templates/assets/system_user_detail.html:353 msgid "success" msgstr "成功" @@ -1238,6 +1235,7 @@ msgstr "文件名" #: audits/models.py:15 audits/templates/audits/ftp_log_list.html:77 #: ops/templates/ops/task_list.html:39 users/models/authentication.py:66 +#: users/templates/users/user_detail.html:443 msgid "Success" msgstr "成功" @@ -1854,7 +1852,7 @@ msgstr "选择用户" #: perms/templates/perms/asset_permission_list.html:136 templates/_nav.html:14 #: users/models/group.py:23 users/models/user.py:55 #: users/templates/users/_select_user_modal.html:16 -#: users/templates/users/user_detail.html:192 +#: users/templates/users/user_detail.html:200 #: users/templates/users/user_list.html:26 msgid "User group" msgstr "用户组" @@ -1907,7 +1905,7 @@ msgid "Add node to this permission" msgstr "添加节点" #: perms/templates/perms/asset_permission_asset.html:125 -#: users/templates/users/user_detail.html:209 +#: users/templates/users/user_detail.html:217 msgid "Join" msgstr "加入" @@ -2326,7 +2324,7 @@ msgid "" "You should use your ssh client tools connect terminal: {}

{}" msgstr "你可以使用ssh客户端工具连接终端" -#: users/api.py:208 users/templates/users/login.html:50 +#: users/api.py:221 users/templates/users/login.html:50 msgid "Log in frequently and try again later" msgstr "登录频繁, 稍后重试" @@ -2405,7 +2403,7 @@ msgstr "" msgid "Paste user id_rsa.pub here." msgstr "复制用户公钥到这里" -#: users/forms.py:73 users/templates/users/user_detail.html:200 +#: users/forms.py:73 users/templates/users/user_detail.html:208 msgid "Join user groups" msgstr "添加到用户组" @@ -2701,7 +2699,7 @@ msgid "Can't provide security? Please contact the administrator!" msgstr "如果不能提供MFA验证码,请联系管理员!" #: users/templates/users/reset_password.html:46 -#: users/templates/users/user_detail.html:352 users/utils.py:80 +#: users/templates/users/user_detail.html:360 users/utils.py:80 msgid "Reset password" msgstr "重置密码" @@ -2773,44 +2771,57 @@ msgstr "发送" msgid "Send reset ssh key mail" msgstr "发送重置密钥邮件" -#: users/templates/users/user_detail.html:295 +#: users/templates/users/user_detail.html:186 +#: users/templates/users/user_detail.html:444 +msgid "Unblock user" +msgstr "解锁用户" + +#: users/templates/users/user_detail.html:189 +msgid "Unblock" +msgstr "解锁" + +#: users/templates/users/user_detail.html:303 msgid "Goto profile page enable MFA" msgstr "请去个人信息页面启用自己的MFA" -#: users/templates/users/user_detail.html:351 +#: users/templates/users/user_detail.html:359 msgid "An e-mail has been sent to the user`s mailbox." msgstr "已发送邮件到用户邮箱" -#: users/templates/users/user_detail.html:362 +#: users/templates/users/user_detail.html:370 msgid "This will reset the user password and send a reset mail" msgstr "将失效用户当前密码,并发送重设密码邮件到用户邮箱" -#: users/templates/users/user_detail.html:376 +#: users/templates/users/user_detail.html:384 msgid "" "The reset-ssh-public-key E-mail has been sent successfully. Please inform " "the user to update his new ssh public key." msgstr "重设密钥邮件将会发送到用户邮箱" -#: users/templates/users/user_detail.html:377 +#: users/templates/users/user_detail.html:385 msgid "Reset SSH public key" msgstr "重置SSH密钥" -#: users/templates/users/user_detail.html:387 +#: users/templates/users/user_detail.html:395 msgid "This will reset the user public key and send a reset mail" msgstr "将会失效用户当前密钥,并发送重置邮件到用户邮箱" -#: users/templates/users/user_detail.html:404 +#: users/templates/users/user_detail.html:412 #: users/templates/users/user_profile.html:211 msgid "Successfully updated the SSH public key." msgstr "更新ssh密钥成功" -#: users/templates/users/user_detail.html:405 -#: users/templates/users/user_detail.html:409 +#: users/templates/users/user_detail.html:413 +#: users/templates/users/user_detail.html:417 #: users/templates/users/user_profile.html:212 #: users/templates/users/user_profile.html:217 msgid "User SSH public key update" msgstr "ssh密钥" +#: users/templates/users/user_detail.html:454 +msgid "After unlocking the user, the user can log in normally." +msgstr "解锁用户后,此用户即可正常登录" + #: users/templates/users/user_group_create_update.html:31 msgid "Cancel" msgstr "取消" @@ -3169,5 +3180,11 @@ msgstr "MFA 解绑成功" msgid "MFA disable success, return login page" msgstr "MFA 解绑成功,返回登录页面" +#~ msgid "Unblock user successfully. " +#~ msgstr "解锁用户成功" + +#~ msgid "Clear" +#~ msgstr "清除" + #~ msgid "MFA setting" #~ msgstr "MFA 设置" diff --git a/apps/users/api.py b/apps/users/api.py index c23112384..a3a613622 100644 --- a/apps/users/api.py +++ b/apps/users/api.py @@ -95,6 +95,19 @@ class UserUpdatePKApi(generics.UpdateAPIView): user.save() +class UserUnblockPKApi(generics.UpdateAPIView): + queryset = User.objects.all() + permission_classes = (IsSuperUser,) + serializer_class = UserSerializer + key_prefix_limit = "_LOGIN_LIMIT_{}_{}" + + def perform_update(self, serializer): + user = self.get_object() + username = user.username if user else '' + key_limit = self.key_prefix_limit.format(username, '*') + cache.delete_pattern(key_limit) + + class UserGroupViewSet(IDInFilterMixin, BulkModelViewSet): queryset = UserGroup.objects.all() serializer_class = UserGroupSerializer @@ -203,7 +216,7 @@ class UserAuthApi(APIView): username = request.data.get('username') ip = request.data.get('remote_addr', None) ip = ip if ip else get_login_ip(request) - key_limit = self.key_prefix_limit.format(ip, username) + key_limit = self.key_prefix_limit.format(username, ip) if is_block_login(key_limit): msg = _("Log in frequently and try again later") return Response({'msg': msg}, status=401) diff --git a/apps/users/templates/users/user_detail.html b/apps/users/templates/users/user_detail.html index d40251563..0182cf521 100644 --- a/apps/users/templates/users/user_detail.html +++ b/apps/users/templates/users/user_detail.html @@ -182,6 +182,14 @@ + + {% trans 'Unblock user' %} + + + + + +
@@ -426,6 +434,33 @@ $(document).ready(function() { var the_url = '{% url "api-users:user-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', uid); var redirect_url = "{% url 'users:user-list' %}"; objectDelete($this, name, the_url, redirect_url); +}).on('click', '#btn-unblock-user', function () { + function doReset() { + {#var the_url = '{% url "api-users:user-reset-password" pk=user_object.id %}';#} + var the_url = '{% url "api-users:user-unblock" pk=user_object.id %}'; + var body = {}; + var success = function() { + var msg = "{% trans "Success" %}"; + swal("{% trans 'Unblock user' %}", msg, "success"); + }; + APIUpdateAttr({ + url: the_url, + body: JSON.stringify(body), + success: success + }); + } + swal({ + title: "{% trans 'Are you sure?' %}", + text: "{% trans "After unlocking the user, the user can log in normally."%}", + type: "warning", + showCancelButton: true, + confirmButtonColor: "#DD6B55", + confirmButtonText: "{% trans 'Confirm' %}", + closeOnConfirm: false + }, function() { + doReset(); + }); + }) {% endblock %} diff --git a/apps/users/urls/api_urls.py b/apps/users/urls/api_urls.py index 683638a4e..017224421 100644 --- a/apps/users/urls/api_urls.py +++ b/apps/users/urls/api_urls.py @@ -29,6 +29,8 @@ urlpatterns = [ api.UserResetPKApi.as_view(), name='user-public-key-reset'), url(r'^v1/users/(?P[0-9a-zA-Z\-]{36})/pubkey/update/$', api.UserUpdatePKApi.as_view(), name='user-public-key-update'), + url(r'^v1/users/(?P[0-9a-zA-Z\-]{36})/unblock/$', + api.UserUnblockPKApi.as_view(), name='user-unblock'), url(r'^v1/users/(?P[0-9a-zA-Z\-]{36})/groups/$', api.UserUpdateGroupApi.as_view(), name='user-update-group'), url(r'^v1/groups/(?P[0-9a-zA-Z\-]{36})/users/$', diff --git a/apps/users/views/login.py b/apps/users/views/login.py index 94071924f..2b86df19a 100644 --- a/apps/users/views/login.py +++ b/apps/users/views/login.py @@ -64,7 +64,7 @@ class UserLoginView(FormView): # limit login authentication ip = get_login_ip(request) username = self.request.POST.get('username') - key_limit = self.key_prefix_limit.format(ip, username) + key_limit = self.key_prefix_limit.format(username, ip) if is_block_login(key_limit): return self.render_to_response(self.get_context_data(block_login=True)) @@ -90,7 +90,7 @@ class UserLoginView(FormView): # limit user login failed count ip = get_login_ip(self.request) - key_limit = self.key_prefix_limit.format(ip, username) + key_limit = self.key_prefix_limit.format(username, ip) set_user_login_failed_count_to_cache(key_limit) # show captcha From 696589a3cfc24464fdb08bce36355ed2ae89be3e Mon Sep 17 00:00:00 2001 From: wojiushixiaobai <296015668@qq.com> Date: Mon, 16 Jul 2018 12:13:06 +0800 Subject: [PATCH 12/26] =?UTF-8?q?=E4=BF=AE=E6=94=B9url?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/urls/views_urls.py | 1 - apps/perms/urls/views_urls.py | 16 ++++++-------- apps/users/urls/views_urls.py | 40 +++++++++++++++++----------------- 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/apps/assets/urls/views_urls.py b/apps/assets/urls/views_urls.py index 418aa63a3..12c351154 100644 --- a/apps/assets/urls/views_urls.py +++ b/apps/assets/urls/views_urls.py @@ -50,4 +50,3 @@ urlpatterns = [ url(r'^domain/(?P[0-9a-zA-Z\-]{36})/gateway/create/$', views.DomainGatewayCreateView.as_view(), name='domain-gateway-create'), url(r'^domain/gateway/(?P[0-9a-zA-Z\-]{36})/update/$', views.DomainGatewayUpdateView.as_view(), name='domain-gateway-update'), ] - diff --git a/apps/perms/urls/views_urls.py b/apps/perms/urls/views_urls.py index 5c3fa3b48..a3cf7ff42 100644 --- a/apps/perms/urls/views_urls.py +++ b/apps/perms/urls/views_urls.py @@ -6,13 +6,11 @@ from .. import views app_name = 'perms' urlpatterns = [ - url(r'^asset-permission$', views.AssetPermissionListView.as_view(), name='asset-permission-list'), - url(r'^asset-permission/create$', views.AssetPermissionCreateView.as_view(), name='asset-permission-create'), - url(r'^asset-permission/(?P[0-9a-zA-Z\-]{36})/update$', views.AssetPermissionUpdateView.as_view(), name='asset-permission-update'), - url(r'^asset-permission/(?P[0-9a-zA-Z\-]{36})$', views.AssetPermissionDetailView.as_view(),name='asset-permission-detail'), - url(r'^asset-permission/(?P[0-9a-zA-Z\-]{36})/delete$', views.AssetPermissionDeleteView.as_view(), name='asset-permission-delete'), - url(r'^asset-permission/(?P[0-9a-zA-Z\-]{36})/user$', views.AssetPermissionUserView.as_view(), name='asset-permission-user-list'), - url(r'^asset-permission/(?P[0-9a-zA-Z\-]{36})/asset$', views.AssetPermissionAssetView.as_view(), name='asset-permission-asset-list'), + url(r'^asset-permission/$', views.AssetPermissionListView.as_view(), name='asset-permission-list'), + url(r'^asset-permission/create/$', views.AssetPermissionCreateView.as_view(), name='asset-permission-create'), + url(r'^asset-permission/(?P[0-9a-zA-Z\-]{36})/update/$', views.AssetPermissionUpdateView.as_view(), name='asset-permission-update'), + url(r'^asset-permission/(?P[0-9a-zA-Z\-]{36})/$', views.AssetPermissionDetailView.as_view(),name='asset-permission-detail'), + url(r'^asset-permission/(?P[0-9a-zA-Z\-]{36})/delete/$', views.AssetPermissionDeleteView.as_view(), name='asset-permission-delete'), + url(r'^asset-permission/(?P[0-9a-zA-Z\-]{36})/user/$', views.AssetPermissionUserView.as_view(), name='asset-permission-user-list'), + url(r'^asset-permission/(?P[0-9a-zA-Z\-]{36})/asset/$', views.AssetPermissionAssetView.as_view(), name='asset-permission-asset-list'), ] - - diff --git a/apps/users/urls/views_urls.py b/apps/users/urls/views_urls.py index 2aaf4a9ae..8052f1384 100644 --- a/apps/users/urls/views_urls.py +++ b/apps/users/urls/views_urls.py @@ -8,13 +8,13 @@ app_name = 'users' urlpatterns = [ # Login view - url(r'^login$', views.UserLoginView.as_view(), name='login'), - url(r'^logout$', views.UserLogoutView.as_view(), name='logout'), - url(r'^login/otp$', views.UserLoginOtpView.as_view(), name='login-otp'), - url(r'^password/forgot$', views.UserForgotPasswordView.as_view(), name='forgot-password'), - url(r'^password/forgot/sendmail-success$', views.UserForgotPasswordSendmailSuccessView.as_view(), name='forgot-password-sendmail-success'), - url(r'^password/reset$', views.UserResetPasswordView.as_view(), name='reset-password'), - url(r'^password/reset/success$', views.UserResetPasswordSuccessView.as_view(), name='reset-password-success'), + url(r'^login/$', views.UserLoginView.as_view(), name='login'), + url(r'^logout/$', views.UserLogoutView.as_view(), name='logout'), + url(r'^login/otp/$', views.UserLoginOtpView.as_view(), name='login-otp'), + url(r'^password/forgot/$', views.UserForgotPasswordView.as_view(), name='forgot-password'), + url(r'^password/forgot/sendmail-success/$', views.UserForgotPasswordSendmailSuccessView.as_view(), name='forgot-password-sendmail-success'), + url(r'^password/reset/$', views.UserResetPasswordView.as_view(), name='reset-password'), + url(r'^password/reset/success/$', views.UserResetPasswordSuccessView.as_view(), name='reset-password-success'), # Profile url(r'^profile/$', views.UserProfileView.as_view(), name='user-profile'), @@ -29,23 +29,23 @@ urlpatterns = [ url(r'^profile/otp/settings-success/$', views.UserOtpSettingsSuccessView.as_view(), name='user-otp-settings-success'), # User view - url(r'^user$', views.UserListView.as_view(), name='user-list'), - url(r'^user/export/', views.UserExportView.as_view(), name='user-export'), + url(r'^user/$', views.UserListView.as_view(), name='user-list'), + url(r'^user/export/$', views.UserExportView.as_view(), name='user-export'), url(r'^first-login/$', views.UserFirstLoginView.as_view(), name='user-first-login'), url(r'^user/import/$', views.UserBulkImportView.as_view(), name='user-import'), - url(r'^user/create$', views.UserCreateView.as_view(), name='user-create'), - url(r'^user/(?P[0-9a-zA-Z\-]{36})/update$', views.UserUpdateView.as_view(), name='user-update'), - url(r'^user/update$', views.UserBulkUpdateView.as_view(), name='user-bulk-update'), - url(r'^user/(?P[0-9a-zA-Z\-]{36})$', views.UserDetailView.as_view(), name='user-detail'), - url(r'^user/(?P[0-9a-zA-Z\-]{36})/assets', views.UserGrantedAssetView.as_view(), name='user-granted-asset'), - url(r'^user/(?P[0-9a-zA-Z\-]{36})/login-history', views.UserDetailView.as_view(), name='user-login-history'), + url(r'^user/create/$', views.UserCreateView.as_view(), name='user-create'), + url(r'^user/(?P[0-9a-zA-Z\-]{36})/update/$', views.UserUpdateView.as_view(), name='user-update'), + url(r'^user/update/$', views.UserBulkUpdateView.as_view(), name='user-bulk-update'), + url(r'^user/(?P[0-9a-zA-Z\-]{36})/$', views.UserDetailView.as_view(), name='user-detail'), + url(r'^user/(?P[0-9a-zA-Z\-]{36})/assets/$', views.UserGrantedAssetView.as_view(), name='user-granted-asset'), + url(r'^user/(?P[0-9a-zA-Z\-]{36})/login-history/$', views.UserDetailView.as_view(), name='user-login-history'), # User group view - url(r'^user-group$', views.UserGroupListView.as_view(), name='user-group-list'), - url(r'^user-group/(?P[0-9a-zA-Z\-]{36})$', views.UserGroupDetailView.as_view(), name='user-group-detail'), - url(r'^user-group/create$', views.UserGroupCreateView.as_view(), name='user-group-create'), - url(r'^user-group/(?P[0-9a-zA-Z\-]{36})/update$', views.UserGroupUpdateView.as_view(), name='user-group-update'), - url(r'^user-group/(?P[0-9a-zA-Z\-]{36})/assets', views.UserGroupGrantedAssetView.as_view(), name='user-group-granted-asset'), + url(r'^user-group/$', views.UserGroupListView.as_view(), name='user-group-list'), + url(r'^user-group/(?P[0-9a-zA-Z\-]{36})/$', views.UserGroupDetailView.as_view(), name='user-group-detail'), + url(r'^user-group/create/$', views.UserGroupCreateView.as_view(), name='user-group-create'), + url(r'^user-group/(?P[0-9a-zA-Z\-]{36})/update/$', views.UserGroupUpdateView.as_view(), name='user-group-update'), + url(r'^user-group/(?P[0-9a-zA-Z\-]{36})/assets/$', views.UserGroupGrantedAssetView.as_view(), name='user-group-granted-asset'), # Login log url(r'^login-log/$', views.LoginLogListView.as_view(), name='login-log-list'), From 812078331e75a2efe5bcec95ae4334c494ba6255 Mon Sep 17 00:00:00 2001 From: BaiJiangJie Date: Mon, 16 Jul 2018 12:13:13 +0800 Subject: [PATCH 13/26] =?UTF-8?q?[Update]=20=E6=B7=BB=E5=8A=A0=E8=A7=A3?= =?UTF-8?q?=E9=99=A4=E7=94=A8=E6=88=B7=E7=99=BB=E5=BD=95=E9=99=90=E5=88=B6?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/i18n/zh/LC_MESSAGES/django.mo | Bin 36926 -> 36944 bytes apps/i18n/zh/LC_MESSAGES/django.po | 8 ++++---- apps/users/api.py | 7 ++++++- apps/users/templates/users/user_detail.html | 17 ++++++++++++----- apps/users/utils.py | 17 ++++++++++++++++- apps/users/views/login.py | 4 +++- apps/users/views/user.py | 10 ++++++++-- 7 files changed, 49 insertions(+), 14 deletions(-) diff --git a/apps/i18n/zh/LC_MESSAGES/django.mo b/apps/i18n/zh/LC_MESSAGES/django.mo index 182ca35ceb4330dca81cc003be9451c796084219..50e22bf55f237bf8d2d1e9ddf1c548523ff9daf9 100644 GIT binary patch delta 4306 zcmYk;dvwor9LMo*yX7)A!;TWUEy<;noESBCDW{Z{ZmQ#6Q!djee91N|bIGw~6)74W zX{$+{h1y9smFOTH$w?-3RYo_f=WE~BAN}?CzTcnE=lywqKKp)uY+nsu14y!$W61CA;RO1aE3W8W{k2-lr+dcF{x*det_$KUu znT{8Ed^ze$pL6~d>`7eV_#|rMQ;y>v_Mgh8AVa|gsCi)l4?5Aab_1$`H|$pXp2v6E zFENREM^Ps_ZEI2M>rII^NV4rv`&{j~Ke8?iZu7vsHp|XJb(n8U>?(crztC}+-GWWX zZ^KY;|K~iY&?!%-#bo06>Cx4uqBd@Wn%B{B51WoE*dO($80q|I)ckRng3~;n=kcY} z`TMJIu@kFM3)b1!>~{MJ>ZAu8A4jdPar}?t`q_N@ z1tj!KScG*qg6jAbYCLX6bh0M4C907$RN<>p8}&hb??W&K@3UjD8}WEsgc-y;LO;Ym z!mkpE!8jfZQH6g;HSm|?^K*F7h#RBEH`p@lN4&-HANF5VqX{#k1Er$Ybwbq*ukb@( z4-9iW!trR-O^idGaHd`0@g=B2MfOEoX18Js#y>`Fe8lkyWL+4<%!(!?p*Fe{FT`}z zf=tu~_t*zeKe;)M=h?;f8N1$YM%ArCy%T#;KgIuIGW!Ryk4A5MGt}FghWf5AM=k8@ z@tZM?_O^;-u6mmD`OX(( zbMj@*zmIBUAF6>Pw$}Lz=W_q*yyM(xVmDNQbjKsGHSuWF@4_6^{O7Um>TS8Lv^!86 z??N5mAZp#usF$|}wZ1mwK@;oINNdy!p}2<|>xU{Z)cL#YM32uv6`JihA9X{E9haik zZ$j07*ZIS!eZpgY_#Jh{!Mw<1RG~Jg&U@hk%s?&NVfUcMzd^09#-3P%n%8B1)IcxP z=XWEjZVs|843=ii=ig$=0P1DLd9oL1!D6e z8`vhO@fN7BBn{&*-T4gEy5Xps8|nN6RQ+tniyc3c$Ng(!1qu0q{mK)6w11-hCzFsL zy+qwmjoe|!+v(Vt{5;g3WGN=#^R^VVZj-Il=c2@iPVDu>Zyg`EHQ1JUF$<%D9Z)Cg zj9Nbsb$}75U(&I7G0s4Jc173@H>19eFR?2&4hy1Rraq{GqfmvWqE3*Dskj1%;zk^V zr%`Wr?Lo5%=Jy48lU==pRa;%SA zJ^lfzvCr%w`x9#2IaDLbi=uh0Q2DN?e1;t!83uPcF~Mfr`PhjCOB}z2D)heN1GXB~ z&~K(&LV$|1Ds#xFuRvt9*Q&i#o_B&LeUr`&xE{VpQqT)8FLRUB* zY%@{y#$zj-f~va&Rqt8U`d2a3#O*xj9ry_A8bMv%e$>K4_N4P?Z7phk{L*NC5_Tp| z#je;N_0R4URGmUwf_gbim-4l$z;(-_0@qi3+`fEBvyye+uh?*`;LYz#-mczObfRQg eb-|X3`42X_xOvIC;Q0ErCz$a6p;b@55dR-#B4M-u delta 4288 zcmX}udvwor9LMo*yG1sWOIgbl5o)H+qIGw&NIIRQGfIv+-A5&>wpo2Gj4ea#bdicP zp&e(*tdvqmbU5lDCr2gSj+m~d+$!t&+UHe&JwEUE=ks}gF2C>hyKP^buzqpEs?n#JD~zHPti>#>!&KaYop2YX;X%~6W46VnObFxC>{<4FOlN$q;~|c3#W%kp%xtEc(^S<6}a1Rq2ppqBOjwSQtkZ9sD+l= zH=SQ^H`z}xo%N%gPW*tHc+eijOyZkw8>%N&Zu#jj{DdgRKbC$@xz=Si5fo!JL0|WFLD30 z$^8C0QI!+Vq9(jxU$d+22dI;N;&=~gev{+h9sh&<$R`!CdCWnLy9{-sgHf;f9Yx%~ z7Azx?hn3iRBd8tkL-ij+oh+si?yHQ5*Qx@n85Nal#X!f03=l!Q|^4|7;JVHhKbepwo)Oyl$wv@p*1s zlY1?m8esApm`>Qj6eJFtFqw6#Ie((v16px*1AsEHS$ z-i9IA3vYEi1^W=sMs2VWJK+XwJ*o3wJ3eR+*<;v6?|%!8uGnQtu)iH@$Dn+zH|P7{S#xIFrh4*unQ{gjao3zUT1Hy<5A-#q8_fPs0HSs zHuOAd{u1ZwF_XB_@eaGY%*ZETCtFR0C zTIb(E)!BmDz%JYDeEX-kf9*W;sW7kysz8q8e9R&qiTW-~LXBU5tygcC+IqVdweSYi z!M361eUEy0n^5zcV;UOxH)dg5e~|ikW0#-`T;cppcC7m!Koxq#aVhGC${jC6&0m75 zzsC8UsCDBn-Pn)1;y-NC)KI81YUkNF4RcWw*V;{}{?AbJzrcamgc^5FdDuWU>h-$@ zwZTGUUK~vijp!LWA2snsy9{-L2FD+xK14h1UfX2n~f=Y{|C{~ zf>+ra>}b@&_c$)LGn}9A_%+mms~vAZ-N-i7Nq6D>_?zR=T%+=nP(OE6MMD#6P#by4 zuCR@EgWYEL*e1M^c}HyS^ic0nRJ{^R#tPKU&BhDyd5kq+BMt3n2P!^@+R#yZ(k9Oc z{i&$8BmTktp?2ZqhUb{-{fh$mN$5zb7gm_l?G7Ugo(Fjzbdr&7R#xrmh4#QV59}l3O z?*5hGgqNZ=ay9aAV>AL^!1dS}3#vl@1WX|=!DNi5(nzFH;f^X)p=YrjzJhJB&i!jp z8(U|$+OJR>{|Pn!r1R~b3HeM^zQ4UZ7)QgLxYgceAI82+D093FwLpX8kL^y>hQ38@ z^mls#b<(8S!FIMIY9krgQSX0m8Y+;7ZSZO78jJc(??S%P(PT`;X4`_ApIXho zZ+JFpqXnos52E^u>~z%IQ=?e#e;o}Cd>2)Cquqfjv=>$2kn^X^32}Q=p)AL_b_lB8 zDC~ygP<6{t^(s;I7GbP`D{1H%cne!Mg1WkmsEJ$cZs+&epHbrvJN^eRAWoVap6&st zKfB{lbxQ3_)Wcabm$y{~vgd^b2Q_TzxoT*en)3ZMD}J2yc0+YxTKDvt^60?w+NS@L JZ&WQw{uiW`Uzz{_ diff --git a/apps/i18n/zh/LC_MESSAGES/django.po b/apps/i18n/zh/LC_MESSAGES/django.po index 09b453262..9e3766748 100644 --- a/apps/i18n/zh/LC_MESSAGES/django.po +++ b/apps/i18n/zh/LC_MESSAGES/django.po @@ -2774,11 +2774,11 @@ msgstr "发送重置密钥邮件" #: users/templates/users/user_detail.html:186 #: users/templates/users/user_detail.html:444 msgid "Unblock user" -msgstr "解锁用户" +msgstr "解除登录限制" #: users/templates/users/user_detail.html:189 msgid "Unblock" -msgstr "解锁" +msgstr "解除" #: users/templates/users/user_detail.html:303 msgid "Goto profile page enable MFA" @@ -2820,7 +2820,7 @@ msgstr "ssh密钥" #: users/templates/users/user_detail.html:454 msgid "After unlocking the user, the user can log in normally." -msgstr "解锁用户后,此用户即可正常登录" +msgstr "解除用户登录限制后,此用户即可正常登录" #: users/templates/users/user_group_create_update.html:31 msgid "Cancel" @@ -3181,7 +3181,7 @@ msgid "MFA disable success, return login page" msgstr "MFA 解绑成功,返回登录页面" #~ msgid "Unblock user successfully. " -#~ msgstr "解锁用户成功" +#~ msgstr "解除登录限制成功" #~ msgid "Clear" #~ msgstr "清除" diff --git a/apps/users/api.py b/apps/users/api.py index a3a613622..840b8c913 100644 --- a/apps/users/api.py +++ b/apps/users/api.py @@ -100,12 +100,15 @@ class UserUnblockPKApi(generics.UpdateAPIView): permission_classes = (IsSuperUser,) serializer_class = UserSerializer key_prefix_limit = "_LOGIN_LIMIT_{}_{}" + key_prefix_block = "_LOGIN_BLOCK_{}" def perform_update(self, serializer): user = self.get_object() username = user.username if user else '' key_limit = self.key_prefix_limit.format(username, '*') + key_block = self.key_prefix_block.format(username) cache.delete_pattern(key_limit) + cache.delete(key_block) class UserGroupViewSet(IDInFilterMixin, BulkModelViewSet): @@ -210,6 +213,7 @@ class UserAuthApi(APIView): permission_classes = (AllowAny,) serializer_class = UserSerializer key_prefix_limit = "_LOGIN_LIMIT_{}_{}" + key_prefix_block = "_LOGIN_BLOCK_{}" def post(self, request): # limit login @@ -217,6 +221,7 @@ class UserAuthApi(APIView): ip = request.data.get('remote_addr', None) ip = ip if ip else get_login_ip(request) key_limit = self.key_prefix_limit.format(username, ip) + key_block = self.key_prefix_block.format(username) if is_block_login(key_limit): msg = _("Log in frequently and try again later") return Response({'msg': msg}, status=401) @@ -231,7 +236,7 @@ class UserAuthApi(APIView): } self.write_login_log(request, data) - set_user_login_failed_count_to_cache(key_limit) + set_user_login_failed_count_to_cache(key_limit, key_block) return Response({'msg': msg}, status=401) if not user.otp_enabled: diff --git a/apps/users/templates/users/user_detail.html b/apps/users/templates/users/user_detail.html index 0182cf521..a5adb31d2 100644 --- a/apps/users/templates/users/user_detail.html +++ b/apps/users/templates/users/user_detail.html @@ -182,7 +182,7 @@ - + {% trans 'Unblock user' %} @@ -283,7 +283,7 @@ $(document).ready(function() { .on('select2:unselect', function(evt) { var data = evt.params.data; delete jumpserver.nodes_selected[data.id]; - }) + }); }) .on('click', '#is_active', function() { var the_url = "{% url 'api-users:user-detail' pk=user_object.id %}"; @@ -301,7 +301,7 @@ $(document).ready(function() { .on('click', '#force_enable_otp', function() { {% if request.user == user_object %} toastr.error("{% trans 'Goto profile page enable MFA' %}"); - return + return; {% endif %} var the_url = "{% url 'api-users:user-detail' pk=user_object.id %}"; @@ -441,7 +441,15 @@ $(document).ready(function() { var body = {}; var success = function() { var msg = "{% trans "Success" %}"; - swal("{% trans 'Unblock user' %}", msg, "success"); + {#swal("{% trans 'Unblock user' %}", msg, "success");#} + swal({ + title: "{% trans 'Unblock user' %}", + text: msg, + type: "success" + }, function() { + location.reload() + } + ); }; APIUpdateAttr({ url: the_url, @@ -460,7 +468,6 @@ $(document).ready(function() { }, function() { doReset(); }); - }) {% endblock %} diff --git a/apps/users/utils.py b/apps/users/utils.py index 937a90867..7cbaa75f0 100644 --- a/apps/users/utils.py +++ b/apps/users/utils.py @@ -333,7 +333,7 @@ def check_password_rules(password): return bool(match_obj) -def set_user_login_failed_count_to_cache(key_limit): +def set_user_login_failed_count_to_cache(key_limit, key_block): count = cache.get(key_limit) count = count + 1 if count else 1 @@ -343,6 +343,15 @@ def set_user_login_failed_count_to_cache(key_limit): limit_time = setting_limit_time.cleaned_value if setting_limit_time \ else settings.DEFAULT_LOGIN_LIMIT_TIME + setting_limit_count = Setting.objects.filter( + name='SECURITY_LOGIN_LIMIT_COUNT' + ).first() + limit_count = setting_limit_count.cleaned_value if setting_limit_count \ + else settings.DEFAULT_LOGIN_LIMIT_COUNT + + if count >= limit_count: + cache.set(key_block, 1, int(limit_time)*60) + cache.set(key_limit, count, int(limit_time)*60) @@ -357,3 +366,9 @@ def is_block_login(key_limit): if count and count >= limit_count: return True + + +def is_need_unblock(key_block): + if not cache.get(key_block): + return False + return True diff --git a/apps/users/views/login.py b/apps/users/views/login.py index 2b86df19a..fc7caf305 100644 --- a/apps/users/views/login.py +++ b/apps/users/views/login.py @@ -51,6 +51,7 @@ class UserLoginView(FormView): redirect_field_name = 'next' key_prefix_captcha = "_LOGIN_INVALID_{}" key_prefix_limit = "_LOGIN_LIMIT_{}_{}" + key_prefix_block = "_LOGIN_BLOCK_{}" def get(self, request, *args, **kwargs): if request.user.is_staff: @@ -91,7 +92,8 @@ class UserLoginView(FormView): # limit user login failed count ip = get_login_ip(self.request) key_limit = self.key_prefix_limit.format(username, ip) - set_user_login_failed_count_to_cache(key_limit) + key_block = self.key_prefix_block.format(username) + set_user_login_failed_count_to_cache(key_limit, key_block) # show captcha cache.set(self.key_prefix_captcha.format(ip), 1, 3600) diff --git a/apps/users/views/user.py b/apps/users/views/user.py index 094d2ced2..56d551efa 100644 --- a/apps/users/views/user.py +++ b/apps/users/views/user.py @@ -36,7 +36,9 @@ from common.utils import get_logger, get_object_or_none, is_uuid, ssh_key_gen from common.models import Setting from .. import forms from ..models import User, UserGroup -from ..utils import AdminUserRequiredMixin, generate_otp_uri, check_otp_code, get_user_or_tmp_user, get_password_check_rules, check_password_rules +from ..utils import AdminUserRequiredMixin, generate_otp_uri, check_otp_code, \ + get_user_or_tmp_user, get_password_check_rules, check_password_rules, \ + is_need_unblock from ..signals import post_user_create from ..tasks import write_login_log_async @@ -168,13 +170,17 @@ class UserDetailView(AdminUserRequiredMixin, DetailView): model = User template_name = 'users/user_detail.html' context_object_name = "user_object" + key_prefix_block = "_LOGIN_BLOCK_{}" def get_context_data(self, **kwargs): + user = self.get_object() + key_block = self.key_prefix_block.format(user.username) groups = UserGroup.objects.exclude(id__in=self.object.groups.all()) context = { 'app': _('Users'), 'action': _('User detail'), - 'groups': groups + 'groups': groups, + 'unblock': is_need_unblock(key_block), } kwargs.update(context) return super().get_context_data(**kwargs) From 09e636495eca1a840b35cb72be2145e0b6995c4c Mon Sep 17 00:00:00 2001 From: BaiJiangJie Date: Mon, 16 Jul 2018 12:22:32 +0800 Subject: [PATCH 14/26] =?UTF-8?q?[Update]=20=E6=A8=A1=E7=89=88=E5=88=A0?= =?UTF-8?q?=E9=99=A4unblock=E7=9A=84id=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/users/templates/users/user_detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/users/templates/users/user_detail.html b/apps/users/templates/users/user_detail.html index a5adb31d2..b664d917f 100644 --- a/apps/users/templates/users/user_detail.html +++ b/apps/users/templates/users/user_detail.html @@ -182,7 +182,7 @@ - + {% trans 'Unblock user' %} From ff3f74abe68dd35ae43e0de18df9600d7c6cce44 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 17 Jul 2018 12:06:47 +0800 Subject: [PATCH 15/26] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/serializers/system_user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/serializers/system_user.py b/apps/assets/serializers/system_user.py index 7a4e3aadc..a295f245c 100644 --- a/apps/assets/serializers/system_user.py +++ b/apps/assets/serializers/system_user.py @@ -53,7 +53,7 @@ class SystemUserAuthSerializer(AuthSerializer): model = SystemUser fields = [ "id", "name", "username", "protocol", - "password", "private_key", + "login_mode", "password", "private_key", ] From 8883e0090fbc7317ad6647dd38e71b5941f5e75b Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 17 Jul 2018 17:12:28 +0800 Subject: [PATCH 16/26] =?UTF-8?q?[Update]=20=E6=9B=B4=E6=94=B9=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/__init__.py | 2 +- apps/templates/_footer.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/__init__.py b/apps/__init__.py index 7e96164aa..be40e1dd2 100644 --- a/apps/__init__.py +++ b/apps/__init__.py @@ -2,4 +2,4 @@ # -*- coding: utf-8 -*- # -__version__ = "1.3.2" +__version__ = "1.3.3" diff --git a/apps/templates/_footer.html b/apps/templates/_footer.html index c78f0da33..70e0c8dcd 100644 --- a/apps/templates/_footer.html +++ b/apps/templates/_footer.html @@ -1,6 +1,6 @@