From 5e89ee9202270ce162198fc1f33f8b2798f7e53f Mon Sep 17 00:00:00 2001 From: jym503558564 <503558564@qq.com> Date: Thu, 13 Feb 2020 19:58:14 +0800 Subject: [PATCH 01/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9README?= =?UTF-8?q?=E4=B8=AD=20jumpserver=20=3D=3D>=20JumpServer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 595677321..50fc97533 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,19 @@ -# Jumpserver 多云环境下更好用的堡垒机 +# 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/) -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 采纳分布式架构,支持多机房跨区域部署,支持横向扩展,无资产数量及并发限制。 +JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向扩展,无资产数量及并发限制。 改变世界,从一点点开始。 -注: [KubeOperator](https://github.com/KubeOperator/KubeOperator) 是 Jumpserver 团队在 Kubernetes 领域的的又一全新力作,欢迎关注和使用。 +注: [KubeOperator](https://github.com/KubeOperator/KubeOperator) 是 JumpServer 团队在 Kubernetes 领域的的又一全新力作,欢迎关注和使用。 ## 核心功能列表 @@ -177,16 +177,16 @@ Jumpserver 采纳分布式架构,支持多机房跨区域部署,支持横向 ## 演示视频和截屏 -我们提供了演示视频和系统截图可以让你快速了解 Jumpserver: +我们提供了演示视频和系统截图可以让你快速了解 JumpServer: - [演示视频](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) +- [系统截图](http://docs.JumpServer.org/zh/docs/snapshot.html) ## SDK -我们编写了一些SDK,供您的其它系统快速和 Jumpserver API 交互: +我们编写了一些SDK,供您的其它系统快速和 JumpServer API 交互: -- [Python](https://github.com/jumpserver/jumpserver-python-sdk) Jumpserver 其它组件使用这个 SDK 完成交互 +- [Python](https://github.com/jumpserver/jumpserver-python-sdk) JumpServer 其它组件使用这个 SDK 完成交互 - [Java](https://github.com/KaiJunYan/jumpserver-java-sdk.git) 恺珺同学提供的 Java 版本的 SDK ## License & Copyright From 1fd2e782f8ba574058dfcc80c7f87639a49f269e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E5=B9=BF?= Date: Thu, 12 Mar 2020 16:24:38 +0800 Subject: [PATCH 02/32] 1.5.7 Merge to dev (#3766) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Update] 暂存,优化解决不了问题 * [Update] 待续(小白) * [Update] 修改asset user * [Update] 计划再次更改 * [Update] 修改asset user * [Update] 暂存与喜爱 * [Update] Add id in * [Update] 阶段性完成ops task该做 * [Update] 修改asset user api * [Update] 修改asset user 任务,查看认证等 * [Update] 基本完成asset user改造 * [Update] dynamic user only allow 1 * [Update] 修改asset user task * [Update] 修改node admin user task api * [Update] remove file header license * [Update] 添加sftp root * [Update] 暂存 * [Update] 暂存 * [Update] 修改翻译 * [Update] 修改系统用户改为同名后,用户名改为空 * [Update] 基本完成CAS调研 * [Update] 支持cas server * [Update] 支持cas server * [Update] 添加requirements * [Update] 为方便调试添加mysql ipython到包中 * [Update] 添加huaweiyun翻译 * [Update] 增加下载session 录像 * [Update] 只有第一次通知replay离线的使用方法 * [Update] 暂存一下 * [Bugfix] 获取系统用户信息报错 * [Bugfix] 修改system user info * [Update] 改成清理10天git status * [Update] 修改celery日志保留时间 * [Update]修复部分pip包依赖的版本不兼容问题 (#3672) * [Update] 修复用户更新页面会清空用户public_key的问题 * Fix broken dependencies Co-authored-by: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> * [Update] 修改获取系统用户auth info * [Update] Remove log * [Bugfix] 修复sftp home设置的bug * [Update] 授权的系统用户添加sftp root * [Update] 修改系统用户关联的用户 * [Update] 修改placeholder * [Update] 优化获取授权的系统用户 * [Update] 修改tasks * [Update] tree service update * [Update] 暂存 * [Update] 基本完成用户授权树和资产树改造 * [Update] Dashbaord perf * [update] Add huawei cloud sdk requirements * [Updte] 优化dashboard页面 * [Update] system user auth info 添加id * [Update] 修改系统用户serializer * [Update] 优化api * [Update] LDAP Test Util (#3720) * [Update] LDAPTestUtil 1 * [Update] LDAPTestUtil 2 * [Update] LDAPTestUtil 3 * [Update] LDAPTestUtil 4 * [Update] LDAPTestUtil 5 * [Update] LDAPTestUtil 6 * [Update] LDAPTestUtil 7 * [Update] session 已添加is success,并且添加display serializer * [Bugfix] 修复无法删除空节点的bug * [Update] 命令记录分组织显示 * [Update] Session is_success 添加迁移文件 * [Update] 批量命令添加org_id * [Update] 修复一些文案,修改不绑定MFA,不能ssh登录 * [Update] 修改replay api, 返回session信息 * [Update] 解决无效es导致访问命令记录页面失败的问题 * [Update] 拆分profile view * [Update] 修改一个翻译 * [Update] 修改aysnc api框架 * [Update] 命令列表添加risk level * [Update] 完成录像打包下载 * [Update] 更改登陆otp页面 * [Update] 修改command 存储redis_level * [Update] 修改翻译 * [Update] 修改系统用户的用户列表字段 * [Update] 使用新logo和统一Jumpserver为JumpServer * [Update] 优化cloud task * [Update] 统一period task * [Update] 统一period form serializer字段 * [Update] 修改period task * [Update] 修改资产网关信息 * [Update] 用户授权资产树资产信息添加domain * [Update] 修改翻译 * [Update] 测试可连接性 * 1.5.7 bai (#3764) * [Update] 修复index页面Bug;修复测试资产用户可连接性问题; * [Update] 修改测试资产用户可连接 * [Bugfix] 修复backends问题 * [Update] 修改marksafe依赖版本 * [Update] 修改测试资产用户可连接性 * [Update] 修改检测服务器性能时获取percent值 * [Update] 更新依赖boto3=1.12.14 Co-authored-by: Yanzhe Lee Co-authored-by: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Co-authored-by: Bai --- apps/applications/hands.py | 2 +- apps/assets/api/asset.py | 70 +- apps/assets/api/asset_user.py | 192 +- apps/assets/api/node.py | 94 +- apps/assets/api/system_user.py | 143 +- apps/assets/api/system_user_relation.py | 39 +- apps/assets/backends/admin_user.py | 10 - apps/assets/backends/asset_user.py | 58 - apps/assets/backends/base.py | 114 +- apps/assets/backends/db.py | 332 ++- apps/assets/backends/manager.py | 224 +- apps/assets/backends/system_user.py | 30 - apps/assets/backends/utils.py | 9 - apps/assets/backends/vault.py | 7 - apps/assets/forms/asset.py | 22 +- apps/assets/forms/user.py | 10 +- apps/assets/hands.py | 2 +- apps/assets/migrations/0047_assetuser.py | 24 + .../migrations/0048_auto_20191230_1512.py | 35 + .../migrations/0049_systemuser_sftp_root.py | 18 + apps/assets/models/__init__.py | 2 + apps/assets/models/asset.py | 25 +- apps/assets/models/asset_user.py | 14 + apps/assets/models/authbook.py | 8 +- apps/assets/models/base.py | 266 +- apps/assets/models/domain.py | 4 +- apps/assets/models/node.py | 159 +- apps/assets/models/user.py | 25 +- apps/assets/serializers/admin_user.py | 8 + apps/assets/serializers/asset.py | 45 +- apps/assets/serializers/asset_user.py | 61 +- apps/assets/serializers/base.py | 16 +- apps/assets/serializers/node.py | 11 +- apps/assets/serializers/system_user.py | 107 +- apps/assets/signals_handler.py | 21 +- apps/assets/tasks/admin_user_connectivity.py | 18 +- apps/assets/tasks/asset_connectivity.py | 54 +- apps/assets/tasks/asset_user_connectivity.py | 109 +- apps/assets/tasks/const.py | 43 +- .../tasks/gather_asset_hardware_info.py | 26 +- apps/assets/tasks/gather_asset_users.py | 9 +- apps/assets/tasks/push_system_user.py | 167 +- apps/assets/tasks/system_user_connectivity.py | 90 +- apps/assets/tasks/utils.py | 51 +- .../assets/_asset_user_auth_update_modal.html | 8 +- .../assets/_asset_user_auth_view_modal.html | 22 +- .../templates/assets/_asset_user_list.html | 129 +- apps/assets/templates/assets/_node_tree.html | 27 +- .../assets/templates/assets/_system_user.html | 17 +- .../templates/assets/admin_user_assets.html | 6 +- .../templates/assets/admin_user_list.html | 2 +- .../assets/asset_asset_user_list.html | 13 +- .../assets/templates/assets/asset_detail.html | 13 +- apps/assets/templates/assets/asset_list.html | 10 +- .../templates/assets/platform_detail.html | 18 +- .../templates/assets/system_user_assets.html | 117 +- .../templates/assets/system_user_detail.html | 62 +- .../templates/assets/system_user_list.html | 13 +- .../templates/assets/system_user_users.html | 212 ++ apps/assets/tests.py | 3 - apps/assets/tests/__init__.py | 2 + apps/assets/tests/test_system_user.py | 2 + apps/assets/urls/api_urls.py | 80 +- apps/assets/urls/views_urls.py | 1 + apps/assets/utils.py | 127 +- apps/assets/views/admin_user.py | 2 +- apps/assets/views/platform.py | 3 + apps/assets/views/system_user.py | 18 +- apps/authentication/backends/cas/__init__.py | 4 + apps/authentication/backends/cas/backends.py | 11 + apps/authentication/backends/cas/callback.py | 16 + apps/authentication/backends/cas/urls.py | 11 + apps/authentication/backends/ldap.py | 25 +- apps/authentication/backends/pubkey.py | 2 +- apps/authentication/errors.py | 15 +- apps/authentication/mixins.py | 7 +- .../authentication/_mfa_confirm_modal.html | 2 +- .../templates/authentication/login.html | 163 +- .../templates/authentication/login_otp.html | 108 +- apps/authentication/urls/view_urls.py | 9 +- apps/authentication/views/login.py | 42 +- apps/common/README.md | 2 +- apps/common/mixins/api.py | 128 +- apps/common/mixins/models.py | 3 +- apps/common/struct.py | 81 + apps/common/utils/common.py | 8 +- apps/common/utils/random.py | 39 + apps/jumpserver/conf.py | 16 +- apps/jumpserver/context_processor.py | 2 +- apps/jumpserver/settings/auth.py | 14 + apps/jumpserver/settings/base.py | 4 +- apps/jumpserver/settings/custom.py | 1 + apps/jumpserver/settings/libs.py | 1 + apps/jumpserver/settings/logging.py | 12 +- apps/jumpserver/views/index.py | 338 +-- apps/jumpserver/views/swagger.py | 19 +- apps/locale/zh/LC_MESSAGES/django.mo | Bin 84170 -> 88260 bytes apps/locale/zh/LC_MESSAGES/django.po | 2146 ++++++++++------- apps/locale/zh/LC_MESSAGES/djangojs.mo | Bin 2741 -> 2782 bytes apps/ops/ansible/runner.py | 2 +- apps/ops/api/adhoc.py | 14 +- apps/ops/api/command.py | 4 +- apps/ops/inventory.py | 8 +- .../ops/migrations/0011_auto_20200106_1534.py | 19 + .../ops/migrations/0012_auto_20200108_1659.py | 22 + .../ops/migrations/0013_auto_20200108_1706.py | 28 + .../ops/migrations/0014_auto_20200108_1749.py | 17 + .../ops/migrations/0015_auto_20200108_1809.py | 33 + .../0016_commandexecution_org_id.py | 18 + .../ops/migrations/0017_auto_20200306_1747.py | 23 + apps/ops/mixin.py | 181 ++ apps/ops/models/adhoc.py | 157 +- apps/ops/models/command.py | 4 +- apps/ops/serializers/adhoc.py | 22 +- apps/ops/tasks.py | 22 +- apps/ops/templates/ops/adhoc_detail.html | 24 +- apps/ops/templates/ops/adhoc_history.html | 12 +- .../templates/ops/adhoc_history_detail.html | 4 +- apps/ops/templates/ops/task_adhoc.html | 10 +- apps/ops/templates/ops/task_detail.html | 22 +- apps/ops/templates/ops/task_history.html | 20 +- apps/ops/templates/ops/task_list.html | 8 +- apps/ops/urls/api_urls.py | 2 +- apps/ops/urls/view_urls.py | 10 +- apps/ops/utils.py | 17 +- apps/ops/views/adhoc.py | 27 +- apps/ops/views/command.py | 4 +- apps/orgs/mixins/api.py | 8 +- apps/orgs/mixins/models.py | 12 + apps/orgs/models.py | 8 +- apps/orgs/utils.py | 31 +- apps/perms/api/mixin.py | 16 +- apps/perms/api/user_permission/common.py | 26 +- apps/perms/api/user_permission/mixin.py | 4 +- .../user_permission/user_permission_assets.py | 7 +- apps/perms/mixins.py | 62 +- apps/perms/serializers/user_permission.py | 1 + apps/perms/signals_handler.py | 77 +- .../perms/asset_permission_list.html | 2 +- apps/perms/urls/asset_permission.py | 2 +- apps/perms/utils/asset_permission.py | 133 +- apps/settings/api.py | 54 +- apps/settings/forms/security.py | 6 +- apps/settings/serializers/ldap.py | 12 +- .../settings/_ldap_test_user_login_modal.html | 58 + .../templates/settings/ldap_setting.html | 15 +- apps/settings/urls/api_urls.py | 3 +- apps/settings/utils/ldap.py | 251 +- apps/static/img/logo_text.png | Bin 21179 -> 11827 bytes apps/static/js/jumpserver.js | 68 +- apps/templates/_base_only_msg_content.html | 67 + apps/templates/_csv_update_modal.html | 2 +- apps/templates/_filter_dropdown.html | 4 +- apps/templates/_nav.html | 2 +- apps/templates/index.html | 22 +- apps/terminal/api/command.py | 20 +- apps/terminal/api/session.py | 81 +- apps/terminal/backends/command/db.py | 17 +- apps/terminal/backends/command/es.py | 37 +- apps/terminal/backends/command/models.py | 7 + apps/terminal/backends/command/serializers.py | 1 + .../migrations/0022_session_is_success.py | 18 + .../migrations/0023_command_risk_level.py | 18 + apps/terminal/models.py | 43 + apps/terminal/serializers/session.py | 23 +- .../templates/terminal/command_list.html | 63 +- .../templates/terminal/session_commands.html | 96 + .../terminal/session_commands_list_modal.html | 58 - .../templates/terminal/session_detail.html | 181 +- .../templates/terminal/session_list.html | 23 +- .../templates/terminal/terminal_detail.html | 54 +- apps/terminal/urls/views_urls.py | 2 + apps/terminal/utils.py | 55 +- apps/terminal/views/session.py | 71 +- apps/users/forms/profile.py | 8 +- apps/users/hands.py | 2 +- .../migrations/0025_auto_20200206_1216.py | 18 + apps/users/models/user.py | 27 +- apps/users/signals_handler.py | 22 +- apps/users/templates/users/_base_otp.html | 2 +- .../templates/users/_granted_assets.html | 8 +- apps/users/templates/users/first_login.html | 11 - .../templates/users/forgot_password.html | 5 - .../users/user_asset_permission.html | 2 +- apps/users/templates/users/user_detail.html | 2 +- .../templates/users/user_disable_mfa.html | 2 +- ...heck.html => user_otp_check_password.html} | 6 +- .../templates/users/user_otp_enable_bind.html | 9 +- .../users/user_otp_enable_install_app.html | 9 +- .../templates/users/user_password_verify.html | 24 + apps/users/templates/users/user_profile.html | 4 +- apps/users/urls/views_urls.py | 4 +- apps/users/utils.py | 41 +- apps/users/views/profile.py | 272 --- apps/users/views/profile/__init__.py | 7 + apps/users/views/profile/base.py | 50 + apps/users/views/profile/mfa.py | 2 + apps/users/views/profile/otp.py | 136 ++ apps/users/views/profile/password.py | 94 + apps/users/views/profile/pubkey.py | 54 + jms | 8 + requirements/requirements.txt | 24 +- requirements/rpm_requirements.txt | 2 +- utils/create_test_data.py | 3 + 204 files changed, 6463 insertions(+), 3860 deletions(-) delete mode 100644 apps/assets/backends/admin_user.py delete mode 100644 apps/assets/backends/asset_user.py delete mode 100644 apps/assets/backends/system_user.py create mode 100644 apps/assets/migrations/0047_assetuser.py create mode 100644 apps/assets/migrations/0048_auto_20191230_1512.py create mode 100644 apps/assets/migrations/0049_systemuser_sftp_root.py create mode 100644 apps/assets/models/asset_user.py create mode 100644 apps/assets/templates/assets/system_user_users.html delete mode 100644 apps/assets/tests.py create mode 100644 apps/assets/tests/__init__.py create mode 100644 apps/assets/tests/test_system_user.py create mode 100644 apps/authentication/backends/cas/__init__.py create mode 100644 apps/authentication/backends/cas/backends.py create mode 100644 apps/authentication/backends/cas/callback.py create mode 100644 apps/authentication/backends/cas/urls.py create mode 100644 apps/common/utils/random.py create mode 100644 apps/ops/migrations/0011_auto_20200106_1534.py create mode 100644 apps/ops/migrations/0012_auto_20200108_1659.py create mode 100644 apps/ops/migrations/0013_auto_20200108_1706.py create mode 100644 apps/ops/migrations/0014_auto_20200108_1749.py create mode 100644 apps/ops/migrations/0015_auto_20200108_1809.py create mode 100644 apps/ops/migrations/0016_commandexecution_org_id.py create mode 100644 apps/ops/migrations/0017_auto_20200306_1747.py create mode 100644 apps/ops/mixin.py create mode 100644 apps/settings/templates/settings/_ldap_test_user_login_modal.html create mode 100644 apps/templates/_base_only_msg_content.html create mode 100644 apps/terminal/migrations/0022_session_is_success.py create mode 100644 apps/terminal/migrations/0023_command_risk_level.py create mode 100644 apps/terminal/templates/terminal/session_commands.html delete mode 100644 apps/terminal/templates/terminal/session_commands_list_modal.html create mode 100644 apps/users/migrations/0025_auto_20200206_1216.py rename apps/users/templates/users/{user_password_check.html => user_otp_check_password.html} (96%) create mode 100644 apps/users/templates/users/user_password_verify.html delete mode 100644 apps/users/views/profile.py create mode 100644 apps/users/views/profile/__init__.py create mode 100644 apps/users/views/profile/base.py create mode 100644 apps/users/views/profile/mfa.py create mode 100644 apps/users/views/profile/otp.py create mode 100644 apps/users/views/profile/password.py create mode 100644 apps/users/views/profile/pubkey.py create mode 100644 utils/create_test_data.py diff --git a/apps/applications/hands.py b/apps/applications/hands.py index 7c83e1332..ee13e589e 100644 --- a/apps/applications/hands.py +++ b/apps/applications/hands.py @@ -6,7 +6,7 @@ Other module of this app shouldn't connect with other app. - :copyright: (c) 2014-2018 by Jumpserver Team. + :copyright: (c) 2014-2018 by JumpServer Team. :license: GPL v2, see LICENSE for more details. """ diff --git a/apps/assets/api/asset.py b/apps/assets/api/asset.py index 0b63522ea..6eb8ebeaf 100644 --- a/apps/assets/api/asset.py +++ b/apps/assets/api/asset.py @@ -23,8 +23,8 @@ from ..filters import AssetByNodeFilterBackend, LabelFilterBackend logger = get_logger(__file__) __all__ = [ 'AssetViewSet', 'AssetPlatformRetrieveApi', - 'AssetRefreshHardwareApi', 'AssetAdminUserTestApi', - 'AssetGatewayApi', 'AssetPlatformViewSet', + 'AssetGatewayListApi', 'AssetPlatformViewSet', + 'AssetTaskCreateApi', ] @@ -36,7 +36,10 @@ class AssetViewSet(OrgBulkModelViewSet): filter_fields = ("hostname", "ip", "systemuser__id", "admin_user__id") search_fields = ("hostname", "ip") ordering_fields = ("hostname", "ip", "port", "cpu_cores") - serializer_class = serializers.AssetSerializer + serializer_classes = { + 'default': serializers.AssetSerializer, + 'display': serializers.AssetDisplaySerializer, + } permission_classes = (IsOrgAdminOrAppUser,) extra_filter_backends = [AssetByNodeFilterBackend, LabelFilterBackend] @@ -80,53 +83,40 @@ class AssetPlatformViewSet(ModelViewSet): self.permission_denied( request, message={"detail": "Internal platform"} ) - return super().check_object_permissions(request, obj) -class AssetRefreshHardwareApi(generics.RetrieveAPIView): - """ - Refresh asset hardware info - """ +class AssetTaskCreateApi(generics.CreateAPIView): model = Asset - serializer_class = serializers.AssetSerializer + serializer_class = serializers.AssetTaskSerializer permission_classes = (IsOrgAdmin,) - def retrieve(self, request, *args, **kwargs): - asset_id = kwargs.get('pk') - asset = get_object_or_404(Asset, pk=asset_id) - task = update_asset_hardware_info_manual.delay(asset) - return Response({"task": task.id}) + def get_object(self): + pk = self.kwargs.get("pk") + instance = get_object_or_404(Asset, pk=pk) + return instance + + def perform_create(self, serializer): + asset = self.get_object() + action = serializer.validated_data["action"] + if action == "refresh": + task = update_asset_hardware_info_manual.delay(asset) + else: + task = test_asset_connectivity_manual.delay(asset) + data = getattr(serializer, '_data', {}) + data["task"] = task.id + setattr(serializer, '_data', data) -class AssetAdminUserTestApi(generics.RetrieveAPIView): - """ - Test asset admin user assets_connectivity - """ - model = Asset - permission_classes = (IsOrgAdmin,) - serializer_class = serializers.TaskIDSerializer - - def retrieve(self, request, *args, **kwargs): - asset_id = kwargs.get('pk') - asset = get_object_or_404(Asset, pk=asset_id) - task = test_asset_connectivity_manual.delay(asset) - return Response({"task": task.id}) - - -class AssetGatewayApi(generics.RetrieveAPIView): +class AssetGatewayListApi(generics.ListAPIView): permission_classes = (IsOrgAdminOrAppUser,) serializer_class = serializers.GatewayWithAuthSerializer model = Asset - def retrieve(self, request, *args, **kwargs): - asset_id = kwargs.get('pk') + def get_queryset(self): + asset_id = self.kwargs.get('pk') asset = get_object_or_404(Asset, pk=asset_id) - - if asset.domain and \ - asset.domain.gateways.filter(protocol='ssh').exists(): - gateway = random.choice(asset.domain.gateways.filter(protocol='ssh')) - serializer = serializers.GatewayWithAuthSerializer(instance=gateway) - return Response(serializer.data) - else: - return Response({"msg": "Not have gateway"}, status=404) + if not asset.domain: + return [] + queryset = asset.domain.gateways.filter(protocol='ssh') + return queryset diff --git a/apps/assets/api/asset_user.py b/apps/assets/api/asset_user.py index a3b9d8906..ce5930a26 100644 --- a/apps/assets/api/asset_user.py +++ b/apps/assets/api/asset_user.py @@ -1,26 +1,23 @@ # -*- coding: utf-8 -*- # - -from rest_framework.response import Response -from rest_framework import generics -from rest_framework import filters -from rest_framework_bulk import BulkModelViewSet -from django.shortcuts import get_object_or_404 -from django.http import Http404 from django.conf import settings +from rest_framework.response import Response +from rest_framework import generics, filters +from rest_framework_bulk import BulkModelViewSet from common.permissions import IsOrgAdminOrAppUser, NeedMFAVerify from common.utils import get_object_or_none, get_logger from common.mixins import CommonApiMixin from ..backends import AssetUserManager -from ..models import Asset, Node, SystemUser, AdminUser +from ..models import Asset, Node, SystemUser from .. import serializers -from ..tasks import test_asset_users_connectivity_manual +from ..tasks import ( + test_asset_users_connectivity_manual, push_system_user_a_asset_manual +) __all__ = [ - 'AssetUserViewSet', 'AssetUserAuthInfoApi', 'AssetUserTestConnectiveApi', - 'AssetUserExportViewSet', + 'AssetUserViewSet', 'AssetUserAuthInfoViewSet', 'AssetUserTaskCreateAPI', ] @@ -34,10 +31,17 @@ class AssetUserFilterBackend(filters.BaseFilterBackend): value = request.GET.get(field) if not value: continue - if field in ("node_id", "system_user_id", "admin_user_id"): + if field == "node_id": + value = get_object_or_none(Node, pk=value) + kwargs["node"] = value continue + elif field == "asset_id": + field = "asset" kwargs[field] = value - return queryset.filter(**kwargs) + if kwargs: + queryset = queryset.filter(**kwargs) + logger.debug("Filter {}".format(kwargs)) + return queryset class AssetUserSearchBackend(filters.BaseFilterBackend): @@ -45,71 +49,62 @@ class AssetUserSearchBackend(filters.BaseFilterBackend): value = request.GET.get('search') if not value: return queryset - _queryset = AssetUserManager.none() - for field in view.search_fields: - if field in ("node_id", "system_user_id", "admin_user_id"): - continue - _queryset |= queryset.filter(**{field: value}) - return _queryset.distinct() + queryset = queryset.search(value) + return queryset + + +class AssetUserLatestFilterBackend(filters.BaseFilterBackend): + def filter_queryset(self, request, queryset, view): + latest = request.GET.get('latest') == '1' + if latest: + queryset = queryset.distinct() + return queryset class AssetUserViewSet(CommonApiMixin, BulkModelViewSet): - serializer_class = serializers.AssetUserSerializer + serializer_classes = { + 'default': serializers.AssetUserWriteSerializer, + 'list': serializers.AssetUserReadSerializer, + 'retrieve': serializers.AssetUserReadSerializer, + } permission_classes = [IsOrgAdminOrAppUser] - http_method_names = ['get', 'post'] filter_fields = [ - "id", "ip", "hostname", "username", "asset_id", "node_id", - "system_user_id", "admin_user_id" + "id", "ip", "hostname", "username", + "asset_id", "node_id", + "prefer", "prefer_id", ] - search_fields = filter_fields - filter_backends = ( - filters.OrderingFilter, + search_fields = ["ip", "hostname", "username"] + filter_backends = [ AssetUserFilterBackend, AssetUserSearchBackend, - ) + AssetUserLatestFilterBackend, + ] def allow_bulk_destroy(self, qs, filtered): return False - def get_queryset(self): - # 尽可能先返回更少的数据 - username = self.request.GET.get('username') - asset_id = self.request.GET.get('asset_id') - node_id = self.request.GET.get('node_id') - admin_user_id = self.request.GET.get("admin_user_id") - system_user_id = self.request.GET.get("system_user_id") + def get_object(self): + pk = self.kwargs.get("pk") + queryset = self.get_queryset() + obj = queryset.get(id=pk) + return obj - kwargs = {} - assets = None + def get_exception_handler(self): + def handler(e, context): + return Response({"error": str(e)}, status=400) + return handler + def perform_destroy(self, instance): manager = AssetUserManager() - if system_user_id: - system_user = get_object_or_404(SystemUser, id=system_user_id) - assets = system_user.get_all_assets() - username = system_user.username - elif admin_user_id: - admin_user = get_object_or_404(AdminUser, id=admin_user_id) - assets = admin_user.assets.all() - username = admin_user.username - manager.prefer('admin_user') + manager.delete(instance) - if asset_id: - asset = get_object_or_404(Asset, id=asset_id) - assets = [asset] - elif node_id: - node = get_object_or_404(Node, id=node_id) - assets = node.get_all_assets() - - if username: - kwargs['username'] = username - if assets is not None: - kwargs['assets'] = assets - - queryset = manager.filter(**kwargs) + def get_queryset(self): + manager = AssetUserManager() + queryset = manager.all() return queryset -class AssetUserExportViewSet(AssetUserViewSet): - serializer_class = serializers.AssetUserExportSerializer +class AssetUserAuthInfoViewSet(AssetUserViewSet): + serializer_classes = {"default": serializers.AssetUserAuthInfoSerializer} http_method_names = ['get'] permission_classes = [IsOrgAdminOrAppUser] @@ -119,66 +114,31 @@ class AssetUserExportViewSet(AssetUserViewSet): return super().get_permissions() -class AssetUserAuthInfoApi(generics.RetrieveAPIView): - serializer_class = serializers.AssetUserAuthInfoSerializer - permission_classes = [IsOrgAdminOrAppUser] - - def get_permissions(self): - if settings.SECURITY_VIEW_AUTH_NEED_MFA: - self.permission_classes = [IsOrgAdminOrAppUser, NeedMFAVerify] - return super().get_permissions() - - def get_object(self): - query_params = self.request.query_params - username = query_params.get('username') - asset_id = query_params.get('asset_id') - prefer = query_params.get("prefer") - asset = get_object_or_none(Asset, pk=asset_id) - try: - manger = AssetUserManager() - instance = manger.get(username, asset, prefer=prefer) - except Exception as e: - raise Http404("Not found") - else: - return instance - - -class AssetUserTestConnectiveApi(generics.RetrieveAPIView): - """ - Test asset users connective - """ +class AssetUserTaskCreateAPI(generics.CreateAPIView): permission_classes = (IsOrgAdminOrAppUser,) - serializer_class = serializers.TaskIDSerializer + serializer_class = serializers.AssetUserTaskSerializer + filter_backends = AssetUserViewSet.filter_backends + filter_fields = AssetUserViewSet.filter_fields def get_asset_users(self): - username = self.request.GET.get('username') - asset_id = self.request.GET.get('asset_id') - prefer = self.request.GET.get("prefer") - asset = get_object_or_none(Asset, pk=asset_id) manager = AssetUserManager() - asset_users = manager.filter(username=username, assets=[asset], prefer=prefer) - return asset_users + queryset = manager.all() + for cls in self.filter_backends: + queryset = cls().filter_queryset(self.request, queryset, self) + return list(queryset) - def retrieve(self, request, *args, **kwargs): + def perform_create(self, serializer): asset_users = self.get_asset_users() - prefer = self.request.GET.get("prefer") - kwargs = {} - if prefer == "admin_user": - kwargs["run_as_admin"] = True - task = test_asset_users_connectivity_manual.delay(asset_users, **kwargs) - return Response({"task": task.id}) + # action = serializer.validated_data["action"] + # only this + # if action == "test": + task = test_asset_users_connectivity_manual.delay(asset_users) + data = getattr(serializer, '_data', {}) + data["task"] = task.id + setattr(serializer, '_data', data) + return task - -class AssetUserPushApi(generics.CreateAPIView): - """ - Test asset users connective - """ - serializer_class = serializers.AssetUserPushSerializer - permission_classes = (IsOrgAdminOrAppUser,) - - def create(self, request, *args, **kwargs): - serializer = self.get_serializer(data=request.data) - serializer.is_valid(raise_exception=True) - asset = serializer.validated_data["asset"] - username = serializer.validated_data["username"] - pass + def get_exception_handler(self): + def handler(e, context): + return Response({"error": str(e)}, status=400) + return handler diff --git a/apps/assets/api/node.py b/apps/assets/api/node.py index 24661bad6..2d959e9ea 100644 --- a/apps/assets/api/node.py +++ b/apps/assets/api/node.py @@ -1,24 +1,11 @@ # ~*~ coding: utf-8 ~*~ -# Copyright (C) 2014-2018 Beijing DuiZhan Technology Co.,Ltd. All Rights Reserved. -# -# Licensed under the GNU General Public License v2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.gnu.org/licenses/gpl-2.0.html -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +from collections import namedtuple from rest_framework import status from rest_framework.serializers import ValidationError -from rest_framework.views import APIView from rest_framework.response import Response from django.utils.translation import ugettext_lazy as _ -from django.shortcuts import get_object_or_404 +from django.shortcuts import get_object_or_404, Http404 from common.utils import get_logger, get_object_or_none from common.tree import TreeNodeSerializer @@ -27,7 +14,8 @@ from orgs.mixins import generics from ..hands import IsOrgAdmin from ..models import Node from ..tasks import ( - update_assets_hardware_info_util, test_asset_connectivity_util + update_node_assets_hardware_info_manual, + test_node_assets_connectivity_manual, ) from .. import serializers @@ -36,9 +24,9 @@ logger = get_logger(__file__) __all__ = [ 'NodeViewSet', 'NodeChildrenApi', 'NodeAssetsApi', 'NodeAddAssetsApi', 'NodeRemoveAssetsApi', 'NodeReplaceAssetsApi', - 'NodeAddChildrenApi', 'RefreshNodeHardwareInfoApi', - 'TestNodeConnectiveApi', 'NodeListAsTreeApi', - 'NodeChildrenAsTreeApi', 'RefreshNodesCacheApi', + 'NodeAddChildrenApi', 'NodeListAsTreeApi', + 'NodeChildrenAsTreeApi', + 'NodeTaskCreateApi', ] @@ -64,9 +52,9 @@ class NodeViewSet(OrgModelViewSet): def destroy(self, request, *args, **kwargs): node = self.get_object() - if node.has_children_or_contains_assets(): - msg = _("Deletion failed and the node contains children or assets") - return Response(data={'msg': msg}, status=status.HTTP_403_FORBIDDEN) + if node.has_children_or_has_assets(): + error = _("Deletion failed and the node contains children or assets") + return Response(data={'error': error}, status=status.HTTP_403_FORBIDDEN) return super().destroy(request, *args, **kwargs) @@ -261,41 +249,41 @@ class NodeReplaceAssetsApi(generics.UpdateAPIView): asset.nodes.set([instance]) -class RefreshNodeHardwareInfoApi(APIView): +class NodeTaskCreateApi(generics.CreateAPIView): model = Node + serializer_class = serializers.NodeTaskSerializer permission_classes = (IsOrgAdmin,) - def get(self, request, *args, **kwargs): - node_id = kwargs.get('pk') - node = get_object_or_404(self.model, id=node_id) - assets = node.get_all_assets() - # task_name = _("更新节点资产硬件信息: {}".format(node.name)) - task_name = _("Update node asset hardware information: {}").format(node.name) - task = update_assets_hardware_info_util.delay(assets, task_name=task_name) - return Response({"task": task.id}) + def get_object(self): + node_id = self.kwargs.get('pk') + node = get_object_or_none(self.model, id=node_id) + return node + @staticmethod + def set_serializer_data(s, task): + data = getattr(s, '_data', {}) + data["task"] = task.id + setattr(s, '_data', data) -class TestNodeConnectiveApi(APIView): - permission_classes = (IsOrgAdmin,) - model = Node - - def get(self, request, *args, **kwargs): - node_id = kwargs.get('pk') - node = get_object_or_404(self.model, id=node_id) - assets = node.get_all_assets() - # task_name = _("测试节点下资产是否可连接: {}".format(node.name)) - task_name = _("Test if the assets under the node are connectable: {}".format(node.name)) - task = test_asset_connectivity_util.delay(assets, task_name=task_name) - return Response({"task": task.id}) - - -class RefreshNodesCacheApi(APIView): - permission_classes = (IsOrgAdmin,) - - def get(self, request, *args, **kwargs): + @staticmethod + def refresh_nodes_cache(): Node.refresh_nodes() - return Response("Ok") + Task = namedtuple('Task', ['id']) + task = Task(id="0") + return task + + def perform_create(self, serializer): + action = serializer.validated_data["action"] + node = self.get_object() + if action == "refresh_cache" and node is None: + task = self.refresh_nodes_cache() + self.set_serializer_data(serializer, task) + return + if node is None: + raise Http404() + if action == "refresh": + task = update_node_assets_hardware_info_manual.delay(node) + else: + task = test_node_assets_connectivity_manual.delay(node) + self.set_serializer_data(serializer, task) - def delete(self, *args, **kwargs): - self.get(*args, **kwargs) - return Response(status=204) diff --git a/apps/assets/api/system_user.py b/apps/assets/api/system_user.py index e3dddd6f5..dc134ee97 100644 --- a/apps/assets/api/system_user.py +++ b/apps/assets/api/system_user.py @@ -1,42 +1,25 @@ # ~*~ coding: utf-8 ~*~ -# Copyright (C) 2014-2018 Beijing DuiZhan Technology Co.,Ltd. All Rights Reserved. -# -# Licensed under the GNU General Public License v2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.gnu.org/licenses/gpl-2.0.html -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - from django.shortcuts import get_object_or_404 from rest_framework.response import Response -from django.db.models import Count -from common.serializers import CeleryTaskSerializer from common.utils import get_logger from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser, IsAppUser from orgs.mixins.api import OrgBulkModelViewSet from orgs.mixins import generics +from orgs.utils import tmp_to_org from ..models import SystemUser, Asset from .. import serializers +from ..serializers import SystemUserWithAuthInfoSerializer from ..tasks import ( push_system_user_to_assets_manual, test_system_user_connectivity_manual, - push_system_user_a_asset_manual, test_system_user_connectivity_a_asset, + push_system_user_a_asset_manual, ) logger = get_logger(__file__) __all__ = [ 'SystemUserViewSet', 'SystemUserAuthInfoApi', 'SystemUserAssetAuthInfoApi', - 'SystemUserPushApi', 'SystemUserTestConnectiveApi', - 'SystemUserAssetsListView', 'SystemUserPushToAssetApi', - 'SystemUserTestAssetConnectivityApi', 'SystemUserCommandFilterRuleListApi', - + 'SystemUserCommandFilterRuleListApi', 'SystemUserTaskApi', ] @@ -48,13 +31,12 @@ class SystemUserViewSet(OrgBulkModelViewSet): filter_fields = ("name", "username") search_fields = filter_fields serializer_class = serializers.SystemUserSerializer + serializer_classes = { + 'default': serializers.SystemUserSerializer, + 'list': serializers.SystemUserListSerializer, + } permission_classes = (IsOrgAdminOrAppUser,) - def get_queryset(self): - queryset = super().get_queryset() - queryset = queryset.annotate(_assets_amount=Count('assets')) - return queryset - class SystemUserAuthInfoApi(generics.RetrieveUpdateDestroyAPIView): """ @@ -62,7 +44,7 @@ class SystemUserAuthInfoApi(generics.RetrieveUpdateDestroyAPIView): """ model = SystemUser permission_classes = (IsOrgAdminOrAppUser,) - serializer_class = serializers.SystemUserAuthSerializer + serializer_class = SystemUserWithAuthInfoSerializer def destroy(self, request, *args, **kwargs): instance = self.get_object() @@ -75,88 +57,61 @@ class SystemUserAssetAuthInfoApi(generics.RetrieveAPIView): Get system user with asset auth info """ model = SystemUser - permission_classes = (IsAppUser,) - serializer_class = serializers.SystemUserAuthSerializer + permission_classes = (IsOrgAdminOrAppUser,) + serializer_class = SystemUserWithAuthInfoSerializer + + def get_exception_handler(self): + def handler(e, context): + return Response({"error": str(e)}, status=400) + return handler def get_object(self): instance = super().get_object() - aid = self.kwargs.get('aid') - asset = get_object_or_404(Asset, pk=aid) - instance.load_specific_asset_auth(asset) - return instance + username = instance.username + if instance.username_same_with_user: + username = self.request.query_params.get("username") + asset_id = self.kwargs.get('aid') + asset = get_object_or_404(Asset, pk=asset_id) + + with tmp_to_org(asset.org_id): + instance.load_asset_special_auth(asset=asset, username=username) + return instance -class SystemUserPushApi(generics.RetrieveAPIView): - """ - Push system user to cluster assets api - """ - model = SystemUser +class SystemUserTaskApi(generics.CreateAPIView): permission_classes = (IsOrgAdmin,) - serializer_class = CeleryTaskSerializer + serializer_class = serializers.SystemUserTaskSerializer - def retrieve(self, request, *args, **kwargs): - system_user = self.get_object() - nodes = system_user.nodes.all() - for node in nodes: - system_user.assets.add(*tuple(node.get_all_assets())) - task = push_system_user_to_assets_manual.delay(system_user) - return Response({"task": task.id}) + def do_push(self, system_user, asset=None): + if asset is None: + task = push_system_user_to_assets_manual.delay(system_user) + else: + username = self.request.query_params.get('username') + task = push_system_user_a_asset_manual.delay( + system_user, asset, username=username + ) + return task - -class SystemUserTestConnectiveApi(generics.RetrieveAPIView): - """ - Push system user to cluster assets api - """ - model = SystemUser - permission_classes = (IsOrgAdmin,) - serializer_class = CeleryTaskSerializer - - def retrieve(self, request, *args, **kwargs): - system_user = self.get_object() + @staticmethod + def do_test(system_user, asset=None): task = test_system_user_connectivity_manual.delay(system_user) - return Response({"task": task.id}) - - -class SystemUserAssetsListView(generics.ListAPIView): - permission_classes = (IsOrgAdmin,) - serializer_class = serializers.AssetSimpleSerializer - filter_fields = ("hostname", "ip") - http_method_names = ['get'] - search_fields = filter_fields + return task def get_object(self): pk = self.kwargs.get('pk') return get_object_or_404(SystemUser, pk=pk) - def get_queryset(self): + def perform_create(self, serializer): + action = serializer.validated_data["action"] + asset = serializer.validated_data.get('asset') system_user = self.get_object() - return system_user.assets.all() - - -class SystemUserPushToAssetApi(generics.RetrieveAPIView): - model = SystemUser - permission_classes = (IsOrgAdmin,) - serializer_class = serializers.TaskIDSerializer - - def retrieve(self, request, *args, **kwargs): - system_user = self.get_object() - asset_id = self.kwargs.get('aid') - asset = get_object_or_404(Asset, id=asset_id) - task = push_system_user_a_asset_manual.delay(system_user, asset) - return Response({"task": task.id}) - - -class SystemUserTestAssetConnectivityApi(generics.RetrieveAPIView): - model = SystemUser - permission_classes = (IsOrgAdmin,) - serializer_class = serializers.TaskIDSerializer - - def retrieve(self, request, *args, **kwargs): - system_user = self.get_object() - asset_id = self.kwargs.get('aid') - asset = get_object_or_404(Asset, id=asset_id) - task = test_system_user_connectivity_a_asset.delay(system_user, asset) - return Response({"task": task.id}) + if action == 'push': + task = self.do_push(system_user, asset) + else: + task = self.do_test(system_user, asset) + data = getattr(serializer, '_data', {}) + data["task"] = task.id + setattr(serializer, '_data', data) class SystemUserCommandFilterRuleListApi(generics.ListAPIView): diff --git a/apps/assets/api/system_user_relation.py b/apps/assets/api/system_user_relation.py index de88cfe38..02dd887a1 100644 --- a/apps/assets/api/system_user_relation.py +++ b/apps/assets/api/system_user_relation.py @@ -8,10 +8,13 @@ from orgs.mixins.api import OrgBulkModelViewSet from orgs.utils import current_org from .. import models, serializers -__all__ = ['SystemUserAssetRelationViewSet', 'SystemUserNodeRelationViewSet'] +__all__ = [ + 'SystemUserAssetRelationViewSet', 'SystemUserNodeRelationViewSet', + 'SystemUserUserRelationViewSet', +] -class RelationMixin(OrgBulkModelViewSet): +class RelationMixin: def get_queryset(self): queryset = self.model.objects.all() org_id = current_org.org_id() @@ -24,7 +27,11 @@ class RelationMixin(OrgBulkModelViewSet): return queryset -class SystemUserAssetRelationViewSet(RelationMixin): +class BaseRelationViewSet(RelationMixin, OrgBulkModelViewSet): + pass + + +class SystemUserAssetRelationViewSet(BaseRelationViewSet): serializer_class = serializers.SystemUserAssetRelationSerializer model = models.SystemUser.assets.through permission_classes = (IsOrgAdmin,) @@ -47,7 +54,7 @@ class SystemUserAssetRelationViewSet(RelationMixin): return queryset -class SystemUserNodeRelationViewSet(RelationMixin): +class SystemUserNodeRelationViewSet(BaseRelationViewSet): serializer_class = serializers.SystemUserNodeRelationSerializer model = models.SystemUser.nodes.through permission_classes = (IsOrgAdmin,) @@ -63,3 +70,27 @@ class SystemUserNodeRelationViewSet(RelationMixin): queryset = queryset \ .annotate(node_key=F('node__key')) return queryset + + +class SystemUserUserRelationViewSet(BaseRelationViewSet): + serializer_class = serializers.SystemUserUserRelationSerializer + model = models.SystemUser.users.through + permission_classes = (IsOrgAdmin,) + filterset_fields = [ + 'id', 'user', 'systemuser', + ] + search_fields = [ + "user__username", "user__name", + "systemuser__name", "systemuser__username", + ] + + def get_queryset(self): + queryset = super().get_queryset() + queryset = queryset.annotate( + user_display=Concat( + F('user__name'), Value('('), + F('user__username'), Value(')') + ) + ) + return queryset + diff --git a/apps/assets/backends/admin_user.py b/apps/assets/backends/admin_user.py deleted file mode 100644 index 8f3644b1b..000000000 --- a/apps/assets/backends/admin_user.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# - -from ..models import AdminUser -from .asset_user import AssetUserBackend - - -class AdminUserBackend(AssetUserBackend): - model = AdminUser - backend = 'AdminUser' diff --git a/apps/assets/backends/asset_user.py b/apps/assets/backends/asset_user.py deleted file mode 100644 index e76baf14b..000000000 --- a/apps/assets/backends/asset_user.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -# -from collections import defaultdict -from .base import BaseBackend - - -class AssetUserBackend(BaseBackend): - model = None - backend = "AssetUser" - - @classmethod - def filter_queryset_more(cls, queryset): - return queryset - - @classmethod - def filter(cls, username=None, assets=None, **kwargs): - queryset = cls.model.objects.all() - prefer_id = kwargs.get('prefer_id') - if prefer_id: - queryset = queryset.filter(id=prefer_id) - instances = cls.construct_authbook_objects(queryset, assets) - return instances - if username: - queryset = queryset.filter(username=username) - if assets: - queryset = queryset.filter(assets__in=assets).distinct() - - queryset = cls.filter_queryset_more(queryset) - instances = cls.construct_authbook_objects(queryset, assets) - return instances - - @classmethod - def construct_authbook_objects(cls, asset_users, assets): - instances = [] - assets_user_assets_map = defaultdict(set) - if isinstance(asset_users, list): - assets_user_assets_map = { - asset_user.id: asset_user.assets.values_list('id', flat=True) - for asset_user in asset_users - } - else: - assets_user_assets = asset_users.values_list('id', 'assets') - for i, asset_id in assets_user_assets: - assets_user_assets_map[i].add(asset_id) - - for asset_user in asset_users: - if not assets: - related_assets = asset_user.assets.all() - else: - assets_map = {a.id: a for a in assets} - related_assets = [ - assets_map.get(i) for i in assets_user_assets_map.get(asset_user.id) if i in assets_map - ] - for asset in related_assets: - instance = asset_user.construct_to_authbook(asset) - instance.backend = cls.backend - instances.append(instance) - return instances diff --git a/apps/assets/backends/base.py b/apps/assets/backends/base.py index 9c9f7ca1e..d5ce1f903 100644 --- a/apps/assets/backends/base.py +++ b/apps/assets/backends/base.py @@ -1,94 +1,48 @@ # -*- coding: utf-8 -*- # -import uuid from abc import abstractmethod +from ..models import Asset + class BaseBackend: - @classmethod @abstractmethod - def filter(cls, username=None, assets=None, latest=True, prefer=None, prefer_id=None): - """ - :param username: 用户名 - :param assets: 对象 - :param latest: 是否是最新记录 - :param prefer: 优先使用 - :param prefer_id: 使用id - :return: 元素为的可迭代对象( or ) - """ + def all(self): pass + @abstractmethod + def filter(self, username=None, hostname=None, ip=None, assets=None, + node=None, prefer_id=None, **kwargs): + pass -class AssetUserQuerySet(list): - def order_by(self, *ordering): - _ordering = [] - reverse = False - for i in ordering: - if i[0] == '-': - reverse = True - i = i[1:] - _ordering.append(i) - self.sort(key=lambda obj: [getattr(obj, j) for j in _ordering], reverse=reverse) - return self + @abstractmethod + def search(self, item): + pass - def filter_in(self, kwargs): - in_kwargs = {} - queryset = [] - for k, v in kwargs.items(): - if len(v) == 0: - return self - if k.find("__in") >= 0: - _k = k.split('__')[0] - in_kwargs[_k] = v - else: - in_kwargs[k] = v - for k in in_kwargs: - kwargs.pop(k, None) + @abstractmethod + def get_queryset(self): + pass - if len(in_kwargs) == 0: - return self - for i in self: - matched = False - for k, v in in_kwargs.items(): - attr = getattr(i, k, None) - # 如果属性或者value中是uuid,则转换成string - if isinstance(v[0], uuid.UUID): - v = [str(i) for i in v] - if isinstance(attr, uuid.UUID): - attr = str(attr) - if attr in v: - matched = True - if matched: - queryset.append(i) - return AssetUserQuerySet(queryset) + @abstractmethod + def delete(self, union_id): + pass - def filter_equal(self, kwargs): - def filter_it(obj): - wanted = [] - real = [] - for k, v in kwargs.items(): - wanted.append(v) - value = getattr(obj, k, None) - if isinstance(value, uuid.UUID): - value = str(value) - real.append(value) - return wanted == real - kwargs = {k: v for k, v in kwargs.items() if k.find('__in') == -1} - if len(kwargs) > 0: - queryset = AssetUserQuerySet([i for i in self if filter_it(i)]) - else: - queryset = self - return queryset + @staticmethod + def qs_to_values(qs): + values = qs.values( + 'hostname', 'ip', "asset_id", + 'username', 'password', 'private_key', 'public_key', + 'score', 'version', + "asset_username", "union_id", + 'date_created', 'date_updated', + 'org_id', 'backend', + ) + return values - def filter(self, **kwargs): - queryset = self.filter_in(kwargs).filter_equal(kwargs) - return queryset - - def distinct(self): - items = list(set(self)) - self[:] = items - return self - - def __or__(self, other): - self.extend(other) - return self + @staticmethod + def make_assets_as_id(assets): + if not assets: + return [] + if isinstance(assets[0], Asset): + assets = [a.id for a in assets] + return assets diff --git a/apps/assets/backends/db.py b/apps/assets/backends/db.py index 40fa41444..7cdba2754 100644 --- a/apps/assets/backends/db.py +++ b/apps/assets/backends/db.py @@ -1,29 +1,317 @@ # -*- coding: utf-8 -*- # +from functools import reduce +from django.db.models import F, CharField, Value, IntegerField, Q, Count +from django.db.models.functions import Concat -from ..models import AuthBook +from common.utils import get_object_or_none +from orgs.utils import current_org +from ..models import AuthBook, SystemUser, Asset, AdminUser from .base import BaseBackend -class AuthBookBackend(BaseBackend): - @classmethod - def filter(cls, username=None, assets=None, latest=True, **kwargs): - queryset = AuthBook.objects.all() - if username is not None: - queryset = queryset.filter(username=username) - if assets: - queryset = queryset.filter(asset__in=assets) - if latest: - queryset = queryset.latest_version() - return queryset +class DBBackend(BaseBackend): + union_id_length = 2 - @classmethod - def create(cls, **kwargs): - auth_info = { - 'password': kwargs.pop('password', ''), - 'public_key': kwargs.pop('public_key', ''), - 'private_key': kwargs.pop('private_key', '') - } - obj = AuthBook.objects.create(**kwargs) - obj.set_auth(**auth_info) - return obj + def __init__(self, queryset=None): + if queryset is None: + queryset = self.all() + self.queryset = queryset + + def _clone(self): + return self.__class__(self.queryset) + + def all(self): + return AuthBook.objects.none() + + def count(self): + return self.queryset.count() + + def get_queryset(self): + return self.queryset + + def delete(self, union_id): + cleaned_union_id = union_id.split('_') + # 如果union_id通不过本检查,代表可能不是本backend, 应该返回空 + if not self._check_union_id(union_id, cleaned_union_id): + return + return self._perform_delete_by_union_id(cleaned_union_id) + + def _perform_delete_by_union_id(self, union_id_cleaned): + pass + + def filter(self, assets=None, node=None, prefer=None, prefer_id=None, + union_id=None, id__in=None, **kwargs): + clone = self._clone() + clone._filter_union_id(union_id) + clone._filter_prefer(prefer, prefer_id) + clone._filter_node(node) + clone._filter_assets(assets) + clone._filter_other(kwargs) + clone._filter_id_in(id__in) + return clone + + def _filter_union_id(self, union_id): + if not union_id: + return + cleaned_union_id = union_id.split('_') + # 如果union_id通不过本检查,代表可能不是本backend, 应该返回空 + if not self._check_union_id(union_id, cleaned_union_id): + self.queryset = self.queryset.none() + return + return self._perform_filter_union_id(union_id, cleaned_union_id) + + def _check_union_id(self, union_id, cleaned_union_id): + return union_id and len(cleaned_union_id) == self.union_id_length + + def _perform_filter_union_id(self, union_id, union_id_cleaned): + self.queryset = self.queryset.filter(union_id=union_id) + + def _filter_assets(self, assets): + assets_id = self.make_assets_as_id(assets) + if assets_id: + self.queryset = self.queryset.filter(asset_id__in=assets_id) + + def _filter_node(self, node): + pass + + def _filter_id_in(self, ids): + if ids and isinstance(ids, list): + self.queryset = self.queryset.filter(union_id__in=ids) + + @staticmethod + def clean_kwargs(kwargs): + return {k: v for k, v in kwargs.items() if v} + + def _filter_other(self, kwargs): + kwargs = self.clean_kwargs(kwargs) + if kwargs: + self.queryset = self.queryset.filter(**kwargs) + + def _filter_prefer(self, prefer, prefer_id): + pass + + def search(self, item): + qs = [] + for i in ['hostname', 'ip', 'username']: + kwargs = {i + '__startswith': item} + qs.append(Q(**kwargs)) + q = reduce(lambda x, y: x | y, qs) + clone = self._clone() + clone.queryset = clone.queryset.filter(q).distinct() + return clone + + +class SystemUserBackend(DBBackend): + model = SystemUser.assets.through + backend = 'system_user' + prefer = backend + base_score = 0 + union_id_length = 2 + + def _filter_prefer(self, prefer, prefer_id): + if prefer and prefer != self.prefer: + self.queryset = self.queryset.none() + + if prefer_id: + self.queryset = self.queryset.filter(systemuser__id=prefer_id) + + def _perform_filter_union_id(self, union_id, union_id_cleaned): + system_user_id, asset_id = union_id_cleaned + self.queryset = self.queryset.filter( + asset_id=asset_id, systemuser__id=system_user_id, + ) + + def _perform_delete_by_union_id(self, union_id_cleaned): + system_user_id, asset_id = union_id_cleaned + system_user = get_object_or_none(SystemUser, pk=system_user_id) + asset = get_object_or_none(Asset, pk=asset_id) + if all((system_user, asset)): + system_user.assets.remove(asset) + + def _filter_node(self, node): + if node: + self.queryset = self.queryset.filter(asset__nodes__id=node.id) + + def get_annotate(self): + kwargs = dict( + hostname=F("asset__hostname"), + ip=F("asset__ip"), + username=F("systemuser__username"), + password=F("systemuser__password"), + private_key=F("systemuser__private_key"), + public_key=F("systemuser__public_key"), + score=F("systemuser__priority") + self.base_score, + version=Value(0, IntegerField()), + date_created=F("systemuser__date_created"), + date_updated=F("systemuser__date_updated"), + asset_username=Concat(F("asset__id"), Value("_"), + F("systemuser__username"), + output_field=CharField()), + union_id=Concat(F("systemuser_id"), Value("_"), F("asset_id"), + output_field=CharField()), + org_id=F("asset__org_id"), + backend=Value(self.backend, CharField()) + ) + return kwargs + + def get_filter(self): + return dict( + systemuser__username_same_with_user=False, + ) + + def all(self): + kwargs = self.get_annotate() + filters = self.get_filter() + qs = self.model.objects.all().annotate(**kwargs) + if current_org.org_id() is not None: + filters['org_id'] = current_org.org_id() + qs = qs.filter(**filters) + qs = self.qs_to_values(qs) + return qs + + +class DynamicSystemUserBackend(SystemUserBackend): + backend = 'system_user_dynamic' + prefer = 'system_user' + union_id_length = 3 + + def get_annotate(self): + kwargs = super().get_annotate() + kwargs.update(dict( + username=F("systemuser__users__username"), + asset_username=Concat( + F("asset__id"), Value("_"), + F("systemuser__users__username"), + output_field=CharField() + ), + union_id=Concat( + F("systemuser_id"), Value("_"), F("asset_id"), + Value("_"), F("systemuser__users__id"), + output_field=CharField() + ), + users_count=Count('systemuser__users'), + )) + return kwargs + + def _perform_filter_union_id(self, union_id, union_id_cleaned): + system_user_id, asset_id, user_id = union_id_cleaned + self.queryset = self.queryset.filter( + asset_id=asset_id, systemuser_id=system_user_id, + union_id=union_id, + ) + + def _perform_delete_by_union_id(self, union_id_cleaned): + system_user_id, asset_id, user_id = union_id_cleaned + system_user = get_object_or_none(SystemUser, pk=system_user_id) + if not system_user: + return + system_user.users.remove(user_id) + if system_user.users.count() == 0: + system_user.assets.remove(asset_id) + + def get_filter(self): + return dict( + users_count__gt=0, + systemuser__username_same_with_user=True + ) + + +class AdminUserBackend(DBBackend): + model = Asset + backend = 'admin_user' + prefer = backend + base_score = 200 + + def _filter_prefer(self, prefer, prefer_id): + if prefer and prefer != self.backend: + self.queryset = self.queryset.none() + if prefer_id: + self.queryset = self.queryset.filter(admin_user__id=prefer_id) + + def _filter_node(self, node): + if node: + self.queryset = self.queryset.filter(nodes__id=node.id) + + def _perform_filter_union_id(self, union_id, union_id_cleaned): + admin_user_id, asset_id = union_id_cleaned + self.queryset = self.queryset.filter( + id=asset_id, admin_user_id=admin_user_id, + ) + + def _perform_delete_by_union_id(self, union_id_cleaned): + raise PermissionError("Could remove asset admin user") + + def all(self): + qs = self.model.objects.all().annotate( + asset_id=F("id"), + username=F("admin_user__username"), + password=F("admin_user__password"), + private_key=F("admin_user__private_key"), + public_key=F("admin_user__public_key"), + score=Value(self.base_score, IntegerField()), + version=Value(0, IntegerField()), + date_updated=F("admin_user__date_updated"), + asset_username=Concat(F("id"), Value("_"), F("admin_user__username"), output_field=CharField()), + union_id=Concat(F("admin_user_id"), Value("_"), F("id"), output_field=CharField()), + backend=Value(self.backend, CharField()), + ) + qs = self.qs_to_values(qs) + return qs + + +class AuthbookBackend(DBBackend): + model = AuthBook + backend = 'db' + prefer = backend + base_score = 400 + + def _filter_node(self, node): + if node: + self.queryset = self.queryset.filter(asset__nodes__id=node.id) + + def _filter_prefer(self, prefer, prefer_id): + if not prefer or not prefer_id: + return + if prefer.lower() == "admin_user": + model = AdminUser + elif prefer.lower() == "system_user": + model = SystemUser + else: + self.queryset = self.queryset.none() + return + obj = get_object_or_none(model, pk=prefer_id) + if obj is None: + self.queryset = self.queryset.none() + return + username = obj.get_username() + if isinstance(username, str): + self.queryset = self.queryset.filter(username=username) + # dynamic system user return more username + else: + self.queryset = self.queryset.filter(username__in=username) + + def _perform_filter_union_id(self, union_id, union_id_cleaned): + authbook_id, asset_id = union_id_cleaned + self.queryset = self.queryset.filter( + id=authbook_id, asset_id=asset_id, + ) + + def _perform_delete_by_union_id(self, union_id_cleaned): + authbook_id, asset_id = union_id_cleaned + authbook = get_object_or_none(AuthBook, pk=authbook_id) + if authbook.is_latest: + raise PermissionError("Latest version could be delete") + AuthBook.objects.filter(id=authbook_id).delete() + + def all(self): + qs = self.model.objects.all().annotate( + hostname=F("asset__hostname"), + ip=F("asset__ip"), + score=F('version') + self.base_score, + asset_username=Concat(F("asset__id"), Value("_"), F("username"), output_field=CharField()), + union_id=Concat(F("id"), Value("_"), F("asset_id"), output_field=CharField()), + backend=Value(self.backend, CharField()), + ) + qs = self.qs_to_values(qs) + return qs diff --git a/apps/assets/backends/manager.py b/apps/assets/backends/manager.py index 75b9c38b8..d686cb922 100644 --- a/apps/assets/backends/manager.py +++ b/apps/assets/backends/manager.py @@ -1,110 +1,162 @@ # -*- coding: utf-8 -*- # +from itertools import chain, groupby from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist -from .base import AssetUserQuerySet -from .db import AuthBookBackend -from .system_user import SystemUserBackend -from .admin_user import AdminUserBackend +from orgs.utils import current_org +from common.utils import get_logger, lazyproperty +from common.struct import QuerySetChain + +from ..models import AssetUser, AuthBook +from .db import ( + AuthbookBackend, SystemUserBackend, AdminUserBackend, + DynamicSystemUserBackend +) + +logger = get_logger(__name__) class NotSupportError(Exception): pass -class AssetUserManager: - """ - 资产用户管理器 - """ +class AssetUserQueryset: ObjectDoesNotExist = ObjectDoesNotExist MultipleObjectsReturned = MultipleObjectsReturned - NotSupportError = NotSupportError - MSG_NOT_EXIST = '{} Object matching query does not exist' - MSG_MULTIPLE = '{} get() returned more than one object ' \ - '-- it returned {}!' - backends = ( - ('db', AuthBookBackend), + def __init__(self, backends=()): + self.backends = backends + self._distinct_queryset = None + + def backends_queryset(self): + return [b.get_queryset() for b in self.backends] + + @lazyproperty + def backends_counts(self): + return [b.count() for b in self.backends] + + def filter(self, hostname=None, ip=None, username=None, + assets=None, asset=None, node=None, + id=None, prefer_id=None, prefer=None, id__in=None): + if not assets and asset: + assets = [asset] + + kwargs = dict( + hostname=hostname, ip=ip, username=username, + assets=assets, node=node, prefer=prefer, prefer_id=prefer_id, + id__in=id__in, union_id=id, + ) + logger.debug("Filter: {}".format(kwargs)) + backends = [] + for backend in self.backends: + clone = backend.filter(**kwargs) + backends.append(clone) + return self._clone(backends) + + def _clone(self, backends=None): + if backends is None: + backends = self.backends + return self.__class__(backends) + + def search(self, item): + backends = [] + for backend in self.backends: + new = backend.search(item) + backends.append(new) + return self._clone(backends) + + def distinct(self): + logger.debug("Distinct asset user queryset") + queryset_chain = chain(*(backend.get_queryset() for backend in self.backends)) + queryset_sorted = sorted( + queryset_chain, + key=lambda item: (item["asset_username"], item["score"]), + reverse=True, + ) + results = groupby(queryset_sorted, key=lambda item: item["asset_username"]) + final = [next(result[1]) for result in results] + self._distinct_queryset = final + return self + + def get(self, latest=False, **kwargs): + queryset = self.filter(**kwargs) + if latest: + queryset = queryset.distinct() + queryset = list(queryset) + count = len(queryset) + if count == 1: + data = queryset[0] + return data + elif count > 1: + msg = 'Should return 1 record, but get {}'.format(count) + raise MultipleObjectsReturned(msg) + else: + msg = 'No record found(org is {})'.format(current_org.name) + raise ObjectDoesNotExist(msg) + + def get_latest(self, **kwargs): + return self.get(latest=True, **kwargs) + + @staticmethod + def to_asset_user(data): + obj = AssetUser() + for k, v in data.items(): + setattr(obj, k, v) + return obj + + @property + def queryset(self): + if self._distinct_queryset is not None: + return self._distinct_queryset + return QuerySetChain(self.backends_queryset()) + + def count(self): + if self._distinct_queryset is not None: + return len(self._distinct_queryset) + else: + return sum(self.backends_counts) + + def __getitem__(self, ndx): + return self.queryset.__getitem__(ndx) + + def __iter__(self): + self._data = iter(self.queryset) + return self + + def __next__(self): + return self.to_asset_user(next(self._data)) + + +class AssetUserManager: + support_backends = ( + ('db', AuthbookBackend), ('system_user', SystemUserBackend), ('admin_user', AdminUserBackend), + ('system_user_dynamic', DynamicSystemUserBackend), ) - _prefer = "system_user" + def __init__(self): + self.backends = [backend() for name, backend in self.support_backends] + self._queryset = AssetUserQueryset(self.backends) - def filter(self, username=None, assets=None, latest=True, prefer=None, prefer_id=None): - if assets is not None and not assets: - return AssetUserQuerySet([]) + def all(self): + return self._queryset - if prefer: - self._prefer = prefer - - instances_map = {} - instances = [] - for name, backend in self.backends: - # if name != "db": - # continue - _instances = backend.filter( - username=username, assets=assets, latest=latest, - prefer=self._prefer, prefer_id=prefer_id, - ) - instances_map[name] = _instances - - # 如果不是获取最新版本,就不再merge - if not latest: - for _instances in instances_map.values(): - instances.extend(_instances) - return AssetUserQuerySet(instances) - - # merge的顺序 - ordering = ["db"] - if self._prefer == "system_user": - ordering.extend(["system_user", "admin_user"]) + def delete(self, obj): + name_backends_map = dict(self.support_backends) + backend_name = obj.backend + backend_cls = name_backends_map.get(backend_name) + union_id = obj.union_id + if backend_cls: + backend_cls().delete(union_id) else: - ordering.extend(["admin_user", "system_user"]) - # 根据prefer决定优先使用系统用户或管理用户谁的 - ordering_instances = [instances_map.get(i, []) for i in ordering] - instances = self._merge_instances(*ordering_instances) - return AssetUserQuerySet(instances) - - def get(self, username, asset, **kwargs): - instances = self.filter(username, assets=[asset], **kwargs) - if len(instances) == 1: - return instances[0] - elif len(instances) == 0: - self.raise_does_not_exist(self.__class__.__name__) - else: - self.raise_multiple_return(self.__class__.__name__, len(instances)) - - def raise_does_not_exist(self, name): - raise self.ObjectDoesNotExist(self.MSG_NOT_EXIST.format(name)) - - def raise_multiple_return(self, name, length): - raise self.MultipleObjectsReturned(self.MSG_MULTIPLE.format(name, length)) + raise ObjectDoesNotExist("Not backend found") @staticmethod def create(**kwargs): - instance = AuthBookBackend.create(**kwargs) - return instance + authbook = AuthBook(**kwargs) + authbook.save() + return authbook - def all(self): - return self.filter() - - def prefer(self, s): - self._prefer = s - return self - - @staticmethod - def none(): - return AssetUserQuerySet() - - @staticmethod - def _merge_instances(*args): - instances = list(args[0]) - keywords = [obj.keyword for obj in instances] - - for _instances in args[1:]: - need_merge_instances = [obj for obj in _instances if obj.keyword not in keywords] - need_merge_keywords = [obj.keyword for obj in need_merge_instances] - instances.extend(need_merge_instances) - keywords.extend(need_merge_keywords) - return instances + def __getattr__(self, item): + return getattr(self._queryset, item) diff --git a/apps/assets/backends/system_user.py b/apps/assets/backends/system_user.py deleted file mode 100644 index 8dda67d2a..000000000 --- a/apps/assets/backends/system_user.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# - -import itertools - -from assets.models import SystemUser -from .asset_user import AssetUserBackend - - -class SystemUserBackend(AssetUserBackend): - model = SystemUser - backend = 'SystemUser' - - @classmethod - def filter_queryset_more(cls, queryset): - queryset = cls._distinct_system_users_by_username(queryset) - return queryset - - @classmethod - def _distinct_system_users_by_username(cls, system_users): - system_users = sorted( - system_users, - key=lambda su: (su.username, su.priority, su.date_updated), - reverse=True, - ) - results = itertools.groupby(system_users, key=lambda su: su.username) - system_users = [next(result[1]) for result in results] - return system_users - - diff --git a/apps/assets/backends/utils.py b/apps/assets/backends/utils.py index 62be16c1d..fbe190ba3 100644 --- a/apps/assets/backends/utils.py +++ b/apps/assets/backends/utils.py @@ -3,14 +3,5 @@ # from django.conf import settings -from .db import AuthBookBackend # from .vault import VaultBackend - -def get_backend(): - default_backend = AuthBookBackend - - # if settings.BACKEND_ASSET_USER_AUTH_VAULT: - # return VaultBackend - - return default_backend diff --git a/apps/assets/backends/vault.py b/apps/assets/backends/vault.py index d21245247..f19a64d9a 100644 --- a/apps/assets/backends/vault.py +++ b/apps/assets/backends/vault.py @@ -1,11 +1,4 @@ # -*- coding: utf-8 -*- # -from .base import BaseBackend - -class VaultBackend(BaseBackend): - - @classmethod - def filter(cls, username=None, asset=None, latest=True): - pass diff --git a/apps/assets/forms/asset.py b/apps/assets/forms/asset.py index 3a7a0f220..54d97f036 100644 --- a/apps/assets/forms/asset.py +++ b/apps/assets/forms/asset.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- # +from itertools import groupby from django import forms from django.utils.translation import gettext_lazy as _ from common.utils import get_logger from orgs.mixins.forms import OrgModelForm -from ..models import Asset +from ..models import Asset, Platform logger = get_logger(__file__) @@ -42,9 +43,26 @@ class AssetCreateUpdateForm(OrgModelForm): ] nodes_field.choices = nodes_choices + @staticmethod + def sorted_platform(platform): + if platform['base'] == 'Other': + return 'zz' + return platform['base'] + def set_platform_to_name(self): + choices = [] + platforms = Platform.objects.all().values('name', 'base') + platforms_sorted = sorted(platforms, key=self.sorted_platform) + platforms_grouped = groupby(platforms_sorted, key=lambda x: x['base']) + for i in platforms_grouped: + base = i[0] + grouped = sorted(i[1], key=lambda x: x['name']) + grouped = [(j['name'], j['name']) for j in grouped] + choices.append( + (base, grouped) + ) platform_field = self.fields['platform'] - platform_field.to_field_name = 'name' + platform_field.choices = choices if self.instance: self.initial['platform'] = self.instance.platform.name diff --git a/apps/assets/forms/user.py b/apps/assets/forms/user.py index 3d67b434b..ff8d27dfd 100644 --- a/apps/assets/forms/user.py +++ b/apps/assets/forms/user.py @@ -88,7 +88,9 @@ class SystemUserForm(OrgModelForm, PasswordAndKeyAuthForm): fields = [ 'name', 'username', 'protocol', 'auto_generate_key', 'password', 'private_key', 'auto_push', 'sudo', + 'username_same_with_user', 'comment', 'shell', 'priority', 'login_mode', 'cmd_filters', + 'sftp_root', ] widgets = { 'name': forms.TextInput(attrs={'placeholder': _('Name')}), @@ -97,11 +99,17 @@ class SystemUserForm(OrgModelForm, PasswordAndKeyAuthForm): 'class': 'select2', 'data-placeholder': _('Command filter') }), } + labels = { + 'username_same_with_user': _("Username same with user"), + } help_texts = { 'auto_push': _('Auto push system user to asset'), 'priority': _('1-100, High level will be using login asset as default, ' 'if user was granted more than 2 system user'), 'login_mode': _('If you choose manual login mode, you do not ' 'need to fill in the username and password.'), - 'sudo': _("Use comma split multi command, ex: /bin/whoami,/bin/ifconfig") + 'sudo': _("Use comma split multi command, ex: /bin/whoami,/bin/ifconfig"), + 'sftp_root': _("SFTP root dir, tmp, home or custom"), + 'username_same_with_user': _("Username is dynamic, When connect asset, using current user's username"), + # 'username_same_with_user': _("用户名是动态的,登录资产时使用当前用户的用户名登录"), } diff --git a/apps/assets/hands.py b/apps/assets/hands.py index 7c83e1332..ee13e589e 100644 --- a/apps/assets/hands.py +++ b/apps/assets/hands.py @@ -6,7 +6,7 @@ Other module of this app shouldn't connect with other app. - :copyright: (c) 2014-2018 by Jumpserver Team. + :copyright: (c) 2014-2018 by JumpServer Team. :license: GPL v2, see LICENSE for more details. """ diff --git a/apps/assets/migrations/0047_assetuser.py b/apps/assets/migrations/0047_assetuser.py new file mode 100644 index 000000000..6c309a0f7 --- /dev/null +++ b/apps/assets/migrations/0047_assetuser.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.7 on 2020-01-06 07:34 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('assets', '0046_auto_20191218_1705'), + ] + + operations = [ + migrations.CreateModel( + name='AssetUser', + fields=[ + ], + options={ + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('assets.authbook',), + ), + ] diff --git a/apps/assets/migrations/0048_auto_20191230_1512.py b/apps/assets/migrations/0048_auto_20191230_1512.py new file mode 100644 index 000000000..b4bf9f9bc --- /dev/null +++ b/apps/assets/migrations/0048_auto_20191230_1512.py @@ -0,0 +1,35 @@ +# Generated by Django 2.2.7 on 2019-12-30 07:12 + +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('assets', '0047_assetuser'), + ] + + operations = [ + migrations.RemoveField( + model_name='authbook', + name='is_active', + ), + migrations.AddField( + model_name='systemuser', + name='username_same_with_user', + field=models.BooleanField(default=False, verbose_name='Username same with user'), + ), + migrations.AddField( + model_name='systemuser', + name='users', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Users'), + ), + migrations.AddField( + model_name='systemuser', + name='groups', + field=models.ManyToManyField(blank=True, to='users.UserGroup', + verbose_name='User groups'), + ), + ] diff --git a/apps/assets/migrations/0049_systemuser_sftp_root.py b/apps/assets/migrations/0049_systemuser_sftp_root.py new file mode 100644 index 000000000..d8e992e25 --- /dev/null +++ b/apps/assets/migrations/0049_systemuser_sftp_root.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.7 on 2020-01-19 07:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('assets', '0048_auto_20191230_1512'), + ] + + operations = [ + migrations.AddField( + model_name='systemuser', + name='sftp_root', + field=models.CharField(default='tmp', max_length=128, verbose_name='SFTP Root'), + ), + ] diff --git a/apps/assets/models/__init__.py b/apps/assets/models/__init__.py index db9c54aed..1bed74a16 100644 --- a/apps/assets/models/__init__.py +++ b/apps/assets/models/__init__.py @@ -1,6 +1,8 @@ +from .base import * from .asset import * from .label import Label from .user import * +from .asset_user import * from .cluster import * from .group import * from .domain import * diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index 70e2abb2a..39ea8420f 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext_lazy as _ from common.fields.model import JsonDictTextField from common.utils import lazyproperty from orgs.mixins.models import OrgModelMixin, OrgManager +from .base import ConnectivityMixin from .utils import Connectivity __all__ = ['Asset', 'ProtocolsMixin', 'Platform'] @@ -40,10 +41,11 @@ def default_node(): class AssetManager(OrgManager): - def get_queryset(self): - return super().get_queryset().annotate( - platform_base=models.F('platform__base') - ) + # def get_queryset(self): + # return super().get_queryset().annotate( + # platform_base=models.F('platform__base') + # ) + pass class AssetQuerySet(models.QuerySet): @@ -243,6 +245,13 @@ class Asset(ProtocolsMixin, NodesRelationMixin, OrgModelMixin): def platform_base(self): return self.platform.base + @lazyproperty + def admin_user_username(self): + """求可连接性时,直接用用户名去取,避免再查一次admin user + serializer 中直接通过annotate方式返回了这个 + """ + return self.admin_user.username + def is_windows(self): return self.platform.is_windows() @@ -275,9 +284,11 @@ class Asset(ProtocolsMixin, NodesRelationMixin, OrgModelMixin): def connectivity(self): if self._connectivity: return self._connectivity - if not self.admin_user: + if not self.admin_user_username: return Connectivity.unknown() - connectivity = self.admin_user.get_asset_connectivity(self) + connectivity = ConnectivityMixin.get_asset_username_connectivity( + self, self.admin_user_username + ) return connectivity @connectivity.setter @@ -290,7 +301,7 @@ class Asset(ProtocolsMixin, NodesRelationMixin, OrgModelMixin): if not self.admin_user: return {} - self.admin_user.load_specific_asset_auth(self) + self.admin_user.load_asset_special_auth(self) info = { 'username': self.admin_user.username, 'password': self.admin_user.password, diff --git a/apps/assets/models/asset_user.py b/apps/assets/models/asset_user.py new file mode 100644 index 000000000..118d4549b --- /dev/null +++ b/apps/assets/models/asset_user.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# +from .authbook import AuthBook + + +class AssetUser(AuthBook): + hostname = "" + ip = "" + backend = "" + union_id = "" + asset_username = "" + + class Meta: + proxy = True diff --git a/apps/assets/models/authbook.py b/apps/assets/models/authbook.py index 0243b43fb..0a0154100 100644 --- a/apps/assets/models/authbook.py +++ b/apps/assets/models/authbook.py @@ -5,26 +5,24 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from orgs.mixins.models import OrgManager -from .base import AssetUser +from .base import BaseUser __all__ = ['AuthBook'] class AuthBookQuerySet(models.QuerySet): - def latest_version(self): - return self.filter(is_latest=True).filter(is_active=True) + return self.filter(is_latest=True) class AuthBookManager(OrgManager): pass -class AuthBook(AssetUser): +class AuthBook(BaseUser): asset = models.ForeignKey('assets.Asset', on_delete=models.CASCADE, verbose_name=_('Asset')) is_latest = models.BooleanField(default=False, verbose_name=_('Latest version')) version = models.IntegerField(default=1, verbose_name=_('Version')) - is_active = models.BooleanField(default=True, verbose_name=_("Is active")) objects = AuthBookManager.from_queryset(AuthBookQuerySet)() backend = "db" diff --git a/apps/assets/models/base.py b/apps/assets/models/base.py index 5d0f3cef1..3c9a481a5 100644 --- a/apps/assets/models/base.py +++ b/apps/assets/models/base.py @@ -12,98 +12,29 @@ from django.utils.translation import ugettext_lazy as _ from django.conf import settings from common.utils import ( - signer, ssh_key_string_to_obj, ssh_key_gen, get_logger + ssh_key_string_to_obj, ssh_key_gen, get_logger, lazyproperty ) from common.validators import alphanumeric from common import fields from orgs.mixins.models import OrgModelMixin -from .utils import private_key_validator, Connectivity +from .utils import Connectivity logger = get_logger(__file__) -class AssetUser(OrgModelMixin): - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField(max_length=128, verbose_name=_('Name')) - username = models.CharField(max_length=32, blank=True, verbose_name=_('Username'), validators=[alphanumeric], db_index=True) - password = fields.EncryptCharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) - private_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH private key')) - public_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH public key')) - comment = models.TextField(blank=True, verbose_name=_('Comment')) - date_created = models.DateTimeField(auto_now_add=True, verbose_name=_("Date created")) - date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated")) - created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by')) - +class ConnectivityMixin: CONNECTIVITY_ASSET_CACHE_KEY = "ASSET_USER_{}_{}_ASSET_CONNECTIVITY" CONNECTIVITY_AMOUNT_CACHE_KEY = "ASSET_USER_{}_{}_CONNECTIVITY_AMOUNT" - ASSETS_AMOUNT_CACHE_KEY = "ASSET_USER_{}_ASSETS_AMOUNT" ASSET_USER_CACHE_TIME = 3600 * 24 - - _prefer = "system_user" - _assets_amount = None - - @property - def private_key_obj(self): - if self.private_key: - return ssh_key_string_to_obj(self.private_key, password=self.password) - else: - return None - - @property - def private_key_file(self): - if not self.private_key_obj: - return None - project_dir = settings.PROJECT_DIR - tmp_dir = os.path.join(project_dir, 'tmp') - key_name = '.' + md5(self.private_key.encode('utf-8')).hexdigest() - key_path = os.path.join(tmp_dir, key_name) - if not os.path.exists(key_path): - self.private_key_obj.write_private_key_file(key_path) - os.chmod(key_path, 0o400) - return key_path - - @property - def public_key_obj(self): - if self.public_key: - try: - return sshpubkeys.SSHKey(self.public_key) - except TabError: - pass - return None + id = '' + username = '' @property def part_id(self): i = '-'.join(str(self.id).split('-')[:3]) return i - def get_private_key(self): - if not self.private_key_obj: - return None - string_io = io.StringIO() - self.private_key_obj.write_private_key(string_io) - private_key = string_io.getvalue() - return private_key - - def get_related_assets(self): - assets = self.assets.all() - return assets - - def set_auth(self, password=None, private_key=None, public_key=None): - update_fields = [] - if password: - self.password = password - update_fields.append('password') - if private_key: - self.private_key = private_key - update_fields.append('private_key') - if public_key: - self.public_key = public_key - update_fields.append('public_key') - - if update_fields: - self.save(update_fields=update_fields) - def set_connectivity(self, summary): unreachable = summary.get('dark', {}).keys() reachable = summary.get('contacted', {}).keys() @@ -150,20 +81,10 @@ class AssetUser(OrgModelMixin): cache.set(cache_key, amount, self.ASSET_USER_CACHE_TIME) return amount - @property - def assets_amount(self): - if self._assets_amount is not None: - return self._assets_amount - cache_key = self.ASSETS_AMOUNT_CACHE_KEY.format(self.id) - cached = cache.get(cache_key) - if not cached: - cached = self.get_related_assets().count() - cache.set(cache_key, cached, self.ASSET_USER_CACHE_TIME) - return cached - - def expire_assets_amount(self): - cache_key = self.ASSETS_AMOUNT_CACHE_KEY.format(self.id) - cache.delete(cache_key) + @classmethod + def get_asset_username_connectivity(cls, asset, username): + key = cls.CONNECTIVITY_ASSET_CACHE_KEY.format(username, asset.id) + return Connectivity.get(key) def get_asset_connectivity(self, asset): key = self.get_asset_connectivity_key(asset) @@ -176,28 +97,103 @@ class AssetUser(OrgModelMixin): key = self.get_asset_connectivity_key(asset) Connectivity.set(key, c) - def get_asset_user(self, asset): + +class AuthMixin: + private_key = '' + password = '' + public_key = '' + username = '' + _prefer = 'system_user' + + @property + def private_key_obj(self): + if self.private_key: + key_obj = ssh_key_string_to_obj(self.private_key, password=self.password) + return key_obj + else: + return None + + @property + def private_key_file(self): + if not self.private_key_obj: + return None + project_dir = settings.PROJECT_DIR + tmp_dir = os.path.join(project_dir, 'tmp') + key_name = '.' + md5(self.private_key.encode('utf-8')).hexdigest() + key_path = os.path.join(tmp_dir, key_name) + if not os.path.exists(key_path): + self.private_key_obj.write_private_key_file(key_path) + os.chmod(key_path, 0o400) + return key_path + + def get_private_key(self): + if not self.private_key_obj: + return None + string_io = io.StringIO() + self.private_key_obj.write_private_key(string_io) + private_key = string_io.getvalue() + return private_key + + @property + def public_key_obj(self): + if self.public_key: + try: + return sshpubkeys.SSHKey(self.public_key) + except TabError: + pass + return None + + def set_auth(self, password=None, private_key=None, public_key=None): + update_fields = [] + if password: + self.password = password + update_fields.append('password') + if private_key: + self.private_key = private_key + update_fields.append('private_key') + if public_key: + self.public_key = public_key + update_fields.append('public_key') + + if update_fields: + self.save(update_fields=update_fields) + + def has_special_auth(self, asset=None): + from .authbook import AuthBook + queryset = AuthBook.objects.filter(username=self.username) + if asset: + queryset = queryset.filter(asset=asset) + return queryset.exists() + + def get_asset_user(self, asset, username=None): from ..backends import AssetUserManager + if username is None: + username = self.username try: - manager = AssetUserManager().prefer(self._prefer) - other = manager.get(username=self.username, asset=asset, prefer_id=self.id) + manager = AssetUserManager() + other = manager.get_latest( + username=username, asset=asset, + prefer_id=self.id, prefer=self._prefer, + ) return other except Exception as e: logger.error(e, exc_info=True) return None - def load_specific_asset_auth(self, asset): - instance = self.get_asset_user(asset) + def load_asset_special_auth(self, asset=None, username=None): + if not asset: + return self + + instance = self.get_asset_user(asset, username=username) if instance: self._merge_auth(instance) def _merge_auth(self, other): if other.password: self.password = other.password - if other.public_key: - self.public_key = other.public_key - if other.private_key: + if other.public_key or other.private_key: self.private_key = other.private_key + self.public_key = other.public_key def clear_auth(self): self.password = '' @@ -216,19 +212,57 @@ class AssetUser(OrgModelMixin): ) return private_key, public_key - def auto_gen_auth(self): - password = str(uuid.uuid4()) - private_key, public_key = ssh_key_gen( - username=self.username - ) + def auto_gen_auth(self, password=True, key=True): + _password = None + _private_key = None + _public_key = None + + if password: + _password = self.gen_password() + if key: + _private_key, _public_key = self.gen_key(self.username) self.set_auth( - password=password, private_key=private_key, - public_key=public_key + password=_password, private_key=_private_key, + public_key=_public_key ) - def auto_gen_auth_password(self): - password = str(uuid.uuid4()) - self.set_auth(password=password) + +class BaseUser(OrgModelMixin, AuthMixin, ConnectivityMixin): + id = models.UUIDField(default=uuid.uuid4, primary_key=True) + name = models.CharField(max_length=128, verbose_name=_('Name')) + username = models.CharField(max_length=32, blank=True, verbose_name=_('Username'), validators=[alphanumeric], db_index=True) + password = fields.EncryptCharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) + private_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH private key')) + public_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH public key')) + comment = models.TextField(blank=True, verbose_name=_('Comment')) + date_created = models.DateTimeField(auto_now_add=True, verbose_name=_("Date created")) + date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated")) + created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by')) + + ASSETS_AMOUNT_CACHE_KEY = "ASSET_USER_{}_ASSETS_AMOUNT" + ASSET_USER_CACHE_TIME = 600 + + _prefer = "system_user" + + def get_related_assets(self): + assets = self.assets.filter(org_id=self.org_id) + return assets + + def get_username(self): + return self.username + + @lazyproperty + def assets_amount(self): + cache_key = self.ASSETS_AMOUNT_CACHE_KEY.format(self.id) + cached = cache.get(cache_key) + if not cached: + cached = self.get_related_assets().count() + cache.set(cache_key, cached, self.ASSET_USER_CACHE_TIME) + return cached + + def expire_assets_amount(self): + cache_key = self.ASSETS_AMOUNT_CACHE_KEY.format(self.id) + cache.delete(cache_key) def _to_secret_json(self): """Push system user use it""" @@ -240,26 +274,6 @@ class AssetUser(OrgModelMixin): 'private_key': self.private_key_file, } - def generate_id_with_asset(self, asset): - user_id = [self.part_id] - asset_id = str(asset.id).split('-')[3:] - ids = user_id + asset_id - return '-'.join(ids) - - def construct_to_authbook(self, asset): - from . import AuthBook - fields = [ - 'name', 'username', 'comment', 'org_id', - 'password', 'private_key', 'public_key', - 'date_created', 'date_updated', 'created_by' - ] - i = self.generate_id_with_asset(asset) - obj = AuthBook(id=i, asset=asset, version=0, is_latest=True) - for field in fields: - value = getattr(self, field) - setattr(obj, field, value) - return obj - class Meta: abstract = True diff --git a/apps/assets/models/domain.py b/apps/assets/models/domain.py index b89c3b128..2f4cc82b3 100644 --- a/apps/assets/models/domain.py +++ b/apps/assets/models/domain.py @@ -10,7 +10,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from orgs.mixins.models import OrgModelMixin -from .base import AssetUser +from .base import BaseUser __all__ = ['Domain', 'Gateway'] @@ -39,7 +39,7 @@ class Domain(OrgModelMixin): return random.choice(self.gateways) -class Gateway(AssetUser): +class Gateway(BaseUser): PROTOCOL_SSH = 'ssh' PROTOCOL_RDP = 'rdp' PROTOCOL_CHOICES = ( diff --git a/apps/assets/models/node.py b/apps/assets/models/node.py index f349eb9f6..2a884a6a1 100644 --- a/apps/assets/models/node.py +++ b/apps/assets/models/node.py @@ -11,9 +11,9 @@ from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext from django.core.cache import cache -from common.utils import get_logger, timeit, lazyproperty +from common.utils import get_logger, lazyproperty from orgs.mixins.models import OrgModelMixin, OrgManager -from orgs.utils import set_current_org, get_current_org, tmp_to_org +from orgs.utils import get_current_org, tmp_to_org, current_org from orgs.models import Organization @@ -26,63 +26,108 @@ class NodeQuerySet(models.QuerySet): raise PermissionError("Bulk delete node deny") +class TreeCache: + updated_time_cache_key = 'NODE_TREE_UPDATED_AT_{}' + cache_time = 3600 + assets_updated_time_cache_key = 'NODE_TREE_ASSETS_UPDATED_AT_{}' + + def __init__(self, tree, org_id): + now = time.time() + self.created_time = now + self.assets_created_time = now + self.tree = tree + self.org_id = org_id + + def _has_changed(self, tp="tree"): + if tp == "assets": + key = self.assets_updated_time_cache_key.format(self.org_id) + else: + key = self.updated_time_cache_key.format(self.org_id) + updated_time = cache.get(key, 0) + if updated_time > self.created_time: + return True + else: + return False + + @classmethod + def set_changed(cls, tp="tree", t=None, org_id=None): + if org_id is None: + org_id = current_org.id + if tp == "assets": + key = cls.assets_updated_time_cache_key.format(org_id) + else: + key = cls.updated_time_cache_key.format(org_id) + ttl = cls.cache_time + if not t: + t = time.time() + cache.set(key, t, ttl) + + def tree_has_changed(self): + return self._has_changed("tree") + + def set_tree_changed(self, t=None): + logger.debug("Set tree tree changed") + self.__class__.set_changed(t=t, tp="tree") + + def assets_has_changed(self): + return self._has_changed("assets") + + def set_tree_assets_changed(self, t=None): + logger.debug("Set tree assets changed") + self.__class__.set_changed(t=t, tp="assets") + + def get(self): + if self.tree_has_changed(): + self.renew() + return self.tree + if self.assets_has_changed(): + self.tree.init_assets() + return self.tree + + def renew(self): + new_obj = self.__class__.new(self.org_id) + self.tree = new_obj.tree + self.created_time = new_obj.created_time + self.assets_created_time = new_obj.assets_created_time + + @classmethod + def new(cls, org_id=None): + from ..utils import TreeService + logger.debug("Create node tree") + if not org_id: + org_id = current_org.id + with tmp_to_org(org_id): + tree = TreeService.new() + obj = cls(tree, org_id) + obj.tree = tree + return obj + + class TreeMixin: - tree_created_time = None - tree_updated_time_cache_key = 'NODE_TREE_UPDATED_AT' - tree_cache_time = 3600 - tree_assets_cache_key = 'NODE_TREE_ASSETS_UPDATED_AT' - tree_assets_created_time = None - _tree_service = None + _org_tree_map = {} @classmethod def tree(cls): - from ..utils import TreeService - tree_updated_time = cache.get(cls.tree_updated_time_cache_key, 0) - now = time.time() - # 什么时候重新初始化 _tree_service - if not cls.tree_created_time or \ - tree_updated_time > cls.tree_created_time: - logger.debug("Create node tree") - tree = TreeService.new() - cls.tree_created_time = now - cls.tree_assets_created_time = now - cls._tree_service = tree - return tree - # 是否要重新初始化节点资产 - node_assets_updated_time = cache.get(cls.tree_assets_cache_key, 0) - if not cls.tree_assets_created_time or \ - node_assets_updated_time > cls.tree_assets_created_time: - cls._tree_service.init_assets() - cls.tree_assets_created_time = now - logger.debug("Refresh node tree assets") - return cls._tree_service + org_id = current_org.org_id() + t = cls.get_local_tree_cache(org_id) + + if t is None: + t = TreeCache.new() + cls._org_tree_map[org_id] = t + return t.get() + + @classmethod + def get_local_tree_cache(cls, org_id=None): + t = cls._org_tree_map.get(org_id) + return t @classmethod def refresh_tree(cls, t=None): - logger.debug("Refresh node tree") - key = cls.tree_updated_time_cache_key - ttl = cls.tree_cache_time - if not t: - t = time.time() - cache.set(key, t, ttl) + TreeCache.set_changed(tp="tree", t=t, org_id=current_org.id) @classmethod def refresh_node_assets(cls, t=None): - logger.debug("Refresh node assets") - key = cls.tree_assets_cache_key - ttl = cls.tree_cache_time - if not t: - t = time.time() - cache.set(key, t, ttl) - - @staticmethod - def refresh_user_tree_cache(): - """ - 当节点-节点关系,节点-资产关系发生变化时,应该刷新用户授权树缓存 - :return: - """ - from perms.utils.asset_permission import AssetPermissionUtilV2 - AssetPermissionUtilV2.expire_all_user_tree_cache() + TreeCache.set_changed(tp="assets", t=t, org_id=current_org.id) class FamilyMixin: @@ -376,15 +421,6 @@ class SomeNodesMixin: ) return obj - @classmethod - def empty_node(cls): - with tmp_to_org(Organization.system()): - defaults = {'value': cls.empty_value} - obj, created = cls.objects.get_or_create( - defaults=defaults, key=cls.empty_key - ) - return obj - @classmethod def default_node(cls): with tmp_to_org(Organization.default()): @@ -413,7 +449,6 @@ class SomeNodesMixin: @classmethod def initial_some_nodes(cls): cls.default_node() - cls.empty_node() cls.ungrouped_node() cls.favorite_node() @@ -523,13 +558,13 @@ class Node(OrgModelMixin, SomeNodesMixin, TreeMixin, FamilyMixin, FullValueMixin tree_node = TreeNode(**data) return tree_node - def has_children_or_contains_assets(self): - if self.children or self.get_assets(): + def has_children_or_has_assets(self): + if self.children or self.get_assets().exists(): return True return False def delete(self, using=None, keep_parents=False): - if self.has_children_or_contains_assets(): + if self.has_children_or_has_assets(): return return super().delete(using=using, keep_parents=keep_parents) diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py index 053ca0f77..40f2b8583 100644 --- a/apps/assets/models/user.py +++ b/apps/assets/models/user.py @@ -4,14 +4,12 @@ import logging -from functools import reduce from django.db import models -from django.db.models import Q from django.utils.translation import ugettext_lazy as _ from django.core.validators import MinValueValidator, MaxValueValidator from common.utils import signer -from .base import AssetUser +from .base import BaseUser from .asset import Asset @@ -19,7 +17,7 @@ __all__ = ['AdminUser', 'SystemUser'] logger = logging.getLogger(__name__) -class AdminUser(AssetUser): +class AdminUser(BaseUser): """ A privileged user that ansible can use it to push system user and so on """ @@ -87,7 +85,7 @@ class AdminUser(AssetUser): continue -class SystemUser(AssetUser): +class SystemUser(BaseUser): PROTOCOL_SSH = 'ssh' PROTOCOL_RDP = 'rdp' PROTOCOL_TELNET = 'telnet' @@ -107,9 +105,11 @@ class SystemUser(AssetUser): (LOGIN_AUTO, _('Automatic login')), (LOGIN_MANUAL, _('Manually login')) ) - + username_same_with_user = models.BooleanField(default=False, verbose_name=_("Username same with user")) nodes = models.ManyToManyField('assets.Node', blank=True, verbose_name=_("Nodes")) assets = models.ManyToManyField('assets.Asset', blank=True, verbose_name=_("Assets")) + users = models.ManyToManyField('users.User', blank=True, verbose_name=_("Users")) + groups = models.ManyToManyField('users.UserGroup', blank=True, verbose_name=_("User groups")) priority = models.IntegerField(default=20, verbose_name=_("Priority"), validators=[MinValueValidator(1), MaxValueValidator(100)]) protocol = models.CharField(max_length=16, choices=PROTOCOL_CHOICES, default='ssh', verbose_name=_('Protocol')) auto_push = models.BooleanField(default=True, verbose_name=_('Auto push')) @@ -117,9 +117,20 @@ class SystemUser(AssetUser): shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell')) login_mode = models.CharField(choices=LOGIN_MODE_CHOICES, default=LOGIN_AUTO, max_length=10, verbose_name=_('Login mode')) cmd_filters = models.ManyToManyField('CommandFilter', related_name='system_users', verbose_name=_("Command filter"), blank=True) + sftp_root = models.CharField(default='tmp', max_length=128, verbose_name=_("SFTP Root")) + _prefer = 'system_user' def __str__(self): - return '{0.name}({0.username})'.format(self) + username = self.username + if self.username_same_with_user: + username = 'dynamic' + return '{0.name}({1})'.format(self, username) + + def get_username(self): + if self.username_same_with_user: + return list(self.users.values_list('username', flat=True)) + else: + return self.username @property def nodes_amount(self): diff --git a/apps/assets/serializers/admin_user.py b/apps/assets/serializers/admin_user.py index 63aac8cc0..5e27b0c64 100644 --- a/apps/assets/serializers/admin_user.py +++ b/apps/assets/serializers/admin_user.py @@ -55,3 +55,11 @@ class ReplaceNodeAdminUserSerializer(serializers.ModelSerializer): class TaskIDSerializer(serializers.Serializer): task = serializers.CharField(read_only=True) + + +class AssetUserTaskSerializer(serializers.Serializer): + ACTION_CHOICES = ( + ('test', 'test'), + ) + action = serializers.ChoiceField(choices=ACTION_CHOICES, write_only=True) + task = serializers.CharField(read_only=True) diff --git a/apps/assets/serializers/asset.py b/apps/assets/serializers/asset.py index c34fad77b..82d6964a4 100644 --- a/apps/assets/serializers/asset.py +++ b/apps/assets/serializers/asset.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- # -import re from rest_framework import serializers -from django.db.models import Prefetch +from django.db.models import Prefetch, F + from django.utils.translation import ugettext_lazy as _ from orgs.mixins.serializers import BulkOrgResourceModelSerializer @@ -12,8 +12,9 @@ from .base import ConnectivitySerializer __all__ = [ 'AssetSerializer', 'AssetSimpleSerializer', + 'AssetDisplaySerializer', 'ProtocolsField', 'PlatformSerializer', - 'AssetDetailSerializer', + 'AssetDetailSerializer', 'AssetTaskSerializer', ] @@ -66,8 +67,6 @@ class AssetSerializer(BulkOrgResourceModelSerializer): slug_field='name', queryset=Platform.objects.all(), label=_("Platform") ) protocols = ProtocolsField(label=_('Protocols'), required=False) - connectivity = ConnectivitySerializer(read_only=True, label=_("Connectivity")) - """ 资产的数据结构 """ @@ -81,7 +80,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer): 'cpu_model', 'cpu_count', 'cpu_cores', 'cpu_vcpus', 'memory', 'disk_total', 'disk_info', 'os', 'os_version', 'os_arch', 'hostname_raw', 'comment', 'created_by', 'date_created', - 'hardware_info', 'connectivity', + 'hardware_info', ] read_only_fields = ( 'vendor', 'model', 'sn', 'cpu_model', 'cpu_count', @@ -102,7 +101,8 @@ class AssetSerializer(BulkOrgResourceModelSerializer): queryset = queryset.prefetch_related( Prefetch('nodes', queryset=Node.objects.all().only('id')), Prefetch('labels', queryset=Label.objects.all().only('id')), - ).select_related('admin_user', 'domain', 'platform') + ).select_related('admin_user', 'domain', 'platform') \ + .annotate(platform_base=F('platform__base')) return queryset def compatible_with_old_protocol(self, validated_data): @@ -130,6 +130,28 @@ class AssetSerializer(BulkOrgResourceModelSerializer): return super().update(instance, validated_data) +class AssetDisplaySerializer(AssetSerializer): + connectivity = ConnectivitySerializer(read_only=True, label=_("Connectivity")) + + class Meta(AssetSerializer.Meta): + fields = [ + 'id', 'ip', 'hostname', 'protocol', 'port', + 'protocols', 'is_active', 'public_ip', + 'number', 'vendor', 'model', 'sn', + 'cpu_model', 'cpu_count', 'cpu_cores', 'cpu_vcpus', 'memory', + 'disk_total', 'disk_info', 'os', 'os_version', 'os_arch', + 'hostname_raw', 'comment', 'created_by', 'date_created', + 'hardware_info', 'connectivity', + ] + + @classmethod + def setup_eager_loading(cls, queryset): + """ Perform necessary eager loading of data. """ + queryset = queryset\ + .annotate(admin_user_username=F('admin_user__username')) + return queryset + + class PlatformSerializer(serializers.ModelSerializer): meta = serializers.DictField(required=False, allow_null=True) @@ -151,3 +173,12 @@ class AssetSimpleSerializer(serializers.ModelSerializer): class Meta: model = Asset fields = ['id', 'hostname', 'ip', 'connectivity', 'port'] + + +class AssetTaskSerializer(serializers.Serializer): + ACTION_CHOICES = ( + ('refresh', 'refresh'), + ('test', 'test'), + ) + task = serializers.CharField(read_only=True) + action = serializers.ChoiceField(choices=ACTION_CHOICES, write_only=True) diff --git a/apps/assets/serializers/asset_user.py b/apps/assets/serializers/asset_user.py index 1e05b8f5b..896ad9bef 100644 --- a/apps/assets/serializers/asset_user.py +++ b/apps/assets/serializers/asset_user.py @@ -8,39 +8,23 @@ from common.serializers import AdaptedBulkListSerializer from orgs.mixins.serializers import BulkOrgResourceModelSerializer from ..models import AuthBook, Asset from ..backends import AssetUserManager + from .base import ConnectivitySerializer, AuthSerializerMixin __all__ = [ - 'AssetUserSerializer', 'AssetUserAuthInfoSerializer', - 'AssetUserExportSerializer', 'AssetUserPushSerializer', + 'AssetUserWriteSerializer', 'AssetUserReadSerializer', + 'AssetUserAuthInfoSerializer', 'AssetUserPushSerializer', ] -class BasicAssetSerializer(serializers.ModelSerializer): - class Meta: - model = Asset - fields = ['hostname', 'ip'] - - -class AssetUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer): - hostname = serializers.CharField(read_only=True, label=_("Hostname")) - ip = serializers.CharField(read_only=True, label=_("IP")) - connectivity = ConnectivitySerializer(read_only=True, label=_("Connectivity")) - - backend = serializers.CharField(read_only=True, label=_("Backend")) - +class AssetUserWriteSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer): class Meta: model = AuthBook list_serializer_class = AdaptedBulkListSerializer - read_only_fields = ( - 'date_created', 'date_updated', 'created_by', - 'is_latest', 'version', 'connectivity', - ) fields = [ - "id", "hostname", "ip", "username", "password", "asset", "version", - "is_latest", "connectivity", "backend", - "date_created", "date_updated", "private_key", "public_key", + 'id', 'username', 'password', 'private_key', "public_key", + 'asset', 'comment', ] extra_kwargs = { 'username': {'required': True}, @@ -57,7 +41,32 @@ class AssetUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer): return instance -class AssetUserExportSerializer(AssetUserSerializer): +class AssetUserReadSerializer(AssetUserWriteSerializer): + id = serializers.CharField(read_only=True, source='union_id', label=_("ID")) + hostname = serializers.CharField(read_only=True, label=_("Hostname")) + ip = serializers.CharField(read_only=True, label=_("IP")) + asset = serializers.CharField(source='asset_id', label=_('Asset')) + backend = serializers.CharField(read_only=True, label=_("Backend")) + + class Meta(AssetUserWriteSerializer.Meta): + read_only_fields = ( + 'date_created', 'date_updated', + 'created_by', 'version', + ) + fields = [ + 'id', 'username', 'password', 'private_key', "public_key", + 'asset', 'hostname', 'ip', 'backend', 'version', + 'date_created', "date_updated", 'comment', + ] + extra_kwargs = { + 'username': {'required': True}, + 'password': {'write_only': True}, + 'private_key': {'write_only': True}, + 'public_key': {'write_only': True}, + } + + +class AssetUserAuthInfoSerializer(AssetUserReadSerializer): password = serializers.CharField( max_length=256, allow_blank=True, allow_null=True, required=False, label=_('Password') @@ -72,12 +81,6 @@ class AssetUserExportSerializer(AssetUserSerializer): ) -class AssetUserAuthInfoSerializer(serializers.ModelSerializer): - class Meta: - model = AuthBook - fields = ['password', 'private_key', 'public_key'] - - class AssetUserPushSerializer(serializers.Serializer): asset = serializers.PrimaryKeyRelatedField(queryset=Asset.objects, label=_("Asset")) username = serializers.CharField(max_length=1024) diff --git a/apps/assets/serializers/base.py b/apps/assets/serializers/base.py index 39e33ffe1..c64b767e9 100644 --- a/apps/assets/serializers/base.py +++ b/apps/assets/serializers/base.py @@ -5,6 +5,7 @@ from django.utils.translation import ugettext as _ from rest_framework import serializers from common.utils import ssh_pubkey_gen, validate_ssh_private_key +from ..models import AssetUser class AuthSerializer(serializers.ModelSerializer): @@ -60,9 +61,6 @@ class AuthSerializerMixin: if not value: validated_data.pop(field, None) - # print(validated_data) - # raise serializers.ValidationError(">>>>>>") - def create(self, validated_data): self.clean_auth_fields(validated_data) return super().create(validated_data) @@ -70,3 +68,15 @@ class AuthSerializerMixin: def update(self, instance, validated_data): self.clean_auth_fields(validated_data) return super().update(instance, validated_data) + + +class AuthInfoSerializer(serializers.ModelSerializer): + private_key = serializers.ReadOnlyField(source='get_private_key') + + class Meta: + model = AssetUser + fields = [ + 'username', 'password', + 'private_key', 'public_key', + 'date_updated', + ] diff --git a/apps/assets/serializers/node.py b/apps/assets/serializers/node.py index 79e07df13..063c91e0f 100644 --- a/apps/assets/serializers/node.py +++ b/apps/assets/serializers/node.py @@ -8,7 +8,7 @@ from ..models import Asset, Node __all__ = [ 'NodeSerializer', "NodeAddChildrenSerializer", - "NodeAssetsSerializer", + "NodeAssetsSerializer", "NodeTaskSerializer", ] @@ -51,3 +51,12 @@ class NodeAssetsSerializer(BulkOrgResourceModelSerializer): class NodeAddChildrenSerializer(serializers.Serializer): nodes = serializers.ListField() + +class NodeTaskSerializer(serializers.Serializer): + ACTION_CHOICES = ( + ('refresh', 'refresh'), + ('test', 'test'), + ('refresh_cache', 'refresh_cache'), + ) + task = serializers.CharField(read_only=True) + action = serializers.ChoiceField(choices=ACTION_CHOICES, write_only=True) diff --git a/apps/assets/serializers/system_user.py b/apps/assets/serializers/system_user.py index e16a7a271..a7e413018 100644 --- a/apps/assets/serializers/system_user.py +++ b/apps/assets/serializers/system_user.py @@ -1,20 +1,21 @@ -import re from rest_framework import serializers from django.utils.translation import ugettext_lazy as _ +from django.db.models import Count from common.serializers import AdaptedBulkListSerializer from common.mixins.serializers import BulkSerializerMixin from common.utils import ssh_pubkey_gen from orgs.mixins.serializers import BulkOrgResourceModelSerializer from assets.models import Node -from ..models import SystemUser -from .base import AuthSerializer, AuthSerializerMixin +from ..models import SystemUser, Asset +from .base import AuthSerializerMixin __all__ = [ - 'SystemUserSerializer', 'SystemUserAuthSerializer', + 'SystemUserSerializer', 'SystemUserListSerializer', 'SystemUserSimpleSerializer', 'SystemUserAssetRelationSerializer', - 'SystemUserNodeRelationSerializer', + 'SystemUserNodeRelationSerializer', 'SystemUserTaskSerializer', + 'SystemUserUserRelationSerializer', 'SystemUserWithAuthInfoSerializer', ] @@ -28,10 +29,13 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer): model = SystemUser list_serializer_class = AdaptedBulkListSerializer fields = [ - 'id', 'name', 'username', 'password', 'public_key', 'private_key', - 'login_mode', 'login_mode_display', 'priority', 'protocol', + 'id', 'name', 'username', 'protocol', + 'password', 'public_key', 'private_key', + 'login_mode', 'login_mode_display', + 'priority', 'username_same_with_user', 'auto_push', 'cmd_filters', 'sudo', 'shell', 'comment', - 'assets_amount', 'nodes_amount', 'auto_generate_key' + 'auto_generate_key', 'sftp_root', + 'assets_amount', ] extra_kwargs = { 'password': {"write_only": True}, @@ -67,17 +71,43 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer): value = False return value + def validate_username_same_with_user(self, username_same_with_user): + if not username_same_with_user: + return username_same_with_user + protocol = self.initial_data.get("protocol", "ssh") + queryset = SystemUser.objects.filter( + protocol=protocol, username_same_with_user=True + ) + if self.instance: + queryset = queryset.exclude(id=self.instance.id) + exists = queryset.exists() + if not exists: + return username_same_with_user + error = _("Username same with user with protocol {} only allow 1").format(protocol) + raise serializers.ValidationError(error) + def validate_username(self, username): if username: return username login_mode = self.initial_data.get("login_mode") protocol = self.initial_data.get("protocol") + username_same_with_user = self.initial_data.get("username_same_with_user") + if username_same_with_user: + return '' if login_mode == SystemUser.LOGIN_AUTO and \ protocol != SystemUser.PROTOCOL_VNC: msg = _('* Automatic login mode must fill in the username.') raise serializers.ValidationError(msg) return username + def validate_sftp_root(self, value): + if value in ['home', 'tmp']: + return value + if not value.startswith('/'): + error = _("Path should starts with /") + raise serializers.ValidationError(error) + return value + def validate_password(self, password): super().validate_password(password) auto_gen_key = self.initial_data.get("auto_generate_key", False) @@ -112,29 +142,34 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer): attrs["public_key"] = public_key return attrs + +class SystemUserListSerializer(SystemUserSerializer): + class Meta(SystemUserSerializer.Meta): + fields = [ + 'id', 'name', 'username', 'protocol', + 'login_mode', 'login_mode_display', + 'priority', "username_same_with_user", + 'auto_push', 'sudo', 'shell', 'comment', + "assets_amount", + 'auto_generate_key', + 'sftp_root', + ] + @classmethod def setup_eager_loading(cls, queryset): """ Perform necessary eager loading of data. """ - queryset = queryset.prefetch_related('cmd_filters', 'nodes') + queryset = queryset.annotate(assets_amount=Count("assets")) return queryset -class SystemUserAuthSerializer(AuthSerializer): - """ - 系统用户认证信息 - """ - private_key = serializers.SerializerMethodField() - - class Meta: - model = SystemUser - fields = [ - "id", "name", "username", "protocol", - "login_mode", "password", "private_key", - ] - - @staticmethod - def get_private_key(obj): - return obj.get_private_key() +class SystemUserWithAuthInfoSerializer(SystemUserSerializer): + class Meta(SystemUserSerializer.Meta): + extra_kwargs = { + 'nodes_amount': {'label': _('Node')}, + 'assets_amount': {'label': _('Asset')}, + 'login_mode_display': {'label': _('Login mode display')}, + 'created_by': {'read_only': True}, + } class SystemUserSimpleSerializer(serializers.ModelSerializer): @@ -186,3 +221,25 @@ class SystemUserNodeRelationSerializer(RelationMixin, serializers.ModelSerialize return self.tree.get_node_full_tag(obj.node_key) else: return obj.node.full_value + + +class SystemUserUserRelationSerializer(RelationMixin, serializers.ModelSerializer): + user_display = serializers.ReadOnlyField() + + class Meta(RelationMixin.Meta): + model = SystemUser.users.through + fields = [ + 'id', "user", "user_display", + ] + + +class SystemUserTaskSerializer(serializers.Serializer): + ACTION_CHOICES = ( + ("test", "test"), + ("push", "push"), + ) + action = serializers.ChoiceField(choices=ACTION_CHOICES, write_only=True) + asset = serializers.PrimaryKeyRelatedField( + queryset=Asset.objects, allow_null=True, required=False, write_only=True + ) + task = serializers.CharField(read_only=True) diff --git a/apps/assets/signals_handler.py b/apps/assets/signals_handler.py index 4f171d36f..696732fc8 100644 --- a/apps/assets/signals_handler.py +++ b/apps/assets/signals_handler.py @@ -7,8 +7,9 @@ from django.db.models.signals import ( from django.db.models.aggregates import Count from django.dispatch import receiver -from common.utils import get_logger, timeit +from common.utils import get_logger from common.decorator import on_transaction_commit +from orgs.utils import tmp_to_root_org from .models import Asset, SystemUser, Node, AuthBook from .utils import TreeService from .tasks import ( @@ -113,6 +114,20 @@ def on_system_user_nodes_change(sender, instance=None, action=None, model=None, add_nodes_assets_to_system_users.delay(nodes_keys, system_users) +@receiver(m2m_changed, sender=SystemUser.groups.through) +def on_system_user_groups_change(sender, instance=None, action=None, model=None, + pk_set=None, reverse=False, **kwargs): + """ + 当系统用户和用户组关系发生变化时,应该将组下用户关联到新的系统用户上 + """ + if action != "post_add" or reverse: + return + logger.info("System user groups update signal recv: {}".format(instance)) + groups = model.objects.filter(pk__in=pk_set).annotate(users_count=Count("users")) + users = groups.filter(users_count__gt=0).values_list('users', flat=True) + instance.users.add(*tuple(users)) + + @receiver(m2m_changed, sender=Asset.nodes.through) def on_asset_nodes_change(sender, instance=None, action='', **kwargs): """ @@ -121,6 +136,8 @@ def on_asset_nodes_change(sender, instance=None, action='', **kwargs): if action.startswith('post'): logger.debug("Asset nodes change signal recv: {}".format(instance)) Node.refresh_assets() + with tmp_to_root_org(): + Node.refresh_assets() @receiver(m2m_changed, sender=Asset.nodes.through) @@ -195,6 +212,8 @@ def on_asset_nodes_remove(sender, instance=None, action='', model=None, def on_node_update_or_created(sender, **kwargs): # 刷新节点 Node.refresh_nodes() + with tmp_to_root_org(): + Node.refresh_nodes() @receiver(post_save, sender=AuthBook) diff --git a/apps/assets/tasks/admin_user_connectivity.py b/apps/assets/tasks/admin_user_connectivity.py index ed089553e..1760c1f4d 100644 --- a/apps/assets/tasks/admin_user_connectivity.py +++ b/apps/assets/tasks/admin_user_connectivity.py @@ -4,11 +4,12 @@ from celery import shared_task from django.utils.translation import ugettext as _ from django.core.cache import cache +from orgs.utils import tmp_to_root_org, org_aware_func from common.utils import get_logger from ops.celery.decorator import register_as_period_task from ..models import AdminUser -from .utils import clean_hosts +from .utils import clean_ansible_task_hosts from .asset_connectivity import test_asset_connectivity_util from . import const @@ -20,7 +21,7 @@ __all__ = [ ] -@shared_task(queue="ansible") +@org_aware_func("admin_user") def test_admin_user_connectivity_util(admin_user, task_name): """ Test asset admin user can connect or not. Using ansible api do that @@ -29,7 +30,7 @@ def test_admin_user_connectivity_util(admin_user, task_name): :return: """ assets = admin_user.get_related_assets() - hosts = clean_hosts(assets) + hosts = clean_ansible_task_hosts(assets) if not hosts: return {} summary = test_asset_connectivity_util(hosts, task_name) @@ -51,10 +52,13 @@ def test_admin_user_connectivity_period(): logger.debug("Test admin user connectivity, less than 40 minutes, skip") return cache.set(key, 1, 60*40) - admin_users = AdminUser.objects.all() - for admin_user in admin_users: - task_name = _("Test admin user connectivity period: {}").format(admin_user.name) - test_admin_user_connectivity_util(admin_user, task_name) + with tmp_to_root_org(): + admin_users = AdminUser.objects.all() + for admin_user in admin_users: + task_name = _("Test admin user connectivity period: {}").format( + admin_user.name + ) + test_admin_user_connectivity_util(admin_user, task_name) cache.set(key, 1, 60*40) diff --git a/apps/assets/tasks/asset_connectivity.py b/apps/assets/tasks/asset_connectivity.py index b777dde7c..8c02d0db1 100644 --- a/apps/assets/tasks/asset_connectivity.py +++ b/apps/assets/tasks/asset_connectivity.py @@ -1,55 +1,55 @@ # ~*~ coding: utf-8 ~*~ +from itertools import groupby from collections import defaultdict from celery import shared_task from django.utils.translation import ugettext as _ from common.utils import get_logger +from orgs.utils import org_aware_func from ..models.utils import Connectivity from . import const -from .utils import clean_hosts +from .utils import clean_ansible_task_hosts, group_asset_by_platform logger = get_logger(__file__) -__all__ = ['test_asset_connectivity_util', 'test_asset_connectivity_manual'] +__all__ = [ + 'test_asset_connectivity_util', 'test_asset_connectivity_manual', + 'test_node_assets_connectivity_manual', +] @shared_task(queue="ansible") +@org_aware_func("assets") def test_asset_connectivity_util(assets, task_name=None): from ops.utils import update_or_create_ansible_task if task_name is None: task_name = _("Test assets connectivity") - hosts = clean_hosts(assets) + hosts = clean_ansible_task_hosts(assets) if not hosts: return {} + platform_hosts_map = {} + hosts_sorted = sorted(hosts, key=group_asset_by_platform) + platform_hosts = groupby(hosts_sorted, key=group_asset_by_platform) + for i in platform_hosts: + platform_hosts_map[i[0]] = list(i[1]) - hosts_category = { - 'linux': { - 'hosts': [], - 'tasks': const.TEST_ADMIN_USER_CONN_TASKS - }, - 'windows': { - 'hosts': [], - 'tasks': const.TEST_WINDOWS_ADMIN_USER_CONN_TASKS - } + platform_tasks_map = { + "unixlike": const.PING_UNIXLIKE_TASKS, + "windows": const.PING_WINDOWS_TASKS } - for host in hosts: - hosts_list = hosts_category['windows']['hosts'] if host.is_windows() \ - else hosts_category['linux']['hosts'] - hosts_list.append(host) - results_summary = dict( contacted=defaultdict(dict), dark=defaultdict(dict), success=True ) - created_by = assets[0].org_id - for k, value in hosts_category.items(): - if not value['hosts']: + for platform, _hosts in platform_hosts_map.items(): + if not _hosts: continue + logger.debug("System user not has special auth") + tasks = platform_tasks_map.get(platform) task, created = update_or_create_ansible_task( - task_name=task_name, hosts=value['hosts'], tasks=value['tasks'], + task_name=task_name, hosts=_hosts, tasks=tasks, pattern='all', options=const.TASK_OPTIONS, run_as_admin=True, - created_by=created_by, ) raw, summary = task.run() success = summary.get('success', False) @@ -59,6 +59,7 @@ def test_asset_connectivity_util(assets, task_name=None): results_summary['success'] &= success results_summary['contacted'].update(contacted) results_summary['dark'].update(dark) + continue for asset in assets: if asset.hostname in results_summary.get('dark', {}).keys(): @@ -79,3 +80,12 @@ def test_asset_connectivity_manual(asset): return False, summary['dark'] else: return True, "" + + +@shared_task(queue="ansible") +def test_node_assets_connectivity_manual(node): + task_name = _("Test if the assets under the node are connectable: {}".format(node.name)) + assets = node.get_all_assets() + result = test_asset_connectivity_util(assets, task_name=task_name) + return result + diff --git a/apps/assets/tasks/asset_user_connectivity.py b/apps/assets/tasks/asset_user_connectivity.py index 5a4bbcc43..6d979d6b1 100644 --- a/apps/assets/tasks/asset_user_connectivity.py +++ b/apps/assets/tasks/asset_user_connectivity.py @@ -3,7 +3,9 @@ from celery import shared_task from django.utils.translation import ugettext as _ -from common.utils import get_logger +from common.utils import get_logger, get_object_or_none +from orgs.utils import org_aware_func +from ..models import Asset from . import const from .utils import check_asset_can_run_ansible @@ -13,15 +15,16 @@ logger = get_logger(__file__) __all__ = [ 'test_asset_user_connectivity_util', 'test_asset_users_connectivity_manual', - 'get_test_asset_user_connectivity_tasks', + 'get_test_asset_user_connectivity_tasks', 'test_user_connectivity', + 'run_adhoc', ] def get_test_asset_user_connectivity_tasks(asset): if asset.is_unixlike(): - tasks = const.TEST_ASSET_USER_CONN_TASKS + tasks = const.PING_UNIXLIKE_TASKS elif asset.is_windows(): - tasks = const.TEST_WINDOWS_ASSET_USER_CONN_TASKS + tasks = const.PING_WINDOWS_TASKS else: msg = _( "The asset {} system platform {} does not " @@ -32,46 +35,98 @@ def get_test_asset_user_connectivity_tasks(asset): return tasks -@shared_task(queue="ansible") -def test_asset_user_connectivity_util(asset_user, task_name, run_as_admin=False): +def run_adhoc(task_name, tasks, inventory): + """ + :param task_name + :param tasks + :param inventory + """ + from ops.ansible.runner import AdHocRunner + runner = AdHocRunner(inventory, options=const.TASK_OPTIONS) + result = runner.run(tasks, 'all', task_name) + return result.results_raw, result.results_summary + + +def test_user_connectivity(task_name, asset, username, password=None, private_key=None): + """ + :param task_name + :param asset + :param username + :param password + :param private_key + """ + from ops.inventory import JMSCustomInventory + + tasks = get_test_asset_user_connectivity_tasks(asset) + if not tasks: + logger.debug("No tasks ") + return {}, {} + inventory = JMSCustomInventory( + assets=[asset], username=username, password=password, + private_key=private_key + ) + raw, summary = run_adhoc( + task_name=task_name, tasks=tasks, inventory=inventory + ) + return raw, summary + + +@org_aware_func("asset_user") +def test_asset_user_connectivity_util(asset_user, task_name): """ :param asset_user: 对象 :param task_name: - :param run_as_admin: :return: """ - from ops.utils import update_or_create_ansible_task - if not check_asset_can_run_ansible(asset_user.asset): return - tasks = get_test_asset_user_connectivity_tasks(asset_user.asset) - if not tasks: - logger.debug("No tasks ") + try: + raw, summary = test_user_connectivity( + task_name=task_name, asset=asset_user.asset, + username=asset_user.username, password=asset_user.password, + private_key=asset_user.private_key + ) + except Exception as e: + logger.warn("Failed run adhoc {}, {}".format(task_name, e)) return - - args = (task_name,) - kwargs = { - 'hosts': [asset_user.asset], 'tasks': tasks, - 'pattern': 'all', 'options': const.TASK_OPTIONS, - 'created_by': asset_user.org_id, - } - if run_as_admin: - kwargs["run_as_admin"] = True - else: - kwargs["run_as"] = asset_user.username - task, created = update_or_create_ansible_task(*args, **kwargs) - raw, summary = task.run() asset_user.set_connectivity(summary) @shared_task(queue="ansible") -def test_asset_users_connectivity_manual(asset_users, run_as_admin=False): +def test_asset_users_connectivity_manual(asset_users): """ :param asset_users: 对象 """ for asset_user in asset_users: task_name = _("Test asset user connectivity: {}").format(asset_user) - test_asset_user_connectivity_util(asset_user, task_name, run_as_admin=run_as_admin) + test_asset_user_connectivity_util(asset_user, task_name) + + +@shared_task(queue="ansible") +def push_asset_user_util(asset_user): + """ + :param asset_user: 对象 + """ + from .push_system_user import push_system_user_util + if not asset_user.backend.startswith('system_user'): + logger.error("Asset user is not from system user") + return + union_id = asset_user.union_id + union_id_list = union_id.split('_') + if len(union_id_list) < 2: + logger.error("Asset user union id length less than 2") + return + system_user_id = union_id_list[0] + asset_id = union_id_list[1] + asset = get_object_or_none(Asset, pk=asset_id) + system_user = None + if not asset: + return + hosts = check_asset_can_run_ansible([asset]) + if asset.is_unixlike: + pass + + diff --git a/apps/assets/tasks/const.py b/apps/assets/tasks/const.py index 5b7db13cd..ce9ad9074 100644 --- a/apps/assets/tasks/const.py +++ b/apps/assets/tasks/const.py @@ -18,27 +18,10 @@ UPDATE_ASSETS_HARDWARE_TASKS = [ } ] -TEST_ADMIN_USER_CONN_TASKS = [ - { - "name": "ping", - "action": { - "module": "ping", - } - } -] -TEST_WINDOWS_ADMIN_USER_CONN_TASKS = [ - { - "name": "ping", - "action": { - "module": "win_ping", - } - } -] - ASSET_ADMIN_CONN_CACHE_KEY = "ASSET_ADMIN_USER_CONN_{}" SYSTEM_USER_CONN_CACHE_KEY = "SYSTEM_USER_CONN_{}" -TEST_SYSTEM_USER_CONN_TASKS = [ +PING_UNIXLIKE_TASKS = [ { "name": "ping", "action": { @@ -46,7 +29,7 @@ TEST_SYSTEM_USER_CONN_TASKS = [ } } ] -TEST_WINDOWS_SYSTEM_USER_CONN_TASKS = [ +PING_WINDOWS_TASKS = [ { "name": "ping", "action": { @@ -55,24 +38,6 @@ TEST_WINDOWS_SYSTEM_USER_CONN_TASKS = [ } ] -TEST_ASSET_USER_CONN_TASKS = [ - { - "name": "ping", - "action": { - "module": "ping", - } - } -] -TEST_WINDOWS_ASSET_USER_CONN_TASKS = [ - { - "name": "ping", - "action": { - "module": "win_ping", - } - } -] - - TASK_OPTIONS = { 'timeout': 10, 'forks': 10, @@ -98,7 +63,9 @@ GATHER_ASSET_USERS_TASKS = [ "name": "get last login", "action": { "module": "shell", - "args": "users=$(getent passwd | grep -v 'nologin' | grep -v 'shudown' | awk -F: '{ print $1 }');for i in $users;do last -F $i -1 | head -1 | grep -v '^$' | awk '{ print $1\"@\"$3\"@\"$5,$6,$7,$8 }';done" + "args": "users=$(getent passwd | grep -v 'nologin' | " + "grep -v 'shudown' | awk -F: '{ print $1 }');for i in $users;do last -F $i -1 | " + "head -1 | grep -v '^$' | awk '{ print $1\"@\"$3\"@\"$5,$6,$7,$8 }';done" } } ] diff --git a/apps/assets/tasks/gather_asset_hardware_info.py b/apps/assets/tasks/gather_asset_hardware_info.py index 2c0d75e99..e473366a5 100644 --- a/apps/assets/tasks/gather_asset_hardware_info.py +++ b/apps/assets/tasks/gather_asset_hardware_info.py @@ -9,15 +9,16 @@ from django.utils.translation import ugettext as _ from common.utils import ( capacity_convert, sum_capacity, get_logger ) +from orgs.utils import org_aware_func from . import const -from .utils import clean_hosts +from .utils import clean_ansible_task_hosts logger = get_logger(__file__) disk_pattern = re.compile(r'^hd|sd|xvd|vd|nv') __all__ = [ 'update_assets_hardware_info_util', 'update_asset_hardware_info_manual', - 'update_assets_hardware_info_period', + 'update_assets_hardware_info_period', 'update_node_assets_hardware_info_manual', ] @@ -82,6 +83,7 @@ def set_assets_hardware_info(assets, result, **kwargs): @shared_task +@org_aware_func("assets") def update_assets_hardware_info_util(assets, task_name=None): """ Using ansible api to update asset hardware info @@ -93,13 +95,13 @@ def update_assets_hardware_info_util(assets, task_name=None): if task_name is None: task_name = _("Update some assets hardware info") tasks = const.UPDATE_ASSETS_HARDWARE_TASKS - hosts = clean_hosts(assets) + hosts = clean_ansible_task_hosts(assets) if not hosts: return {} - created_by = str(assets[0].org_id) task, created = update_or_create_ansible_task( - task_name, hosts=hosts, tasks=tasks, created_by=created_by, - pattern='all', options=const.TASK_OPTIONS, run_as_admin=True, + task_name, hosts=hosts, tasks=tasks, + pattern='all', options=const.TASK_OPTIONS, + run_as_admin=True, ) result = task.run() set_assets_hardware_info(assets, result) @@ -109,9 +111,7 @@ def update_assets_hardware_info_util(assets, task_name=None): @shared_task(queue="ansible") def update_asset_hardware_info_manual(asset): task_name = _("Update asset hardware info: {}").format(asset.hostname) - update_assets_hardware_info_util( - [asset], task_name=task_name - ) + update_assets_hardware_info_util([asset], task_name=task_name) @shared_task(queue="ansible") @@ -123,3 +123,11 @@ def update_assets_hardware_info_period(): if not const.PERIOD_TASK_ENABLED: logger.debug("Period task disabled, update assets hardware info pass") return + + +@shared_task(queue="ansible") +def update_node_assets_hardware_info_manual(node): + task_name = _("Update node asset hardware information: {}").format(node.name) + assets = node.get_all_assets() + result = update_assets_hardware_info_util.delay(assets, task_name=task_name) + return result diff --git a/apps/assets/tasks/gather_asset_users.py b/apps/assets/tasks/gather_asset_users.py index 7dfe0fb01..7914c9720 100644 --- a/apps/assets/tasks/gather_asset_users.py +++ b/apps/assets/tasks/gather_asset_users.py @@ -7,10 +7,10 @@ from celery import shared_task from django.utils.translation import ugettext as _ from django.utils import timezone -from orgs.utils import tmp_to_org +from orgs.utils import tmp_to_org, org_aware_func from common.utils import get_logger from ..models import GatheredUser, Node -from .utils import clean_hosts +from .utils import clean_ansible_task_hosts from . import const __all__ = ['gather_asset_users', 'gather_nodes_asset_users'] @@ -101,11 +101,12 @@ def add_asset_users(assets, results): @shared_task(queue="ansible") +@org_aware_func("assets") def gather_asset_users(assets, task_name=None): from ops.utils import update_or_create_ansible_task if task_name is None: task_name = _("Gather assets users") - assets = clean_hosts(assets) + assets = clean_ansible_task_hosts(assets) if not assets: return hosts_category = { @@ -131,7 +132,7 @@ def gather_asset_users(assets, task_name=None): task, created = update_or_create_ansible_task( task_name=_task_name, hosts=value['hosts'], tasks=value['tasks'], pattern='all', options=const.TASK_OPTIONS, - run_as_admin=True, created_by=value['hosts'][0].org_id, + run_as_admin=True, ) raw, summary = task.run() results[k].update(raw['ok']) diff --git a/apps/assets/tasks/push_system_user.py b/apps/assets/tasks/push_system_user.py index 01348a0fe..961f24a01 100644 --- a/apps/assets/tasks/push_system_user.py +++ b/apps/assets/tasks/push_system_user.py @@ -1,11 +1,13 @@ # ~*~ coding: utf-8 ~*~ +from itertools import groupby from celery import shared_task from django.utils.translation import ugettext as _ from common.utils import encrypt_password, get_logger +from orgs.utils import tmp_to_org, org_aware_func from . import const -from .utils import clean_hosts_by_protocol, clean_hosts +from .utils import clean_ansible_task_hosts, group_asset_by_platform logger = get_logger(__file__) @@ -15,31 +17,34 @@ __all__ = [ ] -def get_push_linux_system_user_tasks(system_user): +def get_push_unixlike_system_user_tasks(system_user, username=None): + if username is None: + username = system_user.username + password = system_user.password + public_key = system_user.public_key + tasks = [ { - 'name': 'Add user {}'.format(system_user.username), + 'name': 'Add user {}'.format(username), 'action': { 'module': 'user', 'args': 'name={} shell={} state=present'.format( - system_user.username, system_user.shell, + username, system_user.shell or '/bin/bash', ), } }, { - 'name': 'Add group {}'.format(system_user.username), + 'name': 'Add group {}'.format(username), 'action': { 'module': 'group', - 'args': 'name={} state=present'.format( - system_user.username, - ), + 'args': 'name={} state=present'.format(username), } }, { 'name': 'Check home dir exists', 'action': { 'module': 'stat', - 'args': 'path=/home/{}'.format(system_user.username) + 'args': 'path=/home/{}'.format(username) }, 'register': 'home_existed' }, @@ -47,29 +52,29 @@ def get_push_linux_system_user_tasks(system_user): 'name': "Set home dir permission", 'action': { 'module': 'file', - 'args': "path=/home/{0} owner={0} group={0} mode=700".format(system_user.username) + 'args': "path=/home/{0} owner={0} group={0} mode=700".format(username) }, 'when': 'home_existed.stat.exists == true' } ] - if system_user.password: + if password: tasks.append({ - 'name': 'Set {} password'.format(system_user.username), + 'name': 'Set {} password'.format(username), 'action': { 'module': 'user', 'args': 'name={} shell={} state=present password={}'.format( - system_user.username, system_user.shell, - encrypt_password(system_user.password, salt="K3mIlKK"), + username, system_user.shell, + encrypt_password(password, salt="K3mIlKK"), ), } }) - if system_user.public_key: + if public_key: tasks.append({ - 'name': 'Set {} authorized key'.format(system_user.username), + 'name': 'Set {} authorized key'.format(username), 'action': { 'module': 'authorized_key', 'args': "user={} state=present key='{}'".format( - system_user.username, system_user.public_key + username, public_key ) } }) @@ -81,26 +86,27 @@ def get_push_linux_system_user_tasks(system_user): sudo_tmp.append(s.strip(',')) sudo = ','.join(sudo_tmp) tasks.append({ - 'name': 'Set {} sudo setting'.format(system_user.username), + 'name': 'Set {} sudo setting'.format(username), 'action': { 'module': 'lineinfile', 'args': "dest=/etc/sudoers state=present regexp='^{0} ALL=' " "line='{0} ALL=(ALL) NOPASSWD: {1}' " - "validate='visudo -cf %s'".format( - system_user.username, sudo, - ) + "validate='visudo -cf %s'".format(username, sudo) } }) return tasks -def get_push_windows_system_user_tasks(system_user): +def get_push_windows_system_user_tasks(system_user, username=None): + if username is None: + username = system_user.username + password = system_user.password tasks = [] - if not system_user.password: + if not password: return tasks - tasks.append({ - 'name': 'Add user {}'.format(system_user.username), + task = { + 'name': 'Add user {}'.format(username), 'action': { 'module': 'win_user', 'args': 'fullname={} ' @@ -112,78 +118,95 @@ def get_push_windows_system_user_tasks(system_user): 'password_never_expires=yes ' 'groups="Users,Remote Desktop Users" ' 'groups_action=add ' - ''.format(system_user.name, - system_user.username, - system_user.password), + ''.format(username, username, password), } - }) + } + print(task) + tasks.append(task) return tasks -def get_push_system_user_tasks(host, system_user): - if host.is_unixlike(): - tasks = get_push_linux_system_user_tasks(system_user) - elif host.is_windows(): - tasks = get_push_windows_system_user_tasks(system_user) - else: - msg = _( - "The asset {} system platform {} does not " - "support run Ansible tasks".format(host.hostname, host.platform) - ) - logger.info(msg) - tasks = [] +def get_push_system_user_tasks(system_user, platform="unixlike", username=None): + """ + :param system_user: + :param platform: + :param username: 当动态时,近推送某个 + :return: + """ + get_task_map = { + "unixlike": get_push_unixlike_system_user_tasks, + "windows": get_push_windows_system_user_tasks, + } + get_tasks = get_task_map.get(platform, get_push_unixlike_system_user_tasks) + if not system_user.username_same_with_user: + return get_tasks(system_user) + tasks = [] + # 仅推送这个username + if username is not None: + tasks.extend(get_tasks(system_user, username)) + return tasks + users = system_user.users.all().values_list('username', flat=True) + print(_("System user is dynamic: {}").format(list(users))) + for _username in users: + tasks.extend(get_tasks(system_user, _username)) return tasks -@shared_task(queue="ansible") -def push_system_user_util(system_user, assets, task_name): +@org_aware_func("system_user") +def push_system_user_util(system_user, assets, task_name, username=None): from ops.utils import update_or_create_ansible_task - if not system_user.is_need_push(): - msg = _("Push system user task skip, auto push not enable or " - "protocol is not ssh or rdp: {}").format(system_user.name) - logger.info(msg) - return {} - - # Set root as system user is dangerous - if system_user.username.lower() in ["root", "administrator"]: - msg = _("For security, do not push user {}".format(system_user.username)) - logger.info(msg) - return {} - - hosts = clean_hosts(assets) + hosts = clean_ansible_task_hosts(assets, system_user=system_user) if not hosts: return {} - hosts = clean_hosts_by_protocol(system_user, hosts) - if not hosts: - return {} + platform_hosts_map = {} + hosts_sorted = sorted(hosts, key=group_asset_by_platform) + platform_hosts = groupby(hosts_sorted, key=group_asset_by_platform) + for i in platform_hosts: + platform_hosts_map[i[0]] = list(i[1]) - for host in hosts: - system_user.load_specific_asset_auth(host) - tasks = get_push_system_user_tasks(host, system_user) - if not tasks: - continue + def run_task(_tasks, _hosts): + if not _tasks: + return task, created = update_or_create_ansible_task( - task_name=task_name, hosts=[host], tasks=tasks, pattern='all', + task_name=task_name, hosts=_hosts, tasks=_tasks, pattern='all', options=const.TASK_OPTIONS, run_as_admin=True, - created_by=system_user.org_id, ) task.run() + for platform, _hosts in platform_hosts_map.items(): + if not _hosts: + continue + print(_("Start push system user for platform: [{}]").format(platform)) + print(_("Hosts count: {}").format(len(_hosts))) + + if not system_user.has_special_auth(): + logger.debug("System user not has special auth") + tasks = get_push_system_user_tasks(system_user, platform, username=username) + run_task(tasks, _hosts) + continue + + for _host in _hosts: + system_user.load_asset_special_auth(_host) + tasks = get_push_system_user_tasks(system_user, platform, username=username) + run_task(tasks, [_host]) + @shared_task(queue="ansible") def push_system_user_to_assets_manual(system_user): - assets = system_user.get_all_assets() + assets = system_user.get_related_assets() task_name = _("Push system users to assets: {}").format(system_user.name) return push_system_user_util(system_user, assets, task_name=task_name) @shared_task(queue="ansible") -def push_system_user_a_asset_manual(system_user, asset): - task_name = _("Push system users to asset: {} => {}").format( - system_user.name, asset +def push_system_user_a_asset_manual(system_user, asset, username=None): + if username is None: + username = system_user.username + task_name = _("Push system users to asset: {}({}) => {}").format( + system_user.name, username, asset ) - return push_system_user_util(system_user, [asset], task_name=task_name) + return push_system_user_util(system_user, [asset], task_name=task_name, username=username) @shared_task(queue="ansible") @@ -199,4 +222,4 @@ def push_system_user_to_assets(system_user, assets): # @after_app_shutdown_clean_periodic # def push_system_user_period(): # for system_user in SystemUser.objects.all(): -# push_system_user_related_nodes(system_user) \ No newline at end of file +# push_system_user_related_nodes(system_user) diff --git a/apps/assets/tasks/system_user_connectivity.py b/apps/assets/tasks/system_user_connectivity.py index ffe618a59..4b3a80b2c 100644 --- a/apps/assets/tasks/system_user_connectivity.py +++ b/apps/assets/tasks/system_user_connectivity.py @@ -1,13 +1,17 @@ +from itertools import groupby from collections import defaultdict + from celery import shared_task from django.utils.translation import ugettext as _ from common.utils import get_logger - +from orgs.utils import tmp_to_org, org_aware_func from ..models import SystemUser from . import const -from .utils import clean_hosts, clean_hosts_by_protocol +from .utils import ( + clean_ansible_task_hosts, group_asset_by_platform +) logger = get_logger(__name__) __all__ = [ @@ -16,7 +20,7 @@ __all__ = [ ] -@shared_task(queue="ansible") +@org_aware_func("system_user") def test_system_user_connectivity_util(system_user, assets, task_name): """ Test system cant connect his assets or not. @@ -27,41 +31,34 @@ def test_system_user_connectivity_util(system_user, assets, task_name): """ from ops.utils import update_or_create_ansible_task - hosts = clean_hosts(assets) + hosts = clean_ansible_task_hosts(assets, system_user=system_user) if not hosts: return {} + platform_hosts_map = {} + hosts_sorted = sorted(hosts, key=group_asset_by_platform) + platform_hosts = groupby(hosts_sorted, key=group_asset_by_platform) + for i in platform_hosts: + platform_hosts_map[i[0]] = list(i[1]) - hosts = clean_hosts_by_protocol(system_user, hosts) - if not hosts: - return {} - - hosts_category = { - 'linux': { - 'hosts': [], - 'tasks': const.TEST_SYSTEM_USER_CONN_TASKS - }, - 'windows': { - 'hosts': [], - 'tasks': const.TEST_WINDOWS_SYSTEM_USER_CONN_TASKS - } + platform_tasks_map = { + "unixlike": const.PING_UNIXLIKE_TASKS, + "windows": const.PING_WINDOWS_TASKS } - for host in hosts: - hosts_list = hosts_category['windows']['hosts'] if host.is_windows() \ - else hosts_category['linux']['hosts'] - hosts_list.append(host) results_summary = dict( contacted=defaultdict(dict), dark=defaultdict(dict), success=True ) - for k, value in hosts_category.items(): - if not value['hosts']: - continue - task, created = update_or_create_ansible_task( - task_name=task_name, hosts=value['hosts'], tasks=value['tasks'], + + def run_task(_tasks, _hosts, _username): + old_name = "({})".format(system_user.username) + new_name = "({})".format(_username) + _task_name = task_name.replace(old_name, new_name) + _task, created = update_or_create_ansible_task( + task_name=_task_name, hosts=_hosts, tasks=_tasks, pattern='all', options=const.TASK_OPTIONS, - run_as=system_user.username, created_by=system_user.org_id, + run_as=_username, ) - raw, summary = task.run() + raw, summary = _task.run() success = summary.get('success', False) contacted = summary.get('contacted', {}) dark = summary.get('dark', {}) @@ -70,23 +67,45 @@ def test_system_user_connectivity_util(system_user, assets, task_name): results_summary['contacted'].update(contacted) results_summary['dark'].update(dark) + for platform, _hosts in platform_hosts_map.items(): + if not _hosts: + continue + if platform not in ["unixlike", "windows"]: + continue + + tasks = platform_tasks_map[platform] + print(_("Start test system user connectivity for platform: [{}]").format(platform)) + print(_("Hosts count: {}").format(len(_hosts))) + # 用户名不是动态的,用户名则是一个 + if not system_user.username_same_with_user: + logger.debug("System user not has special auth") + run_task(tasks, _hosts, system_user.username) + # 否则需要多个任务 + else: + users = system_user.users.all().values_list('username', flat=True) + print(_("System user is dynamic: {}").format(list(users))) + for username in users: + run_task(tasks, _hosts, username) + system_user.set_connectivity(results_summary) return results_summary @shared_task(queue="ansible") +@org_aware_func("system_user") def test_system_user_connectivity_manual(system_user): task_name = _("Test system user connectivity: {}").format(system_user) - assets = system_user.get_all_assets() - return test_system_user_connectivity_util(system_user, assets, task_name) + assets = system_user.get_related_assets() + test_system_user_connectivity_util(system_user, assets, task_name) @shared_task(queue="ansible") +@org_aware_func("system_user") def test_system_user_connectivity_a_asset(system_user, asset): task_name = _("Test system user connectivity: {} => {}").format( system_user, asset ) - return test_system_user_connectivity_util(system_user, [asset], task_name) + test_system_user_connectivity_util(system_user, [asset], task_name) @shared_task(queue="ansible") @@ -94,8 +113,9 @@ def test_system_user_connectivity_period(): if not const.PERIOD_TASK_ENABLED: logger.debug("Period task disabled, test system user connectivity pass") return - system_users = SystemUser.objects.all() - for system_user in system_users: + queryset_map = SystemUser.objects.all_group_by_org() + for org, system_user in queryset_map.items(): task_name = _("Test system user connectivity period: {}").format(system_user) - assets = system_user.get_all_assets() - test_system_user_connectivity_util(system_user, assets, task_name) + with tmp_to_org(org): + assets = system_user.get_related_assets() + test_system_user_connectivity_util(system_user, assets, task_name) diff --git a/apps/assets/tasks/utils.py b/apps/assets/tasks/utils.py index e5983143f..9956665ee 100644 --- a/apps/assets/tasks/utils.py +++ b/apps/assets/tasks/utils.py @@ -7,7 +7,8 @@ from common.utils import get_logger logger = get_logger(__file__) __all__ = [ - 'check_asset_can_run_ansible', 'clean_hosts', 'clean_hosts_by_protocol' + 'check_asset_can_run_ansible', 'clean_ansible_task_hosts', + 'group_asset_by_platform', ] @@ -23,23 +24,43 @@ def check_asset_can_run_ansible(asset): return True -def clean_hosts(assets): - clean_assets = [] +def check_system_user_can_run_ansible(system_user): + if not system_user.is_need_push(): + msg = _("Push system user task skip, auto push not enable or " + "protocol is not ssh or rdp: {}").format(system_user.name) + logger.info(msg) + return False + + # Push root as system user is dangerous + if system_user.username.lower() in ["root", "administrator"]: + msg = _("For security, do not push user {}".format(system_user.username)) + logger.info(msg) + return False + + # if system_user.protocol != "ssh": + # msg = _("System user protocol not ssh: {}".format(system_user)) + # logger.info(msg) + # return False + return True + + +def clean_ansible_task_hosts(assets, system_user=None): + if system_user and not check_system_user_can_run_ansible(system_user): + return [] + cleaned_assets = [] for asset in assets: if not check_asset_can_run_ansible(asset): continue - clean_assets.append(asset) - if not clean_assets: + cleaned_assets.append(asset) + if not cleaned_assets: logger.info(_("No assets matched, stop task")) - return clean_assets + return cleaned_assets -def clean_hosts_by_protocol(system_user, assets): - hosts = [ - asset for asset in assets - if asset.has_protocol(system_user.protocol) - ] - if not hosts: - msg = _("No assets matched related system user protocol, stop task") - logger.info(msg) - return hosts +def group_asset_by_platform(asset): + if asset.is_unixlike(): + return 'unixlike' + elif asset.is_windows(): + return 'windows' + else: + return 'other' diff --git a/apps/assets/templates/assets/_asset_user_auth_update_modal.html b/apps/assets/templates/assets/_asset_user_auth_update_modal.html index 28a1a956d..fe88b7426 100644 --- a/apps/assets/templates/assets/_asset_user_auth_update_modal.html +++ b/apps/assets/templates/assets/_asset_user_auth_update_modal.html @@ -6,25 +6,25 @@
{% csrf_token %}
- +

- +

- +
- +
diff --git a/apps/assets/templates/assets/_asset_user_auth_view_modal.html b/apps/assets/templates/assets/_asset_user_auth_view_modal.html index 417e1021d..8cc3a78de 100644 --- a/apps/assets/templates/assets/_asset_user_auth_view_modal.html +++ b/apps/assets/templates/assets/_asset_user_auth_view_modal.html @@ -12,19 +12,19 @@
- +

- +

- +
@@ -38,11 +38,11 @@ {% endblock %} diff --git a/apps/assets/templates/assets/_asset_user_list.html b/apps/assets/templates/assets/_asset_user_list.html index 3321e2578..d43cea10f 100644 --- a/apps/assets/templates/assets/_asset_user_list.html +++ b/apps/assets/templates/assets/_asset_user_list.html @@ -8,8 +8,8 @@ table.dataTable tbody tr.selected a { color: rgb(103, 106, 108);; } - + @@ -20,7 +20,7 @@ - +{# #} @@ -33,62 +33,60 @@ {% include 'authentication/_mfa_confirm_modal.html' %} diff --git a/apps/assets/templates/assets/_node_tree.html b/apps/assets/templates/assets/_node_tree.html index b4b5040b0..c500f55f8 100644 --- a/apps/assets/templates/assets/_node_tree.html +++ b/apps/assets/templates/assets/_node_tree.html @@ -113,10 +113,11 @@ function initNodeTree(options) { $.get(treeUrl, function (data, status) { zTree = $.fn.zTree.init($("#nodeTree"), setting, data); rootNodeAddDom(zTree, function () { - const url = '{% url 'api-assets:refresh-nodes-cache' %}'; + const url = '{% url 'api-assets:node-task-create' pk=DEFAULT_PK %}'; requestApi({ url: url, - method: 'GET', + method: 'POST', + data: {action: "refresh_cache"}, flash_message: false, success: function () { initNodeTree(options); @@ -173,20 +174,14 @@ function removeTreeNode() { if (!current_node){ return } - if (current_node.children && current_node.children.length > 0) { - toastr.error("{% trans 'Have child node, cancel' %}"); - } else if (current_node.meta.node.assets_amount !== 0) { - toastr.error("{% trans 'Have assets, cancel' %}"); - } else { - var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id); - $.ajax({ - url: url, - method: "DELETE", - success: function () { - zTree.removeNode(current_node); - } - }); - } + var url = "{% url 'api-assets:node-detail' pk=DEFAULT_PK %}".replace("{{ DEFAULT_PK }}", current_node_id); + requestApi({ + url: url, + method: "DELETE", + success: function () { + zTree.removeNode(current_node) + } + }) } function editTreeNode() { diff --git a/apps/assets/templates/assets/_system_user.html b/apps/assets/templates/assets/_system_user.html index d941bf20a..e05a9448b 100644 --- a/apps/assets/templates/assets/_system_user.html +++ b/apps/assets/templates/assets/_system_user.html @@ -34,6 +34,7 @@ {% bootstrap_field form.name layout="horizontal" %} {% bootstrap_field form.login_mode layout="horizontal" %} {% bootstrap_field form.username layout="horizontal" %} + {% bootstrap_field form.username_same_with_user layout="horizontal" %} {% bootstrap_field form.priority layout="horizontal" %} {% bootstrap_field form.protocol layout="horizontal" %} @@ -63,6 +64,7 @@ {% bootstrap_field form.cmd_filters layout="horizontal" %}

{% trans 'Other' %}

+ {% bootstrap_field form.sftp_root layout="horizontal" %} {% bootstrap_field form.sudo layout="horizontal" %} {% bootstrap_field form.shell layout="horizontal" %} {% bootstrap_field form.comment layout="horizontal" %} @@ -226,6 +228,10 @@ $(document).ready(function () { $('.select2').select2(); authFieldsDisplay(); fieldDisplay(); + var checked = $("#id_username_same_with_user").prop('checked'); + if (checked) { + $("#id_username").attr("disabled", true) + } }) .on('change', auto_generate_key, function(){ authFieldsDisplay(); @@ -246,7 +252,7 @@ $(document).ready(function () { var data = form.serializeObject(); objectAttrsIsList(data, ['cmd_filters']); - objectAttrsIsBool(data, ["auto_generate_key", "auto_push"]); + objectAttrsIsBool(data, ["auto_generate_key", "auto_push", "username_same_with_user"]); data["private_key"] = $("#id_private_key").data('file'); var props = { @@ -261,6 +267,15 @@ $(document).ready(function () { readFile($(this)).on("onload", function (evt, data) { $(this).data("file", data) }) +}).on("change", '#id_username_same_with_user', function () { + var checked = $(this).prop('checked'); + var usernameRef = $("#id_username"); + if (checked) { + usernameRef.val(''); + usernameRef.attr("disabled", true) + } else { + usernameRef.attr("disabled", false) + } }) diff --git a/apps/assets/templates/assets/admin_user_assets.html b/apps/assets/templates/assets/admin_user_assets.html index e77cbb689..a42c6032f 100644 --- a/apps/assets/templates/assets/admin_user_assets.html +++ b/apps/assets/templates/assets/admin_user_assets.html @@ -72,9 +72,9 @@ {% endblock %} diff --git a/apps/assets/templates/assets/system_user_assets.html b/apps/assets/templates/assets/system_user_assets.html index ec024c1a7..d48f48201 100644 --- a/apps/assets/templates/assets/system_user_assets.html +++ b/apps/assets/templates/assets/system_user_assets.html @@ -23,16 +23,23 @@
  • - {% trans 'Assets' %} + {% trans 'Asset list' %}
  • + {% if system_user.username_same_with_user %} +
  • + + {% trans 'User list' %} + +
  • + {% endif %}
    - {% trans 'Assets of ' %} {{ system_user.name }} {{ paginator.count }} + {{ system_user.name }} {{ paginator.count }}
    {% trans 'IP' %} {% trans 'Username' %} {% trans 'Version' %}{% trans 'Connectivity'%}{% trans 'Connectivity'%}{% trans 'Datetime' %} {% trans 'Action' %}
    +
    +
    + {% trans 'Assets' %} +
    +
    + + + + + + + + + + + +
    + +
    + +
    +
    +
    {% trans 'Nodes' %} @@ -92,7 +123,7 @@
    - @@ -114,6 +145,7 @@
    + {% include 'assets/_asset_list_modal.html' %} {% endblock %} {% block custom_foot_js %} diff --git a/apps/assets/templates/assets/system_user_detail.html b/apps/assets/templates/assets/system_user_detail.html index b9d6e5c0b..b26cfbf11 100644 --- a/apps/assets/templates/assets/system_user_detail.html +++ b/apps/assets/templates/assets/system_user_detail.html @@ -15,7 +15,14 @@ {% if system_user.can_perm_to_asset %}
  • - {% trans 'Assets' %} + {% trans 'Asset list' %} + +
  • + {% endif %} + {% if system_user.username_same_with_user %} +
  • + + {% trans 'User list' %}
  • {% endif %} @@ -57,7 +64,11 @@ {% trans 'Username' %}: - {{ system_user.username }} + {% if system_user.username_same_with_user %} + {% trans 'Username same with user' %} + {% else %} + {{ system_user.username }} + {% endif %} {% trans 'Login mode' %}: @@ -131,26 +142,6 @@ - {% if system_user.auto_push %} - - {% trans 'Push system user now' %}: - - - - - - - {% endif %} - {% if system_user.is_need_test_asset_connective %} - - {% trans 'Test assets connective' %}: - - - - - - - {% endif %}
    @@ -246,32 +237,7 @@ $(document).ready(function () { var redirect_url = "{% url 'assets:system-user-list' %}"; objectDelete($this, name, the_url, redirect_url); }) -.on('click', '.btn-push', function () { - var the_url = "{% url 'api-assets:system-user-push' pk=system_user.id %}"; - var success = function (data) { - var task_id = data.task; - showCeleryTaskLog(task_id); - }; - requestApi({ - url: the_url, - method: 'GET', - success: success, - flash_message: false - }); -}) -.on('click', '.btn-test-connective', function () { - var the_url = "{% url 'api-assets:system-user-connective' pk=system_user.id %}"; - var success = function (data) { - var task_id = data.task; - showCeleryTaskLog(task_id); - }; - requestApi({ - url: the_url, - method: 'GET', - success: success, - flash_message: false - }); -}).on('click', '#btn-binding-command-filters', function () { +.on('click', '#btn-binding-command-filters', function () { var new_selected_cmd_filters = $.map($('#command_filters_selected').select2('data'), function (i) { return i.id; }); diff --git a/apps/assets/templates/assets/system_user_list.html b/apps/assets/templates/assets/system_user_list.html index 0e88b6461..b3bd556ab 100644 --- a/apps/assets/templates/assets/system_user_list.html +++ b/apps/assets/templates/assets/system_user_list.html @@ -2,9 +2,9 @@ {% load i18n %} {% block help_message %} - {% trans 'System user is Jumpserver jump login assets used by the users, can be understood as the user login assets, such as web, sa, the dba (` ssh web@some-host `), rather than using a user the username login server jump (` ssh xiaoming@some-host `); '%} - {% trans 'In simple terms, users log into Jumpserver using their own username, and Jumpserver uses system users to log into assets. '%} - {% trans 'When system users are created, if you choose auto push Jumpserver to use Ansible push system users into the asset, if the asset (Switch) does not support ansible, please manually fill in the account password.' %} + {% trans 'System user is JumpServer jump login assets used by the users, can be understood as the user login assets, such as web, sa, the dba (` ssh web@some-host `), rather than using a user the username login server jump (` ssh xiaoming@some-host `); '%} + {% trans 'In simple terms, users log into JumpServer using their own username, and JumpServer uses system users to log into assets. '%} + {% trans 'When system users are created, if you choose auto push JumpServer to use Ansible push system users into the asset, if the asset (Switch) does not support ansible, please manually fill in the account password.' %} {% endblock %} {% block table_search %} @@ -26,9 +26,6 @@ {% trans 'Protocol' %} {% trans 'Login mode' %} {% trans 'Asset' %} -{# {% trans 'Reachable' %}#} -{# {% trans 'Unreachable' %}#} -{# {% trans 'Ratio' %}#} {% trans 'Comment' %} {% trans 'Action' %} @@ -40,6 +37,8 @@ {% block custom_foot_js %} +{% endblock %} diff --git a/apps/assets/tests.py b/apps/assets/tests.py deleted file mode 100644 index 7ce503c2d..000000000 --- a/apps/assets/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/apps/assets/tests/__init__.py b/apps/assets/tests/__init__.py new file mode 100644 index 000000000..ec51c5a2b --- /dev/null +++ b/apps/assets/tests/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +# diff --git a/apps/assets/tests/test_system_user.py b/apps/assets/tests/test_system_user.py new file mode 100644 index 000000000..ec51c5a2b --- /dev/null +++ b/apps/assets/tests/test_system_user.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +# diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py index 653b71447..279bd26be 100644 --- a/apps/assets/urls/api_urls.py +++ b/apps/assets/urls/api_urls.py @@ -21,82 +21,46 @@ router.register(r'domains', api.DomainViewSet, 'domain') router.register(r'gateways', api.GatewayViewSet, 'gateway') router.register(r'cmd-filters', api.CommandFilterViewSet, 'cmd-filter') router.register(r'asset-users', api.AssetUserViewSet, 'asset-user') -router.register(r'asset-users-info', api.AssetUserExportViewSet, 'asset-user-info') +router.register(r'asset-user-auth-infos', api.AssetUserAuthInfoViewSet, 'asset-user-auth-info') router.register(r'gathered-users', api.GatheredUserViewSet, 'gathered-user') router.register(r'favorite-assets', api.FavoriteAssetViewSet, 'favorite-asset') router.register(r'system-users-assets-relations', api.SystemUserAssetRelationViewSet, 'system-users-assets-relation') router.register(r'system-users-nodes-relations', api.SystemUserNodeRelationViewSet, 'system-users-nodes-relation') +router.register(r'system-users-users-relations', api.SystemUserUserRelationViewSet, 'system-users-users-relation') cmd_filter_router = routers.NestedDefaultRouter(router, r'cmd-filters', lookup='filter') cmd_filter_router.register(r'rules', api.CommandFilterRuleViewSet, 'cmd-filter-rule') urlpatterns = [ - path('assets//refresh/', - api.AssetRefreshHardwareApi.as_view(), name='asset-refresh'), - path('assets//alive/', - api.AssetAdminUserTestApi.as_view(), name='asset-alive-test'), - path('assets//gateway/', - api.AssetGatewayApi.as_view(), name='asset-gateway'), - path('assets//platform/', - api.AssetPlatformRetrieveApi.as_view(), name='asset-platform-detail'), + path('assets//gateways/', api.AssetGatewayListApi.as_view(), name='asset-gateway-list'), + path('assets//platform/', api.AssetPlatformRetrieveApi.as_view(), name='asset-platform-detail'), + path('assets//tasks/', api.AssetTaskCreateApi.as_view(), name='asset-task-create'), - path('asset-users/auth-info/', - api.AssetUserAuthInfoApi.as_view(), name='asset-user-auth-info'), - path('asset-users/test-connective/', - api.AssetUserTestConnectiveApi.as_view(), name='asset-user-connective'), + path('asset-users/tasks/', api.AssetUserTaskCreateAPI.as_view(), name='asset-user-task-create'), + path('admin-users//nodes/', api.ReplaceNodesAdminUserApi.as_view(), name='replace-nodes-admin-user'), + path('admin-users//auth/', api.AdminUserAuthApi.as_view(), name='admin-user-auth'), + path('admin-users//connective/', api.AdminUserTestConnectiveApi.as_view(), name='admin-user-connective'), + path('admin-users//assets/', api.AdminUserAssetsListView.as_view(), name='admin-user-assets'), - path('admin-users//nodes/', - api.ReplaceNodesAdminUserApi.as_view(), name='replace-nodes-admin-user'), - path('admin-users//auth/', - api.AdminUserAuthApi.as_view(), name='admin-user-auth'), - path('admin-users//connective/', - api.AdminUserTestConnectiveApi.as_view(), name='admin-user-connective'), - path('admin-users//assets/', - api.AdminUserAssetsListView.as_view(), name='admin-user-assets'), - - path('system-users//auth-info/', - api.SystemUserAuthInfoApi.as_view(), name='system-user-auth-info'), - path('system-users//assets//auth-info/', - api.SystemUserAssetAuthInfoApi.as_view(), name='system-user-asset-auth-info'), - path('system-users//assets/', - api.SystemUserAssetsListView.as_view(), name='system-user-assets'), - path('system-users//push/', - api.SystemUserPushApi.as_view(), name='system-user-push'), - path('system-users//assets//push/', - api.SystemUserPushToAssetApi.as_view(), name='system-user-push-to-asset'), - path('system-users//assets//test/', - api.SystemUserTestAssetConnectivityApi.as_view(), name='system-user-test-to-asset'), - path('system-users//connective/', - api.SystemUserTestConnectiveApi.as_view(), name='system-user-connective'), - path('system-users//cmd-filter-rules/', - api.SystemUserCommandFilterRuleListApi.as_view(), name='system-user-cmd-filter-rule-list'), + path('system-users//auth-info/', api.SystemUserAuthInfoApi.as_view(), name='system-user-auth-info'), + path('system-users//assets//auth-info/', api.SystemUserAssetAuthInfoApi.as_view(), name='system-user-asset-auth-info'), + path('system-users//tasks/', api.SystemUserTaskApi.as_view(), name='system-user-task-create'), + path('system-users//cmd-filter-rules/', api.SystemUserCommandFilterRuleListApi.as_view(), name='system-user-cmd-filter-rule-list'), path('nodes/tree/', api.NodeListAsTreeApi.as_view(), name='node-tree'), path('nodes/children/tree/', api.NodeChildrenAsTreeApi.as_view(), name='node-children-tree'), - path('nodes//children/', - api.NodeChildrenApi.as_view(), name='node-children'), + path('nodes//children/', api.NodeChildrenApi.as_view(), name='node-children'), path('nodes/children/', api.NodeChildrenApi.as_view(), name='node-children-2'), - path('nodes//children/add/', - api.NodeAddChildrenApi.as_view(), name='node-add-children'), - path('nodes//assets/', - api.NodeAssetsApi.as_view(), name='node-assets'), - path('nodes//assets/add/', - api.NodeAddAssetsApi.as_view(), name='node-add-assets'), - path('nodes//assets/replace/', - api.NodeReplaceAssetsApi.as_view(), name='node-replace-assets'), - path('nodes//assets/remove/', - api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'), - path('nodes//refresh-hardware-info/', - api.RefreshNodeHardwareInfoApi.as_view(), name='node-refresh-hardware-info'), - path('nodes//test-connective/', - api.TestNodeConnectiveApi.as_view(), name='node-test-connective'), + path('nodes//children/add/', api.NodeAddChildrenApi.as_view(), name='node-add-children'), + path('nodes//assets/', api.NodeAssetsApi.as_view(), name='node-assets'), + path('nodes//assets/add/', api.NodeAddAssetsApi.as_view(), name='node-add-assets'), + path('nodes//assets/replace/', api.NodeReplaceAssetsApi.as_view(), name='node-replace-assets'), + path('nodes//assets/remove/', api.NodeRemoveAssetsApi.as_view(), name='node-remove-assets'), + path('nodes//tasks/', api.NodeTaskCreateApi.as_view(), name='node-task-create'), - path('nodes/cache/', api.RefreshNodesCacheApi.as_view(), name='refresh-nodes-cache'), - - path('gateways//test-connective/', - api.GatewayTestConnectionApi.as_view(), name='test-gateway-connective'), + path('gateways//test-connective/', api.GatewayTestConnectionApi.as_view(), name='test-gateway-connective'), ] diff --git a/apps/assets/urls/views_urls.py b/apps/assets/urls/views_urls.py index eec9dcc0d..25b6deefd 100644 --- a/apps/assets/urls/views_urls.py +++ b/apps/assets/urls/views_urls.py @@ -39,6 +39,7 @@ urlpatterns = [ path('system-user//update/', views.SystemUserUpdateView.as_view(), name='system-user-update'), path('system-user//delete/', views.SystemUserDeleteView.as_view(), name='system-user-delete'), path('system-user//asset/', views.SystemUserAssetView.as_view(), name='system-user-asset'), + path('system-user//user/', views.SystemUserUserView.as_view(), name='system-user-user'), path('label/', views.LabelListView.as_view(), name='label-list'), path('label/create/', views.LabelCreateView.as_view(), name='label-create'), diff --git a/apps/assets/utils.py b/apps/assets/utils.py index eaf3d502a..25e8a46ea 100644 --- a/apps/assets/utils.py +++ b/apps/assets/utils.py @@ -5,68 +5,53 @@ from treelib.exceptions import NodeIDAbsentError from collections import defaultdict from copy import deepcopy -from common.utils import get_object_or_none, get_logger, timeit -from .models import SystemUser, Asset +from common.utils import get_logger, timeit, lazyproperty +from .models import Asset, Node logger = get_logger(__file__) -def get_system_user_by_name(name): - system_user = get_object_or_none(SystemUser, name=name) - return system_user - - -def get_system_user_by_id(id): - system_user = get_object_or_none(SystemUser, id=id) - return system_user - - class TreeService(Tree): tag_sep = ' / ' - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.nodes_assets_map = defaultdict(set) - self.all_nodes_assets_map = {} - self._invalid_assets = frozenset() + @staticmethod + @timeit + def get_nodes_assets_map(): + nodes_assets_map = defaultdict(set) + asset_node_list = Node.assets.through.objects.values_list( + 'asset', 'node__key' + ) + for asset_id, key in asset_node_list: + nodes_assets_map[key].add(asset_id) + return nodes_assets_map @classmethod @timeit def new(cls): from .models import Node - from orgs.utils import tmp_to_root_org - - with tmp_to_root_org(): - all_nodes = list(Node.objects.all().values("key", "value")) - all_nodes.sort(key=lambda x: len(x["key"].split(":"))) - tree = cls() - tree.create_node(tag='', identifier='') - for node in all_nodes: - key = node["key"] - value = node["value"] - parent_key = ":".join(key.split(":")[:-1]) - tree.safe_create_node( - tag=value, identifier=key, - parent=parent_key, - ) - tree.init_assets() + all_nodes = list(Node.objects.all().values("key", "value")) + all_nodes.sort(key=lambda x: len(x["key"].split(":"))) + tree = cls() + tree.create_node(tag='', identifier='', data={}) + for node in all_nodes: + key = node["key"] + value = node["value"] + parent_key = ":".join(key.split(":")[:-1]) + tree.safe_create_node( + tag=value, identifier=key, + parent=parent_key, + ) + tree.init_assets() return tree - @timeit def init_assets(self): - from orgs.utils import tmp_to_root_org - self.all_nodes_assets_map = {} - self.nodes_assets_map = defaultdict(set) - with tmp_to_root_org(): - queryset = Asset.objects.all().values_list('id', 'nodes__key') - invalid_assets = Asset.objects.filter(is_active=False)\ - .values_list('id', flat=True) - self._invalid_assets = frozenset(invalid_assets) - for asset_id, key in queryset: - if not key: - continue - self.nodes_assets_map[key].add(asset_id) + node_assets_map = self.get_nodes_assets_map() + for node in self.all_nodes_itr(): + key = node.identifier + assets = node_assets_map.get(key, set()) + data = {"assets": assets, "all_assets": None} + node.data = data def safe_create_node(self, **kwargs): parent = kwargs.get("parent") @@ -125,32 +110,43 @@ class TreeService(Tree): parent = self.copy_node(parent) return parent - def set_assets(self, nid, assets): - self.nodes_assets_map[nid] = set(assets) - - def assets(self, nid): - assets = self.nodes_assets_map[nid] + @lazyproperty + def invalid_assets(self): + assets = Asset.objects.filter(is_active=False).values_list('id', flat=True) return assets + def set_assets(self, nid, assets): + node = self.get_node(nid) + if node.data is None: + node.data = {} + node.data["assets"] = assets + + def assets(self, nid): + node = self.get_node(nid) + return node.data.get("assets", set()) + def valid_assets(self, nid): - return set(self.assets(nid)) - set(self._invalid_assets) + return set(self.assets(nid)) - set(self.invalid_assets) def all_assets(self, nid): - assets = self.all_nodes_assets_map.get(nid) - if assets: - return assets - assets = set(self.assets(nid)) + node = self.get_node(nid) + if node.data is None: + node.data = {} + all_assets = node.data.get("all_assets") + if all_assets is not None: + return all_assets + all_assets = set(self.assets(nid)) try: children = self.children(nid) except NodeIDAbsentError: children = [] for child in children: - assets.update(self.all_assets(child.identifier)) - self.all_nodes_assets_map[nid] = assets - return assets + all_assets.update(self.all_assets(child.identifier)) + node.data["all_assets"] = all_assets + return all_assets def all_valid_assets(self, nid): - return set(self.all_assets(nid)) - set(self._invalid_assets) + return set(self.all_assets(nid)) - set(self.invalid_assets) def assets_amount(self, nid): return len(self.all_assets(nid)) @@ -186,15 +182,12 @@ class TreeService(Tree): else: # logger.debug('Add node: {}'.format(node.identifier)) self.add_node(node, parent) - # # def __getstate__(self): # self.mutex = None + # self.all_nodes_assets_map = {} + # self.nodes_assets_map = {} # return self.__dict__ - # - def __setstate__(self, state): - self.__dict__ = state - if '_invalid_assets' not in state: - self._invalid_assets = frozenset() - # self.mutex = threading.Lock() + # def __setstate__(self, state): + # self.__dict__ = state diff --git a/apps/assets/views/admin_user.py b/apps/assets/views/admin_user.py index eaefffab7..611b03d7d 100644 --- a/apps/assets/views/admin_user.py +++ b/apps/assets/views/admin_user.py @@ -106,7 +106,7 @@ class AdminUserAssetsView(PermissionsMixin, SingleObjectMixin, ListView): def get_context_data(self, **kwargs): context = { 'app': _('Assets'), - 'action': _('Admin user detail'), + 'action': _('Admin user assets'), } kwargs.update(context) return super().get_context_data(**kwargs) diff --git a/apps/assets/views/platform.py b/apps/assets/views/platform.py index 2e3aff49c..8c74da138 100644 --- a/apps/assets/views/platform.py +++ b/apps/assets/views/platform.py @@ -48,6 +48,9 @@ class PlatformUpdateView(generic.UpdateView): model = Platform template_name = 'assets/platform_create_update.html' + def post(self, *args, **kwargs): + pass + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) meta_form = PlatformMetaForm(initial=self.object.meta) diff --git a/apps/assets/views/system_user.py b/apps/assets/views/system_user.py index 546df4430..5aa1e8431 100644 --- a/apps/assets/views/system_user.py +++ b/apps/assets/views/system_user.py @@ -17,6 +17,7 @@ __all__ = [ 'SystemUserCreateView', 'SystemUserUpdateView', 'SystemUserDetailView', 'SystemUserDeleteView', 'SystemUserAssetView', 'SystemUserListView', + 'SystemUserUserView', ] @@ -100,7 +101,22 @@ class SystemUserAssetView(PermissionsMixin, DetailView): def get_context_data(self, **kwargs): context = { 'app': _('assets'), - 'action': _('System user asset'), + 'action': _('System user assets'), + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class SystemUserUserView(PermissionsMixin, DetailView): + model = SystemUser + template_name = 'assets/system_user_users.html' + context_object_name = 'system_user' + permission_classes = [IsOrgAdmin] + + def get_context_data(self, **kwargs): + context = { + 'app': _('assets'), + 'action': _('System user users'), } kwargs.update(context) return super().get_context_data(**kwargs) diff --git a/apps/authentication/backends/cas/__init__.py b/apps/authentication/backends/cas/__init__.py new file mode 100644 index 000000000..bf0101c81 --- /dev/null +++ b/apps/authentication/backends/cas/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# +from .backends import * +from .callback import * diff --git a/apps/authentication/backends/cas/backends.py b/apps/authentication/backends/cas/backends.py new file mode 100644 index 000000000..ec56c6d4d --- /dev/null +++ b/apps/authentication/backends/cas/backends.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# +from django_cas_ng.backends import CASBackend as _CASBackend + + +__all__ = ['CASBackend'] + + +class CASBackend(_CASBackend): + def user_can_authenticate(self, user): + return True diff --git a/apps/authentication/backends/cas/callback.py b/apps/authentication/backends/cas/callback.py new file mode 100644 index 000000000..64201e607 --- /dev/null +++ b/apps/authentication/backends/cas/callback.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# +from django.contrib.auth import get_user_model + + +User = get_user_model() + + +def cas_callback(response): + username = response['username'] + user, user_created = User.objects.get_or_create(username=username) + profile, created = user.get_profile() + + profile.role = response['attributes']['role'] + profile.birth_date = response['attributes']['birth_date'] + profile.save() diff --git a/apps/authentication/backends/cas/urls.py b/apps/authentication/backends/cas/urls.py new file mode 100644 index 000000000..39a838b6a --- /dev/null +++ b/apps/authentication/backends/cas/urls.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- +# +from django.urls import path +import django_cas_ng.views + + +urlpatterns = [ + path('login/', django_cas_ng.views.LoginView.as_view(), name='cas-login'), + path('logout/', django_cas_ng.views.LogoutView.as_view(), name='cas-logout'), + path('callback/', django_cas_ng.views.CallbackView.as_view(), name='cas-proxy-callback'), +] diff --git a/apps/authentication/backends/ldap.py b/apps/authentication/backends/ldap.py index e01803707..ac3cfc254 100644 --- a/apps/authentication/backends/ldap.py +++ b/apps/authentication/backends/ldap.py @@ -29,26 +29,27 @@ class LDAPAuthorizationBackend(LDAPBackend): def pre_check(self, username, password): if not settings.AUTH_LDAP: - return False - logger.info('Authentication LDAP backend') + error = 'Not enabled auth ldap' + return False, error if not username: - logger.info('Authenticate failed: username is None') - return False + error = 'Username is None' + return False, error if not password: - logger.info('Authenticate failed: password is None') - return False + error = 'Password is None' + return False, error if settings.AUTH_LDAP_USER_LOGIN_ONLY_IN_USERS: user_model = self.get_user_model() exist = user_model.objects.filter(username=username).exists() if not exist: - msg = 'Authentication failed: user ({}) is not in the user list' - logger.info(msg.format(username)) - return False - return True + error = 'user ({}) is not in the user list'.format(username) + return False, error + return True, '' def authenticate(self, request=None, username=None, password=None, **kwargs): - match = self.pre_check(username, password) + logger.info('Authentication LDAP backend') + match, msg = self.pre_check(username, password) if not match: + logger.info('Authenticate failed: {}'.format(msg)) return None ldap_user = LDAPUser(self, username=username.strip(), request=request) user = self.authenticate_ldap_user(ldap_user, password) @@ -130,5 +131,5 @@ class LDAPUser(_LDAPUser): setattr(self._user, field, value) email = getattr(self._user, 'email', '') - email = construct_user_email(email, self._user.username) + email = construct_user_email(self._user.username, email) setattr(self._user, 'email', email) diff --git a/apps/authentication/backends/pubkey.py b/apps/authentication/backends/pubkey.py index db0ace648..3355eacaa 100644 --- a/apps/authentication/backends/pubkey.py +++ b/apps/authentication/backends/pubkey.py @@ -19,7 +19,7 @@ class PublicKeyAuthBackend: return None else: if user.check_public_key(public_key) and \ - self.user_can_authenticate(user): + self.user_can_authenticate(user): return user @staticmethod diff --git a/apps/authentication/errors.py b/apps/authentication/errors.py index b736ef606..183e69288 100644 --- a/apps/authentication/errors.py +++ b/apps/authentication/errors.py @@ -11,6 +11,7 @@ from users.utils import ( reason_password_failed = 'password_failed' reason_mfa_failed = 'mfa_failed' +reason_mfa_unset = 'mfa_unset' reason_user_not_exist = 'user_not_exist' reason_password_expired = 'password_expired' reason_user_invalid = 'user_invalid' @@ -18,7 +19,8 @@ reason_user_inactive = 'user_inactive' reason_choices = { reason_password_failed: _('Username/password check failed'), - reason_mfa_failed: _('MFA authentication failed'), + reason_mfa_failed: _('MFA failed'), + reason_mfa_unset: _('MFA unset'), reason_user_not_exist: _("Username does not exist"), reason_password_expired: _("Password expired"), reason_user_invalid: _('Disabled or expired'), @@ -46,6 +48,7 @@ block_login_msg = _( mfa_failed_msg = _("MFA code invalid, or ntp sync server time") mfa_required_msg = _("MFA required") +mfa_unset_msg = _("MFA not set, please set it first") login_confirm_required_msg = _("Login confirm required") login_confirm_wait_msg = _("Wait login confirm ticket for accept") login_confirm_error_msg = _("Login confirm ticket was {}") @@ -116,6 +119,16 @@ class MFAFailedError(AuthFailedNeedLogMixin, AuthFailedError): super().__init__(username=username, request=request) +class MFAUnsetError(AuthFailedNeedLogMixin, AuthFailedError): + error = reason_mfa_unset + msg = mfa_unset_msg + + def __init__(self, user, request, url): + super().__init__(username=user.username, request=request) + self.user = user + self.url = url + + class BlockLoginError(AuthFailedNeedBlockMixin, AuthFailedError): error = 'block_login' diff --git a/apps/authentication/mixins.py b/apps/authentication/mixins.py index 003027b0d..1c4fb5aa1 100644 --- a/apps/authentication/mixins.py +++ b/apps/authentication/mixins.py @@ -6,7 +6,7 @@ from django.conf import settings from common.utils import get_object_or_none, get_request_ip, get_logger from users.models import User from users.utils import ( - is_block_login, clean_failed_count, increase_login_failed_count, + is_block_login, clean_failed_count ) from . import errors from .utils import check_user_valid @@ -91,8 +91,9 @@ class AuthMixin: return if not user.mfa_enabled: return - if not user.otp_secret_key and user.mfa_is_otp(): - return + unset, url = user.mfa_enabled_but_not_set() + if unset: + raise errors.MFAUnsetError(user, self.request, url) raise errors.MFARequiredError() def check_user_mfa(self, code): diff --git a/apps/authentication/templates/authentication/_mfa_confirm_modal.html b/apps/authentication/templates/authentication/_mfa_confirm_modal.html index 60512d7de..dfa554ebc 100644 --- a/apps/authentication/templates/authentication/_mfa_confirm_modal.html +++ b/apps/authentication/templates/authentication/_mfa_confirm_modal.html @@ -14,7 +14,7 @@
    - {% trans "Need otp auth for view auth" %} + {% trans "Need MFA for view auth" %}
    {% trans "Confirm" %} diff --git a/apps/authentication/templates/authentication/login.html b/apps/authentication/templates/authentication/login.html index 5f1c68c5f..bff33eb17 100644 --- a/apps/authentication/templates/authentication/login.html +++ b/apps/authentication/templates/authentication/login.html @@ -1,116 +1,67 @@ +{% extends '_base_only_msg_content.html' %} {% load static %} {% load i18n %} - - - - - - Jumpserver - - {% include '_head_css_js.html' %} - - - - - +{% block content_title %} + {% trans 'Login' %} +{% endblock %} - -
    -
    -
    - -

    {% trans 'Welcome to the Jumpserver open source fortress' %}

    -

    - {% trans "The world's first fully open source fortress, using the GNU GPL v2.0 open source protocol, is a professional operation and maintenance audit system in compliance with 4A." %} -

    -

    - {% trans "Developed using Python/Django, following the Web 2.0 specification and equipped with industry-leading Web Terminal solutions, with beautiful interactive interface and good user experience." %} -

    -

    - {% trans 'Distributed architecture is adopted to support multi-machine room deployment across regions, central node provides API, and each machine room deploys login node, which can be extended horizontally and without concurrent access restrictions.' %} -

    -

    - {% trans "Changes the world, starting with a little bit." %} -

    +{% block content %} + + {% csrf_token %} + {% if form.non_field_errors %} +
    +

    {{ form.non_field_errors.as_text }}

    -
    -
    -
    - - {% trans 'Login' %} -
    - - {% csrf_token %} - {% if form.non_field_errors %} -
    -

    {{ form.non_field_errors.as_text }}

    -
    - {% elif form.errors.captcha %} -

    {% trans 'Captcha invalid' %}

    - {% endif %} - -
    - - {% if form.errors.username %} -
    -

    {{ form.errors.username.as_text }}

    -
    - {% endif %} -
    -
    - - {% if form.errors.password %} -
    -

    {{ form.errors.password.as_text }}

    -
    - {% endif %} -
    -
    - {{ form.captcha }} -
    - - - {% if demo_mode %} -

    - Demo账号: admin 密码: admin -

    - {% endif %} - - - - {% if AUTH_OPENID %} -
    -

    {% trans "More login options" %}

    -
    - -
    - {% endif %} - - + {% elif form.errors.captcha %} +

    {% trans 'Captcha invalid' %}

    + {% endif %} +
    + + {% if form.errors.username %} +
    +

    {{ form.errors.username.as_text }}

    + {% endif %} +
    +
    + + {% if form.errors.password %} +
    +

    {{ form.errors.password.as_text }}

    +
    + {% endif %} +
    +
    + {{ form.captcha }} +
    + + + {% if demo_mode %} +

    + Demo账号: admin 密码: admin +

    + {% endif %} + + -
    -
    -
    - {% include '_copyright.html' %} + + {% if AUTH_OPENID %} +
    +

    {% trans "More login options" %}

    +
    +
    -
    -
    - - + {% endif %} + + +{% endblock %} diff --git a/apps/authentication/templates/authentication/login_otp.html b/apps/authentication/templates/authentication/login_otp.html index 33ddb8e45..4b460ae66 100644 --- a/apps/authentication/templates/authentication/login_otp.html +++ b/apps/authentication/templates/authentication/login_otp.html @@ -1,88 +1,32 @@ +{% extends '_base_only_content.html' %} {% load static %} {% load i18n %} - - - - - - {{ JMS_TITLE }} - - {% include '_head_css_js.html' %} - - - - - - +{% block title %} + {% trans 'MFA' %} +{% endblock %} - -
    -
    -
    -

    {% trans 'Welcome to the Jumpserver open source fortress' %}

    -

    - {% trans "The world's first fully open source fortress, using the GNU GPL v2.0 open source protocol, is a professional operation and maintenance audit system in compliance with 4A." %} -

    -

    - {% trans "Developed using Python/Django, following the Web 2.0 specification and equipped with industry-leading Web Terminal solutions, with beautiful interactive interface and good user experience." %} -

    -

    - {% trans 'Distributed architecture is adopted to support multi-machine room deployment across regions, central node provides API, and each machine room deploys login node, which can be extended horizontally and without concurrent access restrictions.' %} -

    -

    - {% trans "Changes the world, starting with a little bit." %} -

    - -
    -
    -
    -
    - - {% trans 'MFA certification' %} -
    -
    - -
    -

    {% trans 'The account protection has been opened, please complete the following operations according to the prompts' %}

    -
    - -
    -

     {% trans 'Open Authenticator and enter the 6-bit dynamic code' %}

    -
    - -
    - - {% csrf_token %} - {% if 'otp_code' in form.errors %} -

    {{ form.otp_code.errors.as_text }}

    - {% endif %} -
    - -
    - - - - {% trans "Can't provide security? Please contact the administrator!" %} - - -
    -
    -

    -

    -
    -
    +{% block content %} +
    + {% csrf_token %} + {% if 'otp_code' in form.errors %} +

    {{ form.otp_code.errors.as_text }}

    + {% endif %} +
    +
    -
    -
    -
    - {% include '_copyright.html' %} -
    +
    + + + {% trans 'Open Google Authenticator and enter the 6-bit dynamic code' %} +
    -
    - - + + +
    + {% trans "Can't provide security? Please contact the administrator!" %} +
    +
    +{% endblock %} diff --git a/apps/authentication/urls/view_urls.py b/apps/authentication/urls/view_urls.py index 64d01ae34..b9f76e731 100644 --- a/apps/authentication/urls/view_urls.py +++ b/apps/authentication/urls/view_urls.py @@ -1,8 +1,6 @@ # coding:utf-8 # -from __future__ import absolute_import - from django.urls import path, include from .. import views @@ -10,13 +8,14 @@ from .. import views app_name = 'authentication' urlpatterns = [ - # openid - path('openid/', include(('authentication.backends.openid.urls', 'authentication'), namespace='openid')), - # login path('login/', views.UserLoginView.as_view(), name='login'), path('login/otp/', views.UserLoginOtpView.as_view(), name='login-otp'), path('login/wait-confirm/', views.UserLoginWaitConfirmView.as_view(), name='login-wait-confirm'), path('login/guard/', views.UserLoginGuardView.as_view(), name='login-guard'), path('logout/', views.UserLogoutView.as_view(), name='logout'), + + # openid + path('openid/', include(('authentication.backends.openid.urls', 'authentication'), namespace='openid')), + path('cas/', include(('authentication.backends.cas.urls', 'authentication'), namespace='cas')), ] diff --git a/apps/authentication/views/login.py b/apps/authentication/views/login.py index de3e0dd31..8310b4c8b 100644 --- a/apps/authentication/views/login.py +++ b/apps/authentication/views/login.py @@ -20,7 +20,7 @@ from django.urls import reverse_lazy from common.utils import get_request_ip, get_object_or_none from users.utils import ( - redirect_user_first_login_or_index, set_tmp_user_to_cache + redirect_user_first_login_or_index ) from .. import forms, mixins, errors @@ -52,17 +52,29 @@ class UserLoginView(mixins.AuthMixin, FormView): template_name = 'authentication/xpack_login.html' return template_name + def get_redirect_url_if_need(self, request): + redirect_url = '' + # show jumpserver login page if request http://{JUMP-SERVER}/?admin=1 + if self.request.GET.get("admin", 0): + return None + if settings.AUTH_OPENID: + redirect_url = reverse("authentication:openid:openid-login") + elif settings.AUTH_CAS: + redirect_url = reverse(settings.CAS_LOGIN_URL_NAME) + + if redirect_url: + query_string = request.GET.urlencode() + redirect_url = "{}?{}".format(redirect_url, query_string) + return redirect_url + def get(self, request, *args, **kwargs): if request.user.is_staff: return redirect(redirect_user_first_login_or_index( request, self.redirect_field_name) ) - # show jumpserver login page if request http://{JUMP-SERVER}/?admin=1 - if settings.AUTH_OPENID and not self.request.GET.get('admin', 0): - query_string = request.GET.urlencode() - openid_login_url = reverse_lazy("authentication:openid:openid-login") - login_url = "{}?{}".format(openid_login_url, query_string) - return redirect(login_url) + redirect_url = self.get_redirect_url_if_need(request) + if redirect_url: + return redirect(redirect_url) request.session.set_test_cookie() return super().get(request, *args, **kwargs) @@ -127,12 +139,9 @@ class UserLoginGuardView(mixins.AuthMixin, RedirectView): return self.format_redirect_url(self.login_otp_url) except errors.LoginConfirmBaseError: return self.format_redirect_url(self.login_confirm_url) + except errors.MFAUnsetError as e: + return e.url else: - # 启用但是没有设置otp, 排除radius - if user.mfa_enabled_but_not_set(): - # 1,2,mfa_setting & F - set_tmp_user_to_cache(self.request, user) - return reverse('users:user-otp-enable-authentication') auth_login(self.request, user) self.send_auth_signal(success=True, user=user) self.clear_auth_mark() @@ -174,8 +183,17 @@ class UserLoginWaitConfirmView(TemplateView): class UserLogoutView(TemplateView): template_name = 'flash_message_standalone.html' + @staticmethod + def get_backend_logout_url(): + if settings.AUTH_CAS: + return settings.CAS_LOGOUT_URL_NAME + return None + def get(self, request, *args, **kwargs): auth_logout(request) + backend_logout_url = self.get_backend_logout_url() + if backend_logout_url: + return redirect(backend_logout_url) next_uri = request.COOKIES.get("next") if next_uri: return redirect(next_uri) diff --git a/apps/common/README.md b/apps/common/README.md index 400f19fc8..457fee410 100644 --- a/apps/common/README.md +++ b/apps/common/README.md @@ -16,7 +16,7 @@ provide this ability, not common, You should write it on your app utils. ## Celery usage -Jumpserver use celery to run task async. Using redis as the broker, so +JumpServer use celery to run task async. Using redis as the broker, so you should run a redis instance #### Run redis diff --git a/apps/common/mixins/api.py b/apps/common/mixins/api.py index 694c5606d..6440cdd10 100644 --- a/apps/common/mixins/api.py +++ b/apps/common/mixins/api.py @@ -1,13 +1,20 @@ # -*- coding: utf-8 -*- # +import time +from hashlib import md5 +from threading import Thread + +from django.core.cache import cache from django.http import JsonResponse +from rest_framework.response import Response from rest_framework.settings import api_settings from common.drf.filters import IDSpmFilter, CustomFilter +from ..utils import lazyproperty __all__ = [ "JSONResponseMixin", "CommonApiMixin", - "IDSpmFilterMixin", + "IDSpmFilterMixin", 'AsyncApiMixin', ] @@ -62,3 +69,122 @@ class ExtraFilterFieldsMixin: class CommonApiMixin(SerializerMixin, ExtraFilterFieldsMixin): pass + + +class InterceptMixin: + def dispatch(self, request, *args, **kwargs): + self.args = args + self.kwargs = kwargs + request = self.initialize_request(request, *args, **kwargs) + self.request = request + self.headers = self.default_response_headers # deprecate? + + try: + self.initial(request, *args, **kwargs) + + # Get the appropriate handler method + if request.method.lower() in self.http_method_names: + handler = getattr(self, request.method.lower(), + self.http_method_not_allowed) + else: + handler = self.http_method_not_allowed + + response = self.do(handler, request, *args, **kwargs) + + except Exception as exc: + response = self.handle_exception(exc) + + self.response = self.finalize_response(request, response, *args, **kwargs) + return self.response + + +class AsyncApiMixin(InterceptMixin): + def get_request_user_id(self): + user = self.request.user + if hasattr(user, 'id'): + return str(user.id) + return '' + + @lazyproperty + def async_cache_key(self): + method = self.request.method + path = self.get_request_md5() + user = self.get_request_user_id() + key = '{}_{}_{}'.format(method, path, user) + return key + + def get_request_md5(self): + path = self.request.path + query = {k: v for k, v in self.request.GET.items()} + query.pop("_", None) + query.pop('refresh', None) + query = "&".join(["{}={}".format(k, v) for k, v in query.items()]) + full_path = "{}?{}".format(path, query) + return md5(full_path.encode()).hexdigest() + + @lazyproperty + def initial_data(self): + data = { + "status": "running", + "start_time": time.time(), + "key": self.async_cache_key, + } + return data + + def get_cache_data(self): + key = self.async_cache_key + if self.is_need_refresh(): + cache.delete(key) + return None + data = cache.get(key) + return data + + def do(self, handler, *args, **kwargs): + if not self.is_need_async(): + return handler(*args, **kwargs) + resp = self.do_async(handler, *args, **kwargs) + return resp + + def is_need_refresh(self): + if self.request.GET.get("refresh"): + return True + return False + + def is_need_async(self): + return False + + def do_async(self, handler, *args, **kwargs): + data = self.get_cache_data() + if not data: + t = Thread( + target=self.do_in_thread, + args=(handler, *args), + kwargs=kwargs + ) + t.start() + resp = Response(self.initial_data) + return resp + status = data.get("status") + resp = data.get("resp") + if status == "ok" and resp: + resp = Response(**resp) + else: + resp = Response(data) + return resp + + def do_in_thread(self, handler, *args, **kwargs): + key = self.async_cache_key + data = self.initial_data + cache.set(key, data, 600) + try: + response = handler(*args, **kwargs) + data["status"] = "ok" + data["resp"] = { + "data": response.data, + "status": response.status_code + } + cache.set(key, data, 600) + except Exception as e: + data["error"] = str(e) + data["status"] = "error" + cache.set(key, data, 600) diff --git a/apps/common/mixins/models.py b/apps/common/mixins/models.py index e373a6b08..e0d9b392a 100644 --- a/apps/common/mixins/models.py +++ b/apps/common/mixins/models.py @@ -5,7 +5,6 @@ from django.db import models from django.utils import timezone from django.utils.translation import ugettext_lazy as _ - __all__ = [ "NoDeleteManager", "NoDeleteModelMixin", "NoDeleteQuerySet", "CommonModelMixin" @@ -65,3 +64,5 @@ class DebugQueryManager(models.Manager): print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<") queryset = super().get_queryset() return queryset + + diff --git a/apps/common/struct.py b/apps/common/struct.py index 88bace4a7..e9949de98 100644 --- a/apps/common/struct.py +++ b/apps/common/struct.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- # +from itertools import chain +from .utils import lazyproperty class Stack(list): @@ -23,3 +25,82 @@ class Stack(list): def push(self, item): self.append(item) + + +class QuerySetChain: + def __init__(self, querysets): + self.querysets = querysets + + @lazyproperty + def querysets_counts(self): + counts = [s.count() for s in self.querysets] + return counts + + def count(self): + return self.total_count + + @lazyproperty + def total_count(self): + return sum(self.querysets_counts) + + def __iter__(self): + self._chain = chain(*self.querysets) + return self + + def __next__(self): + return next(self._chain) + + def __getitem__(self, ndx): + querysets_count_zip = zip(self.querysets, self.querysets_counts) + length = 0 # 加上本数组后的大数组长度 + pre_length = 0 # 不包含本数组的大数组长度 + items = [] # 返回的值 + loop = 0 + + if isinstance(ndx, slice): + ndx_start = ndx.start or 0 + ndx_stop = ndx.stop or self.total_count + ndx_step = ndx.step or 1 + else: + ndx_start = ndx + ndx_stop, ndx_step = None, None + + for queryset, count in querysets_count_zip: + length += count + loop += 1 + # 取当前数组的start角标, 存在3中情况 + # 1. start角标在当前数组 + if length > ndx_start >= pre_length: + start = ndx_start - pre_length + # print("[loop {}] Start is: {}".format(loop, start)) + if ndx_step is None: + return queryset[start] + # 2. 不包含当前数组,因为起始已经超过了当前数组的长度 + elif ndx_start >= length: + pre_length += count + continue + # 3. 不在当前数组,但是应该从当前数组0开始计算 + else: + start = 0 + + # 可能取单个值, ndx_stop 为None, 不应该再找 + if ndx_stop is None: + pre_length += count + continue + + # 取当前数组的stop角标, 存在2中情况 + # 不存在第3中情况是因为找到了会提交结束循环 + # 1. 结束角标小于length代表 结束位在当前数组上 + if ndx_stop < length: + stop = ndx_stop - pre_length + # 2. 结束位置包含改数组到了最后 + else: + stop = count + # print("[loop {}] Slice: {} {} {}".format(loop, start, stop, ndx_step)) + items.extend(list(queryset[slice(start, stop, ndx_step)])) + pre_length += count + + # 如果结束再当前数组,则结束循环 + if ndx_stop < length: + break + return items diff --git a/apps/common/utils/common.py b/apps/common/utils/common.py index 07116ea8b..77a48dc60 100644 --- a/apps/common/utils/common.py +++ b/apps/common/utils/common.py @@ -199,11 +199,15 @@ logger = get_logger(__name__) def timeit(func): def wrapper(*args, **kwargs): - logger.debug("Start call: {}".format(func.__name__)) + if hasattr(func, '__name__'): + name = func.__name__ + else: + name = func + logger.debug("Start call: {}".format(name)) now = time.time() result = func(*args, **kwargs) using = (time.time() - now) * 1000 - msg = "End call {}, using: {:.1f}ms".format(func.__name__, using) + msg = "End call {}, using: {:.1f}ms".format(name, using) logger.debug(msg) return result return wrapper diff --git a/apps/common/utils/random.py b/apps/common/utils/random.py new file mode 100644 index 000000000..f32147b6d --- /dev/null +++ b/apps/common/utils/random.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# +import socket +import struct +import random + + +def random_datetime(date_start, date_end): + random_delta = (date_end - date_start) * random.random() + return date_start + random_delta + + +def random_ip(): + return socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff))) + + + +# def strTimeProp(start, end, prop, fmt): +# time_start = time.mktime(time.strptime(start, fmt)) +# time_end = time.mktime(time.strptime(end, fmt)) +# ptime = time_start + prop * (time_end - time_start) +# return int(ptime) +# +# +# def randomTimestamp(start, end, fmt='%Y-%m-%d %H:%M:%S'): +# return strTimeProp(start, end, random.random(), fmt) +# +# +# def randomDate(start, end, frmt='%Y-%m-%d %H:%M:%S'): +# return time.strftime(frmt, time.localtime(strTimeProp(start, end, random.random(), frmt))) +# +# +# def randomTimestampList(start, end, n, frmt='%Y-%m-%d %H:%M:%S'): +# return [randomTimestamp(start, end, frmt) for _ in range(n)] +# +# +# def randomDateList(start, end, n, frmt='%Y-%m-%d %H:%M:%S'): +# return [randomDate(start, end, frmt) for _ in range(n)] + diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 8707690c2..bfed4ec9d 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -84,11 +84,10 @@ class Config(dict): :param defaults: an optional dictionary of default values """ defaults = { - # Django Config + # Django Config, Must set before start 'SECRET_KEY': '', 'BOOTSTRAP_TOKEN': '', 'DEBUG': True, - 'SITE_URL': 'http://localhost:8080', 'LOG_LEVEL': 'DEBUG', 'LOG_DIR': os.path.join(PROJECT_DIR, 'logs'), 'DB_ENGINE': 'mysql', @@ -100,10 +99,13 @@ class Config(dict): 'REDIS_HOST': '127.0.0.1', 'REDIS_PORT': 6379, 'REDIS_PASSWORD': '', + # Default value 'REDIS_DB_CELERY': 3, 'REDIS_DB_CACHE': 4, 'REDIS_DB_SESSION': 5, 'REDIS_DB_WS': 6, + + 'SITE_URL': 'http://localhost:8080', 'CAPTCHA_TEST_MODE': None, 'TOKEN_EXPIRATION': 3600 * 24, 'DISPLAY_PER_PAGE': 25, @@ -148,8 +150,13 @@ class Config(dict): 'RADIUS_ENCRYPT_PASSWORD': True, 'OTP_IN_RADIUS': False, + 'AUTH_CAS': False, + 'CAS_SERVER_URL': "http://host/cas/", + 'CAS_LOGOUT_COMPLETELY': False, + 'CAS_VERSION': 3, + 'OTP_VALID_WINDOW': 2, - 'OTP_ISSUER_NAME': 'Jumpserver', + 'OTP_ISSUER_NAME': 'JumpServer', 'EMAIL_SUFFIX': 'jumpserver.org', 'TERMINAL_PASSWORD_AUTH': True, @@ -179,6 +186,7 @@ class Config(dict): 'HTTP_LISTEN_PORT': 8080, 'WS_LISTEN_PORT': 8070, 'LOGIN_LOG_KEEP_DAYS': 90, + 'TASK_LOG_KEEP_DAYS': 10, 'ASSETS_PERM_CACHE_TIME': 3600 * 24, 'SECURITY_MFA_VERIFY_TTL': 3600, 'ASSETS_PERM_CACHE_ENABLE': False, @@ -284,6 +292,8 @@ class DynamicConfig: ] if self.get('AUTH_LDAP'): backends.insert(0, 'authentication.backends.ldap.LDAPAuthorizationBackend') + if self.static_config.get('AUTH_CAS'): + backends.insert(0, 'authentication.backends.cas.CASBackend') if self.static_config.get('AUTH_OPENID'): backends.insert(0, 'authentication.backends.openid.backends.OpenIDAuthorizationPasswordBackend') backends.insert(0, 'authentication.backends.openid.backends.OpenIDAuthorizationCodeBackend') diff --git a/apps/jumpserver/context_processor.py b/apps/jumpserver/context_processor.py index 0fbef047f..0a49b957d 100644 --- a/apps/jumpserver/context_processor.py +++ b/apps/jumpserver/context_processor.py @@ -13,7 +13,7 @@ def jumpserver_processor(request): 'LOGO_TEXT_URL': static('img/logo_text.png'), 'LOGIN_IMAGE_URL': static('img/login_image.png'), 'FAVICON_URL': static('img/facio.ico'), - 'JMS_TITLE': 'Jumpserver', + 'JMS_TITLE': 'JumpServer', 'VERSION': settings.VERSION, 'COPYRIGHT': 'FIT2CLOUD 飞致云' + ' © 2014-2020', 'SECURITY_COMMAND_EXECUTION': settings.SECURITY_COMMAND_EXECUTION, diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index 978faa751..e6245d02c 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -64,7 +64,21 @@ RADIUS_SERVER = CONFIG.RADIUS_SERVER RADIUS_PORT = CONFIG.RADIUS_PORT RADIUS_SECRET = CONFIG.RADIUS_SECRET +# CAS Auth +AUTH_CAS = CONFIG.AUTH_CAS +CAS_SERVER_URL = CONFIG.CAS_SERVER_URL +CAS_VERIFY_SSL_CERTIFICATE = False +CAS_LOGIN_URL_NAME = "authentication:cas:cas-login" +CAS_LOGOUT_URL_NAME = "authentication:cas:cas-logout" +CAS_LOGIN_MSG = None +CAS_LOGGED_MSG = None +CAS_LOGOUT_COMPLETELY = CONFIG.CAS_LOGOUT_COMPLETELY +CAS_VERSION = CONFIG.CAS_VERSION + +# Other setting TOKEN_EXPIRATION = CONFIG.TOKEN_EXPIRATION LOGIN_CONFIRM_ENABLE = CONFIG.LOGIN_CONFIRM_ENABLE OTP_IN_RADIUS = CONFIG.OTP_IN_RADIUS + +AUTHENTICATION_BACKENDS = DYNAMIC.AUTHENTICATION_BACKENDS diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index 49425b488..22ebd1775 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -51,6 +51,7 @@ INSTALLED_APPS = [ 'rest_framework', 'rest_framework_swagger', 'drf_yasg', + 'django_cas_ng', 'channels', 'django_filters', 'bootstrap3', @@ -75,6 +76,7 @@ MIDDLEWARE = [ 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'authentication.backends.openid.middleware.OpenIDAuthenticationMiddleware', + 'django_cas_ng.middleware.CASMiddleware', 'jumpserver.middleware.TimezoneMiddleware', 'jumpserver.middleware.DemoMiddleware', 'jumpserver.middleware.RequestMiddleware', @@ -220,8 +222,6 @@ EMAIL_USE_SSL = DYNAMIC.EMAIL_USE_SSL EMAIL_USE_TLS = DYNAMIC.EMAIL_USE_TLS -AUTHENTICATION_BACKENDS = DYNAMIC.AUTHENTICATION_BACKENDS - # Custom User Auth model AUTH_USER_MODEL = 'users.User' diff --git a/apps/jumpserver/settings/custom.py b/apps/jumpserver/settings/custom.py index 8a86ba284..a55693c55 100644 --- a/apps/jumpserver/settings/custom.py +++ b/apps/jumpserver/settings/custom.py @@ -82,5 +82,6 @@ USER_GUIDE_URL = DYNAMIC.USER_GUIDE_URL HTTP_LISTEN_PORT = CONFIG.HTTP_LISTEN_PORT WS_LISTEN_PORT = CONFIG.WS_LISTEN_PORT LOGIN_LOG_KEEP_DAYS = DYNAMIC.LOGIN_LOG_KEEP_DAYS +TASK_LOG_KEEP_DAYS = CONFIG.TASK_LOG_KEEP_DAYS ORG_CHANGE_TO_URL = CONFIG.ORG_CHANGE_TO_URL WINDOWS_SKIP_ALL_MANUAL_PASSWORD = CONFIG.WINDOWS_SKIP_ALL_MANUAL_PASSWORD diff --git a/apps/jumpserver/settings/libs.py b/apps/jumpserver/settings/libs.py index 69b580d66..706fb3647 100644 --- a/apps/jumpserver/settings/libs.py +++ b/apps/jumpserver/settings/libs.py @@ -53,6 +53,7 @@ SWAGGER_SETTINGS = { 'in': 'header' } }, + 'DEFAULT_INFO': 'jumpserver.views.swagger.api_info', } diff --git a/apps/jumpserver/settings/logging.py b/apps/jumpserver/settings/logging.py index 7de84ab7e..35eaee3b6 100644 --- a/apps/jumpserver/settings/logging.py +++ b/apps/jumpserver/settings/logging.py @@ -96,12 +96,16 @@ LOGGING = { 'handlers': ['syslog'], 'level': 'INFO' }, - # 'django.db': { - # 'handlers': ['console', 'file'], - # 'level': 'DEBUG' - # } + } } + +if os.environ.get("DEBUG_DB"): + LOGGING['loggers']['django.db'] = { + 'handlers': ['console', 'file'], + 'level': 'DEBUG' + } + SYSLOG_ENABLE = CONFIG.SYSLOG_ENABLE if CONFIG.SYSLOG_ADDR != '' and len(CONFIG.SYSLOG_ADDR.split(':')) == 2: diff --git a/apps/jumpserver/views/index.py b/apps/jumpserver/views/index.py index 2a3304a8c..5cd034a2d 100644 --- a/apps/jumpserver/views/index.py +++ b/apps/jumpserver/views/index.py @@ -1,30 +1,214 @@ -import datetime - +from django.core.cache import cache from django.views.generic import TemplateView from django.utils import timezone from django.utils.translation import ugettext_lazy as _ -from django.db.models import Count +from django.db.models import Count, Max from django.shortcuts import redirect - from users.models import User from assets.models import Asset from terminal.models import Session from orgs.utils import current_org from common.permissions import PermissionsMixin, IsValidUser +from common.utils import timeit, lazyproperty __all__ = ['IndexView'] -class IndexView(PermissionsMixin, TemplateView): +class MonthLoginMetricMixin: + @lazyproperty + def session_month(self): + month_ago = timezone.now() - timezone.timedelta(days=30) + session_month = Session.objects.filter(date_start__gt=month_ago) + return session_month + + @lazyproperty + def session_month_dates(self): + return self.session_month.dates('date_start', 'day') + + def get_month_day_metrics(self): + month_str = [ + d.strftime('%m-%d') for d in self.session_month_dates + ] or ['0'] + return month_str + + @staticmethod + def get_cache_key(date, tp): + date_str = date.strftime("%Y%m%d") + key = "SESSION_MONTH_{}_{}".format(tp, date_str) + return key + + def __get_data_from_cache(self, date, tp): + if date == timezone.now().date(): + return None + cache_key = self.get_cache_key(date, tp) + count = cache.get(cache_key) + return count + + def __set_data_to_cache(self, date, tp, count): + cache_key = self.get_cache_key(date, tp) + cache.set(cache_key, count, 3600*24*7) + + @lazyproperty + def user_disabled_total(self): + return current_org.get_org_members().filter(is_active=False).count() + + @lazyproperty + def asset_disabled_total(self): + return Asset.objects.filter(is_active=False).count() + + def get_date_login_count(self, date): + tp = "LOGIN" + count = self.__get_data_from_cache(date, tp) + if count is not None: + return count + count = Session.objects.filter(date_start__date=date).count() + self.__set_data_to_cache(date, tp, count) + return count + + def get_month_login_metrics(self): + data = [] + for d in self.session_month_dates: + count = self.get_date_login_count(d) + data.append(count) + if len(data) == 0: + data = [0] + return data + + def get_date_user_count(self, date): + tp = "USER" + count = self.__get_data_from_cache(date, tp) + if count is not None: + return count + count = Session.objects.filter(date_start__date=date)\ + .values('user').distinct().count() + self.__set_data_to_cache(date, tp, count) + return count + + def get_month_active_user_metrics(self): + data = [] + for d in self.session_month_dates: + count = self.get_date_user_count(d) + data.append(count) + return data + + def get_date_asset_count(self, date): + tp = "ASSET" + count = self.__get_data_from_cache(date, tp) + if count is not None: + return count + count = Session.objects.filter(date_start__date=date) \ + .values('asset').distinct().count() + self.__set_data_to_cache(date, tp, count) + return count + + def get_month_active_asset_metrics(self): + data = [] + for d in self.session_month_dates: + count = self.get_date_asset_count(d) + data.append(count) + return data + + @lazyproperty + def month_active_user_total(self): + count = self.session_month.values('user').distinct().count() + return count + + @lazyproperty + def month_inactive_user_total(self): + total = current_org.get_org_members().count() + active = self.month_active_user_total + count = total - active + if count < 0: + count = 0 + return count + + @lazyproperty + def month_active_asset_total(self): + return self.session_month.values('asset').distinct().count() + + @lazyproperty + def month_inactive_asset_total(self): + total = Asset.objects.all().count() + active = self.month_active_asset_total + count = total - active + if count < 0: + count = 0 + return count + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context.update({ + 'month_str': self.get_month_day_metrics(), + 'month_total_visit_count': self.get_month_login_metrics(), + 'month_user': self.get_month_active_user_metrics(), + 'mouth_asset': self.get_month_active_asset_metrics(), + 'month_user_active': self.month_active_user_total, + 'month_user_inactive': self.month_inactive_user_total, + 'month_user_disabled': self.user_disabled_total, + 'month_asset_active': self.month_active_asset_total, + 'month_asset_inactive': self.month_inactive_asset_total, + 'month_asset_disabled': self.asset_disabled_total, + }) + return context + + +class WeekSessionMetricMixin: + session_week = None + + @lazyproperty + def session_week(self): + week_ago = timezone.now() - timezone.timedelta(weeks=1) + session_week = Session.objects.filter(date_start__gt=week_ago) + return session_week + + def get_top5_user_a_week(self): + users = self.session_week.values('user') \ + .annotate(total=Count('user')) \ + .order_by('-total')[:5] + return users + + def get_week_login_user_count(self): + return self.session_week.values('user').distinct().count() + + def get_week_login_asset_count(self): + return self.session_week.count() + + def get_week_top10_assets(self): + assets = self.session_week.values("asset")\ + .annotate(total=Count("asset"))\ + .annotate(last=Max("date_start")).order_by("-total")[:10] + return assets + + def get_week_top10_users(self): + users = self.session_week.values("user") \ + .annotate(total=Count("user")) \ + .annotate(last=Max("date_start")).order_by("-total")[:10] + return users + + def get_last10_sessions(self): + sessions = self.session_week.order_by('-date_start')[:10] + for session in sessions: + session.avatar_url = User.get_avatar_url("") + return sessions + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context.update({ + 'user_visit_count_weekly': self.get_week_login_user_count(), + 'asset_visit_count_weekly': self.get_week_login_asset_count(), + 'user_visit_count_top_five': self.get_top5_user_a_week(), + 'last_login_ten': self.get_last10_sessions(), + 'week_asset_hot_ten': self.get_week_top10_assets(), + 'week_user_hot_ten': self.get_week_top10_users(), + }) + return context + + +class IndexView(PermissionsMixin, MonthLoginMetricMixin, WeekSessionMetricMixin, TemplateView): template_name = 'index.html' permission_classes = [IsValidUser] - session_week = None - session_month = None - session_month_dates = [] - session_month_dates_archive = [] - def dispatch(self, request, *args, **kwargs): if not request.user.is_authenticated: return self.handle_no_permission() @@ -42,141 +226,21 @@ class IndexView(PermissionsMixin, TemplateView): @staticmethod def get_online_user_count(): - return len(set(Session.objects.filter(is_finished=False).values_list('user', flat=True))) + count = Session.objects.filter(is_finished=False)\ + .values_list('user', flat=True).distinct().count() + return count @staticmethod def get_online_session_count(): return Session.objects.filter(is_finished=False).count() - def get_top5_user_a_week(self): - return self.session_week.values('user').annotate(total=Count('user')).order_by('-total')[:5] - - def get_week_login_user_count(self): - return self.session_week.values('user').distinct().count() - - def get_week_login_asset_count(self): - return self.session_week.count() - - def get_month_day_metrics(self): - month_str = [d.strftime('%m-%d') for d in self.session_month_dates] or ['0'] - return month_str - - def get_month_login_metrics(self): - data = [] - time_min = datetime.datetime.min.time() - time_max = datetime.datetime.max.time() - for d in self.session_month_dates: - ds = datetime.datetime.combine(d, time_min).replace(tzinfo=timezone.get_current_timezone()) - de = datetime.datetime.combine(d, time_max).replace(tzinfo=timezone.get_current_timezone()) - data.append(self.session_month.filter(date_start__range=(ds, de)).count()) - return data - - def get_month_active_user_metrics(self): - if self.session_month_dates_archive: - return [q.values('user').distinct().count() - for q in self.session_month_dates_archive] - else: - return [0] - - def get_month_active_asset_metrics(self): - if self.session_month_dates_archive: - return [q.values('asset').distinct().count() - for q in self.session_month_dates_archive] - else: - return [0] - - def get_month_active_user_total(self): - return self.session_month.values('user').distinct().count() - - def get_month_inactive_user_total(self): - count = current_org.get_org_members().count() - self.get_month_active_user_total() - if count < 0: - count = 0 - return count - - def get_month_active_asset_total(self): - return self.session_month.values('asset').distinct().count() - - def get_month_inactive_asset_total(self): - count = Asset.objects.all().count() - self.get_month_active_asset_total() - if count < 0: - count = 0 - return count - - @staticmethod - def get_user_disabled_total(): - return current_org.get_org_members().filter(is_active=False).count() - - @staticmethod - def get_asset_disabled_total(): - return Asset.objects.filter(is_active=False).count() - - def get_week_top10_asset(self): - assets = list(self.session_week.values('asset').annotate(total=Count('asset')).order_by('-total')[:10]) - for asset in assets: - last_login = self.session_week.filter(asset=asset["asset"]).order_by('date_start').last() - asset['last'] = last_login - return assets - - def get_week_top10_user(self): - users = list(self.session_week.values('user').annotate( - total=Count('asset')).order_by('-total')[:10]) - for user in users: - last_login = self.session_week.filter(user=user["user"]).order_by('date_start').last() - user['last'] = last_login - return users - - def get_last10_sessions(self): - sessions = self.session_week.order_by('-date_start')[:10] - for session in sessions: - try: - session.avatar_url = User.objects.get(username=session.user).avatar_url() - except User.DoesNotExist: - session.avatar_url = User.objects.first().avatar_url() - return sessions - def get_context_data(self, **kwargs): - week_ago = timezone.now() - timezone.timedelta(weeks=1) - month_ago = timezone.now() - timezone.timedelta(days=30) - self.session_week = Session.objects.filter(date_start__gt=week_ago) - self.session_month = Session.objects.filter(date_start__gt=month_ago) - self.session_month_dates = self.session_month.dates('date_start', 'day') - - self.session_month_dates_archive = [] - time_min = datetime.datetime.min.time() - time_max = datetime.datetime.max.time() - - for d in self.session_month_dates: - ds = datetime.datetime.combine(d, time_min).replace( - tzinfo=timezone.get_current_timezone()) - de = datetime.datetime.combine(d, time_max).replace( - tzinfo=timezone.get_current_timezone()) - self.session_month_dates_archive.append( - self.session_month.filter(date_start__range=(ds, de))) - - context = { + context = super().get_context_data(**kwargs) + context.update({ 'assets_count': self.get_asset_count(), 'users_count': self.get_user_count(), 'online_user_count': self.get_online_user_count(), 'online_asset_count': self.get_online_session_count(), - 'user_visit_count_weekly': self.get_week_login_user_count(), - 'asset_visit_count_weekly': self.get_week_login_asset_count(), - 'user_visit_count_top_five': self.get_top5_user_a_week(), - 'month_str': self.get_month_day_metrics(), - 'month_total_visit_count': self.get_month_login_metrics(), - 'month_user': self.get_month_active_user_metrics(), - 'mouth_asset': self.get_month_active_asset_metrics(), - 'month_user_active': self.get_month_active_user_total(), - 'month_user_inactive': self.get_month_inactive_user_total(), - 'month_user_disabled': self.get_user_disabled_total(), - 'month_asset_active': self.get_month_active_asset_total(), - 'month_asset_inactive': self.get_month_inactive_asset_total(), - 'month_asset_disabled': self.get_asset_disabled_total(), - 'week_asset_hot_ten': self.get_week_top10_asset(), - 'last_login_ten': self.get_last10_sessions(), - 'week_user_hot_ten': self.get_week_top10_user(), 'app': _("Dashboard"), - } - - kwargs.update(context) - return super(IndexView, self).get_context_data(**kwargs) + }) + return context diff --git a/apps/jumpserver/views/swagger.py b/apps/jumpserver/views/swagger.py index 4aed12663..f6f195bed 100644 --- a/apps/jumpserver/views/swagger.py +++ b/apps/jumpserver/views/swagger.py @@ -49,6 +49,16 @@ class CustomSwaggerAutoSchema(SwaggerAutoSchema): return fields +api_info = openapi.Info( + title="JumpServer API Docs", + default_version='v1', + description="JumpServer Restful api docs", + terms_of_service="https://www.jumpserver.org", + contact=openapi.Contact(email="support@fit2cloud.com"), + license=openapi.License(name="GPLv2 License"), +) + + def get_swagger_view(version='v1'): from ..urls import api_v1, api_v2 from django.urls import path, include @@ -65,14 +75,7 @@ def get_swagger_view(version='v1'): else: patterns = api_v1_patterns schema_view = get_schema_view( - openapi.Info( - title="Jumpserver API Docs", - default_version=version, - description="Jumpserver Restful api docs", - terms_of_service="https://www.jumpserver.org", - contact=openapi.Contact(email="support@fit2cloud.com"), - license=openapi.License(name="GPLv2 License"), - ), + api_info, public=True, patterns=patterns, permission_classes=(permissions.AllowAny,), diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 89354bcf1d09cbd9cb194210c3fb13c358df6e2a..f9e23c2815041175cc8508df4de51afe51ad7646 100644 GIT binary patch delta 30916 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 delta 27048 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\n" -"Language-Team: Jumpserver team\n" +"Language-Team: JumpServer team\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -26,9 +26,10 @@ 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:342 assets/models/authbook.py:24 +#: assets/models/asset.py:353 assets/models/authbook.py:23 #: assets/models/gathered_user.py:14 assets/serializers/admin_user.py:32 -#: assets/serializers/asset_user.py:82 assets/serializers/system_user.py:41 +#: assets/serializers/asset_user.py:48 assets/serializers/asset_user.py:85 +#: assets/serializers/system_user.py:45 assets/serializers/system_user.py:169 #: assets/templates/assets/admin_user_list.html:23 #: assets/templates/assets/asset_list.html:170 #: assets/templates/assets/domain_detail.html:55 @@ -42,22 +43,23 @@ msgstr "自定义" #: perms/templates/perms/asset_permission_create_update.html:57 #: perms/templates/perms/asset_permission_list.html:35 #: perms/templates/perms/asset_permission_list.html:87 -#: terminal/backends/command/models.py:13 terminal/models.py:178 -#: terminal/templates/terminal/command_list.html:30 -#: terminal/templates/terminal/command_list.html:66 +#: terminal/backends/command/models.py:19 terminal/models.py:187 +#: terminal/templates/terminal/command_list.html:31 +#: terminal/templates/terminal/command_list.html:106 +#: terminal/templates/terminal/session_detail.html:52 #: terminal/templates/terminal/session_list.html:26 #: terminal/templates/terminal/session_list.html:70 #: users/templates/users/user_asset_permission.html:40 #: users/templates/users/user_asset_permission.html:70 #: users/templates/users/user_granted_remote_app.html:36 -#: xpack/plugins/change_auth_plan/forms.py:73 -#: xpack/plugins/change_auth_plan/models.py:418 +#: xpack/plugins/change_auth_plan/forms.py:74 +#: xpack/plugins/change_auth_plan/models.py:364 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:40 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:54 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:13 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:14 -#: xpack/plugins/cloud/models.py:306 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:60 +#: xpack/plugins/cloud/models.py:266 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:36 #: xpack/plugins/orgs/templates/orgs/org_list.html:17 #: xpack/plugins/vault/forms.py:13 xpack/plugins/vault/forms.py:15 msgid "Asset" @@ -108,8 +110,8 @@ msgstr "运行参数" #: applications/templates/applications/remote_app_list.html:25 #: applications/templates/applications/user_database_app_list.html:16 #: applications/templates/applications/user_remote_app_list.html:16 -#: assets/forms/asset.py:20 assets/forms/domain.py:77 assets/forms/user.py:74 -#: assets/forms/user.py:94 assets/models/asset.py:144 assets/models/base.py:28 +#: 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/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 @@ -121,10 +123,10 @@ msgstr "运行参数" #: assets/templates/assets/domain_gateway_list.html:62 #: assets/templates/assets/domain_list.html:21 #: assets/templates/assets/label_list.html:14 -#: assets/templates/assets/platform_detail.html:43 +#: assets/templates/assets/platform_detail.html:48 #: assets/templates/assets/platform_list.html:16 -#: assets/templates/assets/system_user_detail.html:55 -#: assets/templates/assets/system_user_list.html:24 ops/models/adhoc.py:40 +#: assets/templates/assets/system_user_detail.html:62 +#: assets/templates/assets/system_user_list.html:24 ops/mixin.py:24 #: ops/templates/ops/task_detail.html:58 ops/templates/ops/task_list.html:11 #: orgs/models.py:12 perms/models/base.py:48 #: perms/templates/perms/asset_permission_detail.html:57 @@ -140,11 +142,11 @@ msgstr "运行参数" #: perms/templates/perms/remote_app_permission_user.html:49 #: settings/models.py:26 #: settings/templates/settings/_ldap_list_users_modal.html:32 -#: terminal/models.py:26 terminal/models.py:282 terminal/models.py:314 -#: terminal/models.py:351 terminal/templates/terminal/base_storage_list.html:31 +#: terminal/models.py:26 terminal/models.py:334 terminal/models.py:366 +#: terminal/models.py:403 terminal/templates/terminal/base_storage_list.html:31 #: terminal/templates/terminal/terminal_detail.html:43 #: terminal/templates/terminal/terminal_list.html:30 users/forms/profile.py:20 -#: users/models/group.py:15 users/models/user.py:438 +#: users/models/group.py:15 users/models/user.py:440 #: users/templates/users/_select_user_modal.html:13 #: users/templates/users/user_asset_permission.html:37 #: users/templates/users/user_asset_permission.html:154 @@ -158,16 +160,14 @@ msgstr "运行参数" #: users/templates/users/user_profile.html:51 #: users/templates/users/user_pubkey_update.html:57 #: users/templates/users/user_remote_app_permission.html:36 -#: xpack/plugins/change_auth_plan/forms.py:56 -#: xpack/plugins/change_auth_plan/models.py:63 +#: xpack/plugins/change_auth_plan/forms.py:57 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:59 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:12 -#: xpack/plugins/cloud/models.py:58 xpack/plugins/cloud/models.py:143 +#: xpack/plugins/cloud/models.py:35 #: xpack/plugins/cloud/templates/cloud/account_detail.html:47 #: xpack/plugins/cloud/templates/cloud/account_list.html:12 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:53 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:12 -#: xpack/plugins/gathered_user/models.py:28 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:16 #: xpack/plugins/orgs/templates/orgs/org_detail.html:47 #: xpack/plugins/orgs/templates/orgs/org_list.html:12 @@ -182,7 +182,7 @@ msgstr "名称" #: assets/templates/assets/cmd_filter_rule_list.html:53 #: audits/templates/audits/login_log_list.html:58 #: perms/templates/perms/remote_app_permission_remote_app.html:50 -#: terminal/models.py:316 terminal/models.py:353 +#: terminal/models.py:368 terminal/models.py:405 #: terminal/templates/terminal/base_storage_list.html:32 #: tickets/models/ticket.py:43 tickets/templates/tickets/ticket_detail.html:33 #: tickets/templates/tickets/ticket_list.html:35 @@ -194,7 +194,7 @@ msgstr "类型" #: applications/templates/applications/database_app_detail.html:56 #: applications/templates/applications/database_app_list.html:25 #: applications/templates/applications/user_database_app_list.html:18 -#: ops/models/adhoc.py:185 templates/index.html:91 +#: ops/models/adhoc.py:146 templates/index.html:90 #: users/templates/users/user_granted_database_app.html:36 msgid "Host" msgstr "主机" @@ -202,7 +202,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:24 assets/models/asset.py:190 +#: assets/forms/asset.py:25 assets/models/asset.py:192 #: assets/models/domain.py:50 #: assets/templates/assets/domain_gateway_list.html:64 msgid "Port" @@ -225,8 +225,8 @@ 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:149 assets/models/asset.py:225 -#: assets/models/base.py:33 assets/models/cluster.py:29 +#: assets/models/asset.py:151 assets/models/asset.py:227 +#: 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 #: assets/models/group.py:23 assets/models/label.py:23 @@ -239,33 +239,33 @@ msgstr "数据库" #: assets/templates/assets/domain_detail.html:71 #: assets/templates/assets/domain_gateway_list.html:67 #: assets/templates/assets/domain_list.html:24 -#: assets/templates/assets/platform_detail.html:59 +#: assets/templates/assets/platform_detail.html:64 #: assets/templates/assets/platform_list.html:18 -#: assets/templates/assets/system_user_detail.html:101 -#: assets/templates/assets/system_user_list.html:32 ops/models/adhoc.py:46 +#: assets/templates/assets/system_user_detail.html:112 +#: assets/templates/assets/system_user_list.html:29 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 #: perms/templates/perms/remote_app_permission_detail.html:89 -#: settings/models.py:31 terminal/models.py:36 terminal/models.py:321 -#: terminal/models.py:358 terminal/templates/terminal/base_storage_list.html:33 +#: settings/models.py:31 terminal/models.py:36 terminal/models.py:373 +#: terminal/models.py:410 terminal/templates/terminal/base_storage_list.html:33 #: terminal/templates/terminal/terminal_detail.html:63 #: tickets/templates/tickets/ticket_detail.html:104 users/models/group.py:16 -#: users/models/user.py:471 users/templates/users/user_detail.html:115 +#: users/models/user.py:473 users/templates/users/user_detail.html:115 #: users/templates/users/user_granted_database_app.html:38 #: users/templates/users/user_granted_remote_app.html:37 #: users/templates/users/user_group_detail.html:62 #: users/templates/users/user_group_list.html:16 #: users/templates/users/user_profile.html:138 -#: xpack/plugins/change_auth_plan/models.py:104 +#: xpack/plugins/change_auth_plan/models.py:93 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:115 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19 -#: xpack/plugins/cloud/models.py:76 xpack/plugins/cloud/models.py:172 +#: xpack/plugins/cloud/models.py:53 xpack/plugins/cloud/models.py:136 #: xpack/plugins/cloud/templates/cloud/account_detail.html:67 #: xpack/plugins/cloud/templates/cloud/account_list.html:15 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:102 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:18 -#: xpack/plugins/gathered_user/models.py:42 +#: xpack/plugins/gathered_user/models.py:26 #: xpack/plugins/orgs/templates/orgs/org_detail.html:59 #: xpack/plugins/orgs/templates/orgs/org_list.html:23 msgid "Comment" @@ -280,7 +280,8 @@ msgstr "备注" #: perms/templates/perms/database_app_permission_detail.html:22 #: perms/templates/perms/database_app_permission_list.html:17 #: perms/templates/perms/database_app_permission_user.html:23 -#: templates/_nav.html:66 templates/_nav.html:86 templates/_nav_user.html:22 +#: perms/utils/database_app_permission.py:77 templates/_nav.html:66 +#: templates/_nav.html:86 templates/_nav_user.html:22 #: users/templates/users/user_database_app_permission.html:39 #: users/templates/users/user_database_app_permission.html:64 msgid "DatabaseApp" @@ -306,25 +307,25 @@ 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:223 assets/models/base.py:36 +#: assets/models/asset.py:225 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 #: assets/templates/assets/asset_detail.html:120 #: assets/templates/assets/cmd_filter_detail.html:72 #: assets/templates/assets/domain_detail.html:67 -#: assets/templates/assets/system_user_detail.html:97 -#: common/mixins/models.py:50 ops/templates/ops/adhoc_detail.html:84 +#: assets/templates/assets/system_user_detail.html:108 +#: common/mixins/models.py:49 ops/templates/ops/adhoc_detail.html:84 #: orgs/models.py:16 perms/models/base.py:54 #: perms/templates/perms/asset_permission_detail.html:93 #: perms/templates/perms/database_app_permission_detail.html:89 #: perms/templates/perms/remote_app_permission_detail.html:85 -#: users/models/user.py:479 users/serializers/group.py:32 +#: users/models/user.py:481 users/serializers/group.py:32 #: users/templates/users/user_detail.html:97 -#: xpack/plugins/change_auth_plan/models.py:108 +#: xpack/plugins/change_auth_plan/models.py:97 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:111 -#: xpack/plugins/cloud/models.py:79 xpack/plugins/cloud/models.py:178 -#: xpack/plugins/gathered_user/models.py:46 +#: xpack/plugins/cloud/models.py:56 xpack/plugins/cloud/models.py:142 +#: xpack/plugins/gathered_user/models.py:30 msgid "Created by" msgstr "创建者" @@ -333,14 +334,14 @@ 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:224 assets/models/base.py:34 +#: assets/models/asset.py:226 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 #: assets/templates/assets/cmd_filter_detail.html:64 #: assets/templates/assets/domain_detail.html:63 -#: assets/templates/assets/system_user_detail.html:93 -#: common/mixins/models.py:51 ops/models/adhoc.py:48 +#: assets/templates/assets/system_user_detail.html:104 +#: common/mixins/models.py:50 ops/models/adhoc.py:38 #: ops/templates/ops/adhoc_detail.html:88 ops/templates/ops/task_detail.html:62 #: orgs/models.py:17 perms/models/base.py:55 #: perms/templates/perms/asset_permission_detail.html:89 @@ -350,7 +351,7 @@ msgstr "创建者" #: tickets/templates/tickets/ticket_detail.html:52 users/models/group.py:18 #: users/templates/users/user_group_detail.html:58 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:103 -#: xpack/plugins/cloud/models.py:82 xpack/plugins/cloud/models.py:181 +#: xpack/plugins/cloud/models.py:59 xpack/plugins/cloud/models.py:145 #: xpack/plugins/cloud/templates/cloud/account_detail.html:63 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:98 #: xpack/plugins/orgs/templates/orgs/org_detail.html:55 @@ -364,7 +365,8 @@ msgstr "创建日期" #: perms/templates/perms/remote_app_permission_list.html:17 #: perms/templates/perms/remote_app_permission_remote_app.html:22 #: perms/templates/perms/remote_app_permission_user.html:22 -#: templates/_nav.html:64 templates/_nav.html:82 templates/_nav_user.html:16 +#: perms/utils/remote_app_permission.py:76 templates/_nav.html:64 +#: templates/_nav.html:82 templates/_nav_user.html:16 #: users/templates/users/user_remote_app_permission.html:39 #: users/templates/users/user_remote_app_permission.html:64 msgid "RemoteApp" @@ -372,7 +374,7 @@ msgstr "远程应用" #: applications/templates/applications/database_app_create_update.html:12 #: applications/templates/applications/remote_app_create_update.html:12 -#: assets/templates/assets/_system_user.html:71 +#: assets/templates/assets/_system_user.html:73 #: assets/templates/assets/admin_user_create_update.html:41 #: assets/templates/assets/asset_bulk_update.html:23 #: assets/templates/assets/asset_create.html:81 @@ -414,7 +416,7 @@ msgstr "重置" #: applications/templates/applications/database_app_create_update.html:13 #: applications/templates/applications/remote_app_create_update.html:14 -#: assets/templates/assets/_system_user.html:72 +#: assets/templates/assets/_system_user.html:74 #: assets/templates/assets/admin_user_create_update.html:42 #: assets/templates/assets/asset_bulk_update.html:24 #: assets/templates/assets/asset_create.html:82 @@ -432,15 +434,15 @@ msgstr "重置" #: settings/templates/settings/basic_setting.html:46 #: settings/templates/settings/email_content_setting.html:36 #: settings/templates/settings/email_setting.html:47 -#: settings/templates/settings/ldap_setting.html:48 +#: settings/templates/settings/ldap_setting.html:49 #: settings/templates/settings/security_setting.html:55 #: settings/templates/settings/terminal_setting.html:55 #: terminal/templates/terminal/base_storage_create_update.html:13 -#: terminal/templates/terminal/command_list.html:47 +#: terminal/templates/terminal/command_list.html:48 #: terminal/templates/terminal/session_list.html:50 #: terminal/templates/terminal/terminal_update.html:44 #: users/templates/users/_user.html:52 -#: users/templates/users/forgot_password.html:29 +#: users/templates/users/forgot_password.html:24 #: users/templates/users/user_bulk_update.html:24 #: users/templates/users/user_list.html:40 #: users/templates/users/user_password_update.html:76 @@ -463,6 +465,7 @@ msgstr "提交" #: assets/templates/assets/platform_detail.html:13 #: assets/templates/assets/system_user_assets.html:22 #: assets/templates/assets/system_user_detail.html:13 +#: assets/templates/assets/system_user_users.html:21 #: ops/templates/ops/adhoc_history.html:128 #: ops/templates/ops/task_adhoc.html:114 #: ops/templates/ops/task_history.html:135 @@ -487,7 +490,7 @@ msgstr "详情" #: applications/templates/applications/database_app_list.html:53 #: applications/templates/applications/remote_app_detail.html:16 #: applications/templates/applications/remote_app_list.html:59 -#: assets/templates/assets/_asset_user_list.html:75 +#: assets/templates/assets/_asset_user_list.html:67 #: assets/templates/assets/admin_user_detail.html:19 #: assets/templates/assets/admin_user_list.html:46 #: assets/templates/assets/asset_detail.html:24 @@ -502,8 +505,8 @@ msgstr "详情" #: assets/templates/assets/label_list.html:39 #: assets/templates/assets/platform_detail.html:16 #: assets/templates/assets/platform_list.html:40 -#: assets/templates/assets/system_user_detail.html:23 -#: assets/templates/assets/system_user_list.html:56 audits/models.py:34 +#: assets/templates/assets/system_user_detail.html:30 +#: assets/templates/assets/system_user_list.html:55 audits/models.py:34 #: perms/templates/perms/asset_permission_detail.html:25 #: perms/templates/perms/asset_permission_list.html:144 #: perms/templates/perms/database_app_permission_detail.html:25 @@ -542,6 +545,7 @@ msgstr "更新" #: applications/templates/applications/database_app_list.html:54 #: applications/templates/applications/remote_app_detail.html:20 #: applications/templates/applications/remote_app_list.html:60 +#: assets/templates/assets/_asset_user_list.html:70 #: assets/templates/assets/admin_user_detail.html:23 #: assets/templates/assets/admin_user_list.html:47 #: assets/templates/assets/asset_detail.html:28 @@ -554,9 +558,10 @@ msgstr "更新" #: assets/templates/assets/domain_gateway_list.html:93 #: assets/templates/assets/domain_list.html:51 #: assets/templates/assets/label_list.html:40 +#: assets/templates/assets/platform_detail.html:20 #: assets/templates/assets/platform_list.html:41 -#: assets/templates/assets/system_user_detail.html:27 -#: assets/templates/assets/system_user_list.html:57 audits/models.py:35 +#: assets/templates/assets/system_user_detail.html:34 +#: assets/templates/assets/system_user_list.html:56 audits/models.py:35 #: authentication/templates/authentication/_access_key_modal.html:65 #: ops/templates/ops/task_list.html:74 #: perms/templates/perms/asset_permission_detail.html:29 @@ -607,7 +612,8 @@ msgstr "创建数据库应用" #: assets/templates/assets/domain_list.html:25 #: assets/templates/assets/label_list.html:17 #: assets/templates/assets/platform_list.html:19 -#: assets/templates/assets/system_user_list.html:33 audits/models.py:39 +#: assets/templates/assets/system_user_list.html:30 +#: assets/templates/assets/system_user_users.html:64 audits/models.py:39 #: audits/templates/audits/operate_log_list.html:45 #: audits/templates/audits/operate_log_list.html:71 #: authentication/templates/authentication/_access_key_modal.html:34 @@ -627,7 +633,7 @@ msgstr "创建数据库应用" #: terminal/templates/terminal/session_list.html:34 #: terminal/templates/terminal/terminal_list.html:37 #: tickets/templates/tickets/ticket_list.html:108 -#: users/templates/users/_granted_assets.html:34 +#: users/templates/users/_granted_assets.html:29 #: users/templates/users/user_asset_permission.html:44 #: users/templates/users/user_asset_permission.html:79 #: users/templates/users/user_database_app_permission.html:42 @@ -638,7 +644,7 @@ msgstr "创建数据库应用" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:18 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:20 #: xpack/plugins/cloud/templates/cloud/account_list.html:16 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:67 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:42 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:19 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:20 #: xpack/plugins/orgs/templates/orgs/org_list.html:24 @@ -712,44 +718,36 @@ msgstr "我的远程应用" msgid "Deleted failed, There are related assets" msgstr "删除失败,存在关联资产" -#: assets/api/node.py:61 +#: assets/api/node.py:49 msgid "You can't update the root node name" msgstr "不能修改根节点名称" -#: assets/api/node.py:68 +#: assets/api/node.py:56 msgid "Deletion failed and the node contains children or assets" msgstr "删除失败,节点包含子节点或资产" -#: assets/api/node.py:273 -msgid "Update node asset hardware information: {}" -msgstr "更新节点资产硬件信息: {}" - -#: assets/api/node.py:287 -msgid "Test if the assets under the node are connectable: {}" -msgstr "测试节点下资产是否可连接: {}" - -#: assets/forms/asset.py:65 assets/models/asset.py:194 -#: assets/models/user.py:111 assets/templates/assets/asset_detail.html:186 +#: assets/forms/asset.py:83 assets/models/asset.py:196 +#: 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:87 +#: assets/templates/assets/system_user_assets.html:118 #: perms/models/asset_permission.py:81 -#: xpack/plugins/change_auth_plan/models.py:74 -#: xpack/plugins/gathered_user/models.py:31 +#: xpack/plugins/change_auth_plan/models.py:72 +#: xpack/plugins/gathered_user/models.py:24 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:17 msgid "Nodes" msgstr "节点" -#: assets/forms/asset.py:68 assets/models/asset.py:198 -#: assets/models/cluster.py:19 assets/models/user.py:67 +#: assets/forms/asset.py:86 assets/models/asset.py:200 +#: 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 -#: xpack/plugins/cloud/models.py:160 +#: xpack/plugins/cloud/models.py:133 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:65 #: xpack/plugins/orgs/templates/orgs/org_list.html:19 msgid "Admin user" msgstr "管理用户" -#: assets/forms/asset.py:71 assets/forms/asset.py:113 +#: assets/forms/asset.py:89 assets/forms/asset.py:131 #: assets/templates/assets/asset_create.html:48 #: assets/templates/assets/asset_create.html:50 #: assets/templates/assets/asset_list.html:13 @@ -757,7 +755,7 @@ msgstr "管理用户" msgid "Label" msgstr "标签" -#: assets/forms/asset.py:74 assets/models/asset.py:193 +#: assets/forms/asset.py:92 assets/models/asset.py:195 #: 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 @@ -765,15 +763,15 @@ msgstr "标签" msgid "Domain" msgstr "网域" -#: assets/forms/asset.py:77 assets/models/asset.py:168 -#: assets/models/asset.py:192 assets/serializers/asset.py:66 +#: assets/forms/asset.py:95 assets/models/asset.py:170 +#: assets/models/asset.py:194 assets/serializers/asset.py:67 #: assets/templates/assets/asset_detail.html:100 #: assets/templates/assets/user_asset_list.html:78 msgid "Platform" msgstr "系统平台" -#: assets/forms/asset.py:81 assets/forms/asset.py:116 assets/models/node.py:462 -#: assets/serializers/system_user.py:40 +#: assets/forms/asset.py:99 assets/forms/asset.py:134 assets/models/node.py:497 +#: assets/serializers/system_user.py:44 assets/serializers/system_user.py:168 #: assets/templates/assets/asset_create.html:42 #: perms/forms/asset_permission.py:92 perms/forms/asset_permission.py:99 #: perms/templates/perms/asset_permission_list.html:36 @@ -782,16 +780,15 @@ msgstr "系统平台" #: users/templates/users/user_asset_permission.html:41 #: users/templates/users/user_asset_permission.html:73 #: users/templates/users/user_asset_permission.html:158 -#: xpack/plugins/change_auth_plan/forms.py:74 +#: xpack/plugins/change_auth_plan/forms.py:75 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:55 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:15 -#: xpack/plugins/cloud/models.py:156 +#: xpack/plugins/cloud/models.py:129 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:61 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:61 msgid "Node" msgstr "节点" -#: assets/forms/asset.py:85 +#: assets/forms/asset.py:103 msgid "" "root or other NOPASSWD sudo privilege user existed in asset,If asset is " "windows or other set any one, more see admin user left menu" @@ -799,19 +796,20 @@ msgstr "" "root或其他拥有NOPASSWD: ALL权限的用户, 如果是windows或其它硬件可以随意设置一" "个, 更多信息查看左侧 `管理用户` 菜单" -#: assets/forms/asset.py:88 +#: assets/forms/asset.py:106 msgid "Windows 2016 RDP protocol is different, If is window 2016, set it" msgstr "Windows 2016的RDP协议与之前不同,如果是请设置" -#: assets/forms/asset.py:89 +#: assets/forms/asset.py:107 msgid "" "If your have some network not connect with each other, you can set domain" msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,使用网域网关跳转登录" -#: assets/forms/asset.py:96 assets/forms/asset.py:100 assets/forms/domain.py:17 -#: assets/forms/label.py:15 +#: assets/forms/asset.py:114 assets/forms/asset.py:118 +#: assets/forms/domain.py:17 assets/forms/label.py:15 +#: assets/templates/assets/system_user_assets.html:102 #: perms/templates/perms/asset_permission_asset.html:74 -#: xpack/plugins/change_auth_plan/forms.py:64 +#: xpack/plugins/change_auth_plan/forms.py:65 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:70 msgid "Select assets" msgstr "选择资产" @@ -828,30 +826,31 @@ msgstr "不能包含特殊字符" msgid "SSH gateway support proxy SSH,RDP,VNC" msgstr "SSH网关,支持代理SSH,RDP和VNC" -#: assets/forms/domain.py:78 assets/forms/user.py:75 assets/forms/user.py:95 -#: assets/models/base.py:29 assets/models/gathered_user.py:15 +#: assets/forms/domain.py:78 assets/forms/user.py:75 assets/forms/user.py:97 +#: assets/models/base.py:233 assets/models/gathered_user.py:15 #: assets/templates/assets/_asset_user_auth_update_modal.html:15 #: assets/templates/assets/_asset_user_auth_view_modal.html:21 #: assets/templates/assets/_asset_user_list.html:21 #: assets/templates/assets/admin_user_detail.html:55 #: assets/templates/assets/admin_user_list.html:22 #: assets/templates/assets/domain_gateway_list.html:66 -#: assets/templates/assets/system_user_detail.html:59 +#: assets/templates/assets/system_user_detail.html:66 #: assets/templates/assets/system_user_list.html:25 audits/models.py:81 #: audits/templates/audits/login_log_list.html:57 authentication/forms.py:10 -#: authentication/templates/authentication/login.html:58 +#: authentication/templates/authentication/login.html:21 #: authentication/templates/authentication/xpack_login.html:93 -#: ops/models/adhoc.py:187 perms/templates/perms/asset_permission_list.html:185 +#: ops/models/adhoc.py:148 perms/templates/perms/asset_permission_list.html:185 #: perms/templates/perms/remote_app_permission_user.html:50 #: settings/templates/settings/_ldap_list_users_modal.html:31 -#: users/forms/profile.py:19 users/models/user.py:436 +#: settings/templates/settings/_ldap_test_user_login_modal.html:10 +#: users/forms/profile.py:19 users/models/user.py:438 #: users/templates/users/_select_user_modal.html:14 #: users/templates/users/user_detail.html:53 #: users/templates/users/user_list.html:15 #: users/templates/users/user_profile.html:47 -#: xpack/plugins/change_auth_plan/forms.py:58 -#: xpack/plugins/change_auth_plan/models.py:65 -#: xpack/plugins/change_auth_plan/models.py:414 +#: xpack/plugins/change_auth_plan/forms.py:59 +#: xpack/plugins/change_auth_plan/models.py:63 +#: xpack/plugins/change_auth_plan/models.py:360 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:63 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:53 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:12 @@ -882,7 +881,7 @@ msgstr "" msgid "RDP console" msgstr "" -#: assets/forms/platform.py:40 assets/templates/assets/platform_detail.html:47 +#: assets/forms/platform.py:40 assets/templates/assets/platform_detail.html:52 #: assets/templates/assets/platform_list.html:17 msgid "Base platform" msgstr "基础平台" @@ -891,27 +890,30 @@ msgstr "基础平台" msgid "Password or private key passphrase" msgstr "密码或密钥密码" -#: assets/forms/user.py:26 assets/models/base.py:30 -#: assets/serializers/asset_user.py:63 +#: assets/forms/user.py:26 assets/models/base.py:234 +#: assets/serializers/asset_user.py:72 #: assets/templates/assets/_asset_user_auth_update_modal.html:21 #: assets/templates/assets/_asset_user_auth_view_modal.html:27 #: authentication/forms.py:12 -#: authentication/templates/authentication/login.html:66 +#: authentication/templates/authentication/login.html:29 #: authentication/templates/authentication/xpack_login.html:101 -#: settings/forms/ldap.py:22 users/forms/user.py:22 users/forms/user.py:193 -#: users/templates/users/user_password_check.html:13 +#: settings/forms/ldap.py:22 +#: settings/templates/settings/_ldap_test_user_login_modal.html:16 +#: users/forms/user.py:22 users/forms/user.py:193 +#: users/templates/users/user_otp_check_password.html:13 #: users/templates/users/user_password_update.html:44 +#: users/templates/users/user_password_verify.html:18 #: users/templates/users/user_profile_update.html:41 #: users/templates/users/user_pubkey_update.html:41 #: users/templates/users/user_update.html:20 -#: xpack/plugins/change_auth_plan/models.py:95 -#: xpack/plugins/change_auth_plan/models.py:263 +#: xpack/plugins/change_auth_plan/models.py:84 +#: xpack/plugins/change_auth_plan/models.py:209 msgid "Password" msgstr "密码" -#: assets/forms/user.py:29 assets/serializers/asset_user.py:71 +#: assets/forms/user.py:29 assets/serializers/asset_user.py:80 #: assets/templates/assets/_asset_user_auth_update_modal.html:27 -#: users/models/user.py:465 +#: users/models/user.py:467 msgid "Private key" msgstr "ssh私钥" @@ -923,17 +925,22 @@ msgstr "不合法的密钥,仅支持RSA/DSA格式的密钥" msgid "Password and private key file must be input one" msgstr "密码和私钥, 必须输入一个" -#: assets/forms/user.py:97 assets/models/cmd_filter.py:32 -#: assets/models/user.py:119 assets/templates/assets/_system_user.html:62 -#: assets/templates/assets/system_user_detail.html:164 +#: assets/forms/user.py:99 assets/models/cmd_filter.py:32 +#: assets/models/user.py:119 assets/templates/assets/_system_user.html:63 +#: assets/templates/assets/system_user_detail.html:155 msgid "Command filter" msgstr "命令过滤器" -#: assets/forms/user.py:101 +#: assets/forms/user.py:103 assets/models/user.py:108 +#: assets/templates/assets/system_user_detail.html:68 +msgid "Username same with user" +msgstr "用户名与用户相同" + +#: assets/forms/user.py:106 msgid "Auto push system user to asset" msgstr "自动推送系统用户到资产" -#: assets/forms/user.py:102 +#: assets/forms/user.py:107 msgid "" "1-100, High level will be using login asset as default, if user was granted " "more than 2 system user" @@ -941,35 +948,43 @@ msgstr "" "1-100, 1最低优先级,100最高优先级。授权多个用户时,高优先级的系统用户将会作为" "默认登录用户" -#: assets/forms/user.py:104 +#: assets/forms/user.py:109 msgid "" "If you choose manual login mode, you do not need to fill in the username and " "password." msgstr "如果选择手动登录模式,用户名和密码可以不填写" -#: assets/forms/user.py:106 +#: assets/forms/user.py:111 msgid "Use comma split multi command, ex: /bin/whoami,/bin/ifconfig" msgstr "使用逗号分隔多个命令,如: /bin/whoami,/sbin/ifconfig" -#: assets/models/asset.py:145 +#: assets/forms/user.py:112 +msgid "SFTP root dir, tmp, home or custom" +msgstr "SFTP的起始路径,tmp目录, 用户home目录或者自定义" + +#: assets/forms/user.py:113 +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 msgid "Base" msgstr "基础" -#: assets/models/asset.py:146 assets/templates/assets/platform_detail.html:51 +#: assets/models/asset.py:148 assets/templates/assets/platform_detail.html:56 msgid "Charset" msgstr "编码" -#: assets/models/asset.py:147 assets/templates/assets/platform_detail.html:55 +#: assets/models/asset.py:149 assets/templates/assets/platform_detail.html:60 #: tickets/models/ticket.py:38 msgid "Meta" msgstr "元数据" -#: assets/models/asset.py:148 +#: assets/models/asset.py:150 msgid "Internal" msgstr "内部的" -#: assets/models/asset.py:185 assets/models/domain.py:49 -#: assets/serializers/asset_user.py:28 +#: assets/models/asset.py:187 assets/models/domain.py:49 +#: assets/serializers/asset_user.py:47 #: assets/templates/assets/_asset_list_modal.html:47 #: assets/templates/assets/_asset_user_list.html:20 #: assets/templates/assets/asset_detail.html:60 @@ -978,14 +993,14 @@ msgstr "内部的" #: assets/templates/assets/user_asset_list.html:76 #: audits/templates/audits/login_log_list.html:60 #: perms/templates/perms/asset_permission_list.html:187 -#: settings/forms/terminal.py:16 users/templates/users/_granted_assets.html:31 +#: settings/forms/terminal.py:16 users/templates/users/_granted_assets.html:26 #: users/templates/users/user_asset_permission.html:156 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:50 #: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:24 msgid "IP" msgstr "IP" -#: assets/models/asset.py:186 assets/serializers/asset_user.py:27 +#: assets/models/asset.py:188 assets/serializers/asset_user.py:46 #: assets/serializers/gathered_user.py:20 #: assets/templates/assets/_asset_list_modal.html:46 #: assets/templates/assets/_asset_user_auth_update_modal.html:9 @@ -995,112 +1010,112 @@ msgstr "IP" #: assets/templates/assets/asset_list.html:24 #: assets/templates/assets/user_asset_list.html:75 #: perms/templates/perms/asset_permission_list.html:188 -#: settings/forms/terminal.py:15 users/templates/users/_granted_assets.html:30 +#: settings/forms/terminal.py:15 users/templates/users/_granted_assets.html:25 #: users/templates/users/user_asset_permission.html:157 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:49 #: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:23 msgid "Hostname" msgstr "主机名" -#: assets/models/asset.py:189 assets/models/domain.py:51 +#: assets/models/asset.py:191 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:67 +#: assets/templates/assets/system_user_detail.html:78 #: assets/templates/assets/system_user_list.html:26 #: terminal/forms/storage.py:152 +#: terminal/templates/terminal/session_detail.html:60 #: terminal/templates/terminal/session_list.html:29 #: terminal/templates/terminal/session_list.html:73 msgid "Protocol" msgstr "协议" -#: assets/models/asset.py:191 assets/serializers/asset.py:68 +#: assets/models/asset.py:193 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:59 +#: perms/serializers/user_permission.py:60 msgid "Protocols" msgstr "协议组" -#: assets/models/asset.py:195 assets/models/authbook.py:27 -#: 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 +#: assets/models/asset.py:197 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:201 assets/templates/assets/asset_detail.html:64 +#: assets/models/asset.py:203 assets/templates/assets/asset_detail.html:64 msgid "Public IP" msgstr "公网IP" -#: assets/models/asset.py:202 assets/templates/assets/asset_detail.html:116 +#: assets/models/asset.py:204 assets/templates/assets/asset_detail.html:116 msgid "Asset number" msgstr "资产编号" -#: assets/models/asset.py:205 assets/templates/assets/asset_detail.html:80 +#: assets/models/asset.py:207 assets/templates/assets/asset_detail.html:80 msgid "Vendor" msgstr "制造商" -#: assets/models/asset.py:206 assets/templates/assets/asset_detail.html:84 +#: assets/models/asset.py:208 assets/templates/assets/asset_detail.html:84 msgid "Model" msgstr "型号" -#: assets/models/asset.py:207 assets/templates/assets/asset_detail.html:112 +#: assets/models/asset.py:209 assets/templates/assets/asset_detail.html:112 msgid "Serial number" msgstr "序列号" -#: assets/models/asset.py:209 +#: assets/models/asset.py:211 msgid "CPU model" msgstr "CPU型号" -#: assets/models/asset.py:210 +#: assets/models/asset.py:212 msgid "CPU count" msgstr "CPU数量" -#: assets/models/asset.py:211 +#: assets/models/asset.py:213 msgid "CPU cores" msgstr "CPU核数" -#: assets/models/asset.py:212 +#: assets/models/asset.py:214 msgid "CPU vcpus" msgstr "CPU总数" -#: assets/models/asset.py:213 assets/templates/assets/asset_detail.html:92 +#: assets/models/asset.py:215 assets/templates/assets/asset_detail.html:92 msgid "Memory" msgstr "内存" -#: assets/models/asset.py:214 +#: assets/models/asset.py:216 msgid "Disk total" msgstr "硬盘大小" -#: assets/models/asset.py:215 +#: assets/models/asset.py:217 msgid "Disk info" msgstr "硬盘信息" -#: assets/models/asset.py:217 assets/templates/assets/asset_detail.html:104 +#: assets/models/asset.py:219 assets/templates/assets/asset_detail.html:104 msgid "OS" msgstr "操作系统" -#: assets/models/asset.py:218 +#: assets/models/asset.py:220 msgid "OS version" msgstr "系统版本" -#: assets/models/asset.py:219 +#: assets/models/asset.py:221 msgid "OS arch" msgstr "系统架构" -#: assets/models/asset.py:220 +#: assets/models/asset.py:222 msgid "Hostname raw" msgstr "主机名原始" -#: assets/models/asset.py:222 assets/templates/assets/asset_create.html:46 +#: assets/models/asset.py:224 assets/templates/assets/asset_create.html:46 #: assets/templates/assets/asset_detail.html:220 templates/_nav.html:46 msgid "Labels" msgstr "标签管理" -#: assets/models/authbook.py:25 ops/templates/ops/task_detail.html:70 +#: assets/models/authbook.py:24 ops/templates/ops/task_detail.html:70 msgid "Latest version" msgstr "最新版本" -#: assets/models/authbook.py:26 +#: assets/models/authbook.py:25 #: assets/templates/assets/_asset_user_list.html:22 #: ops/templates/ops/adhoc_history.html:56 #: ops/templates/ops/adhoc_history_detail.html:55 @@ -1108,23 +1123,23 @@ msgstr "最新版本" msgid "Version" msgstr "版本" -#: assets/models/authbook.py:36 +#: assets/models/authbook.py:34 msgid "AuthBook" msgstr "" -#: assets/models/base.py:31 xpack/plugins/change_auth_plan/models.py:99 -#: xpack/plugins/change_auth_plan/models.py:270 +#: assets/models/base.py:235 xpack/plugins/change_auth_plan/models.py:88 +#: xpack/plugins/change_auth_plan/models.py:216 msgid "SSH private key" msgstr "ssh密钥" -#: assets/models/base.py:32 xpack/plugins/change_auth_plan/models.py:102 -#: xpack/plugins/change_auth_plan/models.py:266 +#: assets/models/base.py:236 xpack/plugins/change_auth_plan/models.py:91 +#: xpack/plugins/change_auth_plan/models.py:212 msgid "SSH public key" msgstr "ssh公钥" -#: assets/models/base.py:35 assets/models/gathered_user.py:20 -#: assets/templates/assets/cmd_filter_detail.html:68 common/mixins/models.py:52 -#: ops/models/adhoc.py:49 +#: assets/models/base.py:239 assets/models/gathered_user.py:20 +#: assets/templates/assets/cmd_filter_detail.html:68 common/mixins/models.py:51 +#: ops/models/adhoc.py:39 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:107 #: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:29 msgid "Date updated" @@ -1138,7 +1153,7 @@ msgstr "带宽" msgid "Contact" msgstr "联系人" -#: assets/models/cluster.py:22 users/models/user.py:457 +#: assets/models/cluster.py:22 users/models/user.py:459 #: users/templates/users/user_detail.html:62 msgid "Phone" msgstr "手机" @@ -1164,7 +1179,7 @@ msgid "Default" msgstr "默认" #: assets/models/cluster.py:36 assets/models/label.py:14 -#: users/models/user.py:580 +#: users/models/user.py:595 msgid "System" msgstr "系统" @@ -1192,11 +1207,11 @@ msgstr "BGP全网通" msgid "Regex" msgstr "正则表达式" -#: assets/models/cmd_filter.py:40 ops/models/command.py:22 -#: ops/templates/ops/command_execution_list.html:67 terminal/models.py:186 +#: assets/models/cmd_filter.py:40 ops/models/command.py:23 +#: ops/templates/ops/command_execution_list.html:67 terminal/models.py:196 #: terminal/templates/terminal/command_list.html:28 -#: terminal/templates/terminal/command_list.html:68 -#: terminal/templates/terminal/session_detail.html:48 +#: terminal/templates/terminal/command_list.html:108 +#: terminal/templates/terminal/session_commands.html:49 #: terminal/templates/terminal/session_list.html:31 msgid "Command" msgstr "命令" @@ -1270,8 +1285,9 @@ msgstr "资产组" msgid "Default asset group" msgstr "默认资产组" -#: assets/models/label.py:15 audits/models.py:18 audits/models.py:38 -#: audits/models.py:51 audits/templates/audits/ftp_log_list.html:37 +#: assets/models/label.py:15 assets/templates/assets/system_user_users.html:63 +#: audits/models.py:18 audits/models.py:38 audits/models.py:51 +#: audits/templates/audits/ftp_log_list.html:37 #: audits/templates/audits/ftp_log_list.html:74 #: audits/templates/audits/operate_log_list.html:37 #: audits/templates/audits/password_change_log_list.html:37 @@ -1287,15 +1303,16 @@ msgstr "默认资产组" #: perms/templates/perms/database_app_permission_list.html:15 #: perms/templates/perms/remote_app_permission_create_update.html:41 #: perms/templates/perms/remote_app_permission_list.html:15 -#: templates/index.html:87 terminal/backends/command/models.py:12 -#: terminal/models.py:176 terminal/templates/terminal/command_list.html:29 -#: terminal/templates/terminal/command_list.html:65 +#: templates/index.html:86 terminal/backends/command/models.py:18 +#: terminal/models.py:185 terminal/templates/terminal/command_list.html:30 +#: terminal/templates/terminal/command_list.html:105 +#: terminal/templates/terminal/session_detail.html:48 #: terminal/templates/terminal/session_list.html:25 #: terminal/templates/terminal/session_list.html:69 tickets/models/ticket.py:33 #: tickets/models/ticket.py:128 tickets/templates/tickets/ticket_detail.html:32 #: tickets/templates/tickets/ticket_list.html:34 #: tickets/templates/tickets/ticket_list.html:103 users/forms/group.py:15 -#: users/models/user.py:143 users/models/user.py:159 users/models/user.py:568 +#: users/models/user.py:143 users/models/user.py:159 users/models/user.py:583 #: users/serializers/group.py:20 #: users/templates/users/user_asset_permission.html:38 #: users/templates/users/user_asset_permission.html:64 @@ -1305,13 +1322,13 @@ msgstr "默认资产组" #: users/templates/users/user_group_list.html:15 #: users/templates/users/user_remote_app_permission.html:37 #: users/templates/users/user_remote_app_permission.html:58 -#: users/views/profile.py:70 xpack/plugins/orgs/forms.py:27 +#: users/views/profile/base.py:46 xpack/plugins/orgs/forms.py:27 #: xpack/plugins/orgs/templates/orgs/org_detail.html:108 #: xpack/plugins/orgs/templates/orgs/org_list.html:15 msgid "User" msgstr "用户" -#: assets/models/label.py:19 assets/models/node.py:453 +#: assets/models/label.py:19 assets/models/node.py:488 #: assets/templates/assets/label_list.html:15 settings/models.py:27 msgid "Value" msgstr "值" @@ -1320,38 +1337,37 @@ msgstr "值" msgid "Category" msgstr "分类" -#: assets/models/node.py:164 +#: assets/models/node.py:209 msgid "New node" msgstr "新节点" -#: assets/models/node.py:325 +#: assets/models/node.py:370 msgid "ungrouped" msgstr "未分组" -#: assets/models/node.py:327 +#: assets/models/node.py:372 users/templates/users/_granted_assets.html:130 msgid "empty" msgstr "空" -#: assets/models/node.py:329 +#: assets/models/node.py:374 msgid "favorite" msgstr "收藏夹" -#: assets/models/node.py:452 assets/templates/assets/_node_detail_modal.html:39 +#: assets/models/node.py:487 assets/templates/assets/_node_detail_modal.html:39 msgid "Key" msgstr "键" -#: assets/models/user.py:107 +#: assets/models/user.py:105 msgid "Automatic login" msgstr "自动登录" -#: assets/models/user.py:108 +#: assets/models/user.py:106 msgid "Manually login" msgstr "手动登录" -#: assets/models/user.py:112 +#: assets/models/user.py:110 #: assets/templates/assets/_asset_group_bulk_update_modal.html:11 -#: assets/templates/assets/system_user_assets.html:26 -#: assets/templates/assets/system_user_detail.html:18 +#: assets/templates/assets/system_user_assets.html:94 #: assets/views/admin_user.py:30 assets/views/admin_user.py:49 #: assets/views/admin_user.py:67 assets/views/admin_user.py:84 #: assets/views/admin_user.py:108 assets/views/asset.py:37 @@ -1366,33 +1382,54 @@ msgstr "手动登录" #: assets/views/domain.py:136 assets/views/domain.py:157 #: assets/views/label.py:27 assets/views/label.py:45 assets/views/label.py:73 #: assets/views/platform.py:22 assets/views/platform.py:38 -#: assets/views/platform.py:55 assets/views/platform.py:71 -#: assets/views/system_user.py:29 assets/views/system_user.py:46 -#: assets/views/system_user.py:63 assets/views/system_user.py:79 -#: templates/_nav.html:39 xpack/plugins/change_auth_plan/models.py:70 +#: assets/views/platform.py:58 assets/views/platform.py:74 +#: assets/views/system_user.py:30 assets/views/system_user.py:47 +#: assets/views/system_user.py:64 assets/views/system_user.py:80 +#: templates/_nav.html:39 xpack/plugins/change_auth_plan/models.py:68 msgid "Assets" msgstr "资产管理" -#: assets/models/user.py:115 assets/templates/assets/_system_user.html:55 -#: assets/templates/assets/system_user_detail.html:119 +#: assets/models/user.py:111 assets/templates/assets/system_user_users.html:76 +#: templates/_nav.html:17 users/views/group.py:28 users/views/group.py:45 +#: users/views/group.py:63 users/views/group.py:82 users/views/group.py:99 +#: users/views/login.py:158 users/views/profile/password.py:40 +#: users/views/profile/pubkey.py:36 users/views/user.py:50 +#: users/views/user.py:67 users/views/user.py:111 users/views/user.py:178 +#: users/views/user.py:206 users/views/user.py:220 users/views/user.py:234 +#: users/views/user.py:248 users/views/user.py:262 users/views/user.py:276 +msgid "Users" +msgstr "用户管理" + +#: assets/models/user.py:112 users/templates/users/user_group_list.html:90 +#: users/templates/users/user_list.html:135 +#: users/templates/users/user_profile.html:124 +msgid "User groups" +msgstr "用户组" + +#: assets/models/user.py:115 assets/templates/assets/_system_user.html:56 +#: assets/templates/assets/system_user_detail.html:130 #: assets/templates/assets/system_user_update.html:10 msgid "Auto push" msgstr "自动推送" -#: assets/models/user.py:116 assets/templates/assets/system_user_detail.html:71 +#: assets/models/user.py:116 assets/templates/assets/system_user_detail.html:82 msgid "Sudo" msgstr "Sudo" -#: assets/models/user.py:117 assets/templates/assets/system_user_detail.html:76 +#: assets/models/user.py:117 assets/templates/assets/system_user_detail.html:87 msgid "Shell" msgstr "Shell" -#: assets/models/user.py:118 assets/templates/assets/system_user_detail.html:63 +#: assets/models/user.py:118 assets/templates/assets/system_user_detail.html:74 #: assets/templates/assets/system_user_list.html:27 msgid "Login mode" msgstr "登录模式" -#: assets/models/user.py:179 assets/templates/assets/system_user_list.html:74 +#: assets/models/user.py:120 +msgid "SFTP Root" +msgstr "SFTP根路径" + +#: assets/models/user.py:190 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/templates/audits/ftp_log_list.html:76 @@ -1408,12 +1445,13 @@ msgstr "登录模式" #: perms/templates/perms/database_app_permission_list.html:18 #: perms/templates/perms/remote_app_permission_detail.html:126 #: perms/templates/perms/remote_app_permission_list.html:18 -#: templates/_nav.html:45 terminal/backends/command/models.py:14 -#: terminal/models.py:180 terminal/templates/terminal/command_list.html:31 -#: terminal/templates/terminal/command_list.html:67 +#: templates/_nav.html:45 terminal/backends/command/models.py:20 +#: terminal/models.py:189 terminal/templates/terminal/command_list.html:32 +#: terminal/templates/terminal/command_list.html:107 +#: terminal/templates/terminal/session_detail.html:56 #: terminal/templates/terminal/session_list.html:27 #: terminal/templates/terminal/session_list.html:71 -#: users/templates/users/_granted_assets.html:32 +#: users/templates/users/_granted_assets.html:27 #: users/templates/users/user_asset_permission.html:42 #: users/templates/users/user_asset_permission.html:76 #: users/templates/users/user_asset_permission.html:159 @@ -1430,47 +1468,58 @@ msgstr "系统用户" msgid "%(value)s is not an even number" msgstr "%(value)s is not an even number" -#: assets/models/utils.py:43 assets/tasks/const.py:84 +#: assets/models/utils.py:43 assets/tasks/const.py:49 msgid "Unreachable" msgstr "不可达" -#: assets/models/utils.py:44 assets/tasks/const.py:85 +#: assets/models/utils.py:44 assets/tasks/const.py:50 #: assets/templates/assets/asset_list.html:27 msgid "Reachable" msgstr "可连接" -#: assets/models/utils.py:45 assets/tasks/const.py:86 audits/utils.py:30 +#: assets/models/utils.py:45 assets/tasks/const.py:51 audits/utils.py:30 msgid "Unknown" msgstr "未知" -#: assets/serializers/asset.py:23 +#: assets/serializers/asset.py:24 msgid "Protocol format should {}/{}" msgstr "协议格式 {}/{}" -#: assets/serializers/asset.py:40 +#: assets/serializers/asset.py:41 msgid "Protocol duplicate: {}" msgstr "协议重复: {}" -#: assets/serializers/asset.py:69 assets/serializers/asset.py:149 -#: assets/serializers/asset_user.py:29 -#: assets/templates/assets/_asset_user_list.html:23 -msgid "Connectivity" -msgstr "连接" - -#: assets/serializers/asset.py:95 +#: assets/serializers/asset.py:94 msgid "Hardware info" msgstr "硬件信息" -#: assets/serializers/asset.py:96 orgs/mixins/serializers.py:27 +#: assets/serializers/asset.py:95 orgs/mixins/serializers.py:27 msgid "Org name" msgstr "组织名称" -#: assets/serializers/asset_user.py:31 +#: assets/serializers/asset.py:134 assets/serializers/asset.py:171 +msgid "Connectivity" +msgstr "连接" + +#: assets/serializers/asset_user.py:45 +#: assets/templates/assets/_node_detail_modal.html:18 +#: audits/templates/audits/login_log_list.html:56 +#: authentication/templates/authentication/_access_key_modal.html:30 +#: ops/templates/ops/adhoc_detail.html:47 +#: ops/templates/ops/adhoc_history_detail.html:47 +#: ops/templates/ops/task_detail.html:54 +#: terminal/templates/terminal/session_list.html:24 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:35 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:33 +msgid "ID" +msgstr "ID" + +#: assets/serializers/asset_user.py:49 msgid "Backend" msgstr "后端" -#: assets/serializers/asset_user.py:67 users/forms/profile.py:148 -#: users/models/user.py:468 users/templates/users/first_login.html:42 +#: assets/serializers/asset_user.py:76 users/forms/profile.py:148 +#: users/models/user.py:470 users/templates/users/first_login.html:42 #: users/templates/users/user_password_update.html:49 #: users/templates/users/user_profile.html:69 #: users/templates/users/user_profile_update.html:46 @@ -1478,12 +1527,12 @@ msgstr "后端" msgid "Public key" msgstr "ssh公钥" -#: assets/serializers/base.py:44 +#: assets/serializers/base.py:45 msgid "" "Not support openssh format key, using ssh-keygen -t rsa -m pem to generate" msgstr "暂不支持OPENSSH格式的密钥,使用 ssh-keygen -t rsa -m pem生成" -#: assets/serializers/base.py:50 +#: assets/serializers/base.py:51 msgid "private key invalid" msgstr "密钥不合法" @@ -1495,106 +1544,135 @@ msgstr "值" msgid "The same level node name cannot be the same" msgstr "同级别节点名字不能重复" -#: assets/serializers/system_user.py:42 +#: assets/serializers/system_user.py:46 assets/serializers/system_user.py:170 msgid "Login mode display" msgstr "登录模式显示" -#: assets/serializers/system_user.py:77 +#: assets/serializers/system_user.py:86 +msgid "Username same with user with protocol {} only allow 1" +msgstr "用户名和用户相同的一种协议只允许存在一个" + +#: assets/serializers/system_user.py:99 msgid "* Automatic login mode must fill in the username." msgstr "自动登录模式,必须填写用户名" -#: assets/serializers/system_user.py:88 +#: assets/serializers/system_user.py:107 +msgid "Path should starts with /" +msgstr "路径应该以 / 开头" + +#: assets/serializers/system_user.py:118 msgid "Password or private key required" msgstr "密码或密钥密码需要一个" -#: assets/tasks/admin_user_connectivity.py:56 +#: assets/tasks/admin_user_connectivity.py:58 msgid "Test admin user connectivity period: {}" msgstr "定期测试管理账号可连接性: {}" -#: assets/tasks/admin_user_connectivity.py:63 +#: assets/tasks/admin_user_connectivity.py:67 msgid "Test admin user connectivity: {}" msgstr "测试管理行号可连接性: {}" -#: assets/tasks/asset_connectivity.py:21 +#: assets/tasks/asset_connectivity.py:27 msgid "Test assets connectivity" msgstr "测试资产可连接性" -#: assets/tasks/asset_connectivity.py:75 +#: assets/tasks/asset_connectivity.py:76 msgid "Test assets connectivity: {}" msgstr "测试资产可连接性: {}" -#: assets/tasks/asset_user_connectivity.py:27 -#: assets/tasks/push_system_user.py:130 -#: xpack/plugins/change_auth_plan/models.py:527 +#: assets/tasks/asset_connectivity.py:87 +msgid "Test if the assets under the node are connectable: {}" +msgstr "测试节点下资产是否可连接: {}" + +#: assets/tasks/asset_user_connectivity.py:29 +#: xpack/plugins/change_auth_plan/models.py:473 msgid "The asset {} system platform {} does not support run Ansible tasks" msgstr "资产 {} 系统平台 {} 不支持运行 Ansible 任务" -#: assets/tasks/asset_user_connectivity.py:74 +#: assets/tasks/asset_user_connectivity.py:75 msgid "Test asset user connectivity: {}" msgstr "测试资产用户可连接性: {}" -#: assets/tasks/gather_asset_hardware_info.py:44 +#: assets/tasks/gather_asset_hardware_info.py:45 msgid "Get asset info failed: {}" msgstr "获取资产信息失败:{}" -#: assets/tasks/gather_asset_hardware_info.py:94 +#: assets/tasks/gather_asset_hardware_info.py:96 msgid "Update some assets hardware info" msgstr "更新资产硬件信息" -#: assets/tasks/gather_asset_hardware_info.py:111 +#: assets/tasks/gather_asset_hardware_info.py:113 msgid "Update asset hardware info: {}" msgstr "更新资产硬件信息: {}" -#: assets/tasks/gather_asset_users.py:107 +#: assets/tasks/gather_asset_hardware_info.py:130 +msgid "Update node asset hardware information: {}" +msgstr "更新节点资产硬件信息: {}" + +#: assets/tasks/gather_asset_users.py:108 msgid "Gather assets users" msgstr "收集资产上的用户" -#: assets/tasks/push_system_user.py:142 +#: assets/tasks/push_system_user.py:149 +#: assets/tasks/system_user_connectivity.py:86 +msgid "System user is dynamic: {}" +msgstr "系统用户是动态的: {}" + +#: assets/tasks/push_system_user.py:180 +msgid "Start push system user for platform: [{}]" +msgstr "推送系统用户到平台: [{}]" + +#: assets/tasks/push_system_user.py:181 +#: assets/tasks/system_user_connectivity.py:78 +msgid "Hosts count: {}" +msgstr "主机数量: {}" + +#: assets/tasks/push_system_user.py:198 assets/tasks/push_system_user.py:214 +msgid "Push system users to assets: {}" +msgstr "推送系统用户到入资产: {}" + +#: assets/tasks/push_system_user.py:206 +msgid "Push system users to asset: {}({}) => {}" +msgstr "推送系统用户到入资产: {}({}) => {}" + +#: assets/tasks/system_user_connectivity.py:77 +msgid "Start test system user connectivity for platform: [{}]" +msgstr "开始测试系统用户在该系统平台的可连接性: [{}]" + +#: assets/tasks/system_user_connectivity.py:97 +msgid "Test system user connectivity: {}" +msgstr "测试系统用户可连接性: {}" + +#: assets/tasks/system_user_connectivity.py:105 +msgid "Test system user connectivity: {} => {}" +msgstr "测试系统用户可连接性: {} => {}" + +#: assets/tasks/system_user_connectivity.py:118 +msgid "Test system user connectivity period: {}" +msgstr "定期测试系统用户可连接性: {}" + +#: assets/tasks/utils.py:17 +msgid "Asset has been disabled, skipped: {}" +msgstr "资产或许不支持ansible, 跳过: {}" + +#: assets/tasks/utils.py:21 +msgid "Asset may not be support ansible, skipped: {}" +msgstr "资产或许不支持ansible, 跳过: {}" + +#: assets/tasks/utils.py:29 msgid "" "Push system user task skip, auto push not enable or protocol is not ssh or " "rdp: {}" msgstr "推送系统用户任务跳过,自动推送没有打开,或协议不是ssh或rdp: {}" -#: assets/tasks/push_system_user.py:149 +#: assets/tasks/utils.py:36 msgid "For security, do not push user {}" msgstr "为了安全,禁止推送用户 {}" -#: assets/tasks/push_system_user.py:177 assets/tasks/push_system_user.py:191 -msgid "Push system users to assets: {}" -msgstr "推送系统用户到入资产: {}" - -#: assets/tasks/push_system_user.py:183 -msgid "Push system users to asset: {} => {}" -msgstr "推送系统用户到入资产: {} => {}" - -#: assets/tasks/system_user_connectivity.py:79 -msgid "Test system user connectivity: {}" -msgstr "测试系统用户可连接性: {}" - -#: assets/tasks/system_user_connectivity.py:86 -msgid "Test system user connectivity: {} => {}" -msgstr "测试系统用户可连接性: {} => {}" - -#: assets/tasks/system_user_connectivity.py:99 -msgid "Test system user connectivity period: {}" -msgstr "定期测试系统用户可连接性: {}" - -#: assets/tasks/utils.py:16 -msgid "Asset has been disabled, skipped: {}" -msgstr "资产或许不支持ansible, 跳过: {}" - -#: assets/tasks/utils.py:20 -msgid "Asset may not be support ansible, skipped: {}" -msgstr "资产或许不支持ansible, 跳过: {}" - -#: assets/tasks/utils.py:33 +#: assets/tasks/utils.py:56 msgid "No assets matched, stop task" msgstr "没有匹配到资产,结束任务" -#: assets/tasks/utils.py:43 -msgid "No assets matched related system user protocol, stop task" -msgstr "没有匹配到与系统用户协议相关的资产,结束任务" - #: assets/templates/assets/_asset_group_bulk_update_modal.html:5 msgid "Update asset group" msgstr "更新用户组" @@ -1620,9 +1698,12 @@ msgstr "选择系统用户" #: assets/templates/assets/_asset_group_bulk_update_modal.html:34 msgid "Enable-MFA" -msgstr "启用MFA" +msgstr "启用多因子认证" -#: assets/templates/assets/_asset_list_modal.html:7 assets/views/asset.py:38 +#: assets/templates/assets/_asset_list_modal.html:7 +#: assets/templates/assets/system_user_assets.html:26 +#: assets/templates/assets/system_user_detail.html:18 +#: assets/templates/assets/system_user_users.html:25 assets/views/asset.py:38 #: templates/_nav.html:42 xpack/plugins/change_auth_plan/views.py:118 msgid "Asset list" msgstr "资产列表" @@ -1642,7 +1723,8 @@ msgid "Update asset user auth" msgstr "更新资产用户认证信息" #: assets/templates/assets/_asset_user_auth_update_modal.html:23 -#: xpack/plugins/change_auth_plan/forms.py:60 +#: settings/templates/settings/_ldap_test_user_login_modal.html:18 +#: xpack/plugins/change_auth_plan/forms.py:61 msgid "Please input password" msgstr "请输入密码" @@ -1664,11 +1746,11 @@ msgstr "资产用户信息" msgid "Copy success" msgstr "复制成功" -#: assets/templates/assets/_asset_user_auth_view_modal.html:70 +#: assets/templates/assets/_asset_user_auth_view_modal.html:68 msgid "Get auth info error" msgstr "获取认证信息错误" -#: assets/templates/assets/_asset_user_auth_view_modal.html:97 +#: 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 @@ -1683,8 +1765,8 @@ msgstr "关闭" #: audits/templates/audits/operate_log_list.html:75 #: audits/templates/audits/password_change_log_list.html:57 #: ops/templates/ops/task_adhoc.html:61 -#: terminal/templates/terminal/command_list.html:33 -#: terminal/templates/terminal/session_detail.html:50 +#: terminal/templates/terminal/command_list.html:34 +#: terminal/templates/terminal/session_commands.html:51 #: tickets/templates/tickets/ticket_list.html:37 msgid "Datetime" msgstr "日期" @@ -1694,26 +1776,32 @@ msgstr "日期" msgid "Test datetime: " msgstr "测试日期: " -#: assets/templates/assets/_asset_user_list.html:74 +#: assets/templates/assets/_asset_user_list.html:44 +msgid "Only latest version" +msgstr "仅最新版本" + +#: assets/templates/assets/_asset_user_list.html:66 msgid "View" msgstr "查看" -#: assets/templates/assets/_asset_user_list.html:76 +#: assets/templates/assets/_asset_user_list.html:68 #: assets/templates/assets/admin_user_assets.html:56 #: assets/templates/assets/asset_asset_user_list.html:57 #: assets/templates/assets/asset_detail.html:174 -#: assets/templates/assets/system_user_assets.html:67 -#: assets/templates/assets/system_user_detail.html:149 +#: assets/templates/assets/system_user_assets.html:74 #: terminal/templates/terminal/base_storage_list.html:72 msgid "Test" msgstr "测试" -#: assets/templates/assets/_asset_user_list.html:77 -#: assets/templates/assets/system_user_assets.html:76 -#: assets/templates/assets/system_user_detail.html:139 +#: assets/templates/assets/_asset_user_list.html:69 +#: assets/templates/assets/system_user_assets.html:83 msgid "Push" msgstr "推送" +#: assets/templates/assets/_asset_user_list.html:167 +msgid "Delete success" +msgstr "删除成功" + #: assets/templates/assets/_gateway_test_modal.html:4 msgid "Test gateway test connection" msgstr "测试连接网关" @@ -1731,18 +1819,6 @@ msgstr "如果使用了nat端口映射,请设置为ssh真实监听的端口" msgid "Node detail" msgstr "节点详情" -#: assets/templates/assets/_node_detail_modal.html:18 -#: audits/templates/audits/login_log_list.html:56 -#: authentication/templates/authentication/_access_key_modal.html:30 -#: ops/templates/ops/adhoc_detail.html:47 -#: ops/templates/ops/adhoc_history_detail.html:47 -#: ops/templates/ops/task_detail.html:54 -#: terminal/templates/terminal/session_list.html:24 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:59 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:57 -msgid "ID" -msgstr "ID" - #: assets/templates/assets/_node_detail_modal.html:33 msgid "Full name" msgstr "全称" @@ -1759,19 +1835,11 @@ msgstr "重命名节点" msgid "Delete node" msgstr "删除节点" -#: assets/templates/assets/_node_tree.html:165 +#: assets/templates/assets/_node_tree.html:166 msgid "Create node failed" msgstr "创建节点失败" -#: assets/templates/assets/_node_tree.html:177 -msgid "Have child node, cancel" -msgstr "存在子节点,不能删除" - -#: assets/templates/assets/_node_tree.html:179 -msgid "Have assets, cancel" -msgstr "存在资产,不能删除" - -#: assets/templates/assets/_node_tree.html:255 +#: assets/templates/assets/_node_tree.html:250 msgid "Rename success" msgstr "重命名成功" @@ -1787,18 +1855,18 @@ msgstr "重命名成功" msgid "Basic" msgstr "基本" -#: assets/templates/assets/_system_user.html:40 +#: assets/templates/assets/_system_user.html:41 #: assets/templates/assets/asset_create.html:38 #: assets/templates/assets/gateway_create_update.html:41 #: users/templates/users/_user.html:21 msgid "Auth" msgstr "认证" -#: assets/templates/assets/_system_user.html:44 +#: assets/templates/assets/_system_user.html:45 msgid "Auto generate key" msgstr "自动生成密钥" -#: assets/templates/assets/_system_user.html:65 +#: assets/templates/assets/_system_user.html:66 #: assets/templates/assets/asset_create.html:74 #: assets/templates/assets/gateway_create_update.html:49 #: perms/templates/perms/asset_permission_create_update.html:97 @@ -1829,8 +1897,8 @@ msgid "Asset list of " msgstr "资产列表" #: assets/templates/assets/admin_user_assets.html:47 -#: assets/templates/assets/system_user_assets.html:58 -#: assets/templates/assets/system_user_detail.html:113 +#: assets/templates/assets/system_user_assets.html:65 +#: assets/templates/assets/system_user_detail.html:124 #: perms/templates/perms/asset_permission_detail.html:109 #: perms/templates/perms/database_app_permission_detail.html:105 #: perms/templates/perms/remote_app_permission_detail.html:101 @@ -1848,10 +1916,11 @@ msgid "Replace node assets admin user with this" msgstr "替换资产的管理员" #: assets/templates/assets/admin_user_detail.html:86 +#: assets/templates/assets/system_user_assets.html:126 #: perms/templates/perms/asset_permission_asset.html:99 -#: xpack/plugins/change_auth_plan/forms.py:68 +#: xpack/plugins/change_auth_plan/forms.py:69 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:95 -#: xpack/plugins/gathered_user/forms.py:36 +#: xpack/plugins/gathered_user/forms.py:33 msgid "Select nodes" msgstr "选择节点" @@ -1859,10 +1928,12 @@ msgstr "选择节点" #: assets/templates/assets/asset_detail.html:200 #: assets/templates/assets/asset_list.html:258 #: assets/templates/assets/cmd_filter_detail.html:101 -#: assets/templates/assets/system_user_assets.html:101 -#: assets/templates/assets/system_user_detail.html:181 +#: assets/templates/assets/system_user_assets.html:108 +#: assets/templates/assets/system_user_assets.html:132 +#: assets/templates/assets/system_user_detail.html:172 +#: assets/templates/assets/system_user_users.html:90 #: authentication/templates/authentication/_mfa_confirm_modal.html:20 -#: templates/_modal.html:23 terminal/templates/terminal/session_detail.html:112 +#: templates/_modal.html:23 terminal/templates/terminal/session_detail.html:122 #: users/templates/users/user_detail.html:264 #: users/templates/users/user_detail.html:417 #: users/templates/users/user_detail.html:443 @@ -1870,6 +1941,7 @@ msgstr "选择节点" #: users/templates/users/user_detail.html:511 #: users/templates/users/user_group_create_update.html:28 #: users/templates/users/user_list.html:184 +#: users/templates/users/user_password_verify.html:20 #: xpack/plugins/cloud/templates/cloud/account_create_update.html:30 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:50 #: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:41 @@ -1887,9 +1959,9 @@ msgstr "" #: assets/templates/assets/admin_user_list.html:5 msgid "" -"Jumpserver users of the system using the user to `push system user`, `get " +"JumpServer users of the system using the user to `push system user`, `get " "assets hardware information`, etc. " -msgstr "Jumpserver 使用该用户来 `推送系统用户`、`获取资产硬件信息` 等。" +msgstr "JumpServer 使用该用户来 `推送系统用户`、`获取资产硬件信息` 等。" #: assets/templates/assets/admin_user_list.html:13 #: assets/views/admin_user.py:50 @@ -1907,7 +1979,7 @@ msgstr "资产用户" #: assets/templates/assets/asset_asset_user_list.html:47 #: assets/templates/assets/asset_detail.html:140 -#: terminal/templates/terminal/session_detail.html:85 +#: terminal/templates/terminal/session_detail.html:87 #: users/templates/users/user_detail.html:126 #: users/templates/users/user_profile.html:150 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:126 @@ -2178,69 +2250,87 @@ msgstr "创建标签" msgid "Create platform" msgstr "创建系统平台" -#: assets/templates/assets/system_user_assets.html:35 -msgid "Assets of " -msgstr "资产" +#: assets/templates/assets/system_user_assets.html:32 +#: assets/templates/assets/system_user_detail.html:25 +#: assets/templates/assets/system_user_users.html:31 templates/_nav.html:20 +#: users/views/user.py:51 +msgid "User list" +msgstr "用户列表" -#: assets/templates/assets/system_user_assets.html:64 -#: assets/templates/assets/system_user_detail.html:146 +#: assets/templates/assets/system_user_assets.html:71 msgid "Test assets connective" msgstr "测试资产可连接性" -#: assets/templates/assets/system_user_assets.html:73 -#: assets/templates/assets/system_user_detail.html:136 +#: assets/templates/assets/system_user_assets.html:80 msgid "Push system user now" msgstr "立刻推送系统" -#: assets/templates/assets/system_user_assets.html:95 -msgid "Add to node" -msgstr "添加到节点" +#: assets/templates/assets/system_user_assets.html:279 +#: assets/templates/assets/system_user_users.html:205 +msgid "Have existed: " +msgstr "已经存在: " -#: assets/templates/assets/system_user_detail.html:82 +#: assets/templates/assets/system_user_detail.html:93 msgid "Home" msgstr "家目录" -#: assets/templates/assets/system_user_detail.html:88 +#: assets/templates/assets/system_user_detail.html:99 msgid "Uid" msgstr "Uid" -#: assets/templates/assets/system_user_detail.html:172 +#: assets/templates/assets/system_user_detail.html:163 msgid "Binding command filters" msgstr "绑定命令过滤器" #: assets/templates/assets/system_user_list.html:5 msgid "" -"System user is Jumpserver jump login assets used by the users, can be " +"System user is JumpServer jump login assets used by the users, can be " "understood as the user login assets, such as web, sa, the dba (` ssh " "web@some-host `), rather than using a user the username login server jump (` " "ssh xiaoming@some-host `); " msgstr "" -"系统用户是 Jumpserver 跳转登录资产时使用的用户,可以理解为登录资产用户,如 " +"系统用户是 JumpServer 跳转登录资产时使用的用户,可以理解为登录资产用户,如 " "web,sa,dba(`ssh web@some-host`),而不是使用某个用户的用户名跳转登录服务器" "(`ssh xiaoming@some-host`);" #: assets/templates/assets/system_user_list.html:6 msgid "" -"In simple terms, users log into Jumpserver using their own username, and " -"Jumpserver uses system users to log into assets. " +"In simple terms, users log into JumpServer using their own username, and " +"JumpServer uses system users to log into assets. " msgstr "" -"简单来说是用户使用自己的用户名登录 Jumpserver,Jumpserver 使用系统用户登录资" +"简单来说是用户使用自己的用户名登录 JumpServer,JumpServer 使用系统用户登录资" "产。" #: assets/templates/assets/system_user_list.html:7 msgid "" -"When system users are created, if you choose auto push Jumpserver to use " +"When system users are created, if you choose auto push JumpServer to use " "Ansible push system users into the asset, if the asset (Switch) does not " "support ansible, please manually fill in the account password." msgstr "" -"系统用户创建时,如果选择了自动推送,Jumpserver 会使用 Ansible 自动推送系统用" +"系统用户创建时,如果选择了自动推送,JumpServer 会使用 Ansible 自动推送系统用" "户到资产中,如果资产(交换机)不支持 Ansible,请手动填写账号密码。" #: assets/templates/assets/system_user_list.html:16 -#: assets/views/system_user.py:47 +#: assets/views/system_user.py:48 msgid "Create system user" msgstr "创建系统用户" +#: assets/templates/assets/system_user_users.html:84 users/forms/group.py:19 +#: users/forms/user.py:143 users/forms/user.py:148 +#: xpack/plugins/orgs/forms.py:17 +msgid "Select users" +msgstr "选择用户" + +#: assets/templates/assets/system_user_users.html:118 +#: users/templates/users/user_list.html:106 +#: users/templates/users/user_list.html:110 +msgid "Remove" +msgstr "移除" + +#: assets/templates/assets/system_user_users.html:176 +msgid "Remove success" +msgstr "移除成功" + #: assets/views/admin_user.py:31 msgid "Admin user list" msgstr "管理用户列表" @@ -2249,10 +2339,14 @@ msgstr "管理用户列表" msgid "Update admin user" msgstr "更新管理用户" -#: assets/views/admin_user.py:85 assets/views/admin_user.py:109 +#: assets/views/admin_user.py:85 msgid "Admin user detail" msgstr "管理用户详情" +#: assets/views/admin_user.py:109 +msgid "Admin user assets" +msgstr "管理用户关联资产" + #: assets/views/asset.py:67 templates/_nav_user.html:4 msgid "My assets" msgstr "我的资产" @@ -2325,39 +2419,44 @@ msgstr "更新标签" msgid "Platform list" msgstr "平台列表" -#: assets/views/platform.py:56 +#: assets/views/platform.py:59 msgid "Update platform" msgstr "更新系统平台" -#: assets/views/platform.py:72 +#: assets/views/platform.py:75 msgid "Platform detail" msgstr "平台详情" -#: assets/views/system_user.py:30 +#: assets/views/system_user.py:31 msgid "System user list" msgstr "系统用户列表" -#: assets/views/system_user.py:64 +#: assets/views/system_user.py:65 msgid "Update system user" msgstr "更新系统用户" -#: assets/views/system_user.py:80 +#: assets/views/system_user.py:81 msgid "System user detail" msgstr "系统用户详情" -#: assets/views/system_user.py:102 +#: assets/views/system_user.py:103 assets/views/system_user.py:118 msgid "assets" msgstr "资产管理" -#: assets/views/system_user.py:103 -msgid "System user asset" -msgstr "系统用户资产" +#: assets/views/system_user.py:104 +msgid "System user assets" +msgstr "系统用户关联资产" + +#: assets/views/system_user.py:119 +msgid "System user users" +msgstr "系统用户关联用户" #: audits/models.py:19 audits/models.py:42 audits/models.py:53 #: audits/templates/audits/ftp_log_list.html:77 #: audits/templates/audits/operate_log_list.html:74 #: audits/templates/audits/password_change_log_list.html:56 -#: terminal/models.py:183 terminal/templates/terminal/session_list.html:28 +#: terminal/models.py:192 terminal/templates/terminal/session_detail.html:68 +#: terminal/templates/terminal/session_list.html:28 #: terminal/templates/terminal/session_list.html:72 #: terminal/templates/terminal/terminal_detail.html:47 msgid "Remote addr" @@ -2378,13 +2477,13 @@ msgstr "文件名" #: ops/templates/ops/task_list.html:14 #: users/templates/users/user_detail.html:487 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:14 -#: xpack/plugins/cloud/api.py:61 +#: xpack/plugins/cloud/api.py:85 msgid "Success" msgstr "成功" #: audits/models.py:33 #: authentication/templates/authentication/_access_key_modal.html:22 -#: xpack/plugins/vault/templates/vault/vault.html:8 +#: xpack/plugins/vault/templates/vault/vault.html:7 msgid "Create" msgstr "创建" @@ -2414,8 +2513,7 @@ msgstr "启用" msgid "-" msgstr "" -#: audits/models.py:78 xpack/plugins/cloud/models.py:263 -#: xpack/plugins/cloud/models.py:286 +#: audits/models.py:78 xpack/plugins/cloud/models.py:201 msgid "Failed" msgstr "失败" @@ -2437,16 +2535,18 @@ msgstr "Agent" #: audits/models.py:86 audits/templates/audits/login_log_list.html:62 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 -#: users/forms/profile.py:52 users/models/user.py:460 -#: users/templates/users/first_login.html:45 +#: authentication/templates/authentication/login_otp.html:6 +#: settings/forms/security.py:16 users/forms/profile.py:52 +#: users/models/user.py:462 users/templates/users/first_login.html:45 +#: users/templates/users/user_detail.html:77 +#: users/templates/users/user_profile.html:87 msgid "MFA" -msgstr "MFA" +msgstr "多因子认证" #: audits/models.py:87 audits/templates/audits/login_log_list.html:63 -#: xpack/plugins/change_auth_plan/models.py:422 +#: xpack/plugins/change_auth_plan/models.py:368 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:15 -#: xpack/plugins/cloud/models.py:277 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:64 +#: xpack/plugins/cloud/models.py:214 msgid "Reason" msgstr "原因" @@ -2454,9 +2554,9 @@ msgstr "原因" #: tickets/templates/tickets/ticket_detail.html:34 #: tickets/templates/tickets/ticket_list.html:36 #: tickets/templates/tickets/ticket_list.html:104 -#: xpack/plugins/cloud/models.py:274 xpack/plugins/cloud/models.py:309 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:65 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:62 +#: xpack/plugins/cloud/models.py:211 xpack/plugins/cloud/models.py:269 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:40 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:37 msgid "Status" msgstr "状态" @@ -2472,12 +2572,13 @@ msgstr "登录日期" #: perms/templates/perms/asset_permission_detail.html:81 #: perms/templates/perms/database_app_permission_detail.html:77 #: perms/templates/perms/remote_app_permission_detail.html:73 -#: terminal/models.py:189 terminal/templates/terminal/session_list.html:32 -#: xpack/plugins/change_auth_plan/models.py:249 -#: xpack/plugins/change_auth_plan/models.py:425 +#: terminal/models.py:199 terminal/templates/terminal/session_detail.html:72 +#: terminal/templates/terminal/session_list.html:32 +#: xpack/plugins/change_auth_plan/models.py:195 +#: xpack/plugins/change_auth_plan/models.py:371 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:59 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:17 -#: xpack/plugins/gathered_user/models.py:140 +#: xpack/plugins/gathered_user/models.py:76 msgid "Date start" msgstr "开始日期" @@ -2495,8 +2596,6 @@ msgstr "选择用户" #: ops/templates/ops/command_execution_list.html:49 #: ops/templates/ops/command_execution_list.html:54 #: templates/_base_list.html:37 templates/_user_profile.html:23 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:47 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:45 msgid "Search" msgstr "搜索" @@ -2599,35 +2698,39 @@ msgstr "" msgid "Invalid token or cache refreshed." msgstr "" -#: authentication/errors.py:20 +#: authentication/errors.py:21 msgid "Username/password check failed" msgstr "用户名/密码 校验失败" -#: authentication/errors.py:21 -msgid "MFA authentication failed" -msgstr "MFA 认证失败" - #: authentication/errors.py:22 +msgid "MFA failed" +msgstr "多因子认证失败" + +#: authentication/errors.py:23 +msgid "MFA unset" +msgstr "多因子认证没有设定" + +#: authentication/errors.py:24 msgid "Username does not exist" msgstr "用户名不存在" -#: authentication/errors.py:23 +#: authentication/errors.py:25 msgid "Password expired" msgstr "密码已过期" -#: authentication/errors.py:24 +#: authentication/errors.py:26 msgid "Disabled or expired" msgstr "禁用或失效" -#: authentication/errors.py:25 +#: authentication/errors.py:27 msgid "This account is inactive." msgstr "此账户已禁用" -#: authentication/errors.py:35 +#: authentication/errors.py:37 msgid "No session found, check your cookie" msgstr "会话已变更,刷新页面" -#: authentication/errors.py:37 +#: authentication/errors.py:39 #, python-brace-format msgid "" "The username or password you entered is incorrect, please enter it again. " @@ -2637,36 +2740,40 @@ msgstr "" "您输入的用户名或密码不正确,请重新输入。 您还可以尝试 {times_try} 次(账号将" "被临时 锁定 {block_time} 分钟)" -#: authentication/errors.py:43 +#: authentication/errors.py:45 msgid "" "The account has been locked (please contact admin to unlock it or try again " "after {} minutes)" msgstr "账号已被锁定(请联系管理员解锁 或 {}分钟后重试)" -#: authentication/errors.py:46 users/views/profile.py:202 -#: users/views/profile.py:238 +#: authentication/errors.py:48 users/views/profile/otp.py:63 +#: users/views/profile/otp.py:102 msgid "MFA code invalid, or ntp sync server time" msgstr "MFA验证码不正确,或者服务器端时间不对" -#: authentication/errors.py:48 +#: authentication/errors.py:50 msgid "MFA required" -msgstr "" +msgstr "需要多因子认证" -#: authentication/errors.py:49 +#: authentication/errors.py:51 +msgid "MFA not set, please set it first" +msgstr "多因子认证没有设置,请先完成设置" + +#: authentication/errors.py:52 msgid "Login confirm required" msgstr "需要登录复核" -#: authentication/errors.py:50 +#: authentication/errors.py:53 msgid "Wait login confirm ticket for accept" msgstr "等待登录复核处理" -#: authentication/errors.py:51 +#: authentication/errors.py:54 msgid "Login confirm ticket was {}" msgstr "登录复核 {}" #: authentication/forms.py:29 users/forms/user.py:199 msgid "MFA code" -msgstr "MFA 验证码" +msgstr "多因子认证验证码" #: authentication/models.py:39 msgid "Private Token" @@ -2698,12 +2805,13 @@ msgid "Secret" msgstr "密文" #: authentication/templates/authentication/_access_key_modal.html:48 -#: users/templates/users/_granted_assets.html:80 +#: users/templates/users/_granted_assets.html:75 msgid "Show" msgstr "显示" #: authentication/templates/authentication/_access_key_modal.html:66 -#: users/models/user.py:360 users/templates/users/user_profile.html:94 +#: users/models/user.py:360 users/templates/users/user_disable_mfa.html:32 +#: users/templates/users/user_profile.html:94 #: users/templates/users/user_profile.html:163 #: users/templates/users/user_profile.html:166 msgid "Disable" @@ -2717,121 +2825,63 @@ msgstr "启用" #: authentication/templates/authentication/_mfa_confirm_modal.html:5 msgid "MFA confirm" -msgstr "MFA确认" +msgstr "多因子认证校验" #: authentication/templates/authentication/_mfa_confirm_modal.html:17 -msgid "Need otp auth for view auth" -msgstr "需要二次认证来查看账号信息" +msgid "Need MFA for view auth" +msgstr "需要多因子认证来查看账号信息" #: authentication/templates/authentication/_mfa_confirm_modal.html:25 msgid "Code error" msgstr "代码错误" -#: authentication/templates/authentication/login.html:27 -#: authentication/templates/authentication/login_otp.html:27 -#: xpack/plugins/interface/models.py:36 -msgid "Welcome to the Jumpserver open source fortress" -msgstr "欢迎使用Jumpserver开源堡垒机" - -#: authentication/templates/authentication/login.html:29 -#: authentication/templates/authentication/login_otp.html:29 -msgid "" -"The world's first fully open source fortress, using the GNU GPL v2.0 open " -"source protocol, is a professional operation and maintenance audit system in " -"compliance with 4A." -msgstr "" -"全球首款完全开源的堡垒机,使用GNU GPL v2.0开源协议,是符合 4A 的专业运维审计" -"系统。" - -#: authentication/templates/authentication/login.html:32 -#: authentication/templates/authentication/login_otp.html:32 -msgid "" -"Developed using Python/Django, following the Web 2.0 specification and " -"equipped with industry-leading Web Terminal solutions, with beautiful " -"interactive interface and good user experience." -msgstr "" -"使用Python / Django 进行开发,遵循 Web 2.0 规范,配备了业界领先的 Web " -"Terminal 解决方案,交互界面美观、用户体验好。" - -#: authentication/templates/authentication/login.html:35 -#: authentication/templates/authentication/login_otp.html:35 -msgid "" -"Distributed architecture is adopted to support multi-machine room deployment " -"across regions, central node provides API, and each machine room deploys " -"login node, which can be extended horizontally and without concurrent access " -"restrictions." -msgstr "" -"采纳分布式架构,支持多机房跨区域部署,中心节点提供 API,各机房部署登录节点," -"可横向扩展、无并发访问限制。" - -#: authentication/templates/authentication/login.html:38 -#: authentication/templates/authentication/login_otp.html:38 -msgid "Changes the world, starting with a little bit." -msgstr "改变世界,从一点点开始。" - -#: authentication/templates/authentication/login.html:45 -#: authentication/templates/authentication/login.html:76 +#: authentication/templates/authentication/login.html:6 +#: authentication/templates/authentication/login.html:39 #: authentication/templates/authentication/xpack_login.html:112 -#: templates/_header_bar.html:83 +#: templates/_base_only_msg_content.html:52 templates/_header_bar.html:83 msgid "Login" msgstr "登录" -#: authentication/templates/authentication/login.html:54 +#: authentication/templates/authentication/login.html:17 #: authentication/templates/authentication/xpack_login.html:87 msgid "Captcha invalid" msgstr "验证码错误" -#: authentication/templates/authentication/login.html:87 +#: authentication/templates/authentication/login.html:50 #: authentication/templates/authentication/xpack_login.html:116 -#: users/templates/users/forgot_password.html:12 -#: users/templates/users/forgot_password.html:13 +#: users/templates/users/forgot_password.html:7 +#: users/templates/users/forgot_password.html:8 msgid "Forgot password" msgstr "忘记密码" -#: authentication/templates/authentication/login.html:94 +#: authentication/templates/authentication/login.html:57 msgid "More login options" msgstr "更多登录方式" -#: authentication/templates/authentication/login.html:98 +#: authentication/templates/authentication/login.html:61 msgid "Keycloak" msgstr "" -#: authentication/templates/authentication/login_otp.html:46 -#: users/templates/users/user_detail.html:77 -#: users/templates/users/user_profile.html:87 -msgid "MFA certification" -msgstr "MFA认证" +#: authentication/templates/authentication/login_otp.html:17 +msgid "One-time password" +msgstr "一次性密码" -#: authentication/templates/authentication/login_otp.html:51 -#: users/templates/users/user_disable_mfa.html:11 -msgid "" -"The account protection has been opened, please complete the following " -"operations according to the prompts" -msgstr "账号保护已开启,请根据提示完成以下操作" +#: authentication/templates/authentication/login_otp.html:23 +msgid "Open Google Authenticator and enter the 6-bit dynamic code" +msgstr "请打开 Google Authenticator,输入6位动态码" -#: authentication/templates/authentication/login_otp.html:55 -#: users/templates/users/user_disable_mfa.html:13 -msgid "Open Authenticator and enter the 6-bit dynamic code" -msgstr "请打开手机Google Authenticator应用,输入6位动态码" - -#: authentication/templates/authentication/login_otp.html:65 -#: users/templates/users/user_disable_mfa.html:23 -#: users/templates/users/user_otp_enable_bind.html:25 -msgid "Six figures" -msgstr "6位数字" - -#: authentication/templates/authentication/login_otp.html:67 -#: users/templates/users/first_login.html:108 +#: authentication/templates/authentication/login_otp.html:26 +#: users/templates/users/first_login.html:100 #: users/templates/users/user_disable_mfa.html:26 -#: users/templates/users/user_otp_enable_bind.html:28 -#: users/templates/users/user_otp_enable_install_app.html:25 -#: users/templates/users/user_password_check.html:16 +#: users/templates/users/user_otp_check_password.html:15 +#: users/templates/users/user_otp_enable_bind.html:24 +#: users/templates/users/user_otp_enable_install_app.html:29 msgid "Next" msgstr "下一步" -#: authentication/templates/authentication/login_otp.html:70 +#: authentication/templates/authentication/login_otp.html:29 msgid "Can't provide security? Please contact the administrator!" -msgstr "如果不能提供MFA验证码,请联系管理员!" +msgstr "如果不能提供多因子认证验证码,请联系管理员!" #: authentication/templates/authentication/login_wait_confirm.html:47 msgid "Copy link" @@ -2846,11 +2896,11 @@ msgstr "返回" msgid "Welcome back, please enter username and password to login" msgstr "欢迎回来,请输入用户名和密码登录" -#: authentication/views/login.py:71 +#: authentication/views/login.py:83 msgid "Please enable cookies and try again." msgstr "设置你的浏览器支持cookie" -#: authentication/views/login.py:159 +#: authentication/views/login.py:168 msgid "" "Wait for {} confirm, You also can copy link to her/him
    \n" " Don't close this page" @@ -2858,15 +2908,15 @@ msgstr "" "等待 {} 确认, 你也可以复制链接发给他/她
    \n" " 不要关闭本页面" -#: authentication/views/login.py:164 +#: authentication/views/login.py:173 msgid "No ticket found" msgstr "没有发现工单" -#: authentication/views/login.py:187 +#: authentication/views/login.py:205 msgid "Logout success" msgstr "退出登录成功" -#: authentication/views/login.py:188 +#: authentication/views/login.py:206 msgid "Logout success, return login page" msgstr "退出登录成功,返回到登录页面" @@ -2916,11 +2966,11 @@ msgstr "" msgid "Encrypt field using Secret Key" msgstr "" -#: common/mixins/models.py:34 +#: common/mixins/models.py:33 msgid "is discard" msgstr "" -#: common/mixins/models.py:35 +#: common/mixins/models.py:34 msgid "discard time" msgstr "" @@ -2940,7 +2990,7 @@ msgstr "字段必须唯一" msgid "

    Flow service unavailable, check it

    " msgstr "" -#: jumpserver/views/index.py:178 templates/_nav.html:7 +#: jumpserver/views/index.py:242 templates/_nav.html:7 msgid "Dashboard" msgstr "仪表盘" @@ -2975,123 +3025,157 @@ msgstr "等待任务开始" msgid "Not has host {} permission" msgstr "没有该主机 {} 权限" -#: ops/models/adhoc.py:41 -msgid "Interval" -msgstr "间隔" +#: ops/mixin.py:29 ops/mixin.py:92 ops/mixin.py:162 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:98 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:88 +msgid "Cycle perform" +msgstr "周期执行" -#: ops/models/adhoc.py:41 settings/forms/terminal.py:34 -msgid "Units: seconds" -msgstr "单位: 秒" +#: ops/mixin.py:33 ops/mixin.py:90 ops/mixin.py:111 ops/mixin.py:150 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:90 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:80 +msgid "Regularly perform" +msgstr "定期执行" -#: ops/models/adhoc.py:42 -msgid "Crontab" -msgstr "Crontab" +#: ops/mixin.py:108 ops/mixin.py:147 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:54 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:79 +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:17 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:37 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:69 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:16 +#: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:28 +msgid "Periodic perform" +msgstr "定时执行" -#: ops/models/adhoc.py:42 -msgid "5 * * * *" -msgstr "5 * * * *" +#: ops/mixin.py:122 +msgid "* Please enter a valid crontab expression" +msgstr "* 请输入有效的 crontab 表达式" -#: ops/models/adhoc.py:44 +#: ops/mixin.py:129 +msgid "Range {} to {}" +msgstr "输入在 {} - {} 范围之间" + +#: ops/mixin.py:140 +msgid "Require periodic or regularly perform setting" +msgstr "需要周期或定期设置" + +#: ops/mixin.py:151 +msgid "" +"eg: Every Sunday 03:05 run <5 3 * * 0>
    Tips: Using 5 digits linux " +"crontab expressions (Online tools)
    Note: If both Regularly " +"perform and Cycle perform are set, give priority to Regularly perform" +msgstr "" +"eg:每周日 03:05 执行 <5 3 * * 0>
    提示: 使用5位 Linux crontab 表达式 <" +"分 时 日 月 星期> (在线工" +"具
    注意: 如果同时设置了定期执行和周期执行,优先使用定期执行" + +#: ops/mixin.py:162 +msgid "Tips: (Units: hour)" +msgstr "提示:(单位: 时)" + +#: ops/models/adhoc.py:35 msgid "Callback" msgstr "回调" -#: ops/models/adhoc.py:182 ops/templates/ops/adhoc_detail.html:112 +#: ops/models/adhoc.py:143 ops/templates/ops/adhoc_detail.html:112 msgid "Tasks" msgstr "任务" -#: ops/models/adhoc.py:183 ops/templates/ops/adhoc_detail.html:55 +#: ops/models/adhoc.py:144 ops/templates/ops/adhoc_detail.html:55 #: ops/templates/ops/task_adhoc.html:58 msgid "Pattern" msgstr "模式" -#: ops/models/adhoc.py:184 ops/templates/ops/adhoc_detail.html:59 +#: ops/models/adhoc.py:145 ops/templates/ops/adhoc_detail.html:59 msgid "Options" msgstr "选项" -#: ops/models/adhoc.py:186 +#: ops/models/adhoc.py:147 msgid "Run as admin" msgstr "再次执行" -#: ops/models/adhoc.py:188 ops/templates/ops/adhoc_detail.html:80 +#: ops/models/adhoc.py:149 ops/templates/ops/adhoc_detail.html:80 #: ops/templates/ops/task_adhoc.html:60 msgid "Become" msgstr "Become" -#: ops/models/adhoc.py:189 users/templates/users/user_group_detail.html:54 +#: ops/models/adhoc.py:150 users/templates/users/user_group_detail.html:54 #: xpack/plugins/cloud/templates/cloud/account_detail.html:59 #: xpack/plugins/orgs/templates/orgs/org_detail.html:51 msgid "Create by" msgstr "创建者" -#: ops/models/adhoc.py:270 +#: ops/models/adhoc.py:232 msgid "Task display" msgstr "任务展示" -#: ops/models/adhoc.py:271 +#: ops/models/adhoc.py:233 msgid "Host amount" msgstr "主机数量" -#: ops/models/adhoc.py:273 +#: ops/models/adhoc.py:235 msgid "Start time" msgstr "开始时间" -#: ops/models/adhoc.py:274 +#: ops/models/adhoc.py:236 msgid "End time" msgstr "完成时间" -#: ops/models/adhoc.py:275 ops/templates/ops/adhoc_history.html:55 +#: ops/models/adhoc.py:237 ops/templates/ops/adhoc_history.html:55 #: ops/templates/ops/task_history.html:61 ops/templates/ops/task_list.html:16 -#: xpack/plugins/change_auth_plan/models.py:252 -#: xpack/plugins/change_auth_plan/models.py:428 +#: xpack/plugins/change_auth_plan/models.py:198 +#: xpack/plugins/change_auth_plan/models.py:374 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:58 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:16 -#: xpack/plugins/gathered_user/models.py:143 +#: xpack/plugins/gathered_user/models.py:79 msgid "Time" msgstr "时间" -#: ops/models/adhoc.py:276 ops/templates/ops/adhoc_detail.html:104 +#: ops/models/adhoc.py:238 ops/templates/ops/adhoc_detail.html:104 #: ops/templates/ops/adhoc_history.html:53 #: ops/templates/ops/adhoc_history_detail.html:67 #: ops/templates/ops/task_detail.html:82 ops/templates/ops/task_history.html:59 msgid "Is finished" msgstr "是否完成" -#: ops/models/adhoc.py:277 ops/templates/ops/adhoc_history.html:54 +#: ops/models/adhoc.py:239 ops/templates/ops/adhoc_history.html:54 #: ops/templates/ops/task_history.html:60 msgid "Is success" msgstr "是否成功" -#: ops/models/adhoc.py:278 +#: ops/models/adhoc.py:240 msgid "Adhoc raw result" msgstr "结果" -#: ops/models/adhoc.py:279 +#: ops/models/adhoc.py:241 msgid "Adhoc result summary" msgstr "汇总" -#: ops/models/adhoc.py:323 +#: ops/models/adhoc.py:281 msgid "{} Start task: {}" msgstr "{} 任务开始: {}" -#: ops/models/adhoc.py:332 +#: ops/models/adhoc.py:290 msgid "{} Task finish" msgstr "{} 任务结束" -#: ops/models/command.py:23 +#: ops/models/command.py:24 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:56 -#: xpack/plugins/cloud/models.py:272 +#: xpack/plugins/cloud/models.py:209 msgid "Result" msgstr "结果" -#: ops/models/command.py:58 +#: ops/models/command.py:59 msgid "Task start" msgstr "任务开始" -#: ops/models/command.py:80 +#: ops/models/command.py:81 msgid "Command `{}` is forbidden ........" msgstr "命令 `{}` 不允许被执行 ......." -#: ops/models/command.py:86 +#: ops/models/command.py:88 msgid "Task end" msgstr "任务结束" @@ -3109,8 +3193,8 @@ msgid "Version detail" msgstr "版本详情" #: ops/templates/ops/adhoc_detail.html:20 -#: ops/templates/ops/adhoc_history.html:20 ops/views/adhoc.py:111 -msgid "Version run history" +#: ops/templates/ops/adhoc_history.html:20 ops/views/adhoc.py:106 +msgid "Version run execution" msgstr "执行历史" #: ops/templates/ops/adhoc_detail.html:51 @@ -3168,8 +3252,8 @@ msgstr "最后运行成功主机" #: ops/templates/ops/adhoc_history.html:28 #: ops/templates/ops/task_history.html:34 -msgid "History of " -msgstr "执行历史" +msgid "Executions of " +msgstr "执行历史 " #: ops/templates/ops/adhoc_history.html:51 #: ops/templates/ops/task_history.html:57 @@ -3181,18 +3265,18 @@ msgstr "失败/成功/总" msgid "Ratio" msgstr "比例" -#: ops/templates/ops/adhoc_history_detail.html:17 ops/views/adhoc.py:125 -msgid "Run history detail" +#: ops/templates/ops/adhoc_history_detail.html:17 ops/views/adhoc.py:120 +msgid "Execution detail" msgstr "执行历史详情" #: ops/templates/ops/adhoc_history_detail.html:20 #: ops/templates/ops/command_execution_list.html:69 -#: terminal/backends/command/models.py:16 +#: terminal/backends/command/models.py:22 msgid "Output" msgstr "输出" #: ops/templates/ops/adhoc_history_detail.html:28 -msgid "History detail of" +msgid "Execution detail of" msgstr "执行历史详情" #: ops/templates/ops/adhoc_history_detail.html:51 @@ -3217,8 +3301,8 @@ msgid "Task log" msgstr "任务列表" #: ops/templates/ops/command_execution_create.html:93 -#: terminal/templates/terminal/session_detail.html:95 -#: terminal/templates/terminal/session_detail.html:104 +#: terminal/templates/terminal/session_detail.html:97 +#: terminal/templates/terminal/session_detail.html:114 msgid "Go" msgstr "" @@ -3261,24 +3345,24 @@ msgid "Finished" msgstr "结束" #: ops/templates/ops/task_adhoc.html:17 ops/templates/ops/task_detail.html:18 -#: ops/templates/ops/task_history.html:17 ops/views/adhoc.py:55 +#: ops/templates/ops/task_history.html:17 ops/views/adhoc.py:50 msgid "Task detail" msgstr "任务详情" #: ops/templates/ops/task_adhoc.html:20 ops/templates/ops/task_detail.html:21 -#: ops/templates/ops/task_history.html:20 ops/views/adhoc.py:69 +#: ops/templates/ops/task_history.html:20 ops/views/adhoc.py:64 msgid "Task versions" msgstr "任务各版本" #: ops/templates/ops/task_adhoc.html:23 ops/templates/ops/task_detail.html:24 #: ops/templates/ops/task_history.html:23 -msgid "Run history" +msgid "Execution" msgstr "执行历史" #: ops/templates/ops/task_adhoc.html:26 ops/templates/ops/task_detail.html:27 #: ops/templates/ops/task_history.html:26 -msgid "Last run output" -msgstr "输出" +msgid "Last execution output" +msgstr "最后执行输出" #: ops/templates/ops/task_adhoc.html:34 msgid "Versions of " @@ -3305,17 +3389,17 @@ msgstr "执行" msgid "Task start: " msgstr "任务开始: " -#: ops/utils.py:53 +#: ops/utils.py:60 msgid "Update task content: {}" msgstr "更新任务内容: {}" -#: ops/utils.py:63 +#: ops/utils.py:70 msgid "Disk used more than 80%: {} => {}" msgstr "" -#: ops/views/adhoc.py:31 ops/views/adhoc.py:54 ops/views/adhoc.py:68 -#: ops/views/adhoc.py:82 ops/views/adhoc.py:96 ops/views/adhoc.py:110 -#: ops/views/adhoc.py:124 ops/views/command.py:48 ops/views/command.py:79 +#: ops/views/adhoc.py:31 ops/views/adhoc.py:49 ops/views/adhoc.py:63 +#: ops/views/adhoc.py:77 ops/views/adhoc.py:91 ops/views/adhoc.py:105 +#: ops/views/adhoc.py:119 ops/views/command.py:48 ops/views/command.py:79 msgid "Ops" msgstr "作业中心" @@ -3324,9 +3408,9 @@ msgstr "作业中心" msgid "Task list" msgstr "任务列表" -#: ops/views/adhoc.py:83 -msgid "Task run history" -msgstr "执行历史" +#: ops/views/adhoc.py:78 +msgid "Task execution list" +msgstr "任务执行列表" #: ops/views/command.py:49 msgid "Command execution list" @@ -3336,7 +3420,7 @@ msgstr "命令执行列表" msgid "Command execution" msgstr "命令执行" -#: orgs/mixins/models.py:44 orgs/mixins/serializers.py:26 orgs/models.py:31 +#: orgs/mixins/models.py:56 orgs/mixins/serializers.py:26 orgs/models.py:31 msgid "Organization" msgstr "组织" @@ -3362,7 +3446,7 @@ msgstr "提示:RDP 协议不支持单独控制上传或下载文件" #: perms/templates/perms/database_app_permission_list.html:16 #: perms/templates/perms/remote_app_permission_list.html:16 #: templates/_nav.html:21 users/forms/user.py:168 users/models/group.py:31 -#: users/models/user.py:444 users/templates/users/_select_user_modal.html:16 +#: users/models/user.py:446 users/templates/users/_select_user_modal.html:16 #: users/templates/users/user_asset_permission.html:39 #: users/templates/users/user_asset_permission.html:67 #: users/templates/users/user_database_app_permission.html:38 @@ -3414,7 +3498,7 @@ msgstr "资产授权" #: perms/templates/perms/asset_permission_detail.html:85 #: perms/templates/perms/database_app_permission_detail.html:81 #: perms/templates/perms/remote_app_permission_detail.html:77 -#: users/models/user.py:476 users/templates/users/user_detail.html:93 +#: users/models/user.py:478 users/templates/users/user_detail.html:93 #: users/templates/users/user_profile.html:120 msgid "Date expired" msgstr "失效日期" @@ -3542,7 +3626,7 @@ msgstr "刷新授权缓存" #: users/templates/users/user_database_app_permission.html:41 #: users/templates/users/user_list.html:19 #: users/templates/users/user_remote_app_permission.html:41 -#: xpack/plugins/cloud/models.py:73 +#: xpack/plugins/cloud/models.py:50 #: xpack/plugins/cloud/templates/cloud/account_detail.html:55 #: xpack/plugins/cloud/templates/cloud/account_list.html:14 msgid "Validity" @@ -3726,27 +3810,15 @@ msgstr "远程应用授权用户列表" msgid "RemoteApp permission RemoteApp list" msgstr "远程应用授权远程应用列表" -#: settings/api.py:37 +#: settings/api.py:33 msgid "Test mail sent to {}, please check" msgstr "邮件已经发送{}, 请检查" -#: settings/api.py:76 -msgid "Test ldap success" -msgstr "连接LDAP成功" - -#: settings/api.py:107 -msgid "LDAP attr map not valid" -msgstr "" - -#: settings/api.py:116 -msgid "Match {} s users" -msgstr "匹配 {} 个用户" - -#: settings/api.py:226 +#: settings/api.py:227 msgid "Get ldap users is None" msgstr "获取 LDAP 用户为 None" -#: settings/api.py:233 +#: settings/api.py:234 msgid "Imported {} users successfully" msgstr "导入 {} 个用户成功" @@ -3768,7 +3840,7 @@ msgstr "Email主题前缀" #: settings/forms/basic.py:22 msgid "Tips: Some word will be intercept by mail provider" -msgstr "提示: 一些关键字可能会被邮件提供商拦截,如 跳板机、Jumpserver" +msgstr "提示: 一些关键字可能会被邮件提供商拦截,如 跳板机、JumpServer" #: settings/forms/email.py:15 msgid "SMTP host" @@ -3897,15 +3969,11 @@ msgstr "" msgid "Enable LDAP auth" msgstr "启用LDAP认证" -#: settings/forms/security.py:16 -msgid "MFA Secondary certification" -msgstr "MFA 二次认证" - #: settings/forms/security.py:18 msgid "" -"After opening, the user login must use MFA secondary authentication (valid " -"for all users, including administrators)" -msgstr "开启后,用户登录必须使用MFA二次认证(对所有用户有效,包括管理员)" +"After opening, all user login must use MFA(valid for all users, including " +"administrators)" +msgstr "开启后,所有用户登录必须使用多因子认证(对所有用户有效,包括管理员)" #: settings/forms/security.py:24 msgid "Batch execute commands" @@ -4022,6 +4090,10 @@ msgstr "密钥认证" msgid "Heartbeat interval" msgstr "心跳间隔" +#: settings/forms/terminal.py:34 +msgid "Units: seconds" +msgstr "单位: 秒" + #: settings/forms/terminal.py:37 msgid "List sort by" msgstr "资产列表排序" @@ -4069,7 +4141,7 @@ msgid "Refresh cache" msgstr "刷新缓存" #: settings/templates/settings/_ldap_list_users_modal.html:33 -#: users/forms/profile.py:89 users/models/user.py:440 +#: users/forms/profile.py:89 users/models/user.py:442 #: users/templates/users/user_detail.html:57 #: users/templates/users/user_profile.html:59 msgid "Email" @@ -4090,6 +4162,18 @@ msgstr "当前无勾选用户,请勾选你想要导入的用户" msgid "Import" msgstr "导入" +#: settings/templates/settings/_ldap_test_user_login_modal.html:4 +msgid "Test LDAP user login" +msgstr "测试LDAP 用户登录" + +#: settings/templates/settings/_ldap_test_user_login_modal.html:5 +msgid "Save the configuration before testing the login" +msgstr "请先提交LDAP配置再进行测试登录" + +#: settings/templates/settings/_ldap_test_user_login_modal.html:12 +msgid "Please input username" +msgstr "请输入用户名" + #: settings/templates/settings/_setting_tabs.html:4 #: settings/templates/settings/terminal_setting.html:31 settings/views.py:20 msgid "Basic setting" @@ -4121,6 +4205,10 @@ msgid "Create User setting" msgstr "创建用户设置" #: settings/templates/settings/ldap_setting.html:47 +msgid "Test login" +msgstr "测试登录" + +#: settings/templates/settings/ldap_setting.html:48 msgid "Bulk import" msgstr "一键导入" @@ -4140,6 +4228,103 @@ msgstr "会话管理 -> 终端管理 -> 存储配置" msgid "Here" msgstr "这里" +#: settings/utils/ldap.py:389 +msgid "Host or port is disconnected: {}" +msgstr "" + +#: settings/utils/ldap.py:391 +msgid "The port is not the port of the LDAP service: {}" +msgstr "" + +#: settings/utils/ldap.py:393 +msgid "Please enter the certificate: {}" +msgstr "" + +#: settings/utils/ldap.py:395 settings/utils/ldap.py:422 +#: settings/utils/ldap.py:452 settings/utils/ldap.py:480 +msgid "Unknown error: {}" +msgstr "" + +#: settings/utils/ldap.py:409 +msgid "bind dn or password incorrect" +msgstr "" + +#: settings/utils/ldap.py:416 +msgid "Please enter bind dn: {}" +msgstr "" + +#: settings/utils/ldap.py:418 +msgid "Please enter password: {}" +msgstr "请输入密码: {}" + +#: settings/utils/ldap.py:420 +msgid "Please enter correct bind dn and password: {}" +msgstr "请输入正确的dn和密码: {}" + +#: settings/utils/ldap.py:438 +msgid "Invalid search ou or filter: {}" +msgstr "不合法的ou或过滤器: {}" + +#: settings/utils/ldap.py:469 +msgid "LDAP attribute not include: {}" +msgstr "LDAP属性映射没有包含: {}" + +#: settings/utils/ldap.py:476 +msgid "LDAP attribute map is not dict" +msgstr "LDAP属性映射不合法" + +#: settings/utils/ldap.py:495 +msgid "LDAP authentication is not enabled" +msgstr "LDAP认证没有启用" + +#: settings/utils/ldap.py:513 +msgid "Error (Invalid server uri): {}" +msgstr "错误 (不合法的服务器地址): {}" + +#: settings/utils/ldap.py:515 +msgid "Error (Invalid bind dn): {}" +msgstr "错误 (不合法的DN): {}" + +#: settings/utils/ldap.py:517 +msgid "Error (Invalid attribute map): {}" +msgstr "错误 (不合法的属性映射): {}" + +#: settings/utils/ldap.py:519 +msgid "Error (Invalid search ou or filter): {}" +msgstr "错误 (不合法的搜索OU或过滤器): {}" + +#: settings/utils/ldap.py:521 +msgid "Error (Not enabled LDAP authentication): {}" +msgstr "错误 (没有启用LDAP认证): {}" + +#: settings/utils/ldap.py:523 +msgid "Error (Unknown): {}" +msgstr "错误 (未知): {}" + +#: settings/utils/ldap.py:526 +msgid "Succeed: Match {} s user" +msgstr "成功匹配 {} 个用户" + +#: settings/utils/ldap.py:559 +msgid "Authentication failed (configuration incorrect): {}" +msgstr "认证失败 (配置错误): {}" + +#: settings/utils/ldap.py:561 +msgid "Authentication failed (before login check failed): {}" +msgstr "认证失败 (登录前检查失败): {}" + +#: settings/utils/ldap.py:563 +msgid "Authentication failed (username or password incorrect): {}" +msgstr "认证失败 (用户名或密码不正确): {}" + +#: settings/utils/ldap.py:565 +msgid "Authentication failed (Unknown): {}" +msgstr "认证失败: (未知): {}" + +#: settings/utils/ldap.py:568 +msgid "Authentication success: {}" +msgstr "认证成功: {}" + #: settings/views.py:19 settings/views.py:46 settings/views.py:73 #: settings/views.py:105 settings/views.py:134 settings/views.py:161 #: templates/_nav.html:187 @@ -4151,6 +4336,43 @@ msgstr "系统设置" msgid "Update setting successfully" msgstr "更新设置成功" +#: templates/_base_only_msg_content.html:28 +#: xpack/plugins/interface/models.py:36 +msgid "Welcome to the JumpServer open source fortress" +msgstr "欢迎使用JumpServer开源堡垒机" + +#: templates/_base_only_msg_content.html:33 +msgid "" +"The world's first fully open source fortress, using the GNU GPL v2.0 open " +"source protocol, is a professional operation and maintenance audit system in " +"compliance with 4A." +msgstr "" +"全球首款完全开源的堡垒机,使用GNU GPL v2.0开源协议,是符合 4A 的专业运维审计" +"系统。" + +#: templates/_base_only_msg_content.html:36 +msgid "" +"Developed using Python/Django, following the Web 2.0 specification and " +"equipped with industry-leading Web Terminal solutions, with beautiful " +"interactive interface and good user experience." +msgstr "" +"使用Python / Django 进行开发,遵循 Web 2.0 规范,配备了业界领先的 Web " +"Terminal 解决方案,交互界面美观、用户体验好。" + +#: templates/_base_only_msg_content.html:39 +msgid "" +"Distributed architecture is adopted to support multi-machine room deployment " +"across regions, central node provides API, and each machine room deploys " +"login node, which can be extended horizontally and without concurrent access " +"restrictions." +msgstr "" +"采纳分布式架构,支持多机房跨区域部署,中心节点提供 API,各机房部署登录节点," +"可横向扩展、无并发访问限制。" + +#: templates/_base_only_msg_content.html:42 +msgid "Changes the world, starting with a little bit." +msgstr "改变世界,从一点点开始。" + #: templates/_csv_import_modal.html:12 msgid "Download the imported template or use the exported CSV file format" msgstr "下载导入的模板或使用导出的csv格式" @@ -4195,7 +4417,8 @@ msgstr "商业支持" #: users/templates/users/user_profile.html:17 #: users/templates/users/user_profile_update.html:37 #: users/templates/users/user_profile_update.html:61 -#: users/templates/users/user_pubkey_update.html:37 users/views/profile.py:51 +#: users/templates/users/user_pubkey_update.html:37 +#: users/views/profile/base.py:27 msgid "Profile" msgstr "个人信息" @@ -4288,28 +4511,15 @@ msgstr "" "\"%(user_pubkey_update)s\"> 链接 更新\n" " " -#: templates/_nav.html:17 users/views/group.py:28 users/views/group.py:45 -#: users/views/group.py:63 users/views/group.py:82 users/views/group.py:99 -#: users/views/login.py:158 users/views/profile.py:90 -#: users/views/profile.py:125 users/views/user.py:50 users/views/user.py:67 -#: users/views/user.py:111 users/views/user.py:178 users/views/user.py:206 -#: users/views/user.py:220 users/views/user.py:234 users/views/user.py:248 -#: users/views/user.py:262 users/views/user.py:276 -msgid "Users" -msgstr "用户管理" - -#: templates/_nav.html:20 users/views/user.py:51 -msgid "User list" -msgstr "用户列表" - #: templates/_nav.html:47 msgid "Command filters" msgstr "命令过滤" #: templates/_nav.html:97 terminal/views/command.py:21 -#: terminal/views/session.py:43 terminal/views/session.py:54 -#: terminal/views/session.py:78 terminal/views/terminal.py:32 -#: terminal/views/terminal.py:48 terminal/views/terminal.py:61 +#: terminal/views/session.py:48 terminal/views/session.py:59 +#: terminal/views/session.py:74 terminal/views/session.py:97 +#: terminal/views/terminal.py:32 terminal/views/terminal.py:48 +#: terminal/views/terminal.py:61 msgid "Sessions" msgstr "会话管理" @@ -4317,11 +4527,12 @@ msgstr "会话管理" msgid "Session online" msgstr "在线会话" -#: templates/_nav.html:101 terminal/views/session.py:55 +#: templates/_nav.html:101 terminal/views/session.py:60 msgid "Session offline" msgstr "历史会话" -#: templates/_nav.html:102 +#: templates/_nav.html:102 terminal/templates/terminal/session_commands.html:21 +#: terminal/templates/terminal/session_detail.html:21 msgid "Commands" msgstr "命令记录" @@ -4406,136 +4617,128 @@ msgid "Online sessions" msgstr "在线会话" #: templates/index.html:61 -msgid " Top 5 Active user" -msgstr "活跃用户Top5" - -#: templates/index.html:62 msgid "In the past week, a total of " msgstr "过去一周, 共有 " -#: templates/index.html:62 +#: templates/index.html:61 msgid " users have logged in " msgstr " 位用户登录 " -#: templates/index.html:62 +#: templates/index.html:61 msgid " times asset." msgstr " 次资产." -#: templates/index.html:67 +#: templates/index.html:66 msgid " times/week" msgstr " 次/周" -#: templates/index.html:78 +#: templates/index.html:77 msgid "Active user asset ratio" msgstr "活跃用户资产占比" -#: templates/index.html:81 +#: templates/index.html:80 msgid "" "The following graphs describe the percentage of active users per month and " "assets per user host per month, respectively." msgstr "以下图形分别描述一个月活跃用户和资产占所有用户主机的百分比" -#: templates/index.html:106 templates/index.html:121 +#: templates/index.html:105 templates/index.html:120 msgid "Top 10 assets in a week" msgstr "一周Top10资产" -#: templates/index.html:122 +#: templates/index.html:121 msgid "Login frequency and last login record." msgstr "登录次数及最近一次登录记录." -#: templates/index.html:133 templates/index.html:221 +#: templates/index.html:132 templates/index.html:218 msgid " times" msgstr " 次" -#: templates/index.html:136 -msgid "The last time a user logged in" -msgstr "最近一次登录用户" +#: templates/index.html:135 templates/index.html:221 +msgid "The time last logged in" +msgstr "最近一次登录日期" -#: templates/index.html:138 templates/index.html:226 -msgid "At " +#: templates/index.html:136 templates/index.html:222 +msgid "At" msgstr "于" -#: templates/index.html:144 templates/index.html:183 templates/index.html:232 +#: templates/index.html:142 templates/index.html:180 templates/index.html:228 msgid "(No)" msgstr "(暂无)" -#: templates/index.html:152 +#: templates/index.html:150 msgid "Last 10 login" msgstr "最近十次登录" -#: templates/index.html:158 +#: templates/index.html:156 msgid "Login record" msgstr "登录记录" -#: templates/index.html:159 +#: templates/index.html:157 msgid "Last 10 login records." msgstr "最近十次登录记录." -#: templates/index.html:172 templates/index.html:174 +#: templates/index.html:170 templates/index.html:172 msgid "Before" msgstr "前" -#: templates/index.html:176 +#: templates/index.html:174 msgid "Login in " msgstr "登录了" -#: templates/index.html:194 templates/index.html:209 +#: templates/index.html:191 templates/index.html:206 msgid "Top 10 users in a week" msgstr "一周Top10用户" -#: templates/index.html:210 +#: templates/index.html:207 msgid "User login frequency and last login record." msgstr "用户登录次数及最近一次登录记录" -#: templates/index.html:224 -msgid "The last time logged on to the host" -msgstr "最近一次登录主机" - -#: templates/index.html:268 +#: templates/index.html:264 msgid "Monthly data overview" msgstr "月数据总览" -#: templates/index.html:269 +#: templates/index.html:265 msgid "History summary in one month" msgstr "一个月内历史汇总" -#: templates/index.html:277 templates/index.html:301 +#: templates/index.html:273 templates/index.html:297 msgid "Login count" msgstr "登录次数" -#: templates/index.html:277 templates/index.html:308 +#: templates/index.html:273 templates/index.html:304 msgid "Active users" msgstr "活跃用户" -#: templates/index.html:277 templates/index.html:315 +#: templates/index.html:273 templates/index.html:311 msgid "Active assets" msgstr "活跃资产" -#: templates/index.html:342 templates/index.html:392 +#: templates/index.html:338 templates/index.html:388 msgid "Monthly active users" msgstr "月活跃用户" -#: templates/index.html:342 templates/index.html:393 +#: templates/index.html:338 templates/index.html:389 msgid "Disable user" msgstr "禁用用户" -#: templates/index.html:342 templates/index.html:394 +#: templates/index.html:338 templates/index.html:390 msgid "Month not logged in user" msgstr "月未登录用户" -#: templates/index.html:368 templates/index.html:444 +#: templates/index.html:364 templates/index.html:440 msgid "Access to the source" msgstr "访问来源" -#: templates/index.html:418 templates/index.html:468 +#: templates/index.html:414 templates/index.html:464 msgid "Month is logged into the host" msgstr "月被登录主机" -#: templates/index.html:418 templates/index.html:469 +#: templates/index.html:414 templates/index.html:465 msgid "Disable host" msgstr "禁用主机" -#: templates/index.html:418 templates/index.html:470 +#: templates/index.html:414 templates/index.html:466 msgid "Month not logged on host" msgstr "月未登录主机" @@ -4559,16 +4762,34 @@ msgstr "测试成功" msgid "Test failure: Account invalid" msgstr "测试失败: 账户无效" +#: terminal/backends/command/models.py:14 +#: terminal/templates/terminal/command_list.html:110 +#: terminal/templates/terminal/command_list.html:194 +msgid "Ordinary" +msgstr "" + #: terminal/backends/command/models.py:15 +#: terminal/templates/terminal/command_list.html:111 +#: terminal/templates/terminal/command_list.html:191 +msgid "Dangerous" +msgstr "" + +#: terminal/backends/command/models.py:21 msgid "Input" msgstr "输入" -#: terminal/backends/command/models.py:17 -#: terminal/templates/terminal/command_list.html:32 +#: terminal/backends/command/models.py:23 +#: terminal/templates/terminal/command_list.html:33 #: terminal/templates/terminal/terminal_list.html:34 msgid "Session" msgstr "会话" +#: terminal/backends/command/models.py:24 +#: terminal/templates/terminal/command_list.html:29 +#: terminal/templates/terminal/command_list.html:109 +msgid "Risk level" +msgstr "" + #: terminal/forms/storage.py:41 msgid "Container name" msgstr "容器名称" @@ -4624,9 +4845,9 @@ msgid "" " " msgstr "" -#: terminal/forms/storage.py:143 xpack/plugins/cloud/models.py:303 +#: terminal/forms/storage.py:143 xpack/plugins/cloud/models.py:263 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:106 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:59 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:35 msgid "Region" msgstr "地域" @@ -4684,47 +4905,47 @@ msgstr "远端地址" msgid "HTTP Port" msgstr "HTTP端口" -#: terminal/models.py:145 +#: terminal/models.py:154 msgid "Session Online" msgstr "在线会话" -#: terminal/models.py:146 +#: terminal/models.py:155 msgid "CPU Usage" msgstr "CPU使用" -#: terminal/models.py:147 +#: terminal/models.py:156 msgid "Memory Used" msgstr "内存使用" -#: terminal/models.py:148 +#: terminal/models.py:157 msgid "Connections" msgstr "连接数" -#: terminal/models.py:149 +#: terminal/models.py:158 msgid "Threads" msgstr "线程数" -#: terminal/models.py:150 +#: terminal/models.py:159 msgid "Boot Time" msgstr "运行时间" -#: terminal/models.py:185 terminal/templates/terminal/session_list.html:135 +#: terminal/models.py:195 terminal/templates/terminal/session_list.html:135 msgid "Replay" msgstr "回放" -#: terminal/models.py:190 +#: terminal/models.py:200 terminal/templates/terminal/session_detail.html:76 msgid "Date end" msgstr "结束日期" -#: terminal/models.py:283 +#: terminal/models.py:335 msgid "Args" msgstr "参数" -#: terminal/templates/terminal/command_list.html:43 +#: terminal/templates/terminal/command_list.html:44 msgid "Export command" msgstr "导出命令" -#: terminal/templates/terminal/command_list.html:205 +#: terminal/templates/terminal/command_list.html:199 msgid "Goto" msgstr "转到" @@ -4738,40 +4959,52 @@ msgstr "创建命令存储" msgid "Create replay storage" msgstr "创建录像存储" -#: terminal/templates/terminal/session_detail.html:17 -#: terminal/views/session.py:79 +#: terminal/templates/terminal/session_commands.html:18 +#: terminal/templates/terminal/session_detail.html:18 +#: terminal/views/session.py:75 terminal/views/session.py:98 msgid "Session detail" msgstr "会话详情" -#: terminal/templates/terminal/session_detail.html:28 +#: terminal/templates/terminal/session_commands.html:29 +#: terminal/templates/terminal/session_detail.html:29 #: terminal/views/command.py:22 msgid "Command list" msgstr "命令记录列表" -#: terminal/templates/terminal/session_detail.html:67 +#: terminal/templates/terminal/session_commands.html:68 msgid "There is no command about this session" msgstr "该会话没有命令记录" -#: terminal/templates/terminal/session_detail.html:92 -msgid "Replay session" -msgstr "回放会话" - -#: terminal/templates/terminal/session_detail.html:101 -msgid "Monitor session" -msgstr "监控" - -#: terminal/templates/terminal/session_detail.html:109 -msgid "Terminate session" -msgstr "终止会话" - -#: terminal/templates/terminal/session_detail.html:144 -msgid "Terminate success" -msgstr "终断成功" - +#: terminal/templates/terminal/session_detail.html:64 #: terminal/templates/terminal/session_list.html:30 msgid "Login from" msgstr "登录来源" +#: terminal/templates/terminal/session_detail.html:94 +msgid "Replay session" +msgstr "回放会话" + +#: terminal/templates/terminal/session_detail.html:102 +msgid "Download replay" +msgstr "下载录像" + +#: terminal/templates/terminal/session_detail.html:105 +#: terminal/templates/terminal/session_list.html:137 +msgid "Download" +msgstr "下载" + +#: terminal/templates/terminal/session_detail.html:111 +msgid "Monitor session" +msgstr "监控" + +#: terminal/templates/terminal/session_detail.html:119 +msgid "Terminate session" +msgstr "终止会话" + +#: terminal/templates/terminal/session_detail.html:161 +msgid "Terminate success" +msgstr "终断成功" + #: terminal/templates/terminal/session_list.html:33 msgid "Duration" msgstr "时长" @@ -4788,14 +5021,18 @@ msgstr "确认已完成" msgid "Terminate task send, waiting ..." msgstr "终断任务已发送,请等待" -#: terminal/templates/terminal/session_list.html:141 +#: terminal/templates/terminal/session_list.html:143 msgid "Terminate" msgstr "终断" -#: terminal/templates/terminal/session_list.html:172 +#: terminal/templates/terminal/session_list.html:174 msgid "Finish session success" msgstr "标记会话完成成功" +#: terminal/templates/terminal/session_list.html:242 +msgid "Visit doc for replay play offline: " +msgstr "访问文档查看如何离线播放: " + #: terminal/templates/terminal/terminal_detail.html:13 #: terminal/views/terminal.py:62 msgid "Terminal detail" @@ -4839,7 +5076,7 @@ msgstr "接受终端注册" msgid "Info" msgstr "信息" -#: terminal/views/session.py:44 +#: terminal/views/session.py:49 msgid "Session online list" msgstr "在线会话" @@ -5026,12 +5263,7 @@ msgstr "工单详情" #: users/api/user.py:177 msgid "Could not reset self otp, use profile reset instead" -msgstr "不能再该页面重置MFA, 请去个人信息页面重置" - -#: users/forms/group.py:19 users/forms/user.py:143 users/forms/user.py:148 -#: xpack/plugins/orgs/forms.py:17 -msgid "Select users" -msgstr "选择用户" +msgstr "不能在该页面重置多因子认证, 请去个人信息页面重置" #: users/forms/profile.py:37 msgid "" @@ -5039,25 +5271,25 @@ msgid "" "in. you can also directly bind in \"personal information -> quick " "modification -> change MFA Settings\"!" msgstr "" -"启用之后您将会在下次登录时进入MFA绑定流程;您也可以在(个人信息->快速修改->更" -"改MFA设置)中直接绑定!" +"启用之后您将会在下次登录时进入多因子认证绑定流程;您也可以在(个人信息->快速" +"修改->更改多因子设置)中直接绑定!" -#: users/forms/profile.py:47 -msgid "* Enable MFA authentication to make the account more secure." -msgstr "* 启用MFA认证,使账号更加安全。" +#: users/forms/profile.py:48 +msgid "* Enable MFA to make the account more secure." +msgstr "* 启用多因子认证,使账号更加安全。" #: users/forms/profile.py:57 msgid "" "In order to protect you and your company, please keep your account, password " "and key sensitive information properly. (for example: setting complex " -"password, enabling MFA authentication)" +"password, enabling MFA)" msgstr "" "为了保护您和公司的安全,请妥善保管您的账户、密码和密钥等重要敏感信息;(如:" -"设置复杂密码,启用MFA认证)" +"设置复杂密码,并启用多因子认证)" #: users/forms/profile.py:64 users/templates/users/first_login.html:48 -#: users/templates/users/first_login.html:110 -#: users/templates/users/first_login.html:139 +#: users/templates/users/first_login.html:102 +#: users/templates/users/first_login.html:128 msgid "Finish" msgstr "完成" @@ -5103,11 +5335,11 @@ msgid "Public key should not be the same as your old one." msgstr "不能和原来的密钥相同" #: users/forms/profile.py:137 users/forms/user.py:90 -#: users/serializers/user.py:122 +#: users/serializers/user.py:131 msgid "Not a valid ssh public key" msgstr "ssh密钥不合法" -#: users/forms/user.py:27 users/models/user.py:448 +#: users/forms/user.py:27 users/models/user.py:450 #: users/templates/users/_select_user_modal.html:15 #: users/templates/users/user_detail.html:73 #: users/templates/users/user_list.html:16 @@ -5115,7 +5347,7 @@ msgstr "ssh密钥不合法" msgid "Role" msgstr "角色" -#: users/forms/user.py:31 users/models/user.py:483 +#: users/forms/user.py:31 users/models/user.py:485 #: users/templates/users/user_detail.html:89 #: users/templates/users/user_list.html:18 #: users/templates/users/user_profile.html:102 @@ -5130,7 +5362,8 @@ msgstr "复制用户公钥到这里" msgid "Join user groups" msgstr "添加到用户组" -#: users/forms/user.py:103 users/views/login.py:119 users/views/profile.py:107 +#: users/forms/user.py:103 users/views/login.py:119 +#: users/views/profile/password.py:57 msgid "* Your password does not meet the requirements" msgstr "* 您的密码不符合要求" @@ -5142,7 +5375,7 @@ msgstr "生成重置密码链接,通过邮件发送给用户" msgid "Set password" msgstr "设置密码" -#: users/forms/user.py:132 xpack/plugins/change_auth_plan/models.py:88 +#: users/forms/user.py:132 xpack/plugins/change_auth_plan/models.py:77 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:45 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:67 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:57 @@ -5150,7 +5383,7 @@ msgstr "设置密码" msgid "Password strategy" msgstr "密码策略" -#: users/models/user.py:142 users/models/user.py:576 +#: users/models/user.py:142 users/models/user.py:591 msgid "Administrator" msgstr "管理员" @@ -5171,23 +5404,23 @@ msgstr "组织审计员" msgid "Force enable" msgstr "强制启用" -#: users/models/user.py:428 +#: users/models/user.py:429 msgid "Local" msgstr "数据库" -#: users/models/user.py:451 +#: users/models/user.py:453 msgid "Avatar" msgstr "头像" -#: users/models/user.py:454 users/templates/users/user_detail.html:68 +#: users/models/user.py:456 users/templates/users/user_detail.html:68 msgid "Wechat" msgstr "微信" -#: users/models/user.py:487 +#: users/models/user.py:489 msgid "Date password last updated" msgstr "最后更新密码日期" -#: users/models/user.py:579 +#: users/models/user.py:594 msgid "Administrator is the super user of system" msgstr "Administrator是初始的超级管理员" @@ -5219,15 +5452,15 @@ msgstr "角色只能为 {}" msgid "Password does not match security rules" msgstr "密码不满足安全规则" -#: users/serializers/user.py:107 +#: users/serializers/user.py:116 msgid "Groups name" msgstr "用户组名" -#: users/serializers/user.py:108 +#: users/serializers/user.py:117 msgid "Source name" msgstr "用户来源名" -#: users/serializers/user.py:109 +#: users/serializers/user.py:118 msgid "Role name" msgstr "角色名" @@ -5241,7 +5474,7 @@ msgstr "安全令牌验证" #: users/templates/users/_base_otp.html:14 users/templates/users/_user.html:13 #: users/templates/users/user_profile_update.html:55 -#: xpack/plugins/cloud/models.py:146 +#: xpack/plugins/cloud/models.py:119 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:57 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:13 msgid "Account" @@ -5295,26 +5528,26 @@ msgstr "更新ssh密钥" msgid "First Login" msgstr "首次登录" -#: users/templates/users/first_login.html:72 +#: users/templates/users/first_login.html:65 msgid "I agree with the terms and conditions." msgstr "我同意条款和条件" -#: users/templates/users/first_login.html:73 +#: users/templates/users/first_login.html:66 msgid "Please choose the terms and conditions." msgstr "请选择同意条款和条件" -#: users/templates/users/first_login.html:77 +#: users/templates/users/first_login.html:70 #: users/templates/users/user_update.html:32 msgid "User auth from {}, ssh key login is not supported" msgstr "用户认证源来自 {}, 不支持使用 SSH Key 登录" -#: users/templates/users/first_login.html:104 +#: users/templates/users/first_login.html:96 msgid "Previous" 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" @@ -5324,7 +5557,7 @@ msgstr "向导" msgid " for more information" msgstr "获取更多信息" -#: users/templates/users/forgot_password.html:20 +#: users/templates/users/forgot_password.html:15 msgid "Input your email, that will send a mail to your" msgstr "输入您的邮箱, 将会发一封重置邮件到您的邮箱中" @@ -5411,11 +5644,11 @@ msgstr "最后更新密码" #: users/templates/users/user_detail.html:148 msgid "Force enabled MFA" -msgstr "强制启用MFA" +msgstr "强制启用多因子认证" #: users/templates/users/user_detail.html:165 msgid "Reset MFA" -msgstr "重置MFA" +msgstr "重置多因子认证" #: users/templates/users/user_detail.html:174 msgid "Send reset password mail" @@ -5441,7 +5674,7 @@ msgstr "解除" #: users/templates/users/user_detail.html:365 msgid "Goto profile page enable MFA" -msgstr "请去个人信息页面启用自己的MFA" +msgstr "请去个人信息页面启用自己的多因子认证" #: users/templates/users/user_detail.html:401 msgid "An e-mail has been sent to the user`s mailbox." @@ -5480,16 +5713,27 @@ msgstr "解除用户登录限制后,此用户即可正常登录" #: users/templates/users/user_detail.html:520 msgid "Reset user MFA success" -msgstr "重置用户MFA成功" +msgstr "重置用户多因子认证成功" #: users/templates/users/user_disable_mfa.html:6 -#: users/templates/users/user_password_check.html:6 +#: users/templates/users/user_otp_check_password.html:6 msgid "Authenticate" msgstr "验证身份" -#: users/templates/users/user_disable_mfa.html:32 -msgid "Unbind" -msgstr "解绑 MFA" +#: users/templates/users/user_disable_mfa.html:11 +msgid "" +"The account protection has been opened, please complete the following " +"operations according to the prompts" +msgstr "账号保护已开启,请根据提示完成以下操作" + +#: users/templates/users/user_disable_mfa.html:13 +msgid "Open Authenticator and enter the 6-bit dynamic code" +msgstr "请打开 验证器,输入6位动态码" + +#: users/templates/users/user_disable_mfa.html:23 +#: users/templates/users/user_otp_enable_bind.html:22 +msgid "Six figures" +msgstr "6位数字" #: users/templates/users/user_group_detail.html:17 #: users/templates/users/user_group_granted_asset.html:18 @@ -5506,21 +5750,10 @@ msgstr "添加用户" msgid "Create user group" msgstr "创建用户组" -#: users/templates/users/user_group_list.html:90 -#: users/templates/users/user_list.html:135 -#: users/templates/users/user_profile.html:124 -msgid "User groups" -msgstr "用户组" - #: users/templates/users/user_list.html:32 msgid "Remove selected" msgstr "批量移除" -#: users/templates/users/user_list.html:106 -#: users/templates/users/user_list.html:110 -msgid "Remove" -msgstr "移除" - #: users/templates/users/user_list.html:179 msgid "This will delete the selected users !!!" msgstr "删除选中用户 !!!" @@ -5562,48 +5795,53 @@ msgid "User is inactive" msgstr "用户已禁用" #: users/templates/users/user_otp_enable_bind.html:6 -msgid "Bind" -msgstr "绑定 MFA" +msgid "Bind one-time password authenticator" +msgstr "绑定一次性密码验证器" -#: users/templates/users/user_otp_enable_bind.html:14 +#: users/templates/users/user_otp_enable_bind.html:13 msgid "" "Use the mobile Google Authenticator application to scan the following qr " "code for a 6-bit verification code" msgstr "使用手机 Google Authenticator 应用扫描以下二维码,获取6位验证码" #: users/templates/users/user_otp_enable_install_app.html:6 -msgid "Install" +msgid "Install app" msgstr "安装应用" -#: users/templates/users/user_otp_enable_install_app.html:11 +#: users/templates/users/user_otp_enable_install_app.html:13 msgid "Download and install the Google Authenticator application on your phone" msgstr "请在手机端下载并安装 Google Authenticator 应用" -#: users/templates/users/user_otp_enable_install_app.html:14 +#: users/templates/users/user_otp_enable_install_app.html:18 msgid "Android downloads" msgstr "Android手机下载" -#: users/templates/users/user_otp_enable_install_app.html:19 +#: users/templates/users/user_otp_enable_install_app.html:23 msgid "iPhone downloads" msgstr "iPhone手机下载" -#: users/templates/users/user_otp_enable_install_app.html:22 +#: users/templates/users/user_otp_enable_install_app.html:26 msgid "" "After installation, click the next step to enter the binding page (if " "installed, go to the next step directly)." msgstr "安装完成后点击下一步进入绑定页面(如已安装,直接进入下一步" +#: users/templates/users/user_password_verify.html:8 +#: users/templates/users/user_password_verify.html:9 +msgid "Verify password" +msgstr "校验密码" + #: users/templates/users/user_profile.html:97 msgid "Administrator Settings force MFA login" -msgstr "管理员设置强制使用MFA登录" +msgstr "管理员设置强制使用多因子认证" #: users/templates/users/user_profile.html:156 msgid "Set MFA" -msgstr "设置MFA" +msgstr "设置多因子认证" #: users/templates/users/user_profile.html:178 msgid "Update MFA" -msgstr "更改MFA" +msgstr "更改多因子认证" #: users/templates/users/user_profile.html:188 msgid "Update password" @@ -5891,37 +6129,37 @@ msgstr "Token错误或失效" msgid "First login" msgstr "首次登录" -#: users/views/profile.py:71 +#: users/views/profile/base.py:47 msgid "Profile setting" msgstr "个人信息设置" -#: users/views/profile.py:91 +#: users/views/profile/otp.py:130 +msgid "MFA enable success" +msgstr "多因子认证启用成功" + +#: users/views/profile/otp.py:131 +msgid "MFA enable success, return login page" +msgstr "多因子认证启用成功,返回到登录页面" + +#: users/views/profile/otp.py:133 +msgid "MFA disable success" +msgstr "多因子认证禁用成功" + +#: users/views/profile/otp.py:134 +msgid "MFA disable success, return login page" +msgstr "多因子认证禁用成功,返回登录页面" + +#: users/views/profile/password.py:41 msgid "Password update" msgstr "密码更新" -#: users/views/profile.py:126 -msgid "Public key update" -msgstr "密钥更新" - -#: users/views/profile.py:154 +#: users/views/profile/password.py:72 msgid "Password invalid" msgstr "用户名或密码无效" -#: users/views/profile.py:265 -msgid "MFA enable success" -msgstr "MFA 绑定成功" - -#: users/views/profile.py:266 -msgid "MFA enable success, return login page" -msgstr "MFA 绑定成功,返回到登录页面" - -#: users/views/profile.py:268 -msgid "MFA disable success" -msgstr "MFA 解绑成功" - -#: users/views/profile.py:269 -msgid "MFA disable success, return login page" -msgstr "MFA 解绑成功,返回登录页面" +#: users/views/profile/pubkey.py:37 +msgid "Public key update" +msgstr "密钥更新" #: users/views/user.py:130 msgid "Bulk update user success" @@ -5943,24 +6181,10 @@ msgstr "用户授权远程应用" msgid "User granted DatabaseApp" msgstr "用户授权数据库应用" -#: xpack/plugins/change_auth_plan/forms.py:20 +#: xpack/plugins/change_auth_plan/forms.py:21 msgid "Password length" msgstr "密码长度" -#: xpack/plugins/change_auth_plan/forms.py:75 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:54 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:79 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:17 -#: xpack/plugins/cloud/forms.py:33 xpack/plugins/cloud/forms.py:87 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:37 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:69 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:16 -#: xpack/plugins/gathered_user/forms.py:13 -#: xpack/plugins/gathered_user/forms.py:41 -#: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:28 -msgid "Periodic perform" -msgstr "定时执行" - #: xpack/plugins/change_auth_plan/forms.py:79 msgid "" "Tips: The username of the user on the asset to be modified. if the user " @@ -5969,26 +6193,9 @@ msgstr "" "提示:用户名为将要修改的资产上的用户的用户名。如果用户存在,则修改密码;如果" "用户不存在,则创建用户。" -#: xpack/plugins/change_auth_plan/forms.py:83 xpack/plugins/cloud/forms.py:90 -#: xpack/plugins/gathered_user/forms.py:44 -msgid "Tips: (Units: hour)" -msgstr "提示:(单位: 时)" - -#: xpack/plugins/change_auth_plan/forms.py:84 xpack/plugins/cloud/forms.py:91 -#: xpack/plugins/gathered_user/forms.py:45 -msgid "" -"eg: Every Sunday 03:05 run <5 3 * * 0>
    Tips: Using 5 digits linux " -"crontab expressions (Online tools)
    Note: If both Regularly " -"perform and Cycle perform are set, give priority to Regularly perform" -msgstr "" -"eg:每周日 03:05 执行 <5 3 * * 0>
    提示: 使用5位 Linux crontab 表达式 <" -"分 时 日 月 星期> (在线工" -"具
    注意: 如果同时设置了定期执行和周期执行,优先使用定期执行" - #: xpack/plugins/change_auth_plan/meta.py:9 -#: xpack/plugins/change_auth_plan/models.py:116 -#: xpack/plugins/change_auth_plan/models.py:256 +#: xpack/plugins/change_auth_plan/models.py:105 +#: xpack/plugins/change_auth_plan/models.py:202 #: xpack/plugins/change_auth_plan/views.py:33 #: xpack/plugins/change_auth_plan/views.py:50 #: xpack/plugins/change_auth_plan/views.py:74 @@ -6011,57 +6218,37 @@ msgstr "所有资产使用相同的随机密码" msgid "All assets use different random password" msgstr "所有资产使用不同的随机密码" -#: xpack/plugins/change_auth_plan/models.py:78 -#: xpack/plugins/change_auth_plan/models.py:147 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:98 -#: xpack/plugins/cloud/models.py:164 xpack/plugins/cloud/models.py:218 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:88 -#: xpack/plugins/gathered_user/models.py:35 -#: xpack/plugins/gathered_user/models.py:72 -msgid "Cycle perform" -msgstr "周期执行" - -#: xpack/plugins/change_auth_plan/models.py:83 -#: xpack/plugins/change_auth_plan/models.py:145 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:90 -#: xpack/plugins/cloud/models.py:169 xpack/plugins/cloud/models.py:216 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:80 -#: xpack/plugins/gathered_user/models.py:40 -#: xpack/plugins/gathered_user/models.py:70 -msgid "Regularly perform" -msgstr "定期执行" - -#: xpack/plugins/change_auth_plan/models.py:92 +#: xpack/plugins/change_auth_plan/models.py:81 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:72 msgid "Password rules" msgstr "密码规则" -#: xpack/plugins/change_auth_plan/models.py:212 +#: xpack/plugins/change_auth_plan/models.py:158 msgid "* For security, do not change {} user's password" msgstr "* 为了安全,禁止更改 {} 用户的密码" -#: xpack/plugins/change_auth_plan/models.py:216 +#: xpack/plugins/change_auth_plan/models.py:162 msgid "Assets is empty, please add the asset" msgstr "资产为空,请添加资产" -#: xpack/plugins/change_auth_plan/models.py:260 +#: xpack/plugins/change_auth_plan/models.py:206 msgid "Change auth plan snapshot" msgstr "改密计划快照" -#: xpack/plugins/change_auth_plan/models.py:275 -#: xpack/plugins/change_auth_plan/models.py:432 +#: xpack/plugins/change_auth_plan/models.py:221 +#: xpack/plugins/change_auth_plan/models.py:378 msgid "Change auth plan execution" msgstr "改密计划执行" -#: xpack/plugins/change_auth_plan/models.py:441 +#: xpack/plugins/change_auth_plan/models.py:387 msgid "Change auth plan execution subtask" msgstr "改密计划执行子任务" -#: xpack/plugins/change_auth_plan/models.py:459 +#: xpack/plugins/change_auth_plan/models.py:405 msgid "Authentication failed" msgstr "认证失败" -#: xpack/plugins/change_auth_plan/models.py:461 +#: xpack/plugins/change_auth_plan/models.py:407 msgid "Connection timeout" msgstr "连接超时" @@ -6081,11 +6268,6 @@ msgstr "* 请输入正确的密码长度" msgid "* Password length range 6-30 bits" msgstr "* 密码长度范围 6-30 位" -#: xpack/plugins/change_auth_plan/serializers.py:97 -#: xpack/plugins/cloud/serializers.py:73 -msgid "* Please enter a valid crontab expression" -msgstr "* 请输入有效的 crontab 表达式" - #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:19 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:24 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:23 @@ -6123,10 +6305,10 @@ msgstr "执行失败" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:31 msgid "Execution list of plan" -msgstr "执行列表" +msgstr "执行历史列表" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:104 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:84 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:96 msgid "Log" msgstr "日志" @@ -6155,35 +6337,37 @@ msgstr "更新计划" msgid "Plan execution task list" msgstr "执行任务列表" -#: xpack/plugins/cloud/api.py:60 xpack/plugins/cloud/providers/base.py:93 +#: xpack/plugins/cloud/api.py:84 xpack/plugins/cloud/utils.py:37 msgid "Account unavailable" msgstr "账户无效" -#: xpack/plugins/cloud/forms.py:14 -msgid "Access Key ID" +#: xpack/plugins/cloud/forms.py:15 +msgid "Access Key" msgstr "" -#: xpack/plugins/cloud/forms.py:18 -msgid "Access Key Secret" -msgstr "" +#: xpack/plugins/cloud/forms.py:19 +#, fuzzy +#| msgid "Secret" +msgid "Secret Key" +msgstr "密文" -#: xpack/plugins/cloud/forms.py:58 +#: xpack/plugins/cloud/forms.py:56 msgid "Select account" msgstr "选择账户" -#: xpack/plugins/cloud/forms.py:64 +#: xpack/plugins/cloud/forms.py:62 msgid "Select regions" msgstr "选择地域" -#: xpack/plugins/cloud/forms.py:70 +#: xpack/plugins/cloud/forms.py:68 msgid "Select instances" msgstr "选择实例" -#: xpack/plugins/cloud/forms.py:76 +#: xpack/plugins/cloud/forms.py:74 msgid "Select node" msgstr "选择节点" -#: xpack/plugins/cloud/forms.py:82 xpack/plugins/orgs/forms.py:20 +#: xpack/plugins/cloud/forms.py:80 xpack/plugins/orgs/forms.py:20 msgid "Select admins" msgstr "选择管理员" @@ -6191,102 +6375,150 @@ msgstr "选择管理员" #: xpack/plugins/cloud/views.py:44 xpack/plugins/cloud/views.py:62 #: xpack/plugins/cloud/views.py:78 xpack/plugins/cloud/views.py:92 #: xpack/plugins/cloud/views.py:109 xpack/plugins/cloud/views.py:127 -#: xpack/plugins/cloud/views.py:143 xpack/plugins/cloud/views.py:159 -#: xpack/plugins/cloud/views.py:211 +#: xpack/plugins/cloud/views.py:143 xpack/plugins/cloud/views.py:158 +#: xpack/plugins/cloud/views.py:172 msgid "Cloud center" msgstr "云管中心" -#: xpack/plugins/cloud/models.py:52 +#: xpack/plugins/cloud/models.py:29 msgid "Available" msgstr "有效" -#: xpack/plugins/cloud/models.py:53 +#: xpack/plugins/cloud/models.py:30 msgid "Unavailable" msgstr "无效" -#: xpack/plugins/cloud/models.py:62 +#: xpack/plugins/cloud/models.py:39 #: xpack/plugins/cloud/templates/cloud/account_detail.html:51 #: xpack/plugins/cloud/templates/cloud/account_list.html:13 msgid "Provider" msgstr "云服务商" -#: xpack/plugins/cloud/models.py:65 +#: xpack/plugins/cloud/models.py:42 msgid "Access key id" msgstr "" -#: xpack/plugins/cloud/models.py:69 +#: xpack/plugins/cloud/models.py:46 msgid "Access key secret" msgstr "" -#: xpack/plugins/cloud/models.py:87 +#: xpack/plugins/cloud/models.py:64 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:26 msgid "Cloud account" msgstr "云账号" -#: xpack/plugins/cloud/models.py:149 +#: xpack/plugins/cloud/models.py:122 msgid "Regions" msgstr "地域" -#: xpack/plugins/cloud/models.py:152 +#: xpack/plugins/cloud/models.py:125 msgid "Instances" msgstr "实例" -#: xpack/plugins/cloud/models.py:175 +#: xpack/plugins/cloud/models.py:139 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:94 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:17 msgid "Date last sync" msgstr "最后同步日期" -#: xpack/plugins/cloud/models.py:186 xpack/plugins/cloud/models.py:270 +#: xpack/plugins/cloud/models.py:150 xpack/plugins/cloud/models.py:207 msgid "Sync instance task" msgstr "同步实例任务" -#: xpack/plugins/cloud/models.py:264 xpack/plugins/cloud/models.py:287 +#: xpack/plugins/cloud/models.py:202 msgid "Succeed" msgstr "成功" -#: xpack/plugins/cloud/models.py:265 -msgid "Partial succeed" -msgstr "" - -#: xpack/plugins/cloud/models.py:280 xpack/plugins/cloud/models.py:312 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:66 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:63 +#: xpack/plugins/cloud/models.py:217 xpack/plugins/cloud/models.py:272 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:41 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:38 msgid "Date sync" msgstr "同步日期" -#: xpack/plugins/cloud/models.py:288 -msgid "Exist" -msgstr "存在" +#: xpack/plugins/cloud/models.py:245 +msgid "Unsync" +msgstr "未同步" -#: xpack/plugins/cloud/models.py:293 +#: xpack/plugins/cloud/models.py:246 xpack/plugins/cloud/models.py:247 +msgid "Synced" +msgstr "已同步" + +#: xpack/plugins/cloud/models.py:248 +msgid "Released" +msgstr "已释放" + +#: xpack/plugins/cloud/models.py:253 msgid "Sync task" msgstr "同步任务" -#: xpack/plugins/cloud/models.py:297 +#: xpack/plugins/cloud/models.py:257 msgid "Sync instance task history" msgstr "同步实例任务历史" -#: xpack/plugins/cloud/models.py:300 +#: xpack/plugins/cloud/models.py:260 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:114 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:58 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:34 msgid "Instance" msgstr "实例" -#: xpack/plugins/cloud/providers/aliyun.py:14 -msgid "Aliyun" +#: xpack/plugins/cloud/providers/aliyun.py:16 +msgid "Alibaba Cloud" msgstr "阿里云" -#: xpack/plugins/cloud/providers/aws.py:11 -msgid "AWS (China)" -msgstr "AWS (中国)" - -#: xpack/plugins/cloud/providers/aws.py:12 +#: xpack/plugins/cloud/providers/aws.py:14 msgid "AWS (International)" msgstr "AWS (国际)" +#: xpack/plugins/cloud/providers/aws_china.py:9 +msgid "AWS (China)" +msgstr "AWS (中国)" + +#: xpack/plugins/cloud/providers/huaweicloud.py:13 +msgid "Huawei Cloud" +msgstr "华为云" + +#: xpack/plugins/cloud/providers/huaweicloud.py:16 +msgid "CN North-Beijing4" +msgstr "华北-北京4" + +#: xpack/plugins/cloud/providers/huaweicloud.py:17 +msgid "CN East-Shanghai1" +msgstr "华东-上海1" + +#: xpack/plugins/cloud/providers/huaweicloud.py:18 +msgid "CN East-Shanghai2" +msgstr "华东-上海2" + +#: xpack/plugins/cloud/providers/huaweicloud.py:19 +msgid "CN South-Guangzhou" +msgstr "华南-广州" + +#: xpack/plugins/cloud/providers/huaweicloud.py:20 +msgid "CN Southwest-Guiyang1" +msgstr "西南-贵阳1" + +#: xpack/plugins/cloud/providers/huaweicloud.py:21 +msgid "AP-Hong-Kong" +msgstr "亚太-香港" + +#: xpack/plugins/cloud/providers/huaweicloud.py:22 +msgid "AP-Bangkok" +msgstr "亚太-曼谷" + +#: xpack/plugins/cloud/providers/huaweicloud.py:23 +msgid "AP-Singapore" +msgstr "亚太-新加坡" + +#: xpack/plugins/cloud/providers/huaweicloud.py:24 +msgid "AF-Johannesburg" +msgstr "非洲-约翰内斯堡" + +#: xpack/plugins/cloud/providers/huaweicloud.py:25 +msgid "LA-Santiago" +msgstr "拉美-圣地亚哥" + #: xpack/plugins/cloud/providers/qcloud.py:14 -msgid "Qcloud" +msgid "Tencent Cloud" msgstr "腾讯云" #: xpack/plugins/cloud/templates/cloud/account_detail.html:17 @@ -6321,14 +6553,14 @@ msgstr "同步任务详情" #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:20 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:23 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:21 -#: xpack/plugins/cloud/views.py:160 +#: xpack/plugins/cloud/views.py:159 msgid "Sync task history" msgstr "同步历史列表" #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:23 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:26 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:24 -#: xpack/plugins/cloud/views.py:212 +#: xpack/plugins/cloud/views.py:173 msgid "Sync instance list" msgstr "同步实例列表" @@ -6341,21 +6573,21 @@ msgstr "手动执行任务" msgid "Sync success" msgstr "同步成功" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:60 -msgid "Total count" -msgstr "总数" +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:36 +msgid "New count" +msgstr "新增" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:61 -msgid "Succeed count" -msgstr "成功" +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:37 +msgid "Unsync count" +msgstr "未同步" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:62 -msgid "Failed count" -msgstr "失败" +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:38 +msgid "Synced count" +msgstr "已同步" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:63 -msgid "Exist count" -msgstr "存在" +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:39 +msgid "Released count" +msgstr "已释放" #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:5 msgid "Create sync instance task" @@ -6369,8 +6601,6 @@ msgstr "执行次数" msgid "Instance count" msgstr "实例个数" -# msgid "Sync success" -# msgstr "同步成功" #: xpack/plugins/cloud/views.py:63 msgid "Update account" msgstr "更新账户" @@ -6395,25 +6625,20 @@ msgstr "更新同步实例任务" msgid "Gathered user" msgstr "收集用户" -#: xpack/plugins/gathered_user/models.py:33 -#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:18 -msgid "Periodic" -msgstr "定时执行" - -#: xpack/plugins/gathered_user/models.py:57 +#: xpack/plugins/gathered_user/models.py:39 #: xpack/plugins/gathered_user/templates/gathered_user/gathered_user_list.html:13 msgid "Gather user task" msgstr "收集用户任务" -#: xpack/plugins/gathered_user/models.py:137 +#: xpack/plugins/gathered_user/models.py:73 msgid "Task" msgstr "任务" -#: xpack/plugins/gathered_user/models.py:149 +#: xpack/plugins/gathered_user/models.py:85 msgid "gather user task execution" msgstr "收集用户执行" -#: xpack/plugins/gathered_user/models.py:155 +#: xpack/plugins/gathered_user/models.py:91 msgid "Assets is empty, please change nodes" msgstr "资产为空,请更改节点" @@ -6426,6 +6651,10 @@ msgstr "资产用户" msgid "Create task" msgstr "创建任务" +#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:18 +msgid "Periodic" +msgstr "定时执行" + #: xpack/plugins/gathered_user/views.py:22 msgid "Gathered user list" msgstr "收集用户列表" @@ -6441,8 +6670,8 @@ msgstr "登录页面标题" #: xpack/plugins/interface/forms.py:19 msgid "" "Tips: This will be displayed on the enterprise user login page. (eg: Welcome " -"to the Jumpserver open source fortress)" -msgstr "提示:将会显示在企业版用户登录页面(eg: 欢迎使用Jumpserver开源堡垒机)" +"to the JumpServer open source fortress)" +msgstr "提示:将会显示在企业版用户登录页面(eg: 欢迎使用JumpServer开源堡垒机)" #: xpack/plugins/interface/forms.py:25 xpack/plugins/interface/models.py:19 msgid "Image of login page" @@ -6650,7 +6879,7 @@ msgstr "密码匣子" msgid "Import vault" msgstr "导入密码" -#: xpack/plugins/vault/templates/vault/vault.html:66 +#: xpack/plugins/vault/templates/vault/vault.html:64 msgid "vault" msgstr "密码匣子" @@ -6662,6 +6891,93 @@ msgstr "密码匣子" msgid "vault create" msgstr "创建" +#~ msgid "Exist" +#~ msgstr "已存在" + +#~ msgid "Absent" +#~ msgstr "不存在" + +#~ msgid "Total count" +#~ msgstr "总数" + +#~ msgid "Failed count" +#~ msgstr "失败" + +#~ msgid "Exist count" +#~ msgstr "已存在" + +#~ msgid "Absent count" +#~ msgstr "不存在" + +#~ msgid "Succeed count" +#~ msgstr "成功" + +#~ msgid "Interval" +#~ msgstr "间隔" + +#~ msgid "Crontab" +#~ msgstr "Crontab" + +#~ msgid "5 * * * *" +#~ msgstr "5 * * * *" + +#~ msgid "Aliyun" +#~ msgstr "阿里云" + +#~ msgid "Qcloud" +#~ msgstr "腾讯云" + +#~ msgid "History detail of" +#~ msgstr "执行历史详情" + +#~ msgid "History of " +#~ msgstr "执行历史" + +#~ msgid "Assets count: {}" +#~ msgstr "资产数量" + +#~ msgid "Assets of " +#~ msgstr "资产" + +#~ msgid "MFA authentication failed" +#~ msgstr "多因子认证失败" + +#~ msgid "MFA Secondary certification" +#~ msgstr "MFA 二次认证" + +#~ msgid "Unbind" +#~ msgstr "解绑" + +#~ msgid "Bind" +#~ msgstr "绑定" + +#~ msgid "Have child node, cancel" +#~ msgstr "存在子节点,不能删除" + +#~ msgid "Have assets, cancel" +#~ msgstr "存在资产,不能删除" + +#~ msgid "Add to node" +#~ msgstr "添加到节点" + +#~ msgid "Test ldap success" +#~ msgstr "连接LDAP成功" + +#~ msgid " Top 5 Active user" +#~ msgstr "活跃用户Top5" + +#~ msgid "The last time logged on to the host" +#~ msgstr "最近一次登录主机" + +#~ msgid "No assets matched related system user protocol, stop task" +#~ msgstr "没有匹配到与系统用户协议相关的资产,结束任务" + +#~ msgid "Run history" +#~ msgstr "执行历史" + +#~ msgid "Task run history" +#~ msgstr "执行历史" + #~ msgid "Unlimited" #~ msgstr "无限制" @@ -6708,11 +7024,11 @@ msgstr "创建" #~ msgstr "导入用户" #~ msgid "" -#~ "Jumpserver is an open source desktop system developed using Python and " +#~ "JumpServer is an open source desktop system developed using Python and " #~ "Django that helps Internet businesses with efficient users, assets, " #~ "permissions, and audit management" #~ msgstr "" -#~ "Jumpserver是一款使用Python, Django开发的开源跳板机系统, 助力互联网企业高" +#~ "JumpServer是一款使用Python, Django开发的开源跳板机系统, 助力互联网企业高" #~ "效 用户、资产、权限、审计 管理" #~ msgid "" @@ -6774,9 +7090,6 @@ msgstr "创建" #~ msgid "Create succeed" #~ msgstr "创建成功" -#~ msgid "Delete succeed" -#~ msgstr "删除成功" - #~ msgid "Tips: If there are multiple hosts, separate them with a comma (,)" #~ msgstr "提示: 如果有多台主机,请使用逗号 ( , ) 进行分割" @@ -7044,9 +7357,6 @@ msgstr "创建" #~ msgid "Template" #~ msgstr "模板" -#~ msgid "Download" -#~ msgstr "下载" - #~ msgid "Asset csv file" #~ msgstr "资产csv文件" @@ -7065,9 +7375,6 @@ msgstr "创建" #~ msgid "Beijing Duizhan Tech, Inc." #~ msgstr "北京堆栈科技有限公司" -#~ msgid "Sync User" -#~ msgstr "同步用户" - #~ msgid "" #~ "Import {} users successfully;import {} users failed, Because’TypeError' " #~ "object has no attribute 'keys'" @@ -7076,8 +7383,8 @@ msgstr "创建" #~ msgid "Invalid private key" #~ msgstr "ssh密钥不合法" -#~ msgid "Login Jumpserver" -#~ msgstr "登录 Jumpserver" +#~ msgid "Login JumpServer" +#~ msgstr "登录 JumpServer" #~ msgid "Valid" #~ msgstr "账户状态" @@ -7161,6 +7468,3 @@ msgstr "创建" #~ msgid "Clear" #~ msgstr "清除" - -#~ msgid "MFA setting" -#~ msgstr "MFA 设置" diff --git a/apps/locale/zh/LC_MESSAGES/djangojs.mo b/apps/locale/zh/LC_MESSAGES/djangojs.mo index 24e68caf523648ed333a85c565401a6fbac6a37e..4bd390695a945e5f13744670c777354e7d85cc70 100644 GIT binary patch delta 312 zcmXZWzY76j7zgm@kRO*HB}y1940QG0p`77T$Y8xdGq6mDP<9-({S9Y&x7-NWB7 z4omWX-e9|IAI_0m@;>d^`Ub>PEs2^C`;-6a F{Q~9OCL#a; delta 273 zcmXZWKMnyw6oB!!OV;kjzlh1o5`~h4LM73PBe(!}(Cr1pDRc^Aqfprch)$u=XjN*3 zZ+O*j^1hkOdzhoyx11z$L{^?iQ$#iekve8L#2b<%@c&lT2#d_yIKm!IaG`yx{h*%J z3kKY~V*{VQB)`K)2Zm}xA1gRT`_T+zoMRai?BW{jf+s9thIa8Q*3b?A?~U3~2e_n< N!!&kx`Sk6*a$nFs8a@C3 diff --git a/apps/ops/ansible/runner.py b/apps/ops/ansible/runner.py index b6c6b8ee1..4486bdf1a 100644 --- a/apps/ops/ansible/runner.py +++ b/apps/ops/ansible/runner.py @@ -55,7 +55,7 @@ def get_default_options(): return options -# Jumpserver not use playbook +# JumpServer not use playbook class PlayBookRunner: """ 用于执行AnsiblePlaybook的接口.简化Playbook对象的使用. diff --git a/apps/ops/api/adhoc.py b/apps/ops/api/adhoc.py index 38c59d701..5f7c8318e 100644 --- a/apps/ops/api/adhoc.py +++ b/apps/ops/api/adhoc.py @@ -9,9 +9,9 @@ from django.db.models import Count, Q from common.permissions import IsOrgAdmin from common.serializers import CeleryTaskSerializer from orgs.utils import current_org -from ..models import Task, AdHoc, AdHocRunHistory +from ..models import Task, AdHoc, AdHocExecution from ..serializers import TaskSerializer, AdHocSerializer, \ - AdHocRunHistorySerializer + AdHocExecutionSerializer from ..tasks import run_ansible_task __all__ = [ @@ -28,11 +28,7 @@ class TaskViewSet(viewsets.ModelViewSet): def get_queryset(self): queryset = super().get_queryset() - if current_org.is_real(): - queryset = queryset.filter(created_by=current_org.id) - else: - queryset = queryset.filter(created_by='') - queryset = queryset.select_related('latest_history') + queryset = queryset.select_related('latest_execution') return queryset @@ -61,8 +57,8 @@ class AdHocViewSet(viewsets.ModelViewSet): class AdHocRunHistoryViewSet(viewsets.ModelViewSet): - queryset = AdHocRunHistory.objects.all() - serializer_class = AdHocRunHistorySerializer + queryset = AdHocExecution.objects.all() + serializer_class = AdHocExecutionSerializer permission_classes = (IsOrgAdmin,) def get_queryset(self): diff --git a/apps/ops/api/command.py b/apps/ops/api/command.py index f4deecc1a..48ead8f30 100644 --- a/apps/ops/api/command.py +++ b/apps/ops/api/command.py @@ -8,7 +8,7 @@ from django.conf import settings from orgs.mixins.api import RootOrgViewMixin from common.permissions import IsValidUser -from perms.utils import AssetPermissionUtilV2 +from perms.utils import AssetPermissionUtil from ..models import CommandExecution from ..serializers import CommandExecutionSerializer from ..tasks import run_command_execution @@ -27,7 +27,7 @@ class CommandExecutionViewSet(RootOrgViewMixin, viewsets.ModelViewSet): data = serializer.validated_data assets = data["hosts"] system_user = data["run_as"] - util = AssetPermissionUtilV2(self.request.user) + util = AssetPermissionUtil(self.request.user) util.filter_permissions(system_users=system_user.id) permed_assets = util.get_assets().filter(id__in=[a.id for a in assets]) invalid_assets = set(assets) - set(permed_assets) diff --git a/apps/ops/inventory.py b/apps/ops/inventory.py index ffd7e8619..59179b5c7 100644 --- a/apps/ops/inventory.py +++ b/apps/ops/inventory.py @@ -72,8 +72,8 @@ class JMSBaseInventory(BaseInventory): class JMSInventory(JMSBaseInventory): """ - JMS Inventory is the manager with jumpserver assets, so you can - write you own manager, construct you inventory, + JMS Inventory is the inventory with jumpserver assets, so you can + write you own inventory, construct you inventory, user_info is obtained from admin_user or asset_user """ def __init__(self, assets, run_as_admin=False, run_as=None, become_info=None): @@ -110,7 +110,7 @@ class JMSInventory(JMSBaseInventory): try: asset = self.assets.get(id=host.get('id')) manager = AssetUserManager() - run_user = manager.get(self.run_as, asset) + run_user = manager.get_latest(username=self.run_as, asset=asset) except Exception as e: logger.error(e, exc_info=True) return {} @@ -120,7 +120,7 @@ class JMSInventory(JMSBaseInventory): class JMSCustomInventory(JMSBaseInventory): """ - JMS Custom Inventory is the manager with jumpserver assets, + JMS Custom Inventory is the inventory with jumpserver assets, user_info is obtained from custom parameter """ diff --git a/apps/ops/migrations/0011_auto_20200106_1534.py b/apps/ops/migrations/0011_auto_20200106_1534.py new file mode 100644 index 000000000..0dba0160e --- /dev/null +++ b/apps/ops/migrations/0011_auto_20200106_1534.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.7 on 2020-01-06 07:34 + +import common.fields.model +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ops', '0010_auto_20191217_1758'), + ] + + operations = [ + migrations.AlterField( + model_name='adhoc', + name='become', + field=common.fields.model.EncryptJsonDictCharField(blank=True, default='', max_length=1024, null=True, verbose_name='Become'), + ), + ] diff --git a/apps/ops/migrations/0012_auto_20200108_1659.py b/apps/ops/migrations/0012_auto_20200108_1659.py new file mode 100644 index 000000000..d12bf4576 --- /dev/null +++ b/apps/ops/migrations/0012_auto_20200108_1659.py @@ -0,0 +1,22 @@ +# Generated by Django 2.2.7 on 2020-01-08 08:59 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ops', '0011_auto_20200106_1534'), + ] + + operations = [ + migrations.RenameField( + model_name='task', + old_name='created_by', + new_name='org_id', + ), + migrations.AlterUniqueTogether( + name='task', + unique_together={('name', 'org_id')}, + ), + ] diff --git a/apps/ops/migrations/0013_auto_20200108_1706.py b/apps/ops/migrations/0013_auto_20200108_1706.py new file mode 100644 index 000000000..e6ce99562 --- /dev/null +++ b/apps/ops/migrations/0013_auto_20200108_1706.py @@ -0,0 +1,28 @@ +# Generated by Django 2.2.7 on 2020-01-08 09:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ops', '0012_auto_20200108_1659'), + ] + + operations = [ + migrations.AddField( + model_name='adhoc', + name='org_id', + field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), + ), + migrations.AddField( + model_name='adhocrunhistory', + name='org_id', + field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), + ), + migrations.AlterField( + model_name='task', + name='org_id', + field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), + ), + ] diff --git a/apps/ops/migrations/0014_auto_20200108_1749.py b/apps/ops/migrations/0014_auto_20200108_1749.py new file mode 100644 index 000000000..a9b184e5c --- /dev/null +++ b/apps/ops/migrations/0014_auto_20200108_1749.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.7 on 2020-01-08 09:49 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ops', '0013_auto_20200108_1706'), + ] + + operations = [ + migrations.RenameModel( + old_name='AdHocRunHistory', + new_name='AdHocExecution', + ), + ] diff --git a/apps/ops/migrations/0015_auto_20200108_1809.py b/apps/ops/migrations/0015_auto_20200108_1809.py new file mode 100644 index 000000000..200d9b7e4 --- /dev/null +++ b/apps/ops/migrations/0015_auto_20200108_1809.py @@ -0,0 +1,33 @@ +# Generated by Django 2.2.7 on 2020-01-08 10:09 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('ops', '0014_auto_20200108_1749'), + ] + + operations = [ + migrations.RenameField( + model_name='task', + old_name='latest_history', + new_name='latest_execution', + ), + migrations.AlterField( + model_name='adhocexecution', + name='adhoc', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='execution', to='ops.AdHoc'), + ), + migrations.AlterField( + model_name='adhocexecution', + name='task', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='execution', to='ops.Task'), + ), + migrations.AlterModelTable( + name='adhocexecution', + table='ops_adhoc_execution', + ), + ] diff --git a/apps/ops/migrations/0016_commandexecution_org_id.py b/apps/ops/migrations/0016_commandexecution_org_id.py new file mode 100644 index 000000000..f034a4f90 --- /dev/null +++ b/apps/ops/migrations/0016_commandexecution_org_id.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.10 on 2020-02-27 09:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ops', '0015_auto_20200108_1809'), + ] + + operations = [ + migrations.AddField( + model_name='commandexecution', + name='org_id', + field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), + ), + ] diff --git a/apps/ops/migrations/0017_auto_20200306_1747.py b/apps/ops/migrations/0017_auto_20200306_1747.py new file mode 100644 index 000000000..8eb64257c --- /dev/null +++ b/apps/ops/migrations/0017_auto_20200306_1747.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.10 on 2020-03-06 09:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ops', '0016_commandexecution_org_id'), + ] + + operations = [ + migrations.AlterField( + model_name='task', + name='crontab', + field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Regularly perform'), + ), + migrations.AlterField( + model_name='task', + name='interval', + field=models.IntegerField(blank=True, default=24, null=True, verbose_name='Cycle perform'), + ), + ] diff --git a/apps/ops/mixin.py b/apps/ops/mixin.py new file mode 100644 index 000000000..d3d397220 --- /dev/null +++ b/apps/ops/mixin.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +# +import abc +import uuid +from django.utils.translation import ugettext_lazy as _ +from django.db import models +from django import forms +from rest_framework import serializers + +from .celery.utils import ( + create_or_update_celery_periodic_tasks, disable_celery_periodic_task, + delete_celery_periodic_task, +) + +__all__ = [ + 'PeriodTaskModelMixin', 'PeriodTaskSerializerMixin', + 'PeriodTaskFormMixin', +] + + +class PeriodTaskModelMixin(models.Model): + id = models.UUIDField(default=uuid.uuid4, primary_key=True) + name = models.CharField( + max_length=128, unique=False, verbose_name=_("Name") + ) + is_periodic = models.BooleanField(default=False) + interval = models.IntegerField( + default=24, null=True, blank=True, + verbose_name=_("Cycle perform"), + ) + crontab = models.CharField( + null=True, blank=True, max_length=128, + verbose_name=_("Regularly perform"), + ) + + @abc.abstractmethod + def get_register_task(self): + period_name, task, args, kwargs = None, None, (), {} + return period_name, task, args, kwargs + + @property + def interval_ratio(self): + return 3600, 'h' + + @property + def interval_display(self): + unit = self.interval_ratio[1] + if not self.interval: + return '' + return '{} {}'.format(self.interval, unit) + + def set_period_schedule(self): + name, task, args, kwargs = self.get_register_task() + if not self.is_periodic: + disable_celery_periodic_task(name) + return + + crontab = interval = None + if self.crontab: + crontab = self.crontab + elif self.interval: + interval = self.interval * self.interval_ratio[0] + + tasks = { + name: { + 'task': task, + 'interval': interval, + 'crontab': crontab, + 'args': args, + 'kwargs': kwargs, + 'enabled': True, + } + } + create_or_update_celery_periodic_tasks(tasks) + + def save(self, **kwargs): + instance = super().save(**kwargs) + self.set_period_schedule() + return instance + + def delete(self, using=None, keep_parents=False): + name = self.get_register_task()[0] + instance = super().delete(using=using, keep_parents=keep_parents) + delete_celery_periodic_task(name) + return instance + + @property + def periodic_display(self): + if self.is_periodic and self.crontab: + return _('Regularly perform') + " ( {} )".format(self.crontab) + if self.is_periodic and self.interval: + return _('Cycle perform') + " ( {} h )".format(self.interval) + return '-' + + @property + def schedule(self): + from django_celery_beat.models import PeriodicTask + try: + return PeriodicTask.objects.get(name=str(self)) + except PeriodicTask.DoesNotExist: + return None + + class Meta: + abstract = True + + +class PeriodTaskSerializerMixin(serializers.Serializer): + is_periodic = serializers.BooleanField(default=False, label=_("Periodic perform")) + crontab = serializers.CharField( + max_length=128, allow_blank=True, + allow_null=True, required=False, label=_('Regularly perform') + ) + interval = serializers.IntegerField(allow_null=True, required=False) + + INTERVAL_MAX = 65535 + INTERVAL_MIN = 1 + + def validate_crontab(self, crontab): + if not crontab: + return crontab + if isinstance(crontab, str) and len(crontab.strip().split()) != 5: + msg = _('* Please enter a valid crontab expression') + raise serializers.ValidationError(msg) + return crontab + + def validate_interval(self, interval): + if not interval: + return interval + msg = _("Range {} to {}").format(self.INTERVAL_MIN, self.INTERVAL_MAX) + if interval > self.INTERVAL_MAX or interval < self.INTERVAL_MIN: + raise serializers.ValidationError(msg) + return interval + + def validate_is_periodic(self, ok): + if not ok: + return ok + crontab = self.initial_data.get('crontab') + interval = self.initial_data.get('interval') + if ok and not any([crontab, interval]): + msg = _("Require periodic or regularly perform setting") + raise serializers.ValidationError(msg) + return ok + + +class PeriodTaskFormMixin(forms.Form): + is_periodic = forms.BooleanField( + initial=True, required=False, label=_('Periodic perform') + ) + crontab = forms.CharField( + max_length=128, required=False, label=_('Regularly perform'), + help_text=_("eg: Every Sunday 03:05 run <5 3 * * 0>
    " + "Tips: " + "Using 5 digits linux crontab expressions " + " " + "(Online tools)
    " + "Note: " + "If both Regularly perform and Cycle perform are set, " + "give priority to Regularly perform"), + ) + interval = forms.IntegerField( + required=False, initial=24, + help_text=_('Tips: (Units: hour)'), label=_("Cycle perform"), + ) + + def get_initial_for_field(self, field, field_name): + """ + Return initial data for field on form. Use initial data from the form + or the field, in that order. Evaluate callable values. + """ + if field_name not in ['is_periodic', 'crontab', 'interval']: + return super().get_initial_for_field(field, field_name) + instance = getattr(self, 'instance', None) + if instance is None: + return super().get_initial_for_field(field, field_name) + init_attr_name = field_name + '_initial' + value = getattr(self, init_attr_name, None) + if value is None: + return super().get_initial_for_field(field, field_name) + return value + + diff --git a/apps/ops/models/adhoc.py b/apps/ops/models/adhoc.py index 73dfd4339..01d1e1adb 100644 --- a/apps/ops/models/adhoc.py +++ b/apps/ops/models/adhoc.py @@ -10,45 +10,35 @@ from django.db import models from django.conf import settings from django.utils import timezone from django.utils.translation import ugettext_lazy as _ -from django_celery_beat.models import PeriodicTask from common.utils import get_logger, lazyproperty from common.fields.model import ( JsonListTextField, JsonDictCharField, EncryptJsonDictCharField, JsonDictTextField, ) -from orgs.utils import set_to_root_org, get_current_org, set_current_org -from ..celery.utils import ( - delete_celery_periodic_task, create_or_update_celery_periodic_tasks, - disable_celery_periodic_task -) +from orgs.mixins.models import OrgModelMixin from ..ansible import AdHocRunner, AnsibleError from ..inventory import JMSInventory +from ..mixin import PeriodTaskModelMixin -__all__ = ["Task", "AdHoc", "AdHocRunHistory"] +__all__ = ["Task", "AdHoc", "AdHocExecution"] logger = get_logger(__file__) -class Task(models.Model): +class Task(PeriodTaskModelMixin, OrgModelMixin): """ This task is different ansible task, Task like 'push system user', 'get asset info' .. One task can have some versions of adhoc, run a task only run the latest version adhoc """ - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField(max_length=128, verbose_name=_('Name')) - interval = models.IntegerField(verbose_name=_("Interval"), null=True, blank=True, help_text=_("Units: seconds")) - crontab = models.CharField(verbose_name=_("Crontab"), null=True, blank=True, max_length=128, help_text=_("5 * * * *")) - is_periodic = models.BooleanField(default=False) callback = models.CharField(max_length=128, blank=True, null=True, verbose_name=_("Callback")) # Callback must be a registered celery task is_deleted = models.BooleanField(default=False) comment = models.TextField(blank=True, verbose_name=_("Comment")) - created_by = models.CharField(max_length=128, blank=True, default='') date_created = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name=_("Date created")) date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated")) latest_adhoc = models.ForeignKey('ops.AdHoc', on_delete=models.SET_NULL, null=True, related_name='task_latest') - latest_history = models.ForeignKey('ops.AdHocRunHistory', on_delete=models.SET_NULL, null=True, related_name='task_latest') + latest_execution = models.ForeignKey('ops.AdHocExecution', on_delete=models.SET_NULL, null=True, related_name='task_latest') total_run_amount = models.IntegerField(default=0) success_run_amount = models.IntegerField(default=0) _ignore_auto_created_by = True @@ -63,29 +53,29 @@ class Task(models.Model): @property def is_success(self): - if self.latest_history: - return self.latest_history.is_success + if self.latest_execution: + return self.latest_execution.is_success else: return False @property def timedelta(self): - if self.latest_history: - return self.latest_history.timedelta + if self.latest_execution: + return self.latest_execution.timedelta else: return 0 @property def date_start(self): - if self.latest_history: - return self.latest_history.date_start + if self.latest_execution: + return self.latest_execution.date_start else: return None @property def assets_amount(self): - if self.latest_history: - return self.latest_history.hosts_amount + if self.latest_execution: + return self.latest_execution.hosts_amount return 0 def get_latest_adhoc(self): @@ -106,8 +96,8 @@ class Task(models.Model): failed = total - success return {'total': total, 'success': success, 'failed': failed} - def get_run_history(self): - return self.history.all() + def get_run_execution(self): + return self.execution.all() def run(self): latest_adhoc = self.get_latest_adhoc() @@ -116,58 +106,29 @@ class Task(models.Model): else: return {'error': 'No adhoc'} - def register_as_period_task(self): - from ..tasks import run_ansible_task - interval = None - crontab = None - - if self.interval: - interval = self.interval - elif self.crontab: - crontab = self.crontab - - tasks = { - self.__str__(): { - "task": run_ansible_task.name, - "interval": interval, - "crontab": crontab, - "args": (str(self.id),), - "kwargs": {"callback": self.callback}, - "enabled": True, - } - } - create_or_update_celery_periodic_tasks(tasks) - - def save(self, **kwargs): - instance = super().save(**kwargs) - if self.is_periodic: - self.register_as_period_task() - else: - disable_celery_periodic_task(self.__str__()) - return instance - - def delete(self, using=None, keep_parents=False): - super().delete(using=using, keep_parents=keep_parents) - delete_celery_periodic_task(self.__str__()) - @property - def schedule(self): - try: - return PeriodicTask.objects.get(name=str(self)) - except PeriodicTask.DoesNotExist: - return None + def period_key(self): + return self.__str__() + + def get_register_task(self): + from ..tasks import run_ansible_task + name = self.__str__() + task = run_ansible_task.name + args = (str(self.id),) + kwargs = {"callback": self.callback} + return name, task, args, kwargs def __str__(self): - return self.name + '@' + str(self.created_by) + return self.name + '@' + str(self.org_id) class Meta: db_table = 'ops_task' - unique_together = ('name', 'created_by') + unique_together = ('name', 'org_id') ordering = ('-date_updated',) get_latest_by = 'date_created' -class AdHoc(models.Model): +class AdHoc(OrgModelMixin): """ task: A task reference _tasks: [{'name': 'task_name', 'action': {'module': '', 'args': ''}, 'other..': ''}, ] @@ -185,7 +146,7 @@ class AdHoc(models.Model): hosts = models.ManyToManyField('assets.Asset', verbose_name=_("Host")) run_as_admin = models.BooleanField(default=False, verbose_name=_('Run as admin')) run_as = models.CharField(max_length=64, default='', blank=True, null=True, verbose_name=_('Username')) - become = EncryptJsonDictCharField(max_length=1024, default='', null=True, blank=True, verbose_name=_("Become")) + become = EncryptJsonDictCharField(max_length=1024, default='', blank=True, null=True, verbose_name=_("Become")) created_by = models.CharField(max_length=64, default='', blank=True, null=True, verbose_name=_('Create by')) date_created = models.DateTimeField(auto_now_add=True, db_index=True) @@ -217,22 +178,23 @@ class AdHoc(models.Model): hid = current_task.request.id except AttributeError: hid = str(uuid.uuid4()) - history = AdHocRunHistory( + execution = AdHocExecution( id=hid, adhoc=self, task=self.task, - task_display=str(self.task) + task_display=str(self.task), + date_start=timezone.now(), ) - history.save() - return history.start() + execution.save() + return execution.start() @property def short_id(self): return str(self.id).split('-')[-1] @property - def latest_history(self): + def latest_execution(self): try: - return self.history.all().latest() - except AdHocRunHistory.DoesNotExist: + return self.execution.all().latest() + except AdHocExecution.DoesNotExist: return None def save(self, **kwargs): @@ -261,15 +223,15 @@ class AdHoc(models.Model): get_latest_by = 'date_created' -class AdHocRunHistory(models.Model): +class AdHocExecution(OrgModelMixin): """ AdHoc running history. """ id = models.UUIDField(default=uuid.uuid4, primary_key=True) - task = models.ForeignKey(Task, related_name='history', on_delete=models.SET_NULL, null=True) + task = models.ForeignKey(Task, related_name='execution', on_delete=models.SET_NULL, null=True) task_display = models.CharField(max_length=128, blank=True, default='', verbose_name=_("Task display")) hosts_amount = models.IntegerField(default=0, verbose_name=_("Host amount")) - adhoc = models.ForeignKey(AdHoc, related_name='history', on_delete=models.SET_NULL, null=True) + adhoc = models.ForeignKey(AdHoc, related_name='execution', on_delete=models.SET_NULL, null=True) date_start = models.DateTimeField(auto_now_add=True, verbose_name=_('Start time')) date_finished = models.DateTimeField(blank=True, null=True, verbose_name=_('End time')) timedelta = models.FloatField(default=0.0, verbose_name=_('Time'), null=True) @@ -308,13 +270,9 @@ class AdHocRunHistory(models.Model): return {}, {} def start(self): - self.task.latest_history = self + self.task.latest_execution = self self.task.save() - current_org = get_current_org() - set_to_root_org() time_start = time.time() - date_start = timezone.now() - is_success = False summary = {} raw = '' @@ -322,31 +280,32 @@ class AdHocRunHistory(models.Model): date_start_s = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') print(_("{} Start task: {}").format(date_start_s, self.task.name)) raw, summary = self.start_runner() - is_success = summary.get('success', False) except Exception as e: logger.error(e, exc_info=True) raw = {"dark": {"all": str(e)}, "contacted": []} finally: + self.clean_up(summary, time_start) date_end = timezone.now() date_end_s = date_end.strftime('%Y-%m-%d %H:%M:%S') print(_("{} Task finish").format(date_end_s)) print('.\n\n.') - task = Task.objects.get(id=self.task_id) - task.total_run_amount = models.F('total_run_amount') + 1 - if is_success: - task.success_run_amount = models.F('success_run_amount') + 1 - task.save() - AdHocRunHistory.objects.filter(id=self.id).update( - date_start=date_start, - is_finished=True, - is_success=is_success, - date_finished=timezone.now(), - timedelta=time.time() - time_start, - summary=summary - ) - set_current_org(current_org) return raw, summary + def clean_up(self, summary, time_start): + is_success = summary.get('success', False) + task = Task.objects.get(id=self.task_id) + task.total_run_amount = models.F('total_run_amount') + 1 + if is_success: + task.success_run_amount = models.F('success_run_amount') + 1 + task.save() + AdHocExecution.objects.filter(id=self.id).update( + is_finished=True, + is_success=is_success, + date_finished=timezone.now(), + timedelta=time.time() - time_start, + summary=summary + ) + @property def success_hosts(self): return self.summary.get('contacted', []) @@ -359,5 +318,5 @@ class AdHocRunHistory(models.Model): return self.short_id class Meta: - db_table = "ops_adhoc_history" + db_table = "ops_adhoc_execution" get_latest_by = 'date_start' diff --git a/apps/ops/models/command.py b/apps/ops/models/command.py index 9ce44e20f..53aeff2b9 100644 --- a/apps/ops/models/command.py +++ b/apps/ops/models/command.py @@ -11,11 +11,12 @@ from django.db import models from orgs.models import Organization +from orgs.mixins.models import OrgModelMixin from ..ansible.runner import CommandRunner from ..inventory import JMSInventory -class CommandExecution(models.Model): +class CommandExecution(OrgModelMixin): id = models.UUIDField(default=uuid.uuid4, primary_key=True) hosts = models.ManyToManyField('assets.Asset') run_as = models.ForeignKey('assets.SystemUser', on_delete=models.CASCADE) @@ -80,6 +81,7 @@ class CommandExecution(models.Model): msg = _("Command `{}` is forbidden ........").format(self.command) print('\033[31m' + msg + '\033[0m') self.result = {"error": msg} + self.org_id = self.run_as.org_id self.is_finished = True self.date_finished = timezone.now() self.save() diff --git a/apps/ops/serializers/adhoc.py b/apps/ops/serializers/adhoc.py index 6a3464654..60fd39f90 100644 --- a/apps/ops/serializers/adhoc.py +++ b/apps/ops/serializers/adhoc.py @@ -3,14 +3,14 @@ from __future__ import unicode_literals from rest_framework import serializers from django.shortcuts import reverse -from ..models import Task, AdHoc, AdHocRunHistory, CommandExecution +from ..models import Task, AdHoc, AdHocExecution, CommandExecution -class AdHocRunHistorySerializer(serializers.ModelSerializer): +class AdHocExecutionSerializer(serializers.ModelSerializer): stat = serializers.SerializerMethodField() class Meta: - model = AdHocRunHistory + model = AdHocExecution fields = '__all__' @staticmethod @@ -31,7 +31,7 @@ class AdHocRunHistorySerializer(serializers.ModelSerializer): return fields -class AdHocRunHistoryExcludeResultSerializer(AdHocRunHistorySerializer): +class AdHocExecutionExcludeResultSerializer(AdHocExecutionSerializer): def get_field_names(self, declared_fields, info): fields = super().get_field_names(declared_fields, info) fields = [i for i in fields if i not in ['result', 'summary']] @@ -39,18 +39,18 @@ class AdHocRunHistoryExcludeResultSerializer(AdHocRunHistorySerializer): class TaskSerializer(serializers.ModelSerializer): - latest_history = AdHocRunHistoryExcludeResultSerializer(read_only=True) + latest_execution = AdHocExecutionExcludeResultSerializer(read_only=True) class Meta: model = Task fields = [ 'id', 'name', 'interval', 'crontab', 'is_periodic', - 'is_deleted', 'comment', 'created_by', 'date_created', - 'date_updated', 'latest_history', + 'is_deleted', 'comment', 'date_created', + 'date_updated', 'latest_execution', ] read_only_fields = [ - 'is_deleted', 'created_by', 'date_created', 'date_updated', - 'latest_adhoc', 'latest_history', 'total_run_amount', + 'is_deleted', 'date_created', 'date_updated', + 'latest_adhoc', 'latest_execution', 'total_run_amount', 'success_run_amount', ] @@ -63,11 +63,11 @@ class AdHocSerializer(serializers.ModelSerializer): fields = [ "id", "task", 'tasks', "pattern", "options", "hosts", "run_as_admin", "run_as", "become", - "created_by", "date_created", "short_id", + "date_created", "short_id", "become_display", ] read_only_fields = [ - 'created_by', 'date_created' + 'date_created' ] extra_kwargs = { "become": {'write_only': True} diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py index 9746fdbe7..33d7cb850 100644 --- a/apps/ops/tasks.py +++ b/apps/ops/tasks.py @@ -67,7 +67,7 @@ def clean_tasks_adhoc_period(): for task in tasks: adhoc = task.adhoc.all().order_by('-date_created')[5:] for ad in adhoc: - ad.history.all().delete() + ad.execution.all().delete() ad.delete() @@ -75,17 +75,11 @@ def clean_tasks_adhoc_period(): @after_app_shutdown_clean_periodic @register_as_period_task(interval=3600*24, description=_("Clean celery log period")) def clean_celery_tasks_period(): - expire_days = 30 + expire_days = settings.TASK_LOG_KEEP_DAYS logger.debug("Start clean celery task history") one_month_ago = timezone.now() - timezone.timedelta(days=expire_days) tasks = CeleryTask.objects.filter(date_start__lt=one_month_ago) - for task in tasks: - if os.path.isfile(task.full_log_path): - try: - os.remove(task.full_log_path) - except (FileNotFoundError, PermissionError): - pass - task.delete() + tasks.delete() tasks = CeleryTask.objects.filter(date_start__isnull=True) tasks.delete() command = "find %s -mtime +%s -name '*.log' -type f -exec rm -f {} \\;" % ( @@ -108,13 +102,15 @@ def create_or_update_registered_periodic_tasks(): @register_as_period_task(interval=3600) def check_server_performance_period(): usages = get_disk_usage() - usages = {path: usage for path, usage in usages.items() - if not path.startswith('/etc')} + uncheck_paths = ['/etc', '/boot'] for path, usage in usages.items(): - if usage.percent > 80: + need_check = True + for uncheck_path in uncheck_paths: + if path.startswith(uncheck_path): + need_check = False + if need_check and usage.percent > 80: send_server_performance_mail(path, usage, usages) - return @shared_task(queue="ansible") diff --git a/apps/ops/templates/ops/adhoc_detail.html b/apps/ops/templates/ops/adhoc_detail.html index 777207da4..1a28ee0e8 100644 --- a/apps/ops/templates/ops/adhoc_detail.html +++ b/apps/ops/templates/ops/adhoc_detail.html @@ -17,7 +17,7 @@ {% trans 'Version detail' %}
  • - {% trans 'Version run history' %} + {% trans 'Version run execution' %}
  • @@ -73,7 +73,7 @@ {% else %} {% trans 'Run as' %}: - {{ object.get_latest_history.date_start }} + {{ object.get_latest_execution.date_start }} {% endif %} @@ -90,23 +90,23 @@ {% trans 'Run times' %}: - {{ object.history.all | length }} + {{ object.execution.all | length }} {% trans 'Last run' %}: - {{ object.latest_history.short_id }} + {{ object.latest_execution.short_id }} {% trans 'Time delta' %}: - {{ object.latest_history.timedelta|floatformat}} s + {{ object.latest_execution.timedelta|floatformat}} s {% trans 'Is finished' %}: - {{ object.latest_history.is_finished|yesno:"Yes,No,Unkown" }} + {{ object.latest_execution.is_finished|yesno:"Yes,No,Unkown" }} {% trans 'Is success ' %}: - {{ object.latest_history.is_success|yesno:"Yes,No,Unkown" }} + {{ object.latest_execution.is_success|yesno:"Yes,No,Unkown" }} {% trans 'Tasks' %}: @@ -131,7 +131,7 @@
    - {% for host, task in object.latest_history.failed_hosts.items %} + {% for host, task in object.latest_execution.failed_hosts.items %} {% if forloop.first %} {% else %} @@ -161,7 +161,7 @@
    - {% for host in object.latest_history.success_hosts %} + {% for host in object.latest_execution.success_hosts %} {% if forloop.first %} {% else %} @@ -189,12 +189,12 @@ {% endblock %} diff --git a/apps/ops/templates/ops/adhoc_history.html b/apps/ops/templates/ops/adhoc_history.html index 8272279d4..e9662cb45 100644 --- a/apps/ops/templates/ops/adhoc_history.html +++ b/apps/ops/templates/ops/adhoc_history.html @@ -17,7 +17,7 @@ {% trans 'Version detail' %}
  • - {% trans 'Version run history' %} + {% trans 'Version run execution' %}
  • @@ -25,7 +25,7 @@
    - {% trans 'History of ' %} {{ object.task.name }}:{{ object.short_id }} + {% trans 'Executions of ' %} {{ object.task.name }}:{{ object.short_id }}
    -
    +
    - + - + + + + + {% else %} @@ -127,36 +137,75 @@ $ {{ command.input }} {% endblock %} {% block custom_foot_js %} - - + + + + } + + $(document).ready(function () { + l = $('.btn-download').ladda(); + l.click(function () { + l.ladda('start'); + interval = setInterval(getReplayDetail, 2000) + }); + var downloadDirect = getUrlParam('download'); + if (downloadDirect) { + $('.btn-download').trigger('click'); + } + }).on('click', '.btn-term', function () { + var $this = $(this); + var session_id = $this.attr('value'); + var terminal_id = $this.attr('terminal'); + alert(session_id); + var data = { + name: "kill_session", + args: session_id, + terminal: terminal_id + }; + terminateSession(data) + }) + {% endblock %} diff --git a/apps/terminal/templates/terminal/session_list.html b/apps/terminal/templates/terminal/session_list.html index eee137084..6b50bb9db 100644 --- a/apps/terminal/templates/terminal/session_list.html +++ b/apps/terminal/templates/terminal/session_list.html @@ -132,11 +132,13 @@ function initTable() { }}, {targets: 11, createdCell: function (td, cellData, rowData) { var btnGroup = ""; - var replayBtn = '{% trans "Replay" %}' - {#var replayBtn = '{% trans "Replay" %}'#} + var replayBtn = '{% trans "Replay" %}'; replayBtn = replayBtn.replace("sessionID", rowData.id); + var downloadBtn = ' {% trans "Download" %}'; + downloadBtn = downloadBtn.replace("sessionID", rowData.id); if (rowData.can_replay) { - replayBtn = replayBtn.replace("disabled", "") + replayBtn = replayBtn.replace("disabled", ""); + downloadBtn = downloadBtn.replace("disabled", ""); } var termBtn = '{% trans "Terminate" %}'; if ("{{ request.user.can_admin_current_org }}" === "True") { @@ -145,7 +147,7 @@ function initTable() { .replace("terminalID", rowData.terminal) } if (rowData.is_finished) { - btnGroup += replayBtn + btnGroup += replayBtn + downloadBtn } else { btnGroup += termBtn; } @@ -231,6 +233,19 @@ $(document).ready(function() { var replayUrl = "/luna/replay/" + sessionID; window.open(replayUrl, "height=600, width=800, top=400, left=400, toolbar=no, menubar=no, scrollbars=no, location=no, status=no"); }) +.on('click', '.btn-download', function () { + var sessionID = $(this).data("session"); + var downloadUrl = "{% url 'terminal:session-replay-download' pk=DEFAULT_PK %}" + .replace("{{ DEFAULT_PK }}", sessionID); + var hasConfirm = getCookie('replayConfirm'); + if (!hasConfirm) { + var help_text = "{% trans "Visit doc for replay play offline: " %}"; + help_text += "http://docs.jumpserver.org"; + var r = confirm(help_text); + setCookie("replayConfirm", "1") + } + window.open(downloadUrl) +}) .on("click", '#session_table_filter input', function (e) { e.preventDefault(); e.stopPropagation(); diff --git a/apps/terminal/templates/terminal/terminal_detail.html b/apps/terminal/templates/terminal/terminal_detail.html index ea0ba6614..14aff902c 100644 --- a/apps/terminal/templates/terminal/terminal_detail.html +++ b/apps/terminal/templates/terminal/terminal_detail.html @@ -38,33 +38,33 @@
    @@ -74,7 +74,7 @@ {% endblock %} diff --git a/apps/ops/templates/ops/task_detail.html b/apps/ops/templates/ops/task_detail.html index d2e46cc35..39696b3d9 100644 --- a/apps/ops/templates/ops/task_detail.html +++ b/apps/ops/templates/ops/task_detail.html @@ -21,10 +21,10 @@ {% trans 'Task versions' %}
  • - {% trans 'Run history' %} + {% trans 'Execution' %}
  • - {% trans 'Last run output' %} + {% trans 'Last execution output' %}
  • @@ -72,16 +72,16 @@
    {% trans 'Last run' %}:{{ object.latest_history.date_start }}{{ object.latest_execution.date_start }}
    {% trans 'Time delta' %}:{{ object.latest_history.timedelta|floatformat}} s{{ object.latest_execution.timedelta|floatformat}} s
    {% trans 'Is finished' %}: - {% if object.latest_history.is_finished %} + {% if object.latest_execution.is_finished %} {% trans 'Yes' %} {% else %} {% trans 'No' %} @@ -91,7 +91,7 @@
    {% trans 'Is success ' %}: - {% if object.latest_history.is_success %} + {% if object.latest_execution.is_success %} {% trans 'Yes' %} {% else %} {% trans 'No' %} @@ -121,7 +121,7 @@
    - {% for host, task in object.latest_history.failed_hosts.items %} + {% for host, task in object.latest_execution.failed_hosts.items %} {% if forloop.first %} {% else %} @@ -151,7 +151,7 @@
    - {% for host in object.latest_history.success_hosts %} + {% for host in object.latest_execution.success_hosts %} {% if forloop.first %} {% else %} @@ -179,12 +179,12 @@ diff --git a/apps/ops/templates/ops/task_history.html b/apps/ops/templates/ops/task_history.html index 5121a8045..06dc3416c 100644 --- a/apps/ops/templates/ops/task_history.html +++ b/apps/ops/templates/ops/task_history.html @@ -20,10 +20,10 @@ {% trans 'Task versions' %}
  • - {% trans 'Run history' %} + {% trans 'Execution' %}
  • - {% trans 'Last run output' %} + {% trans 'Last execution output' %}
  • @@ -31,7 +31,7 @@
    - {% trans 'History of ' %} {{ object.name }}:{{ object.short_id }} + {% trans 'Executions of ' %} {{ object.name }}:{{ object.short_id }}
    -
    +
    + @@ -60,13 +61,7 @@ - - +{% include '_filter_dropdown.html' %} {% endblock %} {% block content_bottom_left %}{% endblock %} {% block custom_foot_js %} @@ -105,6 +100,19 @@ $(document).ready(function () { table.ajax.reload(); }); }); + + var filterMenu = [ + {title: "{% trans 'User' %}", value: "user"}, + {title: "{% trans 'Asset' %}", value: "asset"}, + {title: "{% trans 'System user' %}", value: "system_user"}, + {title: "{% trans 'Command' %}", value: "input"}, + {title: "{% trans 'Risk level' %}", value: "risk_level", submenu: [ + {title: "{% trans 'Ordinary' %}", value: "0"}, + {title: "{% trans 'Dangerous' %}", value: "5"}, + ]}, + ]; + initTableFilterDropdown('#command_table_filter input', filterMenu, 15, 50) + }) .on('click', '#btn_bulk_update', function(){ // var action = $('#slct_bulk_update').val(); @@ -113,30 +121,6 @@ $(document).ready(function () { var exportPath = "{% url 'api-terminal:command-export' %}"; var url = exportPath + "?" + params; window.open(url); -}).on("click", '#command_table_filter input', function (e) { - e.preventDefault(); - e.stopPropagation(); - var offset1 = $('#command_table_filter input').offset(); - var x = offset1.left; - var y = offset1.top; - var offset = $(".search-help").parent().offset(); - x -= offset.left; - y -= offset.top; - x += 18; - y += 80; - $('.search-help').css({"top":y+"px", "left":x+"px", "position": "absolute"}); - $('.dropdown-menu.search-help').show(); -}) -.on('click', '.search-item', function (e) { - e.preventDefault(); - e.stopPropagation(); - var keyword = $("#command_table_filter input"); - var value = $(this).data('value'); - var old_value = keyword.val(); - var new_value = old_value + ' ' + value + ':'; - keyword.val(new_value.trim()); - $('.dropdown-menu.search-help').hide(); - keyword.focus() }) .on('click', 'body', function (e) { $('.dropdown-menu.search-help').hide() @@ -201,12 +185,22 @@ function initTable() { interHtml.html(data); $(td).html(interHtml); }}, - {targets: 5, createdCell: function (td, cellData) { + {targets: 2, createdCell: function (td, cellData){ + let risk; + if(cellData === 5){ + risk = "{% trans 'Dangerous' %}"; + } + else{ + risk = "{% trans 'Ordinary' %}"; + } + $(td).html(risk) + }}, + {targets: 6, createdCell: function (td, cellData) { var data = '{% trans "Goto" %}' .replace('{{ DEFAULT_PK }}', cellData); $(td).html(data); }}, - {targets: 6, createdCell: function (td, cellData) { + {targets: 7, createdCell: function (td, cellData) { var data = toSafeLocalDateStr(cellData*1000); $(td).html(data); }}, @@ -214,7 +208,8 @@ function initTable() { toggle: true, ajax_url: commandListUrl, columns: [ - {data: "id"}, {data: "input", orderable: false, width: "40%"}, {data: "user", orderable: false}, + {data: "id"}, {data: "input", orderable: false, width: "40%"}, + {data: "risk_level", orderable: false}, {data: "user", orderable: false}, {data: "asset", orderable: false}, {data: "system_user", orderable: false}, {data: "session", orderable: false}, {data: "timestamp", width: "160px", orderable: false}, ], diff --git a/apps/terminal/templates/terminal/session_commands.html b/apps/terminal/templates/terminal/session_commands.html new file mode 100644 index 000000000..3aeb2989f --- /dev/null +++ b/apps/terminal/templates/terminal/session_commands.html @@ -0,0 +1,96 @@ +{% extends 'base.html' %} +{% load static %} +{% load i18n %} +{% load common_tags %} + +{% block custom_head_css_js %} + + +{% endblock %} +{% block content %} +
    +
    +
    +
    + +
    +
    +
    +
    + {% trans 'Command list' %} +
    + + + + + + + + + + +
    +
    +
    +
    @@ -80,7 +80,7 @@ diff --git a/apps/ops/templates/ops/task_list.html b/apps/ops/templates/ops/task_list.html index 0d2095d78..6f393cb1c 100644 --- a/apps/ops/templates/ops/task_list.html +++ b/apps/ops/templates/ops/task_list.html @@ -79,10 +79,10 @@ $(document).ready(function () { ajax_url: '{% url "api-ops:task-list" %}', columns: [ {data: "id"}, {data: "name", className: "text-left"}, - {data: "latest_history", orderable: false}, - {data: "latest_history", orderable: false}, - {data: "latest_history", orderable: false}, {data: "latest_history"}, - {data: "latest_history", orderable:false}, {data: "id", orderable: false}, + {data: "latest_execution", orderable: false}, + {data: "latest_execution", orderable: false}, + {data: "latest_execution", orderable: false}, {data: "latest_execution"}, + {data: "latest_execution", orderable:false}, {data: "id", orderable: false}, ], order: [], op_html: $('#actions').html() diff --git a/apps/ops/urls/api_urls.py b/apps/ops/urls/api_urls.py index cc242f649..366524aa4 100644 --- a/apps/ops/urls/api_urls.py +++ b/apps/ops/urls/api_urls.py @@ -11,7 +11,7 @@ app_name = "ops" router = DefaultRouter() router.register(r'tasks', api.TaskViewSet, 'task') router.register(r'adhoc', api.AdHocViewSet, 'adhoc') -router.register(r'history', api.AdHocRunHistoryViewSet, 'history') +router.register(r'adhoc-executions', api.AdHocRunHistoryViewSet, 'execution') router.register(r'command-executions', api.CommandExecutionViewSet, 'command-execution') router.register(r'celery/period-tasks', api.CeleryPeriodTaskViewSet, 'celery-period-task') diff --git a/apps/ops/urls/view_urls.py b/apps/ops/urls/view_urls.py index 13759c3f2..592ae9d93 100644 --- a/apps/ops/urls/view_urls.py +++ b/apps/ops/urls/view_urls.py @@ -13,12 +13,12 @@ urlpatterns = [ path('task/', views.TaskListView.as_view(), name='task-list'), path('task//', views.TaskDetailView.as_view(), name='task-detail'), path('task//adhoc/', views.TaskAdhocView.as_view(), name='task-adhoc'), - path('task//history/', views.TaskHistoryView.as_view(), name='task-history'), + path('task//executions/', views.TaskExecutionView.as_view(), name='task-execution'), path('adhoc//', views.AdHocDetailView.as_view(), name='adhoc-detail'), - path('adhoc//history/', views.AdHocHistoryView.as_view(), name='adhoc-history'), - path('adhoc/history//', views.AdHocHistoryDetailView.as_view(), name='adhoc-history-detail'), + path('adhoc//executions/', views.AdHocExecutionView.as_view(), name='adhoc-history'), + path('adhoc/executions//', views.AdHocExecutionDetailView.as_view(), name='adhoc-execution-detail'), path('celery/task//log/', views.CeleryTaskLogView.as_view(), name='celery-task-log'), - path('command-execution/', views.CommandExecutionListView.as_view(), name='command-execution-list'), - path('command-execution/create/', views.CommandExecutionCreateView.as_view(), name='command-execution-create'), + path('command-executions/', views.CommandExecutionListView.as_view(), name='command-execution-list'), + path('command-executions/create/', views.CommandExecutionCreateView.as_view(), name='command-execution-create'), ] diff --git a/apps/ops/utils.py b/apps/ops/utils.py index 3322890f2..16ba8e648 100644 --- a/apps/ops/utils.py +++ b/apps/ops/utils.py @@ -3,37 +3,44 @@ from django.utils.translation import ugettext_lazy as _ from common.utils import get_logger, get_object_or_none from common.tasks import send_mail_async -from orgs.utils import set_to_root_org +from orgs.utils import tmp_to_org, org_aware_func + from .models import Task, AdHoc logger = get_logger(__file__) +DEFAULT_TASK_OPTIONS = { + 'timeout': 10, + 'forks': 10, +} + def get_task_by_id(task_id): return get_object_or_none(Task, id=task_id) +@org_aware_func("hosts") def update_or_create_ansible_task( - task_name, hosts, tasks, created_by, + task_name, hosts, tasks, interval=None, crontab=None, is_periodic=False, callback=None, pattern='all', options=None, run_as_admin=False, run_as=None, become_info=None, ): if not hosts or not tasks or not task_name: return None, None - set_to_root_org() + if options is None: + options = DEFAULT_TASK_OPTIONS defaults = { 'name': task_name, 'interval': interval, 'crontab': crontab, 'is_periodic': is_periodic, 'callback': callback, - 'created_by': created_by, } created = False task, ok = Task.objects.update_or_create( - defaults=defaults, name=task_name, created_by=created_by + defaults=defaults, name=task_name ) adhoc = task.get_latest_adhoc() new_adhoc = AdHoc(task=task, pattern=pattern, diff --git a/apps/ops/views/adhoc.py b/apps/ops/views/adhoc.py index 4df75305b..b8d90f092 100644 --- a/apps/ops/views/adhoc.py +++ b/apps/ops/views/adhoc.py @@ -7,13 +7,13 @@ from django.views.generic import ListView, DetailView, TemplateView from common.mixins import DatetimeSearchMixin from common.permissions import PermissionsMixin, IsOrgAdmin from orgs.utils import current_org -from ..models import Task, AdHoc, AdHocRunHistory +from ..models import Task, AdHoc, AdHocExecution __all__ = [ - 'TaskListView', 'TaskDetailView', 'TaskHistoryView', - 'TaskAdhocView', 'AdHocDetailView', 'AdHocHistoryDetailView', - 'AdHocHistoryView' + 'TaskListView', 'TaskDetailView', 'TaskExecutionView', + 'TaskAdhocView', 'AdHocDetailView', 'AdHocExecutionDetailView', + 'AdHocExecutionView' ] @@ -42,11 +42,6 @@ class TaskDetailView(PermissionsMixin, DetailView): def get_queryset(self): queryset = super().get_queryset() - # Todo: 需要整理默认组织等东西 - if current_org.is_real(): - queryset = queryset.filter(created_by=current_org.id) - else: - queryset = queryset.filter(created_by='') return queryset def get_context_data(self, **kwargs): @@ -72,7 +67,7 @@ class TaskAdhocView(PermissionsMixin, DetailView): return super().get_context_data(**kwargs) -class TaskHistoryView(PermissionsMixin, DetailView): +class TaskExecutionView(PermissionsMixin, DetailView): model = Task template_name = 'ops/task_history.html' permission_classes = [IsOrgAdmin] @@ -80,7 +75,7 @@ class TaskHistoryView(PermissionsMixin, DetailView): def get_context_data(self, **kwargs): context = { 'app': _('Ops'), - 'action': _('Task run history'), + 'action': _('Task execution list'), } kwargs.update(context) return super().get_context_data(**kwargs) @@ -100,7 +95,7 @@ class AdHocDetailView(PermissionsMixin, DetailView): return super().get_context_data(**kwargs) -class AdHocHistoryView(PermissionsMixin, DetailView): +class AdHocExecutionView(PermissionsMixin, DetailView): model = AdHoc template_name = 'ops/adhoc_history.html' permission_classes = [IsOrgAdmin] @@ -108,21 +103,21 @@ class AdHocHistoryView(PermissionsMixin, DetailView): def get_context_data(self, **kwargs): context = { 'app': _('Ops'), - 'action': _('Version run history'), + 'action': _('Version run execution'), } kwargs.update(context) return super().get_context_data(**kwargs) -class AdHocHistoryDetailView(PermissionsMixin, DetailView): - model = AdHocRunHistory +class AdHocExecutionDetailView(PermissionsMixin, DetailView): + model = AdHocExecution template_name = 'ops/adhoc_history_detail.html' permission_classes = [IsOrgAdmin] def get_context_data(self, **kwargs): context = { 'app': _('Ops'), - 'action': _('Run history detail'), + 'action': _('Execution detail'), } kwargs.update(context) return super().get_context_data(**kwargs) diff --git a/apps/ops/views/command.py b/apps/ops/views/command.py index 87e0528c6..4dfc3d2e7 100644 --- a/apps/ops/views/command.py +++ b/apps/ops/views/command.py @@ -66,10 +66,10 @@ class CommandExecutionCreateView(PermissionsMixin, TemplateView): return super().get_permissions() def get_user_system_users(self): - from perms.utils import AssetPermissionUtilV2 + from perms.utils import AssetPermissionUtil user = self.request.user with tmp_to_root_org(): - util = AssetPermissionUtilV2(user) + util = AssetPermissionUtil(user) system_users = util.get_system_users() return system_users diff --git a/apps/orgs/mixins/api.py b/apps/orgs/mixins/api.py index 64314a3f8..7695292c3 100644 --- a/apps/orgs/mixins/api.py +++ b/apps/orgs/mixins/api.py @@ -33,10 +33,10 @@ class OrgQuerySetMixin: if hasattr(self, 'swagger_fake_view'): return queryset[:1] - if hasattr(self, 'action') and self.action == 'list' and \ - hasattr(self, 'serializer_class') and \ - hasattr(self.serializer_class, 'setup_eager_loading'): - queryset = self.serializer_class.setup_eager_loading(queryset) + if hasattr(self, 'action') and self.action == 'list': + serializer_class = self.get_serializer_class() + if serializer_class and hasattr(serializer_class, 'setup_eager_loading'): + queryset = serializer_class.setup_eager_loading(queryset) return queryset diff --git a/apps/orgs/mixins/models.py b/apps/orgs/mixins/models.py index 30429b874..649c450cc 100644 --- a/apps/orgs/mixins/models.py +++ b/apps/orgs/mixins/models.py @@ -20,6 +20,18 @@ __all__ = [ class OrgManager(models.Manager): + def all_group_by_org(self): + from ..models import Organization + orgs = list(Organization.objects.all()) + orgs.append(Organization.default()) + querysets = {} + for org in orgs: + if org.is_real(): + org_id = org.id + else: + org_id = '' + querysets[org] = super(OrgManager, self).get_queryset().filter(org_id=org_id) + return querysets def get_queryset(self): queryset = super(OrgManager, self).get_queryset() diff --git a/apps/orgs/models.py b/apps/orgs/models.py index a9040b378..bae5c408c 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -99,7 +99,7 @@ class Organization(models.Model): if self.is_real(): return self.id elif self.is_root(): - return None + return self.ROOT_ID else: return '' @@ -209,3 +209,9 @@ class Organization(models.Model): def change_to(self): from .utils import set_current_org set_current_org(self) + + @classmethod + def all_orgs(cls): + orgs = list(cls.objects.all()) + orgs.append(cls.default()) + return orgs diff --git a/apps/orgs/utils.py b/apps/orgs/utils.py index 2a7cfca6b..c69af25b8 100644 --- a/apps/orgs/utils.py +++ b/apps/orgs/utils.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- # -import traceback +import uuid +from inspect import signature +from functools import wraps from werkzeug.local import LocalProxy from contextlib import contextmanager @@ -28,7 +30,7 @@ def get_org_from_request(request): def set_current_org(org): - if isinstance(org, str): + if isinstance(org, (str, uuid.UUID)): org = Organization.get_instance(org) setattr(thread_local, 'current_org_id', org.id) @@ -110,4 +112,29 @@ def filter_org_queryset(queryset): return queryset +def org_aware_func(org_arg_name): + """ + :param org_arg_name: 函数中包含org_id的对象是哪个参数 + :return: + """ + def decorate(func): + @wraps(func) + def wrapper(*args, **kwargs): + sig = signature(func) + values = sig.bind(*args, **kwargs) + org_aware_resource = values.arguments.get(org_arg_name) + if not org_aware_resource: + return func(*args, **kwargs) + if hasattr(org_aware_resource, '__getitem__'): + org_aware_resource = org_aware_resource[0] + if not hasattr(org_aware_resource, "org_id"): + print("Error: {} not has org_id attr".format(org_aware_resource)) + return func(*args, **kwargs) + with tmp_to_org(org_aware_resource.org_id): + # print("Current org id: {}".format(org_aware_resource.org_id)) + return func(*args, **kwargs) + return wrapper + return decorate + + current_org = LocalProxy(get_current_org) diff --git a/apps/perms/api/mixin.py b/apps/perms/api/mixin.py index 86e1a8c0a..cbbfa825f 100644 --- a/apps/perms/api/mixin.py +++ b/apps/perms/api/mixin.py @@ -4,7 +4,7 @@ from rest_framework.generics import get_object_or_404 from common.permissions import IsValidUser, IsOrgAdminOrAppUser from common.utils import get_logger -from orgs.utils import set_to_root_org, get_current_org, set_current_org, tmp_to_root_org +from orgs.utils import set_to_root_org, set_current_org, get_current_org from ..hands import User, UserGroup @@ -22,25 +22,15 @@ class UserPermissionMixin: def initial(self, *args, **kwargs): super().initial(*args, *kwargs) - self.current_org = get_current_org() - set_to_root_org() self.obj = self.get_obj() - # def dispatch(self, request, *args, **kwargs): - # """不能这么做,校验权限时拿不到组织了""" - # with tmp_to_root_org(): - # return super().dispatch(request, *args, **kwargs) - - # def get(self, request, *args, **kwargs): - # """有的api重写了get方法""" - # with tmp_to_root_org(): - # return super().get(request, *args, **kwargs) - def get_obj(self): user_id = self.kwargs.get('pk', '') if user_id: user = get_object_or_404(User, id=user_id) else: + self.current_org = get_current_org() + set_to_root_org() user = self.request.user return user diff --git a/apps/perms/api/user_permission/common.py b/apps/perms/api/user_permission/common.py index badd5cbbc..6af3bb6ba 100644 --- a/apps/perms/api/user_permission/common.py +++ b/apps/perms/api/user_permission/common.py @@ -11,7 +11,7 @@ from rest_framework.generics import ( from common.permissions import IsOrgAdminOrAppUser, IsOrgAdmin from common.utils import get_logger from ...utils import ( - AssetPermissionUtilV2 + AssetPermissionUtil ) from ...hands import User, Asset, SystemUser from ... import serializers @@ -51,8 +51,8 @@ class GetUserAssetPermissionActionsApi(UserAssetPermissionMixin, asset = get_object_or_404(Asset, id=asset_id) system_user = get_object_or_404(SystemUser, id=system_id) - system_users_actions = self.util.get_asset_system_users_with_actions(asset) - actions = system_users_actions.get(system_user) + system_users_actions = self.util.get_asset_system_users_id_with_actions(asset) + actions = system_users_actions.get(system_user.id) return {"actions": actions} @@ -81,9 +81,8 @@ class ValidateUserAssetPermissionApi(UserAssetPermissionMixin, APIView): asset = get_object_or_404(Asset, id=asset_id) system_user = get_object_or_404(SystemUser, id=system_id) - system_users_actions = self.util.get_asset_system_users_with_actions( - asset) - actions = system_users_actions.get(system_user) + system_users_actions = self.util.get_asset_system_users_id_with_actions(asset) + actions = system_users_actions.get(system_user.id) if actions is None: return Response({'msg': False}, status=403) if action_name in Action.value_to_choices(actions): @@ -95,7 +94,7 @@ class RefreshAssetPermissionCacheApi(RetrieveAPIView): permission_classes = (IsOrgAdmin,) def retrieve(self, request, *args, **kwargs): - AssetPermissionUtilV2.expire_all_user_tree_cache() + AssetPermissionUtil.expire_all_user_tree_cache() return Response({'msg': True}, status=200) @@ -107,11 +106,14 @@ class UserGrantedAssetSystemUsersApi(UserAssetPermissionMixin, ListAPIView): def get_queryset(self): asset_id = self.kwargs.get('asset_id') asset = get_object_or_404(Asset, id=asset_id) - system_users_with_actions = self.util.get_asset_system_users_with_actions(asset) - system_users = [] - for system_user, actions in system_users_with_actions.items(): + system_users_with_actions = self.util.get_asset_system_users_id_with_actions(asset) + system_users_id = system_users_with_actions.keys() + system_users = SystemUser.objects.filter(id__in=system_users_id)\ + .only(*self.serializer_class.Meta.only_fields) \ + .order_by('priority') + system_users = list(system_users) + for system_user in system_users: + actions = system_users_with_actions.get(system_user.id, 0) system_user.actions = actions - system_users.append(system_user) - system_users.sort(key=lambda x: x.priority) return system_users diff --git a/apps/perms/api/user_permission/mixin.py b/apps/perms/api/user_permission/mixin.py index bbc926ffe..4b0cc32a5 100644 --- a/apps/perms/api/user_permission/mixin.py +++ b/apps/perms/api/user_permission/mixin.py @@ -3,7 +3,7 @@ from common.utils import lazyproperty from common.tree import TreeNodeSerializer from ..mixin import UserPermissionMixin -from ...utils import AssetPermissionUtilV2, ParserNode +from ...utils import AssetPermissionUtil, ParserNode from ...hands import Node, Asset @@ -17,7 +17,7 @@ class UserAssetPermissionMixin(UserPermissionMixin): def util(self): cache_policy = self.get_cache_policy() system_user_id = self.request.query_params.get("system_user") - util = AssetPermissionUtilV2(self.obj, cache_policy=cache_policy) + util = AssetPermissionUtil(self.obj, cache_policy=cache_policy) if system_user_id: util.filter_permissions(system_users=system_user_id) return util diff --git a/apps/perms/api/user_permission/user_permission_assets.py b/apps/perms/api/user_permission/user_permission_assets.py index b2ed1fe65..82f46dd6f 100644 --- a/apps/perms/api/user_permission/user_permission_assets.py +++ b/apps/perms/api/user_permission/user_permission_assets.py @@ -2,9 +2,7 @@ # from django.shortcuts import get_object_or_404 -from rest_framework.generics import ( - ListAPIView, get_object_or_404 -) +from rest_framework.generics import ListAPIView from common.permissions import IsOrgAdminOrAppUser from common.utils import get_logger, timeit @@ -16,8 +14,7 @@ from .mixin import UserAssetPermissionMixin, UserAssetTreeMixin logger = get_logger(__name__) __all__ = [ - 'UserGrantedAssetsApi', - 'UserGrantedAssetsAsTreeApi', + 'UserGrantedAssetsApi', 'UserGrantedAssetsAsTreeApi', 'UserGrantedNodeAssetsApi', ] diff --git a/apps/perms/mixins.py b/apps/perms/mixins.py index 30a588ffd..98ac8bf76 100644 --- a/apps/perms/mixins.py +++ b/apps/perms/mixins.py @@ -4,70 +4,10 @@ from orgs.utils import set_to_root_org __all__ = [ - 'AssetsFilterMixin', 'ChangeOrgIfNeedMixin', + 'ChangeOrgIfNeedMixin', ] -class AssetsFilterMixin(object): - """ - 对资产进行过滤(查询,排序) - """ - - def filter_queryset(self, queryset): - queryset = self.search_assets(queryset) - queryset = self.filter_labels(queryset) - queryset = self.sort_assets(queryset) - return queryset - - def search_assets(self, queryset): - from perms.utils import is_obj_attr_has - value = self.request.query_params.get('search') - if not value: - return queryset - queryset = [asset for asset in queryset if is_obj_attr_has(asset, value)] - return queryset - - def sort_assets(self, queryset): - from perms.utils import sort_assets - order_by = self.request.query_params.get('order') - if not order_by: - order_by = 'hostname' - - if order_by.startswith('-'): - order_by = order_by.lstrip('-') - reverse = True - else: - reverse = False - - queryset = sort_assets(queryset, order_by=order_by, reverse=reverse) - return queryset - - def filter_labels(self, queryset): - from assets.models import Label - query_keys = self.request.query_params.keys() - all_label_keys = Label.objects.values_list('name', flat=True) - valid_keys = set(all_label_keys) & set(query_keys) - labels_query = {} - for key in valid_keys: - labels_query[key] = self.request.query_params.get(key) - if not labels_query: - return queryset - - labels = set() - for k, v in labels_query.items(): - label = Label.objects.filter(name=k, value=v).first() - if not label: - continue - labels.add(label) - - _queryset = [] - for asset in queryset: - _labels = set(asset.labels.all()) & set(labels) - if _labels and len(_labels) == len(set(labels)): - _queryset.append(asset) - return _queryset - - class ChangeOrgIfNeedMixin(object): @staticmethod diff --git a/apps/perms/serializers/user_permission.py b/apps/perms/serializers/user_permission.py index c194cf64a..ac248947f 100644 --- a/apps/perms/serializers/user_permission.py +++ b/apps/perms/serializers/user_permission.py @@ -27,6 +27,7 @@ class AssetSystemUserSerializer(serializers.ModelSerializer): model = SystemUser only_fields = ( 'id', 'name', 'username', 'priority', 'protocol', 'login_mode', + 'sftp_root', 'username_same_with_user', ) fields = list(only_fields) + ["actions"] read_only_fields = fields diff --git a/apps/perms/signals_handler.py b/apps/perms/signals_handler.py index 4a7fe389c..1be6ce9f4 100644 --- a/apps/perms/signals_handler.py +++ b/apps/perms/signals_handler.py @@ -5,8 +5,8 @@ from django.dispatch import receiver from common.utils import get_logger from common.decorator import on_transaction_commit -from .models import AssetPermission -from .utils.asset_permission import AssetPermissionUtilV2 +from .models import AssetPermission, RemoteAppPermission +from .utils.asset_permission import AssetPermissionUtil logger = get_logger(__file__) @@ -16,45 +16,64 @@ logger = get_logger(__file__) @on_transaction_commit def on_permission_change(sender, action='', **kwargs): logger.debug('Asset permission changed, refresh user tree cache') - AssetPermissionUtilV2.expire_all_user_tree_cache() + AssetPermissionUtil.expire_all_user_tree_cache() # Todo: 检查授权规则到期,从而修改授权规则 @receiver(m2m_changed, sender=AssetPermission.nodes.through) -def on_permission_nodes_changed(sender, instance=None, action='', **kwargs): - if action != 'post_add': +def on_permission_nodes_changed(sender, instance=None, action='', reverse=None, **kwargs): + if action != 'post_add' and reverse: return - if isinstance(instance, AssetPermission): - logger.debug("Asset permission nodes change signal received") - nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) - system_users = instance.system_users.all() - for system_user in system_users: - system_user.nodes.add(*tuple(nodes)) + logger.debug("Asset permission nodes change signal received") + nodes = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) + system_users = instance.system_users.all() + for system_user in system_users: + system_user.nodes.add(*tuple(nodes)) @receiver(m2m_changed, sender=AssetPermission.assets.through) -def on_permission_assets_changed(sender, instance=None, action='', **kwargs): - if action != 'post_add': +def on_permission_assets_changed(sender, instance=None, action='', reverse=None, **kwargs): + if action != 'post_add' and reverse: return - if isinstance(instance, AssetPermission): - logger.debug("Asset permission assets change signal received") - assets = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) - system_users = instance.system_users.all() - for system_user in system_users: - system_user.assets.add(*tuple(assets)) + logger.debug("Asset permission assets change signal received") + assets = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) + system_users = instance.system_users.all() + for system_user in system_users: + system_user.assets.add(*tuple(assets)) @receiver(m2m_changed, sender=AssetPermission.system_users.through) -def on_permission_system_users_changed(sender, instance=None, action='', **kwargs): - if action != 'post_add': +def on_asset_permission_system_users_changed(sender, instance=None, action='', + reverse=False, **kwargs): + if action != 'post_add' and reverse: return - if isinstance(instance, AssetPermission): - system_users = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) - logger.debug("Asset permission system_users change signal received") - assets = instance.assets.all().values_list('id', flat=True) - nodes = instance.nodes.all().values_list('id', flat=True) - for system_user in system_users: - system_user.nodes.add(*tuple(nodes)) - system_user.assets.add(*tuple(assets)) + logger.debug("Asset permission system_users change signal received") + system_users = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) + assets = instance.assets.all().values_list('id', flat=True) + nodes = instance.nodes.all().values_list('id', flat=True) + users = instance.users.all().values_list('id', flat=True) + groups = instance.user_groups.all().values_list('id', flat=True) + for system_user in system_users: + system_user.nodes.add(*tuple(nodes)) + system_user.assets.add(*tuple(assets)) + if system_user.username_same_with_user: + system_user.groups.add(*tuple(groups)) + system_user.users.add(*tuple(users)) + +@receiver(m2m_changed, sender=RemoteAppPermission.system_users.through) +def on_remote_app_permission_system_users_changed(sender, instance=None, + action='', reverse=False, **kwargs): + if action != 'post_add' or reverse: + return + system_users = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) + logger.debug("Remote app permission system_users change signal received") + assets = instance.remote_apps.all().values_list('asset__id', flat=True) + users = instance.users.all().values_list('id', flat=True) + groups = instance.user_groups.all().values_list('id', flat=True) + for system_user in system_users: + system_user.assets.add(*tuple(assets)) + if system_user.username_same_with_user: + system_user.groups.add(*tuple(groups)) + system_user.users.add(*tuple(users)) diff --git a/apps/perms/templates/perms/asset_permission_list.html b/apps/perms/templates/perms/asset_permission_list.html index 5b507350a..1f44f7de1 100644 --- a/apps/perms/templates/perms/asset_permission_list.html +++ b/apps/perms/templates/perms/asset_permission_list.html @@ -193,7 +193,7 @@ $(document).ready(function(){ {title: "{% trans 'Exclude' %}", value: "0"}, ]}, ]; - initTableFilterDropdown('#permission_list_table_filter input', filterMenu) + initTableFilterDropdown('#permission_list_table_filter input', filterMenu, 15) }) .on('click', '.btn-del', function () { var $this = $(this); diff --git a/apps/perms/urls/asset_permission.py b/apps/perms/urls/asset_permission.py index 4a649c992..c14db7c3e 100644 --- a/apps/perms/urls/asset_permission.py +++ b/apps/perms/urls/asset_permission.py @@ -25,7 +25,7 @@ user_permission_urlpatterns = [ path('nodes/', api.UserGrantedNodesApi.as_view(), name='my-nodes'), # Node children - path('/nodes/children/', api.UserGrantedNodesApi.as_view(), name='user-nodes-children'), + path('/nodes/children/', api.UserGrantedNodeChildrenApi.as_view(), name='user-nodes-children'), path('nodes/children/', api.UserGrantedNodesApi.as_view(), name='my-nodes-children'), # Node as tree diff --git a/apps/perms/utils/asset_permission.py b/apps/perms/utils/asset_permission.py index 3ba5c68d6..1905bfe62 100644 --- a/apps/perms/utils/asset_permission.py +++ b/apps/perms/utils/asset_permission.py @@ -1,5 +1,5 @@ # coding: utf-8 - +import time import pickle from collections import defaultdict from functools import reduce @@ -8,7 +8,7 @@ from django.core.cache import cache from django.db.models import Q from django.conf import settings -from orgs.utils import set_to_root_org +from orgs.utils import current_org from common.utils import get_logger, timeit, lazyproperty from common.tree import TreeNode from assets.utils import TreeService @@ -19,8 +19,7 @@ logger = get_logger(__file__) __all__ = [ - 'is_obj_attr_has', 'sort_assets', - 'ParserNode', 'AssetPermissionUtilV2', + 'ParserNode', 'AssetPermissionUtil', ] @@ -59,25 +58,48 @@ def get_system_user_permissions(system_user): class AssetPermissionUtilCacheMixin: - user_tree_cache_key = 'USER_PERM_TREE_{}_{}' + user_tree_cache_key = 'USER_PERM_TREE_{}_{}_{}' user_tree_cache_ttl = settings.ASSETS_PERM_CACHE_TIME user_tree_cache_enable = settings.ASSETS_PERM_CACHE_ENABLE + user_tree_map = {} cache_policy = '0' obj_id = '' _filter_id = 'None' @property def cache_key(self): - return self.user_tree_cache_key.format(self.obj_id, self._filter_id) + return self.get_cache_key() + + def get_cache_key(self, org_id=None): + if org_id is None: + org_id = current_org.org_id() + + key = self.user_tree_cache_key.format( + org_id, self.obj_id, self._filter_id + ) + return key def expire_user_tree_cache(self): cache.delete(self.cache_key) @classmethod def expire_all_user_tree_cache(cls): - key = cls.user_tree_cache_key.format('*', '*') - key = key.split('_')[:-1] - key = '_'.join(key) + expire_cache_key = "USER_TREE_EXPIRED_AT" + latest_expired = cache.get(expire_cache_key, 0) + now = time.time() + if now - latest_expired < 60: + return + key = cls.user_tree_cache_key.format('*', '1', '1') + key = key.replace('_1', '') + cache.delete_pattern(key) + cache.set(expire_cache_key, now) + + @classmethod + def expire_org_tree_cache(cls, org_id=None): + if org_id is None: + org_id = current_org.org_id() + key = cls.user_tree_cache_key.format(org_id, '*', '1') + key = key.replace('_1', '') cache.delete_pattern(key) def set_user_tree_to_cache(self, user_tree): @@ -111,7 +133,7 @@ class AssetPermissionUtilCacheMixin: self.set_user_tree_to_cache(user_tree) -class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): +class AssetPermissionUtil(AssetPermissionUtilCacheMixin): get_permissions_map = { "User": get_user_permissions, "UserGroup": get_user_group_permissions, @@ -134,9 +156,12 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): self._user_tree = None self._user_tree_filter_id = 'None' + if not isinstance(obj, User): + self.cache_policy = '0' + @staticmethod def change_org_if_need(): - set_to_root_org() + pass @lazyproperty def full_tree(self): @@ -157,9 +182,7 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): @timeit def filter_permissions(self, **filters): self.cache_policy = '0' - # filters_json = json.dumps(filters, sort_keys=True) self._permissions = self.permissions.filter(**filters) - # self._filter_id = md5(filters_json.encode()).hexdigest() @lazyproperty def user_tree(self): @@ -253,6 +276,8 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): # 获取单独授权资产,并没有在授权的节点上 for key, assets in nodes_single_assets.items(): + if not self.full_tree.contains(key): + continue node = self.full_tree.get_node(key, deep=True) parent_id = self.full_tree.parent(key).identifier parent = user_tree.get_node(parent_id) @@ -280,21 +305,6 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): if not ancestors: continue user_tree.safe_add_ancestors(child, ancestors) - # parent_id = ancestors[0].identifier - # user_tree.move_node(child.identifier, parent_id) - - @staticmethod - def add_empty_node_if_need(user_tree): - """ - 添加空节点,如果根节点没有子节点的话 - """ - if not user_tree.children(user_tree.root): - node_key = Node.empty_key - node_value = Node.empty_value - user_tree.create_node( - identifier=node_key, tag=node_value, - parent=user_tree.root, - ) def add_favorite_node_if_need(self, user_tree): if not isinstance(self.object, User): @@ -321,16 +331,10 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): @timeit def get_user_tree(self): - # 使用锁,保证多次获取tree的时候顺序执行,可以使用缓存 - user_tree = self.get_user_tree_from_local() - if user_tree: - return user_tree user_tree = self.get_user_tree_from_cache_if_need() if user_tree: - self.set_user_tree_to_local(user_tree) return user_tree user_tree = TreeService() - user_tree._invalid_assets = self.full_tree._invalid_assets full_tree_root = self.full_tree.root_node() user_tree.create_node( tag=full_tree_root.tag, @@ -340,13 +344,12 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): self.add_single_assets_node_to_user_tree(user_tree) self.parse_user_tree_to_full_tree(user_tree) self.add_favorite_node_if_need(user_tree) - self.add_empty_node_if_need(user_tree) self.set_user_tree_to_cache_if_need(user_tree) self.set_user_tree_to_local(user_tree) return user_tree # Todo: 是否可以获取多个资产的系统用户 - def get_asset_system_users_with_actions(self, asset): + def get_asset_system_users_id_with_actions(self, asset): nodes = asset.get_nodes() nodes_keys_related = set() for node in nodes: @@ -367,35 +370,35 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): queryset = queryset.filter(args) else: queryset = queryset.none() - queryset = queryset.distinct().prefetch_related('system_users') + asset_protocols = asset.protocols_as_dict.keys() + values = queryset.filter(system_users__protocol__in=asset_protocols).distinct()\ + .values_list('system_users', 'actions') system_users_actions = defaultdict(int) - for perm in queryset: - system_users = perm.system_users.all() - if not system_users or not perm.actions: + for system_user_id, actions in values: + if None in (system_user_id, actions): continue - for s in system_users: - if not asset.has_protocol(s.protocol): - continue - system_users_actions[s] |= perm.actions + for i, action in values: + system_users_actions[i] |= actions return system_users_actions def get_permissions_nodes_and_assets(self): from assets.models import Node - permissions = self.permissions.values_list('assets', 'nodes__key').distinct() - nodes_keys = set() - assets_ids = set() - for asset_id, node_key in permissions: - if asset_id: - assets_ids.add(asset_id) - if node_key: - nodes_keys.add(node_key) + permissions = self.permissions + nodes_keys = permissions.exclude(nodes__isnull=True)\ + .values_list('nodes__key', flat=True) + assets_ids = permissions.exclude(assets__isnull=True)\ + .values_list('assets', flat=True) + nodes_keys = set(nodes_keys) + assets_ids = set(assets_ids) nodes_keys = Node.clean_children_keys(nodes_keys) return nodes_keys, assets_ids @timeit def get_assets(self): nodes_keys, assets_ids = self.get_permissions_nodes_and_assets() - queryset = Node.get_nodes_all_assets(nodes_keys, extra_assets_ids=assets_ids) + queryset = Node.get_nodes_all_assets( + nodes_keys, extra_assets_ids=assets_ids + ) return queryset.valid() def get_nodes_assets(self, node, deep=False): @@ -414,30 +417,9 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): return SystemUser.objects.filter(id__in=system_users_id) -def is_obj_attr_has(obj, val, attrs=("hostname", "ip", "comment")): - if not attrs: - vals = [val for val in obj.__dict__.values() if isinstance(val, (str, int))] - else: - vals = [getattr(obj, attr) for attr in attrs if - hasattr(obj, attr) and isinstance(hasattr(obj, attr), (str, int))] - - for v in vals: - if str(v).find(val) != -1: - return True - return False - - -def sort_assets(assets, order_by='hostname', reverse=False): - if order_by == 'ip': - assets = sorted(assets, key=lambda asset: [int(d) for d in asset.ip.split('.') if d.isdigit()], reverse=reverse) - else: - assets = sorted(assets, key=lambda asset: getattr(asset, order_by), reverse=reverse) - return assets - - class ParserNode: nodes_only_fields = ("key", "value", "id") - assets_only_fields = ("hostname", "id", "ip", "protocols", "org_id") + assets_only_fields = ("hostname", "id", "ip", "protocols", "domain", "org_id") system_users_only_fields = ( "id", "name", "username", "protocol", "priority", "login_mode", ) @@ -490,6 +472,7 @@ class ParserNode: 'ip': asset.ip, 'protocols': asset.protocols_as_list, 'platform': asset.platform_base, + 'domain': asset.domain_id, 'org_name': asset.org_name, }, } diff --git a/apps/settings/api.py b/apps/settings/api.py index 025db8ae8..7b5383755 100644 --- a/apps/settings/api.py +++ b/apps/settings/api.py @@ -12,15 +12,14 @@ from django.utils.translation import ugettext_lazy as _ from .utils import ( LDAPServerUtil, LDAPCacheUtil, LDAPImportUtil, LDAPSyncUtil, - LDAP_USE_CACHE_FLAGS - + LDAP_USE_CACHE_FLAGS, LDAPTestUtil, ) from .tasks import sync_ldap_user_task from common.permissions import IsOrgAdmin, IsSuperUser from common.utils import get_logger from .serializers import ( - MailTestSerializer, LDAPTestSerializer, LDAPUserSerializer, - PublicSettingSerializer, + MailTestSerializer, LDAPTestConfigSerializer, LDAPUserSerializer, + PublicSettingSerializer, LDAPTestLoginSerializer, ) from users.models import User @@ -67,10 +66,18 @@ class MailTestingAPI(APIView): return Response({"error": str(serializer.errors)}, status=401) -class LDAPTestingAPI(APIView): +class LDAPTestingConfigAPI(APIView): permission_classes = (IsSuperUser,) - serializer_class = LDAPTestSerializer - success_message = _("Test ldap success") + serializer_class = LDAPTestConfigSerializer + + def post(self, request): + serializer = self.serializer_class(data=request.data) + if not serializer.is_valid(): + return Response({"error": str(serializer.errors)}, status=401) + config = self.get_ldap_config(serializer) + ok, msg = LDAPTestUtil(config).test_config() + status = 200 if ok else 401 + return Response(msg, status=status) @staticmethod def get_ldap_config(serializer): @@ -78,39 +85,36 @@ class LDAPTestingAPI(APIView): bind_dn = serializer.validated_data["AUTH_LDAP_BIND_DN"] password = serializer.validated_data["AUTH_LDAP_BIND_PASSWORD"] use_ssl = serializer.validated_data.get("AUTH_LDAP_START_TLS", False) - search_ougroup = serializer.validated_data["AUTH_LDAP_SEARCH_OU"] + search_ou = serializer.validated_data["AUTH_LDAP_SEARCH_OU"] search_filter = serializer.validated_data["AUTH_LDAP_SEARCH_FILTER"] attr_map = serializer.validated_data["AUTH_LDAP_USER_ATTR_MAP"] + auth_ldap = serializer.validated_data.get('AUTH_LDAP', False) config = { 'server_uri': server_uri, 'bind_dn': bind_dn, 'password': password, 'use_ssl': use_ssl, - 'search_ougroup': search_ougroup, + 'search_ou': search_ou, 'search_filter': search_filter, - 'attr_map': json.loads(attr_map), + 'attr_map': attr_map, + 'auth_ldap': auth_ldap } return config + +class LDAPTestingLoginAPI(APIView): + permission_classes = (IsSuperUser,) + serializer_class = LDAPTestLoginSerializer + def post(self, request): serializer = self.serializer_class(data=request.data) if not serializer.is_valid(): return Response({"error": str(serializer.errors)}, status=401) - - attr_map = serializer.validated_data["AUTH_LDAP_USER_ATTR_MAP"] - try: - json.loads(attr_map) - except json.JSONDecodeError: - return Response({"error": _("LDAP attr map not valid")}, status=401) - - config = self.get_ldap_config(serializer) - util = LDAPServerUtil(config=config) - try: - users = util.search() - except Exception as e: - return Response({"error": str(e)}, status=401) - - return Response({"msg": _("Match {} s users").format(len(users))}) + username = serializer.validated_data['username'] + password = serializer.validated_data['password'] + ok, msg = LDAPTestUtil().test_login(username, password) + status = 200 if ok else 401 + return Response(msg, status=status) class LDAPUserListApi(generics.ListAPIView): diff --git a/apps/settings/forms/security.py b/apps/settings/forms/security.py index 7b7cc247d..6d30d8b73 100644 --- a/apps/settings/forms/security.py +++ b/apps/settings/forms/security.py @@ -13,10 +13,10 @@ __all__ = ['SecuritySettingForm'] class SecuritySettingForm(BaseForm): # MFA global setting SECURITY_MFA_AUTH = forms.BooleanField( - required=False, label=_("MFA Secondary certification"), + required=False, label=_("MFA"), help_text=_( - 'After opening, the user login must use MFA secondary ' - 'authentication (valid for all users, including administrators)' + 'After opening, all user login must use MFA' + '(valid for all users, including administrators)' ) ) # Execute commands for user diff --git a/apps/settings/serializers/ldap.py b/apps/settings/serializers/ldap.py index 4009c0705..06ae3051f 100644 --- a/apps/settings/serializers/ldap.py +++ b/apps/settings/serializers/ldap.py @@ -3,10 +3,12 @@ from rest_framework import serializers -__all__ = ['LDAPTestSerializer', 'LDAPUserSerializer'] +__all__ = [ + 'LDAPTestConfigSerializer', 'LDAPUserSerializer', 'LDAPTestLoginSerializer' +] -class LDAPTestSerializer(serializers.Serializer): +class LDAPTestConfigSerializer(serializers.Serializer): AUTH_LDAP_SERVER_URI = serializers.CharField(max_length=1024) AUTH_LDAP_BIND_DN = serializers.CharField(max_length=1024, required=False, allow_blank=True) AUTH_LDAP_BIND_PASSWORD = serializers.CharField(required=False, allow_blank=True) @@ -14,6 +16,12 @@ class LDAPTestSerializer(serializers.Serializer): AUTH_LDAP_SEARCH_FILTER = serializers.CharField() AUTH_LDAP_USER_ATTR_MAP = serializers.CharField() AUTH_LDAP_START_TLS = serializers.BooleanField(required=False) + AUTH_LDAP = serializers.BooleanField(required=False) + + +class LDAPTestLoginSerializer(serializers.Serializer): + username = serializers.CharField(max_length=1024, required=True) + password = serializers.CharField(max_length=2014, required=True) class LDAPUserSerializer(serializers.Serializer): diff --git a/apps/settings/templates/settings/_ldap_test_user_login_modal.html b/apps/settings/templates/settings/_ldap_test_user_login_modal.html new file mode 100644 index 000000000..3359d2468 --- /dev/null +++ b/apps/settings/templates/settings/_ldap_test_user_login_modal.html @@ -0,0 +1,58 @@ +{% extends '_modal.html' %} +{% load i18n %} +{% block modal_id %}test_user_login_modal{% endblock %} +{% block modal_title%}{% trans "Test LDAP user login" %}{% endblock %} +{% block modal_comment %}{% trans "Save the configuration before testing the login" %}{% endblock %} +{% block modal_body %} +
    + {% csrf_token %} +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +{% endblock %} +{% block modal_confirm_id %}btn_test_user_login_modal_confirm{% endblock %} diff --git a/apps/settings/templates/settings/ldap_setting.html b/apps/settings/templates/settings/ldap_setting.html index 943a69322..42902391b 100644 --- a/apps/settings/templates/settings/ldap_setting.html +++ b/apps/settings/templates/settings/ldap_setting.html @@ -41,9 +41,10 @@ {% endfor %}
    -
    +
    - + +
    @@ -58,27 +59,28 @@
    {% include 'settings/_ldap_list_users_modal.html' %} + {% include 'settings/_ldap_test_user_login_modal.html' %} {% endblock %} {% block custom_foot_js %} {% endblock %} diff --git a/apps/settings/urls/api_urls.py b/apps/settings/urls/api_urls.py index abee1c0d0..689e1ea82 100644 --- a/apps/settings/urls/api_urls.py +++ b/apps/settings/urls/api_urls.py @@ -8,7 +8,8 @@ app_name = 'common' urlpatterns = [ path('mail/testing/', api.MailTestingAPI.as_view(), name='mail-testing'), - path('ldap/testing/', api.LDAPTestingAPI.as_view(), name='ldap-testing'), + path('ldap/testing/config/', api.LDAPTestingConfigAPI.as_view(), name='ldap-testing-config'), + path('ldap/testing/login/', api.LDAPTestingLoginAPI.as_view(), name='ldap-testing-login'), path('ldap/users/', api.LDAPUserListApi.as_view(), name='ldap-user-list'), path('ldap/users/import/', api.LDAPUserImportAPI.as_view(), name='ldap-user-import'), path('ldap/cache/refresh/', api.LDAPCacheRefreshAPI.as_view(), name='ldap-cache-refresh'), diff --git a/apps/settings/utils/ldap.py b/apps/settings/utils/ldap.py index 726c74c82..36fe36f7f 100644 --- a/apps/settings/utils/ldap.py +++ b/apps/settings/utils/ldap.py @@ -1,21 +1,38 @@ # coding: utf-8 # -from ldap3 import Server, Connection +import json +from ldap3 import Server, Connection, SIMPLE +from ldap3.core.exceptions import ( + LDAPSocketOpenError, + LDAPSocketReceiveError, + LDAPSessionTerminatedByServerError, + LDAPUserNameIsMandatoryError, + LDAPPasswordIsMandatoryError, + LDAPInvalidDnError, + LDAPInvalidServerError, + LDAPBindError, + LDAPInvalidFilterError, + LDAPExceptionError, + LDAPConfigurationError, + LDAPAttributeError, +) from django.conf import settings from django.core.cache import cache from django.utils.translation import ugettext_lazy as _ +from copy import deepcopy from common.const import LDAP_AD_ACCOUNT_DISABLE from common.utils import timeit, get_logger from users.utils import construct_user_email from users.models import User +from authentication.backends.ldap import LDAPAuthorizationBackend, LDAPUser logger = get_logger(__file__) __all__ = [ 'LDAPConfig', 'LDAPServerUtil', 'LDAPCacheUtil', 'LDAPImportUtil', - 'LDAPSyncUtil', 'LDAP_USE_CACHE_FLAGS' + 'LDAPSyncUtil', 'LDAP_USE_CACHE_FLAGS', 'LDAPTestUtil', ] LDAP_USE_CACHE_FLAGS = [1, '1', 'true', 'True', True] @@ -28,9 +45,10 @@ class LDAPConfig(object): self.bind_dn = None self.password = None self.use_ssl = None - self.search_ougroup = None + self.search_ou = None self.search_filter = None self.attr_map = None + self.auth_ldap = None if isinstance(config, dict): self.load_from_config(config) else: @@ -41,18 +59,20 @@ class LDAPConfig(object): self.bind_dn = config.get('bind_dn') self.password = config.get('password') self.use_ssl = config.get('use_ssl') - self.search_ougroup = config.get('search_ougroup') + self.search_ou = config.get('search_ou') self.search_filter = config.get('search_filter') self.attr_map = config.get('attr_map') + self.auth_ldap = config.get('auth_ldap') def load_from_settings(self): self.server_uri = settings.AUTH_LDAP_SERVER_URI self.bind_dn = settings.AUTH_LDAP_BIND_DN self.password = settings.AUTH_LDAP_BIND_PASSWORD self.use_ssl = settings.AUTH_LDAP_START_TLS - self.search_ougroup = settings.AUTH_LDAP_SEARCH_OU + self.search_ou = settings.AUTH_LDAP_SEARCH_OU self.search_filter = settings.AUTH_LDAP_SEARCH_FILTER self.attr_map = settings.AUTH_LDAP_USER_ATTR_MAP + self.auth_ldap = settings.AUTH_LDAP class LDAPServerUtil(object): @@ -93,7 +113,7 @@ class LDAPServerUtil(object): cookie = self.connection.result['controls']['1.2.840.113556.1.4.319']['value']['cookie'] return cookie except Exception as e: - logger.error(e) + logger.error(e, exc_info=True) return None def get_search_filter_extra(self): @@ -129,7 +149,7 @@ class LDAPServerUtil(object): def search_user_entries(self): logger.info("Search user entries") user_entries = list() - search_ous = str(self.config.search_ougroup).split('|') + search_ous = str(self.config.search_ou).split('|') for search_ou in search_ous: logger.info("Search user entries ou: {}".format(search_ou)) self.search_user_entries_ou(search_ou) @@ -332,4 +352,221 @@ class LDAPImportUtil(object): return errors +class LDAPTestUtil(object): + class LDAPInvalidSearchOuOrFilterError(LDAPExceptionError): + pass + class LDAPInvalidAttributeMapError(LDAPExceptionError): + pass + + class LDAPNotEnabledAuthError(LDAPExceptionError): + pass + + class LDAPBeforeLoginCheckError(LDAPExceptionError): + pass + + def __init__(self, config=None): + self.config = LDAPConfig(config) + self.user_entries = [] + + def _test_connection_bind(self, authentication=None, user=None, password=None): + server = Server(self.config.server_uri) + connection = Connection( + server, user=user, password=password, authentication=authentication + ) + ret = connection.bind() + return ret + + # test server uri + + def _test_server_uri(self): + self._test_connection_bind() + + def test_server_uri(self): + try: + self._test_server_uri() + except LDAPSocketOpenError as e: + error = _("Host or port is disconnected: {}".format(e)) + except LDAPSessionTerminatedByServerError as e: + error = _('The port is not the port of the LDAP service: {}'.format(e)) + except LDAPSocketReceiveError as e: + error = _('Please enter the certificate: {}'.format(e)) + except Exception as e: + error = _('Unknown error: {}'.format(e)) + else: + return + raise LDAPInvalidServerError(error) + + # test bind dn + + def _test_bind_dn(self): + user = self.config.bind_dn + password = self.config.password + ret = self._test_connection_bind( + authentication=SIMPLE, user=user, password=password + ) + if not ret: + msg = _('bind dn or password incorrect') + raise LDAPInvalidDnError(msg) + + def test_bind_dn(self): + try: + self._test_bind_dn() + except LDAPUserNameIsMandatoryError as e: + error = _('Please enter bind dn: {}'.format(e)) + except LDAPPasswordIsMandatoryError as e: + error = _('Please enter password: {}'.format(e)) + except LDAPInvalidDnError as e: + error = _('Please enter correct bind dn and password: {}'.format(e)) + except Exception as e: + error = _('Unknown error: {}'.format(e)) + else: + return + raise LDAPBindError(error) + + # test search ou + + def _test_search_ou_and_filter(self): + config = deepcopy(self.config) + util = LDAPServerUtil(config=config) + search_ous = str(self.config.search_ou).split('|') + for search_ou in search_ous: + util.config.search_ou = search_ou + user_entries = util.search_user_entries() + logger.debug('Search ou: {}, count user: {}'.format(search_ou, len(user_entries))) + if len(user_entries) == 0: + error = _('Invalid search ou or filter: {}'.format(search_ou)) + raise self.LDAPInvalidSearchOuOrFilterError(error) + + def test_search_ou_and_filter(self): + try: + self._test_search_ou_and_filter() + except LDAPInvalidFilterError as e: + error = e + except self.LDAPInvalidSearchOuOrFilterError as e: + error = e + except LDAPAttributeError as e: + error = e + raise self.LDAPInvalidAttributeMapError(error) + except Exception as e: + error = _('Unknown error: {}'.format(e)) + else: + return + raise self.LDAPInvalidSearchOuOrFilterError(error) + + # test attr map + + def _test_attr_map(self): + attr_map = self.config.attr_map + if not isinstance(attr_map, dict): + attr_map = json.loads(attr_map) + self.config.attr_map = attr_map + + should_contain_attr = {'username', 'name', 'email'} + actually_contain_attr = set(attr_map.keys()) + result = should_contain_attr - actually_contain_attr + if len(result) != 0: + error = _('LDAP attribute not include: {}'.format(result)) + raise self.LDAPInvalidAttributeMapError(error) + + def test_attr_map(self): + try: + self._test_attr_map() + except json.JSONDecodeError: + error = _('LDAP attribute map is not dict') + except self.LDAPInvalidAttributeMapError as e: + error = e + except Exception as e: + error = _('Unknown error: {}'.format(e)) + else: + return + raise self.LDAPInvalidAttributeMapError(error) + + # test search + + def test_search(self): + util = LDAPServerUtil(config=self.config) + self.user_entries = util.search_user_entries() + + # test auth ldap enabled + + def test_enabled_auth_ldap(self): + if not self.config.auth_ldap: + error = _('LDAP authentication is not enabled') + raise self.LDAPNotEnabledAuthError(error) + + # test config + + def _test_config(self): + self.test_server_uri() + self.test_bind_dn() + self.test_attr_map() + self.test_search_ou_and_filter() + self.test_search() + self.test_enabled_auth_ldap() + + def test_config(self): + status = False + try: + self._test_config() + except LDAPInvalidServerError as e: + msg = _('Error (Invalid server uri): {}'.format(e)) + except LDAPBindError as e: + msg = _('Error (Invalid bind dn): {}'.format(e)) + except self.LDAPInvalidAttributeMapError as e: + msg = _('Error (Invalid attribute map): {}'.format(e)) + except self.LDAPInvalidSearchOuOrFilterError as e: + msg = _('Error (Invalid search ou or filter): {}'.format(e)) + except self.LDAPNotEnabledAuthError as e: + msg = _('Error (Not enabled LDAP authentication): {}'.format(e)) + except Exception as e: + msg = _('Error (Unknown): {}').format(e) + else: + status = True + msg = _('Succeed: Match {} s user'.format(len(self.user_entries))) + + if not status: + logger.error(msg, exc_info=True) + return status, msg + + # test login + + def _test_before_login_check(self, username, password): + ok, msg = self.test_config() + if not ok: + raise LDAPConfigurationError(msg) + + backend = LDAPAuthorizationBackend() + ok, msg = backend.pre_check(username, password) + if not ok: + raise self.LDAPBeforeLoginCheckError(msg) + + @staticmethod + def _test_login_auth(username, password): + backend = LDAPAuthorizationBackend() + ldap_user = LDAPUser(backend, username=username.strip()) + ldap_user._authenticate_user_dn(password) + + def _test_login(self, username, password): + self._test_before_login_check(username, password) + self._test_login_auth(username, password) + + def test_login(self, username, password): + status = False + try: + self._test_login(username, password) + except LDAPConfigurationError as e: + msg = _('Authentication failed (configuration incorrect): {}'.format(e)) + except self.LDAPBeforeLoginCheckError as e: + msg = _('Authentication failed (before login check failed): {}'.format(e)) + except LDAPUser.AuthenticationFailed as e: + msg = _('Authentication failed (username or password incorrect): {}'.format(e)) + except Exception as e: + msg = _("Authentication failed (Unknown): {}".format(e)) + else: + status = True + msg = _("Authentication success: {}".format(username)) + + if not status: + logger.error(msg, exc_info=True) + return status, msg diff --git a/apps/static/img/logo_text.png b/apps/static/img/logo_text.png index 7471c24d51a4e64602e06b59962eca27077da965..8d741116c1a599de5ef54eef7953be1836682961 100644 GIT binary patch delta 11197 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 Su!<1eKNMxvWU8gU1^q8OT7LEb delta 20649 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"col-md-6 text-center"i>><"col-md-4"p>>'; var table = ele.DataTable({ @@ -767,6 +777,7 @@ jumpserver.initServerSideDataTable = function (options) { $('#uc').html(options.uc_html || ''); $('#fb').html(options.fb_html || ''); $('#fa').html(options.fa_html || ''); + $('#lb').html(options.lb_html || ''); }); var table_id = table.settings()[0].sTableId; $('#' + table_id + ' .ipt_check_all').on('click', function () { @@ -1205,6 +1216,14 @@ function objectAttrsIsBool(obj, attrs) { }) } +function objectAttrsIsNumber(obj, attrs) { + attrs.forEach(function (attr) { + if (!obj[attr]) { + obj[attr] = null; + } + }) +} + function cleanDateStr(d) { for (var i = 0; i < 3; i++) { if (!isNaN(Date.parse(d))) { @@ -1396,8 +1415,8 @@ function showCeleryTaskLog(taskId) { } function getUserLang(){ - let userLangZh = document.cookie.indexOf('django_language=en'); - if (userLangZh === -1){ + let userLangEN = document.cookie.indexOf('django_language=en'); + if (userLangEN === -1){ return 'zh-CN' } else{ @@ -1448,3 +1467,34 @@ function initDateRangePicker(selector, options) { function reloadPage() { setTimeout( function () {window.location.reload();}, 300); } + +function isEmptyObject(obj) { + return Object.keys(obj).length === 0 +} + +function getStatusIcon(status, mapping, title) { + var navy = ''; + var danger = ''; + var warning = ''; + var icons = { + navy: navy, + danger: danger, + warning: warning + }; + var defaultMapping = { + true: 'navy', + false: 'danger', + 1: 'navy', + 0: 'danger', + default: 'navy' + }; + if (!mapping) { + mapping = defaultMapping; + } + var name = mapping[status] || mapping['default']; + var icon = icons[name]; + if (title) { + icon = icon.replace('title=""', 'title="' + title + '"') + } + return icon; +} diff --git a/apps/templates/_base_only_msg_content.html b/apps/templates/_base_only_msg_content.html new file mode 100644 index 000000000..1d9ca6c8d --- /dev/null +++ b/apps/templates/_base_only_msg_content.html @@ -0,0 +1,67 @@ +{% load static %} +{% load i18n %} + + + + + + + JumpServer + + {% include '_head_css_js.html' %} + + + + + + + +
    +
    +
    +

    + {% block msg_title %} + {% trans 'Welcome to the JumpServer open source fortress' %} + {% endblock %} +

    + {% block msg_content %} +

    + {% trans "The world's first fully open source fortress, using the GNU GPL v2.0 open source protocol, is a professional operation and maintenance audit system in compliance with 4A." %} +

    +

    + {% trans "Developed using Python/Django, following the Web 2.0 specification and equipped with industry-leading Web Terminal solutions, with beautiful interactive interface and good user experience." %} +

    +

    + {% trans 'Distributed architecture is adopted to support multi-machine room deployment across regions, central node provides API, and each machine room deploys login node, which can be extended horizontally and without concurrent access restrictions.' %} +

    +

    + {% trans "Changes the world, starting with a little bit." %} +

    + {% endblock %} +
    +
    +
    +
    + + + {% block content_title %} + {% trans 'Login' %} + {% endblock %} +
    + {% block content %} {% endblock %} +
    +
    +
    +
    +
    +
    + {% include '_copyright.html' %} +
    +
    +
    + + diff --git a/apps/templates/_csv_update_modal.html b/apps/templates/_csv_update_modal.html index c4c31abda..05709bced 100644 --- a/apps/templates/_csv_update_modal.html +++ b/apps/templates/_csv_update_modal.html @@ -6,7 +6,7 @@ {% block modal_title%}csv {% trans 'Update' %}{% endblock %} {% block modal_body %} -
    + {% csrf_token %}
    diff --git a/apps/templates/_filter_dropdown.html b/apps/templates/_filter_dropdown.html index 3fff427bc..c3a749dcd 100644 --- a/apps/templates/_filter_dropdown.html +++ b/apps/templates/_filter_dropdown.html @@ -30,7 +30,7 @@ function addItem(menuRef, menuItem, parent) { } }) } -function initTableFilterDropdown(selector, menu) { +function initTableFilterDropdown(selector, menu, offset_x=0, offset_y=0) { /* menu = [ {title: "Title", value: "title"}, @@ -52,6 +52,8 @@ function initTableFilterDropdown(selector, menu) { y -= offset.top; {#x += 18;#} y += 30; + x += offset_x; + y += offset_y; $('.search-help').css({"top":y+"px", "left":x+"px", "position": "absolute"}); $('.dropdown-menu.search-help').show(); }); diff --git a/apps/templates/_nav.html b/apps/templates/_nav.html index e517b901e..2222c5fd0 100644 --- a/apps/templates/_nav.html +++ b/apps/templates/_nav.html @@ -122,7 +122,7 @@
    -

    {% trans ' Top 5 Active user' %}

    {% trans 'In the past week, a total of ' %}{{ user_visit_count_weekly }}{% trans ' users have logged in ' %}{{ asset_visit_count_weekly }}{% trans ' times asset.' %}
      {% for data in user_visit_count_top_five %} @@ -133,9 +132,8 @@ {{ data.total }}{% trans ' times' %}
    -

    {% trans 'The last time a user logged in' %}

    -

    {{ data.last.user }}

    -

    {% trans 'At ' %}{{ data.last.date_start |date:"Y-m-d H:i:s" }}

    +

    {% trans 'The time last logged in' %}

    +

    {% trans 'At' %} {{ data.last|date:"Y-m-d H:i:s" }}

    @@ -175,7 +173,6 @@ {% endifequal %} {{ login.user }} {% trans 'Login in ' %}{{ login.asset }}
    {{ login.date_start }} - {% endfor %} @@ -221,9 +218,8 @@ {{ data.total }}{% trans ' times' %}
    -

    {% trans 'The last time logged on to the host' %}

    -

    {{ data.last.asset }}

    -

    {% trans 'At ' %}{{ data.last.date_start |date:"Y-m-d H:i:s" }}

    +

    {% trans 'The time last logged in' %}

    +

    {% trans 'At' %} {{ data.last|date:"Y-m-d H:i:s" }}

    @@ -298,16 +294,16 @@ $(document).ready(function(){ ], series : [ { - name:"{% trans 'Login count' %}", + name: "{% trans 'Login count' %}", type:'line', - smooth:true, + smooth: true, itemStyle: {normal: {areaStyle: {type: 'default'}}}, data: {{ month_total_visit_count|safe}} }, { - name:"{% trans 'Active users' %}", - type:'line', - smooth:true, + name: "{% trans 'Active users' %}", + type: 'line', + smooth: true, itemStyle: {normal: {areaStyle: {type: 'default'}}}, data: {{ month_user|safe }} }, diff --git a/apps/terminal/api/command.py b/apps/terminal/api/command.py index 1dfd0ad3b..1bfa122eb 100644 --- a/apps/terminal/api/command.py +++ b/apps/terminal/api/command.py @@ -9,6 +9,7 @@ from rest_framework.response import Response from django.template import loader +from orgs.utils import current_org from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor from common.utils import get_logger from ..backends import ( @@ -28,6 +29,22 @@ class CommandQueryMixin: ] default_days_ago = 5 + @staticmethod + def get_org_id(): + if current_org.is_default(): + org_id = '' + else: + org_id = current_org.id + return org_id + + def get_query_risk_level(self): + risk_level = self.request.query_params.get('risk_level') + if risk_level is None: + return None + if risk_level.isdigit(): + return int(risk_level) + return None + def get_queryset(self): # 解决访问 /docs/ 问题 if hasattr(self, 'swagger_fake_view'): @@ -38,7 +55,8 @@ class CommandQueryMixin: queryset = multi_command_storage.filter( date_from=date_from, date_to=date_to, input=q.get("input"), user=q.get("user"), asset=q.get("asset"), - system_user=q.get("system_user") + system_user=q.get("system_user"), + risk_level=self.get_query_risk_level(), org_id=self.get_org_id(), ) return queryset diff --git a/apps/terminal/api/session.py b/apps/terminal/api/session.py index 7607d46de..b036f376c 100644 --- a/apps/terminal/api/session.py +++ b/apps/terminal/api/session.py @@ -1,21 +1,18 @@ # -*- coding: utf-8 -*- # -import os - -from django.shortcuts import get_object_or_404 +from django.shortcuts import get_object_or_404, reverse from django.core.files.storage import default_storage -from django.http import HttpResponseNotFound -from django.conf import settings from rest_framework import viewsets from rest_framework.response import Response -import jms_storage from common.utils import is_uuid, get_logger +from common.mixins.api import AsyncApiMixin from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor from common.drf.filters import DatetimeRangeFilter from orgs.mixins.api import OrgBulkModelViewSet +from ..utils import find_session_replay_local, download_session_replay from ..hands import SystemUser -from ..models import Session, ReplayStorage +from ..models import Session from .. import serializers @@ -25,7 +22,10 @@ logger = get_logger(__name__) class SessionViewSet(OrgBulkModelViewSet): model = Session - serializer_class = serializers.SessionSerializer + serializer_classes = { + 'default': serializers.SessionSerializer, + 'display': serializers.SessionDisplaySerializer, + } permission_classes = (IsOrgAdminOrAppUser, ) filterset_fields = [ "user", "asset", "system_user", "remote_addr", @@ -59,10 +59,11 @@ class SessionViewSet(OrgBulkModelViewSet): return super().get_permissions() -class SessionReplayViewSet(viewsets.ViewSet): +class SessionReplayViewSet(AsyncApiMixin, viewsets.ViewSet): serializer_class = serializers.ReplaySerializer permission_classes = (IsOrgAdminOrAppUser | IsOrgAuditor,) session = None + download_cache_key = "SESSION_REPLAY_DOWNLOAD_{}" def create(self, request, *args, **kwargs): session_id = kwargs.get('pk') @@ -83,46 +84,36 @@ class SessionReplayViewSet(viewsets.ViewSet): logger.error(msg) return Response({'msg': serializer.errors}, status=401) - def retrieve(self, request, *args, **kwargs): - session_id = kwargs.get('pk') - session = get_object_or_404(Session, id=session_id) - + @staticmethod + def get_replay_data(session, url): tp = 'json' if session.protocol in ('rdp', 'vnc'): tp = 'guacamole' - data = {'type': tp, 'src': ''} - - # 新版本和老版本的文件后缀不同 - session_path = session.get_rel_replay_path() # 存在外部存储上的路径 - local_path = session.get_local_path() - local_path_v1 = session.get_local_path(version=1) - - # 去default storage中查找 - for _local_path in (local_path, local_path_v1, session_path): - if default_storage.exists(_local_path): - url = default_storage.url(_local_path) - data['src'] = url - return Response(data) - - replay_storages = ReplayStorage.objects.all() - configs = { - storage.name: storage.config - for storage in replay_storages - if not storage.in_defaults() + download_url = reverse('terminal:session-replay-download', kwargs={'pk': session.id}) + data = { + 'type': tp, 'src': url, + 'user': session.user, 'asset': session.asset, + 'system_user': session.system_user, + 'date_start': session.date_start, + 'date_end': session.date_end, + 'download_url': download_url, } - if not configs: - return HttpResponseNotFound() + return data - target_path = os.path.join(default_storage.base_location, local_path) # 保存到storage的路径 - target_dir = os.path.dirname(target_path) - if not os.path.isdir(target_dir): - os.makedirs(target_dir, exist_ok=True) - storage = jms_storage.get_multi_object_storage(configs) - ok, err = storage.download(session_path, target_path) - if not ok: - logger.error("Failed download replay file: {}".format(err)) - return HttpResponseNotFound() - data['src'] = default_storage.url(local_path) + def is_need_async(self): + if self.action != 'retrieve': + return False + return True + + def retrieve(self, request, *args, **kwargs): + session_id = kwargs.get('pk') + session = get_object_or_404(Session, id=session_id) + local_path, url = find_session_replay_local(session) + + if not local_path: + local_path, url = download_session_replay(session) + if not local_path: + return Response({"error": url}) + data = self.get_replay_data(session, url) return Response(data) - diff --git a/apps/terminal/backends/command/db.py b/apps/terminal/backends/command/db.py index 113b7ce17..bb4fa957a 100644 --- a/apps/terminal/backends/command/db.py +++ b/apps/terminal/backends/command/db.py @@ -18,12 +18,12 @@ class CommandStore(CommandBase): """ 保存命令到数据库 """ - self.model.objects.create( user=command["user"], asset=command["asset"], system_user=command["system_user"], input=command["input"], output=command["output"], session=command["session"], - org_id=command["org_id"], timestamp=command["timestamp"] + risk_level=command.get("risk_level", 0), org_id=command["org_id"], + timestamp=command["timestamp"] ) def bulk_save(self, commands): @@ -35,7 +35,8 @@ class CommandStore(CommandBase): _commands.append(self.model( user=c["user"], asset=c["asset"], system_user=c["system_user"], input=c["input"], output=c["output"], session=c["session"], - org_id=c["org_id"], timestamp=c["timestamp"] + risk_level=c.get("risk_level", 0), org_id=c["org_id"], + timestamp=c["timestamp"] )) error = False try: @@ -61,7 +62,7 @@ class CommandStore(CommandBase): def make_filter_kwargs( date_from=None, date_to=None, user=None, asset=None, system_user=None, - input=None, session=None): + input=None, session=None, risk_level=None, org_id=None): filter_kwargs = {} date_from_default = timezone.now() - datetime.timedelta(days=7) date_to_default = timezone.now() @@ -89,15 +90,19 @@ class CommandStore(CommandBase): filter_kwargs['input__icontains'] = input if session: filter_kwargs['session'] = session + if org_id is not None: + filter_kwargs['org_id'] = org_id + if risk_level is not None: + filter_kwargs['risk_level'] = risk_level return filter_kwargs def filter(self, date_from=None, date_to=None, user=None, asset=None, system_user=None, - input=None, session=None): + input=None, session=None, risk_level=None, org_id=None): filter_kwargs = self.make_filter_kwargs( date_from=date_from, date_to=date_to, user=user, asset=asset, system_user=system_user, input=input, - session=session, + session=session, risk_level=risk_level, org_id=org_id, ) queryset = self.model.objects.filter(**filter_kwargs) return queryset diff --git a/apps/terminal/backends/command/es.py b/apps/terminal/backends/command/es.py index 5aa16dfbf..43bd52c02 100644 --- a/apps/terminal/backends/command/es.py +++ b/apps/terminal/backends/command/es.py @@ -3,17 +3,21 @@ from datetime import datetime from jms_storage.es import ESStorage +from common.utils import get_logger from .base import CommandBase from .models import AbstractSessionCommand +logger = get_logger(__file__) + + class CommandStore(ESStorage, CommandBase): def __init__(self, params): super().__init__(params) def filter(self, date_from=None, date_to=None, user=None, asset=None, system_user=None, - input=None, session=None): + input=None, session=None, risk_level=None, org_id=None): if date_from is not None: if isinstance(date_from, float): @@ -22,9 +26,28 @@ class CommandStore(ESStorage, CommandBase): if isinstance(date_to, float): date_to = datetime.fromtimestamp(date_to) - data = super().filter(date_from=date_from, date_to=date_to, - user=user, asset=asset, system_user=system_user, - input=input, session=session) - return AbstractSessionCommand.from_multi_dict( - [item["_source"] for item in data["hits"] if item] - ) + try: + data = super().filter(date_from=date_from, date_to=date_to, + user=user, asset=asset, system_user=system_user, + input=input, session=session, + risk_level=risk_level, org_id=org_id) + except Exception as e: + logger.error(e, exc_info=True) + return [] + else: + return AbstractSessionCommand.from_multi_dict( + [item["_source"] for item in data["hits"] if item] + ) + + def count(self, date_from=None, date_to=None, user=None, asset=None, + system_user=None, input=None, session=None): + try: + count = super().count( + date_from=date_from, date_to=date_to, user=user, asset=asset, + system_user=system_user, input=input, session=session + ) + except Exception as e: + logger.error(e, exc_info=True) + return 0 + else: + return count diff --git a/apps/terminal/backends/command/models.py b/apps/terminal/backends/command/models.py index 39b3f9853..d0ec04bec 100644 --- a/apps/terminal/backends/command/models.py +++ b/apps/terminal/backends/command/models.py @@ -8,6 +8,12 @@ from orgs.mixins.models import OrgModelMixin class AbstractSessionCommand(OrgModelMixin): + RISK_LEVEL_ORDINARY = 0 + RISK_LEVEL_DANGEROUS = 5 + RISK_LEVEL_CHOICES = ( + (RISK_LEVEL_ORDINARY, _('Ordinary')), + (RISK_LEVEL_DANGEROUS, _('Dangerous')), + ) id = models.UUIDField(default=uuid.uuid4, primary_key=True) user = models.CharField(max_length=64, db_index=True, verbose_name=_("User")) asset = models.CharField(max_length=128, db_index=True, verbose_name=_("Asset")) @@ -15,6 +21,7 @@ class AbstractSessionCommand(OrgModelMixin): input = models.CharField(max_length=128, db_index=True, verbose_name=_("Input")) output = models.CharField(max_length=1024, blank=True, verbose_name=_("Output")) session = models.CharField(max_length=36, db_index=True, verbose_name=_("Session")) + risk_level = models.SmallIntegerField(default=RISK_LEVEL_ORDINARY, choices=RISK_LEVEL_CHOICES, db_index=True, verbose_name=_("Risk level")) timestamp = models.IntegerField(db_index=True) class Meta: diff --git a/apps/terminal/backends/command/serializers.py b/apps/terminal/backends/command/serializers.py index bea8c4764..657aa2356 100644 --- a/apps/terminal/backends/command/serializers.py +++ b/apps/terminal/backends/command/serializers.py @@ -12,6 +12,7 @@ class SessionCommandSerializer(serializers.Serializer): input = serializers.CharField(max_length=128) output = serializers.CharField(max_length=1024, allow_blank=True) session = serializers.CharField(max_length=36) + risk_level = serializers.IntegerField(required=False) org_id = serializers.CharField(max_length=36, required=False, default='', allow_null=True, allow_blank=True) timestamp = serializers.IntegerField() diff --git a/apps/terminal/migrations/0022_session_is_success.py b/apps/terminal/migrations/0022_session_is_success.py new file mode 100644 index 000000000..72ef9b283 --- /dev/null +++ b/apps/terminal/migrations/0022_session_is_success.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.10 on 2020-02-27 08:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('terminal', '0021_auto_20200213_1316'), + ] + + operations = [ + migrations.AddField( + model_name='session', + name='is_success', + field=models.BooleanField(db_index=True, default=True), + ), + ] diff --git a/apps/terminal/migrations/0023_command_risk_level.py b/apps/terminal/migrations/0023_command_risk_level.py new file mode 100644 index 000000000..6ada1b826 --- /dev/null +++ b/apps/terminal/migrations/0023_command_risk_level.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.10 on 2020-03-03 08:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('terminal', '0022_session_is_success'), + ] + + operations = [ + migrations.AddField( + model_name='command', + name='risk_level', + field=models.SmallIntegerField(choices=[(0, 'Ordinary'), (5, 'Dangerous')], db_index=True, default=0, verbose_name='Risk level'), + ), + ] diff --git a/apps/terminal/models.py b/apps/terminal/models.py index eebeb611c..f73eada2b 100644 --- a/apps/terminal/models.py +++ b/apps/terminal/models.py @@ -190,6 +190,7 @@ class Session(OrgModelMixin): system_user_id = models.CharField(blank=True, default='', max_length=36, db_index=True) login_from = models.CharField(max_length=2, choices=LOGIN_FROM_CHOICES, default="ST") remote_addr = models.CharField(max_length=128, verbose_name=_("Remote addr"), blank=True, null=True) + is_success = models.BooleanField(default=True, db_index=True) is_finished = models.BooleanField(default=False, db_index=True) has_replay = models.BooleanField(default=False, verbose_name=_("Replay")) has_command = models.BooleanField(default=False, verbose_name=_("Command")) @@ -274,6 +275,48 @@ class Session(OrgModelMixin): def login_from_display(self): return self.get_login_from_display() + @classmethod + def generate_fake(cls, count=100, is_finished=True): + import random + from orgs.models import Organization + from users.models import User + from assets.models import Asset, SystemUser + from orgs.utils import get_current_org + from common.utils.random import random_datetime, random_ip + + org = get_current_org() + if not org or not org.is_real(): + Organization.default().change_to() + i = 0 + users = User.objects.all()[:100] + assets = Asset.objects.all()[:100] + system_users = SystemUser.objects.all()[:100] + while i < count: + user_random = random.choices(users, k=10) + assets_random = random.choices(assets, k=10) + system_users = random.choices(system_users, k=10) + + ziped = zip(user_random, assets_random, system_users) + sessions = [] + now = timezone.now() + month_ago = now - timezone.timedelta(days=30) + for user, asset, system_user in ziped: + ip = random_ip() + date_start = random_datetime(month_ago, now) + date_end = random_datetime(date_start, date_start+timezone.timedelta(hours=2)) + data = dict( + user=str(user), user_id=user.id, + asset=str(asset), asset_id=asset.id, + system_user=str(system_user), system_user_id=system_user.id, + remote_addr=ip, + date_start=date_start, + date_end=date_end, + is_finished=is_finished, + ) + sessions.append(Session(**data)) + cls.objects.bulk_create(sessions) + i += 10 + class Meta: db_table = "terminal_session" ordering = ["-date_start"] diff --git a/apps/terminal/serializers/session.py b/apps/terminal/serializers/session.py index 8d71b2a95..006529b15 100644 --- a/apps/terminal/serializers/session.py +++ b/apps/terminal/serializers/session.py @@ -4,21 +4,34 @@ from orgs.mixins.serializers import BulkOrgResourceModelSerializer from common.serializers import AdaptedBulkListSerializer from ..models import Session +__all__ = [ + 'SessionSerializer', 'SessionDisplaySerializer', + 'ReplaySerializer', +] + class SessionSerializer(BulkOrgResourceModelSerializer): - command_amount = serializers.IntegerField(read_only=True) org_id = serializers.CharField(allow_blank=True) class Meta: model = Session list_serializer_class = AdaptedBulkListSerializer fields = [ - "id", "user", "asset", "system_user", "login_from", - "login_from_display", "remote_addr", "is_finished", - "has_replay", "can_replay", "protocol", "date_start", "date_end", - "terminal", "command_amount", + "id", "user", "asset", "system_user", + "user_id", "asset_id", "system_user_id", + "login_from", "login_from_display", "remote_addr", + "is_success", "is_finished", "has_replay", "can_replay", + "protocol", "date_start", "date_end", + "terminal", ] +class SessionDisplaySerializer(SessionSerializer): + command_amount = serializers.IntegerField(read_only=True) + + class Meta(SessionSerializer.Meta): + fields = SessionSerializer.Meta.fields + ['command_amount'] + + class ReplaySerializer(serializers.Serializer): file = serializers.FileField(allow_empty_file=True) diff --git a/apps/terminal/templates/terminal/command_list.html b/apps/terminal/templates/terminal/command_list.html index 0e5ba0a32..eb51aaac4 100644 --- a/apps/terminal/templates/terminal/command_list.html +++ b/apps/terminal/templates/terminal/command_list.html @@ -26,6 +26,7 @@
    {% trans 'Command' %}{% trans 'Risk level' %} {% trans 'User' %} {% trans 'Asset' %} {% trans 'System user'%}
    + + + + + + + + + + {% for command in object_list %} + + + + + + + {% empty %} + + + + {% endfor %} + + + + + + +
    ID{% trans 'Command' %}{% trans 'Datetime' %}
    {{ forloop.counter }}{{ command.input | truncatechars:40 }}
    +$ {{ command.input }}
    +
    +{{ command.output }}
    +                                                
    {{ command.timestamp|ts_to_date}}
    {% trans "There is no command about this session" %}
    +
      +
      +
      + + + + + + + +{% endblock %} +{% block custom_foot_js %} + + +{% endblock %} diff --git a/apps/terminal/templates/terminal/session_commands_list_modal.html b/apps/terminal/templates/terminal/session_commands_list_modal.html deleted file mode 100644 index 1a1cee6a5..000000000 --- a/apps/terminal/templates/terminal/session_commands_list_modal.html +++ /dev/null @@ -1,58 +0,0 @@ -{% load static %} - - - - - - - {% include '_head_css_js.html' %} - - - - - - - -
      -
      -
      - - - - - - - - - - - - {% for command in object_list %} - - - - - - - {% endfor %} - - - - - - -
      IDCommandOutputDatetime
      {{ command.command_no }}{{ command.command }}{{ command.output_decode |safe }}{{ command.datetime }}
      -
        -
        -
        -
        -
        - - - - diff --git a/apps/terminal/templates/terminal/session_detail.html b/apps/terminal/templates/terminal/session_detail.html index ea5ba9b00..26ec1c785 100644 --- a/apps/terminal/templates/terminal/session_detail.html +++ b/apps/terminal/templates/terminal/session_detail.html @@ -4,6 +4,7 @@ {% load common_tags %} {% block custom_head_css_js %} + {% endblock %} {% block content %} @@ -14,11 +15,11 @@
        @@ -41,40 +42,41 @@
        - - - - - - - - - +
        ID{% trans 'Command' %}{% trans 'Datetime' %}
        - {% for command in object_list %} - - - - - - - {% empty %} - - - - {% endfor %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - -
        {{ forloop.counter }}{{ command.input | truncatechars:40 }}
        -$ {{ command.input }}
        -
        -{{ command.output }}
        -                                                
        {{ command.timestamp|ts_to_date}}
        {% trans "There is no command about this session" %}
        {% trans 'User' %}:{{ object.user }}
        {% trans 'Asset' %}:{{ object.asset }}
        {% trans 'System user' %}:{{ object.system_user }}
        {% trans 'Protocol' %}:{{ object.protocol }}
        {% trans 'Login from' %}:{{ object.login_from_display }}
        {% trans 'Remote addr' %}:{{ object.remote_addr }}
        {% trans 'Date start' %}:{{ object.date_start }}
        {% trans 'Date end' %}:{{ object.date_end }}
        -
          -
          @@ -96,6 +98,14 @@ $ {{ command.input }}
          {% trans 'Download replay' %}: + + + +
          - - - - - - - - - - - - - - - - - - - - - - - - - - -
          {% trans 'Name' %}:{{ terminal.name }}
          {% trans 'Remote addr' %}:{{ terminal.remote_addr }}
          {% trans 'SSH port' %}:{{ terminal.ssh_port }}
          {% trans 'Http port' %}:{{ terminal.http_port }}
          {% trans 'Date created' %}:{{ terminal.date_created }}
          {% trans 'Comment' %}:{{ asset.comment }}
          + + + {% trans 'Name' %}: + {{ terminal.name }} + + + {% trans 'Remote addr' %}: + {{ terminal.remote_addr }} + + + {% trans 'SSH port' %}: + {{ terminal.ssh_port }} + + + {% trans 'Http port' %}: + {{ terminal.http_port }} + + + {% trans 'Date created' %}: + {{ terminal.date_created }} + + + {% trans 'Comment' %}: + {{ asset.comment }} + + +
          diff --git a/apps/terminal/urls/views_urls.py b/apps/terminal/urls/views_urls.py index 5caec1e75..048a79d71 100644 --- a/apps/terminal/urls/views_urls.py +++ b/apps/terminal/urls/views_urls.py @@ -22,6 +22,8 @@ urlpatterns = [ path('session-online/', views.SessionOnlineListView.as_view(), name='session-online-list'), path('session-offline/', views.SessionOfflineListView.as_view(), name='session-offline-list'), path('session//', views.SessionDetailView.as_view(), name='session-detail'), + path('session//commands/', views.SessionCommandsView.as_view(), name='session-commands'), + path('session//replay/download/', views.SessionReplayDownloadView.as_view(), name='session-replay-download'), # Command view path('command/', views.CommandListView.as_view(), name='command-list'), diff --git a/apps/terminal/utils.py b/apps/terminal/utils.py index d7dace0a9..cb8308fcd 100644 --- a/apps/terminal/utils.py +++ b/apps/terminal/utils.py @@ -1,11 +1,18 @@ # -*- coding: utf-8 -*- # +import os + from django.core.cache import cache +from django.core.files.storage import default_storage +import jms_storage from assets.models import Asset, SystemUser from users.models import User - +from common.utils import get_logger from .const import USERS_CACHE_KEY, ASSETS_CACHE_KEY, SYSTEM_USER_CACHE_KEY +from .models import ReplayStorage + +logger = get_logger(__name__) def get_session_asset_list(): @@ -32,4 +39,50 @@ def get_system_user_list_from_cache(): return cache.get(SYSTEM_USER_CACHE_KEY) +def find_session_replay_local(session): + # 新版本和老版本的文件后缀不同 + session_path = session.get_rel_replay_path() # 存在外部存储上的路径 + local_path = session.get_local_path() + local_path_v1 = session.get_local_path(version=1) + # 去default storage中查找 + for _local_path in (local_path, local_path_v1, session_path): + if default_storage.exists(_local_path): + url = default_storage.url(_local_path) + return _local_path, url + return None, None + + +def download_session_replay(session): + session_path = session.get_rel_replay_path() # 存在外部存储上的路径 + local_path = session.get_local_path() + replay_storages = ReplayStorage.objects.all() + configs = { + storage.name: storage.config + for storage in replay_storages + if not storage.in_defaults() + } + if not configs: + msg = "Not found replay file, and not remote storage set" + return None, msg + + # 保存到storage的路径 + target_path = os.path.join(default_storage.base_location, local_path) + target_dir = os.path.dirname(target_path) + if not os.path.isdir(target_dir): + os.makedirs(target_dir, exist_ok=True) + storage = jms_storage.get_multi_object_storage(configs) + ok, err = storage.download(session_path, target_path) + if not ok: + msg = "Failed download replay file: {}".format(err) + logger.error(msg) + return None, msg + url = default_storage.url(local_path) + return local_path, url + + +def get_session_replay_url(session): + local_path, url = find_session_replay_local(session) + if local_path is None: + local_path, url = download_session_replay(session) + return local_path, url diff --git a/apps/terminal/views/session.py b/apps/terminal/views/session.py index 38558f292..a7e56cd57 100644 --- a/apps/terminal/views/session.py +++ b/apps/terminal/views/session.py @@ -1,22 +1,27 @@ # -*- coding: utf-8 -*- # +import os +import tarfile -from django.views.generic import ListView, TemplateView +from django.views.generic import ListView, TemplateView, DetailView from django.views.generic.edit import SingleObjectMixin from django.utils.translation import ugettext as _ from django.utils import timezone -from django.conf import settings +from django.utils.encoding import escape_uri_path +from django.http import FileResponse, HttpResponse +from django.core.files.storage import default_storage from common.permissions import PermissionsMixin, IsOrgAdmin, IsOrgAuditor -from common.mixins import DatetimeSearchMixin -from ..models import Session, Command, Terminal +from common.utils import model_to_json +from ..models import Session from ..backends import get_multi_command_storage from .. import utils __all__ = [ 'SessionOnlineListView', 'SessionOfflineListView', - 'SessionDetailView', + 'SessionDetailView', 'SessionReplayDownloadView', + 'SessionCommandsView', ] @@ -59,9 +64,23 @@ class SessionOfflineListView(SessionListView): return super().get_context_data(**kwargs) -class SessionDetailView(SingleObjectMixin, PermissionsMixin, ListView): +class SessionDetailView(PermissionsMixin, DetailView): template_name = 'terminal/session_detail.html' model = Session + permission_classes = [IsOrgAdmin | IsOrgAuditor] + + def get_context_data(self, **kwargs): + context = { + 'app': _('Sessions'), + 'action': _('Session detail'), + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class SessionCommandsView(SingleObjectMixin, PermissionsMixin, ListView): + template_name = 'terminal/session_commands.html' + model = Session object = None permission_classes = [IsOrgAdmin | IsOrgAuditor] @@ -81,3 +100,43 @@ class SessionDetailView(SingleObjectMixin, PermissionsMixin, ListView): kwargs.update(context) return super().get_context_data(**kwargs) + +class SessionReplayDownloadView(PermissionsMixin, DetailView): + permission_classes = [IsOrgAdmin | IsOrgAuditor] + model = Session + + @staticmethod + def prepare_offline_file(session, local_path): + replay_path = default_storage.path(local_path) + current_dir = os.getcwd() + dir_path = os.path.dirname(replay_path) + replay_filename = os.path.basename(replay_path) + meta_filename = '{}.json'.format(session.id) + offline_filename = '{}.tar'.format(session.id) + os.chdir(dir_path) + + with open(meta_filename, 'wt') as f: + f.write(model_to_json(session)) + + with tarfile.open(offline_filename, 'w') as f: + f.add(replay_filename) + f.add(meta_filename) + file = open(offline_filename, 'rb') + os.chdir(current_dir) + return file + + def get(self, request, *args, **kwargs): + session = self.get_object() + local_path, url = utils.get_session_replay_url(session) + if local_path is None: + error = url + return HttpResponse(error) + file = self.prepare_offline_file(session, local_path) + response = FileResponse(file) + response['Content-Type'] = 'application/octet-stream' + # 这里要注意哦,网上查到的方法都是response['Content-Disposition']='attachment;filename="filename.py"', + # 但是如果文件名是英文名没问题,如果文件名包含中文,下载下来的文件名会被改为url中的path。 + filename = escape_uri_path('{}.tar'.format(session.id)) + disposition = "attachment; filename*=UTF-8''{}".format(filename) + response["Content-Disposition"] = disposition + return response diff --git a/apps/users/forms/profile.py b/apps/users/forms/profile.py index bd1047733..775e33b1f 100644 --- a/apps/users/forms/profile.py +++ b/apps/users/forms/profile.py @@ -37,15 +37,15 @@ class UserMFAForm(forms.ModelForm): 'When enabled, ' 'you will enter the MFA binding process the next time you log in. ' 'you can also directly bind in ' - '"personal information -> quick modification -> change MFA Settings"!') + '"personal information -> quick modification -> change MFA Settings"!' + ) class Meta: model = User fields = ['mfa_level'] widgets = {'mfa_level': forms.RadioSelect()} help_texts = { - 'mfa_level': _('* Enable MFA authentication ' - 'to make the account more secure.'), + 'mfa_level': _('* Enable MFA to make the account more secure.'), } @@ -57,7 +57,7 @@ class UserFirstLoginFinishForm(forms.Form): 'In order to protect you and your company, ' 'please keep your account, ' 'password and key sensitive information properly. ' - '(for example: setting complex password, enabling MFA authentication)' + '(for example: setting complex password, enabling MFA)' ) diff --git a/apps/users/hands.py b/apps/users/hands.py index 5e2007c8a..50229f386 100644 --- a/apps/users/hands.py +++ b/apps/users/hands.py @@ -6,7 +6,7 @@ Other module of this app shouldn't connect with other app. - :copyright: (c) 2014-2018 by Jumpserver Team. + :copyright: (c) 2014-2018 by JumpServer Team. :license: GPL v2, see LICENSE for more details. """ diff --git a/apps/users/migrations/0025_auto_20200206_1216.py b/apps/users/migrations/0025_auto_20200206_1216.py new file mode 100644 index 000000000..7eed2ad54 --- /dev/null +++ b/apps/users/migrations/0025_auto_20200206_1216.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.10 on 2020-02-06 04:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0024_auto_20191118_1612'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='source', + field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID'), ('radius', 'Radius'), ('cas', 'CAS')], default='local', max_length=30, verbose_name='Source'), + ), + ] diff --git a/apps/users/models/user.py b/apps/users/models/user.py index a062f6c99..21cc9bf03 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -412,11 +412,11 @@ class MFAMixin: return self.check_otp(code) def mfa_enabled_but_not_set(self): - if self.mfa_enabled and \ - self.mfa_is_otp() and \ - not self.otp_secret_key: - return True - return False + if not self.mfa_enabled: + return False, None + if self.mfa_is_otp() and not self.otp_secret_key: + return True, reverse('users:user-otp-enable-start') + return False, None class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): @@ -424,11 +424,13 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): SOURCE_LDAP = 'ldap' SOURCE_OPENID = 'openid' SOURCE_RADIUS = 'radius' + SOURCE_CAS = 'cas' SOURCE_CHOICES = ( (SOURCE_LOCAL, _('Local')), (SOURCE_LDAP, 'LDAP/AD'), (SOURCE_OPENID, 'OpenID'), (SOURCE_RADIUS, 'Radius'), + (SOURCE_CAS, 'CAS'), ) id = models.UUIDField(default=uuid.uuid4, primary_key=True) @@ -532,9 +534,17 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): def is_local(self): return self.source == self.SOURCE_LOCAL - def save(self, *args, **kwargs): + def set_unprovide_attr_if_need(self): if not self.name: self.name = self.username + if not self.email or '@' not in self.email: + email = '{}@{}'.format(self.username, settings.EMAIL_SUFFIX) + if '@' in self.username: + email = self.username + self.email = email + + def save(self, *args, **kwargs): + self.set_unprovide_attr_if_need() if self.username == 'admin': self.role = 'Admin' self.is_active = True @@ -548,6 +558,11 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): def set_avatar(self, f): self.avatar.save(self.username, f) + @classmethod + def get_avatar_url(cls, username): + user_default = settings.STATIC_URL + "img/avatar/user.png" + return user_default + def avatar_url(self): admin_default = settings.STATIC_URL + "img/avatar/admin.png" user_default = settings.STATIC_URL + "img/avatar/user.png" diff --git a/apps/users/signals_handler.py b/apps/users/signals_handler.py index 902dfa4d7..45c03f3cf 100644 --- a/apps/users/signals_handler.py +++ b/apps/users/signals_handler.py @@ -3,6 +3,7 @@ from django.dispatch import receiver from django.db.models.signals import m2m_changed +from django_cas_ng.signals import cas_user_authenticated from common.utils import get_logger from .signals import post_user_create @@ -11,16 +12,6 @@ from .models import User logger = get_logger(__file__) -# @receiver(post_save, sender=User) -# def on_user_created(sender, instance=None, created=False, **kwargs): -# if created: -# logger.debug("Receive user `{}` create signal".format(instance.name)) -# from .utils import send_user_created_mail -# logger.info(" - Sending welcome mail ...".format(instance.name)) -# if instance.email: -# send_user_created_mail(instance) - - @receiver(post_user_create) def on_user_create(sender, user=None, **kwargs): logger.debug("Receive user `{}` create signal".format(user.name)) @@ -37,5 +28,12 @@ def on_user_groups_change(sender, instance=None, action='', **kwargs): """ if action.startswith('post'): logger.debug("User group member change signal recv: {}".format(instance)) - from perms.utils import AssetPermissionUtilV2 - AssetPermissionUtilV2.expire_all_user_tree_cache() + from perms.utils import AssetPermissionUtil + AssetPermissionUtil.expire_all_user_tree_cache() + + +@receiver(cas_user_authenticated) +def on_cas_user_authenticated(sender, user, created, **kwargs): + if created: + user.source = user.SOURCE_CAS + user.save() diff --git a/apps/users/templates/users/_base_otp.html b/apps/users/templates/users/_base_otp.html index 89ac8d656..a9589c50b 100644 --- a/apps/users/templates/users/_base_otp.html +++ b/apps/users/templates/users/_base_otp.html @@ -10,7 +10,7 @@ {% endblock %}
          -
          +
          {% trans 'Security token validation' %}  {% trans 'Account' %} {{ user.username }}  {% trans 'Follow these steps to complete the binding operation' %}

          {% block content %} diff --git a/apps/users/templates/users/_granted_assets.html b/apps/users/templates/users/_granted_assets.html index ce6bf3cd4..9d5006910 100644 --- a/apps/users/templates/users/_granted_assets.html +++ b/apps/users/templates/users/_granted_assets.html @@ -18,11 +18,6 @@
          -{#
          #} -{# #} -{# #} -{#
          #} @@ -131,6 +126,9 @@ function initTree(refresh) { }; $.get(treeUrl, function(data, status) { + if (data.length === 0) { + data.push({"name": "{% trans 'empty' %}", "id": ""}) + } zTree = $.fn.zTree.init($("#assetTree"), setting, data); if (!refresh) { initTable(); diff --git a/apps/users/templates/users/first_login.html b/apps/users/templates/users/first_login.html index fb8af6257..417d20a3d 100644 --- a/apps/users/templates/users/first_login.html +++ b/apps/users/templates/users/first_login.html @@ -58,13 +58,6 @@ {% csrf_token %} {{ wizard.management_form }} - {#{% if wizard.form.forms %}#} - {#{{ wizard.form.management_form }}#} - {#{% for form in wizard.form %}#} - {#{% bootstrap_form form %}#} - {#{% endfor %}#} - {#{% else %}#} - {#{% endif %}#} {% if form.finish_description %} {{ form.finish_description }}
          @@ -86,7 +79,6 @@ {% if form.pubkey_description and request.user.can_update_ssh_key %} {{ form.pubkey_description }} {% endif %} -
          @@ -111,11 +103,8 @@ {% endif %}
          -
          - - diff --git a/apps/users/templates/users/forgot_password.html b/apps/users/templates/users/forgot_password.html index d48cf0277..cbaadaa73 100644 --- a/apps/users/templates/users/forgot_password.html +++ b/apps/users/templates/users/forgot_password.html @@ -3,11 +3,6 @@ {% load i18n %} {% load bootstrap3 %} {% block custom_head_css_js %} - {% endblock %} {% block html_title %}{% trans 'Forgot password' %}{% endblock %} {% block title %} {% trans 'Forgot password' %}?{% endblock %} diff --git a/apps/users/templates/users/user_asset_permission.html b/apps/users/templates/users/user_asset_permission.html index 21ae72722..d0975f4b8 100644 --- a/apps/users/templates/users/user_asset_permission.html +++ b/apps/users/templates/users/user_asset_permission.html @@ -162,7 +162,7 @@ $(document).ready(function() { {title: "{% trans 'Exclude' %}", value: "0"}, ]}, ]; - initTableFilterDropdown('#permission_list_table_filter input', filterMenu) + initTableFilterDropdown('#permission_list_table_filter input', filterMenu, 15, 38) }) .on('click', '.toggle', function (e) { e.preventDefault(); diff --git a/apps/users/templates/users/user_detail.html b/apps/users/templates/users/user_detail.html index 7bac7a454..e9bdf8b92 100644 --- a/apps/users/templates/users/user_detail.html +++ b/apps/users/templates/users/user_detail.html @@ -74,7 +74,7 @@ - + {% endif %} - + - + diff --git a/apps/assets/templates/assets/domain_detail.html b/apps/assets/templates/assets/domain_detail.html index 5b01c30fe..119b58080 100644 --- a/apps/assets/templates/assets/domain_detail.html +++ b/apps/assets/templates/assets/domain_detail.html @@ -63,10 +63,6 @@ - - - - diff --git a/apps/assets/templates/assets/system_user_detail.html b/apps/assets/templates/assets/system_user_detail.html index b26cfbf11..01e71fc1c 100644 --- a/apps/assets/templates/assets/system_user_detail.html +++ b/apps/assets/templates/assets/system_user_detail.html @@ -106,7 +106,7 @@ - + From 15ca775005b01d182e56f871b4e8ab8439de0c16 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 17 Mar 2020 15:21:12 +0800 Subject: [PATCH 17/32] =?UTF-8?q?[Update]=20=E5=88=A0=E9=99=A4=E6=8E=A8?= =?UTF-8?q?=E9=80=81=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7=E6=97=B6=E5=85=B3?= =?UTF-8?q?=E4=BA=8Etask=E7=9A=84log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/tasks/push_system_user.py | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/assets/tasks/push_system_user.py b/apps/assets/tasks/push_system_user.py index 472d5de4e..eb3978178 100644 --- a/apps/assets/tasks/push_system_user.py +++ b/apps/assets/tasks/push_system_user.py @@ -121,7 +121,6 @@ def get_push_windows_system_user_tasks(system_user, username=None): ''.format(username, username, password), } } - print(task) tasks.append(task) return tasks From 516e75cbf45a57ecf1684058f23cdc2f606d14e5 Mon Sep 17 00:00:00 2001 From: jym503558564 <503558564@qq.com> Date: Tue, 17 Mar 2020 15:30:59 +0800 Subject: [PATCH 18/32] =?UTF-8?q?[Fix]=20=E4=BF=AE=E6=94=B9=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E7=95=8C=E9=9D=A2LOGO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/static/img/login_image.png | Bin 192089 -> 212541 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/static/img/login_image.png b/apps/static/img/login_image.png index 11a19957eb077d2a8b8e365448b04c2443abd49b..f5b87b61289a12adbe4ce1a5e63e9d9c8e0d8874 100644 GIT binary patch literal 212541 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 `=+p@1<>u#y^PKz*$;!+|)e83QDjIL& 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 literal 192089 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 z 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 `-hVGX<8 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 From a67b445026a48a702eba96d30d3f133d8f847ad6 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 17 Mar 2020 16:15:37 +0800 Subject: [PATCH 19/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E5=A4=8D=E5=BD=95?= =?UTF-8?q?=E5=83=8F=E5=AD=98=E5=82=A8ceph=E7=9A=84help=5Ftext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/forms/storage.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/terminal/forms/storage.py b/apps/terminal/forms/storage.py index a94375e81..3b586560c 100644 --- a/apps/terminal/forms/storage.py +++ b/apps/terminal/forms/storage.py @@ -117,13 +117,6 @@ class ReplayStorageCephForm(BaseReplayStorageForm): ) ceph_endpoint = forms.CharField( max_length=128, label=_('Endpoint'), required=False, - help_text=_( - """ - S3: http://s3.{REGION_NAME}.amazonaws.com
          - S3(China): http://s3.{REGION_NAME}.amazonaws.com.cn
          - Example: http://s3.cn-north-1.amazonaws.com.cn - """ - ) ) From a6054ff6a59afc652014496458f98c5034fc0923 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 17 Mar 2020 17:06:59 +0800 Subject: [PATCH 20/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E5=A4=8D=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E5=88=A0=E9=99=A4=E8=B5=84=E4=BA=A7=EF=BC=8C=E5=BD=93?= =?UTF-8?q?=E5=BE=85=E5=88=A0=E9=99=A4=E6=95=B0=E9=87=8F=E5=92=8C=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E6=80=BB=E6=95=B0=E7=9B=B8=E7=AD=89=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E5=88=A0=E9=99=A4=E5=A4=B1=E8=B4=A5=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/templates/assets/asset_list.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html index f7588043a..24a789404 100644 --- a/apps/assets/templates/assets/asset_list.html +++ b/apps/assets/templates/assets/asset_list.html @@ -258,6 +258,10 @@ $(document).ready(function(){ confirmButtonText: "{% trans 'Confirm' %}", closeOnConfirm: false },function () { + function fail() { + var msg = "{% trans 'Asset Deleting failed.' %}"; + swal("{% trans 'Asset Delete' %}", msg, "error"); + } function success(data) { url = setUrlParam(the_url, 'spm', data.spm); requestApi({ @@ -268,13 +272,10 @@ $(document).ready(function(){ swal("{% trans 'Asset Delete' %}", msg, "success"); reloadTable(); }, + error: fail, flash_message: false, }); } - function fail() { - var msg = "{% trans 'Asset Deleting failed.' %}"; - swal("{% trans 'Asset Delete' %}", msg, "error"); - } requestApi({ url: "{% url 'api-common:resources-cache' %}", method: 'POST', From cedb8624200f4d445623d924a815b5307d148efc Mon Sep 17 00:00:00 2001 From: jym503558564 <503558564@qq.com> Date: Tue, 17 Mar 2020 17:28:53 +0800 Subject: [PATCH 21/32] =?UTF-8?q?[Fix]=20=E4=BF=AE=E6=94=B9=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E5=9B=BE=E7=89=87=E4=BA=AE=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/static/img/login_image.png | Bin 212541 -> 268986 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/static/img/login_image.png b/apps/static/img/login_image.png index f5b87b61289a12adbe4ce1a5e63e9d9c8e0d8874..60c851e7814d13dad85bfece1f1d3a24bb9f3845 100644 GIT binary patch literal 268986 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

          cL>e7#PvC_L{nW3pHul=S>d; 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

          =LCT@nKhzl8C0WL;MTk7 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 z z??#{{5d%1Qn*kJ=1RSU=8a?a~N?!td)Og~3JCi^f9MHITPA%mD8uJX35dM88i53k# zN%NHKAPhx-F8vCUWyA>MqLX(|n&F=5ebQAgZjDqOTb75QcbsZe_CxxK6EJ9(WDR5J zy*Sy5*j#rRnUsPvH%LHP>Iyo8zrv7_m{ z+g4Kl{^acR>GLoC{V)HGme;HXr*d+3R`1}=dOd4sN|^?CI)a%m>H@X;?mzy6cnzeX zveGxV+j%x$)D>ep-upU|#pQW*b@ll1kR*IX|9VU*80fc74gS z_1*1v-(88YomHWFW@u9Dx@vv=@a*Zcb*&eNZJy6@7%0St7MjqT?C`s!o-yqCv^hxMq^=UTMZM;lV9 zmkYPYKYn;$m;btIpFRGp?mYA-sKSfB1NJ zds{Eg-EMPIPbCz2dvJ2Z$JpbOlRWQ7jRU6UcE|NE6X6ouF-&cfAx!^J!967vM9<p|EOV}ljSzHDLlj;i2s8E=*V2}n{p^wtb*oD*%jxg7RMK8TR7rte(f0RD5w|fIVo!UuzPKn{{2R zLsqtIm$OE8hf%uALC+~DrFy9EbAwj<;>DJlx<;R!o*o>mjySmVAD1<2~lOXYH zK|DM<{OtL&M6)Q*k)Y?>7(jh@@#vy$LPf75k;Bw?b@uexGs)NuU_UJq@@%#^KYv7# zD-Ct4(_^lwN-}|8T?p!Db6S55KwXLJj=J4!>LDntRtJYi!*+4m1S%hvcQ^M;}ZvzK&&#B1l zR-y;IwS%fI*Y!6G&t6ow!aq|=vcWcG&67i2A^M52*A)!xg|-@mvjnx^WO{E8BqKyj z(aR{?jLtkW^7IdrVKh9s9^5-17oTiAQY0E_NK9hj6}X|>*mpjOxuB*(mex}i6ayN* zu;W%ngkXYEA2_k2pw3w-OiHKSB}hTN_@p*3ppQ50T*ptdXzDbNn}O`rP*T7rWj?W& zQV-gXpFFJ>`SI+eJF5F+-AKlEY4P`k5aNkm*Jo5_K}zrmN5&LSP|y;AK}m$CC+*L6 zvpqOHxx2klGlGWAgz=f-tv|bMU$tyQ+x- zN?lCrqWSX=KOnc%fEN;_XtC^|NUN`8G}Gwy_4T&N>2~$E&zo4SX?)17)z#y|s}^UM zM}i`d{3uz7PpuRw%MDqXZj%1g0+5E^Uj9}uuH9}IK4H@tHTp#GRfD3Ks66cR&Gl8S zi}}~|+Pew*M_mdE5sHrv5BueO2D^HSpU>OY*)4OeRa0$ep2Q;*hMPek+=JTGC zwdRY1y5bxh9uBiP5Q~v_yp%QaM{U!~gT-PsS1Ye98jHoeK8N-Cesy%z*W&!>kOBvW z2BsUan>E=-YxNE+ht3-LtC$t^X{~uY1Sv%K0I%9Iieexdq8}nNeOnm-B;Qk$(Qb7j5{y z+l`y;eS-Wc-bB!%SnC1YTLRWAjx7mW#Q6}$)?@8=)g}1jyZ7xFJr%sw1ADD&?kUJ; zviQrIk?$Mjpskg!XbP{H=*X@0>&vTk?$+B4ixANPEbXm-|KZ*3`nGA~cH35+f%?^R z{&4y6>iSAzcAN8G;~P){fj+)}-wr-4qcVA1Uz2w2-oAQ8qNY)LKA_)GTwSv(TO)WB zUPX_ztDkoRjI^hy2_2(ZA3>3S?FKkHJ!ZS_Y&AD|SF0$vtP|Q~i#chIy?TV9Pq<=enSZz02JG@GSBb8~~?mPtE2 zVaFZ!_=8|R zDL+nU3r4b`k`Y1GFk_H?l(0K6f*(q%N`^Rj=1`1!k$3hfT6bHWWBg?!O0hnV)4Yph zG>0>{T+c=2Xjv^Z5TxC}Ejm5h7B%OC1vW_=r>)a+P0~JWL01&lJIWuIf~8pm)_#7sYt&6pv3&R|f}oA3v&ZZfY~esfcD6XRB48jM!BK_hZdscd=Nh zYQ57=az!c0CioTU!l|F{Y(85aF3T`#cDq8g#ob=aMU0-Ws~|D$=(hpu!BR}jN!s4X z1s6&lS!Q7ZdG%^RPFO=)BPnKrq$DM39;0;A@<~C77p>q!$1FE{ILoXARwB~4tg)Bg z_@h1@BgRI=5GIv0ONoyCyuRzd72cr%2p}M#>^YTC^Qx*6eN<>Xlj6(1DE7cTyJb%m zk0CWlYdKJ&8Trr}1Fg`uS!)(j%aD5`m#Qx~$^A|6A>M=fk_Tv4AkBy%| zUHD)z-ls?K|6N>MoLxLxU*8;^pML%I*FXRIODR$behT#F6;(YGfBxmy+xwwj7hiny z?QU%Cg${B^M+BTO_~a?i`~LGUzF5u{cel5Xp1t^o`}ONLZ{5?u5@{yMtl4sjN* zD>_v;^R9pL{Mq7gwZ2=gjt>9)&;L_B6Ew0C6|C9cOsTx-onu#2IzB&#|NZ~`zvB`> z;R|e1)t1GGO!9FE7IWXnB>Wi$0;tEJs4l7#Vh+u$i$^2~YDWrBX&CAn5>iKP!h+5& z5#MZ4$_usTS@g%r9PJ9;ZMy4U=EHTDd&;6N7VqhBSt9Bx0xDF#nu#PeuQ~=LxL$OL z47tc-gw_Wg0t#bD25_o^GayD*^ClW3Q!K*(p3iHhRbD_sn7pp!V8WgZcKYK2c6Se} zo3n2hH?NO3Z}M!egO6T=y9yB(lY6jDp)W*@`XTRr{q^GyZ*Twf_4)bfF;ccjmnP|9 z(uosQwdxsKE1DBeEoK}+i`4$ zglS=Digd1_skPq0*;(1_ps9Gf>&uU~w>MxkAGGvI3nUgf)_k=(JU$_!d_yG+>rFib zj2tOTgW?PmI1`uV^{wl>zW!trY~aw>r#|mCw|Bekkh5*=*&7R?^sE2SoWWfl2wh*R z>G~ifa*bg|kYZ4Q+7IeEyNA5p?CNLQb+sUGnRrslNC1mP|Fk1iuN;L&)$6+5dP{3U zSKo+T%?wCs334ZqxT*Bx^=;m4>SnQPcXaNT%Xu-F6^2LxNnsTKJeQffvK#KV zM6;|9J zSrW#7`0VAC7ZTyp3Si?Glw{B~v|@{rQHaOENu-!NMxTo@+T;oZP{v#=K&HVzI`^i? z!CnT$Lh#S(yOSJv?Im-lyEK*pISb^C5O(7J-e$8#f9c@j z+4ILAcqu#HJK4z);RSpROfU9MI~7w3}jYN%fWhwz7^pK{$K%68Xv3vSo6=(7tH&0sR5dFHqsW~-SV$#K4#r^&e3 zN6@`OMd;_S?$3GF)CgV6{Tkc-&QKj$(8f08Mag$5#Pj2x)rgENlq1tvs5djHw8$Du zAQ=@Vbw<{3@IMTVZQKTF+kr@sx$c*n-TgQgOAU}yF|9*oEIlgkLmI@Ooi9FOa}~(J zW1X&JgW86T@>3*(LPjOZnU%hU^d)K;GE!Nl`V#7Vw#`Zt&v^dUG;LkJxw@)1WZ%se zt)OG|j0cnJ-a@NDkv?xn5Yl0NI~!Xx&>SPFtJ{=Ig4dPt#;9kcq+!yZKMNgGcWsX~>SY`YN}phMcW8SQND$_Gs0d5dY! z$j+#yVzDK)&)Wpe$&3M>#>W&oD|W{cY@#6ja2tYwWZp|&2D;RZQawz9!hoC1r!!7X zLbX(6kX12Dn^9WyMIJi@%donOhfS^wODN%V?f(W)(u=?_)zgPEC3e<}o)Bc0#j#E4 zM!vVad4+W5D?%^jA80pKHy`Wm+bYT2F1htxDMjCK#Sj;3Z^+(Ne{iu}@)h0$sIBr^ z*M*pgp6QzR0C4DAFkF*}_+V&r5v&F2wqe5fmqy5D5Z0JXMjK5d?XmO4;_&pO!>+)X zm;K%C&DF0z3$fQK8|@g3W+W35BdL;vpGcvA&LKgH$fW~QvR>?T-&AaYCs2+UC=h7B z7gf4cLTe}R?(|&+%hnMnQbx;lk!yHVCtv{a8p9+)?odub(`9#)Zuf|Mr)cuU}108|Wf1db(P>nX{_3ho!!9kuk#rUut?r(4FA*i4CR{Pcq_U7{D`s2s5$4_Q? z#te$>_P%|B+hNrd5mGswIespwlJU^S;G(c3BQAR)`e|AUIC34qt zYd6**1K1RjgxWaDMj+F_ zM~^H{s3S@UiQ&%TnJ6(#H8!nrmIREA!{y3X2>hpW^>rX%a?Z;-#aO(+9gYZ25XTF&K z?)QIq{Ne=;<@)NwfBf6O-QC`))!x?^Q>H*{{s$CUy#T)W^2@J&|A%?ExVgFh%fJ5X z)zuZD2p;@WQyT@kgmho<0iZMC9&7_YHPK3es$xmJlQ~8F`xr;{|LYHa8nR^BeV;;# z_{)A@m)~LcPygkA&5QZ>fBDM~-+!M*7J5x%-zS!Je2~dPXNc|g?EL)j?DV%Ee*FIX z@9X2Hta5k{&z4C-@5g-UtWldaTd*&N)5l%{x{Q*>-OzQjZZW&RyRVyk*_HMB_OykT z^wtF)+r|&8qvQ46dUwA$zBsL~_Wt&s^uptEwand&6(^g!+x6YuY_)=}U#w>H)q&~+ zV8VXsBoa>k74-~-VA9WMzQ4<<8%5#kYAspibkgtWtR}C+5~&Em>Z_}iG%z40n~E+@ zZS~;94EO|*8r6USlF5lSm*QN?QNlMUSX+D(f?<;mwr@o01j#wu)KfS%qTEL{ABVJU zTJ0EC;DI#irUwPoEb%4Z9S=JLw}R0w3l+71I=W zd{m^_E7bw|jbuDInxGY>v`7$|C|*FKv*oDHYcYgzQhmE;egErUzx(;8pN#D}r7YmS zXl)pN7>48Xi=&IvH$VUK)6YMR+nx0N|8xFYDZl-;IXpT2=1+gTyS)C}-~LwrH|;Hg zleNS9LhFy0FMs~!@zdx1a`x&kztn<;^EM`I&Icee6=%vYxlJ{8!|RtXpMCMw$@$s) zzrMWs@V+Hblr%~Hiu_MQf#Jl1`CzS6Ey;tI0-sV-+px{98r$M0J!*I;jDUyiq&<#) z{N3VLm@Mmo;R&H2rq*#=j<&n&o10-bE@z9I>$W%NSwGoI9!5i1uP?y$>q6ATZJW&r zz-E1i;|Lr9lRmA1?30bIi{m^dYIH&PTIPTTtCJ)Q8nm{%zrDGi^*02fKR7-0&K{jn)uZtux`Jw^Bv_c6 z1cG-|D~`kb;IJDuEuMrCJZOhTD%Rx8tM)N+Vc34j97k={LQ#M*&pGLRDv2wx-1$5t z>3D=aZ@gu+p)#lY6`EeyDG3gdJRyNr$`e(?j$E#m-O$z_ zG^#^{1#9WwzkTcov{VH`#yu30Fy zjmra1BN$iwRA@%-z!r)P`2ZW6=8DO9R<7hUIb1<>kb{5!UJOXWhX73LYv?AwH&gcX zC)_{J!E`|vE7Kk$A}pLSv<@)Dj0D<*NJ02y3GA!0Y6!#bZko?tsavi?u$A3K4yNMK z|48Z^-2&roY>R0r_cwP3Cnv`zCq3nqv=}a8eLFU~k6jC}1i=v?`GNpp=Vl!h5e0rp;HI6(#bqMuqZWKvHA0v`bMXlu0? zOLfW;GD;pw`C{^Dg4hOn@YYS#<=KNpb}sR$<_}b zjNbB~QGw1Lo!85xYfhWKF09QDJ)iRwx_kWyaoifoPD7_vV=zbxpHcW%uvjkBF5wzn`-b`!paqghwW4kR$=3CZ$WcFt zk!PbQt7|SAFr~H*{=!?!9ltlQk3ml6*+lHELg<=( z@*HoEqBQr|yGVggJ)z5^_9UEqud)-=T*<({z_0@;cF?zVoHhw?q8A2h8Q~ryI4txy zA%joG4AT?DUXhFDpA1Vg!d@*q>DYoX>vU;1$de2)b#>SG(DI0N(E|$%4isT4UQ>8^ zc0E|v3?}To6lz%noaS!%S8U{S>5m;z#BU+VKIjGr2`f%q5YoS|YinBz`|jlYw3fa6 z0$WqK@0ux&iXdX5=Y!Kj4zKER!$R*0_VbR7;Sfz{Nr$MizDPn+6f9YLv1l}?6^Mm6 z)l?xCLPpT!2$@ctgAG;6Ac}F#{w|BPotij0U3rd?vTnosF^l*_tRgcG2 zA3xnu-HW$VAf^lB92NqT1ZBk(!<1|hthp>q>-Lg&_N0Nr%Tw=9JcVeq3tMJX&F&L6 z6w==$bO3zCg%I)wp`DOm+L{ULwbfE_TbdZ-AU*KtC4*ww({on7QwaClwT3uE$1Cf$ z6^Vtmx#_`j(w$KYIYNjA#{C{kSi-Ys;Q&nL>k!PxaslcbD|?$$5)fINw;ND7c)8EZ zjdpaN&iXV11Oq0h-EC1S?B3nyl`#X`QZsT<$~KC?L}7+r*`F#eQCarG{Fl)3iY@px#Qoly~180i!fc~ zGENX~pR9s0efpmL#IOhhIW)yZAbcxK+a>7OkBNWIDzs^g6Yih5aazFQL=6o3s_lf2 z$svB;IgXa4eHY2(Ex@4SNqdVXL}q&^fhX#Z2RNSesdv{~B9ywQu=YI|^(Qvh*v3ZR zl+pKZcSz$WG#()GHOus2*$}3wx6PlN3}8b55Qh6out7x`L!7cP761s@1xmBGa=mD& z1_p`=wkDc(CH0I!iL4kWBA|_|c^X4zT9~6&mLKiiF+Hpr-`*e~NFb*0;Ds5YCJhLrahj=25B>l2(u=auQ^+gI# z!M_QDPIQP6@W`?p@({{=Z06}hTW1v-SJW77tv9{y(a`mFZpfUb3X|!Eyusf3Dh>JP z*k&17i$*+CD2y}e)rg@q659?W+IcKxve0A+tfO-nByY%R5!6v&RY?zGKf_5ITz3ZH z1_(pDG*OuWVhpy!$&DUoZ^r!y!E~RvH(^g?lO_s^N%o44gM6&E7jPPt#nawGo+gw= z<12<`-QD<-QUxj#Mgyz6k_Ce&9K+KNUDXLL>A|j*ya5!eY<1~j41t8odFuNz7&SdCJu27Pa4gpQE z5RB6hI+^IpsCbbr+|zU06HF{pA`H%M*g|9SN;4!UH*}$PE^~-H5a5}7GgYJ#3_2RQ zsa1hJyAVpwX=-}{Q5a;;vhxE$(F$;s%d<%2Fv!@N`=JujERUBZG)dp|oI zyCH}DF(I#&>M~QYLeFB?t;J`pSQ=Tnf-1|Qti%#X22feDw2D+_Z75cxEnx0VDMrct zk#dN|02N*A6=r+Y1~?;rGWtpA!aH}rh|Qg@E^)jAIfI&hFPp&Jdy6@?Y4t3Q3d)$& z(jvN$5MMnFsOLDT*n59Duqg5A-x^X;A(k29f}$!0d{D=_`@DG7nmm6aO)A%v9;{H| z4DJDL5csFyD`_kN@zWI@q&NN}XFrxo zi%E|-!dUrx%uBp+l6RA)y0m!VVEiC(+NBTY1T=oERx#S;2-qK-T=lT8+`!2jjPQx` zOR%QsyOm{xFY6sG6GirXur3N1HBT`#F0t@SmSwrct^KJkeH153GNqz#Sgumt2fA;I8s%~iWNDkqwP{H zxo41pue=2vmB}&ETt2bP)?;ju$-I9xBVW=iIGbWfqf^tP!*nx~no#0R6wUv@cpe)Ex=pQlY_uN^?xsXCmodo4lbrE1VvPzEUWDUiuFjhBR_p26T|< z)hqXiL5)znS3!<980?D|Ahh=)1_XktDlC-KVie;%%d2OuJ#xtM*{6HC_#mFNi}3WP z>nvj6aYD>#0?>_5tc=!_ETQKHQ=riP$r<)}(|~ce!Q?A|zOTlAEf6kCcsP>W*DPDZ z&FsCt+UK}02Bd0S8DPH&GwBIIh*rUnnxeBA(55z$vPh=wI0fuMRMEulElz%i#8#88 zG$$PHsSzb)wKyAepem!8vFwG3v-r4@qMek zqA&5`wE|y}t?fxkY$%O6?w8A6m6N>mg7S#EC>1q(zgOq1WEa`EDx zKfN@vU>!B_*#TF^vEo&e&Q;2K$!GS&EghQ>W?!?Q93X> zUbInK5i|okMB0R$6F+O=IQrf%9~N~1+KSleh?ZIwtSQWeZ+Jpt7PRPf(5we(Naf%o z@piHb zLt#a;P8UqWY?ThC2gRrw7jV)UM%+6B$FnQKBnH{590Bg5`=e5rMNKLD5XTAZ$o3Ld zy^Ej1@_H8)(j=kDiHeidIJICuVjd&?6k!utkjQI`JwZs~pMsc1 zj)uxKC#6?4DnT{GO$q1>s-eblY$TN~anvmY*CAhn42}np`!e>(`ias3%|aT3EDm1t zb!#EVC}f=xO#n+kw7;erl(xVlBvH8%xFVx^_*ir7Hc`+K7X2irjh2B;Yqq_K*1+!b zV(CPNhEpG$VdSJb)?^~B#9b=QR8P$U!N{=$iTdTPOo>TsX0>K}2iRy(CZ`an^t{bB ziHc->wMXk7%&bLY%(+OdBtY&I%W(p^hZ7JCJRVTBV$eg~m0kbjoF}VNLYUNLTAG3Bizg*%4pZ%(B6t0gHDRdBbN8?am_BiQZ>=J(J@&_O zdmT><^Hxi6pB~F|gj&S;KE`&+p6waML5{(wZ|e&L$*@bf(&R7^id5m0rhvYe_RpSg z7=wx|6k0_4Qc5fo2w)2L8;L>{ZCwU;(*ZzOid~&7p&pR+g%dh3e;_mv+Sj#UKu{Ouy~ET~mQplffFL-*wc?PJ2>>Re zmZTG&pJ{swT|~t>?oDt?h~0K|LDp7+@4OUA$zq4(0tGB!v5Zmo!LPJnKs-q1xxV+Egh)f0M)0I$5m2tk;8`Cz zurkjNL6w2jSE2b^DY_=tSKLV;X%x~*2N&}v=J{DE#3`usM}78%D}3XliauC8!fNLR zPfARx_APYJaLib-oIr+7u)i+IaAjJr*fSY>WDdS+_i3><0SJU5F|Ilb71Fhu^rH<$ zIG;ay@?>+rxw*b7KY?nl$jGZh3N*SYpIg+ zJ{|jEqVG`TOtc_DoCgm^dXruZU@7}ljwWBzz#Cz6A-X@ZfM#%Lty+>NdZ6jPMagR| zH6HrW4K5)X=zFQwW!b5Bm_dcfo@>c^Qg4TiKE?%YJQWH^YI(@b(Z`cQ?)H-Jj6YEV zr4=U_an^hb4UTCbY_F0QI9g~Cgp-BX*mE*p2JI`9gR5O{bb%2;v+4IrqZ1_FDO=iu zmE^_5>(Uo8s}^(C=~Dq$--v6jK?5xLTNGU^{%WtMYooeW+%+~EFSELa+BJnqVzMBI zb9iGqQ(b69C+hsL^9#=9jqxJXpd^%MjT2QTx0kR(bHQl#YB4o(HY~6#zFbiY4afpP zI1W?}gk943)2yi$<3tLjs}Vwh6ll094)bz8JUl)6N36gamM+Yl$tC zIo4;=8ONZe*ZGhxD8;Mu1eWPN)l)xQZ&89IC$qpbsnpDP;?fQsQo|k)Lp@GtEqKp# z#QnBDTbyNz%MaKo7Qw^HK;*h9uxebaCOaJl9L2;UUpO$+7M_-AL6!^V8_gwWv%i+@Q#@m zV`RE-lcCV&qtzp*hKg%q-P*+89O93un%LhqFm|#agoak1-y2+WlN#fWx;g{O`xZhR07mD`TssvH`P;p@ruMGR}BnhC? zPRck8w>MY3=5ym--j@tA^U$$JGyaSo5Y{rt`@Sx~+hM!DTer4+YE&KQ`^9pxqkKtz zVWX@H8H1EOY8FrhcN6iiAhB?wLWSsdn`EU<6>kyaE4}rp+z`DMh9GRvLJ0ylC3|NDK;ygM2AOHV#8)}skjEW}uz^DcDWoEK$%i`3?3`*2a$V?FT-X!hxE2(>X)EWtEZn2) z!lI03zEasA1m%n!Z?fwyK{a^PJXLOa0d$jv2oU5u#lJ^e4v<z$2eDs=3of2a$2XKE}MEaay+AZQ?jMgizq>(sCnPwPcFO=8(m;H8`5NW zrnf6yRHZ~cb$w1HV^$o84*YCxY=&A!Itzro9u3-0QAiUtKbW;PP8nKC?URp3xO*Z3 z<6M__Z{G?#yzYFW!(v#Hu%=2Q(9sMaQ$vO>+3U;8O#XFLB)rH`bH2J%Mn~qsY6)IZ zga`KKiHIp^{EO1*i}WWTxh*CP*}$9Co&lD^oF9ucMGT~-$0^je8vypunjr+&Pv5+t zDn03s0et*93X;Hga5(=uca~;AlRrKt1hdd9hg3@9XRT)<4_r zIP3T58r~yDMPPSu<{C%51Ae%+*c6GT*Otm?S_SHBX6;K9CWguKp>%UgJ{CO+ zV9sXF6q6L|HwxeV{3<&+tU$J$j5LzKwH**7hPLG=slaI^2Mqw!S5!t} zch;{*ciFJ-5X+3>4wWINTbJDbCeO)M{}w$cWnNm7O!FwddGUoIB+x3^rJ~+C=1wZ9TPJ7f1X>nMx#;6ZC zf^PLw^8-$;cP79DSv}lf8_=7H?jk{sKxnq)G(q)%Rq2skB%>3YA0B-D)mL@tyj|Zv z|NM*f&CSP;AKS5c9J$ev!-Q-PooqUt`V3|{KY#IJb#Qohx4wA%0n0$9om=cpI1&prS(C3HADGg1>Ml^5&SiL>k?pB?U;EV$nIHv!<0E z_p{pKovDVB$ZKv~z5pa!EVOpj>ZbG0Vy9nFK9NrHH87g>aX<~N`g}(m9zB14eS7oq z!-s(JolaAf`P#0r*xL5-F+wXrEHnRa!vYpsmvDh=U;zSi|+gT&Ew}U{#eTU%lE1Hn$>xF z9B9?q-j)sw=iRo#zMnt({Ml@_ykFn1&QAaM&;RoN&FhhF&MroL00if(UxBC~Cy*if z9*RttK+rg4dOJIBNFYjdXPD+1wpkF_uFn?PyHBGz~ z)^-y&capm|TP;>chh^6WNCyW;fBu*MWxZaru~w7Tf@TFN`i@>smWVi6#QMHl9370i zZCi(C{a63^k551Ug3&rKJ?rp8_EtY8%LOV5edh?fBET6Tv9BK>^R|4_TCOAz|Cf^o4)(nmja2@;F$XpAumX*Mz;|44USTl8^L*#R+ zwnan;jpN?9nY+PhN+QtXw1NV~mpvvSw-+1qQRQCbKwenWkEDnIWjhOb4jk!#PJS|l zJsIATmfImNrR6`lP(V_|lCE1}nf;U;P|^l5x{xnpt1qtS=6Zat{i;{M=D^%!bB0U!8l zDnx4;w~Bc64}bjg{r#=Qd_V9OyL_;TB9=>f9`)_*pMLrE`DdSv-xKRnyZaX$)L>bRMdtCnuMJ1!m2^0}YV9le_oQue^Fj@-=A&f-J%)(_HReHxB?g{&?*dX+hy6M~AFO*@ISX*2SR+vMj5(cTSbJgCY#= zq}QP&L+$1j*@<(A&hs8n4ph_vZewpP)Lvw&A;yskNjan1l$7H_i&czrVV3ASRcyT3 z)+4(ICrvUDh!^o{Hqin!fv{})x~_|6Su#WEQ!Z?np{}v6XlW7^m!kh5FK46g#Q;<7#eHWRiKJ#=NDE+hl?i}og%n1#_$b`DiY+tPYd zEXvg;UF-tR7)iEqXWyqy7ggNzTr2=e4s$N9LmQjR+f0GQ)Jh|Eb{<&@G@BpxJyqN~ z>0!t`FBT-t;p|3sev_!MYvBD>t}Z($lRj?=ozyrKYu)9|inPAG0dtP;`9;IE!k1kz&sIH_~Ft8;mRk0K=yEfMfK>-v_OL@W`RK5gxN_ zUG1lKX}gufH@|in<7a6O8W>(svS6(P4M!!_x^#Agr>HA{xpz5!lyaQSBBrNW6cKEF zg`MVxNVKMmU!Z764}h&CDhOds9iK_FOWZ;k6gwWWC93Vn_}8j{DjHh@oSiG1AdDl@ z!=qY|+|xtP+OmAL{6p7&CI6N6#-tk88Uk5BJ4K!Udq7jG^N3h6GK-SXoyEa<79XQs zg=94M29`CyKdP?QS&*uK_OL#QF9U-=x+T)TT~(z^PVwU=P0-;J zY%#h;3)sh#bp*&FX!Pq#mX|OpLXi~nh!QnxO5*ugN+{?x2ySQ3q-0_>V>a8;ms`cs zNhl&ehW!XT5fj&0$ib$J_pf`L1=FShrAHtXi=1@DD$-)=+F3=)>P#CfjUx(75M1K~ z-KZwOpt?s#|E03kc!?})#037<29*=7T8xwMQNY7=PM7N2fD6-v!|Sln95ly#BWIQ5 z`Iwp#Q%cm7?KPVJGxl8i1Q2syXR?PAe$dwT@TJLhi=UQi!^A-c9?N9z4M2H0A&gYZ z9N6oCSX)x&%nX5+q!ronWIEJCM$If>$p$kYv?k?Wt|bSK#<9`gpT%h-v)v*cWeF)t zx*Qfh&SWz^bN|NXqH??rRe=mUEvK!cWu`pP<*1YbM-|ZVYS7Q=HD_OX5EX}lhVXG4 z4>xy5vitF7FR=E}#-Q{qo$eN-R!|&6tG6j=te4 ze#k7pp+~Gy0@`OSpf(%@<|KWkJ@-|B)35b2FUjV@Nn_`1kek&IMOUl9?~CNxq4RH@ zh{E6PSu?y)maG$8Ld&!wXhy@02Iu61F;6#(YZ~a}*jD7B@Txa-{KQG+);vX-&6b7b z>x#>_7FMASgZQh*l1eyyE6P=%8rE2Ejug$26Qt|axiMUr?K*&vfy)becY9H~@w)*ih(;zCB_gJgza6%zF58Y>9m z$q24M7z+jBzhr2tu2yQaECX^SCANyL>8?tduew^CmaW7)=uw(h#`dn$h}E9m_5{P@W^U-k&+&xgAX;VveLM0%T%XJvV`5n^Sj0)|N2{%SQ2@ zVj++?C34MqD5R?9C7zR^89Gi?Y={=NoQ~?K6GAt6Cl-zTs#5&yi?t#$oqY`xH4zt$ zm_g=nX8YCl>)b*k=g52pLp~7#=F) zkuz*tA&0@-E)sa67DK!CGOx}>wkPW3k_x8dgEPV)Z(X(+364Nj^H@7*_97%5MUmo> zORZj}pOn-t z5<-!UYk;h(@vSePq;CV0E)rWya*}@6WI0#)tlB%KD|epQggD#SdzfmBu(Wjk)xBe0 z?Ci#>VGH9>TSqDmUo)+cB4VY6;04Ek#;G_D$&v_-kE0rK*vBs?Ei=Plks3YTpt1mN z5MwoW2Dy;$+9U#Zop~S4!zW`$7Ca>{@=5_sPD*>naIV3myP8E(#*U!W>E}si5rmL& zP=Z~wjnSkwYtMEJ&<_qFk~fS#TxQ&WPt;t@TR3+r@jS47ojK7%XPrDvkbQzuq%|9k zx_px7B!?l9wc3d>aH5NOgQe~e!1I(HP?}hcRLv|<$Y|0`hV~$bRmo-2g-CX)<~1N& zNqH;>%tK<~xQ#>eRX?isiSNZwd=2QbC zs&;&#nIfxcujsr4)8Jqq``4SCW=&Fub~MH5xsja=dV#8W;C3dML6=K@o{zh7Aj=@g zTWlm)l5{LHl~Q7OW;24Qw^N69vIS{qN)`{M&PyLF`6LGnRQkwMGM($`Aw}0gE-jRJ z$`v9=ge@N(6|9?7wvK#2kz+CDfaoKVtk>pQv%|8jT>84KaZcBo6h&cv(fk?N2`_o% z3?5w>NB+x1fwQT=1o+f8+4}c`?+ps}v!il}ReI0~g?5U8Fl=6&Z1@if4hLn(A!AUbBeSA)jF=aLiiVUyZ%p&L?1uVp4c`}(XH8p~4(hhq8 z6a(IG@uW@VpD5!J5Fp_9Y%*J%HeJN0$SF{?#Cs1^01*^^DkbF&D zo%<_XE!%jEj3lii!tbZ_jkSVS2#}5-QIX)fV2SOPsTNwUX7RpDY7~7qxn%iA^}X`O zQb2i^tdAUZszdkV03`T!+AHwMUAhYy?A9kE41$KxikPRPn{UMF(HQI^R=S*lt}GyB zGMcwd$POuu1Z~DG8VAWII!eN}4$#e$>3Ukeo-*ysC}UfCCZpD_B5^`KfV9Wtd>k%e z>bG_5W|F6uN5Sr)J`-uwsBavZ_)g^x3K0Qx@+#E*qP!kCK3MmeHiHtHZr%qNImSUv z1A5OF{|+{2icB9}P)2t`)^&~NzeV43+6mBK2uW1rNF>J-m)6MpjG=~bib__cvs~HJ z?MkPH*rAg&!n$nD&b=n}M86HD$dsr@0jjuRgNOKy~ggJSa2t0BWTwDggE) z$nDpOBgKM)>8xxAND%LxDAZ*6EnN0e`t*dd)L!ABmc2B|9~Wq&xFoE5M=x;{T)n&_ zfJ!Ol`Bc`U80fpNS(L5pB;;nhv-)-(DEHfuF4r04WoEQyvP4m?ddE@}E$$N?YRCfi zq~zX;!?U9ktgx6v@=2GaUyeC=JJrD15sDt!-x2~c_`MJ3HsO$HRKL_GMw9h(@1l$ z7EOdo6GfNFp+iFzV1l)zmxt3qQ~^`CklnseU1bho6OZPo)1rEzlaY+AiCm3l%{|JJ z?5Md*dXvZ>d2_f_5FiVML!!!%b*Owo5v$N-q(`L-;&FrFV4`yQbRhDtl+P82oN#4eSeKSms zKfhUDmHEe^>*pu$w~GtBSMjCnN6~!xzYK(rLydx7sqY za+bRj(sSfKa3VFNek8hxt9n{41LaR?11@3c>v4fhxgvb!W(}NoRIi+gxm}pS6jA#l zc0Jc;w2V=ZTOAx!PG_9`RT#>2rcWSWDv(89I-MLl6w;Og3;xOoX&OJT^_llEOqDO| zX~#F3#OrYDgH53#qRjNuy#Q+47y6vJ(N-U!Q}4V2mQb>s3uqIA1ZBnx#I;`c8g1 z!CuvyB^;woaiq(;Ua7bNSzpb_DVCg< z)k)9;mX6^}dfCW;DETqd`qMe)p|*2c@jf+Ll>pY56|E|{Y+ak2SzJ*JRuNi)0v;t$ z2o=T9$sR9M5A)2S>Z+{s)7rAA&Xhu}XKP5!bH2T~|JUzdUtX`_2v6_U>-TS7{q6gU zgV~?IdbC=txcgDY!3}a~go^eKw^Yw@{I_4;|M>pC^%;j@et7WjzuuqsyFY)?EtbpO zAOR(GMq#g!QhsqzEzHOrVdQhTS{51P&&yesb64URfW+wP5kvAiNx*yBoJP&ff^6X} zMRJe0)HhN%-^1E-;e9YC>u!kq4^38uW~Nd3t*@9WN7IScDD{b~!W|vhEy$va<|czI zy8xD@veKaJvKuk8c0526EWj={0qd!FHmRyq+B$5^4VKp=D~3kPvVoBg=$TKDqy$BY z+?DTZwgc$LvP<_HdUZjOFA8mVc>JEo`Q1gE9L~&D!(Q$*Mg@j!=0H^ne={&`N0Y|Y zG8B_R!{%ujgO({%SWzT75(pS*%=i$b2P)>t!tnqd^+g*2YMms8SMjoDm>(U^XS1@i zkQ?U%WAr_v$?P?JI(rldRmAn0q4JYj?OlB@hGFRET|IXeYn4jkCB~#`h)kz> z#gry)7SL_o8(NXRW3@E~PL=1aDN2Ydc3POS9FR+Knlewxs4C@ETxM#(Ml;!~vL3~x z36KQ=XB6J7abw2Y;Nf9W&+?BiKV05!(rgCX^~=Bgwa>Y1?%%A}M~nQ2FLIKb7un=p znES*ln>+^o`u_HZH#cp1u$-TqoqV{u!m+$euv}dI>5IPcj^tQ_NvZRsuPu~y#5+oT z_E{ZXSyYIsz7Phe9+8+@N(TU)Hlv6Uibw`E>1~Ry%^_tSP5t5_N@kA+JN>i`dbCA0 z3AD*s>L9R4JqmKWPzq%0(PvPyfyEG6!E2oXUy<87(n*6ES;CYxPnOnWe-7=(BuQO5#{xazKXcYC?LTLU=m(1Cm~ zLFCCJ=BPPyxlmR%WI_oj*BG!OP_HJGXM3GaZax9_1jZtm_71aV{F#bNt}F1gaF`H| zcp8!=1Q(|IIZs&1m_plu=HOlO!b>;BwmN5_l38ZRI1E>>ULBoZEDjFZoj5u>3zat| z@j#G0NsMQ>d?j>pLH5H?A8nA*XvdjI_0#OMlV-uY#ekVcQq?w`9pXbQftHv~Q?xrG zfx(D_t9%j*ZL}FD6sstG>a5e<5)7snQcRetCsl=tKH{8l3KpWH3fniN(xfV+Pkv`x z&~nf}6S`Mr-H?A0ReH;Wpx>M6>)YVmekh8Oz(HCh=W^4NYzi4IB?vTUot~-x#DBSTLfXLz)ZP=`?BP$~U z4m`XALMe0(AXHatbpv^nmDEanr(byDwUxkE6*?(*!4_}m=(Oum(95r1brpk0JppMU zE)KS_AFfXG0JzDHk+icB68Lb_H}I^NclG7@@$mkB^Xa}$j1|+BE25T*!JLm}1&dD3 zz~N|Y&^*1($z(QLtUBqsa_CPDs8m;d8EeNHLBwt&*{t&2NNcyU{s}Tk3bEw7Z}<$> zk_F`JGG`wO%~E+v6-Zg*mSMS_UVc11fB&Oyx0`88!mBUyQ;I`%xuYupaWC2Xv-C`| z-EWNcI&l=tS0Eo-;GEE}I-}z~ll9R&b zNAr@z$q+LFYuS$$n>Od&_uq#2CD^q6Ct=sQ|ay}=hv zQ-Yfjy5B2)a|4FwYQRZFN)p&ecK#C>6v9)w;?x0bwd2jaq)+E#GhyCRIB#!${q=ty ze*XUW_=yFE71~a$;j2mHm3hR2??W~4Z^Ol6$A(SG}G?yyega(y_bQ?4|M#v_r zvJP2OIPJ8QIZ&yCu%>Ea0ZsZ8TiP_q0<0C1BpDlhYK8(od6%XnnFQv z)U^wbR0a7g7I*g4S6C!z?s3eT)40+!806^#m8|Aqq-r#{!TF==!79SM9Mo@z`!8Rn z{ho>`jX5Cs`PiW~$>8iYiLe>dI8Pl4Y-0o&upxQqW_W0C%x0y8uOJ6FGs@GJP=&1# zflmMfJn1Mn+~QhPr#Yoqxqp@An>kq0f9vH=9%Z*S%wDs#Savogd6uKk!!KftDrZ_P z8f$fyyRV<$UZ2iy@7vo=*!o7eHc!_%#f5Sc=tp};b9<^lU8?zJyW8xqm!4_)K!k zv^@rGybfFuS%jz;g$WjPjhH-3J7^QIG<0{V5`M&C4YTs(R&6;ckkl>o4A@oDhoPVI zBN`HP$)Fx$O;s&Xxi8%3*@jLdvk+-nuG`jr)wAsPU;g@U|9dxWy07Ed!;Bhldm3<1 zVq3_MEq}WmujO=ZPp@yU$MY{=zkGeT1<7x!JeOLlCQb|OwD>yI_u~{225B~B1`8a) z;*NsHp)fPdiDzNrGQM?V)}1&{sjN&7t@t+RfJy|{gVW|_K*pzNLF08LC>}@#3yJ+> zZ?&N_=zp;XGbM$UX4Gq}uuRM(rBM(cHoG}&ldxlN(*2d@#u2nXcHEY(IzCu!7Bd4K z>SAm-KvJqJbOyPYt2gWz&r2t<^kduo`FzrIk95)gp>AKO=kxeTC)l(h)9&;5a`&Cb zxr8WR6^w*q-9A38;cn>PtdV!yNmh+tHLkF^uS;|9M^CVHatr8C+|idvDWaasrz7k=Zyn1n_fs#t&}7*vXN~C6*~$%Z0cw z+je=q=7J7xmnFjv8+`+61&4>RbCU^9r{)r->Si-QX5n1Zkf>HC zaL7FT!2G|R8sQ9raRw;TcZ4+~j{-x#Y-$H8DgS&pqV^Lpi4FZZqBAbm!^m z=Hc5ff1mXH+Konf^?tb7>|{I@{b6aA9e`f6r65mX6f4#9PIqRlwcaP66|M8!{ zEf4GMZo1oVyY+6HE!A0a5kv>s>~N`;%P9_gj1xd&6YYSN-!?UF7f)bkjf6E4h_Y#G zoe%!F1H<)DQ-q~e<3yKTO0+5w>|v&%jIv=jDBqft^8yhcP8kWXVoSRQqv zy8(BS2zE1=zFCMubhFZ^*s3(V9>;)Cg=wyALg=HV@myJa`v6+G3@ob?&@du5fSsH~ zGSO8N9Fp~e%ym7VO%iD*p^I4Y6|k)d$^kEtQ;F885@86HT?@4Y_Ed^~$4M{NnxbWbGZ6w8Y5? z{hcbYKI_n72dD1WTfxdMo*P^vgh8hCSk(mk3W73FOU`9^h)<{U+uJ)0gZ!M#;itBV z@6^|6E9|DNcSSSY&TVPpmy&cko%&j7)0aroG|6~QXlXWj*me%?9|2(i@j>wo*an`E9xe=XH5h!MG{$cV3O#uz5;5wLbM&DLX} z^Nq8n<|G;w(($bpS{psCY!!`2wBmAaW zY@;kpz9c9SYj^=LswN9!sO+ylC zxt7&1QJ%S7??-|1!|IakmcqwA%~l zi~wNqd}bBc1yn$jfH0G3B#-Sx7wpS6$au}^c$9mQWaGwxCHBKeiMMr)P#p`wSsBIJ zWk-WA0$)oPi693Qv)i~G<{klZd%gd+UpK#$r}_E&a^`K@>6cIX?|<2T+Hae?ge&ZL z-3mfUVqf0ihr8+D|9btfIlVtW9^c=VPrBO6|N6`Jub;2ZGoM5A9n!N+ks~N}E8}D` zew|628|{^=sz=M(%mm`ss7H4Gw+LeoD}W{*`@;R7>T028rJ%vD2c|7!sfWMrPo@nn z6oHRdTn%PyG<#0sdaX&f5C2)vBhm5N6)v?zM7!l1hDn5kubT0$CFDz!Q<`Gr^Jg1? z!(dTUEIXuw385yr+}7`AAR;WUA_P^cUOx7;VJs!2$(I&4OyH4=N?KcSt!r^qFYNGf zf4bAVXVwAON8;xyzmvvMp~Pga0{l*thBq#~aUR`NxH?maQ}K4V^HhWK1dp~twOnIu z<);^4w|&1BOg+%q?4I{biDC+;B3w7BlcU9jJiarq%g4hH=cw{n#oNCzTVXcz6@hRg zabU1}Ma*jyAWp}+mJgoaPfJO?zPmXe&d1~F{Nri)xes4HyFHrXUDw0uw3LXYW8H2$ zL*wn~XWed2-97MpI-Ym?O{ZfbkZWAl<@KC(DYb8}{k^*Xbhmuk@o?U4wy$rm*LT-% z&o6H;FIP8r%l&w@+x`BJe=H^Y;oG;<>3DoOJnN6U`Sp4`S!%^iG zD!X4lx9d9ppC9M{csW1p%m4Vg`Q`qmb@TYu${co5U=$2TU8s5CfQC<0DCwqbi4v;G zP@B0wYGj;nZF{lE=8=zp$$$aX>h3{e@-WOBb+gw-e0HEu)5o^*Q$+Wy+97oJ~iRo!fwWoLjrRon?IGRVSs zBN?S4#VV&qXNNXhM|kbmDaBrlqFiS{?S@v|MAbI@O}B^+frv=-(R=e z{p-uq-KS-0-CK=#etmg)dS1HXjnwUKcRU`qo2}&&bzi`-?px03dHMLZr;IP3uvFIL z@qBoFx%u>I`LfgLwAA0j+u?kg@4wuurDUoY33d5y$9BBEyO~v=A77S!YxzRsH7}*( z{`1%U&0bG!De=d{`_28Q<;VT}{kLhex&QigdtQ3AKirh9lIq*NWM?K_3W~32#9t&@ z8m^x)H!NJ1TrZbF7OLzfb&}u!V$3%`c#YtJR}DKPb?xGqtfwKb9{T2Smd-S(L~19x z5fg>>2LG&$1M!5OeOO2I?sT);Z{=L&Q1td{d$qkS(+=r3Mq3pRT%=`&@-FG^U~*M>J}>igs+%Fx&oC2(uyA(5ipNu+Z6l_V3`>VW`1oDQEPS#1a z@j15a4UVHbW_UYohXhGr#NT=<`0Lw{n#yTujr*gyw6vRHVb#T^%LiXyURzr_(UW%F z$2?WJy4lT3XZ+hAONk!bhHB5y^0!N6e|dhMWZLbv4`09D-hCQosrBl5|N8oNJRKgt ze_#Fqt}^#hyWj0T-QVx8ug*)O`~JTCpk7ydOwH!*;q%SyZEvaP^YXE!7hb;MX;l1Q z|Nghz`_JQ>n8j6fx7q>ARmvM{Gpk=Ov|@=KO_Na$R9I-vWB_1TPl{-dDtv59t zxmh7IANuK9YszzWUGkU+ijk2FY@PE8fbzWllSs9$gjH>4UObqtU&KCr>^i2s+>P69 zopwwhPVVYVRL6)bj45-Y!n$3)b{YV(^h*!kJn>G+JCpPg<*>@=QV$QGvU35XGePgP zl?d7fbN;j$2}YoZ*BM^$<-(J?1T#C+PzMBGkbFU_A8a6uP5{}2Wbib+2vodS*V#u` zRt8O8DRWX(H!m*Pz;4up$zf^5YpCcQ#TILdDmhl2Fy?Yib6ZQCFUYfrMN4w3`j_B8 z9jR#9i7KPFD7XE=7-*O+y8$o>rDe_UW<+B)o-aPOoVBCJBH)r-+j)h&aM)nsEU8UbyZ7VUlPZC-k zn%5E_iU4h6pX+EoT}e@n-PnyD*@PwnO>4Zls$74%yS=?zTGZ3=Fm1N|VU$ieHY9H; zi+7(tU*BH$rP=a`U0)Yj%i*BdQQmp$Yj}!9w z@#*;XHm332QeKS<(5qQ5xRY@$u5WI3BaC|Kc9#aYZU7xEz4-QOw6r&JdOtt@@%{eW zxBY&9c<;Vz1zkQkR6I@@CPY=XITwIV)Z<5sMK@Okn3w zxi#|iib%HzUq_SN8IeOsf2(lEWc8?gh&pkNyn^v)&9>2BF3sF*O|GElA?3l9{2?zD zP5=e!S*x=II#j?LiM;jLcGijOFk`G#UBz%H(>=U&=rD{NGO5Y!1w8hYA{`8EA=_cx zgN^p$u0WR}TZblK94)K#CPc&ZN^RZ`mT)M(9tnb&tn9yy?M=q3jfx(C3YQ5MT-ucq zg{YoyOd=fz;fjPIbhyZA7+R0v{7~JT*BU5?9q8UGmx6^7Np5uY&7YHdXLTz}HpnTK zwz$)nRwNR&!5%5iMg5}{9Vmy{f)Kw3oKp=f6Aj@5{o!zFb3%A+?&Hnh!3e*d)@$wv zz-_X1WOS*T7zeXEE{oEO-Rdkk?}B!7sBn3fz;+`xKgo}c7f49}AG+DzCRgm-gknFw zfyS>{V-e0SU%NiJN;&c0H#p!y=~_x(yS~2aEbO`4W_LJiGj+INs!Js{q2y*MsJpHN z>Ae3gi=M=#l-mk>?Qudb_4MKE7rIN1IELj5kNw|=Q|C_np@F`@8!)J)K>iSA*Isgn~3VhE`WJ8mFkhr%rv{BWand zb^NMz$ah=9nhR@w%^57VeITvVnRu?Y!HkatP^hfC)n1#K8XzS%nKGFgV=`X7UJ#{32 zoP&OkS%NZAg0;0agmwk42)=QE7ba`H`4|8vG0rS>i;l)(^kCMR!g!v!>=JGVDf7)` zktyVnSED*t%mvOAhN3OMzT_EtMwjPAA#cN0pw9Ma{oc zBpqP2)f8AGbZ4F-D5$7rfjjS?=9!^(=n5keLZmm94fBFS%Rfrq(tvK3H~n^LRGDl! zdPiGwOuABA405Z9q4dHbP@Rxe(FK;>)pmLAZ}0Aw_O?@7=N?s!J(Or{gVZA&H0unV zQ)~cyr?}o+*Sp(!IXXHljXKr32u$7ox}mYfJwprml6Zt|SS274qidZ;*k&SVcePZ)tX`GYU{codV~i7SpTOl7HV=DMfI-A$!C3r%(RXvP#F5 zs$BpyoA9m*93b6FwKBTSynH(&pl17BO|2%j(sWC*wT}oTV`EA{kF4|y8(vVBnFR|Y zhNcSRo`gnIgRxr?HwlOcu@2;&BOuJ(V8P3lreU6Juin;1+<<{&OC#UF1Z(W^n=4JK zNd)NxRgGhBoP;9&l88SDBPLriuqw^*L}-z%nm5Fbj*8Hb4%JLKZ3!tnxvV3wVV{6+ zE$(!0zc=N74boh0^1@ViR1J>|6|cD_Ez#s?p~ZKOxC9|Bb7{4>l+iV927a@##RnXB zFtdX_x z6wTcd9nJeYFd41c2+mgf?bMF7B-42jrYaz0TmI0*Og|XLo4rp-v3L$E5C>?1k65S+ zPbv##8NF0w^?som6z4%Wen`sZ6{@e2Lr9PYoA@CnAKcsrhpTz<9nQJL zj=(%)8HFp(nBan9*jB6wk3>qEI-ob^L%U(^gMv&*6!rYANZu47i!b|Lil@c${PP@N ziQH_`R{@g_pJ{|qZ2E!@N{~julBC3tN{>5prRb0H*cRhGdHsT>;Ti zlAr$^<0dWjymjTg3pc_{Xlo?$d9z=goeZ2IY7KJX;6f`9*cr*s((szVcB9!NNJWCh zOSD+eh8&+wYnw>%X}HvN#CyRyu8=_1#0~8Xg~x_FnQ>v6X*^tY*IupOPBmsqjf$Wi z;D8N*u5$T2@4UEA)9NtuASDcc2!4l6n@8#)hMB@8Uvp;%YG+oAQd^k{C~mC5t`j&W zmcXK`VK40rSIb)exX3keik-kE?SJqGL2!dH z`HROv+McoM%6Es$u^iukFJx;YoIndA8u@BR8LH}uHoz{Na~9a8g9Cq-2CtW3rmjAr z$%Xrhe>bnfUV^Rcu8idExo#_+8-fh_r_JaKlD9loYI)ZL3rNTdC5%z3`yBD8vmOZ; z{pkNHn*{)IM%6&vbWYtgiM+rTC-j6tHm=155t3AR)uX7ZT*!!%z}m@@%8N^&DK1Jx zEIVS(gcM*$?vJX-D=AcPtXRXK5LGn4fl7Cclj{y-Ms1`@8{ao&44tW8BM4J~aUtcJ{$kzGL}tMuGsymcc* zxuwhAWYtmrSrH83gZDwrZ|jOlxrF2aQa7rnSOEq0$4x%EtH(;M$)CQAi(YueY4yKK zulB8;%oq&4yHl( z|Hl$)FceE&o7kmdnmk2=rJJMa*T24TJpB4if8#b9Q^VMl{;oHyW5K8I7~nB>hA8tuA<(QrQy z4=;zex3{HkzQ4T{)6}W%_E$>}1T*g8+rU zv4$)gCTkL8L?eHA4n1hDCH{Ese?J=OW~Oa%WFxVL)A^y93!K{gNL>>t7eCaP71cli zEU@9<#<~n!4090zS*H1QEMfMqZq~f&=dI8T5ZW5vzN@TjHFcpo9bchTIg&1)Nf$h8y5$L10-AL(?eYYa8h$kS4G-Wb6ozv7TRTi#l83LRR3|l**LS}? zmr4*y0kDneu3LJV(S#cZV>g2cyUr{?eWObaT9|N;6%zSIxv8?-U3Dei)z&(MrR*-B zxx2nz8r#io``iD0T$PV=<(urTw;ioG9(PyUPxpUWUeosaYN>%e z412H`Z|?3oQS|Y@Z0S8EGtL=cHAZ?}`4x1&I3>G)jm!LU7hA6i% zQnSF&$#E?|{LIFYvMc4v9<)^O<0o!!nlAv{AW)L~U8--O;c+aNy20-&DM!v&W~Beo z<(=jNX#bhh1RTXZV{$6hma%q-8x@&KWn ziL|?Fw-eN`Vy)%xnO=#k>%v8cD`n+B7p2*M5ph=?wAkq{GS<>PPch04rwP(23iq|v-=>^bX-b|y?K;Cb0dOQ>$eRVW%+v82OH zEz_%;WC%Vx?n?UGj1>FNl?3=ikDQ{Gkp0G<1C`=U^X?O-Pf?Jje7u@@arDo;zPmoW9z?eL?n2!^xRl+c;_Q0mou2;q zvHa&>|NGyUAGDNUk=xehtDCEiqYi^U-EF^q`!;Pi1`f=pGY?a@BD6JIKWFE$Hm@-H zt7F@16<`(*5>QW(R=}p!ObG1BG=8C4=qFlQZSKoq-%edsPemz^jTqqZGsbf;n~jYL zSWS0cN4%by=m|1n?766s?vlc>VP??f;Nm@Mq8_8OH|tV6U@PHg9yY@mU&KSLOLGQs z;~LUazAJ|t+O5&?L2^rr{1Fh@u>Pg01?KMtmYc`VL^`&3>Y5~@16^a2nm#U!FQpcM z0mR7TU?c}mgf>>MnoQ1pg>_LYb2;cNfuw*y|GSn8;}Mmp1)B5NFDi0AS(E-EmtD<2 zj&1u2M;3+(OEA2nIWr6-r5u=CE@k)>IKXkhFn8a+*D_mvm^Anl-{8_=vTTcsY_#7V z3J>2(aonzwv!jCbT72I)PN3ToEjmwU&#^=Ytt^HuyBx zB}zug?HgVoQR%u=l2sfX7S0pJUpr!SoSU-3OlTF-okGLiR9hfvz=-1ljcys+k0wZ? zx95`VLSVsFp_f;8W1v5Srch02iQrAOyu|subg#PIY#Ha$OS9b^k3SxtUtS)*eCvdy z<7s%F(4Nn@M?<+PQ$_vtQCs7L_j%e{x^WR>t#9$scC${!>hjpRshL4`--z+cTASM( zV=Rdn!{TMfIml)_16l|#6}nZ|%a1LMXzgtnZ2__{6(%-^V|iNFyoD8j zkPb*%I#fs4ZN|muphYrDpvhjYu|*+Le6iAu6LH-yyWpkd(3VO+ME?%)BLyZdYr&t; zca7SOq%(xmUu4H5)8Y}2R4miT(Z8UG7G1R^jZdO7N%In98GgCJxB~63n-gs|#&EEn ztDSl%z_44;hx>=?+pBi&t2zE4H4KH8^TkX5Di$?wn}*p$FSsMnvUy}^F^vn-H=2e9 ztRRXf23chl6Zfmv6h6~$#o6Klq1m&{I&oXeR&rpF8N3PC8&m;L#WIRquLcdLLGg`p zorcdhHJu`;V)c##$)+)y2~UU5G)WPh(!px=V;`??7$_wngz zl7xE%X~YEOQ+4#Drim^m9Tex->ILzX_g)QK797I@-|lKyOZ7nUlE&~xH`J~iimmJl zMg3E__JUq^!3lGQ*~)(h+>AuMKx#>oHOWEJmy44eY!;>p;{xhkd-@TRs42oZ!#b^m zC_`gS90z2w#B{67v^<>X@j>azpyoj5f_xS1NGrYHBq#W-J(Q!m`7$$c=}KBi%11T} znV!Y*7Ds7G0-S3>JjXE=?}g;RCv?iGspWg6vPt)J7~DD`-H? zt*mW4Vf2F=A&YKe_w7YVJ&V)>Gp*J)w7@Q_tE+eh(RjE-O{N_F+(9jx73)ETy_rdl zZ}0Dh_s+_;-u+d0A{XQmG6@0v=5$Ud5}B(1p0?VoCF~}!84xEcDx_nfE>_A`!yXpS zu&&q^>v;ouGeu}MrG;(YEarpqmP&I1reLd09g1bX(*@AE%wfAL>WQcx-I$pFXe?Xo z9VgmFS~hr1l!#i~PeU_kk^%z36@crmZ0P+h=|Gl%PC`oQH&X*5HhlGlBxaSe>rpjM zD5eFa-8iiDPFGJWVX>TUWs;2`0xQMSK{zn=s1b!Xp)dz<1=_9%Nf&#z4;ypIoVLvW z^~XOw-tnLA_QGCl^_fx`dMsl(4Z(tyY)uR@n5>61gdXws93Mj=+n9 zEwfYn*vstc4@?zZ|L4WNF0hOCagQp@5J@(27c@J`LJW%eDGGCFSL(V!pmcb=)vY!E zCRjKzVJrt(Dm5-9KgqK3!sUoB?M+G4ZRTwwCb9VsUwNxo-I>0ePN(e7WK!*OBI`?jm(8Lpe1s$1(w%}c9 zu(CAu0J*+c-Vc3;mp*$Kn!^0RfDU^kJVVbA`jPILc!iQg(j|?#bU6so5EAm0DSpBv;l|^f(TJYntZh{> z@wFJ#TM6H$k|JX?1=HYupM_A1;P|2Z=kj6paX3Hc>p9f(O(gBvlf>{(O0ZV_STFG9 z-uKmuw5P;P^VNW4)}X+CS=I^5)m1iHvQ1u18OiinmjK~?;A{Aa)m?g7XPLd`L$~BM zcF_2Iinp%We>-)qnAXdwIcZFaw1}2Xif!d7^^x{h%1W`Vsb2pnJFs4SgcrT$ciw)f z%mp0RtMNx@J}k{?WJN8knQxaxSdtz4;8j$Z>)?|j`2rUKpb|Z%Wt_ocKvuGjB-|{k zP*Gz!(`I5MLod&7cO^a?*{ThYZtQ8TFb4hgZal(ykSVK?Dv`n3}BT?=vJh6PL8`==~n9`U~JQ<>RV=`8SY!JsF zG9piq$t2ao2`A180;>o!)*%sKxMKR1Qt+d(Zk_`wB8kDMbpweR!E0jWKM`$a;;HnZ zU0zRrX+x7zD=p^YWFD3FY_+EPi@xlFP2q(m)m&MV95fMlee{lB zt$V(&DO(VgsE|Kb(jP7*82 znZ}P;O_VsT9^V=eKg+JNG}Ler3NBJAyqXnEm4^F_V%mUfUFZo-ViaKkhak8$2SGw2 zFj|DZb94bQV+-eQvQ=7&(PlFp-j9d(_qwUu&Gvje{d|1f?e@3#cTYclZg%^zsXH#8 ze>%K<{g;2~DzW|c@OC_%j+@i;{_^_i^TTepGsx)W`DH0ocQ>~`zyIhh_jc0Ld1HhR zE+@(GnHjY(s%d1Mhk(eG({A%)6azyl)#dHY%oGiApVK(+c-ly<=K@oqdT#CnZ*A;I zb20}~1CEE~kkF_h9JmoaU!lCy}0W zA^23c5k3a;r!W{?nBW9q53+HrsrUQ>28m<$pedh7io-CDLhv$-zJ=Tt(s&!#=Bsv+ z@ljqSVdL%XsyJNEGjB}`F_&Ul<3F0J=cQ;cpK3M5*}1&J!GQ}?Q2)=B+9C*QVI`Vb z!2VZbXI(26#VyS)O50TVh-{Q#MgeXB8Z*?^2z?Spl!9?3E5S^~-`5}y`|xO9T+Q9T zs6!BXA=t{PO4d4C%}FyGJ7YnH!gALy_4l9u`2G3u=lOIbtX=Df-F$w0efs(M{`&g* z{POzx^7zkx_Bfvbj?brg`RHb|efs|6_4#?)PO;P+r^fO{r}y_R;yCHm-QCFVX}+Ir z!v>zP>ky+5jjXh!L>Ren4Z%S`EdRpHn(=PXe@aF>O9vEK?xn3HvzlQKV#>M()}fi_ zRj0i}5CQjUyn-o<6%1dXL9Cb*B3I%ve5;}3n8)2;LlUM* zQUND(EJOcv~ynuxTEbE0lEzcxN+J%xi0u-aIw zsD1dw|EDl7rv<8J?@;ffgN2%Dy;T#bg<5^;TCnU&In$mD7cCpjc_EArZSDXfE;ffg zzk7yAB9KUWbL65kT?>W7ey9f1F2gwLQ_DwdW`EDU;Z5~7U#|=L%Ev{ko0Z1duySAG z%SZ!|y12_NtH_KaWj-zF;yN);1S2s83Cl1{fT|;10ndxVyW%y95bIa8H5;O@apqAp`;m z1jx<%o$ov6{y6LYxV^ep@2;+=>Z#hbSMRlZCn9v!i3#Wl000271{|gj0AQ^DyUy@{ z|0ItHKEHoAI$u>2Ujt7E-vG3?JpgLwX=4x8a7R1Z>)WI4f}YLT%L4$IPR@oVz9u@_ zvbLV?g6RL~2nM=){X+u)@`{08Xj@l%U$Bk6qqBzs+xM4m*uc(q3T(y_I>I_$D)vs! z@L+FygJ4}l+hA8)89O$`Ct&$N*?$Jy?S0YUKzBC}AK5?!w*Rs#`>*{Uu@D>hzf^o( z71;h4DH9z8SjE%Z9xNd!CSWTpA_A6_6ciDckdzeR2a5`ehzbe+J0%4~#APKUWksdH z|9!Ci^X6^mAgd2k`)^T1{L=MdW{M{NJ$3GBV2IV$u>4GLoVqBC1g6KP*%lsw|)~pIBKHZ+o<_r?;V}r`!Kj0K&=B*VD(z(+jL(APMHtLEAce{71n1 zpAPz8@xtuAo&D|Y)Vw|2!T*(ES?B)?15r_7QK*chvcx~~|2uLROjJ}#0t%H75o7yr ztlj^gtO@-iBlMs0_fz5*tBP}08Cj|4H(og zaI@u=V>X9|H>Z;eGk*}ZyXY{{(YY7jpTmQL$G@a91Lhbw$7Ng-S-1hq5*|$sF3cOz z0^%-RZ0zzS1-wCbKY2rbeg4Z*OS$>i0HEo7_-Ieb^Ec`8ueM@N`8RX&k8gS*;Y7C^ zuQ3*00Z*!TKBtp~t0lCL@84kpI|7!Z4*Fu>zrgk7257QB*L!pc6Ic2be)#jA0dUWG z7+_RS|47&NR9?k*YShcz(1&ZaH%4lig0S7tajv~*Xe2|fJY4eL>d+Au9`{>*&)Bw~ zng9EbH+=!XN|~TL@vERCduvKLJWGYc-;a*p%5yXojd2%Gk}rdKq=-*qR}>9tm>=uZ ztG_ISC51`etG%Sk)O!k*mC{yBKe@i&4IDde;*lzFufI?7r9KF$k?Npn-h%z*{Zw(W zM*L576vLMt7gBFf~(!zWka z`LOGfQ3_RWyusHGH0seHf1bLr&feyAG2F0lK-?UuBKQr8Ec~fCx>Sf{PkH<&ON~Ix zN$D-b_a38~7;t$udLH}JKI{u-xJxS)$(tzan&0ZeEb)vT_hL*O16h}nxhc9&yn_jE z-7I21O&!P)+;6eI*2>n32qgHFrF=)3$C6+f7if7R0vs4q(v91eMGXIv^a{Y6;9w0> zyL~Gwg9d*EzfLXTmV80l_~UeaB&53c&BBnwXz8?(Nw#CX(ha9G_M}uy`BlI~EdKl^ zk9Vhyw#b2B))S9uV727%fO8j*gm7Q|@;*c@k>A@b?SmQm&aS?-V@Gy8{OC_sxRbHk z#^Uh2pwb$Mi*T5vAOQGk=Z?h4sGwl%la#m6mwn8mlNs{}s~8tcPoHe@tX>hcZ$54ertfUw$6K*r;UX@lDiM+-TDWoJryOF$Ihhq-|v-L$)5F581;*KB%L?NI%HNEyJT)SM%FT*xKx$N{O@+p z`5K}_T0VW=o}FDs%N99>XEIg!Q*h$VeXXk5_lt`-%Skyt>y%Ld|IKc#KSnx%)v8V5 zgnS;SKWX=Ap7SL)XcWMG&fQ|&*Q1I|G~Vvu0lJDJ2in`3Kgx|@7&p1V4DKeGDYLmH2v8x*Zq#Yi@`~Fn1)JVphIyOVe8ty? z&Qlxx(CIA;Rg0TZi1`Kfi;vsEDSE;Sl#4N#ebJ9o0a*9IrcOcy0^hTU#Gh(v3UA@* z@v?RhI*5FiP{{`qO!2O!s1RhluKI0Of~@PcUv}A z&wBtvbLzwgNAr0FnOF1uKWzn%Ji3gw%>h2#qeGehpQt(n>-c(i^9J|sRU zeZ2l1=BjS!uu@fX*0;#PQlgwq2tJm$Lb<{lHs<#MPTUDnErc+~5K`7|X}6b%!? zd(7S4an9_%OGM7;&^DB*dQ|RG7g?iO^B4>{H-83|$cq8+$;*C6^BVwU-q7g#pp3u` z`jdE1V*8nE2+bpRob2FO#lmzD{^|$78&#zzdZhv@7lV1P1dn=n3tCSt_L9f3gumu3 zCYA^oWm3v`YfyNn5OL5*GEX;qrPxq*98?yxX!EwCE$c9CL`VC+?Bqm&Rzh6MhVfRIRb!pd!6gRoQgbaQvBqstnt1$NW^X2q{1af=+4)IGOk2hH7l6e zC5muB<#ie-{M4is@?VKwFX*8bS+aZw!6N0V-tT^`hUH}>NP2cx6A<7T_(%mzn$mJ zBM~_O8MVC6DLFfSvR16{o> zO4t@CKS7z~^I~QS_uWQWqiP?+oII2Kg>DzGrVv~mrT6UmU5CvL)b)4_4+h7JLtEjL#aS-CCiM|?eB&_hR9fC2 z&jcMrBy?H}He%S>xmj5c`<&DI^4J(Ak2QRT--##pD|=FPGEF}t76_x(yyblJnd~yz zh<~B(tcN}$c6us`(#mPnA6}nyO9iX32%kq;Xd_*L(T4KE=rZg#jd2@p9ON=W^4dZ0o7`GLPCY zq6wXqCCz@on$kVe%0aemY70Hpe!Wc_s*=tfm-yP~MpV{Op zc+1KIRy+9GRsVD%Vr2;_S5XX4yJn=kRH@Uimz2p`v13pG)q%Wxp1KRd0~kfC;)$B- za(4Zv^t1SWj&-edknY%ZwnZ@ofB(KH0I_H+IC_2E-fxlPRE0;L%N$jmo!I2fChMW3 zOZjQqRGeTdshLPa3KjLppwz`kwa5QMEPQ?;rQYCA$G!ZpTrW&Brb_NvPNfS zip&B^BD5xFhiL5Nz{d!~dvi$!;s&jx)H6SDDyBf^$BdF!Y-6a;1-qMMH=2?;I0I*I zWBSy;JwGyxm~{`--=_F;K5cBw4Ja5S9NLh;m*NfsYF6V9jO|L%Wu-lj>3M%_bNmXk zeuM(?CgEgjKlbZ*33Mk?fbxT*hq{`w=!`3PcgIpIYYwMOIhw~WuvouklCdu~oUIm7 zE0-?s3*nw*P!SCx_|qDS{d%}f16u;s29kC7i^froj{*ymO1xmiUaFUD^Fuqc-}IJuE^ zicQfI(!~oKa9LiO>|^U#C{)CBI&=oBQ}#>1xhq$5;YclNU$^P@(=|lv?DQ zgo@VnWEoB@XkG+6)3h9g%j=OiGjG@T1k0rL#jKNE5pW{V@NX5XPn8K3O^htJWDR)4 zNLdB#%<>{o(8gF!{5=X-<`9E0NoH;iOtZ{n?sy)+fe` z--zAC!-Fwy#)8l9OVkBZvtL9MaHB_2oe?;!lPPLq<*m~bvo&eH0f2_Xd%~rAl7Zl$W?XF`{`JpL8M4ubeoS0&1&~t+74Zw4om&U1JH; zhBF-@TCk!9G?_I;m2N>TbyM%FCa+X|)%kA6?j<|F7%XaKQe@)LhwB^5y%mdAkogQjK#=CaEfWx^9{lq5B~tZl6I z9?2=gJlNJ{Me6m~OEwIg`6$bfr0NRxtuUNpxl97eyo~kOYCom_@PYCsYHY{WU=+&i zLpZGE?zo!VYG&@P#XTS4!qX4VJG-E~tqGzJ%-ZB`62db9OKOio^1P-&W85fqv)SeWES4WE!>dH z9V&;E5`;GDSl{jo9x zWN2N1lbycL%4oq5I~h>|U^*|BacQid;v#{hUF*~}RR|6zANt-RERIUt>l;H*om}xg z$*3~Z1ed%)DwAjQ)8mVrfsqE8#D(R`Y-=0(FzaNX;rpi3Q(MQ8pltAXI1hAK;c7)$ zbv+{)N>G)k3A(f?!5JMQxpkglCfEo09v!Wi0w@!=^luS$KY;6z6P3$T2{{pq_jsw( zI8Vc@yQe$5J+8{3B73lQ*)`Gk-p>?~8`Cy5U|QEQ!LR&G#J5>0cU#&vDoUSZ^u?mR z1q4IMGBZUrr2P4RbZUZIelf)CN}PpxKGryb(!lobZJP zJYJNe>h}J#p30<-O>Zoz1h`QUwkX@jha_J17a8oj)+K?XXR|c|o!A2|Ivy(N`j%(K zmoJhm7x6cy%s~vZ1sH7KaSUo=YU*;2tO+`xn@!PKuEMz(&^r6X0jp4g$=ul(DjBuY zj7hGx7_;v@YcdrkS`E|&^P#C#$fs&N85ca2mQN9e?i-tvVfVUj;DdD;Lhtw&Bs%>b zR12B@yg-^`GQL;ZRShB|OlV2B=AjY?`$@urGzd?tMN9kgy0lNxRwM3=M zC&BM}Lnw~4_F6!h+^hJ(_!|s!i822sz9`)%*(77+4c1p0_C*WFD!*N=z{0y@z0ny$l%n zbod3w{ao93O6+MA-uxGbmnHMUuF1DI>#=UhZioLvpt9{w|4TwZ=+for;Z&GBnDSdgD@{ByvSdY zY0_xKZPkL?XmvcjPjkHWBCK6JUz0!|lkfG14@$`}3QN*Sv4HOJEWPs~ z*eGVDMuJvgL&W@oC|tO|N1bfCfx#eG$zV)GLSIdU>5JD$h5|v(rg0~tY2h9GS%<@G zrH5m~H__bfjDVe$M$n=LRWX|k*6_4X1;KJ-iDxhf{P(wlnRC0d+Xz|odATacAB9MVOnOw5~;VC0`($nyI?8Jp!JkGqs^7w#^0Tqhv)H`1Q zXJtmBW@&;qCcd4)3;JS}OxU@VG)|!fK&?l(x3Eh+ix-m@a+&BNZXH2<6McY2cZ+09 z1y<>U#23n-x*B;)y!k*(PMq=haV#7Ca^-XNgbH;?9VboXP`9ZwkkW32DuciiJna-T zXW4>v27zN>ApL4yv&Au7CkoFB;)~jl^u4*B;X*wTGCNqlOI{j3ImOUBFD!YA~;MYDC1Ja77&f1Eg@i=Y{)31x%NcwTB(Uek{i zO(&3VzQ-WrbF`)LSW`~^EW-lb!gBL#rSNnBOXP3*=XX#4Mz@ZjG_4C7)1qqiqvG=5 zRb&zgTW=2INbqx%+;Fs^xFKf~L+hPUQQz5SK!vRs!v zS+!mL^sAAY_U7eoEj*EDjQBgvY7!W!2%g~l;bEm$!!4YK7-iF1@wv_(rCe{+T8Q*| zlf?n7a%)t!I~O**zoJ_l^|@Y7= z+Jt?J_E^{=IOcAWMVwCZFi4+yO&nwn2jQaiO7B^Odww@PT~!sclkAju{nIblJU6Qn zM-q5LmC}>cozjG##9%nsWF-|5i%P3+5VfCm=26JO72VrGOG?;lLu#F5dhDb#a z=t|zPDjqTu(|xsd*)%XL03Uo-%XP*!#Nb4E&H7ohPBmPTTbZcfbB)$r*2xAdBb1ys zmScdwuvQ4fkFxq@-BN$x*W5-20r5aevbdu&Cd*zDiUc|Z;NHC$!%^o~5ZBHx`^pgv z!8M|uE29~UI*I&@j)^v#6B*hN$dhY`V@PJv=uEhbF<6ky`~vFt)2*53?ZPnNv~J#t z0+V5EnAGz9pX2xAnP-vrJu#~Wja+?`NR1{E0U2~vOA_tw#VGV#;LgYVgN+ z0V%cMNDdB}Po(hTU{tSV`zU%mdv8L1rB#ze6`ziqPEvTr)`00w0Dk6shB{nSAFoB` zT(wm;^u}>V28n8RMjX|SogaqQvqA~*kGUcs0J7?={}n#7B~4dPIsbK4QHOu zJ^3=^ylGWUNSL1(3&w0NVNnrrCfFXMAtW*m+IkkkJ6C<0Su=6QdDr%BbqMo_c zBgI)s9+4%`9NltZ7tOBvR;0%v6XfK*tV>%}a0!snOsBkz;aEo74bC&IZkD^ox6}_{ zM%b$dV@yZ9?7ZJ|xX<`}q)}fuD3fx_tJMBq~m9{lG z!)Qe5husf)JqqLBj4@9pYZZGmCBdn*C%aVNpgg23IUP2H5X)2>YwVjM-uWB0-klr= zf)wVf^j)aU!%K-$1wUqqk;UT-?~De70fZDiFXcj&8F3Iee*f;n@@$3>UPX5~UNv`0 z>%tk|UJXH5K=aS8?)Hpn4nzGm7$N3e()0ok8*f`|WE1leGF=519Zks^%GRNUpQusR z|C8qnCe^cE@3cWEZ=z^H2ET|dnZrAi8w2|urkRIJJ4BZNp^m`(Z+I674)dSksQH~M zz;5mrr=*|1O;2amVp~mk`wXxiYLp9(a8j8-ySlr4Cj3**a~_>%X;RQQmN|J#)LkAzQ#f`7oawjUzR*n@G6zGC!GTG_l!hu@~k~ebyZp zLJTfm1C1<3CDHl;d;iK!*qSJ1rQ1L|@S6S#3IQv|=_EDTfZovtVD3jK7P zY9A;;l2WKLC?4Gz~|p)g0nh!}koZ zR~2&tSd%teO*cB6mYrB`+V6q*a`JO%331HT@3GCvVMD}?r3S5=kJdX`a1Jk=U@lQ# z!7VN)@`D#M1!+WTO;p+F5Do&!HEU3*A#HU0>hIOK9M-NR6OMTOa?a1L3HmLTm9+@M zYn!n@p3S7KA9N4XZKi=0{b}PXFB%}GD=U;`s`Jj3)S;8~7D=Vp^Q^fi`0LVIl=6&l ziIk*p;LvT7Yry0}YzlDC?_Yt7Qy&r)Ue$F+YH5oO%O*fs>4(z}7=1aEQOo_G2sA0R zUqe1)&n5Ga{mts*{EFAOpywqT%QW&k$__}K6(^f<2WaAmM*TtZHZBn8bgc@<(l05u z-%YM-H!a$`P7}dltDCXw^_8ep3}3Q9gZ{IVBy?ZPnt*Nqz1v2O-2t_QFDYt*rEac} zwvTe*8C-!&aQOptB;|;1c~k-#PafIy?Fvc!z6;;I^6e8DpGbpjDo)EK$5_#in$L={ z?XL2+$uu09zPe)hD{vdUIS|aK&>Dc&^6ymX#w&5>ki|#m7U8?sDF>~K^=M(o9yKHp z6D0Nnh6lq}_=10RS8;iXP02~GAJ5NUxc|J&S=l70|DcdJ@Gf@6qIrTH)yU_F9Wl)g zsbM-uuxE5Bay8~!|I!$pV@KSSLR>pGZ%&=Zww!XBODfZOd~&fGhv$l&X7&*zXScHU z*xmbHQ*tFFvd=(ljsO#OreA_msrsrK+=PkNHLNzAD!7)$azEfB#bmuYsb79Py5o9{ zj$+{lkWX(?AU5^jRaZqMiyv4kJB!`IOiLS4-h(1eNTndfn_C7fm84Cj(Y%8oUwq?g zL&yh%rs8%Bf`VM++7rLZEaFgm6E5_i7B zaMK~SM7~%^O2h$kV;D9nNY|cbujEyu&@pfp_J?&5MkLVmXb^|l-8h(?>{r@_W8bjC zubQUxjEfkP)39;V+2{vnf^2&){d(@xN5F8^VxH^5ZL=`R}H5k(P+eyUSftKN2@UMJQ;182qt$VyOcFT@!KCtur(N` zLMwe@z(Et+KOz&U@+Urx600gZ)#$Zau!?`GQx|iR;VBJ3X296jF2RmfROKti5Vovo z4tSPp6@RDfDmmEO5{WcD2-C<)^^Z`y@|Zp2-8yD(UJGQyNc?B|RFVTYeMl zVO(SnpL%r5;kn<=x)Z20SX*fDtEOf+g1Cng%m^hF3{)3kJesob-526rT{fN|F&sn> z&(*iZ#&1UUt>>cwm-2f>gBYOQI^M^mTRd~7jphz0s3C)W5nO=E5T7gBK)H!KPiUTZ z8=2jK(?50-ln!}PZS>S&kYZgj0vsh8>SmFZnqSZ;vLS`BYGny~aPIyvx%F6`>E| zt#T673N4J|)kvg+*Ah0%4|eer=Ua8=ZdY=Y(C#C1_eKj{tRT2gbZM}NK%4w;X36K6 zqDktOvfq#^XD*GEM&Z|m6QG?`>9mXhgBG<$&ZFo;mAdAoaMMxrCwn)<~VruDCnSyEq1j4R^7P=%Ds2S-)()~iCO-brH# z*D8!U!~IguV0tATUrbIf#a+rxo|Y?VI9_!im#C_3rvY;LM|Dz~PW8u07*#ieXe5@$ zT#_|x-$a%Y#mDuNs#N%M%TsMXfABA5w(RG1OT!eIqN!G_WFKK_(J#-a1g3^WE5W!a@2R0yZJi<6FMG%&ptcqT-xizS z7L>joek7)}gwueNRMa#L+kl)%)AmuVE-9<}L8x?0$(M~?)5_G98CK;~ocKpsKzs(LKLet47#G;? z9REyI(%}GE`%66n1Yst%Nv-NCjx9B%-saKjAJFGEBdnM7RVaXQxgC;;j^e3h?)h}2 z5G~eSO@cGI6CstMGjP9QdEdpb33?*>_7iXcPEJoHvy1Tjv%3N8%}%H9RfO7XBlISHPjv;pq&l^ltm z1*K$2rk%-XoPcPyI+B>sr#OywLLYwzR1OmRJ!S$qKW3AEVMXZxG)iYFJJk)YZO8~Z zP6~_&&PFQKi-P&ubDgszOMGp?1^vytaV2 zkbK$7NpIYxnr{&fm=i5JQT^RRIvyMKeumlE}Z;uWRr zD=V%his<&W!l4G}*OpG>9U3wMs1om5475xUgAs4Qaq1hE1l8m5@v}s+p;doej2}ooB1Mgm%LtZ zBe>^`ZX^ZGnRViR;?|r+DK@2P!_GSpnY$`%UJ(as=(V|aAqCX9E^<-5%Cu<7ytfa- z+|5SZ1W`ruc`H%A$`Hhn{e$PW&bS_TZ{lSu^Tk6)=8_&?(|3X{pQ|#Otb&9Rb^KAx;sJ*HLwzRvNPU+ zi+mQ`4k^sH*pkxcElpd4NGXm3V<+&jsDQGZ^xl;ldS>{kv9w#V1QKLa`>`)E)(10G zTLP*|}K*PZsCh$)feq+j|GIqq?=B8BEe6Xg+#WtX+emHDfY z`LT}U4DzYAbv=tVBKt`BPMqtVk=q@{=5~&*!WoX@0fY7cw+Tjx$7|qQRS|}HqG1Pm znXcH;P0r)E`c$9Y>*;n{vAyFr5}1DY$LX7I=w$KEN4&Vgg1VKd%ju~45M~Q9%yXS| z0{ZDzu6xhhVkb97n&`khF%$@=0AU&We>--#9B?l_pAyyPSBV)Bkb_524>ma39Bvk; zHCZ{XmTC?5&RL>)OHM{Fux3|X`Sb_9+lCDTgOrFlKUdn952h7H3D>l6ktK=wF_rvH zdAq#Ks>Gg;(%D^MY+JVDSs!mvO(U6EmUk7hGCs#>MDjy^!PpXKmw7U@&^E6s?>z7K#wEb(~OFoFRX+R#-d+~q{q%<%$o-Em;V_$l>=40>VhI_>6NZoM9% z$hDY`oXlz!==}cp>7*IQfeU5SymsEjn^m|t4qsB>DkWJd#WTl)^*ZUHNnRD8P6wFv zCwqcw-V>?4O2|Fq1ny>hb~!ny*G4fq%WOv#har)uv&rX5CuQCKP2xmU&$Ujko_VFB zhDYNPl}l~X^LbqqNLycXoXy!NCI4>C6MlAe5rz+%awglNHIdC0MVW3&49yXc zA8@YYm^voIo5jT!@c@3RS)DXivVztHxYT}AiYO+ivS0WLTp)kyQj&K6fD`$}}r+(_uMxt38SUkIU~>#@X-1wK5Ht3=%0EMbJzBPN&A6Xd~g6I>9hl zMHEg973h})tu6e!+*|hl%o6yy)E3}$DCaC1yB}CKg|j8_9e)bcaxx3Sw7sE6pqK1d zzfrQdcCB|UKXWD%oe~od!kMKr)8?6@k5fdbugLfCV**I*7HS{9X`3CwC!a`g_4iKO zRpu9CEoF#u>g<6=oFYezG?->b1de>oN5*?Z$o6A7ka0CWjQ!L~1s;wW8d8|Tw)F7+ z4XTANXgaBVn%(ZahwZPyt{Z&<|WolMie zaWY^(_PL6cpU~1BsKfW%)Kuslxxe}XMh(NXI_^8hiVqxyVEI(m`<;uV#qxs;HHw%_ zv&FWceJ7`H<9~Waganp*^iC}f5?YIQ=%CPo*&j^X>O?NB*}qK+*^)$LXSIci5{pJC zLk?sDR@BIuo1bc-g-r_TiRcs7p|)w4`gl>M7)SL&n^*H+q?@JeOgVT zU(1F;US(zb^vssDS!legPL#e=`k^JsR-pZhRRbwRmpb+KP&UEU8yu|E`$3)Hv-Wl~ zUG3YyQ$zL!DcGFjU)S@c&r;cNF->T=uX;|jz4cOG$TaKQeF&XMaAo0-v_Iw1Nn}$C zy64HF1j@=Qm)KA%bE;Mumd@0cQ(xV>Nn(W!Zgs1e8pD;}Q6A+VG4YoUO-xnE0l+^P zhY5}gCF2J=d(Ey)*k1Nu$vtRX`=t4IhS;AsyTrg4YNtS7Cz^YjRqCfx{JZP?pp$}J zTE)>Xmo%QL&1MTijWrv3Z(rebq-v@~7o?GLUo`bkP%_v$i_?J1G;N?$#! zlH}Hb&yUbR1IAQ&2HHk#`Vul_T*v0Zpr&7MG zh28Zdqk{#X**VPkCbN2)r?<$JzyAuT!V>8I;1tDE2w}xh4#9RG$JP(kx1mWCjjL%V z{d&6=XmhEo@)g&40g^BTpRSp#(ah95#QEx}v~+DA`^toG|Ijbxp$*D0+)17)dK6Zk zh0{P3je~24hl4l}5n-Z)KUa``o{P^KNT8rDJD!W{(GfJtiej|el_ z2<7wI)g`tK> zi3b!b5F|_Ws;$|uOb#3Xlr)JswL4hZJj$Fm$(@26=>)4sk`a^liMQ71GQY*ujxHCC ztqy7lfwJX_%Kf>;zTGXwr-SuAc#7pz!;*u;H(BHv5Z?zWxAn2V~0 z2eVo@MN~)Al28S^!?Pp=YZ}bZqO2F2XS!<2;f(3$RFlIU0c;eg;^%9BM*M=+mgCdcL<+Dz#3pH@aCMZj# z;$05mGD1tgOkOp+atp8_QJY)vY}N%+w#D8ds5oTDZc6zNUQr0Pl8cga7~o?gR!=>5 zpY63=EYd>@xSG;Mlb*PJI znnf-kT;hH@fV$7^&K|7>Z4~DzN0~$yo7xb0+s4fSO_lR9U&}ytYU%8*0VfR+W45nR z3>q_=HXju)>QPDaW3~`sW1=v=*JjC*hS~3O#-FvRNulf&P)84jS_T!g?9qDK$bPN3 zI8;|QGukCY6hmr`=q@7th!S>$*V7pE^#hWARDIc8iD!KNATXn$g%zaZQhmCOIg=yN z;O@$Xc>pK}Mg1Wj z9`Bn=b_z#Mqnrt~_)k&DQh&M<`QI>CrW>Xi*BZ|8(6|^QYmTSbIyeRa8JQ5FeFM&f zvUiZFIt|FOiS|BJ;|uYL9D|_-Oy9)SrN?ZM5#=Wa0o5G;&B8zTQ>4)`YG4x8v|xXB z$?jjY+iYVg;oK>fM=q^M@tnu*kuk&O391QOazYfKQq=R&B}y76Bknd6;lXaF)!y3|T402q_0aYg0q`Wc3# zMXpq`^9%1;4Id@=I3{4|>cVN9E)?V~M5jzVSy_*%aRU?AR*al#+cpI^K)Rpm-|a{tQK*3&4eA4f#^ z_6qQOUD8ZiiSB#0Dl3Nw@1KW#>GOc+V)QUrkgYYh(pVbgv`2o1?~Ss?#;ag#{m4+v z$nb@pNV^YuvXIqETYvBrq{iV#0<3j?3H_4MUGXy-N7#x&z$9AmfdH$OR5 zCXAk-eb8NI9~IndU4BS%rfuPjCIj{F zh04-T$=j=qwC_k6ZCw2ND6ke{h9j` zZmn6E^g|a|91J`FK^l)WYX=wU*1ccTq(oz|$FcDzMj@JRlx4R$rN9*Z)r^?dU)3A(HkuOyCXrTC}hgVlpXApPItbqtlVGstA| z^0Wi#;dol;h{2YgUzKI&yAR1-D8-Ptcj8%}?8}IfDlx+&vB-X9SjbZ~dyl269S$fk z4a*+W*M^>L`S+-`rO}_9no=&1{q;ngS|(U1*#>9Gmg$QcXL(5aHjOO5nb?>y1nN1E zhF7#mnVymX*k)5P+PpS>6MN}ZlB8@{OZf%JD4Q~vg2rlXYzh#tSY9mw+cMP)ka}clZok1`~V0`K(^gR|{_R6>_>(VJg)T*ie@Uy8?lUO|FQxTuW zFPP&E6tS9X_*3x@$QrMvD>#RrI5L(r@LI5(=S zB$<||@wRBj#m}E6Gq^>A&(OJ_beBV>L(Qnj_B}=*X{ybst5TprZZFku(Gz#TsFxMS zK+900jVqXSU$_vk#|Qkx-1_Z$8$ZL_{}`*d3TpVUwoBOt3)m&$;fa?m0d)|K*DEH=&kq!E(> zH$#ooFFmu$20pros~u&Z{A8G62mN`cabwc`Z%fDT*{CnBPk`;o)x00e)u!0y0+kCJ zMsu3cE4QaFU!zzcgbKOlqnDqwgbVa3xN6^B3Fn)tf#{AGWuW$u}-(i!zg*e^1t z)S`Q}dO6uFBs*8~`J{%;nasZh=^B;v=^>5Tp8_?jnmWM4x0^Sl+IePKn(4NSqy#G* zu!zuNQSxlvt$@|?Wcf(p9ODy%V^P`>_v(5gZZbU95%exCSS8np};7!Gg}6lgvBew=HpLe6ja&(H6VxbrhjkC+L-D zuQ+Db8Ivx%murUN5CNbMlbFeXkk!5UJJQVE@857HW|ZxiDAyFuHPQfpezm|iH^6#f zi&ec(Xi)H^0kwsn$z;<2@q&6Ms(u%!E0dKiXFlK0EqHnW#lk(Br{i&rTGLA}&gcHK zcm3_&8*|~-WY`tuM z^U(6@N!-`+;`c|%hi(q3mmvl3zY%_bMNu zc}g_Ghl2O}!nYqb!CvD%xTtm&)q4HncWb}x`@9#=8lrwjkY zix$64j~}}l>-!e0kcP|PZ1v{WE6h)VIXxi?x9dii8(XeHLGD)2Eq<;B2g;-##>4iE z&g{ zAJ-<=aDW|xiTw{fgs}MtK-i2$OK$J0j1pU0SD}2N#oSovFHe@TP8OHPnyoC1^4}fD ztgww?xWF?*#wH~%(7iKq{S!aP%Ai)fhnaRP&Nf#$HV(*E1XxS;m+^ca1iEy|nJI!Z zC%o8rjCAm&nz1el4NEVG>zl8ZceZN^%fQw;h8MwH%y*Q@_&-gxhw2O#nHPa~>rtm` zpy%wymQ$&{qs7-(`)fiUhDQL&6Qf0)ho|>}>j7kv*Ox!7N#gBJ$cVcqc$&_d25;tL zGASw=;-On)0i9jDt$0x^ttU+BcvtdP){N?Z{to<(y(y7IJXAzWI~~5jHhIdGrPSP3*J`{J46qT!lBQuZ*9ze*zf%) zC2bvsvBo!Px!9O%zF1g;ZsTU@Zck+WAXWJ!`dS{TByt{b!i{!pF-jw5rV>#RIBX~O z2qZSF2okmYIFbHWf_fK8z)5k5Q6}0mMU>*1!pDVb;x8&W%dR2pR-mY&<&oWm%%J5) zHq!D7M8gM6CQejjlN3l8WF?I>wZ)WL#`$H znut&RL3Wy&B!NxzT;QuCO>wYd4?Bia45pJL4b{I8><8?GH(#D5E8O9V0Ni}|kP|!&I!_Z$bJl_9x4`R5 z;{1j3zusGzM0BH*)b)P1v7Y0{zy7QJIq>R^huvYf-S76}aX-4a7>|d;e0~N=Rjva8 zPb+vZ2RRcS2u$%PdOssCmr$b&)28{Apoi?;v7YdxlpJZYQDq<_%(dxG0+DPkk|IbG zZ6OBaqi&L*6Mr6}&L@DNi(L5_+TT&DAYmEZ#-<+Cj;7qQT+>JiTjoem$T}w&m84Wf z9EMibr`f!<08ldr>|~lWHSo|Uu49)K-&=st`B`<))oE_o1SVT)P++GI0wz`8UemtO zJFHl>7cUSb<_7eq8F-60o9(yjm#2sMd@;-x^Z9&rdF3b%ekDDA`@DX7S}d1ntVKIq zzx%LQosGvs2bwAekMinel#+tXQ!r{wT2w@r6%gydv*3upNp7gd@d&OOHz3j0bO*7o zyRw7Rvs|vu?fF|ra&~d~;ZJ|IF2|m^-9gWf_erRz=hD<9ZM=RE8k+9KY)^Z5teTEl zs5OVv5HYIBqqhy*)ozAP_Nr88!bmjPP~ils<}U=3rQ_%+E=G{&2l_#?ses26(V%`R zx?wwT$!J7bUQTpHNM@1bna=EjiU4<|-vQM2rMAFq*$n1U?WB`2k3r1bHR^E*4vm#7 z!5Z5ALs*(bhN-4-Md}}b)-vWlt+|5}dt*`%XQK0}7v$n(JOj;g?>4nNR;3O$Y5M%t zsUn_GkZE?OI9!k*vi8qtZr*)&ee=%o56p4D-#mW%a{u{vYj$lQym@(=FXuMDxAEu2 z&6{Pk!bdet6=342Q9u$fV31Z2kR|f&bt%I;h z5afD?>SXIxP&{F+p@TokdlV;Mr|w6TZR6!T$TYx?7h@^5Gg8R=`=aRtqId&!sSo=M zp749ag8H`L)s7u0*HyvCO$1%gU7*^aQ0Tt^HR@Jw$DqpakIHlcXY#d(6K^^#(xfdw zEH(*X2esgri8U;fBx4QxFiheMuikC)YNNG#*Y7`G+`P3XY2#x1-(kPM|MJ_*)8l-x0vK%g zd46?setC6tRv0He<%ALG0$0P#8pc5Nh28VZ%fmz9UASge#}%GuHd}~N_S@|+42S)0 zzuUOk96E_6<7gvd?Wt*QY|?nN|GQY7<8j=qpT^_pa<8NPa~S3egQn9LKH=0w%*wMS z>Hr$1QahG4k<>thH7J)rO=4QT;J)wUfoWE#P8GkR8Bi@X@!PAuGE{8xR01=#m+4Ot zah|$JOL|f!SVC8*)y>-+yr;rkf_7w06e!f4pv138!B`}bdqF3XE~TmTLODmGVsBIL zTPZlTEgsWA)Kr143h0p+$Q7BS`&uQ;9#S!pU8=tPBff&{b@KJ8xZ4>8U#+(`!e+|* z-R|voKX6k0NghS7^2SDG_?}~J9LS3kkg<(A58I911&h@RK^q*wsH@vIc8PB{8=LOC z$${1YyT8ENt>xL-)yTG?ZS8)&xwyTxTlvecKdsKK2l?Pe>KPTn@A-Tg`#=kENJzPJy*Zo7(4EspuHE9>R{n_kS%FRs?lPj5baKVK|8 z_X{Rb!wI>fW*?)?w`bNA?e_<;1%eJjP|-B)usq9*GKYkgn`@){eiKD%!O z*9H7BF^ZnPy`)}vx7j_Z7JltJe->$!YxqS1+zUS%gvklnC<6*si zy1ag4)X{O8t&v^K?c&<3A0NJbxqkch;`+_z6c}{}&2hK!M1r4uja;Z(Y<_MpvX+O^Qi|vo3)ApHl2+Y15PoEO2fd zPlg%Pg*2NZO}8NC6S+ViFnd~$hT>=2Iuc4;3rq#Y!ED6IIH;P=2t-Ah+$8d7a)Oaz zHHK6WzzVRjF~CWFAcKo|N(WcQYKr(g(RwDSJGqA-v2lBSB-0HSsxKuz!C2~PlA&}o z?3Z-BO`6TtFOQqe(_(q%6YbgN`3XRGP)KN$l<_s0f&G@l@%Ylsvv z4l<%l4b@R`rEQ>L-Z`Cb1o?hKqEBdy+JP7;Vo2(H$b^At(g18icb%EgHGo3Wt0sD# zIqfelP7|N2q23Nu2aTPkJ*dfEJJr`zgI6@&;i;13v{Hd%j9cS#*zFIytu-9C?|=CG z%TIT||9boJJ0BF|q!1-`WPrF+K{M#ZX8rK;^r#MpXRU8P{9vuCF*V5MK@zv?Y-(@+ zb@k@GwSi&Oyr0y3w2`U(m5oNVTB;F;`TYFy(t#4ibDWS~8fFV?CAZH{H}Ai*hIPcy zB3hbE<9t0bq;~yuf#bNkxOBZ325m%tadT?}cI&q0PA_6OySQE)_BP5s9`~2G@2!;| z0IqJ|&F1sL72m)dU5|!6e{i(unfgNaRlKyRZ_vPvCi-W%x3*-9kj@}CEL`;TL zH~F-}{S0{}9ZGHh99MH|5c;va^E!7vQ8QTenU)zoV{OR-!AmP3MH|-T0=h}q^Tx< zB~u#AcyNjH{_ybi)6@Oe>o*_Xe)q$-PruBTi_4q0j_V2&=*Mf2`IsEr)cfq>ay;y< z*|Kr(c-&WK=;arN$FE=P58wUsU&ENN(S^F@{u~d7)%oSw`DV9S>jBO#u3Fg&&-zeg z#CZs)-MX`u@#X$*{d8|H(}uLZ0os?%^X$YxgePLF_Rq?mFu3!#N0}{F%kvA@%(qzD ze_B@&&Rl_ue2@G6Y_Yh0`_8pv4j$Yx!KPxE_Tnix!|`xDw>SOc56?Cb{`$$D)$NDx z?FVf*?E15Zd0#tJoyz$IAZxgI_dP%v#S2lwAXQ}`F#{Bfj1nc4{gao`edoGb(|~bE2e1*0Wr`i7-vYmvLCOszPCpPv1!)YaeTqcUQk~?#Papw4UY;@N z=EHml%u^xhQhjmQi7*)^>s=FJ9dtVSCNze65}HmBGU($i&d#i1vU#|T&aU3PJMMOe z-NsrO8=@gXA9(Hgl@ehF<=@AOn!Q@x+6gMaia>_ib9UNO~pVnj%<@?8hEK9wF{zJ0Ta zb0F;=4qN;8-S2R)gGhQ_afW4sJH5}Uyn(^`L=kc(+e)rLt z-su@rZe9Vz_nV#kXJ;7~ z&SsZ&iKg%`hrrC*PWF_T9Qmfs+6XHLZN@}D(#Z=@(H!g%9Pm`8ML%E7YrsyU1kx6c zf?%Q&P-ToTOPvN%2{mA)IaSXHV$=xI#3u5zD$W2+%c;E-)`8HoklN&Pb10EFZsKx- zY^)PB#=k(ubsAB+Jc?ioz`RZP7GgY&9|uQ)|-Ab z!E8g-9TAoMn$|D(pYOkZa@KY}bFt)ZYvbbM@o3z1C~J{_9c*kiU--PF$#K%A?tCJfZFUBG4PW0X@7tKG?6gynVA+otd${1h;an zOPF0=d*L^~-yIg=n8U88&JlpD#!IW#ge=08o9*s$A5p#z~_sE+HW@ zg$7E}Dz>v&^Ta2}Rye*Tk6q7N0U17yq6~3z59E<=|HVIyAJ&k=C{Y)nE%GU1g(E_V zStO5iK>K1A86}@$d?vooK^v4R8r2okgG%mdEwk~kBJK5<{7ThQXmRK?kw8iVoUkTP zGXe?n(j1>Rhy*il^@w}3(G|RE8m%BZhnWu;97*!`NYR@=G`I*RXVKp{qD^Ve+Glt-T8?K zJYQJD`t{eJtZlity8iB;|7!1>GbkRewWh}=Z6(OUIHqP9ryRWq$P=+*Kgl1=@I#vEvZD;umTIv}MPP4LS)>8?u6p*w?>c=QJrng~$ zP_)H5>AHnjI9uV&yD-`2^;hnRSh&{|N)vw?_cCEgN{VV+Fr<-3#1LqV(m8-YDse>9 zw-?a0vz@9OT=8-wVqLXEbxK{oyEjPam7ylcRyfn-D9bLJaGjnnB2!Q<{UwQgfm|)K zGPnYz?j)PI8kH2e1YxoQov$s9$5H(OnlL%?a)N+?ec%;O9RVg!k4o=4BW0J^n~y(` zoUU;F1I`H^%~kjAcQ%k5_d6RPkK?f)p1UIqpby)Z!*&}2rrCVC-)=JW=n7}!c>VU{ z!cRU9ho15M|Fs!BkqgUF5K_@;B1lte3*Uq~upT-W_TBN~VubavNWd#Y> zqRHd1C*uDe(W4XgP_8+|{=7QBc)I`c`In#G|M*Y7u6XD(XQ0n3O?t#6cP(M5DljMn z+Cv$|7T^W?DLOcpz!!Pjn351j%dRtW6N56qrWQA?E+s5-Ink{oi95X>&AnnzyUe!m z0Rv{eA25I**jdtLSVY%J>7Pc#3gzf8$HEnGtQ6CrJfR|58=zv+68PIfCRK$jDhZ}x zqm`bDf?8anVofOEknyBW{8UgpjTDyb4g1Y{y*YK$BaoqgrY8lCdm$2>N?P5H7#2%= z;hXi#Vzu;TF(6=m;gdOgtzh%=bbfJdjhTlguu~q4muw@r%QqjKy*(bU-+nkAcT6J1 zMaSd(Y^jIg{@Z6|#>?Bc?_At>kjkMGw7h5%kNblYo?NXq&(GFsF3&HOQ`b58(0*nu z%SGJk!W!QF`o$Sd<8IyR?7~L$FOHS` zG21Il%tyvjSCw=n{hk%<$W9vtJOss zWbZ>6bDYf=SMNWr@4ju;Pwp-_0D5|8X(?D+tL;KoYjuqStL%M1FBN28ag4O1Gxydx zx%QL8&Pn_zWk0grtbHFxk8K^pVH=p+6Wy)X*2(R+FZQr*ZiqF&vtiKArti0F`w;9S zxc~I)`yc;eUvH<4c!9T=M!Mk2`2PWjp}HQnFORcs^K-Dd1jem`{Jp+#Wo&9o);w1PER*TjcS>z=8JXmI6wlEduQHa5zOTg?i>x7 zp(FOyjfE-T&d&#NVqS)NMU75%Kw&k>tAvgvg${LenjR+)DzSV1>dm{mPrq%SAJ49C z9Fjm{Vf*{VVs-!N7yHk}^8C!rLcaDvtLihCNh<4}v5^qL95wGQu5Q$i;F!giH)b6B znE`g7n1o1%D8P&wAcL(m0tBzT15S0yjEJuoq@7STXLD27D1O*BuTd zEC^@p+wkmr^k8H0rM;iK?Lpgs{dll0cD7jBtKDrk*3i#*E`%zD!#OUFWw%UtAeIH0 zWg-z%u&s%smH}lXra40yK+G}QUG4HjVYJW`c*n$fClw}D^|?fJh!;}IT{_vVG)swy zoEA|ttW$BtTTqZ=CINy7;cy5O@=0nO!~){9G|ta8othfQ!K(_C`aEo)70jM5ywE zX;qLIfdn*n%;rcdZJan)h&zLTrab`wui0ac$hZ<&*!W2>uXOMSr7BsVYj!> z&ZRpp+ZgqHK4bcXK@1^NJ_pXkhNsCf}Q=FJS;YIhaZT4KdzPFp>{hYB|U z8{*uVcib?g*$1E|kX3C4JXWBwdC|ZP=gfG$rQ}7V(c-r!FHOMQ2>wECXrO4fK@zpA zgFy-$i-4}6?g<^;@zRQ2IA$5p_a_(zCV^se?GhkGq$(7LiEH{*i?$0+N+>>x6S$EF z4cutE6$I1@i&~UocbrUy?UdS1V6XjB9!}P6*y^=`FplQiZ$I0OYm;aPBMh@Izx=$o zzdOIUS}a$}tAcG_9yiVkf4sVVyM1|DKbz%QR{O;XMf~G&3`P@*Qd8RtN$-_8;g(SO z5OPTK66*Elh;h4}ecx=DZMU2A%WDATK?TR&m^VO=OgDiAI%$5s0fI2#C zWw2rA^2|6i;$Z(8J;;8xSXq~~IzRWFFRll3u~;t7E^|v6JH9^wYtMiG>EDn0!`ttE zyt;iiy5sG+|1jrQ*S-PoV8*RL-1gSOM&Eidc-!gX@!4Xr@cl2di-mJajss`ru&{5N zRsF}A`M~?syx-6oa~P7)$mUUe)!%7!q!r3?!H`Hzqz`7lT_Jcu*F7GyO*^M&XNePN+A%)g>IbSc$1a{ zYXUE>Ad+y{QnG2@Y;IF}uu1yr;?i|6KR>Qk7f!LkM;>2t-=lya8xpr2t6Iy;W=+U{>ff`_>^x{ zIod!tY^g!dM{}GX4>J@*g-e-^%*{-wM}mxzpezwb&bUM#uUX7XQs>CKhhWXIc1I`o zKqD@uga9~9j3;CSQmz52uv3Ry395v4Kh_nlqBWfOA#GU-sj<-YG$BprafBSAOe(A) zbpprNFeplcj4EkkoamM)BS3-Vq-mCDQMuH#RfsEb>eTT{@e3p)U1%#^J8c;!gUl{# zt+*>Fgt}f5}FKj|%FWp<~zw{Lr}(})6; z`$(lWu(X?FsSp~c*y44mNY;asoO2Q9Ri|)de8p4)>{s);+{o%hGal`(e*gWC)*gkY z@ay0He=mONO7+?)g{{!H!)-Uuuv_ouYnwXT*!k-A?WGNe{k+Rg@E)J1wUsK&if?Bp z()vpMx1yvQT1mDiY{T%U`#T#>T00xmDtJ(A^e`+hE_W}_#w-@Av$=7*X8riM-)@zs z0DB&V3DY279`4D*t>%Wg4pTO%}#GGCdJA|SJn z&!kag%WLPb3eiYXLBuXl|`+(mu3 z!UHsvpoxd$gPt|KYX*%Q>gsxT`eoP9+T*i*0|Xmij%S45^)#U!oAk7dg2f7n4Sk!RY$> z^eh*e9DTxiuOQhm<{mo2!_@1i$KCej{f~dP!894HCzl!Q7r55)<#PM-Y`x&~{kMS0 z%;t-WtDDQ4H`XYRu0zi(miFm<@Bq5@B~}-??{~Xlt`NQOZ!Saj; zS5)w1$btp~8>N@gkJ|XEY2GDoNy45gj)`m$8kj=9$(gDqhls6^1}(I{LOr*JCP-+E z5~vWoftDu_i+FL*3d7`h3*l2JtMX%?89(6^E8U!Nm<_idzPC2UMv<;%Zakn53bb#6 zu<^irxpL#{2cOsCX!1Bwq#7S`XIVVvbY>QqhP;xgX7Mx-pm#Y8yK1qR~Hx7ki9(K+3O7oLDnw2uIE7y z);KEDx<-4U!!R3tw{%cGvbSg$<~TFK@Wq@`!?2hy4lD3uJOuxQ_tgBd_U(K|(j%01m{_}5--@aVGd4K!yd(Q$qp7{orq{`*U8-B`l zj96T7{o%j;-*F;l2EJ}|DMpGVIhZ!R* zH<%dUE$$>wYO6cBL#6KHsEUC8|DAWXX@&DzETYWZ0f(#)v;E=t_n-gA5q6i?Z*I>& zuA+1ZJC9_x6LW;fuL~Hcb1uL;!lInn(W7V9DjSt~DT>T{u0|#CZU$`BYBI%`l<6Q3 z7g1Q~2N;{^GP$E@s(J2Dq7u`Qs>q-nu7S~BI`jomx@ z!}|9pn6TzqfF?HUCwm3f-`L>s?Bc>J&>PZ}Oed#lRLHn!9tKuIZU#IFAO+0L_RFt7 zefZO#Z6u2Zr{#mgnw%|M%JTW||9O6Sb$)r{gglok>rt%pcz(R!uGfpz>f@jO#ai~m zVLcfY;c)T(ds?5-beac%>Q`Dwb6t^@S40sAs_{SZExyW9BJOe*qs@nG{0S2-96TPM z(m8t79Y`5`&7dG%#t9?^SUJpUWdo2n;2A@B9(H)dgPmm@$Jt`8VQz2q;ke$7J5Tpq zxirW>I^#+5fx4JKXd*_IF&K}qCoRo10ts_qj)`|^{iJmd7*4}rA?0Rtf_5w`PMn~m zX1kN`^WJ12vBGH(7I>>#aMmNLQ00J8jtA2b+nhEuR+Yiv^bH(VZ#2uWPL~14eUTw zh$4-{d~OZFI3D+#&364_^X1+8Ww%-Hw;LO#*#q09JIvf4A>`y8pU%wQ-5i-A#7 zGZsvyJ(xrW1?1!5bI42y8x^NksZKcosc<{ZTx0hxC`QPz&t+*77RTTAJvoU|>i~i= z$c12DDXv;|Je*%#oUN|c&tG=O2XkK-1&UCyHNooUuMDKwT&wD+5 zxavsf5%jbtx^%4XnLV3>-DK{Z0*n)EER^CO@X#BpHV}r>GCVsuBqU%0Qg4>KD5IlD z6Fm}8KqlJ7?k1>+XUL@DSc5lLnyXV{-ZGwriukNLV{#(iZRKdYZ?U5d51k~PA2}5a zIkgUiDTPyfUOc5ARK2L#!6W0wX}XWc-SgdpP4>rwHP(j|7e>WA`|RfP)o6~Z)y3KM zwb#=bPhaCy1ECM%hWYyW@#*X5bDNdV=GF@Nkxur1_aQX4R_XEU?>Fzi53{$}gpOfu zjg;LqH}5}s-C^ec+=4qCZN5KWF2ahmr|n-ga>qact+YqZLrNNo>)yPC2-n2a(0+Sa zL>T+*oE2Dobd4TpUXil}c{x{h^p0?_JJeqF)8pM?zq@m?rNeBo_|yOPe}4MuZ@>M= zzkU4Yf4RDOci3-x;Mh!2%__{TRxIFU23G=(ksHW3R*aZ_X1-M!{!zAXGn*nO#aQEn zvK1!XSZS_PqW`8wUMBDvY{SB7xh~@jc^?F;7_p9C?sfD%l#JzW7n1$-;&WiaxyUNBjNOC@1mh7KzmDuR*l@zNKiZW(o9%79v)dbN zrP?#ZAus_bgPJpyLJOb|sY2vlC(6NdfJr663ifCk#Y?Aj?$@J|m{b5mtc&3keU0^4 z)^t}z2Y2D*u;d9#r#f924N~D(3V5_95fq8&kOHz$^C+7t?U{T2?=hSN)$oGBeC= zto`uy^I~~skLH@Ig*-Nv5Y^}7#f%0qU=z43VW`M23H^ONz$j7yM{ zF%Dk_efj3CpAM>wF>>Q#EUPDa#&JCC4mKOW3}?@KKQW6CUtSckWUa_**Vxc-sF z!kcD|C#GuE`^!daGcOe9igHRFw`;TC{mXyMK*eEIFu zfBsGX1Yz~XJ$=-ZXGFZ>h!lEJF}?YI8p+1 z^&~iLv~-r085((B18KTIf@r$oI>TZyPr3>w^O_wS(n*ILk6~UG`gTdLZ0f29VjrG{F%*Jf@I6UPHmS^mS4Pq33l8b_``bX8 z{gyWQ9`tU#vtEKr5jL$Hz}f?OR8`hNVP!y}6<3xO2!@cM>55A|(Ysuv8xQ zP+|X$thV1-E9?xJ>w=3=y`Sq829DZj7@b(8IV5sN;7(;c2iN(AvTMcDvuKt=)ICoI~R1t*uQLwBtF=LV%2c zPcgdQyZzqLu6?JPUaVG2H)qdjB`ZI6uOk@Eaw&Vo&XO-yyUnvb$iW$m2DjqG9E zZLC>#p5B2KPUqjTIo%k5<7}oKGO<7G9v`(`?s~ajzi91d*7}(TTQ@z+54IY82af%q z;)g8`zA!lYs&lZAe)n1nj&`9#cn+Ta=J$6fw>l+%vs~bIH=+T>(+7Tcu#9aM z%uuE`r*a*OQ^~=wQg55m+$HP=s5@Zmaw!5=krRzCbcEAVu`V^VD1%*@u?|INnbwc~! z{pa6bp6+cxI?Pv|N$DonjpN=66zfcow+6?qXFXrI9B(|@IAU1LNd#I4m=4l46&aPq zgLVsyhr{EyPfo>nwX&w;Xv{3i1iDS)+9He}$vN6YZe~`?-F5>H_m_UGvhSnYzTDrv z`|$m4yS@MP+hVzzpPl1TW&sj7B8p5YKeWm2L7NS{JU(onAGX`g(I0s}U#!kA?f=^# z*M;Pv_TG}u5+vbZl-*{xd9nX(KL7Th_3G^W`t1h~>4u?Gsss0z^|m@c->#ny+wFX{ zx*Ue>=4HNI-M;(Y{;)j1SU)}3yZQdRKYjk?KfnC?)AxV*Kjw=wugh^H0Fj?rr^vui zBuE7ck!+IhK{}#>$v@Tu)Z3zYzd;o9h@I3&K?3B^e$6JmF`6kcGWDo5Ryc|wyki5q zGD5*OgEp&iedP!1%Iq_}eEZ(6I2#@7+1wR^cXpNId@ej{$n};V@F5FPq-OJ%{RL&MV z&uur18_8(DahSz=na&+GG3v9q5YFdg=IsNaiP5@xZ95EIi&>}=iiJ!-He|kFXs|3A z6m_1%vTZ^`PT_GoqJ&I2l&242B{#tgeD1W#{Vj2(uhOrXiwu*);#9w7P8jWs$&flh z1Ak&cuhMQ{>%y(kvG&fn+gK*bV`h_@2rXx(vAqVdU%sQQ1jGHO-=819+3@OrQud}> za^pz4AOP;9@3BbAlya$>J3VL4{n79L7W41UJzZ5@DWzifo%@0@Gk_#Wr-yQ~va>^> z2zNRO7;O0#EZOT4s%*#!AkGTM@m=5XJopZYoXM)H)AIomVK}%TZw#XaX{*-PBrmF> zA}*MiJZ%+rdH3)q1VII%wJireV#!II9)(+##WJ(VdLx5VN}wD&8g9CfJBD!Muse+L zYgQIz5Y6M`ehGOiglySNp-KjaB79_S*<~6-1dq>0xD3>h@T0|M5kxbz;8XVzn~GAk zH1wp7%OP8W98Mj0Xp8xB13w0*1so6O<32h4W3j%w`Si2WF}e<|QFEm#oUe9o&uM&I zxVI>2F<%x%206OL$wjb48&=rh^UdvX`?`Jn3W3FSJ&5XI z$P9^}t|KAGNGWC-CNTv{?%8Cri>$JfCy+yd9yaI+n$WanXiveeWdA&;0|0! znVn#f)m{Ye3pdV2cD}%RkA~2StPV@v63ljOi>$N;2fmaSc(JR5UDJPq_2fUzZ#-RReMw4ynkQ8rI!I}-KBBzmEjlLKbqQ@Zd^&s1I1MHI!J4%Uyz$=lGPMv4x z51;==bC;UGk2r)v(S|(OgJ^kp`6G#saLrIdEN||k#lmttNsJF1(W%Ar(QKX^kM+Fr{UA9W zAQ6U)3=W1gjqz?sM1^~pYv0xwUDEyAv-9?}`S3YF4oijyj0(7&7TQ1>&J=)edCy(% z;&SI1X1@C5?p~;GXbuE!^p6eG+IDcnh7o3DIH#eyreWu>!^R8{!3dEmgzY-Ef>^fy zr#ljG05+AwN)MuCelB7Qo{+@3N3E7GhXC3%7Ni%J?FX|UTxM~CSwK-`$J5b`?r(px zqNF@+izK$grSLpBbMdr?WVom-*QMc{g!BQ8TVd(=fm?)7lG?6cqzOuD9k*~P!F*Xs zi6?wRjbf)X@GoiaS@gTOzacAkO3?^@Pmo&_$ug2VWM1kK?uzUy1&zX_4W1Qj@ROmIf zi*S)Z>?_FqS9Ji|I>VF+peP|ULQu^z8Y!;`Rv6%A%Sz+(>A1Hnmx?nN79;HBXughC zYsU+c!|wdJDOh0jaCX zG+Qlmxme$-U$I>O`1*9(y+H7Tn2Vig%R<9x8<7c?aKgnZoUJ5jk2TaBfsehsxr5^U zuzSNjSLDHBRp157D}z&Np}H;v`lp9Kq0)!sdp2L8@@F*1BaOs&l%_-thfkR!{Jz4* z0!`{F4T~^cZaXp^SJupUiy+KnJrT@qfBD_J9@Agc^(6@Dw0l&XdFs!nfDQKmYrGfB5;=*>VjvxNR_r<$&$h&FDH?giG(W zOP2c3)Timx%6r5Qm2+wp<0L~2q6*}t9 zejZmz1-l53d6}Ml>=W=DmU~tEkU?OQT)>KH%G!$N7NpbR97lOY3I`y~Oe>NLsgmvU znFx-SzhZW2c>xKVHW1tq*#iqD%cP5oRJNLXxD5OmHlu}u(KUe8P~^!W7tDyL%zbFjsDz28E3I&)No*6@dn2az} z7VSHfe`rT`snn#JaBw%k-z z{_^#|(cuElZ(Bze6lrW~mFMPZvb?=_s9|Ej`i062+6lc>mxMH2NVcmAc^8&tkfx}8 zp*11lCo@u8x8X>(^OAyZjpeMibD&R#jcXj)*|_DfHGwnpuGOr^fRe;L zAactTA0?Ada6=r|gRKautA{vfhxKUZi!m<&km1MR!uD@ZXv^e#yeOGvRcT7B6+GB1 z+^U5e_{fKb>^Pd;@K1;B%j=(C;TnU*(!Rt+4EqCZYCq0@r)D%0U&{-Y7welL2J}@o zmWFFy0cQC-M!$o~_DA+(YAaj9b)2p*Tw`0IMaq*L2#3R8R?-Tb<$~H<4RJ?dd3g{j zRkA?X;93?bFA7-msEI`?BUN6U_OFmWKy8Ne2Nd-<3PKd3j(ALu(5tu}cQ?_Qpos&HJNoR}3<2l5TKz{;1ou8$JE@?z@9 z#~Vm=GcuIO5fJhO?E=yFvIpv@Lc4Q9NUaf6gtNW|(g)fR7H8%#p%a~GIHGP5ZUK2N z@si8S2ca+z$@#c{d4NbcTW!Mm3Vu6=T>A0PvdoAgK`FltTg(p}{C~FXa2tP7rMrTw zkZ&3lj3@qTNKP4h*%UaYFLOAyPUpiGwqOv=wBAM27;TC{r2@aYy1UO(s0|*LcOPf- zWqLlM^pEN!)|iE1yM|d+p4y&A177Rq<{4bqg$G=(%E znn#fS!Yc5WH-f;7vOphjX-RuAC%BBH8mp8=h1eL!W~f-I$=OL92lITjxgpDO3tt}+ zr3TMLTCoOYTn_D*uaGFF zI2}Voy{T0+#z|j;KwPtM=GVcq6aE^?^3QPt2*K(3;Ds{}B^0V4ghhh>HxQVhT6aCa z8DcQuoQ7QrFR=Oeb8%wuz6C3ytSc{=&zCoKk-=dA zDIqLHi?CW{Q9vHbYl3%K4x+n?3}UhFFc?^ti^Q87sVnw|34b9u9}(DxKwhCH8EB*{ zQ~?cDg6~<{#Dibf6A-z)Fo3|B#^*I5F_e);CkRLGB+d5m&*SbDR(Uv^RYmdo@CT(q z+;*`e4!I|sVQ|`Dij9*o*-sBzIvQ3XO~(Xb1FNr={HqHCi`no$KMZtqh7Fo0r(=9N zoDaKbzF6P?HY6jsp3)D{W*x&=UX^F>ohv&N(n0#%jrn@zw9dq0#9waB zAi5_lOzX4BLCZS;B!k>*a{>;F{+&rVAAPj)IL^*zFYp}OZXoJGJyI7qU8rgdk70yC zsH$q>#@JpUYzOH<(Gp%DjZab$FtA|+#a0DR4aJrO>^cuUU-N`xud0$oCes+++i^q8 z9graHL#B-V4On7nLPqCsgf`p@EyBrDBTE~X#Oe%T?pDx%R@3<=6GR{Xi9oPG^4jh=L9wmNV_M8%V=Hp zgzACAWuOc^DJC1g)u&|^mi&mIfb%1qtvcCEbP&R}K>YOepU2l1j(|}Y(s_8V5W?Z+ zZhik@vAPXrbH{Tjsp496SP3HbOjtRz&uY zM8C-&5Q1=3xeiI?GsRz%Iu2Lxd8;CYUFE+qWKa^#VW(CX#0`n`$$thpM@LLT;^%!g$o;UVa;!A z5R&hBit{7MWd-&C>V2WOpSI8*RUB8r17;NNh$XVcSM`|i z_5q1DB&re$=S&?jy_3E$96F@w^U@g@P6cZ=w89!6xP0IaVgl&eqg`)v*KtwBs{hG% z+~?l0b{=U#T>jPo%Y|4`KlH;WPtNgaAI%o9QQ>j=LAbp607(`60OW2cV?xt8>YrBW zIS%Iwo5<@GCl}&SHK#y#X^L`5%x8nsUR0ccTwwJdb;^Q7-nT=7Hsje}+ z%i`vKeftr@mOm#@mxor+*zVL!z!o{9lz^nt>ZQ6H0%(QJR=9519+=K!^GhT6ak8g5 zYh^Km4@3xo`E?mEcB60xpwa#Ktg48|b*VcplUevK^ngA_zpm zaeY;jSQ}3cd)U!7k_<#c-q^F%X0}+TaIasV;XDfFOPb1#B~7r+D8%aaBP@pV>EMSm zh%NBqu#4d|h6Gtn4B_8hT2nW!G~15*)mm+>7-K3SQ(m zMpOJS*_OF=mXukJy;%~XN8&Oe@M@vO-oj`>V5okOuS#wft^{^#Sr|Lg7H8zVziVqlN)=J0el9z5tMm?ueuS_p{)8C8)(6;m~J5Jacl7J~0$ za|`DUTsE9QNKNn5*CaEum#Ohs=N!>#6A!c=WQ#=`%vgH0ViT?^%sgs5&Euv7IB$QZ zgE(rkJ zao=90wbbv^-1{MwoVTYXK4&{W0P;)It!e~m@0MQhV3%?4X88S@Rx9F(u`|0Tf ziLj5*D=dE;*T;m&b~QM0>JI5oUn^z568?cVSVHC%$MNZat6Fl^JiYn&6C_;E-~Y(Y z=dysnb|kzPb{I@Ntg59TL8sm*gaHh@NbAQwwdDpOT&JKJv86HzY&|3Yh?}Z&%N5g3!_n_Jkq5UCL#?FSR+b=-kg7N3*zDMCd$ zTe&k8Sq4EL?rMD8osN4bR^X6(d;E4fyunUJdL#y7vvn{!l!vBae4>YFnyz)<6-K@_ zl)={)@q9v|(2&M7bRF5yzGbMSb4i`L*ySozc$f~`E%rb~Vbz+b^E{Ros+=Lc&2lX- zz$GY4Bx`D?DAN9y_@g-1gH2x~GC8s=K`Q~rg*_I>XN^K?@dt<^v~YGSNX-v#isMvi z^7i_a;n|Mg@Po)Adja?rOjxQ4C&j47Np&C8o34-44@ffdf^y1Mv0m3L3UCA$E+nDv z7@ug#4EwE&4H~muI2J|@)@!VfWR+TkQxAk6jP-`0oSvSRkSP z#h4)=FhODq2_s}-eiY%Ob{y0x!HJr6SqqG)qHY-AdwC&-a}rQj(ScLP0kTU!n$0$M zkbozLouIKD#CO!}D=RMuRFLYuVM%RWfoN?4SHW%w<_kRjsU{=P0xCTcp_;I^Et9*y zEf)2Nv(!TAOPnY|o+8MY2-YJMj=mqD%d(sv+2I_;vLLB{{r(lwbDWe^HALZ?pT58~ zOVng&Wyav?| z1ay%K^P%s8xm~!)85}6l>afVoc?%c3*J5PMa5(N{ZZCv<#={^vPPE2CT!vNxg$g{2 zaB5-c>1iW12wb&_t)_-^9i9d%n^iR=v6c#)6p$3USmiinE~^|pVk=Swl1)~ZaglIB zCd2b4ayr#W3M7qbnhhZtk{BC9s((5jVcC&93Z9(NYU2h`Q{*T?5zcT-U6NiG%Tgm-))F~v$4Z1N#i(RjdSo2dOeF|<1}5D{i{ zH+56{g(bTtGJg-UI}LaqwWWGpWrN8AsT^j+qd@!)UzuIMEo{o*<5I!`BLdCAJx9kH zX83IOGDn^d)n^F18qQIuSRvSXVbqW?4KviPrzqDW0bjIoP{tf83L^#`LNf$GOW?P| zISS3BP@lz^cUYJK_z1bhP9+Y_22-Y1l!zl)uE=w^N_asmqDf6hdB`c?(oitZRKm0% zw3XOc@Trjn7hyAw2;<{jhSj13p7pKBNOp)3s> z4)}+<>2%>P)<>;PD%Lq#R~zn)<70MF=Vh5@WtQWr%F-f9(maJgi+pG7-&ih$QP+c| zRwK-?;rhs^G#7*BgkgyXVIuOVkCz zkvm&%U{ld^#;VGlEggFBHRR(Eh`G%zTRDKhUt)_x$-oI>cJNNDneGevhDn9qH;-sO z4m#6Gs`&%F8{jc>A#gcpVfC#EVd%h(5?*N>ohB%fzpJr$mE6xw&pI|BdP=0N3oY`( zuEbn+okz!~a&&eDl+%7PA@U?f+cGai1_Y*zmP#JGe>v%-amBjz{BXV?tzJs)6dZ=! ze5M#JmzqS(fCu#AO^{7vPcw)}ma~H7G&vohzNTc>DhllRhV!LiTgJNiD_hGE7iofbC{HE>uG4TA(iR{Y?(Yu5uU+Y4wcZFu2oS&Xmeaw%86fuZ2kG`zmB`t z_5G*YpMH7y{uMHekH7q0mnifKcV+kTl$?){`v*ak#1Pl^5Z55=#;4u#<{mz5o}w)$ z`Yj3TJw0Y2b#>%XL+F?fRyW>LRl3d_X{j5R*U`WI3J?J^@i1qHPd_KmYAN zTsPQnpW&mgZa-ksX2C~@Rinw4L+y4sp`$gJmKYQ}llMk5NsatfY@#-QY7EPrZa*2a zJd{1QZ4S}Rdgwzd)1*F(53`k#>4Yf_E_^14~BT1q$)_5u%mg7FfK!uaHY(4$kk`MLVCQPE`b&T3OMn~89 z(5hU;Ne&GUq=uy{$1yD;s0IET*2=}Tf*DPx+^NQ%aM%Zt<2n~O;t@iAB0Z;+t#h=* z$^hcjVf$PbX;tCKA%eo3X7?sANs(Y$k}uBlakN(T;BjSs+}5!2G71~#qt%ltMZ4u0 z8<)`rhz2sl=WqW!?%wV`|GN43^V`GMyhuNN`CT!gm08^Y*17h6{Y;w92vRE#;9knjs2>vt?0WPsVOxPKH%o2XIl?>=xcV zG^y(f713Ej=t&JTE$hvhymsTzLhpuaoNQImjLFQ97uNM&2X*R{u$uvG<)pigJUZ;U zHm$)Kp(P+d!>u9MW>q2k-U%WI$AKFhk6VPJVGP1!rGY~Y^5fG9Y85}42eUPlF1#+` zl(Xnqhd_;8f7u*gU+YS4zWl!X_TTC8(BNNjICt}^ncu7r$2}|;hB|~j;Tua8*Uifc z4)*x8hf|icODc%?!Ocfu!DB1X22n~lfo;rg(z?hv_px~*Y}N2qIdDU-=2~@8HKwN8 z(5F>Xlt;rl)5uPtD@E_?D$UM)GeowKMF_L7d1kbqwQ`AxX)w5R?PRwjR&#mH!f4cV z;@u2FN|PXDsEOza#AH|Zo#`OE66WNU-cGmW8YsPsB#uuNXM7Un$-63Ya1%7MxH|zc znHJX$fNRL;DTz)TIF|vj^|JWPEenck0yyUb2x)&D;Fvd$&yc#}9GafKO-Kr%biIV$ zI0}_83H65BuLHzTQh<6WgidZ)W0=Jlt>MG#({a1K`}7%tW0@xLVFx**AI-?%PBR(c zkL-m(EZe_4R;Xbn-X6c(sNpH$$6T6s)pZ>$*RV0SPk-*89`iW4|MD9Yxk-$mV4SZY zaHWJe`|!tqRo`++bY$3T^X2B_-~I;_xJ90lMqP=GT3WhU62E@`3O}>j+zHox`TB3T zIYAULtWCK(`VdTo;PJFItsSFi;Ru;8HnwHIJbW#aM5yLFa%x<7%j5nPKj3U0Emn}} z;|z*P!^dbalo|MLG;BC6F+r%(%yHxh+%{@24We*MRMh|^!3R1oob~v&rW?-70k6bN z=6c`2p8loA!CV^w;Yy<+T|@0H96>aw`h=`D!joI!VvTT?{dT{5DUmOSM=<3%bs5K1 zk|t0YMKgc4bS;}zNm-+$h!Ql0B^dAC;0nBU3wwO0R%L+GSz{4|semQplZ2Ej}#XYr1(-_~(LaZW_%+QJM? z=h3-RI&gKw;A@4b#_OIXm4WAYwEPPb>t(cI%@VoFv@Zjz~eSt#w@t^-& zAddJ`Js>x?1tIT!8!l@sNa2EL{^85t&ik$B`3ReFJ;>Q1G{bW~>|WF446zt~=6u{~ z_}Ty+!MWjqHYLBJaSeivl+}z;TStxKveSy4bPO{QM*0_dr+m=9l+=Xrq41DFz2n2y zN5>fQT~}Fxk}@d*3CX6u778d-qt=?@Db;C){Rj_r{5%YWA#xl^^H+(Us8a>CwNYd6 zT-Al}0^!*3m@$ZJUFQbQWC-+|kH6w{JWUw&KJxekd6V9uh^*$e=L*+OPsez_D~k*w zz12$9!fIHpZyj4SNP0$bMUrr%ag5`mizE_8NLL>FAJki6BwR1agodiSmajh4UDN05 zz+QP2g$+MxP00{a%bRtpLA1gb{cNyxWtF@~v#}v$Q4YPcIiKKnTvbBjMh4FeVdAb= zOiFc@;GDlh+?dQXCzRE$SSwBN^hiKawS$$LyU?0moEe6HY9yx=$P@&Ps1*92T77+; zb$wNXaVk~ky;ek1X*)K~uSm2gG&DA^$@Q3sZ3N>O%x*7TfZJDqMOYAO0#%7EN(;ya ziPPgKvK*b!J2m=8ZZtthR{Ra{heINH- zS$e(~pO5f5$L)(B%%a5-zSzAyr12SkXTDnJc@BX!&ysMykVHap17xB{M4f=t%Y!$n zQC{3et+YVJ8%W7#>y1)|S*~u&s`~!#|AJd_|MPDIIO!FfA-97IfWW=Fxph%7ql1%; z*IR=cHBK~Nkr+RQa-Y!OaPd$Iz%@Vw$ny+NA{~gQWmfc7<`Y^!eAM4DRBMG<+F>sFjP#%sEJuq>b;3Ot|MV7R$)Schf-@RlXRteIP` zjpCfzO|C)mT^g5J&JiGIL+Ed+Mvl)$+2R=nu;9xl)DJv+C7_mQ&WB_;rj_fNsny3h zGra{^Z#Tf(0sOSTF*j1hiK(3&3d{G*y4Dc8p+GG3bopu)`HqwXy9m?rM;PSR=~55S z`sRbYs&^+RxVBeu9c;??cajsxufz4;X^0PwpEk9+b}oUcq*Q~1fcfH0NHs@lIiZJ)lERS6m8 z;^sbsDERsePkeL#Nl^RMLRS=bxw-X%2y#yseUn!R9}FWuh}24fDgnotxDze-Ylw-i z>#MxPaUC0_Z!r$T&qD6}_V9-v1oxkR<7jSD_AZ~c1F!$~@Xd9-)!m1;hp$o+G0hbbMjA6VKZ+nU`y`3!1v7PC+w3ZliD@0n(TdV~z>V3jZT*Oc1mzat(1uN+ zC~~c*ry)7ZOr3A0t?}BTvvZ;3y)CFANTFb2dLGDn2WixKu!ZRLiKr)m8EuxQmP!u= zLs@If5j8PA(BcIjzY|4ejI8_3-Dl39_dE305?pjB998$jYRk@N(O$9>Mz=rz3U7LP zeMwFS2vMsKKb?=;WVe;dC`=X73KrC`7N&xqK*{&PQkbuA(H9nH)=XkX%!!4GdaMm9 zaF^Wkk${??b8M$nluR+t2^Y(a?R!K%h9xcXvK-w3f?JR(K78(vf~$mpFUVmQT~#hMd|F zi02WcRxF^($rYZWF0%%f^7OIV`R+; zWCJgjs4FYk{pa6{EQa5M@Y^7(+rl1hEA19UGd^GT{u*6rQr9gwvzEk&>cxO0SJK0$ z!*2ij1Yu!y`w`+SDza5N3d0XT&@Ynn%lALvrEWg|s%X>a(*Y9X`C_%a`v5o^ybODtr=viMh4dqEH}Ov&`jB;LP26I7TkgaS=bPHPv;Xvc385>`BY{} znWpe!v)OumbLabB2LdF`0X4D{W;?0tOI)ORgQBC;7;5!Om1Q39I-fL7mu#q=DBA|8 zG*o`%h2<#crdZn`l)v8=Wd<(8RQ_qT`Xn_sx!_`otntHE!)2#JzB|F=(+JC}n(k~$ ztzyChO>x*@d*>-~+>rthpVep~Pg6)g(N%y%8FYZ=Q@Q_`$KHy}_5}FG1d76YLdl=R zNclUT_9Q+lj{9xkM-)%7zMj%cVqHdTTeg}$D&aD0aJXKco;)uwS`#Ym7Kjf@;`z<3 z62w8GBXR2sH}ZNZJAWWNWz73;#?~ z#!W8)fw)n4DGQRPx5qz@+gHeWKYaOpwpv$Jp)g1eB+SGSKRiFYJ${4tz5D#DLqZ(U zax-7wFw%)m)Et&me2u4Vr;I>>|}vt6V-fj``RZ zdgQUqWzX-p)aV>B>#jnKIUlF@olA%65$hvFPNl%t%!elGcfo};BpJ2rPDkjPj?UMF zgs!EiauhmI>eO-JshxLt){^Gs9*&kggC}01X2oe&S9NkamU)8xOJp8)LAX+2j*Nr^xU)~ ze$SFPTC6^N`OQ(<;&_o*dWNfwA4G@k3p}&M`i>1D+wbz`^*139e;B%@5BHpr`SMO# zw&$(!2{i!Kg=m4mU9LKuy7bhm*2T_f^!AD}QvZ4vM=n(qjq#wCP(c}N^!e7!3e0&? z-KQ+FJWU$Nec?-pi$X$epG#gfvV<3OeLI+0u8&QkDueXE_CuQ(`Y2*zbChgBr&u9} zPAkaq*WPV3{w)f`iX)ft91>pxmMMz6TO{E|{C%c84P}o>uyOST77ijp$M;J}htl}4 z-yU{vxbd>Y%+OvFexO86 z+c}P!Ejvq2G5n;W%%NdYqx_X&>7}Prk>^mu6-2ctvQ&MI|K|FOoW8D*zJ&7Xs1SxI zwzMqD&Bvc{mQpvH4?jT$P?Z$~9WfAH>u(nZVtBPA!D!nw-9msh3^@;MI4?qz8gm3E zNz@I#d3<{zIV9f?W|&n#yk9IK{Xe`uXYn3#aB|16WY=KjlT65Kz`p4M1!)16gL|CG z^n5-%KfXQx8J~`@Jy$n(5P~7~)`UVP;bc0#J#C-AA9g4}5k&LbpMP23eIPZVvf~Vs za$Ds^Q4mJd*2rg@+h$-4$bX2yL1x{Ujdrak$GORBGIVwfxo?wc8_sKVXOV6+i*QoGN?9W;^{_h~k6D_~Gy^I8O!Vyn zIH%{!W#IadCsE%}=phy7ora}Fb3Bz4w>ms*QYuLfdrV!Qf%k15Z9c=g5809&^}N6| z3*<(?G#FWC%Zf8T>AJ$N(6NW}36sk%TW2BcJmLluVvu+LfaN^VpM^&aTW)X%2D(&#a z%{>&nZV)2)y=oxmLK#fgg&XL>*A@I!iH^t|{urwHc10nW+$L)Jm-q_wb)&!2e@zmX z#4p9H6Mfzw2h0+zx*(<`=Oet1N(&%M7@j@c5Signl9x2kK*6j=s?h}{j0}=ni=+k2 zn*h5q2xop2r4V+vuUULhSq%~oZ|(#Vf1#?}qDBwFhn3;F>X;cY0`@Kkl4*S`k_1rg zbrhE^%H+7;zdavbpCJCi#fIU0bN}h)F~5Lhay9^FcRP2~ zi0NpKooq!TO-m$0n^AF%`oSIVvBq71X5EkVLb`^ut+E;J+Q-BIMruD~#9DZ@A&U*1 zJXj=bZ8ZhP*jljDahIIWc(asrhZc?+Iu3O@pp9zgqP1NwZG+lbcAXchA)^$Yl<>B` zJ&m+|clF`38_i$8{Ubl0T`zFLIUN1uc7v*2WqO9VTh|4)I4G%B60thh8-h3CO+D9J zu5Vz`U|LV>w?Ur>M2NIU0i$|^mrb1}Su+MBv_8#zfIR8ot+KZk?c1-$gwk~K9#|Z8 zm5*uLGH_-d!o=kjF--YBYC@W}(y9+A6*de~E5}yQt9QDz*J5HPo`8AEIpH3Gi6)F5H6cY$Z}8j@*7>;0PAAB-mbZ5h@s~IE z5EW0`m-YQeT9asgZVs~E00b&P+S=kW!c!_o42iA zBKISuBG1UD&W3|w21$b-!VVHbyi;W0B_VlCjbxNaVWaxp3LrGe354(pKZXwWr(K!l z@Y62bTPZ}tP+JHC&894aq?bcalFdR8Ilq7#FsJenZXXjW1e z1-h2tIf023(x_myKw?fpNDx~g>4BrSRuXP#e1pPD@OG{j+AeCCkVSOGM!e$TLL%6e z`1X(g1($mN&Ru7PtP!6poFFgD!`nlK zhP&jBM`BZ)$aWZ)8>vmtm1MpkuC(JR;tA55(OfaD6O`1VI+h|-(?+{?R%<)<{KL=i zDu?f1aRQ5J8zfae9K`7l|7^`Pt0*}gCWKSr~e1K}Y=>3TYu8$$0l z7D9|&p~ZlNY`r?tJckv?wZLNU3&=bA&KT+2|LwRXJ2W;lrBdYxUf6n%PNE=8@pzN# zbFJVU_I2fuS}E1(+t8D012MlM&L^+X(gt-RY$WsnPGU&b&{WIzRHVE4`IqC%W1O6Q z&qpq@fP&C!o|o9a$>DOh^deNh%c>SW>&^hx2KF_vx1`iItKhgp9i{ zzdwKdC)DrJe7S#lfOmxQAE{ypdku;-MPnbz9M?#n0aMN?E z^K?}V3MGumNMIh;6;iGlV^Y2|e&ovDVsOxO$2)KI^lX|Cs2z%A1EoL~pR+VZ6ccHR zq9PoYjO3qQ=4DkXcpPa|kiH$nM;ynaep@STkCS#xvygE|H7&xEsAg+L<}Ax43qED| zToIH?3hEa-jt|ip?m4`&rM;JwYCap%7q2Z?Qpodymp}iVCZ~^IekY@r=Gu`z`bE2+ zqVu89dz;Ac-m{!*%2rP-=R-XTGl-9{pY3|+^4xxu&U=2H5z3{ZV<|hqao)=x8Us3g z48n47XfDxc(FIjKS!tIt*&?!&TcgL24j4i8`b^~PT=liiM(_)V6a zVC~(=Cc3>XlLUpIPit zO}OZc2R~h_zGoNoWKU7k9^L&2RW`CEX|&2Bt$q+UoVZQM1Rt;(8&l%vQb)p6ZsXHp zz>-~|zx9EGnS@WAt&XzO36B7NWo$Bt4)7G9C_cPBLuzLGvocBH1*4k{B*V%1G+Qn+ zG)$?aW0z&A$|E*(NA0ezp5kX9&$Y3nuf(O1vs+V13(-GZETAHuuWleaOV7vo>h|#V z6h(8#g~%JjFQbeZSu3Mqdr_dBkKj#Nkt>Jw`tTK^HdNVVllLUVo~a}Ihu#+y#*L&J zUUl^HGm$6d$BGdXwj?&;YQ>c?h8dhfuTA>icvQenEQ^vHATgW=)W1egDdZ5? z4T)DM7g4HfuX#)J>%&;QeO?&FXfK_G?uyc^<~nw;59Ri-BhhBTotBGfuA$Xx)afpa z7}|!&f!2f>Ri!Bx(0dB^5x;foFv1vDEeE2z^A>>2I|UV;i8r!?$2DkQPUm$0 zCgH?}A3?FyTA9pu0{LHK1v z&(YH^SgcS@RVa7#8g`(|9W=;gkN}2Z7AJ~L2k}@fICXY5xJ(K3QP!pg2MMOAgRdKK z_VmZjE?V|B0J3unXs5PPY70AQe4of2y~{_-2;mw<*U~w3`P8ioIiiWkksk3-N@0+6 z@zxc^XcwUqoc-_oqD?H$B8}c=juY~X%Epbsvxme$H^46TQ zcV#QafsBe)7N7P>d_;42&sUO(P$@%3;6>5t?e)WNe?RSClO%@sE#FdDz(t-r9=f-o z&;eEGu-oB+q0CN`GeePtQ+$rX*_;#`_!V%-HGqd48X7SJsyunG-gj2NW-&QQU{Qfj zsY@|sJ%y|%MBC#Q#tawd?X^}=qTXwxl;>LPFhQ3Z-r72~AW0>?tDF|#?%I~3eh9nW zvn{t#JLa+Lma_6X%-y&rQik*S?wO;e8t#Nzt5i~(Lz*9~%cF;;X3`Ml=_LdD_tlA5(}`&rQWd>gP}6=w2 z%JU{oZKz=UfLCZ;BOM2V8L8->ak4-i6=+4_d93zoxUrL&^W;qt6CWy#IFqkxZo}_gcd2(AFnbDfGKqhn=*%i3h zI}JN*Zo23UV39qF&LS&Ps)e&pLN!~LovO>Y;vV#9nkiBF7J!aDS#*(Du5Y0@v!XeC zGdUlkxATP^ zkw1GhrOBg5B}k%$$#zdt=pbZA-8wN}Ls{@CP$R!+P>esRupFpn;^SUYcLg39ye*uI zhCJS+mY&LpJ3OY@8R#&2-Pld)pxkyL8gq+i059*g)?}w-FknCPLA^R?REd)g^j+3nK7#dG3!$9k;mv5tajPgy9_<58&tRR?rx$bs104c$MfrZ z6TI!0TqoK|o*WOvF2g93oQ@D}|@d>pcn1EBjChvIe zxDd6;hS7!PtsI@PMMirkIqoAIC)QKt@HJi^zs?MNM;(-1_sM?8?vGvfbsZP}LWNFN z_qZIbgx(A-1}0Cw(SMtFEoHA^%j6WIXZn*`!b$VP;q4h4l2w_-@*QeHuE;k@!h!%jzdryiB4{kovsF>c4{I6_J^+xTeS+thu zN_g7ph2hzc2zBqk%O-z-O;XFI!uqv2A#a(oPL{+)oVZSzY4U^4>cg$op7;eZFnpk6k zoP8h>MkrvBhtXoTS`!>gh!*Na@x~fEP9d}I<|7|%osKMJrutKx#t4_a)JrGa!#agc z&IcB}d`Qp`7yh9Jh}fh@bDdmXTI1nCL4udv>`~TAA|0|w$1QD9lDiRvU|HgqOdAeD z46E>8Wh6?PmL&R9RtQRi%+$vWrKozG0Ler&vX@q9P)9;mNmeJtAWwq))v**06)r5g zy@yTZM6)_Wm0^{F3Sv{C%Mql~B(93Kb&l-^AsivZL&1&;y61764wDCPMP|U*1eRq1 zzhXJA1KSuU6^J+%ExAVDMUI$aA;7K^bU^JF&oi5lo?tRV>2WJcrH6L!(QNR z9HypxH+yan=YvJTujehA<=j(sWhc*$Gy%f!U9U0UH=tuzB-z*%aumN}YjjOc$fz91 zQ@t#56kn}NCGKBjIXv+q#fV(wsUJqzPAYS>HLFU}(BXNOpdBq_=6MFy8$@Bp@zCJ8 zX?TnDCT>CLdx0|C`ccPVlA?XdpzFV>9qD`fG)^mSw66G-e3>c#+i~w|Qcg&S^n5%W zcF}U(5|^35f3Zlvv*w&%p*Zp%>4)&CUy<)H^hn2%4V-4ia!Y6>oSu$FkuTPpHRQOY zq=6zqkKf|sHa#Db(>_mQ*AFdQnCv^qh(C2cEJItHZdk(&UNRr5P4dBaS~l#3#9=3< zH`V6mErX65%9)%GXd1kiua_5MHdJzO+tLniogNmXwCDVsRB=`364Kiw$3RR& z^Zu+;sh|3TRt|$>Ez1d4XcIuV;j)cZ2H%@PT&)oX(lAu@Y_UK(Jo-guZ~;XyUtzNq z<7QB$DO&#`1V>=rjZG5W_^m70XlY*L0zyj|A}-BwQDYF{kh$P$28aF1Iz2I{RJ}k= zlVEcrN>7MEq-%Eojyojl?O!{JV$alIvMqDkY3!I0ub zpT9$u5Rj_m^@$>TSA_cVhsEWihmQ#v?*91^@}Xe1Y-iQ{GP8y-=D2PepHMvWr{63O z>Cv|5L2Hs3|f94AiN*B*`Yv z!7$nw&|3A0tA=M}1p-GmXDFUh6{u7VUn5_Rp0Pvn!DVf@T+>ahs(8P{N&Rd-Uu^>0 zF4L2wAPw~=x15GRIoNb)c!O~I8bymp23#3vN`uO*I7YZt%Bq)XG^eD!mQEX*xf+?P zPpKw=+8c@KwhA40oNLFp*7?aG$@jAq$wv|$?iDc2Mq%WT6B^Z#qr|wZo{i6bPzKA$~0ug1%;hEQ$BpFpLj{O<6np;R82J0^_US zk54C9lk@d0d2;#>whL$;~7Fx&;y545TTvQ5@|8bhNz#JGa0ns`xpF~H@mH(g89=z@70uVvR4 z?uZ){KDZ&3DV4~yY9V5>m?d>n1dfk|AhY3n(R?jzmrPcmaJzw&q{(9fy)@2Z)ifv# z4B3a&Lk|*pX;_-&hxkw=hlbo3;gXDJz^pK^mh)!2tXdecg>Xck z@8A(Y*e&BTwik#D*dIR~bBw^+oIG#NyEjOUmp6Alx!wvF1)s1mvmMw)4dUKVhJxIc zJjj@F1g|J|QrVj8XGLrx3yNH0tStKpZu_M42(Pzl(djPD>v$(7OnRUl+p!D5(ioNT zPNhq%gyE+-%$cAkc zQ9}<1QK4%%B4D8!%HW$mnqblsbWjhBN;9$uvSC$0f{c2JsF8M5(Nu|DQIe|W)(vtH z)NBg{QfeNM#J0B9Q&Uz_IU(eL+NM%N2^8s}o7K=u(nthhUk+*mRYjGfUrb(RF`f~^ z&XX8+1jOaK$j`RWcfO^enT!z3UO!SQg~zs(kFsSGyV`$!!6X5#p zC-eZUip$9@q;Apbrbyz)KmIFA6N$7yq!$vCR+L4-(cr;@tT~0dCoIQv;l9BEW_R<% zp7&}Z77VhKL9~z^^r`2}3O=+%(pU&-`qbz@_rS}RKF5a9miK%S+3jqNmTOv@ym6IE zNLnc28}hJ#<;&~ZC7b55+ErFvBq!m|9pA+>>2S0hs_x<5#4$e~+;CAr(d5B`iRi^3 zo30Bf(=;tnb25h2jaen~MJ%PKgH#*329JIR#nht znnM5;uH6)sv1fUg$YPaxKJTh(ar>RcY-&~%b)G3$n&kzwDI3{`IqC`% z=M}EN#)8tSkObJL?Oo(;z3XI)i|bT;G)AH(^s&1CO?ztgG>^7TVJr%5D%aEOBbnMp75}_{S0|BMdsq7seyDF_f_#ZVwVe)gRDf5#`azJ0%Ak2%#hp$&WN7C3xO% zrMx)J-e-LeTk-Rk;730>EX?)<(59g0x z|5X<`mS$1s*!EF?R~R=1xZD=)Kb_$YC2Dze=5 zvEhJ`oNkY=Pv1%Zz|z7Lcx_0SQr~G>u7D)gE?jyNpR4lg>h2z5E0)4WD@OH9jxP_p z*C*5i2?MxnhdfHk9E<6y%55|S@lf2OhMSQ>h<|A;x9F!{ca7q#=wm=1uZ>&TeqSmtSoQ8bE1CkdXhU#gD1S5r-w~wWj*Hmy zLK|73C&(z--gN}57du+ujfUzTR(zh)iY4{nt=5F`0@xB5QQO{#$%A~NZB}*Uv_$QJzAh4=FI2+6ws;b<-JVL6ty!`-cxPuQOr_{15Qs$&i0^v8& zNnO-+X*85!H#iWow@=?)*!zoBx1z7(Mz~VKr_q8f6-keN&0==v0A|tAN5c1#PEF+I zHbli*-hA+asIwHI@xQ%&{C?cNxV{g0G45!=)6-t*M;8q|Tv6-hp>UASCs3U+jrVV_ zcHh7??R`zQP)|-!U?KH5TX&3hEe)L7d*L2KBA}DCG#7i{@RfrU*d*Ce$5OU@1UV4a z@Be|_AnJ-KEiy{a-6#@A)KXgA+&Er<7=tpa^Bfaf$U_lO;aM~{P+%Y=L0;OouDpRHbGV4QrC zGnS>Z;LajlAo2myMk?lV#VaX`%=1Gs!b90pM7A-WrZIVy))q})nPP~wu8#C%YQY=` zAZWvE+2L$H2Ja6o~1#wm{*N$ zG#1z(pB+HtTaj$lDdtSi;;44+eViL6jiI_6$Pf=VyclX98&Oz}uxqUQuQX$~lCWuv z{0SE^YaBS%8e&ExXv~5m8U=zY88DQ0msP0_PiwwVGci?M&|tJk3K9gWGo*Xq1WYP5 z6W+8Aki5lDp_Gqn2M!c}Okfqm$){0CHBg@clYe-vR&s$eYTK#xMD~mV6DdlgWm!W3 zh&WK1$w+NJgI$yMm~3QK!-`CgJHFg-SwUXUQ5ejE?aOTsHl*+nM`~I2DAyy3cwdyX z-(`l>+9cIgSrK*aP;!JZl-(gJyZ-MOZ)47AnKXsd&^)JI!4i%N1Y@{ zLr~_qa=If&M2l%FWve2KE9L2h1TD-5D;Gt=BqH9*(uG1dh?Ie`9BPR+Exe_saIZGS zk6JP8U8ICGz1QIXMYDx!=C%@RGMq0dm8l3G+ZalLxa{`NSf@iO{qfhozdd}z)ow}j zl=D4V4^B!5h>ri05=^sQMDp!ko?y=e(F_NVly*R&0Lk_Fu!AQ8fgAp+EDJc-&0$l)2K(fCT=FVjE0>G(P6q4aJ4qcE^~X+I58aK%UKbN!Fn(co*=+g+7eZXh%~bhp;sq z7YCGk%X@gb@J$C{fR3k0>Sf*tbP#BYQbM9@JFqR{GKSzMbJS6_e7_-QPc^Po)GgNZ zdLrDl)s%xfq#e!*hVM&uUrptMp5KZn^)bp{Na6!iHLiVR2Z*<~Dc;`;w zQ~s3~sH%{hC=qi`iik>!GEI)h?bda@n@^v%Pv6j8h56SG09Xg;Qwe7$ z2G&A(7jmTsCRKa4<;5VcD03V~wT#Kk4PoP19M9IP))Gr8-3jFrg#A3O`g2IrAGsA? ziNfq%!rR4NYRl2y4YQMs8G2GcE_`@>*}go&-TUeH|FL_0jF0=(?FUGEVPO-xZg}{s z6CL3_kl*BxJHto*@acElEZFtMH-+#WEf7|`efabF`yY2deSrfq&(l0j7Mr{Ia#NPY zyQl0BCj&>S;|KyxNzqW5qOv~}!qhwq+oh3ZrC7^QufPsn+}wGy1=10E;GoFT6TCZ| z1tnAol>9bSG#uZa5DZfxZqJLNsyOFKA{^Vw&cSS{Bx?#tpADJV-hDv!UubzzW45Nh z-(|0|<2tEvRf|dPTMZ+n7D;%UPM(7G%9hfkcu6)AC{kz)(H;k)AD4FnK(64Hf=0-S zdgJ+UvLV74LSaR+AiOG|sIxr83^kTh)n#185a%!`Q$;DXSEHb&NTWD)yh{`b3+&IA zB-7?qjw)Sr#1c#!`Zl_=++%L3$;2(sK_GJpKUQ^u>s6L9+iQ|jjx7?0hTIhz#<(8r zSI9#czrk$axMj&1wzBQdD|s%H)IsZFmL&;%AZ(R%o&B!vq$Z!zX0F?WMbES3B%f_S zN#`B2QB|j-!B0zh)DUXfeNIzInj0cstWTDWplXit*o8#O=yd45(;1pJTKY#`VJ-73 zu;O=UU48o!HkA`#%MX&f!|P)T>F9a``4XcZ?qUC$$8j{9N2`tM#`lAQ2@D3VCa9$x z&qdxm4wtp80`^IZLZQ>t2FB4BE3E)W7qE>TFMyC#kq1nc#8~jgr*=Nxbow%cBStha zL4DC0;Kp{mN=%Ohlqx1T;ICsZbjj8aC|*{r?a zjK4j6bzT4N^KT7F!L&bv0*6h7+WGgt{q6aWe{P??J6~KV0~hNXxT~ZfAudFnu7PB* zQ|!QRV0a0KZ8k57*JRf)P zGatVE_VmZU;`1I`7Ip1~A(RNHLXIO!#5ZAMYN%Qw$6}bh-yg_t%R{Wh$k``vo(HcVLhp&(lT^>cO2eW_VKLVK73r){gZMYHuMt;}5;ke4Ax=MwcB8WZX42wI(>bVCvKP(D1fzc1`?@T_NLMb+J=z1c}Zp z1?(=^fq9yq_HVC${sGCC7tM~_7uZg&>!P+pLz>j2AkGGMYGVO2Bmo9tmYiXuYM*05 z$Uw9uKP`@yaWo)OMIMA0R9UME#F1GTz6<0;cciYqUC0cHvx>WjV*o3W$q)zi9 zYw{ejW#M?#&}f*3G?20n7N?5R!eyRp9-k66OM1FIou7P73cd4xtW4bA7;tc?^n zahivn!MPWO5cYYKRgLVBy6V}(3q-Sk7iE>iUO2P-u#69RoQ9iwCk(52pC4XrZ{{xU zaa>qs5R08zgq>(9oglOzyC)c?y7!H48R}UXuC2OJ-t0zPnEI(2EW8*zZjLsksMSi=}R?E z2$vXkk8dxqFz!EoNz?e{+aI&_2BI^Sw{#9p=xyrPheW{-qvYs7C94g+6fKENVRh9Z zb*qh>=k2QC5Xig$9VG~M%!> zJ}=jkAA+3LNNdJ35@N5%*!+Cj!6Sx)6JkM;#0rmc|M}OtBJo?AuG{@)>cPD9MbkDJ zMj^F#WA4-#yOty~NE{{>f}80!@2Zfd!^W|`CDJ1`q}iQl7~|JH9Qt2^wOC_NL?uJa z5KyfLvV(9wuhkqx{f}A|MHWL?v=R4)>MAadn8oS1OV5Y8DAd-bv{_$2Z_DQ@%bS-{ z2U5fZH`36DRFiJRt_eYE5!{XfKUg_#fO8C zct1nsrihwhaev8<>!xSg`Kh}$gXTN}{>tlYI^Mx4dAm$Cr*60duc7+o6*&m`J_Q5E zt|eCeRgoRup2KJc`7eqBmlfnv=veA|kP4l)Z#Zys9F#6G=||JVJmyD>JWC;5LVBw= z842U6W(YBx?S}MHppN3yp@x4*%12-yhQ?N&A3;5CwPXZ>;*^eyEH1;*{Tk)>5-7;7 zD~P^BHN4h{SJX8NZW`2xAAk8wX>ticYO%hvY%5FP2#YC6kl}0=F4mCGqw6^tiFSr> zsLVx;7r5sry9|-BDEw${BQ`J0&L=cKr6{a?rwC0rISCPl;vk!l231EOpP)@*rVCHD zZivA+b-GIl7qf4gJjDYNy$3BveFO;KqC(Lc1(>PHANuw2PdMOlG#`e9HnD8pbv_5c z-o96B!ppj!>BP@Qc5~do?iqe`Qiol$5!`8&%bqc8$c#%9I3YWQ#<)K(Udd%SJ8$zfMRs?v1Q7NST0v{kVr zLlz`rkUt|IDKbdyuj2TT=ll2=;e!+zyi}RRXiS=tcb4Ft=nm=t0aUe32%` zWCNEXX}at%qEqec!?SO&an-10@XEx}LrR4d&M)vb>faawTTR zP~_qC_Uie8N{3;+_)b9h1ZfGeT;IaqocCJ@i-b92BfHGeo5I5gLgZ^8Os&l7*5sv4 ztLewH|KEeo6{Riz8dqsVO}SjNfu$aV~>f!XTDZignU)yQqP5^p=g ze0;X>mQ`#{>V`CpmImFSkeM`Mx_U4DF0$pXbX^GEwm5kYNj7{(`=-Rjh0$xPI1Z&g za_!X}$5}Lon5bM*@+3wQogdgA$ z0FNE(5GgM~uoCT*atQiPU3w8JLucoM<793SL7hu19ZSLZaBwFZg;&dqB6565>qZq# z)p-xem=(^*!9WP#M_)QIb2dMijU15M(aY5Z8A!N6Lr|)39sV0;o@p{O2Sr=UNrsv~sxk20GqRcsWAv}eo|3Kh@%d}TsakHLO z-guuZ{zLp9K@NoT{PYKW{>}X->Zr7Xun}kqjUqLm7;*jB(kO}U!qfBV`1YD-F`hIC z?{oacjPTs(XR5XNaZf{Vc9fKogV;D<#S#m3K~c>kOJg{@;9!GeQjTxM`}Fk5(`!PK z7%qN&|0zup)Pr7bu(-i1tZadk0JuOnhg=seXl)c)DADW{qErEwe0+QS)7JH6>(nXv z0EpIm<8VHpckq6fw5ALLYDOm{&sguKVcKf2uEp5t4Yyt34tmk^3h0&E*0Ah^Xs0qa zh5oe4y5beJY>@ehBz#IMu>Xr_l3Kb#*{pELPLrZIpY}DHnG4Hvy8>UTzADZ@aW>Wo z*1%ncs)9M#hErVb#wZKAR1<}Mj)x+N$uvu3`6-WMm7pptDvlixgW(_+4KiG`LTY%P zA@t355#Mw=VpB4lVWFC*b)jIQHP$<>n;Z}LLQ2c37m#S1`$92kDSgL2mo~%_gSw}s zyzw7Y_L5z2;d(WBIUomgtzHx6YM4e#W1t`}7r5!%F%iYv)tF<#b=j{Lg6>Hv(Myevhk0fW+E!z&}2K2Q|G zezYs{O}5L>oROfH_<63Phd*F4XlUag8lneNI% z4sQnOwigCc2$JiJgA0DDfb^$_+~~~O|F5*x7-xS{!J9)IeS0vg(V=xxO~;L1DjREy z`}Vahn^aiCGL#UuQkuZ8?4u`{-_rr?Q=ee{@|ZFsCIKif3?qi(E!5Ww;~*M9aT6!Q z!EiJfPX_2_G=^dsenoiz7Ih2M9C#>;9MLjReuW|DyoJg@l8EbVS92QiVS9nBxLvB( zE5WEGXb+avByxgSWBjrnN;^R~E(<7uo#Au_v3PQR$#`vdMcAK-yR#mVd*?Xm>v^PO z%LBdelHcbjB5zIgRE48rHTuMl{z z-hN2e%jMJkaCR19LmaW)*cMkCylB4PfBtQ=n3MD%B9XG)dcR#4L}5ijmXGvWUUTQv z@QL+zB-*zvwm=7?crb!|3y!(0$XyWm3N@LWGMdieH-h^K4gq+f~<=$xMqWsjVg`yR0S7r>yXp3JgNtP+`^uZI5E7Xq#7m!k8+$cnk0%C3u530kSr+avZ zU^opXGcQ8rHFS(Fa|WRX74`-Q2!x0*!YIrd!(PgNMN>k0<1yHJioB5G0zzw5I#NmU$XIlAzFz2Y?zI%apBRdxygp;HBBot+xtyeC;UpTjz3 z(cxCYXgi#QNaRf@q{cx=i5U45Qh%bV<)2#Yhd4?~hGZ)TK{J5LDU2d72zg!GU$Ks2 zh{Z^CMFC8dJ_u^m&!Bs$t^-)NLc0mF3O}Iypkm~i1)Bl!`mmu4+2VM1&ZXqgpN0?C z;|ki=P{9MySa(42DLh0r423F9+8GPAqn>Ai+Ll`|WDC zUhcP>iYg4)T%Cr{e|(lYi9g+&8GIO0uBKXl zVABS+iqXX_Hxe7YF6Cgy5T9%a$tpDSmfF5+s|mPFYcNV7Ax+U!S~8B&|5c(=j2nvo zwFYxHdYui}>4>*v!Nl?1;Pw?ge`F#%3NT;h)nNw}3)v<)btRz-v^&9t8BY+3lnkPf ziqirW%MhuZm%@>bROp8Z^BfJT*5x+pFTsVyI{=pjvo!Kq%cg>QF*v*MNV*UwFVUce zRQHg&==VJmqYOHV9K8vXDg9i!QS6aYqT3p62{8|a^aF`P;pNx!>P z-QbGrfGfM59d$i||4Dvfk7UTGDy!A}0lvc^8B@NiXlc}Hj)|~GZXGCLL}AuN+z!@6 zWGPE3#zNqRF;a#=4z)y3Rn-@O9HH&j z`$Ajc*Y)o{{*rFDH*elUtx$Hb-P%FiCH>Fk<2@>XMuRAhx9df=+u^5s9-`TzX!-m| zL}wJGjEBSJ^TTL7gAKB(%8n)pY1P9Ep;myxzc^&m%bU^cOcXJ&&U~cI)rT~N$POPQ z7Cvqv?rFC=b{bXY8B5N568pl1za!`FFs_nqgDd0 zpQ9ijW-Aaey-`v#HJBv+Flt`;Ug&v4*stROyf7!7!=^iGo*GwsUEnGUuyn!)gJckR zkQR>#y;Pt>C@lLTLyk3BBcPQ-k@K=bej@W^wXWgYs!=c6Ifug`M+rfZhdYh6oTb0j z_**%x)VRr-n{UC`v2c)TAvxN3yLTpiTmv`e%chZ*Verv-+L{wQ$2@pqNgy)c??(-v z&gOWJcNstFxWSHsc=I#dHxPE=HiIZ|ar+9sf=7JKa&tLh)CEpMEf|{A%;*;NAYU@wBIa8vvV{| zsVn3A3A|%6oJ<15Q@WH4x?~K>DHq0y2ySS|vIj%#M^DZ#<76ZN$Ot^3JX-ycB82E? zsUC5g|2+A(Oi(vDdIbrxb)w0cgIdOrDCPM+J!D04ei5PsU!_$FMFmZYaZK1YKqisq zx!8cDRG1RbPz)tzbtfz_yj~$QW^1BZa__d9+Hq?`HJrFYA~*OnO`GmRt2Xj528M%_ z9cVaN)sSvPO^=xO8|RqHTNpelnxk5*l2i2PP69};50mnqsK_fQh9ddvZ~yc>@5OgN z;O$uz#~C+8M$(Ka3MA}f_YA?a6rDrN*IWU26dL_*nHSl9)69M?`DR`_x_@=N-&u5r zAdGg)1*F3e#L5+Pw!g^}PWAO|mh{`UF#;oI!u^6KR~$mn^) zTH-yBWNkGpFNBIM4Ic!SEfl7AAAcQBkw>%LEFpKQOQA;KLa-iP2t|` zf=5xNT*IZ(kxdZ2>{Va58FY#K+m&@F(<&IQDrD>S4#0KK!nCha+V;|sh_DA@T~I5m z7PJda8f*urJYcd(EHriJGD1+`_e~)sNDsAWhE@10-{V*6#{V1VnA&*C6 zhT`ANh@4A^FMdl0T^@?Pz_dy?R9E#SSgCS+}O@BB!j%t z;d?!O{WO2Pn?f@D`aPL)p(qlGz@famu>2I9Q#Ej9uAC4_{n%C%76}$)Hc>o8+pzT_ zijarq(oB<+AP}UkP$8(Z(Km`b;Zbei&*+@P-UIateCTTVobI+zc?cj!S4+xJq^mjP zyf{9e%zV@`nEE(&4bU0ukmdUw>{2K<5yiXh3KiyDH`{N0Kk{R2G5L_!^Oip0(GRjw z+oo+wUWGA&akZO<2^LmDnr1r8v~B~l1mKyP{yVNAv}Tg%>MqcXoCLLWgQO>>_;|Od zN(VvUBG`DsWYiV-4c~>*2o|IOjbo$7MeAiGZ$v{Dq6JaD-IXLB&k=JT!imF)iWhot zg|;cn4^Wxx4>=Tf!`YNzWSb%MSSU-VQeDWEI~0W>zNBf2b9T>_Bu9b|3k^d?R(3UOBNOENbiySh zqm3Jq{pNBp5-q3E9ciR88CM=1LM>nUcyNQ+Ve^~YKX8k8qTp+_c1Ys9Z|293020C` z2OmVTz+peTyp4xLUe#SM=?3(XI=E}d_;Ayv^8_0h?lXv4FW&y;?vJ0JzI?oR@v6%r ziV5{`;`Nq>2Ey@R5T_upM@Pw3e-DXwL(S|16m?ZR80J|PB?%;1?W4kI*D7gCz#v0#@1L;miHUU(T*yB%?_wtAP$Z z6WlU`a5O!Gtt%wQGT3GD9HL>H3kmynv*KAgo}58_lZ?jO)nc=Fg31Pdl^-&M(w2oc zyu5AGmm3_h)W&9wG`B_>H`y`M#M1^Dsyh6RMN_sraC!{rFcT!ln4J(Yy@2YTsSkIw zI5~4{4wlH4l+YK4l8+0oTWssPa`?bdy%lj^Wx*hZB7TUwQQ{?2H$?U`oYviDgS}?z z=lX+WaDL`OB!il9yX9FHP}zuxB1)4h5{`&tDDn_hT9j2wz?+McN^;cH4R*sYfOkWH zj*kMVWwu9oBbRW^V$ufpoFf2v%%|3{^1qN#m?V!}VN{dBe|fGabdJV|8&C$;JZSNg znO1IUkE58=(;#McvzW6seVO$U29EOLPAscq&kIc@D6Zx*NF>EMi`NrLJGcpGFp;CC zB19jTxhFx#RuG5(V7X>{s5%cw!J(-=b6u6OyRNi<@48(Hv;)f(_VNwnP<{{&21<-c zw2&}bAsKADfgKv2*0_{)a!;5mnR|65VI6g8{IjxuZvEZ-lfXF=e1dSg{eCo^p|2x{ zf*Pq1kj=Gl(3pw@=*IT#kDt@+_Tu*C#f#TfT?i3pNQ0m6zRd5x?l;S9zuT>s>%|id z-?qEWYQ1ybJ%!`w2cL zHYG;5q!KHU$qas2&z}(SJs$I#_aQCe9uDF`w%fqBgW5$@-i{Q+Ba?0@Xb93nIUJtV zA-=gJK>A@MS`)0h3oXePn##-^&9G3YU2T}99_QwwF>uG4&7rd|y-by>mI+Tbwn!1) z>vm<&j>xlI<7<>Xk5n0}wbKrTU!pt{0+bA!B@HbcKo(qAII)Fy@dhJ^eJ<+zY!~yV zyvUpBepSLRJgB@%R2yMff+1o*iV#uc2EIU;A-*V%prk5D^wLB=E1aO7hqaQ&2W>$dIuiMivsTZT9UowTux(nrB+kZ zqcHmst*&uLZpT`f;uZytIel_&dKSyA;cxe%>0(*49*&31WU89uoYS(#;3x2&g1^HN z4^ziDRX6abCmSS!$Z^DHJ$#UA~KK4}Qnhvn#}Y{>txpoStkj){6uLp+kU z-FE097ZP{#{P^(Y54ihoU%#7PTtj53CC?p_#30*lN%69RGkkV^3!jssv3xYUyhi)v zbXTIE5Q>QMy6QPXQ6-}gFr?%ed0W64&JTw?O(8m?xqTZo!MaATR&gL@(oV5UoSL`= z19Bw68D^dhr)Q33)5grC7;Wj|WV1rOkvJYACo_!T3(|gt`zy)@Q2`8RgBoJKOX`gR zlPBS8MmlT)AGIC2qP9nph>GaGkHxC#Kv_6s;L0H zwaQHq8qt@~wqm>)@VF?sE#PXzeSmZ(KVUP<;lcpa@j?{&Ma+DFd1j8wY@eo@%7u5B z%OaNrVtevK?9L-Z%&CjK%rY(vmbg%iz=95GBC4Bdd7(7==vXMj!VKdftYgGA5 z;SRSiRBMSaHH$qRj#+0}DFOU~cZq>m(uhy2M$N@WASa|(IWC*H8EEwiQ!rg$Q)hWc zwv*`Hi8_B3YQ97ff|Hg{50Lu7F9#^NT6Z;`o?=7_sz)O9VU|R&ex}gFgsWf{J`AQ-03@Tp6!Ewf|DrhN~t zG^BQZGWOz;A4J)1mu}V&pD{OqtR#p~rAQbW8kay$1F;d|98##5QyF*-z#4O!tl01j z(QdsB;7@iJj^=2``4zKecuXr%?MCa^G1v42(Vz>aw`$hSgzg9+W^|xBsJ1fVldDnn zC1B<3R!g{EQ8G5ThDRt@;vEwf#T8aQaK(4)70M~V-6A_jEWnZoiqkc1)qX@gI=xsr zw=i-`!=cT7y@JS&`PXm^*ZQ#E9S$kHDT)q{CWqZFM7=8Si1*dEbMT%{DC<|Z>6935 zHYQ$*k6u~ot2sWl!T^3ooKTtJL zqN^SpILe6x*!HX`FjugXL6V1?N>$CyuT*P-J0|1RX*7sU&MGqqSdD6gdQdJk*4V~c z)H`8qquBeFGlz)swFIhJNwJ2kFox3O=KqBlWQv^{^LxYn`nPh0(GaoyB5pq!eGADlnQqS%p|+EEL(F+*$;Vdfake7!p} z-cxe3F8K%jh{D_pcqI3`TN9mX7TAo1>kg?1TrNm?49K08Ka$Qj0&9q5%qjgv3x@q> z4fQcGY&^lTgQOM1R5FC38}5hU?80!;JPMTPR)A`z>!*i2+r$1k98clhASh$S9fsrC z#rX23NcWJqd0_yBnG8Cta}s!h_tnQ9?4uNRns<;Ja~Q(`EFZq!fB6Wz{djtQ^X9u` zG*(td?KlYA*LJI zeS#F;z-d@pEVU5b(d-hgDA`IBNbltkPEx#C!ibo<`EI?0<441_+4;qb*ATpk&|#vD ztj@1pv8wK{W2HNe+4pPhy3Ei-QyG!yMX2$RCdW!Dv&gPxcSHDbNV0}BWpa3rIG>v4 zadsri&6zRhsp(&?h{afEc|nvzd9d3L1_PW(R58=NMPfd$Z`&;sYW3@;ve$7HU?m5AnCcp(?hT%Bv2tLMi)@SVDl&( z!0zv(YTp2{#6|6fu}8*8Rz<*tv%Ty=>~`DqkjdOlv>sJW!feiQGqy7t6bk%gqq6!% z0nH+Z+ao&-8Ma!n*l4yVu^2j!eorVL#dUS+OE7Wx2x_DQ$qZ$!j2w7y2 z9~O__p1ytBZ#RQvc>Vg_>>4U*t_+Ggnn#doY*!1!IKw$vFD7SK=PzER>*eC{9=4XN z*Y9B$g#8S1+hjbeo7Mz7sXM|1+fZt!G3R6j(0p;CuX<14KEs*3e)InF_BDz$jmE>t z6c1y)f_(za%>y$eTc(O|#d6-XyVloSNb(J&dHgKy!Kf=!1UMM#FpTepCShygSR;e}dz3<{|- zL9%0jfi_CB1FEQqAmzGA7$Bt%^#_s|9q?Qqu1W!$LK+4!(x_aQ2-c7$heQCWIcq59 zL>eT8Bl3w!QFJwx$R|6=G>Qx(KyoG8q;0X)j(MWvYl{9DMxKsk)nc^jtsrsC*I-t& z=}+9Hn@!b}r00#(0Q>)?y(?8aRc`GZQx!PzMGjd;z+PDXDXc@tp`sY28oem=9N0T^ za*#udPdJC$<#U)Mei%cH5|aYvaMRdKoDzttoAnAc%tw*oZg4E0flgV@ z)@+ych<5g6#~6p#%lRSO-@g4misSo_zh>#4JJt28_g8N|-2L{`dj52F{gN6Tojf3X zk0RSo&MxwF4|@s1nLW=|nzvq6mVyT2!pEW84(`?xs*G_9q19oQ?ew?vxz%$u-7##r zA7iss(bl?UmE3!CT^m@N85T7bO@>QZV7fiVEoSg-`Eh7gp18YZwB@!5kn$fP!*L;f ziWBw{HC|nGF=D8+j+F4(`C;=6u}tJR{$Rohii_>PAebZr->J)NgW!q^^H%(UTw5wA z9#JITM~`&hmpZ(P4ik+=HL17Ykj>TTT`q+9E-uC>T>(XIws+zr7@fh*n{QV55eLU3 z(P4KmWQ63G8;rURaz;nFJ>1QQ{kA3n5!oVQhTB&I?QM{+S~ozcXZGY)#*NMT$esp# z!Xj%J81V)vY^(pY1A1r0Zg z%!aDki=mdvaHvqAU+wDo0bVek%&7W2sFN#1N%12+A5y7Mj)v+QU49qO@NpNnuLPW2 z>Eo!LV^u)bmd|mXjI*!he0p|4Ud60SKUY|QdBjn2{>&0d3!XW0q^qn6VR__-1H`Pu z4&`Ctrh*%FI=f6J6DZ+PRIE_YU3S7YNv+wknqAzCre}|zf4}?V7ud$GUcd9>!Rql2 zLKUKg81DxT9_#1ve(ubv*#IO%>1H`TgA8=^@W(Gj0To7o0K~kAqro5Bo#$-HOsk&Nd zwdR5l4W=wB&n+45X($`)Ih7wpMLIZa*U5AeM1#$Go}w%v^MY`kB$4kCI+8?S$xsXO z*CImgQkS>r{Wi;40e-by1amB-5Q`Pvg=w?OQafk29GkjIv@Q^bP+IbE{tmkrVN~=$ zfn4KM66H7TI-JeoON#7J#Muxrjs+_Y7=>YtL5042yoVqQOC9#Y{c4es>@@**Y8s@X zKQYu$nhfQK5t+^nC^d7WJ>5}PfhKsP-DVZU1GwKHK*H^2ByKHw1>7}-hZ^)DZ&(`K z5{F?HONMlh$w#-y%LDomL9oF6fOGgFXeBqE!WV>d!Kq<)B(LL~Fnfl$wp*{i{Q6&K z*S9af|F`-5=lR{&Y`?pC{XRii_fLoYE>1@Ms9rVIB)c4A9@y8o=yt|JQ=T2twWjBn zyX6z)p%=HW;oZ{x2CfT&&%=mk$k_5NihRcaP!!?Qi|gg%9bC9Dit4)Rw?kB2W8c4e z`G&k!aOy+tP)}V%dG>sru^OrlrWsPZgU)z&>cM&)AFY-}EovX58B!bcIgL0Lp;`5a zEtLrq&{!KnY$8~@O$Dsb7_BKgWjrMW;HqSmFH{&fB*!%i2PmQ9dmbbm`*er1yC689 zUB*$oeZEJ&>1bF&2880=m`?hr$X-DpCLxHz!BmCpN(r`t<1)xk%c{&$H;e|OQC8&G z>!2xn91jL@eAsNtGL6O)q%u1wU|Q~XF6JOXo~9LdquHhByG_QU)+vchID#*lAF#vC zod)HtTN7M0gIy!dlK&DEmk!h~>mAAUXP8z}smq1KrA)%*d?D~V=~p%b~qLj)hz4!NTvQ3tNxZoL#hT69px znJtc)A*7DaFAxii>I5ZP5~5p@Pkvn(l28#5hq~k`RpD?C;l@M-+RUG(7gv<(wrBka ziXxCxofi-?(#?8ueq}EL9j(y6;ft)nDc!BW_Yu zfhusVmBo*`z)VP_y9Qt5$Q-PdoN^}L*>UwCvgtNhb%#o&O|cT@8nL+DF%(w!vPaBn z%|OvMcuwQ-WByl^mFwk9&bGYTtq@^79OnDocDF2u!GXeSkhSjDB&Swp>je~ML5wMC zMNbHE;O;?cg+>gb{TGH1c131d?DwK$TV?wgVsVm`n~i7@`gl8pDBR;PFG>m|HwRuc zgeA)hH0aIq(j82YT<5gAd>BE{I>aT-{~C@L{e2OO%naSi#`q9}4$)>*nS)U0TF*dr zx7{)1&5r%vcw2I`8QR+BN!qZGQldnF<5krG4e028gvbJw>~j75RA=YXjlBSw$?wXz(guFP(cH6;t3V|4zwSLf8yW7h+nM_vCkAWM) zfgQ44Fi3b=v`8YHEIfwe@n$(+%pWz4UUBlc4##R^792oS*$f7uA4jm4phB1z2%E#2 zM5bDxE|+#GZdP1cUgJC@Bwe<+byTh{;q# zpc~g>4(MD(iR*FS<2{xtI>PGaFKf1eCTHWqE=IK`nlYW}+$^+%gxP(qzXi9_aQ)Sk zvoSX(31w0G4Dn^uD5Ljw7=*wyOVNUZg+8w!m}2i?I4BN~u5OZqwCqG@m885KawNkR zK~cEGt%4HIk723g5Ywa4I7r6DepBRoj|r<#RQpCL|Lw|)2atEcjaFwV4|y<}MR8K& zYTHK<50a5cXKDj+P4@AXD^^*}(+uH?D(P`tgFVhk_>Z$T?ZUD9P!hz=RR!BpUu*Bh z?HrmPwGW!7@P_}Rmn>ImQQX$1Fk8$HZ-dC%yb%$AYhD|DFxO$NBCVe{C2t3eHOdUt zkz#BC(!)wj5z*xa(-@D}9^5P_&Ju)B=?own+HJGlCL9cPa*pC8VpQzZ@n{s)LlQQD zO*%gU#z}pO!En6F_K@X;aSSE=^zw=VaXaIKxZtB&`Utai-%Iz~KwL*TsuByVc_BuRlRu|Kj@}*H8D$r+d`37z`ZF`-tiA zwu^^vkmJL-TF)QPU%a9=F7E=eo`9V@ZV**aHS!XwoYCxJzg|IMK|atyaY#qgb0|sE z_3A)1N-QsHXM;=5hrPfX1Y^R_HKa`Qi!&3O&*TVQcxMRy5&4Q#q@q!|o(1=5?MN*j zT!rA|PFL^TX^96JiU3RuJv61)h_F)J$C2t4+%=-D`rFa5yS9_`S^|@gM&aU_T5OXy zO$nFeZ}clloENx}raGYLD?0RI;zPs<4@ zpEUQY{7@97OSyU&MI`Qb5X-<1Nad@p<9Gm1hL7jM`~X&aoKV-YAVoI@fu9>)QQh5T zDEC;40Sia1ivl77?)ILqRGwYKAcJ!ST61M;EIm>T0hvZW#4#dZcYD=2mF3z-_!AJYhW91W+h3OBTA4x%UzlJsyiSEGX6W`(+L zK_H|}W3)#@)Qtyw^JoNd8se`+uNWVVP)6SqvF%6}y+Pc;4FT~b-EI;DQLPSXN~Rm- zany#4VKkjSXFK0z*KOY^ z)_I{}H^NTBdiC)60GiJ5WjwP8~nNG5r z6rv3!NkQWkV|4m~gggq`4iTk>-7VxFQv5~0LM8S;#0XlA!y}1d@O5HXTo=Q4o5&T`B0-WOwKuazFA}m~gj(EEsNQ2UV^~NrFN{Eo4Mp*%T0t zWQ>LvaB-nA_!iv#~^DIIrQH7?Mp~a>MkstDA)Pc)_sRZeqC2D6i>e)Q-w( zN&Lo~7HVT|p|@s8k8{V=firMc6{ZAk>|&1?N9n#lp3LA9m&s`3J?-H>Ar6c-!a6=sqm_)#p z+3sS<0Ion$zqh>*o={W{B-*ZsnUXhCDp!b zU@Md322-Y0?0LT^O3$Rc=~Q%yBFO%U4%H?$nRl$Awwy@ESe|QuP1(`Qb9#(Pr8yg% zepEO^LX8yYB;io9v|u>4aw?XLCne6ca`Y8+{aSWENwvDh91YhJR3`=37l)DG#AY$) z^lrn+465(C8O|6*B(9x$IGe4X9z#@~JmiNwlztO!gfC>pkZD4&Myn+5K)gd)#j-wf zgJ-8j8~#i~q|XpY9t@lfC<`X9t{*=C4*BWro9_nW$@AT32xJhBH^gannWxoVAZlmn z7Q*h$>-U54^x@O5&-Y&-U*=`Cdb%r!VcfJP=oZNjsA&i10SDoT$jxDQXCOFVZjd4D#>Zv`8xev z^`>iSS1*hk}jtyOdt30K|pPmFP* zro%EDluDgKPY9RMaDXUs2>VS&6DS=ansSsEfFKEXVO@x=xhS$jiG7Q~0JW8?Ixnh2 zQPPurhZZvgV|V~wizeyF&OlAe9Qns?6b`*$;K#!t9(qwi0>?N5@=){8Fq0L)9m%iO z_RQ3(D@ycqsS7cq6Fg=mdgH$%7vYL)Zo(L6f{4=L2aO95c2iQfo6K&guGm8zl% zRZZkZ4p*u`a~6CKY{@=ZwZmeDpi>jS94=IzZSkE411QE@@IbpyjW5K!o6H?J1R&J+ z>2krKPDd0E((M`!xX3b0-#p(=pHDz*os$NsykF#@Ifw9lcdI1?qtWbaa(20V`nFxq zuV1|%42P?yN6`s|NQYidlPNrZyL^JX{pRh5Jl)OjzlA|`{pLfq+pXr0Bd8EBZnleO zAC-L1MGB8+BN_xKS_bF5b_J9nz^*-{KoOkDnkS<%;Z+W^%WGIT3ij)CaoL^Y9y%KP zqC+owdcx)b9|z%byPT6Ic;7xG!5fD(T|9h69ZphPh1~*IjVIlSNwk0w>f8}vbF@>z zNDt{6#`*|tc!oaw|6mvo$Ai%rZ=~$NL;|Q2VQxsE{poURG_jSMyOFVqK7b_4DIrP= z^B{aLL?hU>6XCk?Ns>FAZfF=Owqxq@xk@meaSOXW!6`lhF6iXgZe=*_9)*UyutxZkYbuZuJker%9YfpdpjaaEIW5<;o& zKK%wC{rba?Uw-@P_rL$IcR&93*MIrj=U@K;N2k<*#b^Qr*x1*PFW&z!fBg3F^<$cD zZ{Pp0y8k+VyqlmPS>PxiIeqE|!*Pw4NGk+-r~71xCVpiFTibd(on@rIadveJkrdAS z5sHp=eevdO)Lh>{Bm|7ZMz(xtiKaOK^u*`(_IFGPlV`?2UCD6lcT^FU}BTMB* z$XestRUyre3}@%f*=XgmZnece z6XOn<3T9~%bO;Kt78%8yHaKndcvCb&Du|FtRp58!@SUyh8Y}1;mOP}E2@24ZRS-dj zTVunYyjtL7g_yHsqRHS$w=S15;;g1<%bm(4{lO43;sJR{AeI1fACx1|l~}h}rM!O` zDQb!y@gdEU@x<`v;pWougnrm!9uFW4rBL#cI!e_=a^pRxf_149_i;2V>sR=`m^?B* z9?w>f_ptZfy!mdue4gKbon75d&o9@D$MTQ|aWtBo!OJ(RIVK-PzIuANeDNChoBMB& zCSSdNHyBNJ>t&9d2$U<6p4K9a)Mbb&JON3U9jc;)H>7#J3l|F~Z~9+a~1U1bs9{%(~J$9XHqWj>Hy|yd>iLdVo1HSYv#%_LSk}yIAkRv zjnJoqu!Q8oOh9)6RMH=DN(nD11>6MTmALtIfTC+6`U%oax7mg`52z#DxTQ7(Cz;X- zb6KVJjPo3{BXiI@QUt~K6+QnTss7K4>LN({>0dRvB0LgdI2qnF($*Sc@{QI^zNkQi;Z>m?+lICUwC z@!2_&>>T2Apr*U5x@bfy=grh3u9=~?O$*I9jodKlV9rss&^j*H={MY}1qrQFn zouf3}c`E^@GY=mWqEQ)wMo2{+TYRuceLt)u&aaz@d^BX^UB!VMY{CK^PR~Z?=ezA{ ze*XobPi}{{7;5hcte%qlMKS9fPX&oAW{{^V$CiR(h4d9{?)R1~0JRk~cF^n*H^W`G zw=dBweld0von;NNVun43nJhbvnsB>xHCc15o0J(XX^XVQ9EBd08S!zx!Ij{HwK;Mf ziMS4ige?=2sukSsjO>PL1;XXhAVp1MR38U^aOFLuvA5c#xUT>_mM<}K&<6a)Tx9@6 z<{~71K^a+r7K*DvnD1$zL?iny0MSe-9ipj$ZGd z&wbi=pa~9cEfHpeGMzT!zyu{X0i57it}im;J`7eHrV3}O%yZOpNXC$aLg++sOHz+z zWD1LlEyQZ85T_V8%4Bdb8Wo2w&58G$V8tSghy>rIc zmsTq7VuW&(LaI31?jSYBjnIl5G+gm~oYavWAFQ=xG&a=QI=r}!{6^aYRdELvC|A-R zuj`&{XXnM*Y25}%)_RGVtu~vI+jN1OY}b()ar<_0n;hB9(|A9T+TpxmZgHuwV17N? z30Tu4F&4K=wK}R_z>OuSJAygE5Vi(?tK?o{v4#93O3owXAj4TcV&f)jOelRK#gFAHk4Yl z8pqpmdQN)81Sce=F_&yt1d*JSv??l$JT7u+Ss{610f+!zdiDHRkn@FD({R=X$q>HL=U;zHCgbb3?>CG2{m0)fZr`3= z-mFlIITPpKp4+-`z7N?BPBzj@(rq$13zGz8ptoC6{HRphz3(n%{TQ4M?PejH1-r=A zi?{I4$FF}Z9ud)D^eC{ufZ`)ATx(9s?zM8sII##iuee4}Qb6)Zbb>ieMr;MFQ|>F) zm9Cp4Mb6(?+h5F_hchz{ILZb|8E{AlFjuW)dw&liYmymo4&9|=b(+6tw9v0{F>veB(gE;_c|y1y1>hAcz#J(#uKhy+BsN;_!Q z02QmqAoM{rN5Tw4P}>*9RmY`W=r!||we*N>c98j)B{S^w*wXcP>G)}vv_CH#I;Y}H z-z~H;*1k*TG`%V??Zi-Ej}Q=6k_p-&gL8}sSsb>=p&k5yx?Dx!`H|Q}Aq2p!0abHJ z_N-#$K?;0690P<6s951|$QvzyX=;?<1LDcEE5SXM;@3*Uh;AH|(3`uJ; z#BTWf={|~LBCTzF-ycoS;GMCd>^Qe?zb_Am`TbW2-{-flw#(=B@_BZ7JDQzuBx>T! zP;9_z9Twqw@eH3nnVyf&F5@JL(1i$DPT6ipLQ4Y)I&90c_1$GBI^ZgKtI>Z4wmPUV zvi)YeT%ey}GSoFL91mPq*gVjjkU>T~;@yh-&PmZxZeYjotir;^RG{4oX#nV~M_SO@ z-d%%&Q8%D^X1ohXv)K@x)w*mC@TN&1kk>{cY{)Q3 zayqg;G6)hGgaeX%6T}5q53s}p&HwI(5I4H&Y+xk#^OFY zUT5#PB}2@PI(&W6-Mk%Zqf1rmadfxt8awLxRd9Wwz=Y6AX6X)8!KPw{cu&anoZ*BE zpJ%dcweX%g4{Z zUA_JeBHH7(kHh`;_T3LpUq9V_{N?J^+YliZ)p2PH>F4y~CLSb+?JG-}|1x(tnGS|S zq}XuId-YOJ!Yw;sK!&&iolH2bus5IsZ&evkLbUe54i!TY68M@miHz|2^p?;1J3qvt z#r+k}w(qp59L{mGsaBj0Gu?A6DR-wfqt?azp(YQss-AlIT?IwX3|Im z(U~#c;EK7b^6kx08c7?It(t4zw$h1|EngQKe_0BbKV>$5Tmg2);dq1@r3{K1uhPI? zMn>0dr*4gLWCM~A5;XF=)Kc!9ni4ozt%{mVpc&;UMu)W~5{dLSY48n4MsKc}O$zrC z*#eOI@!ZwQ6HK-+l)8>KA!+MMFlIBCd$DW$7(k?@iA)lQDXGSe5o{LftreqdG~2+PAo4_f|MsTH`)l*Af4Xj-A9jQlgTo$8&*7F!w`(8s z?qI(Ac7A=EqnL>c!Pg;{^LnvJH>)>4{QKu${ti{z*~RVR=^G^QmoMKw-F=2cesXr9 zuwqr5jH|l({PTa_yn6roFaP%Cx1aLg|9SiF!+yPj92t`9;dp9qehj5lJa0TZBegqI zbqKpbgjzw5WLvO}{TZFTuP}4E#660-LLY0v;%aU!1jG=NQqnWH&&<2{PtSb&Fql;M zq)o6T5aD)3ZucnZaeKBJJ3(e{hX{a{Rnxr)W@N`Enu67KH7_GY^G{QZjfUAr{tU8N zEY$>>c_3cTS~)A@()G|hRLG++g<9~WK)7E2HL+P$Yxf91z#Q8=faxiE$H}sk>$nM) zRVRQqu5+H4<0|Nx%A}Fa4^ zrj!|Vj7f7-gg}&(Q{IlTzSEOEVX+6_0%Fs8{v4wqP6DwQ37mKjc;z8;g9u_}gl}F` zl;>SQTHb>#uU1VT-L}Yh_ds(|F&rTMKmXo)j;lafeJ>q|b``A7s^$~nngMy8+Um`1*kq z?9A*DXvI2>_2AZ2fvZ`$oP#k(gN2!G1)_nov>=p7reyJn$YZG1v&I?~3k6EJ4WS0@ zyQwe=G%#fvzAZbo@^>z?NxF%N#*Oh3lUhCUP1U=KHV7r)%KTYJde<>LLGk;z z3N^uO0eFQCXUt5_Rpw|oiOM$>;h!CM0=g*4J%hV$YGxNjnX#VsZ@1l~Nk*!mik=-|flpQd9ervH1X;RYJv~5;eDUH9y7R3T*Kgj}MY&o$&d#sl zn6hk#imlTbx`dFW$n5HN`FIcc>h0U_ck4Oi#g{MMVDA_q6Bwc3P*EU%z1VLy5XvuZ zUkyg%=lidRbbIsmJ6=|cXY45>MFLS1XGb*U6X0u+$D@9yo|p9F7J9uz`%jV6HS?r} z<9Wp)&$GSA?gq)w46R%MwpU!Ar#AaXKZ20XVn}y z%Ku#XCT>Hr5&q4J)zSP+Gd54m74UT*MmKFlf}!@9nmLBut9mADu_c&z&^3z^ zLrtmK?oAXd;|9dzxTLl4Wz89EDPtZtWn0qk9UWn288fvpH^%BP?^oIJsaqZQ6liBp*Du`l&sh0g&HtQPX zu+tkQ&K^8(yIwqh`*ii{E&T4=??0d2zDyDfosbs~k}+~dYT=aXrJHqC6qhgGte4ME z-#)(j%fE$D^!VlDXf})DVNnzw>T-AvT8`9%(GUVIq{DE#zWw2EMV^2C{pa!d<<*Nf zkaQnVZ#MX|BjhbGIz-`Yzk{7%w_a!aEed{;jtrE8h!+VZ(i#M zBx5U@j&z*4E|BgXMeABn>)Lq%OL7$VMsa61PZnQ!ji$h_VLzpTPifh-* z<+u$fHs@=MSrUs)sVZuE3em3J3gC*+p}TwHEt*uiz0A0C9MN>dZ90S6o!)}jw&1%~ zX=J^V)4be9g=wa;c_VQp@~YBE8SD*C3X{)a%uI*1fREec|AOqyJW|}{;Ay7|Bf~Ff?Aa-9R#X z_3~}H+dw)zy}Ut7^Y!xf-S?2dlEw{Ar9?8m->eHnn51zs9FJ#n6br6yzxyjBzw7yY ze0G6JF=J!I5j(r}3f^-xokh`Le*YCt=*{cz_Ukp|+LPJE?{Q&p2EwE66C*Jx1hwzt0aT3YH=Q6SMS<`kk>s_5)>QT^FvpC$gcd(qf}E zEPKy#y4jTAOk;?d(E~BN$=x3Jwvtj;_U(t_kU?;qo?WH;O}bsZ`tY|5F%`=oMAkBz zPcNV0!>4DLi>LeHXfha%pYFamRsG__kNeFM-Unsu{gB{me79br7hbxDs6CvXFYdqQ zhyCsQzf^g?UOa};0NxyuQziPtdv*@%al)3N8A3c7!yYi4p3Saq;1fxe3AIV<5(DjF zw@tSjypW`Q5d@)!R#FEzq~+5c1iry&LW)|1#z3KbpSX)2xE-qEY{lJHH4y!aCjy+h|a+H4z6Lg_g}IIQm3eyGdA(SlQ53^7zWnlEH*Y_{J-D3TpIzKMKi+-$ z?H_M{{0~G@L+IgB8-BIehEXyaPap)peEa?7?dylHACb!Z!@qy~A@HtfgCo%t5)rQW)!k=?PS07-eehwk+Tb6QCn3Z^NEo2Bg<%uq6gC zg0?U&+hNSivAMzHFoDAQL2ejqi!`}zu{N5fkVZ-KqXLV!w-zmA-1_;Xlb3U(V%*k} zKT448E2=o6G$&AZ4_9;CzOc=YHU$e=0bvf_bMbh$+dvK&`$%&L(B3ofD;(0mLQO~G zSv(w~F%mlgQ99uxY4i;cC0>^Brv5G-3fy{`Swymv12#S0FCV{s@}ua*`@bCik=6dZ-7FG@qcV3MQp!)m(-(r zEIjgOF_dsS9U6PJH)TcWxr516pwQ4PcC$YC{$MzAT~^mtlYv~?s{L|>y7j2O=0jZ0 z^8*6R{QzweeJc<%-_Lj3<>Or?Mp&+^yWXM)ik(fwD7vGw3sMsF%ERIQ%O5X4`~bQ6 z{M)DVo0kwZHuJ}e>z9yTLcSOc5+)(iRT#&YFW%jK`URzeqxj3O|9JKNkKA?V_g_(a z*AMmm%1OIs71XIt4wH0xZHj5I+0vPqrJ-)Z?~)Ye!I%j4AOs3X_Al#A=Vil zykUf;3H+l(b=&IL`oxjG>8|iIOLyzda_)ygnPmp1EHi%Rs8TK{SJKh8DtQaY*;@H6S%^C@O*lyWT)5Hb{o(=o2SC z83j4$M4n?OB@9iIG89CuIpp>5k9aVG?3Fmv5V8(Xl|xv>9te7Tpu8_h;%>^SgpFtU z^f0@634wkwe;m)wA<*x4+v)jbmZccAr)Ms5d@=gKVVqsvZdP+rs`D354`-LxuzR6w zWs26K@Nziv?dl1>z~$}h-Fk6Icb7M>ciR@!2IrUOzxQFQnLTU|G70kxG-J86X}rHXGp-C8IG)`P6kZ98NE;V9$$2 z;{J$=5<*fDm3Of5HGeQ zA##s`4k!6|k1nxKDz;?(=SbAVZEaCGbiT>{6<~C2h^V!Y2Da8PtDUxNqcSIEb+;^v z(mmo*g2z##s4jw^Ziez>7OyKnX{z^asH1Cun}Jy4GDaKy-QLB;x<^3F=m{_@r|v_s z2*DL*iaa!sUMBIsu8O#FiMmFTtOK!Y10E#d!Dw!96~T`X9Y)9B0#0;=Vq?o`;_orB z?*t;9*&7+N@fFAY8*U$sZU#BB!h|mlX^rcium$QBs3m=aYW4htt{lk_mDj^ydVY<| zbub_oJBBl$`~V9H!Wk?eLh`y@!~H&Z9P13zB1`fD4-M;F7uGo>$;c;`#5V?69;5}M z$#lP3<%djUxagh-xi6$|Il4p#VIyim3I<$|Rnq9p>1HGz*1A}Ws=B1Nt4_nO2^*u#$RNBzfZNdM4C2#z`2;B;WNq+)kPkuOI~h@z0IraM$dA5PAE-&;Q2 zLx6+hg`66qc03qjv_+8FIiV(=;Om@UzgRxq!5sw=7D6^W5+?}+M?CmL28SmC@n*FU z!xh*SE?>NcFSS}cVc(-H;D_OO3h6VPr14Z_#C>cYqr67Yfm=a=QWY+#szXqQH$el| zEX^SsEpj-L{IG|wkB&{#Y1M>yDO01I?VWy@c^CbM@R1&cTM`~1F-*LC9I> zg)(VYe$y2?AC?7bos%gl?CSY}I{zL9;wx@XZgBr1h`bsWZy;7zp{z_nngPOGiZplA((n#R&G8Kz~MS<4}424H7x z-2zngrN%uNVm)3{si#K&s_5B1R)ts7&?S`)J3=hN=rlBB4(+YPm;uS)8idz0vzhKk zGsig{VcR{KRy(4nJJA9tn^FCQlUg?=m9=2ST=9L-k<4XoSMcp4zc%|I#I7<&n})K? zQQ>Bg7~B+GO&%)pU@lCyNqu;X)^*24pXYgrie(wqwopXlpbsa37}?#rwnRuEs0mvT zh%8||Ac?pF{qbB#U3ZY^A%_qLbO9<+ptbY>QfA^Y_}b&LB==H8`cBWD?!Q9Fi<9AM z@eBzv#6;L^2FVyw)X{VX*(?;-5F&=t+3NXWe0~Y16MndU^$v~)tv4>O;kGHuDnZ3d zc=8g;@Y(eXWXj!rh0nTt`F8Q}6(S0J)^@cJqH(e{v3!Ov`0B%7ck2aI8#iyitH`b6 z;`TLU1IzgXx^Dy#d^E4?lgwVzaTR+Du!ThN(2o$52ET;Jh`@*J0DI{n&ETjY@WHnx z)2S9ynK>s`veQfSaDBhZ3)rP#D?)NJ23c}yu1b|z*TO`iAXz@_T-Ahchp&df4D5Os z`dRo0jR!sP<-8GQ#Jr{WE@EZp0oE!-WlC9CJVCgLvu&~+C@Ie+@Tj-A{{q<@6z1r4B&}(b zAQbE<$*_PdFVA5^fQysw_vl0!h5}s|L{U-XkOeaoev2Ux)66GO^k0@8|6rg70p%;vAKvATFa3XST;m-wVP)4CyUoyN7JQSvvxF}-o}Iyo+HKYl_hCD^ ze*67q{s~#j3=qX!X=G457TExbcTrDYg0mR? ziV0Sb=aYgRw4B!TX9T%=Ie1&*4#*EkuTeX2gV-|>_rI}^eIv6~T+WMk)v(l#C zY0U+)4!Y&8Z{P?GY*60qnh28o#*G84bn z*=aC{xD8v{;-j%9z_H_YwgfaVJ;7_{a<-^2<-%^GMr;i;1;xcNNhI7LCo-d>B6lT? zYcSfkt^#p)+`alMnen#`xMqDwcizuB`V&23#!R*NCL?y708%8^?V(BcQBh_801}!* zx<@xqh{bskK(Qa7k^m|UDSDUAY$8TRC72R#uMRtgXL-ONLg<=i20f*ZOk#6cwrGUyZT zO1!F2!Z?ilKw>8#Xu<)*Yo}+I>($)%F>PKv-CezSol-+%IG#X$3a^E{6???{U2#Z} zq=1@?;eNBcxP67ucJch;`yU}?!=aq(jizUi#_v|oZ_CtPv4|%?P{T`k`Prfkpi2G=P?LALb z{iX0FLR2p)d7?dYJn-;H_|fLxIYDLpa;aviSHo5Xn{`FvaIUsWqo#xa(s*GQz||UI z^9n8&gxbMyJQ`2YWN$hfP0rvpfYUgXKg=L!hbKUF0?)*ZxNc%-K8$ZylX0A%>c+=rf4%3cI zdMve}CWoyZ<@Uy{vRV=1*og|fVLCTm0Ny2aqea>jy-mk2apqN9*lXl`Y)2~B5Pdf_ z8^qtjPeL1d=mv+0_Y-Ltt5f8CpdU3U!KSF$T=)lfzUapsO z2<5cd;4F)}4Vxm*E?>Td&4zZ;8ovAa^-IWwv+er!yC2~33g>=ja6UGR1w^73@BRXj z6q4>2Z~szPIczE@`hI;2fu5`|U5Kr4Fx%CfuwlV^{xm+jIJ>-tSPWVD&71eI)xqbI z-8JOeXS}M91ylPQ1$F|<8muV7SVxoT0J8G&4C;@;Xp)Sk5RNg(4ku_M8%4BJQc*>8d128cY%pmTDdn)v=@Bw< z4H~h6H*nMJxy62EJ=H~%q#d<}%`n*7rW8Jv=_w<(oSU5nDPif09laN8wY?cLGC{Xt zDTsPf^9P$n?^(nL*4Sh)OLpUwl0jQEK?$dcHbB#$Z!|6Cdy+G>&6REp>r@UagQsgK zH#myc?68*Q22)VD7P!JOG$FXQnrF;TZ(A~$$Fn=LcWksNSbxi)FJ3!c`udKM6g4S5 z{fvRwJ?#YI^qEc5T$^WT#)D&TcuQ>5<|#y_BF)OO#BrPFR#=BRQ1(L6Z;C(AV6EPv zyS4+%55gJ5O$c^j977xxat&~OR?jFGS(7ca*z90^&MvMYXmY8)CvJNzz`ekSjRB%0 ztYk#!5*Z949sDVf1C~MF>w7)~1$h(8wzOXsIpmyjZgz%77;vrsrFlp}{kg zF~rs|&vvW%GsO0*mv10bM!n6vgga?=b-Q?eK$+00F3SQT7QP2r{C2fWMia>E7f<(j zmcIDzuVt3aAHTslnO)q#HUsaiP!pIDPtUK*`~V>sb_IBo)zkeUOCg(vkhELRAti@H z5yFpF#TVB9zdlF`g#{VgzcK zTE+w~E;Telp^0llGF$Q549DdT`kbb9)E32q+5c=OF}3cQGR=rkT{D&CnV!3KcN)YM z<+>3dKlZHS9nxUDlW=fMpmgo#k;-CSBUCaIwqW*)`BC-FPeDJ-?yrdB(n+M*>KX&V zCaL4hBsVk?5>lDiF$Tcx!{EC4t;3bg$Fa-+JACRo_B30ExiRlBy2CB;c-EoEY%Z); zkdGOzI%*M4m__9WB;^0Gs^JM4C6S2yWy9mm7n zdIewV?BY7zZUvtkXZtiV+AJ6F;O)B)kfnNohhw)ayM6mzx>=_w+Q$hkS9mI%sHbnA zVB>+n4LL7zG`|1a=E+_yjDHpwmBth5q~v@jv317szPTiSw;y#=8fXc(YF>wvD@7gHA9LqrDLt^ zv7!H&Us>kj!WfB}skqP}Hnr!uWAurcYP>VnSW0MohjdU?Ww4}t*f!6#*;3|5*?xy% zX;;4duMO+iNuYYKTf8}ll`b7b=y2U0m5E~$2X?$NArQkdgIp5htgz3fPDNE>wM#k= z4#d{Mc%lTu#QPuzDDVS_#R%^uy%>C{p@Z*DJ`u*Z+^UH-WotEc?gTz4qGk_{`69CSxdb z5z;Kx+d#=s6mJ@+NTh@ip+Tk!Ns=K+r5Dkll1eH?DurY`#~Ge!&+}UM|GMsZP5bD5 zfB*eCAI^E6J*>Ufy07~hzC*oQC{`+yv#>+JXBCk6o9Hx_5qCvMyHOvTnu9%KY10O{ zN2gY80U0{VM_3fHMlSl(MB_f}J9iq@>D60y+pR`*X>4jXnM_re5m4a{`bcHas0lK1 zpg=~jV@Bd4{A~y3)9NJCaHzxn0F_0DE}Y3^GR>@yym%0%4;_S^awq8@GseO1h@tXh z^YHIikFxl%PE*Esr^)u=7Bo!4Z$=kiQ4%6@HMKZx<@o7OX8gMHmL!r$N`v@R8q9rV z!A&XEh+jhVK}yUr`wdr!CrT=x6f< zc&pObq?69{d#(E7LJBnq4i2JF9*1Ha;x9y7Cz(Rl zb+bObatjEw&FUf?$@uIVID^ApHwE#2Yyx(kc73VcXqLvtVSj=>X64q~_d5vnt<0{3 z(*@xk&XPb)@Yanj^*(T;$roPKM3#gk$J$%Z%95ZBt_A<({vK6pRCb zy^Y9)<mO%f9|Aw`IZBqUQ6j5VN&M%cg#)KvKT;FpXL18g!tLY$A^0W7X^_6!f3l*9b&9$ zLZJ^ib&wp+pP6uatp-FfEzPPoIhH8#OvppPauEWVbiu<8$)JziT>M-qp=qN)`_iWM ztwya~tF{}RzXf{5=edA)a?zjk?F=Ay8EkB2lYW9-oGCq1Wr6ssj_j z;mg#+K6SI#Z9(KMPtEq3`)zr08r!DBVLF#%h8MjQDnGDSvAGpL8$2S18>!Le8VFoW z@O_9YTha)It$1NFnSnF5xPG0B4$V2ZSXpG~rr};qDX0u3liTfT`NSuE-Qg$)S{jgQ zBsyR9F*#7^EkbA|xNbR-BGCNx{O8)I*y!fuB7)Lb@iyI1q#RSq0P}FK zQCi3sAwhf|&H8X98~BTd7%etWQ@0_Ln?NYBq05E4TdP%r|0f;DGU0%p4`Utv0-QaeTrX3}vIksaF>pOY;^X z0r4W~ZOw*Dw!qR+Wltu=IdExu(sGyCrs2(xWDs|NO=DZAKS2QI3MgU<;CcM6;czhs zsR>4+5q6HgDv(eid4pDO_+;cFI}F(&R6S9Ll7aP%!35!`ZREw3#u7pln2xAs;5jZT zOSFc=9=sZ5g7Y~pQyFMwz|PukG?wSrr!zTSL$dQhSRD8IgI2RPJ~@*q6xogv+tGqR zTw7XzQUER%ZX`oS8=)xZ!2rWb6UvaKXH-C_RG8F}m(J(%g|cjLN%b{PkBJ1h+=@^{ zQ^bv+c(Jb0sV9Pnyz)|IN6agLrf(`H-pS@Tin8mj{C( zq|c1%N(>=BvA<+;g+du?d7`2x#z%+rx^w^`6>dv>e+U!#VkuuJDXjr>k}9plDf5yb zg1kqyvbNamJkg)yWrR9%>UlnC4^?$oh>g>0P$Vj@0*@*eG?#NO2p=a?m)lrSOC?mq zNM+#3wsN{c(_Yp@NhBFBhQ`w?IgQY6EG|HriT+H<6m~{h5NmBny;GSiHW^d`h&zD` zVK|e^k4?_ZuV3p9`}`y`3#cR{$mJ~vvZ_b3@K zt?DF6o3G`G51d{H$tDh;ZroyRy~0hH<<4Y*e$-oM*!A;>J9PGt&q!LB4`pf*Rlpv6rba;q|8e%JLnt>sPYnWkEX zi(Me^*~T)c*KMO1kmU7YqM9HA;!li*j8?!F_o^LH;74vk)IZv=X{;@=6@zUscT3fF zC+fcNg(pjheTM`m#R?A<7D3J%=_@n&m* zP&iw|KJq@Y`J#vLGRjfC5cMJZwo^$&2U0JS&$nB3xHQRhN=o$y&lLl}&_N%0m>)2C@qN%a`4420ZVof zJH^<~HcRhZ<*4LW6dT>232#4PXJsp%b795c8R%%0kIl?>qlNaxE;oR!saYSNSqb56 zapPKucjfV^R3ah5q?VKmQ{N{moLQB<$f zW_=qP8TzFk0bzbj-F&gaf{o@yurY5JC4p=n8L-VV?AK84F5wKUzQfE=5CzDzs4bMi z#OvjZuF*y|iwU>W;=Of0{YjRJR6AJW?3HjPw!c#>1jnc(iFit(-19F(F&vjd7_uNz zmP;zA3pwF1?%1Sg`(g>@tu;^I2Ojl-`r`VOhT4(}<$Yn@UT4owNC`P5S4SmU)iW)Zv^$Nl!?PXC({Cmm@QnPKh;gk6 zULiVp@x|gW>0@LDY{p{CZ}&*U+;_8Q!S{b^P~XXjn|Va!B~c+@ggT5brWDF!oo1uc zZWU8wn%}{cclzy4rcg?z)6&q0usjcHWE2UTn3~(T?rCuiiEfheliKfgAkbv;1z0fL zIwX-ojKpv-5WJ0~12H9miVNv>vzpE4d);2rNiuH^TtMz%$beD_iyMy;JElbwY0hND zIG;uWb>l#RG)C^-ijV0u20;^y$fzHUMD29H-(B3W;JR);UrKS74fa|R6hUcvxWPID zPH}8W{w*eC{SV_DS2+UiUZJ8Dx1t?k;xLxwc|F@RV0g-E3Rzi^ZOA& zihWf4aS{%;aaeZW$?*3WEc-!xRhye2Arrnml~SFvCTE*yOBkPNs%BbjaZ8Sc0nunj9akf}WXLAt5376n9k%YuT4JMy9gk7^TIma~HBJTv&mvG%yZ7EkMBvY9|ucIjqT>71jC9R~>ZZsfkhKQ0# zrV}WhIpjEHhAly#f&Q?cro2rodc@SP$L+f{DGLV1XjkXzaORV6jZqXTVI`^Sli{TE1Wn_(8sWTaKg75)Md+<^ocqI|bwF+OpzGT{z~ z?M5Bqdt+f94vczkI+KT>V3CZ!KQn4>8lwvx*KNl>wKs4HQ|o2W2vkqUxuQoy^As|Y ze-RsnWnQnlCDd}^>v#ICv5D!W`3;bYX0lm66syi}$`wlKLeU%a_*G!M7*wKw*j<{M zb26EAk3Yh=;~CDdNHQa5Br9SG;(D$d*GPfqEzhrqBPmbL4)Oh|kCJSotsRq{xB8tn zZk(vcj~r+;tiv?egFTWC`V2cknIUu%4%*pV6=o5itXIHqjH3&vz<7BwO1g6I^+YdE zCZaMB1wR#Elwj(MCd)waiz4b%8tgrV39Tw2_JpFmO34kMQ8vsLs5OtbR6PC{BrH;H z{@__$!yn-`?6-_IE>Tm#W~=0qTQq=aq_W0WFbtobvp8a{tYL9^9xgv*GwmT;(?YOR z@WdRC%7mX-uI`2KokeJc`G#Q8nWM^rjXa*oOZv9uK!4ZrQ^+aZ44^ow&m7Fehz3yv z-qNB*$sy4ydOS_|S;;$eMrn31|DkCIled?&V>L?+j?DB#cA>KMT z)}NS3<+2HkYXbwxK#a>o$`ezH^kI_()V~l%2E8uBgyAW4QW>bavxNey9s@=WRJIAt z3lx{Sj<81M#-`4~{Q6$I3H!>BO|IaH6LYIz50D_R5v36wt@*&fbELZIxooZkHN;SK z44|$b=F4N9cB|E_6~-phnG6CR7B`|vQKtn#8FP_D5>|1iUh8(-E)!+PO(T(X(y6iO z*;FQxMBK7AF~YYpKc-SM)~vFrk%61ul(?X{#^QyO1r zkDd-iIts@|b~ar@E&&mBl#itk3w79QBgl!le})kzjAGk0ixYkqLN+(PVs*FGkUfov zu^5_$WU}3M(?ULBKH<>B(B{PDR5}fJe4$bq^am+e?hTUF& z(1SEBo6pCXS>cBG4A6Yx#pXgjs#Mr{%H ziF7)fDdaGuS}gc=+Pz^P)*9?mOayHhr3)dbCH-y>;Si}b{Is?--&mS2k4@%_6}&nm z2ytVeX@|8tJa|d3-5{2OKV&^3Oo539D-JQs-T=;=+aFk{a!Q=gATDlXO=9*dJ!J^+ zSyXi9JprP%e&x3oI5?`KB2iND3J5?|nkME4w1!{D0JtZ%!+Qmdk zJS(|k)i1{IFH}usXG0G35QFA%jc`w-sFe8CicDvEt)ru8+f)j?dtB>55ts4mCb&?j zWsJdYuMTtkD5KzSH9Kkky9c9Utw6Uby0#|J_el)b%f2LeQ{ zJSMwadLo-hrrWipUZ*2;CycILyHTs5n3;MvgL5j&P$;YG)g>IFU>%J$4;rbVF{M3h zw+p3Gzu)aPTeMKLy@cluyUk`2O;N33uZNBv2{gy!;3s%FY$bkHF=Y~TX$W}`;~=w6 zIH-AoB5cE9DwXnlOC7g)q*3Gw%p;=>cQgD2LO)6;8%{;>DyOkT8=QBcwf08hB!=#A ze(h6JtF~0J7}X<_&e+Tx#8xOixE(W>u!FxYZ(851FBdBl>0I8DY%JJ0;WXq5g+aex zTY&VrH$J<{Z(XYI5QhnPHXF<1Q!7zGZhm98+bT~?mnsvkMz)1!(JVLh5Sr$|R)J~I z&`mN8OjbgB)({~s1C+S4`~8m7O~KJ6@)I*OYQ#x2&Ri-TP*b{wT`fqz@!tf52Ot9B&((m_LwJO)Qt0RyDBASaY@i@jdfmF0iV0j|+747J&*>ZVtJ;K5&enYp@f(y~>G~vwPc#YD0X$+3DUR{7=$BAgj zlN&ywRb57Jy>i9%yxROmc;l%Rt8&HiP*f_>4Re6h=?WIxsbw_! z2*<-wqJB>>m$F{1ESqa7?==EJ}nB8?(tZ z1T1tACz@RpJ$Mi^FEx=037oUuLf^%&>KB-itpk)B~!VVXl7-xq#&WEg-cf;V(X?9TiBFVfaS-PFcLR#0$}8kd9QBuV!BeZs^o z88HOim|R9&X14PbUdS@|1dc%-2Ih-_ZH=GQ$4_qp;&7x`Q5^WG9vGwCc8<95VI?GV78! z7li#g&wQ$2&%hZkr4Hvb6NBF>rE82SxHg^_`7s{?@#U#G5(eEDo12^tr&_!0BNApm zMRqbh8iCOzhJ~+okv<5R5F0Y6Okdu^1$p_ZW(5!ZGPcZ&4lafkhU1yk3BwNDQrv^mMSEw^3T@LZ=+ zD~?Y{7jOS1wuv`@y=sujAvz7t587ZSy?kjLvPOt`32wH4xB#eNa-Bw<*{~)hQbPD~ zz-bwqoPq7o9SpPi5(H3qnt<|0jgQSc8h2c3!BxhQT`HSQA)$`R5+!(Hq+Oo9fzZM5 z6rWL|{V6l4u$1x+k%m1g0LVlHiX~Yu1#e&b=so{xJpNidP=@m#tT1YimFzsYG$jv+6?1j8fOMy8f&SpS`{RyEhlqNoj5AU z7fGmZ!}V7vAsRtK)CNO*(T~buAqntBh+$~KdxJJlv~A6P;q{0Qjw7jzL_9Z|qa2#- zh3Iw)jX~opf4VuYu{lju%0^-`N=$Q+aKm@>Xo!vgs6{=&zv}G7ppE^99OGG0Gp-?| z6m#Tsp^$PtHsD1WMkqx$J^LiH`?by83kBXB2g+wimzawVmbZ=ia)Km^mGN%3HRyEV zi4Z$-41+8SYGOcyID(7+Tp}(6=|KHfHRU|ndozdBicbxVVZ$-icd3Ed zW>93M02{DMGm%Jws74e#-`2sOC}9UBpvj~d41akkuB(&-i81sd5ui`Qd)v}1392Wd z#Hf3HnhaC|qCCH|v@o|*Tn8du@1pvL0l8w!Z#fja1$lo)sIk{ z4M$07Bwl#LEHtitEc>CX&S=+b*=#<+$l}b)DsCU8*f6&3Mr{#lh;$~GWy}kY!FZXQ z#t^;}1oztFLZ{U#O-wTVPd6M-x&0lYL}(mMoW$@`DEHN7oqay3^%SZ#avZuYRA&pAPPgg}-gii%4sr%o0)#fMKM84Fx6_7I!{P4^O2RwL2~BLN!+|SQ zghCHgstkI0M0dSC=Jo`CGP&a7hINpSPtB~XGbg&*@&d%@$=OvTnS|%Uh5;KqN7-+D z_K9@1fQG8>=)U}B6(>TiJ;J_h5+a6$^7;JkrB*y)2fOo`0(K(m%k$k0EqGyNYBrtC zH>yjBvmQchMfD#iks6zx$>j2E_(o$)##tq43+t2M>C&h!FUn-VGVEnX4@Zd1h)qKw z)t%MW?%MQT73OGeXxr&@TIZYQ@)NGjq}OVpE*#q@;SKxkP7j4n&_V?V%B*ODN4M3a zScCK-w)P=F_Xn_LS!nvgiURg4I9eBjvIqa=dqJn!;5Ojw{$m3$18Qt&BI^A?K+t3Q zkA$dsn^+lQtVK)=g5t*+b+A9RBE)B5tt$f!CJ``2Ek8`O)VokCPdHa@^uGI#yu= zXyQZJMA)=4-2e;jMwSuNc<2m?8pp*+C5!+go4)Q=B8id@Tx}f|JY2qRrv-@ztJ5`s z+{{L8ELscwPP@l6*f?GlhdJ=KWU^3Va^p;QjZNWEL9tO?T;8~zn^`~zhBxZ+O1}F8EGAuqZqD~m`)P9877Nmo(gz>2z=G~4NIGz8=IUNn_bauH{mCfb1U18 z8pPskE)QR}iFQY%-$NiB`c$P;!~OtXnh<(i-umX z<}9`&^2JK0S%(9IQw;}?Qo$)KG>T&r`SKVXs~6$Y#Frx`wH9}~!T}@>P%)<*^f_J| zt~E9^h{b|gl8{JpW}F>ZNZ?oqK8EsqwWb8rLee&fl5yZ0h3zLT8~t1+J44_U;vB=H z4qT_f5IxT`84ATg!o?ob(Bm{W#Es(+fkA-TsF<+E3T(NM+{5?ukQjr+@FZel940@A z`f~Qru@gxvMW`!BTSU>*q$-XEZwO+EP9J@e?o>JG2DLFM&qZA#NhiEkuxLmdOhIi` zQ=e!wAe9>1401y}B{8A!ZPbj7oU6>nF_x_+e8OJOBbMqFSq4RqYIvY-St(gV`D2M6 z7j0r1ncz4Sa)(=n)_It3NbHy^m2d*!} z)YEOa?IDOmcFEAe*kbOrTaffZ`U|!HaDckwa7G{~ENoZ@f0%ec z?MtCfnVy@y3!3r+K5W|kkNGu*P2LF~pj7l&78cIE6vT*$%WV2Nj zmh>B;xj`K&g%c?eS_V9b`X~`Hi=(EH4zn?|!a~BPg9i07+3XNa6ZqGIZ7Pq=eu&5x zg+q7JX`K8*nUhC4Hp(EuF{Lt)2`896A_74=Z43EAnPdtZDRAx4c`K8FQ&}FL93li~ zKwXDP0(zpvmqaD5;I0H?w7i!hG8t4l4eAn{Y|l6DBj)=M?({(doDuE1K&U?#rqU%t zK-Vadz+Phcq$Y{B>NARKZ;kEBJ7=Z#O#F%3D0eKeiPB@#)8&sr12?}Q_P{kDmG)j6Y@T2mBLP9!C(z7m=N)S7S%0WiPSrXa>NW2&jjagkn1sJ=T zy&ms5blWXhsF02^gHYz$$#C+$ZU_DjWirH~?eIa*~-XK?LYF>yT;| z$`$VHkgtqGIA}NOl)Fh=*7)@7#ELagEK}+drhf*Bwu5WORt1EE+*|@bhuj5fN9yBP z#X)*yZ-~#A*u~%~^&GFqmqY{Y>^#T=CswY3Di#uU1S^R7A$cD2QoY-97I=Mmv5S7z z^Nr;NsDe>^+0!^i}qKx;Or4aFts=n12)M_HkHmoXo8>jAc`}lrGw{Tvo)DMc-|uxLEe&t zE6?a@Swx{4B&>=~s(h1v+?;ctsl^E&Bfl_4h7}*EJ88VAUE(Bw^ zHM7McEan7jB115S9I6LJ9xR_UijgDO14AU5R}O}KxY1dU74LJX1+&>47c;}9G91GD zwCc;u^4aG7U(97#vw|PQ08?+|Pis>m1fzPar;!rsl-%x1(MRPU=Ez4v#jWOY2ITtE z**pX|xJpUJTY;y*&cQf@i73i=?3fNIFc5_o7f|PsTA6GfHj?V%JluAfLP3op;Y;<} z?S8LQsEjie3lbyA5HY6}BTW(qPsEH4LMWVDIGAjql+EYa2FA%WF5|2!b2J52kUvF6 zhLwP`kjg+*hBxc98nEwT50-8g5GkI)d&E>ZSy0KUqq4$%ff|- z@=>r*@rhb}OrYCU!b!QPJT-_E)SSh63e|7&%6M~$8VW-`?5{s-H`~OPXP`ff5?;0H*+U*7y)Qh?IX2e~D z8?oIKal1*!^Mvd-pG&u@%TVjA+;Uq?b&*xUI5<)rg*p0o-A;oIvz^A$0;gZfq6mdk zkYdGeVwU|B#>O(aqG1t4N6=mvK*K@M9z6Q!ZJKPQ;qVd>Dot?+7IAmC+ij+dLr_4j z+s>E994FnZFXc*QNIK*E=i<{Q>Ivpmj?8ZR9X?!anrY+z&oo2J!YC?4aX)yNV z5NtM#xql+wgbEcfi}i@|P}4wW-K^INrE=UbFtG94y3MJjA>=w$m|LdCYe*mp!#Cyu zPD7)T_|-;@DU{h2l_6f^mIbj-aafg!ocIY5JPYw(6Q8H|M6GCLjDm<6tUVE@{0KB# zG~x}t2BJYmDzZpjWGT58iPs{=Sy84?zFjS>Xl`a%hQhlr+L2R@D{oPJE) z)B`={fvL~}2pY@fAuW`|dKyn_^hY$Q2|OI z9R9$}DX5HvmN_qyskrVrm=hxdOd!;QXoN<)@M>1k$V1*I@qALxs%K0MXCTU`tZGT|@UE9j)T+iOr)KF#J`nOaAx;3)c*Y{x3!a`rz$aZO9 zB*l)SyQ0w0MURYg>;ZbgYlk=Jncg1A$^(^v8vmKD&A=i|emj z%;;m~J;4m||O`Rj=800ye5tI)^ZE_#jPH z#n&eCle3nF6Zj<4L@1%!WR_@$Ia~snbV|6q#NEjndqK36kSPsJjTx2*Hrz-`4#2g! zyqH-LOKM?SN?lWzrNpOKWcmIZt;63PevcGvsgr$an6B8q(nUgHy6Qne{1H|lKu+Onw&+85PavUZM`fQ^4&qm&@ zUu^51w_ywCOP8!5%g!>l9V?F9F`9~K_JOJ8!=D%%vEF#Kh_z*^Qp4VqL zPQt|n-p^#SijWF%8AUHyhR&d`L#AiJoFb4ihX25yqagYKJ}6fj<8$?>07OTgu7I)I zsDNlElE^T02Z;2tY*qxM+Rb_cRn|&yEbT@et*jG?%ES~kRK4IUr!(1B1LtYwi5b^* zLyW-@1F-)jbmBwv6T$vB9CfuKyTw&9?C#&-tJFUhL zuOKSe340*fI2F)qAyp#HSQM^H=cu-6MDNLz$2MZ6rKJ+gc41gAocM#Xl9fVtGO92!vQy;}u}Gu{CY3VLQPa8T zGBT{%CQ~}4XB0vz`E)ReNym#8ny}(gYb0KMJJRnt&c%^LA>jf#aMp-S6XGI*D6;u> zt1)2FlXrd*bCfP*(^*IZyUdlHFVlXn2Q_uRSXQ6zF;O7~{2Iz}kDV_RheNmD?Ucr+ zh-E7`HtL7ZyC}h)N+M243j8>2sVk@9oN48hD)41X~HJ6kS~=hQ*-P}^~JExl3F|x1jPFU zMA^|(qj@1gtP;ZEV?>#u)103WgK!m?j}d7;MkStr>b#R0rVUiWM$H^c1}PnyWbaHK z0tpU%beg7wJq-;@?oek|kBqy*YIVYQk?|$by|McfSmkNbD{^!=OUU9{b zfBIt$V+y2t)Xsz<0=4N)=d8ak2R?N-JOiqlKibZS%cy6!TtJdoai%athOB)v!)^FJG#M93#E!X1b zT2@?D9@CX3JXNK`A$r9R2E7)lxg!8$=nhCfgBoBdh#h0oGyH9e;}dfn==Y{pt(jV}MW@{ybi20WaGakU8|q7m?C{D2gtO(1&!scD zbT%vd2{hh>Fs4IAEj~m|GMUhr#6MD*$ch2v_+QJ|d0Yt|_Sa^zikm30Ad#;wF0@|q4IK+8+H85yHHS$z9Xs3-9VZeStrxWo2mo^~3fDxbUHi}(EcH}IPS z-u&hdAM?RO4}Qm~pFVxV#*JYlmZca7MBo8^{cS@0*kSFs|Lp~c>+~_Fv4-SLE!9j9efZ-AX?}TSV#FQ}e6FS0J3S!VE ziGOPv^_L*0?yYZl-C+kEu+JVZA)DJj_@mqFz3y%Ad=4-7XiIr3zDXT~d_p8nW^~`rXa<-h=OpO6GGt`VXI#A#0`dZ#MllG#kLJnol*B(YPt5HtuPY`40c zKoYhGUt!SeqB>e4v9w`bdbv=njG@y9mhE^LQf@eSmSD%3m|NBFbs#UEU9&aUUynB% zh^0zm#BtFq1ACF~h_S6T(r$HBvzRAZL+ZgnN)i$?KVces8`eHGvvNyxo<`82Xh>x_%O_=P|G>Hc@T>+oOy=C}N#Z@=S?0}eXqsi&U4 z_Udn*^6`^>$6&^K{sB=+=hVk77Z_gQ?cte=*#LM@!QY8^)o7D z6pq0A3IkTpfN(4MTjKYci^z!0J};$K{A`5=Sk7_7E&XxCS2bCF)57PQi(BP#@ta?{ z=+e)f^Rhknc%D%h9+`A{dTJtSH=*&^3^IZY!taBGoyZqUc^u-STT;7O$9Y{kLp=0! zs7%fzQfb#4FqXf^-8=f-9_Q3qo~f0N3$2LC!Wk|A;5aEe0TF>ZNEJiaRuY}w3I0hs zs1m{C(=c#z$`u+jCwZ!bXl2V9bh;Sm1yVRt(anmP$np&XlhAZJldzp`3+=1n-6~VF z5Sk$UXDX3{;c&o=KI0Nkq+i4P%&gi9{=RALQ`p_cWAm(Npv`DhxD{{LGJ2vwqTI#< zKOx-6m5o4^`Z^cYL=wiJ*IV4UjzwXvYDh(GXP}9-#-j=BVt6^>(P{HgYW5tcR4B6p z$0=dF3XR4iuV*P)*+8B`BRh)3Z!SqfIN&J$sxJgkYJ^}F|AbjH!z!4gAupf+_Kvq5 zc;^qkH#akT#CzX+@t406*4I7zyz`Fx*a^Gtvdb;s{oa1B-OmU_5>aHP;Q>aY9k59D zWQU#@AP%B*!lAx5w^cKpkWiK5-|dJ$C{v$!Tip1A z$c9&R_84dq`#+pe)1-;SW6Oebwrn);1x1rZ z^z1=3U&c>E9tRc1zPwJw;0uA0L+;R{St^SvX*WV6yTGGC3xqfS;E)@&MF>WfiJ2^N zH^`vdq0DoWT5*W;AYK@vIcyu#tG05P@SBUg=ZstkbaVJwsYn9xD`C^10Op7gY{icO zqB2k@H{duE$ORvCd!h}^e&aGR4LG%M?OKhR7Iq_42*Zoq$EP76jFCJ=GZ4KC8B(a< zbk{R&)2K3sQ&TkoR3!XOG;h{`&6!J?n8u34XQn3;J)$RT;=TPYbYbKiRUBb)OoqX! zIl2>>o%e!mxBb@Fzjnl7hhB2o74QGZM-~?sc@Tf)%U^NuLGP%PN=k<0Uynb2_)$mR z{Jon`JpTC0zw+gYiOCQ&Lh|AQBN6Ixkc4Cv+eCE^i4q6a5yvRDgcj+DG*Iq8I)~-3 zKqfOHIT7;B3AI8yo26$4M1W&u|BwW`o&i5>N;eyUOw6Cs5;ABomgSd>)6O`S!5JZ@ zY1N4QH29NmU3Srm*%|A9^;o@P&OgTs|HWMVG{*8nT+xJ+wi6stYCBNOVltJ;7K-U? zmRYpn!J`a~pqY|kf6%Hf_gW3aMWLLH?=I(OW!USo6cU1V%0sm+6qrR-odL!Ih-gUm z!@e~B1^x?Z8X`BKwsQMO_Um;9@ErVk7d=4|j64wiWv!T`SbuT&bZ#%*s4foCcnNV` zYoB;DfqL%~EGF79AnxGC=A!#aYIe<5aKk+Jq zL54pn5LUMFxzztvW!5IFm!+nso^1>58|rU@6B>3dlZeP*mFoGx8oES{%+ZX&oFU+2 z*{b7Bs6Q>SRcrXPPn`UkSG@e^ci;1ci!N4PZrg6N)hA9oasT}=?X8}2%0-u6dc(JG zP$N5nP)B0(aI!~TNn(KEX>R5;s?oNaeY>}ysNkj|?f=G>NA8Ahi zA{b*0E`40u5+o(Ra-Y5T+-+CufBTr7nTna`#B7R8vz6Nsah{Z=1|^o&Zq!ijm3@&! zGMO(HS+zcl>d4?{p@f^~W{VXkrJR1K&*O$9@|7_NdCg9zI6lGH(rWxAb;UJ;iJEhJ zOB|)gnv+6fDwR$_{9xT%5)&>X!Gijku*1x(+G=Uj+Kua;<_j^E$xP0zvC}C!7>*>= z1UFP~*msiY65+o5Y38r0Kf)%GLuSloKB-&nwXNf39`Al zYn*V88RF5*uvM+WKAJ0*tMltSttK(}_;?TSpzK1h?m=ndXso_)fTA+T;U+Z3m`)l8 zTU1oI2Ik&BAu&o#1IkY|drs>!nr@UdV7(C0uOY^YC0dJIl)rI(IUgZ9ynKZo8?g*< z7yF8D+<(90-v9pjg@q%JId=W}4LncF=X1v&d(1KKd!KrPO1XT_nP(pQj)OjT!3Dp& z?>>dQIPJ_cU-ZHq&OGh(*SzvoU%L3>`~Gx)kf2OVCs0x9#SY<8Dik$&!y(`vYFWA@iI_f9O>bcWMwEvA=zQQsbGjM|%0B5j>I0w)cUfu$ z+rNSITX6Bs@+me|3G_mae)nP4|KTw%q%TL{l&P_;;Ckw|TFm_u1;!Nr71E=|@?x*k zW=`<9M2CZ}+wT{~#+V=u4Fj*?RG~0UB9Aw&JB-4CFhU0w#f;^Fi#wquu-PomHcWz* zmWwiThJfLagfOg;7&{~4TT#65xRIBn0Z=cU%g=4GUAqapPA`#4=L;3a0`F-*9_*Iz zHYlahR5achvt2aqOU`Y%O?7@lb!i@Uvhw6Kx*{QIWoW2FM1m;r=b3z|S)K1Rn|x>% zh0Gf&9iiI_8gZCX%8S*SPDG<=_z8*9fuI z8_mtkefEq~XQ!qvzv}8c@4Cy95-LX?e)vZ}bnL{$cz8|jwBt_S{?@g(-*LwmFT8N= zy0!en|M|!x?>h25M;v~{nWvxr=wtsn{WAzUjzk9#OXXD<7hQ zc#$b+r0AkvjiqAY6?^X$cgCPDzx&>MAAjPhjq{7$ZZDlqm5cd_@$u=Y$u+B1?)<_X z;5plEyG=|Q6=E@<#O(lOWmrnn>oilDT&{pJ=cskiYIxodYVCfvn79b zOrZ?B0vsV+5lBwu`6QclwKa~)7UK=%3A&IA!}mhqHc4!J_HhKRI0*w3sAe#@*(8%` zWI0MCKUG*MMqy=xG@|{RZ9UkhLMG7)Dq!gZl^SUt)wUFBRmq4z6+>7mxJ#R0+{=ki zIDq)N5X8VX>0&l^LSt0%22jn`m^_~c>L*S(?zOLc#c%HW{rivms0s3@P`OW|JhBtimYgb(UwJXuMmmT4^Z@lsQx7_lXGtRjAhUm1Xex_}m!(QFoq<4%4mDIrmA9(ZcC*e9uk0O@sdA~3DU{f4=0$>eVIk!TCD$GH zdTofRiA0Kvok2KeP&VdQk0BuC*+{*EFoHufMw~*Qh5_w$JNcr^L}*7il| z&~@9*M!(%em3kzq5cU@r{f7xnrn4v@*@h>yA(!N~q-avtYI==&v4SDh9S-9z1atg@ z7xf_QBCHK6j%u}0U1(Gn5e!!-WYSp&6?+|Z;N0|@p&D>!K+H0=+V#4N`gVDg^$>>I zBf3nK*~TVBkRvSC!HCeo`iSa_{@{ddYvf(Dl9hA)A<#L*T8O?FP1Fj zS!c8lm^F(66^P6+5OS$1YE-W_=u}~}j0sZ}QC^^em_ZbCOd69?Bcb+$9hA@chZ<;F z8i~S;E+=$$DeaH^5jXPY*sQ4geJ| z%+lU4Q5KYKa|%TXjcz!MhFwwB2MjcOSWRS0P=xv@Pj7CXgiJ`aJ5IDTn%y>y>4^pp zD=4UGCdj^_ZWwbEJ$1v*h|3VO=I$I16!X=RD_6`$9`&>9)_v&Xr&_ToHvaeNwd>Bm z_^Vmu6OV=u^BRT>hv>vO=;2IkdgbaQ&f;vwOm-m5<#42f_F(B;0lr5EeSPZa3128N z=LEXAeqE>C%tL-UKJG9i8DzN6t$nI8J~=+U0;03>X7+OyAdr`dAg zdoj5pNdF;*VmGGO>-YOmC%_lvx8A0;Pa%7-H0D}^7{Z7NYeNu7Dw9pm=3(z?HEQj8 zwK~6nxrd-blEeBzsLH?+Jvu~qFNA)Gn3+7p-vmnd_qvdVqtkXWsZG`yG}Q2=Mlo@e zoa^=(O&mh&kTT~acwq?z^_}|iJbX0T!r4LH8vbw@fv_|&o@M3$j{Y_Egr`u5;cxrq z)zUUdd0r}~Og|b`c7fS*Sv5^PA%sH}Jx_Asd`W~%y#oMeY6Y7g!6ogR{82-Lf=B_) zm}o)l>50mDXMTEaX6D*&f9LzR-p*qYtbr3h^5GA?@94nUd_IpAD^^^1!3BpLeDDPq zU;N-hf8n>$gAYCQ&ZGYO=p&E(?3thb=cA9EdgfXEL7&Q|1QncP$t)wp^5fl1=7nY^ z2gwt$b1|L;7xIObE9M%FdZW>5G+V+0`F?bdqpq}Dz6-8a9u1pk~I zAKP=cU3c8!1><95kZwG;e$$^Hdg#v&{XLW;i)B1kDn*{E`|f`r9`5El%N=YqS@Aq8 z{BJg!+jYkm?y%hpCd!3ODg{674ctc``R8B%@yPn6dau(Obh|D~j-*d6MkV4T_Sk)| zT&@6#P;Fs;ww$d@&prOsy1}4_-lD@netZIA`ttln$oqF5_2*MZ=iNtO@ z?fAm&w_PxQ?t`! z5PvYvFdedW>z`Yy)+lC^E>j#%=1`*uIHhNrS3*}TM0};7Xuho{9+Rdu#!Zl6EvcncaHmnfgc>l`8^u*js zrnyN4YQk1XGhqZo{UMwZzr8#MF%c7UiaER|K%^ooNyu|AK}{{_@+0Vc-)89tX}

          82ZRy6MZ8U$Jpvo`1D(UU%JhZ@J~%Gtd0tO*ek;hyQcU^*0dZmgKAQ zJ%a;nTL$#Q=osi+a`OxZ_OzGmw#yH`^>tW>?M|m!tu57R@ZZOuc=D99Kc~}E7UoX= z$T9CZ^x%4Ur@#F5FMs`8{=vmU@s{hZ3VhBd&p!X&Km6&055D*H zuX$yqTn_y9SNGm`?8&Du*N_=}=mBs3;8BP3W^4HI;NSj!+11zI{^*h z?|=8Z%x8Z3{0n~dyWgL5%=_N-`u#HLbl`pd_RmKyzWnRIy7%{CB^RPWOTNdxFWn== z#fpRnSTVgY@j}?ij`{C*zxnn1ja4dtUfnY(*!IL=wUWUnSRG ze(B8gl==K!Ua`ODrS{x$`s_{Z`}X#i!KO1f9Sf~@4mOi7#^(si3xPEkpIwo-*dnlUq3rD z9r<;hS-b9scl`Kk-@2jKh5e-oSzmo=p->(#PfQPoy#wCx>Qhhrs1G=J<9E;b(j{B0 zTD9LRU%u;3FMCuBxVxErC3o451JOswAnC3mZ#^& z82F^$??FkzIyo5eAn$fCJ$Hr80~7JcmnvQ!I}GTz%jhMPQAi-$D2|Qu!WA|Eqd;80 z!dAVS%H|5W9QNvyPOslk@eX7lCoA?^WK zd^n=pC|lXlp-QoH4X=1&1sSCn_=zo93tARk<+%7ASkr+>;HSjSP@(NceLJ4kL{KjA zUUbKt_(5qFF#O^NZQp(N{MfO_K!S17X=ncP(MNfzxBG6peBtb~w%vLw>;KW? z@OQrRZ3iBB(WPI$`nv1*7l2#s#8W=?vc2~D#0ekW?^Un*;>DN#?VtZ3rhW$2+^j8N z``tSz)ktI`Ry-fX1iy%U>J1C4kk7-PRV!D(KVPxWUZEA3XYtXPp*z46ojIpIdME#z|*<_T2}+?Og{QIO1q` z-+8BRT=IppFSz7#h*QR14~cv*^dJABb5Hw3-1|VF|K?XN`uG{=K#T~4(R#fZ`4XrY zuD{~alh69>#!U;37>4i` zt78%`f7#0-5A0{Z{FP@X@`Vy*_AYS#U%cBcU%Tk@)02}UzRsFeD^ED){RbcLmiHb1 z@n7G47X;9;skzel6hmlHFI17f<`w%+OpL$v4f}`R3S!(j=bk5Y@MF4J@zSPhK7pch zDD_DaIEX}l&x|x0!^i+}P>$wA?~_5_>{KS7$zem)L%Dsc+irDRE#{EnK!9&7FC}1q z$mY3*Cw@eKP+Okwx7!voI0t+}{o=2@Kl2k-@Z;nV1F=YnTrXmAZ(Q6;%hT zF_@fjNg6RBO0k%uOoT)<8&P@+8Y|tM(3V;?5{XCsEeDbE7+E*BK{Y~Y$gL-|KhkJ= znctyHKT5^oh3B7h<|j}7pF8e6?0v^P^4KE^E&wM4Hvj)9)PCl?bKmjKcYggF--vrc zE}Q-Ir%t)+_S;_fn%64pk^BDmhl7rI_wVn&|DrFPfA(pop-rE!%jx+YolSTdRRSQE z?6YsCGa;{_=S8$=o_zWlO(2(V6iJv?^DAy8I|v1fm2T%X5 zKDO3g5?fkNoq|$Ksy9?_PV}ee3tmIQgSH?XZ0eDmfte z=<7%Cy~m5Myy)|zqp*7Hy7NxIxc!!NCS@h;T&V=997JJAse1i>;F%EIBcm{0!N(tk z`{&j>f7b7ZMRl!8rM%@9Yaq%Gun*fEbh`acyWei@_2TGv`_9eZYd30;_qA%(PP4vp zX6lyfzA-uqn>WDiH(fh9H90mlQ<|6>qNSb}c{^>fdR1f;hR462d@^6Iv}-lyJYvW2 zflSs6iMM>Q8C9ikq1b1CFz62Y><=867s*Cp-H|~bJHJeGgUwNskUzsot1mA>9*x!; z7~);ZWR=pH%=F4FisMrbOG+3bgd<#B7KEjf1?x*drrhha*FN!ByV*!G;Z~-9X@HFU z+UDjO)`61};%O=>(eOZn5h2u!mHQkc(TVR&lx>^DDNxf+S$Vh-H7hc45hfxkLa~{e z8MyY^B0*-e^?{>~_|7-K2HD(O4t@8xZ@$GwaJ%hE3%3Uz`rF?7z43DwUK|;-e64rS z`^#Vd`u4*PyY7Z>Kk(p#pa0SYZ+z=pes#}1anIj&n{BST>?>ct>?=Dn^aXFfTz1t} zhaUCc6BA>%-E`xj2fbajVwiyj4Ushn@oOv)g}7dHLRZCX=ZU zWg`M-3NO6+%U}ABj%{Xo`l_#93d^$J>+(xa|HH3Zt=IeAuIGBcy7zaHPuOSgz4OIN zu2jbVmhmrJY_-)kQDtAPR{!0fAHrvr%7t>JP^sK>&DZ~67lwoo!A7O1lFJw2neZo9g!nu+ zxngy;P(-g}RvN%@_FB#L&pcjT*hpE^9C5?mC>Wr5{)|Sgz`RkZ(#3r51QtR^ORg&~ zIJyeHN+SdTh)=eanpU5d<@b0aS{H`~n03UYauK4zYD7h%?YG-skwc+ejocwofsvaq=Lt|O0n=&ygZByI7rfBoy|V~+Xg z$4`20{rb39z3$bozU_NApK;13i^U>8)aB*saUcK07cRZ@h{F!O`m0}FxpI}L2~>la z1bj3oC8qU8+@%X<#3RUerWht2DVxLD-;``#z=#q;=05C-Nov3yNIUF8%GB)C$}Oi?Z#BDS>$x>s&#d0MGCf+^W*}WRCgC;`X_)VR7Ty z;b6c|H!+jna0vGOP~jx})Do@>t0ja5CRmE*5CKP1(UlN0zXT)P@W0sxJ9*z zO#ex0VgUHxFFyaAU;O&FhrRcM4?X-3_~|}-?s3WI&;8ETSDt+QM^?ZpRhkg&rT>2F zsl$$X@A+T4Fz$Al7$3j+hU;Ip_uj^Kfp77nJMMhV>)&wMl~<0q)s8;$J-`0Rokzaw zUGf`{-`soOfrlNwVbi9wPd|mV_DKNErh5V=A)3ZajH1%m5iJbQsPA~x9+43X2dj~3 z+h6|vk2~)A#qaL_^XQ}6uyNCme{uKiKfUYObp{5#gBjf%OBi+$McL1(^Hd&AN=+oT>JIwueg+j2x*|V#;m)0kL7g`kO!b#XS=2H3fR zH*^=)Khtg0SW}yXf~KxZ5GvPf)Rq^T^=hk8ZB~~WwWVftd3pXh_`aEJwpgmbZx=VN z!#mqa1-9gHm)}m1POI6hFXN7o&le}A*i6s0XtdP;0}~HjHh&W>TW00QQ5l{~lc`jB zY;tPl7PDKtV0MdbW>;-BHnSp?%EC*WP+$vWNrHSsO!X|P<#mMKgYax%P$-fAiVlVh z7GhXOmD8n=QI!GK=mRs|O`^z?4_w8^UK@6Pd)SOmEXEv40%pC z?wF&G67YsSUUKw%j`-47zIyd_-!}c`;VWKs?REFud+&K?oUzA?cMqH&sC{`FXP^ElDT6_zXj($3p!=ocO=#L?AQKkV4pgHuVwE*n_GS~_m?wPw+8e%k-hM#fIlJw$GZ9Vj zQD@$DU3jbe|NP(s4?NKB4~ykWA)i}VsB(A`+<15Y_P#gm|JuN-R?N<)S zX}J5mG{Qrm(QN(_GGca$5OAB$Znw?W;isMY+0Wm4=TF4tzU~Hi!%u$nLxJb)_`)5e z|2mCKDNMMgC&)|_oCC1w3On5H)tTUyD5wq!XV5g(j zA#Z!Dio*PnPNz;k`J@}a@wM%?-PR}x@c1E09`c?eFSzv5xD$2cyWjn@AN@$A#zxWf z*uNhC!12c)cjAfve&Wfv*Y2{@jyHYln<%HkwyHI&R=K=gBuCCx z1=o!z$sxK~K|^Za^{d}pbK`fzPg}KOg+B=rXYfmxeeJNL zkNu4w>coez!G% za--Fd4PCN1smxHnmk5JxkM*91{XPQ2Jx{5R#jZVK0#!pSwjX}Vo$}f(1LP%Ih6cJ;-N{vG4zg{1mrSARGJ%9Sc zn@{}6u{`Eb>6iy^arxJ;`LBZx{?h{wM!s;Ht+$5M_{>vJvvey?eBvEH{psu8@|G`L zbWuMv2j`D+sgz1G1z0Lu5=yvUhFi*SXlm7?fV zzx?&6kDPeu(Z_!Kd$&X}o1-7cfAHv?cG$r@fngvs=CDI|#msc6SS*(caIK34{BH!b zCZ~CNeyD&B=-<8lr}a+1GBq#Zu~(%2Y8>5>fz-LM^g4kWgj zq(dxw#O4n>^!!Jyl$Ev$cb{gaPxc=oA{&pxrd@wtA# zXEg3;j4xtjX!bu-Mmi@jg$qYvs&yJzlIw{SSVm$ls6>fYZM3wcCXqsky0Jl2lUeJ; zo90-W6A0`>K6k7I%Mq^wk;fi8#lY`hN zhUO|Hok~Upeqwew;Oj(2F`d%Kj}R$QghK@;i8#1)Iu+^(`qUDjK!!hOUvSCG_uAv7 zFWzn6yWL)?L5)^+9h5HhEt9lHG^BUMiE#6-&GB5&<`Ewpw@J z^IKcwu%u9~?8e5%;u(a*1yB%_i?$2TH%fc0 zRyvb`LY_6j&7>8#E5}K;TaAUa&t{AHR5njt_{=sJv_nmwY^Kw!Cz2@~yfHQBcC+pz z)8&b2o1uF7H)WTDw(79!q+#P>3QY)KgMY$tR3>K%m5J*7hEB7QNG2;&vzc6uX@N!p znIrvYBZXM?y0g{fCy)_)W-K<$;w-7-rDKGrmI!G+T3DgQqmZ&8~M2HR))S#_u z*)8hl?`gdYnFz}qjw%}h?r<6!>RD##{l^C$eAoMqW%$|X#|wAZ{`#w~{Op;hiR6V+ zr3`l2Rad>`9fv&hx4*@u#y4Jb&8I$bviZeXXUX2Mal^@{fBJ}{-~VUXF2vc$&wp{= z1s7Y&Ooo_l7zv`V-ak8X}E79$V}URJZS=LPH|#ofXC{K}q|od++<=SFSklh@;=~uA{zw?e(>KBeq}s z(mnVr(Hw__AK6SMD<2S-Bexudc~2x#t$KCn4#Fp5Y5j)f#ZA>s8>*W&R_8Y@ZQRgp z)*-Bv$EP`YfPbSO-xbj-*m3*qCMU-sAPst*7w;OO!hF{+@7eI&Gs~Mc)D|{YH?6BJ zZfZ8Fk#!Foe~x{TTrO9D(nja-ypin9^~6-UO$Plzx7~(lSg$U5-T-zE zPs=xp+nFiQrJB{HjccFkwj1#KLaFS!Ucc9OnUX!Ev%FU5HXD{l`+Yc7Rpt-9f{D6$ ze9!B5J8(WBW$rZUjipTx&Ee(M`HcgpUop#cA#f+t8I0DBgHn0Tdb`mu?o<+zqYFEK zlTg(5ePx?#Dw?j5=1QZ6G_JYw1UyVdPA)BP+=Pv}Orll8gGgmK)nhg`3xg)D zZ&R(5$(UyX7E|5xHKVWBcJc3oOs4W0Yb=Td%Iq^l@T*Mus1iXqv3%bjg7)V z3}W2zk0cO!mS^ieRD5^a4y*(k8pH=5|9JFYpTG2q*Bp4r1AqN{+;g_xVv7(8>VNYP zZbm3hhGg7unhAG(p;CcejkUs|I!@&B1xVH`lyW|R9mjkm3%F}qGsc;2=>jW8uK%IebhSi32koC`_4qe`Ke zO5ItW$cRi%sEYDuT14fvLVLn9^E#u2`N@C^F~_QWR7j7xhWU6I0q;-1_H# z>C(gA`@Y8>e?0DPs#MBfJolU%uDWu&?Y0qbD8bB^UVgTLLj>F&ofiurNPspcJX^{+9m*~JK6)z>0#LyzvDKrrf?KlRC zn(&eleOCWD9tm{wLCdZGkG1arkfK=LpPIb{$H5)p$U%|>6`u-`F<{U7KNDu@h z2#6pVB%>f8h$2XmoO4h_as~m(;W)zOu+#sZ>FMt3nVvn~`~COvaM>_B)6-pD_0?Bj zMaoSG4a~sb!@U3k7qsk25cC0%>EmE@g(&?}wLvBLvgh{SSFc@vt7V()oE+_8<86PC z1ZQt<^x=5cwsLV^Zno%b?{!6s6fIe{lEYE0mXK5;>_{k3Lz7KC&$Mf-h}ksFjEuDT zOPBh;UaxNLtjx?hH`gqll<3a{E?BgvNU@~y)$3NSbz7xc^~zSQSvbDv|9m-x3dI>= z3ml2HK!=zZc0-|zbQ<+LjreTkVyA&qe$nD3izF3KELkSOkvGC*HAfdT>hk%2FP%GO zqvQ?`BquW?<@}k;7tYc@DfI92XQ}nPeEv*!R)!<{U=>X&nOLffm6s>ml-O1&TqLPv z*~-Lfy_W9E%=wgeb_mmj1v2oEcvEkf&>XMg8E=MDe!bOt`7fVbmRhn)amN(sJ z==Ni6b5f$3Y!W4lAvD^NZj4V9|I+c%n8GG1dJ_%fK~8tvLreg-G8P3DjP{o=6P10% zeJjh=>IE)wE0k)8+xT4yb`exzBFadJHyOBX`|ihIc(p_8Pd@$d{lEyc;XTXd&K^B} z!mv?eut7L=?(E5vry@*8>KfnQs8P>8-`KjBZp(6>I^+GO+>OFjH?z z9Rq}*C?Hqgp8C2+UVh&Hu#h4o>r6!rxIo89Pj^5%ngw7ht{iH_%0Ld9xzjHorQ6rDZEResaaCNo6a9sV_`V zD=*)Sg2HjO?z62V5sI?xW~}zF5w9-{0d0K!&Vl!Nl$^n;Q_M6E3FoBbeFw$EzNMbz7hj)JYth;{qR0=9CR_=G8*?% z?+R$Y##IZ5r**VU>xaW?!lVEO+l^LzfuT#Y`sO2_y%0#<;iN~<>oH$SO|^KJarUcm zv6@^zQv3FsTEpk3cv3EOpNkD(m4(%;q4z;e(jzato}QVZD!zKXk8s$Q&7#qvEs<_& zZxrNZX6D%Mnz@;_ZX`7yd3pI!Q6W1q6&IVAogH7KSWZ5*6y}y~+pnjkVf>mt?z;W< z=$M$wl`3fr@tXCeD^#JLDYfQ#c{%AhnRF~eM!uH6@$$Q$oIG>dWX&jDf5`Gg64XX! z*;_)U6}BaB($lVM_%N}t@x_Wq#l&V_zm{?B3N`(7DyCn%TBKMaHF^1Nc23>5u|UC>)=VYkS$bo*Qa|(K+^>SA_bxMHADmT#n9-3tRcrv(CxR zN=z;-u7%N2ocTjgA|Pl}*T(Q9Sjo?bB2EWS7SrJhI@YzpkR)Pc=7dx(A;R4uvNw{n zrD~2Hk$}}+6u9Y})Vc)WWdkC>$@OD-B31bjc0v~Jtz_#AnM%u~)*roFvwF3*ox5jc zWs0Qy-u;JOc=MeP-+8-Bhju}>gHGZfzZ<)H{dzh?O&i~T;|^xIGG#($h#{545Ebvx zR@(Je@B(KhkIYUrv?6CB+f3o$k#`<`Y& zmRj$9YM~Iq8*h^W4&}m2x*vY@fhH@~tiO8gnkXN5?~PYAkwG5zt>Ed$9=IrFYFM~z8MTS z`8BDjc`ck!l>T%~Tw(iY>DNn?DVKKTib29znd#a8W)v@7p8C;TDpO0?iXa6CIR+LO_DU1aFL{FM((n2(TrFrp=G-9P{sM4y=G>CPw6X!Y@1ue`W+DOKLN}JS!Lo8`>`rJ9cG$^$}_tw8_^IzM1%a}Qi zte2zZboK=57}8_L#KviNFR*)R*!LzB9TRPu)M`gZ$C^>0{G6Py6}H(0;jqmZAx2JC z=I@J^dJHjrbZpzYcFh{zG~K!lPI8YreR<9)8Bw{H6B$62c=l*% zh=_wA9)(mG2BkLIAUq==fLNCc;+`u3(F4w)QJZ0_2b3DxulFMlHSIra_`j#l@V1=f z*ztc`eEjL#uf5#0L;Kj+7~}u&p!T=Vz=7AUT^A@i+f`nF`Nb|BIuzl0o2J_#%0x+x z5NeD>WOI4v@y_cn)5UOu=YaGcN$R!h+RscKJG}3Z5ql0Erh`zjc!^pysy4mv-U#;9 z(zl(9j6p;)))7d~p&K|%R4DXt(*gpNuWbj89L-3-PW`f28}`)}Iuq)mrpHpdV5`_rFW6=r zXJ^~MZYY#cw7An?)YgrRDQrs{uiv~mJtLz?yrSv)XtM|XSFuDXjbrUQTuX7}*zw90 zD|kNNt5f^TtgPMp52jv8wVQ5$%>#>%iz`;FXmY8Nb!yh!v1jkLox6z;Hvotn@$gpQ zrjX3mVMH=Gq8@H2D!O#Vn=YR}b1gN6#sm)Ax3~>8*!1dr+wZcd?`-oicqy|#9I?$r z*#3N8ar*V5NmhP-EFHScH2Rg2G>S`k#OE!MV`B09Px2tzEoa(H|Y+-z5R z2d3mVW-^oZol8`&2~wBx7~6}*U#HGxa%&TsWOQed(T94kZ}+j8$jVgg>UdQ&Rw{;@9+^W zB|*+#xZq!$PWT-2b+Ej8fORd1zJ^QKB6`dq`;36zj!UTOf2W9T+WHq>A(t*)CQ6%X z+bGjN|J5<)OU{hDL|3ibtD!rMG00K*~TQRXQF>&_C7A{-)>J3Ogui3ao z2bkD@&tJ0Qp(frPE7azqH zijI!4yJbVz=_^VsDIRYWfVF8b3T-Ke_fTd4UxM(4Ndjawm=d|=B#TT_QA*_H6QZdy zt1Si-{J$-mj~QIeN7D)(3s-`|eq97-Yu7}R;+RXW7 z%3ZhL4ooP+A^*}?^~1L9d-VAxCnxv6TA$xdob*WZXV+}lC~I2?gv?Oq_U-0Q|JiGW zHBpr1dgPa#gCxFty@^608STRZbiUy6?qC` z=rQ6Od7Qs+af>YlC%vJIms4)MnmOn(ea-@pzccgqg~7}SD4LLvSd2Q33DlN_kiK1F zLSY&U+XOYcJj@Dq|EU48T+tb@#lW0@T9T5*eOlI>V$QZ7D*$!^T}vuYM6b7B&Nb#2PcB=wa<#blqSTXhsBi9{ zyxeSu_h$J#Yfmo^!%;_bA#bpy*`irb23tGLvV7ob1VMVgx%Z@n4IOIXRMu%Hw#Wj> zk|xP?kxg^&m-g23I~uW>+p#!E_-J0Npzd_rQO_yliOP0@e{efr5O2~Sva4b_MB z_hAX*qLBcCgy*8Xbak&sY`Lj=mpEo&`T{o(E?%x+JF*5@FpmW@lqe0FmE{L0bxuUt z0YMf#9$OyA3Cntyc&M&oiXaB)N&TeHZLebMmDqj5C0sVd$Gb%zWQm1RW$M{&N ztOJo5h!GPVlayGnAzrp-UCRz#{V>*;36u99Jp6yN#SoD<;d5{xQW&RH+XRp_q)LhI zaq&_LXGCZo)DeFA^%lGK9q@Z15ju1f_?R_+;l!VR)f&nv(`QbfGw;7T+RZgh^SC>;HKE7(@N~%9- z2HaaM6+yfA8@lVY*F;`kjtwk;>4#Qyh^?V(JW6!9QL$u; zPP<_XQU!L+LzHWsWkIcJXvBg6l#o*{HX>zf)P5!4+h(LJjIVf?h_VKS;|4Bq&8GaB zN_m*jLSruc(PPIVOrz4t$zz5MUbbRY?}0-vT)e<&Gt?%3H|fVewr=g-xud^z*zDiu z4;wl5?1gh4f8~u=Uhe!^I~u`7p13DZpLR`_3#7|IB;W;HOC}{1D;lZfDI5+D9yw;h zv>C)8x_S!o_{(q3nKHoWQpQ@54RK5g$rp!2BO)ff?Nmf*%nVq zBuHz5(MkN^wH?012=Y5C~?%sFM@e`*yeELzal9Bfs|8x7T>o#n10_xmC zg%fI2ujctop+be6vRc2Oj1f?uV!twP(b5*Lz7+JkTet5_OV0=h+oi=H@%^OJXU}(Q z-#UT^<9Xb9d%Z(P{}E%ZbsdT)6)UJ2sG;j@L?R-yhR&FhfX{1dDT8nZtxv6$`!NDo zZu*Z!`O#sMd%G5LA}yx$&NC$-y%iYgS7LTC@c}5j z6paZ;%1oglc@rL|l09b5T|kZL^G`n+VJ1ELaI?nu-8*FD=*iQji^15nci&5Izt`lx zdmG);pj_FqdHH#Vj~rdScKyMlM?^t2`}I0?YJJ(U<2?=PN1m^{_w4OGV9>=&mkbYc z9(X~Wz==4VarmF(2aX)Y3UKsV_8vGagCv%d%@5N9#@h!}aMdf<(*#LJn|+Utjy{)i zY2osfCYVH@ss?Q$d+F-6RVr1iR;6-Ki+JCDd1mFh4L{GGcl^Z3pks;`f0#D?_od5U ze&)$WciSp%O!m|Bpkw~e@e_xR96fyWpMQ=X&CbjSMMV`aU7iNogGY@mo|Gi}>;mNG z=J6^dZF2;@ZK9#TrmcUKDqh0!*)O`-zn?NKqBW66o4sK1veoNee&(shjqa{jw{Eeb z8af)?|LEp-^w@EFQQLR!#=F9XKmIISxDZZ4(v3VINoWKU3?j4z(|W0XM>`0q2pZ3z zM%`M=P6EJ(Kzz?7M3ty(ayFirU|QuX<}iTdfq5~xdEI3_wKCMG&B zFP}P$*V581rCdIJ=IlY+#S20MNdyB?G@(e@(#bS1qK6Gzw#seFg>xw>mr|~zrd>}n zZ6&do+}!M_=$JAUtA?$7lzfZeFp?Wc;u{6oum9yUbk3A3U7FfrIz;rw<=T(D^o;bY z*V7SMJBVWt&^Xn>iEf128|fwa9kK6k5!>sb}bW68q&v; zk3ZV^v$jq%h=>60idFrFjW~7s4D08Ym{{!U_3P-2O%4T_oaoI_QXpwrnR^Z#!Z#fh z{XAhZiQ4m8V}B*(zZwTOB7`lUK6O2J&nHMRS zp^9|DTptJPt6RJv0c3IwTufPVA$-|zLXch6+%&EqL@a)iApb}|+f*)$@ZxMFX$-jA zNW@kYtv`BqaNk~z@rBXjCq2~sh2^W)L^hotz1w2-f;kU0Z7jA0%c*PNCuY{JS#$j8 z5hDi;h-`(=U%1fzi*BEE=ydwbDLQzSDpmY->f~>F^>7WN^g_ez$Q+R%h}~uh4N@V6 zV+ln&Lo!+f++zih7C`o+atSQn8Rm>C>OiP02@@3r8L~l@&aEK8mDn@~l7;fzw>Djt z3<2I~3tV01hz^^A!)RIek$qTga$LJyAsCJ{RC<%4H6{6Zb{nDigrZ4hDkhh&R6MzS zV)5i6#gY(T$_REXiB9w@C|(AA234V96^NV?-$fB!?}-Q=C5fPK=gYzyz8so=5Q0pe z5nRR=#OL+o?uf2MDfsRt2^e!D_!9IZU}`hp;OYyDwhk(8X&@1AZe$6lhbPFh@%Rra z0a;0`gJ}Cs3_+m)fiV-@&`whOIem?pU?7^)7MVt|GtjW}`KO;+@%yZ1O&Zhv<=>Mh zKWX2oRfkU0MUAk|D^;v8Vbt&ug9hGOrw;Ir5cD@|RHLcikK0E@X??+)s9Ku) z%yX@Ra%e~lPmHH{7l_6>@SP7O2Z(BWh`6)hnG>L-2@H^1zGP0C#E{L0?ccHjm=%CJ z7Wmgmfq|!?Q~V)5Us4-HlY$QDXEHfBUpSnXmy@59WtU(SDiohsJh4>isOT6(!wSma zYdgRjK2Q~OL<>J{OKbarOgZ>We`JSUyL%BG&BM@L6lhy`sP966{Hec~0(1ivRCWP6 z^b5B%e=N(K3 zBLspkN-+@Djl`1N-2)aX+9l4FD^(mna_FLED+Y}idFu4pWh+;&T)Vbi%a)&h^nL_m z`t;+E(m%&eocPyap;oF;q1sJV3e5BD*|-0j!9%zHy@Q3{_ubQ=>*wuj*K!33b8~ap z2@S^1)-R6i>E8${3IV^X_0XXpphk=5!he%$3(DF>0Fe!U!!=#j&Imv`ZgBLB z;EFpEamsmjQ$I9en4U&x2I`rC$AgGI&B(~g7}G%V@tyBA{{`mQ8=OWceSZQGGQzya3CAR4kb!2W z8Hf|R7__N;27Q@(+(cJ`%z7Bgjvfe=295WoB=eELFQ)_~9mW1h+>|2;to;>@ z5CdX!t;0ov*NGAA*aj_8tv5t;&Q}ngVEGkc0!{-WB9%r#bYoIbJBi4(x!MRoyXYbl zJV*eUp+JBhA|^;9kkX9c&ErOHItkc~hz=$yaOQwC#MsZV+(tcs#bI%oEvsBMLLtL6 zmGD=VZp#;?nN|Q}Nm+6YI|=EsbwLSzrN%*)+f};7#q|mz_J# z{%LaE+O>(T4s+t2R&CmK?sDPcMdSbWShHc{gHJs(?uW_5*>zri?wM7Ket+%77d#(x zHEk6r$5ap1ttMD)gjx)u@Lwm|~KE+Ql$A)wq@8yFFf zE8wlHW9}&7g6y9DI>3-)R*&rVS{2=UbdZC`?UBvLfH%BnurF^h$x?72Bwl2zJNu_C zBG6KVS_a-N=}&{ka9BDz>VN9pwqVAzj%`0>M_I6B#e+{hH-7Sz|IGwnO1a#j>zD7h zYJ2k38EOz~RJ-ZN??(^#x>r(CqCU&SSh4_0meWw0#j-S(D>?yE`x&X{vtY#`18|vV zff1`duS>+R6i@>AUZul`h$rN9+w8Fvql=R8drur%pW8hE&=F8yS9Hn<%x1zIpdev< z8wmF6org0c*)x-=ov^}aFr4=2_H)yaJrsfWUo`n1;%Tv`T{-^OwS)u`(YOa0Qxfd1 zl8DJG?NW!}ESwSS|AH1z0GBdcWI8ScZz%C>ZO;KY^baapbZS}!>%jV2%*q{M*zB042`wtuW+-q-c{NvC6$_oE9 zeMYmVpPA=KuFxxK`|-!i=FVz-Z=kRwXZxFg^q5?9R;mFx7v-eWKmtG#dIdGZU~+Lh z>=AqJHQV?so(yyhD_CkoFGCP-ji1o2Cq!zzg9v&EpnlJQW&?sI6x#!;Awg*hA@rS; zq*FU`d;`mF8bjn?OrwgoyK^=LLU19GJ2q0I#F422CT?r;|DcES7O>Zu-RB=$KVSW2Y1VIL)pb|BdQP+G?iq`}rMT4;T z$dFD1JeTNvd=i{R4B~#k4Pc%SVCW-|XZ*tO{wYmF<9I{pQL-ThqMAC#JUE>)IEmM@ z;9aB`nO%aoWvCyd%i01W)Qt&NFcnl{ofSs=3259*iIWfnwvdw%)m~~;uQu(6aZ{(y z81(JP%7QLC4qYyNqg)}=}oAd|Rb*Y5s9zumTD7hB(r8{Ye6=g+HGs~Y)R z+js49wl6Wdma{*B4E!ibyJ0=}xx*a!({64Fhv@qmB@H!w?z~q*(g>7FH zUymKr6x0ji?KF)lNdUXP*r*d_hn6T9xNQd|G(oRu$L@W%)!CC+G@)3rqQw#tm;`%L zu>{MqvYbX6wxqaEL(=4P(v(3GZ!utat5%q7AOpS}i7N#h=N^ds9*YJ{@Z)rrE7j@_ zg2}yZ-fP!OCj(wQ#oA+uKIMWf$_*+O5+Gjd;9`rYmz;A(A%kP_#8M2JbK^nwI=7f> z#Tin(qayz?E`{rYhbB+=3TYQNCJGr4=FD`dRc@FFLgJ-BisvjDSm3q<0(Fek7+$Xk ztc7K~RvvKsV_E9peG4rDAdxIMM5NgnI+k>>Ar?i&vX_R^Ldgg*5iHjAg4gr18D|o1 z{+uDyaUo2;6fG~_L}Y0mAW=2x_Zdh}0{@$+IYl(~Ca>x+U5h|+a&z5NVGE7-c9aIgjNa=)MXP4cn1TN7YnBWlUD@xA}`^ zI=vxcqhpFDBot3dEMKPd*>e{Nn}tp*Yny~1)5rGft^wjz;;6n8jDkELY|Io`U4v4C z)@|~9%T!gtn4?X=ovao|=|PR1rA)O&a7z=wcgVd?(fC@THYTDe5@n$aVQ)v_z)`*? z&X9qsmZfG{c*}HtXI(%sEW;klsadr9`hXeYMO#ii7VGQd%oJ9dlRte*Qi&spf!zb-H&uLh6 zZ4;$=h>6!Ac+!8s3)2DnV&Zv(#^^qqYqvbAUhSq5C5r#K^>5;#jPOollA~rI-ZMnx zJE-r<4&}~Wy|@0ICr_U_b?$<=rW#eNRH;y5#kvis9a%xhu<|J)dLtOT>{Vn#L39b$ zP{^Dh%|!mY3DWF1-z!@>`PSOCR&UtEveQnj5J@gsvUZJXfA8L#o{^!18Vrv#<^C-k zXh2=*0F-`dqM)A}6xqlQH=HJ}w*tO&7M@Tz4uyh5*9=dzhsi@?JWZap0#q@l7-HF# zL#DDg_UHUfCpdM7H0zqV)&&Ya47+P;)$0DQI?ru zm!lEWEzt%`S`D^kK#z`}-QV!;e#1tt+pt-*hEyJit5&{Txm)ViE?hY7;-$-f@7$f8na!+KlSU1@v};}a<{FWg?ct;Ud_8#R#y_^A z5Rp9pV~f^6e(ap(rk}0oT*g zGqbY)TsH5f%9WC9-{D`PC<>Rcogu`G#Jf_vMdRA|(_ViqpI-I zO!Vy!JRV4wg@RhO2AORBXnaqDyYIMNEEygG+Y8|O_3MZKIX-Xca_*biKXzY(JHP#= zSN%ttKk?85Q$`P~)}ZnA>uI9H`m9OcHM#fhQnl`oI`Pt%G89)$OdWTS2v>T+V`+fW z#|!H$5TDxzs3DLRF&Bs|1Q7LzQ4mo^{~nQUWRxf3;LYyk#seVS4|bzjRzz&;M5%!$ zM87!@BF(>JAPGV@@OWdBij8kjV?9%1oq~-Fq77)snc$WS&e@~cZ^*aJpLqPsj-S2o z^y8m*@9k)ql3DWr6hZ60=C4@2wrj`FUV659&;Z87#B}S>?uDnG=sj@YhK*b3!aI5L z#F?`v?S|gAHg!Jz)mv|_^;w%%1s2!Q$B>a@#!Q%K_f!l48}_86qC@(ARkn2L9{mPw z+VUqj(X|;0iJq-2{9`jIDXI8<_tpmjJ}DnNOSJF6!9z!nC6_8ex16I#|Jm@z*2)zs z-qYX?8FUdMsJqOz=H%uqT)xuE4>MHMaD*%K^75!)=x@I zyp(cz{iZ*Eo%{Qx)GMNyOO5JPZ@;DPu6_IIn)Jb-ipx-|>P=5Q{z#(+cNQ;J>_SS) zhClwAy zKeyBcUZqc?+Hg30{?esQfBZ!x9ors<5&ge@AYvpmc+_`;Mt|=%q;&fo5E=~b+q8;4 z%g)Y;jg7(M|4GO0vllI)R(Sp9KRp1u2zm?0#Vz@DN|7S*!5U2V$Nt)}t7WI|`er4* zC(pe7;m$Qn-hTOosWWHO!$w6#RjE{A&Bo1-H+um83Vj~7!YkKrqPO*z??*Mezmez2 z7gH`%<5<0F75|TBWoO^g=;5@?46zBcc=g4nAAKn363(1EPYp3hFvmztN~}_;B7L5g zW=n2bjywF|{f%l=y(zh532KGUoV~<-3-%NY%;^N) z_Xw0iSZs(bELpK?K=1DJf1NsM+Ap)_Euoi{QPrU{@V8br)_dFvxviMrUo(JhTQB~VTFxQv}s3aQPB`G z>eQ+>ykDO{xMTjpPQCixQtRfSU-wwQ`H%Hmwl;tA(cWKlh)Zr|Bw@bE2vZzA58(eC39 zMvkA@_uDZL3{ZU8zD=7C-;qYSW_9~e9oqEhKXm+0zp(j3Kl%D|%|B}K#?Wy;3?4mB z9&;A2BIXP{*^rVKVe~&NX;!4nQK6>l~^{lB+x@Ft; z$`#7f?~a@>IRdRcKE80#gd!x^BenZ<6pAZwBGHpBQ#v^+6r!H{?)?YoPPTT_mQ!cX zeemXM^xbMzD*rfosQ7SNdPaiNrnXL_W+|yx4jejMq;TOdN@>#bX>iBw)F%G%_jb!7 z>iIxMMiw>V7!Hk&ilQ-M&AXdQ_>oIBZCpItmT2FnGS3rrv=}c^XFHs-wde7rSwk0#iThs$1-sKU+H+vkrd!Dqk%GB zCIE+jiBvo{d23^WkWY?W^{e~tY0#}hnI&Nd>{p4#b?aE+?f2lwkkr$oC>U+h18 zlt#LC6MJXxx4@)k!tVHM?@^&pD2968A)6#%=H}WOiN}tg_;LCSPjnPALpyfwVZxXU zyryq1TD~$nJDWMY^zqKCFWpk7*2JHFIdJ43w({w_*}1v&4y^or#%*Nal!N-pMLEfVT(U{`weD=sezuqY{k`U*GncPJ@x2A-9K;p-O&EWPn_JjcR#(M z*U~cWJY-si23O<3<-i_ayz|=2^lA5R1}|T`p1NZtOO|N<*u!76Y1yai=hWXE{lgSS ztz)`nX=!O3Y9c&|0!-BW+VymH`_nV+-<`L3>C%;J*{{XL#oc}9?XSJ??C@{Cij9e# z`15q;8Lj_g>-sg<0pzxyIZKx3-5fK?c5F;Vchlb z(|#A%tKEMCZTaZuH!S$AXhK3>em>pN>0Nv7$;T%BGUL71Ul~93=Xr~kU%q-J^@^=X z85I?(dvnc`XU<+vOS|S&_J2Kel>dPJx^?>Ct=F2r`9T4EEjG=fLUeA@%k)=QQfu1v6r^S;JXa2sh^%u6>)%pE@kDWN>>!Bl)OO)8VX{A&lXP&R9 zJOJVX&!Xe7>&gP*jkFjnNqqSOI|Ybql{gK788{Yuu@4X|ncz_b^fovJp(mhBZ`JAG zrBI3_k63K?c7E*7ltmt8wQ+_dqW z1&c?GpJ=CgVq)p#7b=>>@Rl$k(R9zV^U9Vz{!TL`b~$YKK6vEl&ogEdIgbopx(y;Q zVcyNLV<)K9X5l&=t$KB9Q$svq>Muu*9d{4t+@p_Myh+zHUB+Ge^k>8M*aJ;}9zSaQ zw*zmx|6$_bs^4_)Y;Q$xeX!B)i0rgzyPh_3{G@+Q{5xsX&>zPPtM|ZThFkb28CPnm zz<%xiyX#XcOc!nA<}cIlvK4hLJ#E;y34i?cH?@7#FJ8Q2)v5XrlioX|MJ~P zYK7ly*>=^2%>wG4|I-f_E?ycwVGS2t@=az| zR*wP0_HI~C-#u~iH2eDGkwf18v^|qX(dPT<^Mr&V9-0UVhD1YlqYxcC3+(PN)K6Eh z2XUjq77uD6_3E_><;vbw?>0BGs$TW3dbif9X(w0c-h!|&p4ze6eM1hApReZ(8Nc9= z;n{B(8OT0GkUNvenz%E(|Ip!!moD$#sY8=S_w?#Nyy0FTpQ z`I>cq@7jH5z1zx^Ds?X9(q}DgEu@Llrf=N34bL_@$P1RQVgY7_GG$JmJFif=B?c#! z0~y$}3;j>qZeLL=EE3%82GSUx`ogV0Xwj{G>kmHr!jli+w_l{TG-IAzqNGBQ0Q;E3 zznkzGjdfan(7AU%#S(&AcHqo#YG+H8EHSK4&xf1d|JsM2+E$of!>i9eea~HY3>p3X z!;SB&QmMl3{RisSzWLs}?xaD(9k<;wbKZhB-FmT^cJaXWNk9MEweKK(d6vf>6NLn9 zsPq(2GVtzW^`UcO9UVH*EC*DNkoqQsmj<8vK1oPH)MDvIuH&bfW1 zvR~xl4BL`#bm&Uh;H(I7{ajJ!EV8n*yvror8!lW*0mJ~KkE>1t(~~>4 z&~MQv7Y_XW`bTXRtyo3<_l46Z=jG+olYHcXCJ!~apDk58=JVA4fT>Vj4MP^opq+(_ zm4jQ}0HBbB1)BnpQz_FHjJ_>Navt(K(_`T>0HAW9y(Z6nm*_(s&l4|3OjMC?6ZxUC zWtbBgFz7%+Bpi3(G(zG{Dhfsh+Q3X9Mb7$xxD-p5LI|e9jOb7%e!9=R0PU}2{5`QV>vg2~v6XB^x9;Sc) zFzr`NNfaE6X3xD!gH0xDCrU_^X~z+_O6AK{yQxY>X6EdLOZ@IK{nUu>CsITF)FThY z#>C|0f}Us6l@%j|iv zak15^RC)b{<}>Ck*tTlE-^U2(B%$Xyky_#y&G42H+kBi z(ce+enq@>ql9;7jScd)IQ?^>{pk7_IV{ZomU?P?~iFTT%uUxrpEj{jTpZpjh;S{qCFP7mr8S$cRuR+^ z4dF3^p)djfOkBQ)De!_>!Mz9`bn^7MtBTGx03MqnEghcd5N1}S+y$-JPO*x&1tZEp ze0|l)W*dxRxTWI_e7E%USy%BRq;9U1$#J{vzRwJkh1zY1ku?PeS%eeBE&1X$+FQ;K zh?UKSD{P}30(Z|d?W*C>@Uh?jHh1oTufJL_ed<>Ohi>|Fn`wqqQd2v2|7zCn3;T5M zTnCAz75JcE={sb^<4Eah9Ak^E!Zc3(|| zJAtofWSly4wxVsXEAKya#E`W>;AXLL0f_QtP;4xk1{W?~%+Ah9C=#DsqPRowFpvZ* zA~HK)waHb^^*8uWy_M@X;X1$%+J8~BNRcxaTs5f8TelTUNEkQdo3~$m@zUkXb#Jaw zI=K{e3IB6zUAxS3&pzfFl}k=u^vmS`Y9rsaYxmQyzvnh5myRdq1cKA_%a}M~pcBrA zKkL?e_M#=9_x$?Brysj=<=UCE=jr!YKh{1&NA2FX-zDin2&6)yYZ{6bO`sdkroaAf z`R<$a4-Hmk{=N`!rMpb|L;sQE#!Q;Zq `=+p@1<>u#y^PKz*$;!+|)e83QDjIL& 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 From 00d9f713847ad667c917a4e0324e3d1456cc169d Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 18 Mar 2020 13:45:49 +0800 Subject: [PATCH 22/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E6=89=A7?= =?UTF-8?q?=E8=A1=8Ctask=E6=97=B6=E5=88=87=E6=8D=A2root=E7=BB=84=E7=BB=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/tasks.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py index 0967ac482..981c2a9f2 100644 --- a/apps/ops/tasks.py +++ b/apps/ops/tasks.py @@ -33,7 +33,8 @@ def run_ansible_task(tid, callback=None, **kwargs): :param callback: callback function name :return: """ - task = get_object_or_none(Task, id=tid) + with tmp_to_root_org(): + task = get_object_or_none(Task, id=tid) if task: result = task.run() if callback is not None: From 91c42e853023ee9c8b6e95c9c3c2424878d46425 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 18 Mar 2020 14:02:36 +0800 Subject: [PATCH 23/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E6=89=A7?= =?UTF-8?q?=E8=A1=8Ctask=E6=97=B6=E5=88=87=E6=8D=A2root=E7=BB=84=E7=BB=872?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/tasks.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py index 981c2a9f2..7ea11a3e4 100644 --- a/apps/ops/tasks.py +++ b/apps/ops/tasks.py @@ -10,7 +10,7 @@ from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from common.utils import get_logger, get_object_or_none, get_disk_usage -from orgs.utils import tmp_to_root_org +from orgs.utils import tmp_to_root_org, tmp_to_org from .celery.decorator import ( register_as_period_task, after_app_shutdown_clean_periodic, after_app_ready_start @@ -35,20 +35,24 @@ def run_ansible_task(tid, callback=None, **kwargs): """ with tmp_to_root_org(): task = get_object_or_none(Task, id=tid) - if task: + if not task: + logger.error("No task found") + return + with tmp_to_org(task.org): result = task.run() if callback is not None: subtask(callback).delay(result, task_name=task.name) return result - else: - logger.error("No task found") @shared_task(soft_time_limit=60, queue="ansible") def run_command_execution(cid, **kwargs): with tmp_to_root_org(): execution = get_object_or_none(CommandExecution, id=cid) - if execution: + if not execution: + logger.error("Not found the execution id: {}".format(cid)) + return + with tmp_to_org(execution.run_as.org): try: os.environ.update({ "TERM_ROWS": kwargs.get("rows", ""), @@ -57,8 +61,6 @@ def run_command_execution(cid, **kwargs): execution.run() except SoftTimeLimitExceeded: logger.error("Run time out") - else: - logger.error("Not found the execution id: {}".format(cid)) @shared_task From ae98eee0c73d6591bd2a5a0409d2e1c4c4ab1a5e Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 18 Mar 2020 16:34:37 +0800 Subject: [PATCH 24/32] =?UTF-8?q?[Update]=20=E6=9B=B4=E6=96=B0=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/jumpserver/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/jumpserver/const.py b/apps/jumpserver/const.py index fa33f262c..5db1e8f3b 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.6' +VERSION = '1.5.7' CONFIG = ConfigManager.load_user_config() DYNAMIC = ConfigManager.get_dynamic_config(CONFIG) From 7dcd04ca1aa87d4bf200eb133617f27e34e94922 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 18 Mar 2020 17:03:49 +0800 Subject: [PATCH 25/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7de6a3f60..2d58a8fae 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![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/) -JumpServer 是全球首款完全开源的堡垒机,使用 GNU GPL v2.0 开源协议,是符合 4A 机制的运维安全审计系统。 +JumpServer 是全球首款开源的堡垒机,使用 GNU GPL v2.0 开源协议,是符合 4A 机制的运维安全审计系统。 JumpServer 使用 Python / Django 进行开发,遵循 Web 2.0 规范,配备了业界领先的 Web Terminal 方案,交互界面美观、用户体验好。 @@ -32,6 +32,9 @@ JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向

          + + + From eac46302726a91b8345a525f2efe932fe18b23c7 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 18 Mar 2020 17:14:21 +0800 Subject: [PATCH 26/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9readme2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d58a8fae..c7edb0d41 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向
          {{ object.role_display }}
          {% trans 'MFA certification' %}:{% trans 'MFA' %}: {% if object.mfa_force_enabled %} {% trans 'Force enabled' %} diff --git a/apps/users/templates/users/user_disable_mfa.html b/apps/users/templates/users/user_disable_mfa.html index e95fd26a5..e1f6aa644 100644 --- a/apps/users/templates/users/user_disable_mfa.html +++ b/apps/users/templates/users/user_disable_mfa.html @@ -29,7 +29,7 @@ {% endblock %} diff --git a/apps/users/templates/users/user_password_check.html b/apps/users/templates/users/user_otp_check_password.html similarity index 96% rename from apps/users/templates/users/user_password_check.html rename to apps/users/templates/users/user_otp_check_password.html index 217bdc88b..f83e03b78 100644 --- a/apps/users/templates/users/user_password_check.html +++ b/apps/users/templates/users/user_otp_check_password.html @@ -10,15 +10,11 @@
          {% csrf_token %}
          - +
          - - {% if 'password' in form.errors %}

          {{ form.password.errors.as_text }}

          {% endif %} -
          {% endblock %} - diff --git a/apps/users/templates/users/user_otp_enable_bind.html b/apps/users/templates/users/user_otp_enable_bind.html index 7aaa25236..65d770cde 100644 --- a/apps/users/templates/users/user_otp_enable_bind.html +++ b/apps/users/templates/users/user_otp_enable_bind.html @@ -3,11 +3,10 @@ {% load i18n %} {% block small_title %} - {% trans 'Bind' %} + {% trans 'Bind one-time password authenticator' %} {% endblock %} {% block content %} -

          @@ -17,21 +16,15 @@

          Secret: {{ otp_secret_key }}
          -
          {% csrf_token %} -
          - - - {% if 'otp_code' in form.errors %}

          {{ form.otp_code.errors.as_text }}

          {% endif %} -
          diff --git a/apps/users/templates/users/user_otp_enable_install_app.html b/apps/users/templates/users/user_otp_enable_install_app.html index 809296b2c..e3462cd3a 100644 --- a/apps/users/templates/users/user_otp_enable_install_app.html +++ b/apps/users/templates/users/user_otp_enable_install_app.html @@ -3,12 +3,16 @@ {% load static %} {% block small_title %} - {% trans 'Install' %} + {% trans 'Install app' %} {% endblock %} {% block content %}
          -

          {% trans 'Download and install the Google Authenticator application on your phone' %}

          +

          + + {% trans 'Download and install the Google Authenticator application on your phone' %} + +

          {% trans 'Android downloads' %}

          @@ -27,7 +31,6 @@ diff --git a/apps/users/templates/users/user_password_verify.html b/apps/users/templates/users/user_password_verify.html new file mode 100644 index 000000000..bfc72ee87 --- /dev/null +++ b/apps/users/templates/users/user_password_verify.html @@ -0,0 +1,24 @@ +{% extends '_base_only_content.html' %} +{% load static %} +{% load i18n %} +{% load bootstrap3 %} +{% block custom_head_css_js %} +{% endblock %} + +{% block html_title %}{% trans 'Verify password' %}{% endblock %} +{% block title %} {% trans 'Verify password' %}{% endblock %} + +{% block content %} +
          + {% if 'password' in form.errors %} +

          {{ form.password.errors.as_text }}

          + {% endif %} + {% csrf_token %} +
          + +
          + +
          +{% endblock %} + + diff --git a/apps/users/templates/users/user_profile.html b/apps/users/templates/users/user_profile.html index 8c9088504..8f76871f3 100644 --- a/apps/users/templates/users/user_profile.html +++ b/apps/users/templates/users/user_profile.html @@ -84,7 +84,7 @@
          {% trans 'MFA certification' %}{% trans 'MFA' %} {% if user.mfa_force_enabled %} {% trans 'Force enable' %} @@ -166,7 +166,7 @@ ">{% trans 'Disable' %} {% endif %} {% else %} - {% url 'users:user-otp-enable-authentication' %} + {% url 'users:user-otp-enable-start' %} ">{% trans 'Enable' %} {% endif %} diff --git a/apps/users/urls/views_urls.py b/apps/users/urls/views_urls.py index 7773ca7d6..23f209d5c 100644 --- a/apps/users/urls/views_urls.py +++ b/apps/users/urls/views_urls.py @@ -13,6 +13,7 @@ urlpatterns = [ path('password/forgot/sendmail-success/', views.UserForgotPasswordSendmailSuccessView.as_view(), name='forgot-password-sendmail-success'), path('password/reset/', views.UserResetPasswordView.as_view(), name='reset-password'), path('password/reset/success/', views.UserResetPasswordSuccessView.as_view(), name='reset-password-success'), + path('password/verify/', views.UserVerifyPasswordView.as_view(), name='user-verify-password'), # Profile path('profile/', views.UserProfileView.as_view(), name='user-profile'), @@ -20,7 +21,8 @@ urlpatterns = [ path('profile/password/update/', views.UserPasswordUpdateView.as_view(), name='user-password-update'), path('profile/pubkey/update/', views.UserPublicKeyUpdateView.as_view(), name='user-pubkey-update'), path('profile/pubkey/generate/', views.UserPublicKeyGenerateView.as_view(), name='user-pubkey-generate'), - path('profile/otp/enable/authentication/', views.UserCheckPasswordView.as_view(), name='user-otp-enable-authentication'), + + path('profile/otp/enable/start/', views.UserOtpEnableStartView.as_view(), name='user-otp-enable-start'), path('profile/otp/enable/install-app/', views.UserOtpEnableInstallAppView.as_view(), name='user-otp-enable-install-app'), path('profile/otp/enable/bind/', views.UserOtpEnableBindView.as_view(), name='user-otp-enable-bind'), path('profile/otp/disable/authentication/', views.UserDisableMFAView.as_view(), name='user-otp-disable-authentication'), diff --git a/apps/users/utils.py b/apps/users/utils.py index 5acb4df9a..831c6571f 100644 --- a/apps/users/utils.py +++ b/apps/users/utils.py @@ -1,6 +1,5 @@ # ~*~ coding: utf-8 ~*~ # -from __future__ import unicode_literals import os import re import pyotp @@ -14,7 +13,8 @@ from django.core.cache import cache from datetime import datetime from common.tasks import send_mail_async -from common.utils import reverse +from common.utils import reverse, get_object_or_none +from .models import User logger = logging.getLogger('jumpserver') @@ -193,34 +193,17 @@ def send_reset_ssh_key_mail(user): send_mail_async.delay(subject, message, recipient_list, html_message=message) -def get_user_or_tmp_user(request): +def get_user_or_pre_auth_user(request): user = request.user - tmp_user = get_tmp_user_from_cache(request) if user.is_authenticated: return user - elif tmp_user: - return tmp_user - else: - raise Http404("Not found this user") - - -def get_tmp_user_from_cache(request): - if not request.session.session_key: - return None - user = cache.get(request.session.session_key+'user') + pre_auth_user_id = request.session.get('user_id') + user = None + if pre_auth_user_id: + user = get_object_or_none(User, pk=pre_auth_user_id) return user -def set_tmp_user_to_cache(request, user, ttl=3600): - cache.set(request.session.session_key+'user', user, ttl) - - -def delete_tmp_user_for_cache(request): - if not request.session.session_key: - return None - cache.delete(request.session.session_key+'user') - - def redirect_user_first_login_or_index(request, redirect_field_name): if request.user.is_first_login: return reverse('users:user-first-login') @@ -231,15 +214,13 @@ def redirect_user_first_login_or_index(request, redirect_field_name): return url_in_get -def generate_otp_uri(request, issuer="Jumpserver"): - user = get_user_or_tmp_user(request) - otp_secret_key = cache.get(request.session.session_key+'otp_key', '') - if not otp_secret_key: +def generate_otp_uri(username, otp_secret_key=None, issuer="JumpServer"): + if otp_secret_key is None: otp_secret_key = base64.b32encode(os.urandom(10)).decode('utf-8') - cache.set(request.session.session_key+'otp_key', otp_secret_key, 600) totp = pyotp.TOTP(otp_secret_key) otp_issuer_name = settings.OTP_ISSUER_NAME or issuer - return totp.provisioning_uri(name=user.username, issuer_name=otp_issuer_name), otp_secret_key + uri = totp.provisioning_uri(name=username, issuer_name=otp_issuer_name) + return uri, otp_secret_key def check_otp_code(otp_secret_key, otp_code): diff --git a/apps/users/views/profile.py b/apps/users/views/profile.py deleted file mode 100644 index dc0359fa9..000000000 --- a/apps/users/views/profile.py +++ /dev/null @@ -1,272 +0,0 @@ -# ~*~ coding: utf-8 ~*~ - -from __future__ import unicode_literals - - -from django.contrib.auth import authenticate -from django.core.cache import cache -from django.conf import settings -from django.http import HttpResponse -from django.shortcuts import redirect -from django.urls import reverse_lazy, reverse -from django.utils.translation import ugettext as _ -from django.views import View -from django.views.generic.base import TemplateView -from django.views.generic.edit import ( - UpdateView, FormView -) -from django.contrib.auth import logout as auth_logout - -from common.utils import get_logger, ssh_key_gen -from common.permissions import ( - PermissionsMixin, IsValidUser, - UserCanUpdatePassword, UserCanUpdateSSHKey, -) -from .. import forms -from ..models import User -from ..utils import ( - generate_otp_uri, check_otp_code, get_user_or_tmp_user, - delete_tmp_user_for_cache, check_password_rules, get_password_check_rules, -) - -__all__ = [ - 'UserProfileView', - 'UserProfileUpdateView', 'UserPasswordUpdateView', - 'UserPublicKeyUpdateView', 'UserPublicKeyGenerateView', - 'UserCheckPasswordView', 'UserOtpEnableInstallAppView', - 'UserOtpEnableBindView', 'UserOtpSettingsSuccessView', - 'UserDisableMFAView', 'UserOtpUpdateView', -] - -logger = get_logger(__name__) - - -class UserProfileView(PermissionsMixin, TemplateView): - template_name = 'users/user_profile.html' - permission_classes = [IsValidUser] - - def get_context_data(self, **kwargs): - mfa_setting = settings.SECURITY_MFA_AUTH - context = { - 'action': _('Profile'), - 'mfa_setting': mfa_setting if mfa_setting is not None else False, - } - kwargs.update(context) - return super().get_context_data(**kwargs) - - -class UserProfileUpdateView(PermissionsMixin, UpdateView): - template_name = 'users/user_profile_update.html' - model = User - permission_classes = [IsValidUser] - form_class = forms.UserProfileForm - success_url = reverse_lazy('users:user-profile') - - def get_object(self, queryset=None): - return self.request.user - - def get_context_data(self, **kwargs): - context = { - 'app': _('User'), - 'action': _('Profile setting'), - } - kwargs.update(context) - return super().get_context_data(**kwargs) - - -class UserPasswordUpdateView(PermissionsMixin, UpdateView): - template_name = 'users/user_password_update.html' - model = User - form_class = forms.UserPasswordForm - success_url = reverse_lazy('users:user-profile') - permission_classes = [IsValidUser, UserCanUpdatePassword] - - def get_object(self, queryset=None): - return self.request.user - - def get_context_data(self, **kwargs): - check_rules = get_password_check_rules() - context = { - 'app': _('Users'), - 'action': _('Password update'), - 'password_check_rules': check_rules, - } - kwargs.update(context) - return super().get_context_data(**kwargs) - - def get_success_url(self): - auth_logout(self.request) - return super().get_success_url() - - def form_valid(self, form): - password = form.cleaned_data.get('new_password') - is_ok = check_password_rules(password) - if not is_ok: - form.add_error( - "new_password", - _("* Your password does not meet the requirements") - ) - return self.form_invalid(form) - return super().form_valid(form) - - -class UserPublicKeyUpdateView(PermissionsMixin, UpdateView): - template_name = 'users/user_pubkey_update.html' - model = User - form_class = forms.UserPublicKeyForm - permission_classes = [IsValidUser, UserCanUpdateSSHKey] - success_url = reverse_lazy('users:user-profile') - - def get_object(self, queryset=None): - return self.request.user - - def get_context_data(self, **kwargs): - context = { - 'app': _('Users'), - 'action': _('Public key update'), - } - kwargs.update(context) - return super().get_context_data(**kwargs) - - -class UserPublicKeyGenerateView(PermissionsMixin, View): - permission_classes = [IsValidUser] - - def get(self, request, *args, **kwargs): - private, public = ssh_key_gen(username=request.user.username, hostname='jumpserver') - request.user.public_key = public - request.user.save() - response = HttpResponse(private, content_type='text/plain') - filename = "{0}-jumpserver.pem".format(request.user.username) - response['Content-Disposition'] = 'attachment; filename={}'.format(filename) - return response - - -class UserCheckPasswordView(FormView): - template_name = 'users/user_password_check.html' - form_class = forms.UserCheckPasswordForm - - def form_valid(self, form): - user = get_user_or_tmp_user(self.request) - password = form.cleaned_data.get('password') - user = authenticate(username=user.username, password=password) - if not user: - form.add_error("password", _("Password invalid")) - return self.form_invalid(form) - if not user.mfa_is_otp(): - user.enable_mfa() - user.save() - return redirect(self.get_success_url()) - - def get_success_url(self): - if settings.OTP_IN_RADIUS: - success_url = reverse_lazy('users:user-otp-settings-success') - else: - success_url = reverse('users:user-otp-enable-install-app') - return success_url - - def get_context_data(self, **kwargs): - context = { - 'user': get_user_or_tmp_user(self.request) - } - kwargs.update(context) - return super().get_context_data(**kwargs) - - -class UserOtpEnableInstallAppView(TemplateView): - template_name = 'users/user_otp_enable_install_app.html' - - def get_context_data(self, **kwargs): - user = get_user_or_tmp_user(self.request) - context = { - 'user': user - } - kwargs.update(context) - return super().get_context_data(**kwargs) - - -class UserOtpEnableBindView(TemplateView, FormView): - template_name = 'users/user_otp_enable_bind.html' - form_class = forms.UserCheckOtpCodeForm - success_url = reverse_lazy('users:user-otp-settings-success') - - def form_valid(self, form): - otp_code = form.cleaned_data.get('otp_code') - otp_secret_key = cache.get(self.request.session.session_key+'otp_key', '') - - if check_otp_code(otp_secret_key, otp_code): - self.save_otp(otp_secret_key) - return super().form_valid(form) - - else: - form.add_error("otp_code", _("MFA code invalid, or ntp sync server time")) - return self.form_invalid(form) - - def save_otp(self, otp_secret_key): - user = get_user_or_tmp_user(self.request) - user.enable_mfa() - user.otp_secret_key = otp_secret_key - user.save() - - def get_context_data(self, **kwargs): - user = get_user_or_tmp_user(self.request) - otp_uri, otp_secret_key = generate_otp_uri(self.request) - context = { - 'otp_uri': otp_uri, - 'otp_secret_key': otp_secret_key, - 'user': user - } - kwargs.update(context) - return super().get_context_data(**kwargs) - - -class UserDisableMFAView(FormView): - template_name = 'users/user_disable_mfa.html' - form_class = forms.UserCheckOtpCodeForm - success_url = reverse_lazy('users:user-otp-settings-success') - - 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: - user.disable_mfa() - user.save() - return super().form_valid(form) - else: - form.add_error('otp_code', _('MFA code invalid, or ntp sync server time')) - return super().form_invalid(form) - - -class UserOtpUpdateView(UserDisableMFAView): - success_url = reverse_lazy('users:user-otp-enable-bind') - - -class UserOtpSettingsSuccessView(TemplateView): - template_name = 'flash_message_standalone.html' - - def get_context_data(self, **kwargs): - title, describe = self.get_title_describe() - context = { - 'title': title, - 'messages': describe, - 'interval': 1, - 'redirect_url': reverse('authentication:login'), - 'auto_redirect': True, - } - kwargs.update(context) - return super().get_context_data(**kwargs) - - def get_title_describe(self): - user = get_user_or_tmp_user(self.request) - if self.request.user.is_authenticated: - auth_logout(self.request) - title = _('MFA enable success') - describe = _('MFA enable success, return login page') - if not user.mfa_enabled: - title = _('MFA disable success') - describe = _('MFA disable success, return login page') - delete_tmp_user_for_cache(self.request) - return title, describe - diff --git a/apps/users/views/profile/__init__.py b/apps/users/views/profile/__init__.py new file mode 100644 index 000000000..1bc58d06f --- /dev/null +++ b/apps/users/views/profile/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# +from .base import * +from .password import * +from .pubkey import * +from .mfa import * +from .otp import * diff --git a/apps/users/views/profile/base.py b/apps/users/views/profile/base.py new file mode 100644 index 000000000..2044a0c94 --- /dev/null +++ b/apps/users/views/profile/base.py @@ -0,0 +1,50 @@ +# ~*~ coding: utf-8 ~*~ +from django.conf import settings +from django.urls import reverse_lazy +from django.utils.translation import ugettext as _ +from django.views.generic.base import TemplateView +from django.views.generic.edit import UpdateView + +from common.utils import get_logger +from common.permissions import ( + PermissionsMixin, IsValidUser, +) +from ... import forms +from ...models import User + + +__all__ = ['UserProfileView', 'UserProfileUpdateView'] +logger = get_logger(__name__) + + +class UserProfileView(PermissionsMixin, TemplateView): + template_name = 'users/user_profile.html' + permission_classes = [IsValidUser] + + def get_context_data(self, **kwargs): + mfa_setting = settings.SECURITY_MFA_AUTH + context = { + 'action': _('Profile'), + 'mfa_setting': mfa_setting if mfa_setting is not None else False, + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class UserProfileUpdateView(PermissionsMixin, UpdateView): + template_name = 'users/user_profile_update.html' + model = User + permission_classes = [IsValidUser] + form_class = forms.UserProfileForm + success_url = reverse_lazy('users:user-profile') + + def get_object(self, queryset=None): + return self.request.user + + def get_context_data(self, **kwargs): + context = { + 'app': _('User'), + 'action': _('Profile setting'), + } + kwargs.update(context) + return super().get_context_data(**kwargs) diff --git a/apps/users/views/profile/mfa.py b/apps/users/views/profile/mfa.py new file mode 100644 index 000000000..ec51c5a2b --- /dev/null +++ b/apps/users/views/profile/mfa.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +# diff --git a/apps/users/views/profile/otp.py b/apps/users/views/profile/otp.py new file mode 100644 index 000000000..7bae70c58 --- /dev/null +++ b/apps/users/views/profile/otp.py @@ -0,0 +1,136 @@ +# ~*~ coding: utf-8 ~*~ + +from django.urls import reverse_lazy, reverse +from django.utils.translation import ugettext as _ +from django.views.generic.base import TemplateView +from django.views.generic.edit import FormView +from django.contrib.auth import logout as auth_logout +from django.conf import settings + +from common.utils import get_logger +from common.permissions import IsValidUser +from ... import forms +from .password import UserVerifyPasswordView +from ...utils import ( + generate_otp_uri, check_otp_code, get_user_or_pre_auth_user, +) + +__all__ = [ + 'UserOtpEnableStartView', + 'UserOtpEnableInstallAppView', + 'UserOtpEnableBindView', 'UserOtpSettingsSuccessView', + 'UserDisableMFAView', 'UserOtpUpdateView', +] + +logger = get_logger(__name__) + + +class UserOtpEnableStartView(UserVerifyPasswordView): + template_name = 'users/user_otp_check_password.html' + + def get_success_url(self): + if settings.OTP_IN_RADIUS: + success_url = reverse_lazy('users:user-otp-settings-success') + else: + success_url = reverse('users:user-otp-enable-install-app') + return success_url + + +class UserOtpEnableInstallAppView(TemplateView): + template_name = 'users/user_otp_enable_install_app.html' + + def get_context_data(self, **kwargs): + user = get_user_or_pre_auth_user(self.request) + context = {'user': user} + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class UserOtpEnableBindView(TemplateView, FormView): + template_name = 'users/user_otp_enable_bind.html' + form_class = forms.UserCheckOtpCodeForm + success_url = reverse_lazy('users:user-otp-settings-success') + + def form_valid(self, form): + otp_code = form.cleaned_data.get('otp_code') + otp_secret_key = self.request.session.get('otp_secret_key', '') + + valid = check_otp_code(otp_secret_key, otp_code) + if valid: + self.save_otp(otp_secret_key) + return super().form_valid(form) + else: + error = _("MFA code invalid, or ntp sync server time") + form.add_error("otp_code", error) + return self.form_invalid(form) + + def save_otp(self, otp_secret_key): + user = get_user_or_pre_auth_user(self.request) + user.enable_mfa() + user.otp_secret_key = otp_secret_key + user.save() + + def get_context_data(self, **kwargs): + user = get_user_or_pre_auth_user(self.request) + otp_uri, otp_secret_key = generate_otp_uri(user.username) + self.request.session['otp_secret_key'] = otp_secret_key + context = { + 'otp_uri': otp_uri, + 'otp_secret_key': otp_secret_key, + 'user': user + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class UserDisableMFAView(FormView): + template_name = 'users/user_disable_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: + user.disable_mfa() + user.save() + 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 UserOtpUpdateView(UserDisableMFAView): + success_url = reverse_lazy('users:user-otp-enable-bind') + + +class UserOtpSettingsSuccessView(TemplateView): + template_name = 'flash_message_standalone.html' + + def get_context_data(self, **kwargs): + title, describe = self.get_title_describe() + context = { + 'title': title, + 'messages': describe, + 'interval': 1, + 'redirect_url': reverse('authentication:login'), + 'auto_redirect': True, + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + def get_title_describe(self): + user = get_user_or_pre_auth_user(self.request) + if self.request.user.is_authenticated: + auth_logout(self.request) + title = _('MFA enable success') + describe = _('MFA enable success, return login page') + if not user.mfa_enabled: + title = _('MFA disable success') + describe = _('MFA disable success, return login page') + return title, describe + diff --git a/apps/users/views/profile/password.py b/apps/users/views/profile/password.py new file mode 100644 index 000000000..c9bb97f38 --- /dev/null +++ b/apps/users/views/profile/password.py @@ -0,0 +1,94 @@ +# ~*~ coding: utf-8 ~*~ + +from django.contrib.auth import authenticate +from django.shortcuts import redirect +from django.urls import reverse_lazy, reverse +from django.utils.translation import ugettext as _ +from django.views.generic.edit import UpdateView, FormView +from django.contrib.auth import logout as auth_logout + +from common.utils import get_logger +from common.permissions import ( + PermissionsMixin, IsValidUser, + UserCanUpdatePassword +) +from ... import forms +from ...models import User +from ...utils import ( + get_user_or_pre_auth_user, + check_password_rules, get_password_check_rules, +) + +__all__ = ['UserPasswordUpdateView', 'UserVerifyPasswordView'] + +logger = get_logger(__name__) + + +class UserPasswordUpdateView(PermissionsMixin, UpdateView): + template_name = 'users/user_password_update.html' + model = User + form_class = forms.UserPasswordForm + success_url = reverse_lazy('users:user-profile') + permission_classes = [IsValidUser, UserCanUpdatePassword] + + def get_object(self, queryset=None): + return self.request.user + + def get_context_data(self, **kwargs): + check_rules = get_password_check_rules() + context = { + 'app': _('Users'), + 'action': _('Password update'), + 'password_check_rules': check_rules, + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + def get_success_url(self): + auth_logout(self.request) + return super().get_success_url() + + def form_valid(self, form): + password = form.cleaned_data.get('new_password') + is_ok = check_password_rules(password) + if not is_ok: + form.add_error( + "new_password", + _("* Your password does not meet the requirements") + ) + return self.form_invalid(form) + return super().form_valid(form) + + +class UserVerifyPasswordView(FormView): + template_name = 'users/user_password_verify.html' + form_class = forms.UserCheckPasswordForm + + 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) + if not user: + form.add_error("password", _("Password invalid")) + return self.form_invalid(form) + if not user.mfa_is_otp(): + user.enable_mfa() + user.save() + self.request.session['user_id'] = str(user.id) + self.request.session['auth_password'] = 1 + return redirect(self.get_success_url()) + + def get_success_url(self): + referer = self.request.META.get('HTTP_REFERER') + next_url = self.request.GET.get("next") + if next_url: + return next_url + else: + return referer + + def get_context_data(self, **kwargs): + context = { + 'user': get_user_or_pre_auth_user(self.request) + } + kwargs.update(context) + return super().get_context_data(**kwargs) diff --git a/apps/users/views/profile/pubkey.py b/apps/users/views/profile/pubkey.py new file mode 100644 index 000000000..29b557232 --- /dev/null +++ b/apps/users/views/profile/pubkey.py @@ -0,0 +1,54 @@ +# ~*~ coding: utf-8 ~*~ + +from django.http import HttpResponse +from django.urls import reverse_lazy +from django.utils.translation import ugettext as _ +from django.views import View +from django.views.generic.edit import UpdateView + +from common.utils import get_logger, ssh_key_gen +from common.permissions import ( + PermissionsMixin, IsValidUser, + UserCanUpdateSSHKey, +) +from ... import forms +from ...models import User + +__all__ = [ + 'UserPublicKeyUpdateView', 'UserPublicKeyGenerateView', +] + +logger = get_logger(__name__) + + +class UserPublicKeyUpdateView(PermissionsMixin, UpdateView): + template_name = 'users/user_pubkey_update.html' + model = User + form_class = forms.UserPublicKeyForm + permission_classes = [IsValidUser, UserCanUpdateSSHKey] + success_url = reverse_lazy('users:user-profile') + + def get_object(self, queryset=None): + return self.request.user + + def get_context_data(self, **kwargs): + context = { + 'app': _('Users'), + 'action': _('Public key update'), + } + kwargs.update(context) + return super().get_context_data(**kwargs) + + +class UserPublicKeyGenerateView(PermissionsMixin, View): + permission_classes = [IsValidUser] + + def get(self, request, *args, **kwargs): + username = request.user.username + private, public = ssh_key_gen(username, hostname='jumpserver') + request.user.public_key = public + request.user.save() + response = HttpResponse(private, content_type='text/plain') + filename = "{0}-jumpserver.pem".format(username) + response['Content-Disposition'] = 'attachment; filename={}'.format(filename) + return response diff --git a/jms b/jms index fcbe189a8..d61e53da1 100755 --- a/jms +++ b/jms @@ -7,6 +7,7 @@ import threading import datetime import logging import logging.handlers +import psutil import time import argparse import sys @@ -351,6 +352,7 @@ def watch_services(): rotate_log_if_need() time.sleep(30) except KeyboardInterrupt: + print("Start stop service") time.sleep(1) break clean_up() @@ -437,6 +439,11 @@ def stop_service(srv, sig=15): os.kill(pid, sig) with LOCK: process = processes.pop(s, None) + if process is None: + try: + process = psutil.Process(pid) + except: + pass if process is None: print("\033[31m No process found\033[0m") continue @@ -529,6 +536,7 @@ if __name__ == '__main__': start_services_and_watch(srv) os._exit(0) elif action == "stop": + print("Stop service") if args.force: stop_service_force(srv) else: diff --git a/requirements/requirements.txt b/requirements/requirements.txt index c3edaf181..1fad7c89b 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -3,18 +3,18 @@ ansible==2.8.2 asn1crypto==0.24.0 bcrypt==3.1.4 billiard==3.5.0.3 -boto3==1.6.5 +boto3==1.12.14 botocore==1.9.5 -celery==4.1.0 +celery==4.1.1 certifi==2018.1.18 -cffi==1.11.5 +cffi==1.13.2 chardet==3.0.4 configparser==3.5.0 coreapi==2.3.3 coreschema==0.0.4 -cryptography==2.3.1 +cryptography==2.8 decorator==4.1.2 -Django==2.1.11 +Django==2.2.10 django-auth-ldap==1.7.0 django-bootstrap3==9.1.0 django-celery-beat==1.4.0 @@ -24,6 +24,7 @@ django-ranged-response==0.2.0 django-redis-cache==1.7.1 django-rest-swagger==2.1.2 django-simple-captcha==0.5.6 +django-timezone-field==3.1 djangorestframework==3.9.4 djangorestframework-bulk==0.2.1 docutils==0.14 @@ -31,6 +32,7 @@ ecdsa==0.13.3 enum-compat==0.0.2 ephem==3.7.6.0 eventlet==0.24.1 +future==0.16.0 ForgeryPy==0.1 greenlet==0.4.14 gunicorn==19.9.0 @@ -39,16 +41,16 @@ itsdangerous==0.24 itypes==1.1.0 Jinja2==2.10.1 jmespath==0.9.3 -kombu==4.0.2 +kombu==4.2.1 ldap3==2.4 -MarkupSafe==1.0 +MarkupSafe==1.1.1 mysqlclient==1.3.14 olefile==0.44 openapi-codec==1.3.2 paramiko==2.4.2 passlib==1.7.1 Pillow==6.2.0 -pyasn1==0.4.2 +pyasn1==0.4.8 pycparser==2.19 pycrypto==2.6.1 pyotp==2.2.6 @@ -77,7 +79,7 @@ python-keycloak-client==0.1.3 rest_condition==1.0.3 python-ldap==3.1.0 tencentcloud-sdk-python==3.0.40 -django-radius==1.3.3 +django-radius==1.4.0 ipip-ipdb==1.2.1 django-redis-sessions==0.6.1 unicodecsv==0.14.1 @@ -90,3 +92,7 @@ channels-redis==2.4.0 channels==2.3.0 daphne==2.3.0 psutil==5.6.5 +django-cas-ng==4.0.1 +python-cas==1.5.0 +ipython +huaweicloud-sdk-python==1.0.21 diff --git a/requirements/rpm_requirements.txt b/requirements/rpm_requirements.txt index 14fe36fde..2e02f07bd 100644 --- a/requirements/rpm_requirements.txt +++ b/requirements/rpm_requirements.txt @@ -1 +1 @@ -gcc krb5-devel libtiff-devel libjpeg-devel libzip-devel freetype-devel lcms2-devel libwebp-devel tcl-devel tk-devel sshpass openldap-devel mariadb-devel mysql-devel libffi-devel openssh-clients telnet openldap-clients +gcc krb5-devel libtiff-devel libjpeg-devel libzip-devel freetype-devel lcms2-devel libwebp-devel tcl-devel tk-devel sshpass openldap-devel mariadb-devel mysql-devel mysql libffi-devel openssh-clients telnet openldap-clients diff --git a/utils/create_test_data.py b/utils/create_test_data.py new file mode 100644 index 000000000..3d98261b1 --- /dev/null +++ b/utils/create_test_data.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +# + From 41e03c629f256a44cb67d7627848c11d7efc7cdf Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 12 Mar 2020 16:33:33 +0800 Subject: [PATCH 03/32] =?UTF-8?q?[Update]=20=E6=9B=B4=E6=96=B0=E4=BE=9D?= =?UTF-8?q?=E8=B5=96jms-storage=3D0.0.27?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 1fad7c89b..5b6c92a8d 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -61,7 +61,7 @@ pytz==2018.3 PyYAML==5.1 redis==2.10.6 requests==2.22.0 -jms-storage==0.0.26 +jms-storage==0.0.27 s3transfer==0.1.13 simplejson==3.13.2 six==1.11.0 From eb448dc3f24580ce388ac50169173dcfcb3a3a76 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 12 Mar 2020 19:00:22 +0800 Subject: [PATCH 04/32] =?UTF-8?q?[Update]=20=E6=9B=B4=E6=96=B0=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/zh/LC_MESSAGES/django.po | 269 +++++++++++++-------------- apps/settings/utils/ldap.py | 22 +-- 2 files changed, 145 insertions(+), 146 deletions(-) diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index c2b1638bf..7356b96e3 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-03-10 18:01+0800\n" +"POT-Creation-Date: 2020-03-12 17:27+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -53,13 +53,13 @@ msgstr "自定义" #: users/templates/users/user_asset_permission.html:70 #: users/templates/users/user_granted_remote_app.html:36 #: xpack/plugins/change_auth_plan/forms.py:74 -#: xpack/plugins/change_auth_plan/models.py:364 +#: xpack/plugins/change_auth_plan/models.py:267 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:40 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:54 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:13 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:14 #: xpack/plugins/cloud/models.py:266 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:36 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:47 #: xpack/plugins/orgs/templates/orgs/org_list.html:17 #: xpack/plugins/vault/forms.py:13 xpack/plugins/vault/forms.py:15 msgid "Asset" @@ -257,7 +257,7 @@ msgstr "数据库" #: users/templates/users/user_group_detail.html:62 #: users/templates/users/user_group_list.html:16 #: users/templates/users/user_profile.html:138 -#: xpack/plugins/change_auth_plan/models.py:93 +#: xpack/plugins/change_auth_plan/models.py:77 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:115 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19 #: xpack/plugins/cloud/models.py:53 xpack/plugins/cloud/models.py:136 @@ -322,7 +322,7 @@ msgstr "参数" #: perms/templates/perms/remote_app_permission_detail.html:85 #: users/models/user.py:481 users/serializers/group.py:32 #: users/templates/users/user_detail.html:97 -#: xpack/plugins/change_auth_plan/models.py:97 +#: xpack/plugins/change_auth_plan/models.py:81 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:111 #: xpack/plugins/cloud/models.py:56 xpack/plugins/cloud/models.py:142 #: xpack/plugins/gathered_user/models.py:30 @@ -449,6 +449,7 @@ msgstr "重置" #: users/templates/users/user_profile_update.html:68 #: users/templates/users/user_pubkey_update.html:81 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:66 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:67 #: xpack/plugins/interface/templates/interface/interface.html:74 #: xpack/plugins/vault/templates/vault/vault_create.html:42 msgid "Submit" @@ -644,7 +645,7 @@ msgstr "创建数据库应用" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:18 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:20 #: xpack/plugins/cloud/templates/cloud/account_list.html:16 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:42 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:52 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:19 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:20 #: xpack/plugins/orgs/templates/orgs/org_list.html:24 @@ -731,7 +732,7 @@ msgstr "删除失败,节点包含子节点或资产" #: assets/templates/assets/asset_detail.html:194 #: assets/templates/assets/system_user_assets.html:118 #: perms/models/asset_permission.py:81 -#: xpack/plugins/change_auth_plan/models.py:72 +#: xpack/plugins/change_auth_plan/models.py:56 #: xpack/plugins/gathered_user/models.py:24 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:17 msgid "Nodes" @@ -849,8 +850,8 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC" #: users/templates/users/user_list.html:15 #: users/templates/users/user_profile.html:47 #: xpack/plugins/change_auth_plan/forms.py:59 -#: xpack/plugins/change_auth_plan/models.py:63 -#: xpack/plugins/change_auth_plan/models.py:360 +#: xpack/plugins/change_auth_plan/models.py:47 +#: xpack/plugins/change_auth_plan/models.py:263 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:63 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:53 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:12 @@ -906,8 +907,9 @@ msgstr "密码或密钥密码" #: users/templates/users/user_profile_update.html:41 #: users/templates/users/user_pubkey_update.html:41 #: users/templates/users/user_update.html:20 -#: xpack/plugins/change_auth_plan/models.py:84 -#: xpack/plugins/change_auth_plan/models.py:209 +#: xpack/plugins/change_auth_plan/models.py:68 +#: xpack/plugins/change_auth_plan/models.py:183 +#: xpack/plugins/change_auth_plan/models.py:270 msgid "Password" msgstr "密码" @@ -1127,13 +1129,15 @@ msgstr "版本" msgid "AuthBook" msgstr "" -#: assets/models/base.py:235 xpack/plugins/change_auth_plan/models.py:88 -#: xpack/plugins/change_auth_plan/models.py:216 +#: assets/models/base.py:235 xpack/plugins/change_auth_plan/models.py:72 +#: xpack/plugins/change_auth_plan/models.py:190 +#: xpack/plugins/change_auth_plan/models.py:277 msgid "SSH private key" msgstr "ssh密钥" -#: assets/models/base.py:236 xpack/plugins/change_auth_plan/models.py:91 -#: xpack/plugins/change_auth_plan/models.py:212 +#: assets/models/base.py:236 xpack/plugins/change_auth_plan/models.py:75 +#: xpack/plugins/change_auth_plan/models.py:186 +#: xpack/plugins/change_auth_plan/models.py:273 msgid "SSH public key" msgstr "ssh公钥" @@ -1385,7 +1389,7 @@ msgstr "手动登录" #: assets/views/platform.py:58 assets/views/platform.py:74 #: assets/views/system_user.py:30 assets/views/system_user.py:47 #: assets/views/system_user.py:64 assets/views/system_user.py:80 -#: templates/_nav.html:39 xpack/plugins/change_auth_plan/models.py:68 +#: templates/_nav.html:39 xpack/plugins/change_auth_plan/models.py:52 msgid "Assets" msgstr "资产管理" @@ -1509,8 +1513,8 @@ msgstr "连接" #: ops/templates/ops/adhoc_history_detail.html:47 #: ops/templates/ops/task_detail.html:54 #: terminal/templates/terminal/session_list.html:24 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:35 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:33 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:45 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:44 msgid "ID" msgstr "ID" @@ -1584,12 +1588,11 @@ msgstr "测试资产可连接性: {}" msgid "Test if the assets under the node are connectable: {}" msgstr "测试节点下资产是否可连接: {}" -#: assets/tasks/asset_user_connectivity.py:29 -#: xpack/plugins/change_auth_plan/models.py:473 +#: assets/tasks/asset_user_connectivity.py:30 msgid "The asset {} system platform {} does not support run Ansible tasks" msgstr "资产 {} 系统平台 {} 不支持运行 Ansible 任务" -#: assets/tasks/asset_user_connectivity.py:75 +#: assets/tasks/asset_user_connectivity.py:102 msgid "Test asset user connectivity: {}" msgstr "测试资产用户可连接性: {}" @@ -2477,7 +2480,6 @@ msgstr "文件名" #: ops/templates/ops/task_list.html:14 #: users/templates/users/user_detail.html:487 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:14 -#: xpack/plugins/cloud/api.py:85 msgid "Success" msgstr "成功" @@ -2544,7 +2546,7 @@ msgid "MFA" msgstr "多因子认证" #: audits/models.py:87 audits/templates/audits/login_log_list.html:63 -#: xpack/plugins/change_auth_plan/models.py:368 +#: xpack/plugins/change_auth_plan/models.py:287 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:15 #: xpack/plugins/cloud/models.py:214 msgid "Reason" @@ -2555,8 +2557,8 @@ msgstr "原因" #: tickets/templates/tickets/ticket_list.html:36 #: tickets/templates/tickets/ticket_list.html:104 #: xpack/plugins/cloud/models.py:211 xpack/plugins/cloud/models.py:269 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:40 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:37 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:50 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:48 msgid "Status" msgstr "状态" @@ -2574,8 +2576,8 @@ msgstr "登录日期" #: perms/templates/perms/remote_app_permission_detail.html:73 #: terminal/models.py:199 terminal/templates/terminal/session_detail.html:72 #: terminal/templates/terminal/session_list.html:32 -#: xpack/plugins/change_auth_plan/models.py:195 -#: xpack/plugins/change_auth_plan/models.py:371 +#: xpack/plugins/change_auth_plan/models.py:169 +#: xpack/plugins/change_auth_plan/models.py:291 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:59 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:17 #: xpack/plugins/gathered_user/models.py:76 @@ -2990,7 +2992,7 @@ msgstr "字段必须唯一" msgid "

          Flow service unavailable, check it

          " msgstr "" -#: jumpserver/views/index.py:242 templates/_nav.html:7 +#: jumpserver/views/index.py:244 templates/_nav.html:7 msgid "Dashboard" msgstr "仪表盘" @@ -3125,8 +3127,8 @@ msgstr "完成时间" #: ops/models/adhoc.py:237 ops/templates/ops/adhoc_history.html:55 #: ops/templates/ops/task_history.html:61 ops/templates/ops/task_list.html:16 -#: xpack/plugins/change_auth_plan/models.py:198 -#: xpack/plugins/change_auth_plan/models.py:374 +#: xpack/plugins/change_auth_plan/models.py:172 +#: xpack/plugins/change_auth_plan/models.py:294 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:58 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:16 #: xpack/plugins/gathered_user/models.py:79 @@ -3153,11 +3155,11 @@ msgstr "结果" msgid "Adhoc result summary" msgstr "汇总" -#: ops/models/adhoc.py:281 +#: ops/models/adhoc.py:281 xpack/plugins/change_auth_plan/utils.py:86 msgid "{} Start task: {}" msgstr "{} 任务开始: {}" -#: ops/models/adhoc.py:290 +#: ops/models/adhoc.py:290 xpack/plugins/change_auth_plan/utils.py:98 msgid "{} Task finish" msgstr "{} 任务结束" @@ -3185,7 +3187,7 @@ msgstr "定期清除任务历史" #: ops/tasks.py:76 msgid "Clean celery log period" -msgstr "" +msgstr "定期清除Celery日志" #: ops/templates/ops/adhoc_detail.html:17 #: ops/templates/ops/adhoc_history.html:17 @@ -3341,6 +3343,7 @@ msgid "Pending" msgstr "等待" #: ops/templates/ops/command_execution_list.html:70 +#: xpack/plugins/change_auth_plan/models.py:259 msgid "Finished" msgstr "结束" @@ -3395,7 +3398,7 @@ msgstr "更新任务内容: {}" #: ops/utils.py:70 msgid "Disk used more than 80%: {} => {}" -msgstr "" +msgstr "磁盘使用率超过 80%: {} => {}" #: ops/views/adhoc.py:31 ops/views/adhoc.py:49 ops/views/adhoc.py:63 #: ops/views/adhoc.py:77 ops/views/adhoc.py:91 ops/views/adhoc.py:105 @@ -4230,11 +4233,11 @@ msgstr "这里" #: settings/utils/ldap.py:389 msgid "Host or port is disconnected: {}" -msgstr "" +msgstr "主机或端口不可连接: {}" #: settings/utils/ldap.py:391 msgid "The port is not the port of the LDAP service: {}" -msgstr "" +msgstr "端口不是LDAP服务端口: {}" #: settings/utils/ldap.py:393 msgid "Please enter the certificate: {}" @@ -4243,34 +4246,34 @@ msgstr "" #: settings/utils/ldap.py:395 settings/utils/ldap.py:422 #: settings/utils/ldap.py:452 settings/utils/ldap.py:480 msgid "Unknown error: {}" -msgstr "" +msgstr "未知错误: {}" #: settings/utils/ldap.py:409 -msgid "bind dn or password incorrect" -msgstr "" +msgid "Bind DN or Password incorrect" +msgstr "绑定DN或密码错误" #: settings/utils/ldap.py:416 -msgid "Please enter bind dn: {}" -msgstr "" +msgid "Please enter Bind DN: {}" +msgstr "请输入绑定DN: {}" #: settings/utils/ldap.py:418 -msgid "Please enter password: {}" +msgid "Please enter Password: {}" msgstr "请输入密码: {}" #: settings/utils/ldap.py:420 -msgid "Please enter correct bind dn and password: {}" -msgstr "请输入正确的dn和密码: {}" +msgid "Please enter correct Bind DN and Password: {}" +msgstr "请输入正确的绑定DN和密码: {}" #: settings/utils/ldap.py:438 -msgid "Invalid search ou or filter: {}" -msgstr "不合法的ou或过滤器: {}" +msgid "Invalid User OU or User search filter: {}" +msgstr "不合法的用户OU或用户过滤器: {}" #: settings/utils/ldap.py:469 -msgid "LDAP attribute not include: {}" +msgid "LDAP User attr map not include: {}" msgstr "LDAP属性映射没有包含: {}" #: settings/utils/ldap.py:476 -msgid "LDAP attribute map is not dict" +msgid "LDAP User attr map is not dict" msgstr "LDAP属性映射不合法" #: settings/utils/ldap.py:495 @@ -4278,28 +4281,28 @@ msgid "LDAP authentication is not enabled" msgstr "LDAP认证没有启用" #: settings/utils/ldap.py:513 -msgid "Error (Invalid server uri): {}" -msgstr "错误 (不合法的服务器地址): {}" +msgid "Error (Invalid LDAP server): {}" +msgstr "错误 (不合法的LDAP服务器地址): {}" #: settings/utils/ldap.py:515 -msgid "Error (Invalid bind dn): {}" -msgstr "错误 (不合法的DN): {}" +msgid "Error (Invalid Bind DN): {}" +msgstr "错误(不合法的绑定DN): {}" #: settings/utils/ldap.py:517 -msgid "Error (Invalid attribute map): {}" -msgstr "错误 (不合法的属性映射): {}" +msgid "Error (Invalid LDAP User attr map): {}" +msgstr "错误(不合法的LDAP属性映射): {}" #: settings/utils/ldap.py:519 -msgid "Error (Invalid search ou or filter): {}" -msgstr "错误 (不合法的搜索OU或过滤器): {}" +msgid "Error (Invalid User OU or User search filter): {}" +msgstr "错误(不合法的用户OU或用户过滤器): {}" #: settings/utils/ldap.py:521 msgid "Error (Not enabled LDAP authentication): {}" -msgstr "错误 (没有启用LDAP认证): {}" +msgstr "错误(没有启用LDAP认证): {}" #: settings/utils/ldap.py:523 msgid "Error (Unknown): {}" -msgstr "错误 (未知): {}" +msgstr "错误(未知): {}" #: settings/utils/ldap.py:526 msgid "Succeed: Match {} s user" @@ -4307,11 +4310,11 @@ msgstr "成功匹配 {} 个用户" #: settings/utils/ldap.py:559 msgid "Authentication failed (configuration incorrect): {}" -msgstr "认证失败 (配置错误): {}" +msgstr "认证失败(配置错误): {}" #: settings/utils/ldap.py:561 msgid "Authentication failed (before login check failed): {}" -msgstr "认证失败 (登录前检查失败): {}" +msgstr "认证失败(登录前检查失败): {}" #: settings/utils/ldap.py:563 msgid "Authentication failed (username or password incorrect): {}" @@ -4766,13 +4769,13 @@ msgstr "测试失败: 账户无效" #: terminal/templates/terminal/command_list.html:110 #: terminal/templates/terminal/command_list.html:194 msgid "Ordinary" -msgstr "" +msgstr "普通" #: terminal/backends/command/models.py:15 #: terminal/templates/terminal/command_list.html:111 #: terminal/templates/terminal/command_list.html:191 msgid "Dangerous" -msgstr "" +msgstr "危险" #: terminal/backends/command/models.py:21 msgid "Input" @@ -4788,7 +4791,7 @@ msgstr "会话" #: terminal/templates/terminal/command_list.html:29 #: terminal/templates/terminal/command_list.html:109 msgid "Risk level" -msgstr "" +msgstr "风险等级" #: terminal/forms/storage.py:41 msgid "Container name" @@ -4846,8 +4849,9 @@ msgid "" msgstr "" #: terminal/forms/storage.py:143 xpack/plugins/cloud/models.py:263 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:29 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:106 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:35 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:46 msgid "Region" msgstr "地域" @@ -5375,7 +5379,7 @@ msgstr "生成重置密码链接,通过邮件发送给用户" msgid "Set password" msgstr "设置密码" -#: users/forms/user.py:132 xpack/plugins/change_auth_plan/models.py:77 +#: users/forms/user.py:132 xpack/plugins/change_auth_plan/models.py:61 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:45 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:67 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:57 @@ -6194,8 +6198,8 @@ msgstr "" "用户不存在,则创建用户。" #: xpack/plugins/change_auth_plan/meta.py:9 -#: xpack/plugins/change_auth_plan/models.py:105 -#: xpack/plugins/change_auth_plan/models.py:202 +#: xpack/plugins/change_auth_plan/models.py:89 +#: xpack/plugins/change_auth_plan/models.py:176 #: xpack/plugins/change_auth_plan/views.py:33 #: xpack/plugins/change_auth_plan/views.py:50 #: xpack/plugins/change_auth_plan/views.py:74 @@ -6206,55 +6210,59 @@ msgstr "" msgid "Change auth plan" msgstr "改密计划" -#: xpack/plugins/change_auth_plan/models.py:57 +#: xpack/plugins/change_auth_plan/models.py:41 msgid "Custom password" msgstr "自定义密码" -#: xpack/plugins/change_auth_plan/models.py:58 +#: xpack/plugins/change_auth_plan/models.py:42 msgid "All assets use the same random password" msgstr "所有资产使用相同的随机密码" -#: xpack/plugins/change_auth_plan/models.py:59 +#: xpack/plugins/change_auth_plan/models.py:43 msgid "All assets use different random password" msgstr "所有资产使用不同的随机密码" -#: xpack/plugins/change_auth_plan/models.py:81 +#: xpack/plugins/change_auth_plan/models.py:65 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:72 msgid "Password rules" msgstr "密码规则" -#: xpack/plugins/change_auth_plan/models.py:158 -msgid "* For security, do not change {} user's password" -msgstr "* 为了安全,禁止更改 {} 用户的密码" - -#: xpack/plugins/change_auth_plan/models.py:162 -msgid "Assets is empty, please add the asset" -msgstr "资产为空,请添加资产" - -#: xpack/plugins/change_auth_plan/models.py:206 +#: xpack/plugins/change_auth_plan/models.py:180 msgid "Change auth plan snapshot" msgstr "改密计划快照" -#: xpack/plugins/change_auth_plan/models.py:221 -#: xpack/plugins/change_auth_plan/models.py:378 +#: xpack/plugins/change_auth_plan/models.py:195 +#: xpack/plugins/change_auth_plan/models.py:281 msgid "Change auth plan execution" msgstr "改密计划执行" -#: xpack/plugins/change_auth_plan/models.py:387 -msgid "Change auth plan execution subtask" -msgstr "改密计划执行子任务" +#: xpack/plugins/change_auth_plan/models.py:254 +msgid "Ready" +msgstr "" -#: xpack/plugins/change_auth_plan/models.py:405 -msgid "Authentication failed" -msgstr "认证失败" +#: xpack/plugins/change_auth_plan/models.py:255 +msgid "check_condition" +msgstr "" -#: xpack/plugins/change_auth_plan/models.py:407 -msgid "Connection timeout" -msgstr "连接超时" +#: xpack/plugins/change_auth_plan/models.py:256 +msgid "Change auth" +msgstr "" -#: xpack/plugins/change_auth_plan/serializers.py:58 -msgid "* For security, do not change {}'s password" -msgstr "* 为了安全,禁止更改 {} 的密码" +#: xpack/plugins/change_auth_plan/models.py:257 +msgid "Verify auth" +msgstr "" + +#: xpack/plugins/change_auth_plan/models.py:258 +msgid "Save auth" +msgstr "" + +#: xpack/plugins/change_auth_plan/models.py:284 +msgid "Step" +msgstr "步骤" + +#: xpack/plugins/change_auth_plan/models.py:301 +msgid "Change auth plan task" +msgstr "改密计划任务" #: xpack/plugins/change_auth_plan/serializers.py:68 msgid "* Please enter custom password" @@ -6308,7 +6316,7 @@ msgid "Execution list of plan" msgstr "执行历史列表" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:104 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:96 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:106 msgid "Log" msgstr "日志" @@ -6325,6 +6333,14 @@ msgstr "执行失败" msgid "Create plan" msgstr "创建计划" +#: xpack/plugins/change_auth_plan/utils.py:237 +msgid "Failed to connect asset" +msgstr "连接资产失败" + +#: xpack/plugins/change_auth_plan/utils.py:239 +msgid "Incorrect password" +msgstr "密码错误" + #: xpack/plugins/change_auth_plan/views.py:34 msgid "Plan list" msgstr "计划列表" @@ -6337,19 +6353,13 @@ msgstr "更新计划" msgid "Plan execution task list" msgstr "执行任务列表" -#: xpack/plugins/cloud/api.py:84 xpack/plugins/cloud/utils.py:37 -msgid "Account unavailable" -msgstr "账户无效" - #: xpack/plugins/cloud/forms.py:15 msgid "Access Key" msgstr "" #: xpack/plugins/cloud/forms.py:19 -#, fuzzy -#| msgid "Secret" msgid "Secret Key" -msgstr "密文" +msgstr "" #: xpack/plugins/cloud/forms.py:56 msgid "Select account" @@ -6430,8 +6440,8 @@ msgid "Succeed" msgstr "成功" #: xpack/plugins/cloud/models.py:217 xpack/plugins/cloud/models.py:272 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:41 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:38 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:51 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:49 msgid "Date sync" msgstr "同步日期" @@ -6457,7 +6467,7 @@ msgstr "同步实例任务历史" #: xpack/plugins/cloud/models.py:260 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:114 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:34 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:45 msgid "Instance" msgstr "实例" @@ -6531,10 +6541,6 @@ msgstr "账户详情" msgid "Create account" msgstr "创建账户" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:29 -msgid "Region & Instance" -msgstr "地域 & 实例" - #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:33 msgid "Node & AdminUser" msgstr "节点 & 管理用户" @@ -6544,21 +6550,21 @@ msgid "Load failed" msgstr "加载失败" #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:17 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:20 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:19 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:18 #: xpack/plugins/cloud/views.py:144 msgid "Sync task detail" msgstr "同步任务详情" #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:20 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:23 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:22 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:21 #: xpack/plugins/cloud/views.py:159 msgid "Sync task history" msgstr "同步历史列表" #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:23 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:26 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:25 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:24 #: xpack/plugins/cloud/views.py:173 msgid "Sync instance list" @@ -6573,22 +6579,26 @@ msgstr "手动执行任务" msgid "Sync success" msgstr "同步成功" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:36 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:46 msgid "New count" msgstr "新增" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:37 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:47 msgid "Unsync count" msgstr "未同步" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:38 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:48 msgid "Synced count" msgstr "已同步" -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:39 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:49 msgid "Released count" msgstr "已释放" +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:63 +msgid "Delete released assets" +msgstr "删除已释放的资产" + #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:5 msgid "Create sync instance task" msgstr "创建同步实例任务" @@ -6601,6 +6611,10 @@ msgstr "执行次数" msgid "Instance count" msgstr "实例个数" +#: xpack/plugins/cloud/utils.py:37 +msgid "Account unavailable" +msgstr "账户无效" + #: xpack/plugins/cloud/views.py:63 msgid "Update account" msgstr "更新账户" @@ -6891,26 +6905,11 @@ msgstr "密码匣子" msgid "vault create" msgstr "创建" -#~ msgid "Exist" -#~ msgstr "已存在" +#~ msgid "Assets is empty, please add the asset" +#~ msgstr "资产为空,请添加资产" -#~ msgid "Absent" -#~ msgstr "不存在" - -#~ msgid "Total count" -#~ msgstr "总数" - -#~ msgid "Failed count" -#~ msgstr "失败" - -#~ msgid "Exist count" -#~ msgstr "已存在" - -#~ msgid "Absent count" -#~ msgstr "不存在" - -#~ msgid "Succeed count" -#~ msgstr "成功" +#~ msgid "Region & Instance" +#~ msgstr "地域 & 实例" #~ msgid "Interval" #~ msgstr "间隔" diff --git a/apps/settings/utils/ldap.py b/apps/settings/utils/ldap.py index 36fe36f7f..cb11101bb 100644 --- a/apps/settings/utils/ldap.py +++ b/apps/settings/utils/ldap.py @@ -406,18 +406,18 @@ class LDAPTestUtil(object): authentication=SIMPLE, user=user, password=password ) if not ret: - msg = _('bind dn or password incorrect') + msg = _('Bind DN or Password incorrect') raise LDAPInvalidDnError(msg) def test_bind_dn(self): try: self._test_bind_dn() except LDAPUserNameIsMandatoryError as e: - error = _('Please enter bind dn: {}'.format(e)) + error = _('Please enter Bind DN: {}'.format(e)) except LDAPPasswordIsMandatoryError as e: - error = _('Please enter password: {}'.format(e)) + error = _('Please enter Password: {}'.format(e)) except LDAPInvalidDnError as e: - error = _('Please enter correct bind dn and password: {}'.format(e)) + error = _('Please enter Correct Bind DN and Password: {}'.format(e)) except Exception as e: error = _('Unknown error: {}'.format(e)) else: @@ -435,7 +435,7 @@ class LDAPTestUtil(object): user_entries = util.search_user_entries() logger.debug('Search ou: {}, count user: {}'.format(search_ou, len(user_entries))) if len(user_entries) == 0: - error = _('Invalid search ou or filter: {}'.format(search_ou)) + error = _('Invalid User OU or User search filter: {}'.format(search_ou)) raise self.LDAPInvalidSearchOuOrFilterError(error) def test_search_ou_and_filter(self): @@ -466,14 +466,14 @@ class LDAPTestUtil(object): actually_contain_attr = set(attr_map.keys()) result = should_contain_attr - actually_contain_attr if len(result) != 0: - error = _('LDAP attribute not include: {}'.format(result)) + error = _('LDAP User attr map not include: {}'.format(result)) raise self.LDAPInvalidAttributeMapError(error) def test_attr_map(self): try: self._test_attr_map() except json.JSONDecodeError: - error = _('LDAP attribute map is not dict') + error = _('LDAP User attr map is not dict') except self.LDAPInvalidAttributeMapError as e: error = e except Exception as e: @@ -510,13 +510,13 @@ class LDAPTestUtil(object): try: self._test_config() except LDAPInvalidServerError as e: - msg = _('Error (Invalid server uri): {}'.format(e)) + msg = _('Error (Invalid LDAP server): {}'.format(e)) except LDAPBindError as e: - msg = _('Error (Invalid bind dn): {}'.format(e)) + msg = _('Error (Invalid Bind DN): {}'.format(e)) except self.LDAPInvalidAttributeMapError as e: - msg = _('Error (Invalid attribute map): {}'.format(e)) + msg = _('Error (Invalid LDAP User attr map): {}'.format(e)) except self.LDAPInvalidSearchOuOrFilterError as e: - msg = _('Error (Invalid search ou or filter): {}'.format(e)) + msg = _('Error (Invalid User OU or User search filter): {}'.format(e)) except self.LDAPNotEnabledAuthError as e: msg = _('Error (Not enabled LDAP authentication): {}'.format(e)) except Exception as e: From 04945809a556069b31a4c3ee9a79018f29ef56a4 Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 13 Mar 2020 12:33:09 +0800 Subject: [PATCH 05/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E5=8F=AA?= =?UTF-8?q?=E6=9C=89local=E7=94=A8=E6=88=B7=E9=9C=80=E8=A6=81=E5=8F=91?= =?UTF-8?q?=E9=80=81=E5=88=9B=E5=BB=BA=E6=88=90=E5=8A=9F=E9=82=AE=E4=BB=B6?= =?UTF-8?q?=E3=80=81=E5=8F=91=E9=80=81=E5=AF=86=E7=A0=81=E8=BF=87=E6=9C=9F?= =?UTF-8?q?=E9=82=AE=E4=BB=B6=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/users/models/user.py | 5 +++++ apps/users/signals_handler.py | 2 +- apps/users/tasks.py | 6 ++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 21cc9bf03..b696795a8 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -596,6 +596,11 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): user.save() user.groups.add(UserGroup.initial()) + def can_send_created_mail(self): + if self.email and self.source == self.SOURCE_LOCAL: + return True + return False + @classmethod def generate_fake(cls, count=100): from random import seed, choice diff --git a/apps/users/signals_handler.py b/apps/users/signals_handler.py index 45c03f3cf..aa1458c7d 100644 --- a/apps/users/signals_handler.py +++ b/apps/users/signals_handler.py @@ -17,7 +17,7 @@ def on_user_create(sender, user=None, **kwargs): logger.debug("Receive user `{}` create signal".format(user.name)) from .utils import send_user_created_mail logger.info(" - Sending welcome mail ...".format(user.name)) - if user.email: + if user.can_send_created_mail(): send_user_created_mail(user) diff --git a/apps/users/tasks.py b/apps/users/tasks.py index 45e1c40cd..5c7bc0e47 100644 --- a/apps/users/tasks.py +++ b/apps/users/tasks.py @@ -22,15 +22,15 @@ logger = get_logger(__file__) @shared_task def check_password_expired(): - users = User.objects.exclude(role=User.ROLE_APP) + users = User.objects.filter(source=User.SOURCE_LOCAL).exclude(role=User.ROLE_APP) for user in users: if not user.is_valid: continue if not user.password_will_expired: continue - send_password_expiration_reminder_mail(user) msg = "The user {} password expires in {} days" logger.info(msg.format(user, user.password_expired_remain_days)) + send_password_expiration_reminder_mail(user) @shared_task @@ -55,6 +55,8 @@ def check_user_expired(): continue if not user.will_expired: continue + msg = "The user {} will expires in {} days" + logger.info(msg.format(user, user.expired_remain_days)) send_user_expiration_reminder_mail(user) From 0682f4fc90bf6f52056244d1e22b2377f42e24d8 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 13 Mar 2020 13:57:21 +0800 Subject: [PATCH 06/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/README.md b/README.md index 50fc97533..7de6a3f60 100644 --- a/README.md +++ b/README.md @@ -182,13 +182,6 @@ JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向 - [演示视频](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) -## SDK - -我们编写了一些SDK,供您的其它系统快速和 JumpServer API 交互: - -- [Python](https://github.com/jumpserver/jumpserver-python-sdk) JumpServer 其它组件使用这个 SDK 完成交互 -- [Java](https://github.com/KaiJunYan/jumpserver-java-sdk.git) 恺珺同学提供的 Java 版本的 SDK - ## License & Copyright Copyright (c) 2014-2019 飞致云 FIT2CLOUD, All rights reserved. From 3138abb00cd44c0504aa4fd6bc8e11f531d9a37d Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 16 Mar 2020 14:18:29 +0800 Subject: [PATCH 07/32] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8Dops=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E4=BB=BB=E5=8A=A1=E6=97=A0=E6=B3=95=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/models/adhoc.py | 2 +- apps/ops/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ops/models/adhoc.py b/apps/ops/models/adhoc.py index 01d1e1adb..faa3ac01f 100644 --- a/apps/ops/models/adhoc.py +++ b/apps/ops/models/adhoc.py @@ -206,7 +206,7 @@ class AdHoc(OrgModelMixin): def __str__(self): return "{} of {}".format(self.task.name, self.short_id) - def __eq__(self, other): + def same_with(self, other): if not isinstance(other, self.__class__): return False fields_check = [] diff --git a/apps/ops/utils.py b/apps/ops/utils.py index 16ba8e648..81b5a1afd 100644 --- a/apps/ops/utils.py +++ b/apps/ops/utils.py @@ -56,7 +56,7 @@ def update_or_create_ansible_task( new_hosts = set([str(asset.id) for asset in hosts]) hosts_same = old_hosts == new_hosts - if not adhoc or adhoc != new_adhoc or not hosts_same: + if not adhoc or not adhoc.same_with(new_adhoc) or not hosts_same: logger.debug(_("Update task content: {}").format(task_name)) new_adhoc.save() new_adhoc.hosts.set(hosts) From 2f9598ba49631374a03b7066f40c8ef57c1e6d9a Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 16 Mar 2020 14:41:24 +0800 Subject: [PATCH 08/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E5=A4=8Dops=20task?= =?UTF-8?q?=E4=B8=AD=E4=BB=BB=E5=8A=A1=E6=9F=90=E7=89=88=E6=9C=AC=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/urls/view_urls.py | 2 +- apps/ops/views/adhoc.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ops/urls/view_urls.py b/apps/ops/urls/view_urls.py index 592ae9d93..f17fb8662 100644 --- a/apps/ops/urls/view_urls.py +++ b/apps/ops/urls/view_urls.py @@ -15,7 +15,7 @@ urlpatterns = [ path('task//adhoc/', views.TaskAdhocView.as_view(), name='task-adhoc'), path('task//executions/', views.TaskExecutionView.as_view(), name='task-execution'), path('adhoc//', views.AdHocDetailView.as_view(), name='adhoc-detail'), - path('adhoc//executions/', views.AdHocExecutionView.as_view(), name='adhoc-history'), + path('adhoc//executions/', views.AdHocExecutionView.as_view(), name='adhoc-execution'), path('adhoc/executions//', views.AdHocExecutionDetailView.as_view(), name='adhoc-execution-detail'), path('celery/task//log/', views.CeleryTaskLogView.as_view(), name='celery-task-log'), diff --git a/apps/ops/views/adhoc.py b/apps/ops/views/adhoc.py index b8d90f092..e21c7b575 100644 --- a/apps/ops/views/adhoc.py +++ b/apps/ops/views/adhoc.py @@ -89,7 +89,7 @@ class AdHocDetailView(PermissionsMixin, DetailView): def get_context_data(self, **kwargs): context = { 'app': _('Ops'), - 'action': 'Task version detail', + 'action': _('Task detail'), } kwargs.update(context) return super().get_context_data(**kwargs) From 00b3c7c9459ac955733d9beb0024ab6d0038fb0b Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 16 Mar 2020 15:23:15 +0800 Subject: [PATCH 09/32] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8D=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E6=89=B9=E9=87=8F=E5=91=BD=E4=BB=A4=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/inventory.py | 4 ++-- apps/ops/models/command.py | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/ops/inventory.py b/apps/ops/inventory.py index 59179b5c7..b0fe5f8ef 100644 --- a/apps/ops/inventory.py +++ b/apps/ops/inventory.py @@ -92,7 +92,7 @@ class JMSInventory(JMSBaseInventory): for asset in assets: host = self.convert_to_ansible(asset, run_as_admin=run_as_admin) - if run_as: + if run_as is not None: run_user_info = self.get_run_user_info(host) host.update(run_user_info) if become_info and asset.is_unixlike(): @@ -104,7 +104,7 @@ class JMSInventory(JMSBaseInventory): def get_run_user_info(self, host): from assets.backends import AssetUserManager - if not self.run_as: + if self.run_as is None: return {} try: diff --git a/apps/ops/models/command.py b/apps/ops/models/command.py index 53aeff2b9..662131bc5 100644 --- a/apps/ops/models/command.py +++ b/apps/ops/models/command.py @@ -33,7 +33,12 @@ class CommandExecution(OrgModelMixin): @property def inventory(self): - return JMSInventory(self.hosts.all(), run_as=self.run_as.username) + if self.run_as.username_same_with_user: + username = self.user.username + else: + username = self.run_as.username + inv = JMSInventory(self.hosts.all(), run_as=username) + return inv @property def result(self): From 02a901467b00880402045ca2b14498f0fa318445 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 16 Mar 2020 16:13:54 +0800 Subject: [PATCH 10/32] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8D=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7=E7=99=BB=E5=BD=95?= =?UTF-8?q?windows=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/models/user.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py index 40f2b8583..bb672fff3 100644 --- a/apps/assets/models/user.py +++ b/apps/assets/models/user.py @@ -158,6 +158,12 @@ class SystemUser(BaseUser): def can_perm_to_asset(self): return self.protocol not in [self.PROTOCOL_MYSQL] + def load_asset_special_auth(self, asset=None, username=None): + instance = super().load_asset_special_auth(asset=asset, username=username) + if self.username_same_with_user: + instance.username = username + return instance + @property def cmd_filter_rules(self): from .cmd_filter import CommandFilterRule From c91ce2b99fce8cb5d2017b439f292d1b08be716f Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 16 Mar 2020 16:59:45 +0800 Subject: [PATCH 11/32] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8D=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7=E8=BF=94=E5=9B=9E?= =?UTF-8?q?auth=20info=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/models/user.py | 7 +++---- apps/assets/serializers/system_user.py | 9 ++++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/assets/models/user.py b/apps/assets/models/user.py index bb672fff3..7085a3b2b 100644 --- a/apps/assets/models/user.py +++ b/apps/assets/models/user.py @@ -158,11 +158,10 @@ class SystemUser(BaseUser): def can_perm_to_asset(self): return self.protocol not in [self.PROTOCOL_MYSQL] - def load_asset_special_auth(self, asset=None, username=None): - instance = super().load_asset_special_auth(asset=asset, username=username) + def _merge_auth(self, other): + super()._merge_auth(other) if self.username_same_with_user: - instance.username = username - return instance + self.username = other.username @property def cmd_filter_rules(self): diff --git a/apps/assets/serializers/system_user.py b/apps/assets/serializers/system_user.py index a7e413018..6a9a31b9f 100644 --- a/apps/assets/serializers/system_user.py +++ b/apps/assets/serializers/system_user.py @@ -1,5 +1,4 @@ from rest_framework import serializers - from django.utils.translation import ugettext_lazy as _ from django.db.models import Count @@ -164,6 +163,14 @@ class SystemUserListSerializer(SystemUserSerializer): class SystemUserWithAuthInfoSerializer(SystemUserSerializer): class Meta(SystemUserSerializer.Meta): + fields = [ + 'id', 'name', 'username', 'protocol', + 'password', 'public_key', 'private_key', + 'login_mode', 'login_mode_display', + 'priority', 'username_same_with_user', + 'auto_push', 'sudo', 'shell', 'comment', + 'auto_generate_key', 'sftp_root', + ] extra_kwargs = { 'nodes_amount': {'label': _('Node')}, 'assets_amount': {'label': _('Asset')}, From 55554a025f85556241fc1380e8e423a300e50d4e Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 16 Mar 2020 19:15:29 +0800 Subject: [PATCH 12/32] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8D=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=97=B6=E6=97=A0=E6=B3=95=E6=8E=A8=E9=80=81?= =?UTF-8?q?=E7=9A=84bug,=20=E4=BF=AE=E5=A4=8D=E9=80=9A=E8=BF=87relation=20?= =?UTF-8?q?api=E6=97=A0=E6=B3=95=E8=A7=A6=E5=8F=91m2m=5Fchange=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/system_user_relation.py | 40 +++++++++++++++++++++++ apps/assets/signals_handler.py | 21 +++++++++++++ apps/assets/tasks/push_system_user.py | 8 ++--- apps/perms/signals_handler.py | 42 +++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 4 deletions(-) diff --git a/apps/assets/api/system_user_relation.py b/apps/assets/api/system_user_relation.py index 02dd887a1..69605b74a 100644 --- a/apps/assets/api/system_user_relation.py +++ b/apps/assets/api/system_user_relation.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- # +from collections import defaultdict from django.db.models import F, Value +from django.db.models.signals import m2m_changed from django.db.models.functions import Concat from common.permissions import IsOrgAdmin @@ -26,6 +28,34 @@ class RelationMixin: )) return queryset + def send_post_add_signal(self, instance): + if not isinstance(instance, list): + instance = [instance] + + system_users_objects_map = defaultdict(list) + model, object_field = self.get_objects_attr() + + for i in instance: + _id = getattr(i, object_field).id + system_users_objects_map[i.systemuser].append(_id) + + sender = self.get_sender() + for system_user, objects in system_users_objects_map.items(): + m2m_changed.send( + sender=sender, instance=system_user, action='post_add', + reverse=False, model=model, pk_set=objects + ) + + def get_sender(self): + return self.model + + def get_objects_attr(self): + return models.Asset, 'asset' + + def perform_create(self, serializer): + instance = serializer.save() + self.send_post_add_signal(instance) + class BaseRelationViewSet(RelationMixin, OrgBulkModelViewSet): pass @@ -43,6 +73,9 @@ class SystemUserAssetRelationViewSet(BaseRelationViewSet): "systemuser__name", "systemuser__username" ] + def get_objects_attr(self): + return models.Asset, 'asset' + def get_queryset(self): queryset = super().get_queryset() queryset = queryset.annotate( @@ -65,6 +98,9 @@ class SystemUserNodeRelationViewSet(BaseRelationViewSet): "node__value", "systemuser__name", "systemuser_username" ] + def get_objects_attr(self): + return models.Node, 'node' + def get_queryset(self): queryset = super().get_queryset() queryset = queryset \ @@ -84,6 +120,10 @@ class SystemUserUserRelationViewSet(BaseRelationViewSet): "systemuser__name", "systemuser__username", ] + def get_objects_attr(self): + from users.models import User + return User, 'user' + def get_queryset(self): queryset = super().get_queryset() queryset = queryset.annotate( diff --git a/apps/assets/signals_handler.py b/apps/assets/signals_handler.py index 696732fc8..3bf185bc4 100644 --- a/apps/assets/signals_handler.py +++ b/apps/assets/signals_handler.py @@ -16,6 +16,8 @@ from .tasks import ( update_assets_hardware_info_util, test_asset_connectivity_util, push_system_user_to_assets, + push_system_user_to_assets_manual, + push_system_user_to_assets, add_nodes_assets_to_system_users ) @@ -95,6 +97,25 @@ def on_system_user_assets_change(sender, instance=None, action='', model=None, p push_system_user_to_assets.delay(system_user, assets) +@receiver(m2m_changed, sender=SystemUser.users.through) +def on_system_user_users_change(sender, instance=None, action='', model=None, pk_set=None, **kwargs): + """ + 当系统用户和用户关系发生变化时,应该重新推送系统用户资产中 + """ + if action != "post_add": + return + if not instance.username_same_with_user: + return + logger.debug("System user users change signal recv: {}".format(instance)) + queryset = model.objects.filter(pk__in=pk_set) + if model == SystemUser: + system_users = queryset + else: + system_users = [instance] + for s in system_users: + push_system_user_to_assets_manual.delay(s) + + @receiver(m2m_changed, sender=SystemUser.nodes.through) def on_system_user_nodes_change(sender, instance=None, action=None, model=None, pk_set=None, **kwargs): """ diff --git a/apps/assets/tasks/push_system_user.py b/apps/assets/tasks/push_system_user.py index 961f24a01..472d5de4e 100644 --- a/apps/assets/tasks/push_system_user.py +++ b/apps/assets/tasks/push_system_user.py @@ -193,10 +193,10 @@ def push_system_user_util(system_user, assets, task_name, username=None): @shared_task(queue="ansible") -def push_system_user_to_assets_manual(system_user): +def push_system_user_to_assets_manual(system_user, username=None): assets = system_user.get_related_assets() task_name = _("Push system users to assets: {}").format(system_user.name) - return push_system_user_util(system_user, assets, task_name=task_name) + return push_system_user_util(system_user, assets, task_name=task_name, username=username) @shared_task(queue="ansible") @@ -210,9 +210,9 @@ def push_system_user_a_asset_manual(system_user, asset, username=None): @shared_task(queue="ansible") -def push_system_user_to_assets(system_user, assets): +def push_system_user_to_assets(system_user, assets, username=None): task_name = _("Push system users to assets: {}").format(system_user.name) - return push_system_user_util(system_user, assets, task_name) + return push_system_user_util(system_user, assets, task_name, username=username) diff --git a/apps/perms/signals_handler.py b/apps/perms/signals_handler.py index 1be6ce9f4..7a40bcb66 100644 --- a/apps/perms/signals_handler.py +++ b/apps/perms/signals_handler.py @@ -62,6 +62,34 @@ def on_asset_permission_system_users_changed(sender, instance=None, action='', system_user.users.add(*tuple(users)) +@receiver(m2m_changed, sender=AssetPermission.users.through) +def on_asset_permission_users_changed(sender, instance=None, action='', + reverse=False, **kwargs): + if action != 'post_add' and reverse: + return + logger.debug("Asset permission users change signal received") + users = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) + system_users = instance.system_users.all() + + for system_user in system_users: + if system_user.username_same_with_user: + system_user.users.add(*tuple(users)) + + +@receiver(m2m_changed, sender=AssetPermission.user_groups.through) +def on_asset_permission_user_groups_changed(sender, instance=None, action='', + reverse=False, **kwargs): + if action != 'post_add' and reverse: + return + logger.debug("Asset permission user groups change signal received") + groups = kwargs['model'].objects.filter(pk__in=kwargs['pk_set']) + system_users = instance.system_users.all() + + for system_user in system_users: + if system_user.username_same_with_user: + system_user.groups.add(*tuple(groups)) + + @receiver(m2m_changed, sender=RemoteAppPermission.system_users.through) def on_remote_app_permission_system_users_changed(sender, instance=None, action='', reverse=False, **kwargs): @@ -77,3 +105,17 @@ def on_remote_app_permission_system_users_changed(sender, instance=None, if system_user.username_same_with_user: system_user.groups.add(*tuple(groups)) system_user.users.add(*tuple(users)) + + +@receiver(m2m_changed, sender=RemoteAppPermission.users.through) +def on_remoteapps_permission_users_changed(sender, instance=None, action='', + reverse=False, **kwargs): + on_asset_permission_users_changed(sender, instance=instance, action=action, + reverse=reverse, **kwargs) + + +@receiver(m2m_changed, sender=RemoteAppPermission.user_groups.through) +def on_remoteapps_permission_user_groups_changed(sender, instance=None, action='', + reverse=False, **kwargs): + on_asset_permission_user_groups_changed(sender, instance=instance, + action=action, reverse=reverse, **kwargs) From 672b82c3d654ed164b9ff1bc637cff806bac7aef Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 16 Mar 2020 19:24:48 +0800 Subject: [PATCH 13/32] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8D=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E6=97=A0=E6=B3=95=E6=89=BE=E5=88=B0command=20executio?= =?UTF-8?q?n=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/tasks.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/ops/tasks.py b/apps/ops/tasks.py index 33d7cb850..0967ac482 100644 --- a/apps/ops/tasks.py +++ b/apps/ops/tasks.py @@ -10,6 +10,7 @@ from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from common.utils import get_logger, get_object_or_none, get_disk_usage +from orgs.utils import tmp_to_root_org from .celery.decorator import ( register_as_period_task, after_app_shutdown_clean_periodic, after_app_ready_start @@ -44,7 +45,8 @@ def run_ansible_task(tid, callback=None, **kwargs): @shared_task(soft_time_limit=60, queue="ansible") def run_command_execution(cid, **kwargs): - execution = get_object_or_none(CommandExecution, id=cid) + with tmp_to_root_org(): + execution = get_object_or_none(CommandExecution, id=cid) if execution: try: os.environ.update({ From caee286973d1e98c3fcf43ca5c69f17aee27f038 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 17 Mar 2020 10:59:49 +0800 Subject: [PATCH 14/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E5=8D=8E?= =?UTF-8?q?=E4=B8=BA=E4=BA=91=E5=A7=8B=E7=BB=88=E6=9C=89=E6=95=88=E7=9A=84?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset_user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/api/asset_user.py b/apps/assets/api/asset_user.py index ce5930a26..c0d834737 100644 --- a/apps/assets/api/asset_user.py +++ b/apps/assets/api/asset_user.py @@ -105,7 +105,7 @@ class AssetUserViewSet(CommonApiMixin, BulkModelViewSet): class AssetUserAuthInfoViewSet(AssetUserViewSet): serializer_classes = {"default": serializers.AssetUserAuthInfoSerializer} - http_method_names = ['get'] + http_method_names = ['get', 'post'] permission_classes = [IsOrgAdminOrAppUser] def get_permissions(self): From 8e84efb2963c879849cb95cb715c6b17e01e3645 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 17 Mar 2020 13:51:41 +0800 Subject: [PATCH 15/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E6=96=87=E6=A1=88=E5=92=8C=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/backends/db.py | 5 +-- apps/locale/zh/LC_MESSAGES/django.mo | Bin 88260 -> 88806 bytes apps/locale/zh/LC_MESSAGES/django.po | 34 +++++++++++------- .../templates/terminal/session_detail.html | 2 +- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/apps/assets/backends/db.py b/apps/assets/backends/db.py index 7cdba2754..35be8b9fd 100644 --- a/apps/assets/backends/db.py +++ b/apps/assets/backends/db.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # +from django.utils.translation import ugettext as _ from functools import reduce from django.db.models import F, CharField, Value, IntegerField, Q, Count from django.db.models.functions import Concat @@ -240,7 +241,7 @@ class AdminUserBackend(DBBackend): ) def _perform_delete_by_union_id(self, union_id_cleaned): - raise PermissionError("Could remove asset admin user") + raise PermissionError(_("Could not remove asset admin user")) def all(self): qs = self.model.objects.all().annotate( @@ -301,7 +302,7 @@ class AuthbookBackend(DBBackend): authbook_id, asset_id = union_id_cleaned authbook = get_object_or_none(AuthBook, pk=authbook_id) if authbook.is_latest: - raise PermissionError("Latest version could be delete") + raise PermissionError(_("Latest version could not be delete")) AuthBook.objects.filter(id=authbook_id).delete() def all(self): diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index f9e23c2815041175cc8508df4de51afe51ad7646..b952d9ab4f927284d0409b7b1971b1108d3c5829 100644 GIT binary patch delta 27492 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 J^Nh&;e*pc`hQ|N^ delta 26858 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 cB|Z0nEA`7t2&Z4FPi diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 7356b96e3..27dc9addd 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-03-12 17:27+0800\n" +"POT-Creation-Date: 2020-03-17 13:50+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -535,7 +535,7 @@ msgstr "详情" #: xpack/plugins/cloud/templates/cloud/account_detail.html:20 #: xpack/plugins/cloud/templates/cloud/account_list.html:40 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:26 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:57 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:60 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:46 #: xpack/plugins/orgs/templates/orgs/org_detail.html:20 #: xpack/plugins/orgs/templates/orgs/org_list.html:93 @@ -587,7 +587,7 @@ msgstr "更新" #: xpack/plugins/cloud/templates/cloud/account_detail.html:24 #: xpack/plugins/cloud/templates/cloud/account_list.html:42 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:30 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:58 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:61 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:47 #: xpack/plugins/orgs/templates/orgs/org_detail.html:24 #: xpack/plugins/orgs/templates/orgs/org_list.html:95 @@ -727,6 +727,14 @@ msgstr "不能修改根节点名称" msgid "Deletion failed and the node contains children or assets" msgstr "删除失败,节点包含子节点或资产" +#: assets/backends/db.py:244 +msgid "Could not remove asset admin user" +msgstr "不能移除资产的管理用户账号" + +#: assets/backends/db.py:305 +msgid "Latest version could not be delete" +msgstr "最新版本的不能被删除" + #: assets/forms/asset.py:83 assets/models/asset.py:196 #: assets/models/user.py:109 assets/templates/assets/asset_detail.html:186 #: assets/templates/assets/asset_detail.html:194 @@ -3169,23 +3177,23 @@ msgstr "{} 任务结束" msgid "Result" msgstr "结果" -#: ops/models/command.py:59 +#: ops/models/command.py:64 msgid "Task start" msgstr "任务开始" -#: ops/models/command.py:81 +#: ops/models/command.py:86 msgid "Command `{}` is forbidden ........" msgstr "命令 `{}` 不允许被执行 ......." -#: ops/models/command.py:88 +#: ops/models/command.py:93 msgid "Task end" msgstr "任务结束" -#: ops/tasks.py:63 +#: ops/tasks.py:65 msgid "Clean task history period" msgstr "定期清除任务历史" -#: ops/tasks.py:76 +#: ops/tasks.py:78 msgid "Clean celery log period" msgstr "定期清除Celery日志" @@ -3349,6 +3357,7 @@ msgstr "结束" #: ops/templates/ops/task_adhoc.html:17 ops/templates/ops/task_detail.html:18 #: ops/templates/ops/task_history.html:17 ops/views/adhoc.py:50 +#: ops/views/adhoc.py:92 msgid "Task detail" msgstr "任务详情" @@ -3383,7 +3392,7 @@ msgstr "内容" #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:135 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:54 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:138 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:55 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:58 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:44 msgid "Run" msgstr "执行" @@ -4261,7 +4270,9 @@ msgid "Please enter Password: {}" msgstr "请输入密码: {}" #: settings/utils/ldap.py:420 -msgid "Please enter correct Bind DN and Password: {}" +#, fuzzy +#| msgid "Please enter correct Bind DN and Password: {}" +msgid "Please enter Correct Bind DN and Password: {}" msgstr "请输入正确的绑定DN和密码: {}" #: settings/utils/ldap.py:438 @@ -4970,7 +4981,6 @@ msgid "Session detail" msgstr "会话详情" #: terminal/templates/terminal/session_commands.html:29 -#: terminal/templates/terminal/session_detail.html:29 #: terminal/views/command.py:22 msgid "Command list" msgstr "命令记录列表" @@ -6575,7 +6585,7 @@ msgid "Run task manually" msgstr "手动执行任务" #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:178 -#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:99 +#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:102 msgid "Sync success" msgstr "同步成功" diff --git a/apps/terminal/templates/terminal/session_detail.html b/apps/terminal/templates/terminal/session_detail.html index 26ec1c785..1863ad75f 100644 --- a/apps/terminal/templates/terminal/session_detail.html +++ b/apps/terminal/templates/terminal/session_detail.html @@ -26,7 +26,7 @@
          {% trans 'Created by' %}:{{ asset_group.created_by }}{{ admin_user.created_by }}
          {% trans 'Comment' %}:{% trans 'Date created' %}: {{ object.date_created }}
          {% trans 'Created by' %}:{{ object.created_by }}
          {% trans 'Comment' %}: {{ object.comment }}
          {% trans 'Created by' %}:{{ asset_group.created_by }}{{ system_user.created_by }}
          {% trans 'Comment' %}:
          OpenID 认证(实现单点登录)
          CSA 认证 (实现单点登录)
          MFA认证 MFA 二次认证(Google Authenticator)
          - + From b801d2f2e9c621388a312631c97a12aef0136724 Mon Sep 17 00:00:00 2001 From: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Date: Wed, 18 Mar 2020 17:16:53 +0800 Subject: [PATCH 27/32] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c7edb0d41..76465a36e 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向 - + From a41988d2b579ce775ec70736eced0ddd3cbb1414 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 18 Mar 2020 19:10:27 +0800 Subject: [PATCH 28/32] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E6=94=B9=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=87=E4=BB=B6=EF=BC=8C=E6=94=AF=E6=8C=81cas=20pro?= =?UTF-8?q?xy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/conf.py | 3 ++- apps/jumpserver/settings/auth.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index bfed4ec9d..9beb2954a 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -142,6 +142,7 @@ class Config(dict): 'AUTH_OPENID_CLIENT_SECRET': '', 'AUTH_OPENID_IGNORE_SSL_VERIFICATION': True, 'AUTH_OPENID_SHARE_SESSION': True, + 'CAS_ROOT_PROXIED_AS': '', 'AUTH_RADIUS': False, 'RADIUS_SERVER': 'localhost', @@ -152,7 +153,7 @@ class Config(dict): 'AUTH_CAS': False, 'CAS_SERVER_URL': "http://host/cas/", - 'CAS_LOGOUT_COMPLETELY': False, + 'CAS_LOGOUT_COMPLETELY': True, 'CAS_VERSION': 3, 'OTP_VALID_WINDOW': 2, diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index e6245d02c..bad698e4c 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -74,6 +74,7 @@ CAS_LOGIN_MSG = None CAS_LOGGED_MSG = None CAS_LOGOUT_COMPLETELY = CONFIG.CAS_LOGOUT_COMPLETELY CAS_VERSION = CONFIG.CAS_VERSION +CAS_ROOT_PROXIED_AS = CONFIG.CAS_ROOT_PROXIED_AS # Other setting From d0fac3f83829b60cdf5bef6f0876512902a56c7e Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 18 Mar 2020 19:58:08 +0800 Subject: [PATCH 29/32] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8Dtask=20?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E3=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/models/adhoc.py | 1 + apps/ops/serializers/adhoc.py | 5 +++-- apps/ops/templates/ops/task_list.html | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/ops/models/adhoc.py b/apps/ops/models/adhoc.py index faa3ac01f..c29493fb2 100644 --- a/apps/ops/models/adhoc.py +++ b/apps/ops/models/adhoc.py @@ -182,6 +182,7 @@ class AdHoc(OrgModelMixin): id=hid, adhoc=self, task=self.task, task_display=str(self.task), date_start=timezone.now(), + hosts_amount=self.hosts.count(), ) execution.save() return execution.start() diff --git a/apps/ops/serializers/adhoc.py b/apps/ops/serializers/adhoc.py index 60fd39f90..afdd659fc 100644 --- a/apps/ops/serializers/adhoc.py +++ b/apps/ops/serializers/adhoc.py @@ -39,6 +39,7 @@ class AdHocExecutionExcludeResultSerializer(AdHocExecutionSerializer): class TaskSerializer(serializers.ModelSerializer): + summary = serializers.ReadOnlyField(source='history_summary') latest_execution = AdHocExecutionExcludeResultSerializer(read_only=True) class Meta: @@ -46,12 +47,12 @@ class TaskSerializer(serializers.ModelSerializer): fields = [ 'id', 'name', 'interval', 'crontab', 'is_periodic', 'is_deleted', 'comment', 'date_created', - 'date_updated', 'latest_execution', + 'date_updated', 'latest_execution', 'summary', ] read_only_fields = [ 'is_deleted', 'date_created', 'date_updated', 'latest_adhoc', 'latest_execution', 'total_run_amount', - 'success_run_amount', + 'success_run_amount', 'summary', ] diff --git a/apps/ops/templates/ops/task_list.html b/apps/ops/templates/ops/task_list.html index 6f393cb1c..a004138df 100644 --- a/apps/ops/templates/ops/task_list.html +++ b/apps/ops/templates/ops/task_list.html @@ -35,7 +35,7 @@ $(document).ready(function () { $(td).html(innerHtml); }}, {targets: 2, createdCell: function (td, cellData) { - var summary = cellData ? cellData.stat : {failed: 0, success: 0, total: 0}; + var summary = cellData || {failed: 0, success: 0, total: 0}; var innerHtml = 'failed/success/total'; innerHtml = innerHtml.replace('failed', summary.failed) .replace('success', summary.success) @@ -79,7 +79,7 @@ $(document).ready(function () { ajax_url: '{% url "api-ops:task-list" %}', columns: [ {data: "id"}, {data: "name", className: "text-left"}, - {data: "latest_execution", orderable: false}, + {data: "summary", orderable: false}, {data: "latest_execution", orderable: false}, {data: "latest_execution", orderable: false}, {data: "latest_execution"}, {data: "latest_execution", orderable:false}, {data: "id", orderable: false}, From 98f6d0146c8bbd57fcb7265db309653a99c2122b Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 19 Mar 2020 10:21:19 +0800 Subject: [PATCH 30/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E7=A7=BB=E9=99=A4=E8=8A=82=E7=82=B9=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E8=8A=82=E7=82=B9=E7=BB=99=E5=87=BA=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/templates/assets/asset_list.html | 1 + apps/locale/zh/LC_MESSAGES/django.po | 85 ++++++++++---------- apps/settings/utils/ldap.py | 2 +- 3 files changed, 45 insertions(+), 43 deletions(-) diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html index 24a789404..2eeda8f69 100644 --- a/apps/assets/templates/assets/asset_list.html +++ b/apps/assets/templates/assets/asset_list.html @@ -307,6 +307,7 @@ $(document).ready(function(){ function doRemove() { if (!current_node_id) { + toastr.error("{% trans 'Please select node' %}"); return } diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 27dc9addd..1a79d4c44 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-03-17 13:50+0800\n" +"POT-Creation-Date: 2020-03-18 17:58+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -29,7 +29,7 @@ msgstr "自定义" #: assets/models/asset.py:353 assets/models/authbook.py:23 #: assets/models/gathered_user.py:14 assets/serializers/admin_user.py:32 #: assets/serializers/asset_user.py:48 assets/serializers/asset_user.py:85 -#: assets/serializers/system_user.py:45 assets/serializers/system_user.py:169 +#: assets/serializers/system_user.py:44 assets/serializers/system_user.py:176 #: assets/templates/assets/admin_user_list.html:23 #: assets/templates/assets/asset_list.html:170 #: assets/templates/assets/domain_detail.html:55 @@ -236,7 +236,7 @@ msgstr "数据库" #: assets/templates/assets/cmd_filter_detail.html:60 #: assets/templates/assets/cmd_filter_list.html:25 #: assets/templates/assets/cmd_filter_rule_list.html:57 -#: assets/templates/assets/domain_detail.html:71 +#: assets/templates/assets/domain_detail.html:67 #: assets/templates/assets/domain_gateway_list.html:67 #: assets/templates/assets/domain_list.html:24 #: assets/templates/assets/platform_detail.html:64 @@ -313,7 +313,6 @@ msgstr "参数" #: assets/templates/assets/admin_user_detail.html:63 #: assets/templates/assets/asset_detail.html:120 #: assets/templates/assets/cmd_filter_detail.html:72 -#: assets/templates/assets/domain_detail.html:67 #: assets/templates/assets/system_user_detail.html:108 #: common/mixins/models.py:49 ops/templates/ops/adhoc_detail.html:84 #: orgs/models.py:16 perms/models/base.py:54 @@ -500,7 +499,7 @@ msgstr "详情" #: assets/templates/assets/cmd_filter_list.html:56 #: assets/templates/assets/cmd_filter_rule_list.html:81 #: assets/templates/assets/domain_detail.html:19 -#: assets/templates/assets/domain_detail.html:98 +#: assets/templates/assets/domain_detail.html:94 #: assets/templates/assets/domain_gateway_list.html:92 #: assets/templates/assets/domain_list.html:50 #: assets/templates/assets/label_list.html:39 @@ -555,7 +554,7 @@ msgstr "更新" #: assets/templates/assets/cmd_filter_list.html:57 #: assets/templates/assets/cmd_filter_rule_list.html:82 #: assets/templates/assets/domain_detail.html:23 -#: assets/templates/assets/domain_detail.html:99 +#: assets/templates/assets/domain_detail.html:95 #: assets/templates/assets/domain_gateway_list.html:93 #: assets/templates/assets/domain_list.html:51 #: assets/templates/assets/label_list.html:40 @@ -780,7 +779,7 @@ msgid "Platform" msgstr "系统平台" #: assets/forms/asset.py:99 assets/forms/asset.py:134 assets/models/node.py:497 -#: assets/serializers/system_user.py:44 assets/serializers/system_user.py:168 +#: assets/serializers/system_user.py:43 assets/serializers/system_user.py:175 #: assets/templates/assets/asset_create.html:42 #: perms/forms/asset_permission.py:92 perms/forms/asset_permission.py:99 #: perms/templates/perms/asset_permission_list.html:36 @@ -1032,7 +1031,7 @@ msgstr "主机名" #: assets/templates/assets/domain_gateway_list.html:65 #: assets/templates/assets/system_user_detail.html:78 #: assets/templates/assets/system_user_list.html:26 -#: terminal/forms/storage.py:152 +#: terminal/forms/storage.py:145 #: terminal/templates/terminal/session_detail.html:60 #: terminal/templates/terminal/session_list.html:29 #: terminal/templates/terminal/session_list.html:73 @@ -1441,7 +1440,7 @@ msgstr "登录模式" msgid "SFTP Root" msgstr "SFTP根路径" -#: assets/models/user.py:190 assets/templates/assets/system_user_list.html:73 +#: 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/templates/audits/ftp_log_list.html:76 @@ -1556,23 +1555,23 @@ msgstr "值" msgid "The same level node name cannot be the same" msgstr "同级别节点名字不能重复" -#: assets/serializers/system_user.py:46 assets/serializers/system_user.py:170 +#: assets/serializers/system_user.py:45 assets/serializers/system_user.py:177 msgid "Login mode display" msgstr "登录模式显示" -#: assets/serializers/system_user.py:86 +#: assets/serializers/system_user.py:85 msgid "Username same with user with protocol {} only allow 1" msgstr "用户名和用户相同的一种协议只允许存在一个" -#: assets/serializers/system_user.py:99 +#: assets/serializers/system_user.py:98 msgid "* Automatic login mode must fill in the username." msgstr "自动登录模式,必须填写用户名" -#: assets/serializers/system_user.py:107 +#: assets/serializers/system_user.py:106 msgid "Path should starts with /" msgstr "路径应该以 / 开头" -#: assets/serializers/system_user.py:118 +#: assets/serializers/system_user.py:117 msgid "Password or private key required" msgstr "密码或密钥密码需要一个" @@ -1624,25 +1623,25 @@ msgstr "更新节点资产硬件信息: {}" msgid "Gather assets users" msgstr "收集资产上的用户" -#: assets/tasks/push_system_user.py:149 +#: assets/tasks/push_system_user.py:148 #: assets/tasks/system_user_connectivity.py:86 msgid "System user is dynamic: {}" msgstr "系统用户是动态的: {}" -#: assets/tasks/push_system_user.py:180 +#: assets/tasks/push_system_user.py:179 msgid "Start push system user for platform: [{}]" msgstr "推送系统用户到平台: [{}]" -#: assets/tasks/push_system_user.py:181 +#: assets/tasks/push_system_user.py:180 #: assets/tasks/system_user_connectivity.py:78 msgid "Hosts count: {}" msgstr "主机数量: {}" -#: assets/tasks/push_system_user.py:198 assets/tasks/push_system_user.py:214 +#: assets/tasks/push_system_user.py:197 assets/tasks/push_system_user.py:213 msgid "Push system users to assets: {}" msgstr "推送系统用户到入资产: {}" -#: assets/tasks/push_system_user.py:206 +#: assets/tasks/push_system_user.py:205 msgid "Push system users to asset: {}({}) => {}" msgstr "推送系统用户到入资产: {}({}) => {}" @@ -2135,18 +2134,22 @@ msgstr "删除选择资产" msgid "Cancel" msgstr "取消" -#: assets/templates/assets/asset_list.html:267 -msgid "Asset Deleted." -msgstr "已被删除" +#: assets/templates/assets/asset_list.html:262 +msgid "Asset Deleting failed." +msgstr "删除失败" -#: assets/templates/assets/asset_list.html:268 -#: assets/templates/assets/asset_list.html:276 +#: assets/templates/assets/asset_list.html:263 +#: assets/templates/assets/asset_list.html:272 msgid "Asset Delete" msgstr "删除" -#: assets/templates/assets/asset_list.html:275 -msgid "Asset Deleting failed." -msgstr "删除失败" +#: assets/templates/assets/asset_list.html:271 +msgid "Asset Deleted." +msgstr "已被删除" + +#: assets/templates/assets/asset_list.html:310 +msgid "Please select node" +msgstr "请选择节点" #: assets/templates/assets/asset_update.html:7 msgid "Configuration" @@ -3189,11 +3192,11 @@ msgstr "命令 `{}` 不允许被执行 ......." msgid "Task end" msgstr "任务结束" -#: ops/tasks.py:65 +#: ops/tasks.py:68 msgid "Clean task history period" msgstr "定期清除任务历史" -#: ops/tasks.py:78 +#: ops/tasks.py:81 msgid "Clean celery log period" msgstr "定期清除Celery日志" @@ -3210,7 +3213,7 @@ msgstr "执行历史" #: ops/templates/ops/adhoc_detail.html:51 #: ops/templates/ops/command_execution_list.html:65 #: ops/templates/ops/task_adhoc.html:57 ops/templates/ops/task_list.html:13 -#: terminal/forms/storage.py:158 +#: terminal/forms/storage.py:151 msgid "Hosts" msgstr "主机" @@ -4270,9 +4273,7 @@ msgid "Please enter Password: {}" msgstr "请输入密码: {}" #: settings/utils/ldap.py:420 -#, fuzzy -#| msgid "Please enter correct Bind DN and Password: {}" -msgid "Please enter Correct Bind DN and Password: {}" +msgid "Please enter correct Bind DN and Password: {}" msgstr "请输入正确的绑定DN和密码: {}" #: settings/utils/ldap.py:438 @@ -4821,22 +4822,22 @@ msgid "Endpoint suffix" msgstr "端点后缀" #: terminal/forms/storage.py:61 terminal/forms/storage.py:84 -#: terminal/forms/storage.py:108 terminal/forms/storage.py:132 +#: terminal/forms/storage.py:108 terminal/forms/storage.py:125 msgid "Bucket" msgstr "桶名称" #: terminal/forms/storage.py:64 terminal/forms/storage.py:87 -#: terminal/forms/storage.py:111 terminal/forms/storage.py:135 +#: terminal/forms/storage.py:111 terminal/forms/storage.py:128 msgid "Access key" msgstr "" #: terminal/forms/storage.py:68 terminal/forms/storage.py:91 -#: terminal/forms/storage.py:115 terminal/forms/storage.py:139 +#: terminal/forms/storage.py:115 terminal/forms/storage.py:132 msgid "Secret key" msgstr "" #: terminal/forms/storage.py:72 terminal/forms/storage.py:95 -#: terminal/forms/storage.py:119 terminal/forms/storage.py:146 +#: terminal/forms/storage.py:119 terminal/forms/storage.py:139 msgid "Endpoint" msgstr "端点" @@ -4849,7 +4850,7 @@ msgid "" " " msgstr "" -#: terminal/forms/storage.py:97 terminal/forms/storage.py:121 +#: terminal/forms/storage.py:97 #, python-brace-format msgid "" "\n" @@ -4859,14 +4860,14 @@ msgid "" " " msgstr "" -#: terminal/forms/storage.py:143 xpack/plugins/cloud/models.py:263 +#: terminal/forms/storage.py:136 xpack/plugins/cloud/models.py:263 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:29 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:106 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:46 msgid "Region" msgstr "地域" -#: terminal/forms/storage.py:160 +#: terminal/forms/storage.py:153 msgid "" "\n" " Tips: If there are multiple hosts, separate them with a comma " @@ -4881,11 +4882,11 @@ msgstr "" " eg: http://www.jumpserver.a.com,http://www.jumpserver.b.com\n" " " -#: terminal/forms/storage.py:168 +#: terminal/forms/storage.py:161 msgid "Index" msgstr "索引" -#: terminal/forms/storage.py:171 +#: terminal/forms/storage.py:164 msgid "Doc type" msgstr "文档类型" diff --git a/apps/settings/utils/ldap.py b/apps/settings/utils/ldap.py index cb11101bb..bfb8754f2 100644 --- a/apps/settings/utils/ldap.py +++ b/apps/settings/utils/ldap.py @@ -417,7 +417,7 @@ class LDAPTestUtil(object): except LDAPPasswordIsMandatoryError as e: error = _('Please enter Password: {}'.format(e)) except LDAPInvalidDnError as e: - error = _('Please enter Correct Bind DN and Password: {}'.format(e)) + error = _('Please enter correct Bind DN and Password: {}'.format(e)) except Exception as e: error = _('Unknown error: {}'.format(e)) else: From 7cf000262d56024b9f3be139783836e857874362 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 19 Mar 2020 11:11:18 +0800 Subject: [PATCH 31/32] =?UTF-8?q?[Update]=20django=20cas=20ng=20=E9=80=80?= =?UTF-8?q?=E5=87=BA=E9=80=BB=E8=BE=91=E6=9C=89=E9=97=AE=E9=A2=98=EF=BC=8C?= =?UTF-8?q?=E6=9A=82=E6=97=B6=E5=B1=8F=E8=94=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/views/login.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/authentication/views/login.py b/apps/authentication/views/login.py index 8310b4c8b..c51ccbfc6 100644 --- a/apps/authentication/views/login.py +++ b/apps/authentication/views/login.py @@ -185,8 +185,8 @@ class UserLogoutView(TemplateView): @staticmethod def get_backend_logout_url(): - if settings.AUTH_CAS: - return settings.CAS_LOGOUT_URL_NAME + # if settings.AUTH_CAS: + # return settings.CAS_LOGOUT_URL_NAME return None def get(self, request, *args, **kwargs): From b8d0272e371ddcac0ee245e6a417b2af35a9843c Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 19 Mar 2020 11:47:39 +0800 Subject: [PATCH 32/32] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/tasks/system_user_connectivity.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/assets/tasks/system_user_connectivity.py b/apps/assets/tasks/system_user_connectivity.py index 4b3a80b2c..96ba2ec4d 100644 --- a/apps/assets/tasks/system_user_connectivity.py +++ b/apps/assets/tasks/system_user_connectivity.py @@ -50,8 +50,8 @@ def test_system_user_connectivity_util(system_user, assets, task_name): ) def run_task(_tasks, _hosts, _username): - old_name = "({})".format(system_user.username) - new_name = "({})".format(_username) + old_name = "{}".format(system_user) + new_name = "{}({})".format(system_user.name, _username) _task_name = task_name.replace(old_name, new_name) _task, created = update_or_create_ansible_task( task_name=_task_name, hosts=_hosts, tasks=_tasks,
          身份认证
          Authentication
          登录认证登录认证 资源统一登录与认证
          OpenID 认证(实现单点登录)
          CSA 认证 (实现单点登录)CAS 认证 (实现单点登录)
          MFA认证