diff --git a/apps/jumpserver/api.py b/apps/jumpserver/api.py index 02fb8ba8e..fd580093e 100644 --- a/apps/jumpserver/api.py +++ b/apps/jumpserver/api.py @@ -36,7 +36,7 @@ class MonthLoginMetricMixin: @staticmethod def get_cache_key(date, tp): date_str = date.strftime("%Y%m%d") - key = "SESSION_MONTH_{}_{}".format(tp, date_str) + key = "SESSION_MONTH_{}_{}_{}".format(current_org.id, tp, date_str) return key def __get_data_from_cache(self, date, tp): diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 91ecbb8b2..0b752ed50 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-05-11 13:59+0800\n" +"POT-Creation-Date: 2020-05-11 16:53+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -26,7 +26,7 @@ msgstr "自定义" #: applications/templates/applications/remote_app_list.html:27 #: applications/templates/applications/user_remote_app_list.html:18 #: assets/forms/domain.py:15 assets/forms/label.py:13 -#: assets/models/asset.py:352 assets/models/authbook.py:27 +#: assets/models/asset.py:353 assets/models/authbook.py:27 #: assets/models/gathered_user.py:14 assets/serializers/admin_user.py:32 #: assets/serializers/asset_user.py:47 assets/serializers/asset_user.py:84 #: assets/serializers/system_user.py:44 assets/serializers/system_user.py:176 @@ -112,7 +112,7 @@ msgstr "运行参数" #: applications/templates/applications/user_database_app_list.html:16 #: applications/templates/applications/user_remote_app_list.html:16 #: assets/forms/asset.py:21 assets/forms/domain.py:77 assets/forms/user.py:74 -#: assets/forms/user.py:96 assets/models/asset.py:145 assets/models/base.py:232 +#: 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 @@ -204,7 +204,7 @@ msgstr "主机" #: applications/models/database_app.py:27 #: applications/templates/applications/database_app_detail.html:60 #: applications/templates/applications/database_app_list.html:26 -#: assets/forms/asset.py:25 assets/models/asset.py:191 +#: 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" @@ -227,7 +227,7 @@ msgstr "数据库" #: applications/templates/applications/remote_app_list.html:28 #: applications/templates/applications/user_database_app_list.html:20 #: applications/templates/applications/user_remote_app_list.html:19 -#: assets/models/asset.py:150 assets/models/asset.py:226 +#: 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 @@ -309,7 +309,7 @@ msgstr "参数" #: applications/models/remote_app.py:39 #: applications/templates/applications/database_app_detail.html:72 #: applications/templates/applications/remote_app_detail.html:68 -#: assets/models/asset.py:224 assets/models/base.py:240 +#: 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 @@ -335,7 +335,7 @@ msgstr "创建者" #: applications/models/remote_app.py:42 #: applications/templates/applications/database_app_detail.html:68 #: applications/templates/applications/remote_app_detail.html:64 -#: assets/models/asset.py:225 assets/models/base.py:238 +#: 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 @@ -737,7 +737,7 @@ msgstr "不能移除资产的管理用户账号" msgid "Latest version could not be delete" msgstr "最新版本的不能被删除" -#: assets/forms/asset.py:83 assets/models/asset.py:195 +#: 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:118 @@ -748,7 +748,7 @@ msgstr "最新版本的不能被删除" msgid "Nodes" msgstr "节点" -#: assets/forms/asset.py:86 assets/models/asset.py:199 +#: 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 @@ -766,7 +766,7 @@ msgstr "管理用户" msgid "Label" msgstr "标签" -#: assets/forms/asset.py:92 assets/models/asset.py:194 +#: 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 @@ -774,8 +774,8 @@ msgstr "标签" msgid "Domain" msgstr "网域" -#: assets/forms/asset.py:95 assets/models/asset.py:169 -#: assets/models/asset.py:193 assets/serializers/asset.py:67 +#: 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" @@ -980,24 +980,24 @@ msgstr "SFTP的起始路径,tmp目录, 用户home目录或者自定义" msgid "Username is dynamic, When connect asset, using current user's username" msgstr "用户名是动态的,登录资产时使用当前用户的用户名登录" -#: assets/models/asset.py:146 xpack/plugins/cloud/providers/base.py:16 +#: assets/models/asset.py:147 xpack/plugins/cloud/providers/base.py:16 msgid "Base" msgstr "基础" -#: assets/models/asset.py:147 assets/templates/assets/platform_detail.html:56 +#: assets/models/asset.py:148 assets/templates/assets/platform_detail.html:56 msgid "Charset" msgstr "编码" -#: assets/models/asset.py:148 assets/templates/assets/platform_detail.html:60 +#: assets/models/asset.py:149 assets/templates/assets/platform_detail.html:60 #: tickets/models/ticket.py:38 msgid "Meta" msgstr "元数据" -#: assets/models/asset.py:149 +#: assets/models/asset.py:150 msgid "Internal" msgstr "内部的" -#: assets/models/asset.py:186 assets/models/domain.py:49 +#: assets/models/asset.py:187 assets/models/domain.py:49 #: assets/serializers/asset_user.py:46 #: assets/templates/assets/_asset_list_modal.html:47 #: assets/templates/assets/_asset_user_list.html:20 @@ -1015,7 +1015,7 @@ msgstr "内部的" msgid "IP" msgstr "IP" -#: assets/models/asset.py:187 assets/serializers/asset_user.py:45 +#: assets/models/asset.py:188 assets/serializers/asset_user.py:45 #: assets/serializers/gathered_user.py:20 #: assets/templates/assets/_asset_list_modal.html:46 #: assets/templates/assets/_asset_user_auth_update_modal.html:9 @@ -1033,7 +1033,7 @@ msgstr "IP" msgid "Hostname" msgstr "主机名" -#: assets/models/asset.py:190 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:78 @@ -1045,84 +1045,84 @@ msgstr "主机名" msgid "Protocol" msgstr "协议" -#: assets/models/asset.py:192 assets/serializers/asset.py:69 +#: 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:60 msgid "Protocols" msgstr "协议组" -#: assets/models/asset.py:196 assets/models/cmd_filter.py:22 +#: 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:202 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:203 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:206 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:207 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:208 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:210 +#: assets/models/asset.py:211 msgid "CPU model" msgstr "CPU型号" -#: assets/models/asset.py:211 +#: assets/models/asset.py:212 msgid "CPU count" msgstr "CPU数量" -#: assets/models/asset.py:212 +#: assets/models/asset.py:213 msgid "CPU cores" msgstr "CPU核数" -#: assets/models/asset.py:213 +#: assets/models/asset.py:214 msgid "CPU vcpus" msgstr "CPU总数" -#: assets/models/asset.py:214 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:215 +#: assets/models/asset.py:216 msgid "Disk total" msgstr "硬盘大小" -#: assets/models/asset.py:216 +#: assets/models/asset.py:217 msgid "Disk info" msgstr "硬盘信息" -#: assets/models/asset.py:218 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:219 +#: assets/models/asset.py:220 msgid "OS version" msgstr "系统版本" -#: assets/models/asset.py:220 +#: assets/models/asset.py:221 msgid "OS arch" msgstr "系统架构" -#: assets/models/asset.py:221 +#: assets/models/asset.py:222 msgid "Hostname raw" msgstr "主机名原始" -#: assets/models/asset.py:223 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 "标签管理" @@ -2797,7 +2797,7 @@ msgid "" msgstr "账号已被锁定(请联系管理员解锁 或 {}分钟后重试)" #: authentication/errors.py:48 users/views/profile/otp.py:63 -#: users/views/profile/otp.py:102 +#: users/views/profile/otp.py:100 users/views/profile/otp.py:116 msgid "MFA code invalid, or ntp sync server time" msgstr "MFA验证码不正确,或者服务器端时间不对" @@ -2860,10 +2860,10 @@ msgid "Show" msgstr "显示" #: authentication/templates/authentication/_access_key_modal.html:66 -#: users/models/user.py:360 users/templates/users/user_disable_mfa.html:32 -#: users/templates/users/user_profile.html:94 +#: users/models/user.py:360 users/templates/users/user_profile.html:94 #: users/templates/users/user_profile.html:163 #: users/templates/users/user_profile.html:166 +#: users/templates/users/user_verify_mfa.html:32 msgid "Disable" msgstr "禁用" @@ -2909,8 +2909,8 @@ msgid "More login options" msgstr "更多登录方式" #: authentication/templates/authentication/login.html:61 -msgid "OpenID" -msgstr "OpenID" +msgid "Keycloak" +msgstr "" #: authentication/templates/authentication/login_otp.html:17 msgid "One-time password" @@ -2922,10 +2922,10 @@ msgstr "请打开 Google Authenticator,输入6位动态码" #: 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_check_password.html:15 #: users/templates/users/user_otp_enable_bind.html:24 #: users/templates/users/user_otp_enable_install_app.html:29 +#: users/templates/users/user_verify_mfa.html:26 msgid "Next" msgstr "下一步" @@ -5776,26 +5776,6 @@ msgstr "解除用户登录限制后,此用户即可正常登录" msgid "Reset user MFA success" msgstr "重置用户多因子认证成功" -#: users/templates/users/user_disable_mfa.html:6 -#: users/templates/users/user_otp_check_password.html:6 -msgid "Authenticate" -msgstr "验证身份" - -#: 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 #: users/views/group.py:83 @@ -5854,6 +5834,11 @@ msgstr "用户已失效" msgid "User is inactive" msgstr "用户已禁用" +#: users/templates/users/user_otp_check_password.html:6 +#: users/templates/users/user_verify_mfa.html:6 +msgid "Authenticate" +msgstr "验证身份" + #: users/templates/users/user_otp_enable_bind.html:6 msgid "Bind one-time password authenticator" msgstr "绑定一次性密码验证器" @@ -5864,6 +5849,11 @@ msgid "" "code for a 6-bit verification code" msgstr "使用手机 Google Authenticator 应用扫描以下二维码,获取6位验证码" +#: users/templates/users/user_otp_enable_bind.html:22 +#: users/templates/users/user_verify_mfa.html:23 +msgid "Six figures" +msgstr "6位数字" + #: users/templates/users/user_otp_enable_install_app.html:6 msgid "Install app" msgstr "安装应用" @@ -5946,6 +5936,16 @@ msgstr "更新用户" msgid "User auth from {}, go there change password" msgstr "用户认证源来自 {}, 请去相应系统修改密码" +#: users/templates/users/user_verify_mfa.html:11 +msgid "" +"The account protection has been opened, please complete the following " +"operations according to the prompts" +msgstr "账号保护已开启,请根据提示完成以下操作" + +#: users/templates/users/user_verify_mfa.html:13 +msgid "Open Authenticator and enter the 6-bit dynamic code" +msgstr "请打开 验证器,输入6位动态码" + # msgid "Update user" # msgstr "更新用户" #: users/utils.py:24 @@ -6193,19 +6193,19 @@ msgstr "首次登录" msgid "Profile setting" msgstr "个人信息设置" -#: users/views/profile/otp.py:130 +#: users/views/profile/otp.py:144 msgid "MFA enable success" msgstr "多因子认证启用成功" -#: users/views/profile/otp.py:131 +#: users/views/profile/otp.py:145 msgid "MFA enable success, return login page" msgstr "多因子认证启用成功,返回到登录页面" -#: users/views/profile/otp.py:133 +#: users/views/profile/otp.py:147 msgid "MFA disable success" msgstr "多因子认证禁用成功" -#: users/views/profile/otp.py:134 +#: users/views/profile/otp.py:148 msgid "MFA disable success, return login page" msgstr "多因子认证禁用成功,返回登录页面" diff --git a/apps/users/templates/users/user_disable_mfa.html b/apps/users/templates/users/user_verify_mfa.html similarity index 100% rename from apps/users/templates/users/user_disable_mfa.html rename to apps/users/templates/users/user_verify_mfa.html diff --git a/apps/users/views/profile/otp.py b/apps/users/views/profile/otp.py index 7bae70c58..2d823f5ab 100644 --- a/apps/users/views/profile/otp.py +++ b/apps/users/views/profile/otp.py @@ -83,12 +83,26 @@ class UserOtpEnableBindView(TemplateView, FormView): return super().get_context_data(**kwargs) -class UserDisableMFAView(FormView): - template_name = 'users/user_disable_mfa.html' +class UserVerifyMFAView(FormView): + template_name = 'users/user_verify_mfa.html' form_class = forms.UserCheckOtpCodeForm success_url = reverse_lazy('users:user-otp-settings-success') permission_classes = [IsValidUser] + def form_valid(self, form): + user = self.request.user + otp_code = form.cleaned_data.get('otp_code') + + valid = user.check_mfa(otp_code) + if valid: + return super().form_valid(form) + else: + error = _('MFA code invalid, or ntp sync server time') + form.add_error('otp_code', error) + return super().form_invalid(form) + + +class UserDisableMFAView(UserVerifyMFAView): def form_valid(self, form): user = self.request.user otp_code = form.cleaned_data.get('otp_code') @@ -104,7 +118,7 @@ class UserDisableMFAView(FormView): return super().form_invalid(form) -class UserOtpUpdateView(UserDisableMFAView): +class UserOtpUpdateView(UserVerifyMFAView): success_url = reverse_lazy('users:user-otp-enable-bind')