fix: Open redirect security vulnerability

pull/15771/head
wangruidong 2025-07-23 11:04:02 +08:00 committed by 老广
parent 51c5294fb4
commit 36ae076cb0
6 changed files with 238 additions and 113 deletions

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n" "Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-07-17 15:06+0800\n" "POT-Creation-Date: 2025-07-24 15:19+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n" "Language-Team: JumpServer team<ibuler@qq.com>\n"
@ -130,8 +130,8 @@ msgstr ">>> 开始执行测试网关账号可连接性任务"
#: audits/signal_handlers/login_log.py:34 authentication/confirm/password.py:25 #: audits/signal_handlers/login_log.py:34 authentication/confirm/password.py:25
#: authentication/confirm/password.py:27 authentication/const.py:10 #: authentication/confirm/password.py:27 authentication/const.py:10
#: authentication/forms.py:28 #: authentication/forms.py:28
#: authentication/templates/authentication/login.html:362 #: authentication/templates/authentication/login.html:367
#: authentication/templates/authentication/login.html:408 #: authentication/templates/authentication/login.html:413
#: settings/models.py:243 settings/serializers/auth/ldap.py:27 #: settings/models.py:243 settings/serializers/auth/ldap.py:27
#: settings/serializers/auth/ldap.py:53 settings/serializers/auth/ldap_ha.py:35 #: settings/serializers/auth/ldap.py:53 settings/serializers/auth/ldap_ha.py:35
#: settings/serializers/msg.py:37 settings/serializers/terminal.py:32 #: settings/serializers/msg.py:37 settings/serializers/terminal.py:32
@ -140,6 +140,8 @@ msgstr ">>> 开始执行测试网关账号可连接性任务"
#: users/templates/users/_msg_user_created.html:13 #: users/templates/users/_msg_user_created.html:13
#: users/templates/users/user_password_verify.html:18 #: users/templates/users/user_password_verify.html:18
#: xpack/plugins/cloud/serializers/account_attrs.py:43 #: xpack/plugins/cloud/serializers/account_attrs.py:43
#: xpack/plugins/cloud/serializers/account_attrs.py:105
#: xpack/plugins/cloud/serializers/account_attrs.py:112
msgid "Password" msgid "Password"
msgstr "密码" msgstr "密码"
@ -196,11 +198,11 @@ msgstr "发现"
msgid "Template" msgid "Template"
msgstr "模板" msgstr "模板"
#: accounts/const/account.py:32 ops/const.py:47 xpack/plugins/cloud/const.py:74 #: accounts/const/account.py:32 ops/const.py:47 xpack/plugins/cloud/const.py:75
msgid "Skip" msgid "Skip"
msgstr "跳过" msgstr "跳过"
#: accounts/const/account.py:33 audits/const.py:24 rbac/tree.py:279 #: accounts/const/account.py:33 audits/const.py:24 rbac/tree.py:280
#: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 #: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6
msgid "Update" msgid "Update"
msgstr "更新" msgstr "更新"
@ -208,7 +210,7 @@ msgstr "更新"
#: accounts/const/account.py:34 accounts/const/automation.py:115 #: accounts/const/account.py:34 accounts/const/automation.py:115
#: accounts/serializers/automations/change_secret.py:171 audits/const.py:66 #: accounts/serializers/automations/change_secret.py:171 audits/const.py:66
#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:66 #: audits/signal_handlers/activity_log.py:34 common/const/choices.py:66
#: ops/const.py:77 terminal/const.py:81 xpack/plugins/cloud/const.py:53 #: ops/const.py:77 terminal/const.py:81 xpack/plugins/cloud/const.py:54
msgid "Failed" msgid "Failed"
msgstr "失败" msgstr "失败"
@ -408,7 +410,7 @@ msgstr "数据库"
#: accounts/const/vault.py:8 assets/const/category.py:12 #: accounts/const/vault.py:8 assets/const/category.py:12
#: assets/models/asset/database.py:10 assets/models/asset/database.py:29 #: assets/models/asset/database.py:10 assets/models/asset/database.py:29
#: xpack/plugins/cloud/const.py:39 #: xpack/plugins/cloud/const.py:40
msgid "Database" msgid "Database"
msgstr "数据库" msgstr "数据库"
@ -867,12 +869,14 @@ msgstr "重复密码"
#: authentication/serializers/connect_token_secret.py:53 #: authentication/serializers/connect_token_secret.py:53
#: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_different_city.html:9
#: authentication/templates/authentication/_msg_oauth_bind.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9
#: authentication/templates/authentication/login.html:408 #: authentication/templates/authentication/login.html:413
#: terminal/serializers/storage.py:136 users/forms/profile.py:32 #: terminal/serializers/storage.py:136 users/forms/profile.py:32
#: users/forms/profile.py:117 users/models/user/__init__.py:64 #: users/forms/profile.py:117 users/models/user/__init__.py:64
#: users/serializers/profile.py:190 #: users/serializers/profile.py:190
#: users/templates/users/_msg_user_created.html:12 #: users/templates/users/_msg_user_created.html:12
#: xpack/plugins/cloud/serializers/account_attrs.py:41 #: xpack/plugins/cloud/serializers/account_attrs.py:41
#: xpack/plugins/cloud/serializers/account_attrs.py:103
#: xpack/plugins/cloud/serializers/account_attrs.py:110
msgid "Username" msgid "Username"
msgstr "用户名" msgstr "用户名"
@ -1174,7 +1178,7 @@ msgstr "账号存在策略"
#: settings/models.py:41 tickets/models/ticket/apply_application.py:13 #: settings/models.py:41 tickets/models/ticket/apply_application.py:13
#: users/models/preference.py:12 xpack/plugins/cloud/models.py:41 #: users/models/preference.py:12 xpack/plugins/cloud/models.py:41
#: xpack/plugins/cloud/models.py:326 #: xpack/plugins/cloud/models.py:326
#: xpack/plugins/cloud/serializers/account.py:81 #: xpack/plugins/cloud/serializers/account.py:83
msgid "Category" msgid "Category"
msgstr "类别" msgstr "类别"
@ -1945,8 +1949,8 @@ msgid ""
"10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 (Domain name " "10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 (Domain name "
"support)" "support)"
msgstr "" msgstr ""
"* 表示匹配所有。例如: 192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, 2001:" "* 表示匹配所有。例如: 192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, "
"db8:2de::e13, 2001:db8:1a:1110::/64 (支持网域)" "2001:db8:2de::e13, 2001:db8:1a:1110::/64 (支持网域)"
#: acls/serializers/base.py:41 assets/serializers/asset/host.py:19 #: acls/serializers/base.py:41 assets/serializers/asset/host.py:19
msgid "IP/Host" msgid "IP/Host"
@ -1978,8 +1982,8 @@ msgid ""
"With * indicating a match all. Such as: 192.168.10.1, 192.168.1.0/24, " "With * indicating a match all. Such as: 192.168.10.1, 192.168.1.0/24, "
"10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 " "10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 "
msgstr "" msgstr ""
"* 表示匹配所有。例如: 192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, 2001:" "* 表示匹配所有。例如: 192.168.10.1, 192.168.1.0/24, 10.1.1.1-10.1.1.20, "
"db8:2de::e13, 2001:db8:1a:1110::/64" "2001:db8:2de::e13, 2001:db8:1a:1110::/64"
#: acls/serializers/rules/rules.py:48 #: acls/serializers/rules/rules.py:48
#: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_oauth_bind.html:12
@ -2125,6 +2129,7 @@ msgstr "无法连接到 {port} 上的端口 {address}"
#: assets/automations/ping_gateway/manager.py:58 #: assets/automations/ping_gateway/manager.py:58
#: authentication/middleware.py:95 xpack/plugins/cloud/providers/fc.py:47 #: authentication/middleware.py:95 xpack/plugins/cloud/providers/fc.py:47
#: xpack/plugins/cloud/providers/proxmox.py:29
msgid "Authentication failed" msgid "Authentication failed"
msgstr "认证失败" msgstr "认证失败"
@ -2208,8 +2213,7 @@ msgstr "脚本"
#: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:76 #: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:76
#: settings/serializers/feature.py:81 settings/serializers/feature.py:94 #: settings/serializers/feature.py:81 settings/serializers/feature.py:94
#: settings/serializers/msg.py:30 terminal/models/component/endpoint.py:14 #: settings/serializers/msg.py:30 terminal/models/component/endpoint.py:14
#: terminal/serializers/applet.py:17 xpack/plugins/cloud/const.py:38 #: terminal/serializers/applet.py:17 xpack/plugins/cloud/const.py:39
#: xpack/plugins/cloud/manager.py:101
#: xpack/plugins/cloud/serializers/account_attrs.py:87 #: xpack/plugins/cloud/serializers/account_attrs.py:87
msgid "Host" msgid "Host"
msgstr "主机" msgstr "主机"
@ -2228,7 +2232,8 @@ msgstr "云服务"
msgid "Web" msgid "Web"
msgstr "Web" msgstr "Web"
#: assets/const/category.py:16 common/sdk/sms/endpoint.py:20 #: assets/const/category.py:16 common/sdk/sms/custom_file.py:47
#: common/sdk/sms/endpoint.py:20
msgid "Custom type" msgid "Custom type"
msgstr "自定义类型" msgstr "自定义类型"
@ -2290,7 +2295,7 @@ msgid "ChatGPT"
msgstr "ChatGPT" msgstr "ChatGPT"
#: assets/const/host.py:13 rbac/tree.py:29 rbac/tree.py:68 #: assets/const/host.py:13 rbac/tree.py:29 rbac/tree.py:68
#: xpack/plugins/cloud/const.py:75 #: xpack/plugins/cloud/const.py:76
msgid "Other" msgid "Other"
msgstr "其它" msgstr "其它"
@ -2937,7 +2942,7 @@ msgstr "端口超出范围 (0-65535)"
msgid "Protocol is required: {}" msgid "Protocol is required: {}"
msgstr "协议是必填的: {}" msgstr "协议是必填的: {}"
#: assets/serializers/asset/common.py:353 #: assets/serializers/asset/common.py:353 labels/api.py:107
msgid "Invalid data" msgid "Invalid data"
msgstr "无效的数据" msgstr "无效的数据"
@ -3313,7 +3318,7 @@ msgstr "删除目录"
#: audits/const.py:14 audits/const.py:25 #: audits/const.py:14 audits/const.py:25
#: authentication/templates/authentication/_access_key_modal.html:65 #: authentication/templates/authentication/_access_key_modal.html:65
#: rbac/tree.py:280 #: rbac/tree.py:281
msgid "Delete" msgid "Delete"
msgstr "删除" msgstr "删除"
@ -3339,7 +3344,7 @@ msgstr "下载"
msgid "Rename dir" msgid "Rename dir"
msgstr "映射目录" msgstr "映射目录"
#: audits/const.py:23 rbac/tree.py:278 terminal/api/session/session.py:285 #: audits/const.py:23 rbac/tree.py:279 terminal/api/session/session.py:285
#: terminal/templates/terminal/_msg_command_warning.html:18 #: terminal/templates/terminal/_msg_command_warning.html:18
#: terminal/templates/terminal/_msg_session_sharing.html:10 #: terminal/templates/terminal/_msg_session_sharing.html:10
#: xpack/plugins/cloud/manager.py:102 #: xpack/plugins/cloud/manager.py:102
@ -3348,7 +3353,7 @@ msgstr "查看"
#: audits/const.py:26 #: audits/const.py:26
#: authentication/templates/authentication/_access_key_modal.html:22 #: authentication/templates/authentication/_access_key_modal.html:22
#: rbac/tree.py:277 #: rbac/tree.py:278
msgid "Create" msgid "Create"
msgstr "创建" msgstr "创建"
@ -3360,8 +3365,8 @@ msgstr "导出"
msgid "Connect" msgid "Connect"
msgstr "连接" msgstr "连接"
#: audits/const.py:31 authentication/templates/authentication/login.html:329 #: audits/const.py:31 authentication/templates/authentication/login.html:333
#: authentication/templates/authentication/login.html:401 #: authentication/templates/authentication/login.html:406
#: templates/_header_bar.html:101 #: templates/_header_bar.html:101
msgid "Login" msgid "Login"
msgstr "登录" msgstr "登录"
@ -3376,7 +3381,7 @@ msgstr "同意"
#: audits/const.py:42 ops/models/celery.py:85 #: audits/const.py:42 ops/models/celery.py:85
#: terminal/models/session/sharing.py:128 tickets/const.py:26 #: terminal/models/session/sharing.py:128 tickets/const.py:26
#: xpack/plugins/cloud/const.py:73 #: xpack/plugins/cloud/const.py:74
msgid "Finished" msgid "Finished"
msgstr "结束" msgstr "结束"
@ -3401,7 +3406,7 @@ msgstr "登录日志"
#: audits/const.py:55 rbac/tree.py:66 terminal/models/applet/host.py:144 #: audits/const.py:55 rbac/tree.py:66 terminal/models/applet/host.py:144
#: terminal/models/component/task.py:22 #: terminal/models/component/task.py:22
#: xpack/plugins/cloud/serializers/account.py:78 #: xpack/plugins/cloud/serializers/account.py:80
msgid "Task" msgid "Task"
msgstr "任务" msgstr "任务"
@ -3749,7 +3754,7 @@ msgid ""
msgstr "用户来自 {} 请去相应系统修改密码" msgstr "用户来自 {} 请去相应系统修改密码"
#: authentication/api/password.py:69 #: authentication/api/password.py:69
#: authentication/templates/authentication/login.html:393 #: authentication/templates/authentication/login.html:398
#: users/templates/users/forgot_password.html:41 #: users/templates/users/forgot_password.html:41
#: users/templates/users/forgot_password.html:42 #: users/templates/users/forgot_password.html:42
#: users/templates/users/forgot_password_previewing.html:13 #: users/templates/users/forgot_password_previewing.html:13
@ -4242,13 +4247,13 @@ msgstr "私有令牌"
#: authentication/models/ssh_key.py:15 terminal/serializers/storage.py:146 #: authentication/models/ssh_key.py:15 terminal/serializers/storage.py:146
#: users/models/user/__init__.py:94 #: users/models/user/__init__.py:94
#: xpack/plugins/cloud/serializers/account_attrs.py:237 #: xpack/plugins/cloud/serializers/account_attrs.py:244
msgid "Private key" msgid "Private key"
msgstr "ssh私钥" msgstr "ssh私钥"
#: authentication/models/ssh_key.py:18 settings/serializers/terminal.py:38 #: authentication/models/ssh_key.py:18 settings/serializers/terminal.py:38
#: users/forms/profile.py:175 users/models/user/__init__.py:97 #: users/forms/profile.py:175 users/models/user/__init__.py:97
#: xpack/plugins/cloud/serializers/account_attrs.py:234 #: xpack/plugins/cloud/serializers/account_attrs.py:241
msgid "Public key" msgid "Public key"
msgstr "SSH公钥" msgstr "SSH公钥"
@ -4392,8 +4397,8 @@ msgid ""
"Retention Period" "Retention Period"
msgstr "" msgstr ""
"系统在连接资产或创建临时密码时,会生成相应的连接 Token 或临时密码记录。为了保" "系统在连接资产或创建临时密码时,会生成相应的连接 Token 或临时密码记录。为了保"
"障系统安全并控制数据存储量,系统会根据“安全设置 > 密码安全 > Token 保留时" "障系统安全并控制数据存储量,系统会根据“安全设置 > 密码安全 > Token 保留时长”"
"长”中的配置,每天凌晨 2 点自动清理所有已过期的 Token 记录" "中的配置,每天凌晨 2 点自动清理所有已过期的 Token 记录"
#: authentication/templates/authentication/_access_key_modal.html:6 #: authentication/templates/authentication/_access_key_modal.html:6
msgid "API key list" msgid "API key list"
@ -4444,6 +4449,7 @@ msgstr "需要 MFA 认证来查看账号信息"
#: authentication/templates/authentication/_mfa_confirm_modal.html:20 #: authentication/templates/authentication/_mfa_confirm_modal.html:20
#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:37 #: authentication/templates/authentication/auth_fail_flash_message_standalone.html:37
#: templates/_modal.html:23 templates/flash_message_standalone.html:37 #: templates/_modal.html:23 templates/flash_message_standalone.html:37
#: templates/redirect_confirm.html:39
#: users/templates/users/user_password_verify.html:20 #: users/templates/users/user_password_verify.html:20
msgid "Confirm" msgid "Confirm"
msgstr "确认" msgstr "确认"
@ -4558,7 +4564,8 @@ msgid ""
msgstr "如果这次公钥更新不是由你发起的,那么你的账号可能存在安全问题" msgstr "如果这次公钥更新不是由你发起的,那么你的账号可能存在安全问题"
#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:28 #: authentication/templates/authentication/auth_fail_flash_message_standalone.html:28
#: templates/flash_message_standalone.html:28 tickets/const.py:19 #: templates/flash_message_standalone.html:28
#: templates/redirect_confirm.html:34 tickets/const.py:19
msgid "Cancel" msgid "Cancel"
msgstr "取消" msgstr "取消"
@ -4566,17 +4573,17 @@ msgstr "取消"
msgid "Retry" msgid "Retry"
msgstr "重试" msgstr "重试"
#: authentication/templates/authentication/login.html:308 #: authentication/templates/authentication/login.html:312
msgid "" msgid ""
"Configuration file has problems and cannot be logged in. Please contact the " "Configuration file has problems and cannot be logged in. Please contact the "
"administrator or view latest docs" "administrator or view latest docs"
msgstr "配置文件有问题,无法登录,请联系管理员或查看最新文档" msgstr "配置文件有问题,无法登录,请联系管理员或查看最新文档"
#: authentication/templates/authentication/login.html:309 #: authentication/templates/authentication/login.html:313
msgid "If you are administrator, you can update the config resolve it, set" msgid "If you are administrator, you can update the config resolve it, set"
msgstr "如果你是管理员,可以更新配置文件解决,设置配置项" msgstr "如果你是管理员,可以更新配置文件解决,设置配置项"
#: authentication/templates/authentication/login.html:416 #: authentication/templates/authentication/login.html:421
msgid "More login options" msgid "More login options"
msgstr "其他方式登录" msgstr "其他方式登录"
@ -4623,7 +4630,7 @@ msgid "Do you want to retry ?"
msgstr "是否重试 " msgstr "是否重试 "
#: authentication/utils.py:27 common/utils/ip/geoip/utils.py:26 #: authentication/utils.py:27 common/utils/ip/geoip/utils.py:26
#: xpack/plugins/cloud/const.py:34 #: xpack/plugins/cloud/const.py:35
msgid "LAN" msgid "LAN"
msgstr "局域网" msgstr "局域网"
@ -4896,7 +4903,7 @@ msgstr "无效的ID应为列表"
#: xpack/plugins/cloud/serializers/account_attrs.py:20 #: xpack/plugins/cloud/serializers/account_attrs.py:20
#: xpack/plugins/cloud/serializers/account_attrs.py:71 #: xpack/plugins/cloud/serializers/account_attrs.py:71
#: xpack/plugins/cloud/serializers/account_attrs.py:95 #: xpack/plugins/cloud/serializers/account_attrs.py:95
#: xpack/plugins/cloud/serializers/account_attrs.py:174 #: xpack/plugins/cloud/serializers/account_attrs.py:181
msgid "This field is required." msgid "This field is required."
msgstr "该字段是必填项。" msgstr "该字段是必填项。"
@ -5105,6 +5112,10 @@ msgstr "自定义短信文件无效"
msgid "SMS sending failed[%s]: %s" msgid "SMS sending failed[%s]: %s"
msgstr "短信发送失败[%s]: %s" msgstr "短信发送失败[%s]: %s"
#: common/sdk/sms/custom_file.py:47 common/serializers/common.py:98
msgid "File"
msgstr "文件"
#: common/sdk/sms/endpoint.py:16 #: common/sdk/sms/endpoint.py:16
msgid "Alibaba cloud" msgid "Alibaba cloud"
msgstr "阿里云" msgstr "阿里云"
@ -5149,10 +5160,6 @@ msgstr "请在 {} 秒后发送"
msgid "Children" msgid "Children"
msgstr "节点" msgstr "节点"
#: common/serializers/common.py:98
msgid "File"
msgstr "文件"
#: common/serializers/fields.py:139 #: common/serializers/fields.py:139
msgid "Invalid data type" msgid "Invalid data type"
msgstr "无效的数据" msgstr "无效的数据"
@ -5172,7 +5179,7 @@ msgid "Invalid data type, should be list"
msgstr "错误的数据类型,应该是列表" msgstr "错误的数据类型,应该是列表"
#: common/serializers/fields.py:237 #: common/serializers/fields.py:237
#: xpack/plugins/cloud/serializers/account.py:115 #: xpack/plugins/cloud/serializers/account.py:117
#: xpack/plugins/cloud/serializers/task.py:122 #: xpack/plugins/cloud/serializers/task.py:122
msgid "Invalid choice: {}" msgid "Invalid choice: {}"
msgstr "无效选项: {}" msgstr "无效选项: {}"
@ -5275,11 +5282,15 @@ msgstr "你的账号已创建成功"
msgid "JumpServer - An open-source PAM" msgid "JumpServer - An open-source PAM"
msgstr "JumpServer 开源堡垒机" msgstr "JumpServer 开源堡垒机"
#: jumpserver/context_processor.py:28
msgid "FIT2CLOUD"
msgstr ""
#: jumpserver/views/celery_flower.py:22 #: jumpserver/views/celery_flower.py:22
msgid "<h1>Flower service unavailable, check it</h1>" msgid "<h1>Flower service unavailable, check it</h1>"
msgstr "Flower 服务不可用,请检查" msgstr "Flower 服务不可用,请检查"
#: jumpserver/views/other.py:28 #: jumpserver/views/other.py:30
msgid "" msgid ""
"<div>Luna is a separately deployed program, you need to deploy Luna, koko, " "<div>Luna is a separately deployed program, you need to deploy Luna, koko, "
"configure nginx for url distribution,</div> </div>If you see this page, " "configure nginx for url distribution,</div> </div>If you see this page, "
@ -5288,11 +5299,11 @@ msgstr ""
"<div>Luna是单独部署的一个程序你需要部署lunakoko, </div><div>如果你看到了" "<div>Luna是单独部署的一个程序你需要部署lunakoko, </div><div>如果你看到了"
"这个页面证明你访问的不是nginx监听的端口祝你好运</div>" "这个页面证明你访问的不是nginx监听的端口祝你好运</div>"
#: jumpserver/views/other.py:76 #: jumpserver/views/other.py:78
msgid "Websocket server run on port: {}, you should proxy it on nginx" msgid "Websocket server run on port: {}, you should proxy it on nginx"
msgstr "Websocket 服务运行在端口: {}, 请检查nginx是否代理是否设置" msgstr "Websocket 服务运行在端口: {}, 请检查nginx是否代理是否设置"
#: jumpserver/views/other.py:90 #: jumpserver/views/other.py:92
msgid "" msgid ""
"<div>Koko is a separately deployed program, you need to deploy Koko, " "<div>Koko is a separately deployed program, you need to deploy Koko, "
"configure nginx for url distribution,</div> </div>If you see this page, " "configure nginx for url distribution,</div> </div>If you see this page, "
@ -6251,22 +6262,26 @@ msgid "Can view console view"
msgstr "可以显示控制台" msgstr "可以显示控制台"
#: rbac/models/menu.py:16 #: rbac/models/menu.py:16
msgid "Can view audit view" msgid "Can view pam view"
msgstr "可以显示审计台" msgstr "可以显示审计台"
#: rbac/models/menu.py:17 #: rbac/models/menu.py:17
msgid "Can view audit view"
msgstr "可以显示审计台"
#: rbac/models/menu.py:18
msgid "Can view workbench view" msgid "Can view workbench view"
msgstr "可以显示工作台" msgstr "可以显示工作台"
#: rbac/models/menu.py:18 #: rbac/models/menu.py:19
msgid "Can view web terminal" msgid "Can view web terminal"
msgstr "Web终端" msgstr "Web终端"
#: rbac/models/menu.py:19 #: rbac/models/menu.py:20
msgid "Can view file manager" msgid "Can view file manager"
msgstr "可以查看文件管理" msgstr "可以查看文件管理"
#: rbac/models/menu.py:20 #: rbac/models/menu.py:21
msgid "Can view System Tools" msgid "Can view System Tools"
msgstr "可以查看系统工具" msgstr "可以查看系统工具"
@ -6320,6 +6335,10 @@ msgstr "所有权限"
msgid "Console view" msgid "Console view"
msgstr "控制台" msgstr "控制台"
#: rbac/tree.py:25
msgid "Pam view"
msgstr "PAM"
#: rbac/tree.py:26 #: rbac/tree.py:26
msgid "Workbench view" msgid "Workbench view"
msgstr "工作台" msgstr "工作台"
@ -6383,24 +6402,24 @@ msgstr "许可证"
msgid "Job audit" msgid "Job audit"
msgstr "作业审计" msgstr "作业审计"
#: rbac/tree.py:169 #: rbac/tree.py:170
msgid "App organizations" msgid "App organizations"
msgstr "组织管理" msgstr "组织管理"
#: rbac/tree.py:170 #: rbac/tree.py:171
msgid "Ticket comment" msgid "Ticket comment"
msgstr "工单评论" msgstr "工单评论"
#: rbac/tree.py:171 settings/serializers/feature.py:164 #: rbac/tree.py:172 settings/serializers/feature.py:164
#: settings/serializers/feature.py:166 tickets/models/ticket/general.py:310 #: settings/serializers/feature.py:166 tickets/models/ticket/general.py:310
msgid "Ticket" msgid "Ticket"
msgstr "工单" msgstr "工单"
#: rbac/tree.py:172 #: rbac/tree.py:173
msgid "Common setting" msgid "Common setting"
msgstr "一般设置" msgstr "一般设置"
#: rbac/tree.py:173 #: rbac/tree.py:174
msgid "View permission tree" msgid "View permission tree"
msgstr "查看授权树" msgstr "查看授权树"
@ -7122,7 +7141,7 @@ msgid "SSO auth key TTL"
msgstr "令牌有效期" msgstr "令牌有效期"
#: settings/serializers/auth/sso.py:20 #: settings/serializers/auth/sso.py:20
#: xpack/plugins/cloud/serializers/account_attrs.py:224 #: xpack/plugins/cloud/serializers/account_attrs.py:231
msgid "Unit: second" msgid "Unit: second"
msgstr "单位: 秒" msgstr "单位: 秒"
@ -7279,7 +7298,7 @@ msgstr "租户 ID"
#: settings/serializers/feature.py:110 terminal/serializers/storage.py:68 #: settings/serializers/feature.py:110 terminal/serializers/storage.py:68
#: xpack/plugins/cloud/manager.py:119 xpack/plugins/cloud/manager.py:124 #: xpack/plugins/cloud/manager.py:119 xpack/plugins/cloud/manager.py:124
#: xpack/plugins/cloud/models.py:292 #: xpack/plugins/cloud/manager.py:161 xpack/plugins/cloud/models.py:292
msgid "Region" msgid "Region"
msgstr "地域" msgstr "地域"
@ -8044,7 +8063,7 @@ msgid ", disabled {}"
msgstr ", 禁用 {}" msgstr ", 禁用 {}"
#: templates/_csv_import_export.html:13 templates/_csv_import_modal.html:5 #: templates/_csv_import_export.html:13 templates/_csv_import_modal.html:5
#: xpack/plugins/cloud/const.py:71 #: xpack/plugins/cloud/const.py:72
msgid "Import" msgid "Import"
msgstr "导入" msgstr "导入"
@ -8164,10 +8183,16 @@ msgstr "等待:"
msgid "The verification code has been sent" msgid "The verification code has been sent"
msgstr "验证码已发送" msgstr "验证码已发送"
#: templates/_without_nav_base.html:26 #: templates/_without_nav_base.html:46
msgid "Home page" msgid "Home page"
msgstr "首页" msgstr "首页"
#: templates/redirect_confirm.html:26
msgid ""
"You are about to be redirected to an external website. Please confirm that "
"you trust this link: "
msgstr "您即将跳转到一个外部网站, 请确认您信任该链接"
#: templates/resource_download.html:20 templates/resource_download.html:35 #: templates/resource_download.html:20 templates/resource_download.html:35
#: users/const.py:77 #: users/const.py:77
msgid "Client" msgid "Client"
@ -8273,7 +8298,7 @@ msgstr "会话不存在: {}"
msgid "Session is finished or the protocol not supported" msgid "Session is finished or the protocol not supported"
msgstr "会话已经完成或协议不支持" msgstr "会话已经完成或协议不支持"
#: terminal/api/session/session.py:350 #: terminal/api/session/session.py:350 tickets/api/ticket.py:140
msgid "User does not have permission" msgid "User does not have permission"
msgstr "用户没有权限" msgstr "用户没有权限"
@ -8767,8 +8792,8 @@ msgstr "命令及录像存储"
#: terminal/notifications.py:258 terminal/tasks.py:212 #: terminal/notifications.py:258 terminal/tasks.py:212
#: xpack/plugins/cloud/api.py:182 #: xpack/plugins/cloud/api.py:182
#: xpack/plugins/cloud/serializers/account.py:137
#: xpack/plugins/cloud/serializers/account.py:139 #: xpack/plugins/cloud/serializers/account.py:139
#: xpack/plugins/cloud/serializers/account.py:141
msgid "Test failure: Account invalid" msgid "Test failure: Account invalid"
msgstr "测试失败: 账号无效" msgstr "测试失败: 账号无效"
@ -8825,9 +8850,9 @@ msgid ""
"days. <a href=\"https://learn.microsoft.com/en-us/windows-server/remote/" "days. <a href=\"https://learn.microsoft.com/en-us/windows-server/remote/"
"remote-desktop-services/rds-client-access-license\">Detail</a>" "remote-desktop-services/rds-client-access-license\">Detail</a>"
msgstr "" msgstr ""
"如果不存在RDS 将处于试用模式,试用期为 120 天。<a href='https://learn." "如果不存在RDS 将处于试用模式,试用期为 120 天。<a href='https://"
"microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-client-" "learn.microsoft.com/en-us/windows-server/remote/remote-desktop-services/rds-"
"access-license'>详情</a>" "client-access-license'>详情</a>"
#: terminal/serializers/applet_host.py:55 #: terminal/serializers/applet_host.py:55
msgid "RDS License Server" msgid "RDS License Server"
@ -9041,8 +9066,8 @@ msgid ""
"If there are multiple hosts, use a comma (,) to separate them. <br>(For " "If there are multiple hosts, use a comma (,) to separate them. <br>(For "
"example: http://www.jumpserver.a.com:9100, http://www.jumpserver.b.com:9100)" "example: http://www.jumpserver.a.com:9100, http://www.jumpserver.b.com:9100)"
msgstr "" msgstr ""
"如果有多个主机,请用逗号 (,) 分隔它们。<br>例如http://www.jumpserver.a." "如果有多个主机,请用逗号 (,) 分隔它们。<br>例如http://"
"com:9100http://www.jumpserver.b.com:9100" "www.jumpserver.a.com:9100http://www.jumpserver.b.com:9100"
#: terminal/serializers/storage.py:199 #: terminal/serializers/storage.py:199
msgid "Index by date" msgid "Index by date"
@ -9977,7 +10002,7 @@ msgstr "密码不满足安全规则"
msgid "The new password cannot be the last {} passwords" msgid "The new password cannot be the last {} passwords"
msgstr "新密码不能是最近 {} 次的密码" msgstr "新密码不能是最近 {} 次的密码"
#: users/serializers/profile.py:194 #: users/serializers/profile.py:195
msgid "Perms" msgid "Perms"
msgstr "权限" msgstr "权限"
@ -10363,14 +10388,6 @@ msgstr "账号保护已开启,请根据提示完成以下操作"
msgid "Open MFA Authenticator and enter the 6-bit dynamic code" msgid "Open MFA Authenticator and enter the 6-bit dynamic code"
msgstr "请打开 MFA 验证器,输入 6 位动态码" msgstr "请打开 MFA 验证器,输入 6 位动态码"
#: users/utils.py:65
msgid "Auth success"
msgstr "认证成功"
#: users/utils.py:66
msgid "Redirecting to JumpServer Client"
msgstr "重定向到 JumpServer 客户端"
#: users/views/profile/face.py:57 users/views/profile/face.py:58 #: users/views/profile/face.py:57 users/views/profile/face.py:58
msgid "Face binding successful" msgid "Face binding successful"
msgstr "绑定人脸特征成功" msgstr "绑定人脸特征成功"
@ -10555,55 +10572,59 @@ msgstr "深信服SCP"
msgid "Apsara Stack" msgid "Apsara Stack"
msgstr "阿里云专有云" msgstr "阿里云专有云"
#: xpack/plugins/cloud/const.py:43 #: xpack/plugins/cloud/const.py:34
msgid "Proxmox"
msgstr "Proxmox"
#: xpack/plugins/cloud/const.py:44
msgid "Private IP" msgid "Private IP"
msgstr "私有IP" msgstr "私有IP"
#: xpack/plugins/cloud/const.py:44 #: xpack/plugins/cloud/const.py:45
msgid "Public IP" msgid "Public IP"
msgstr "公网IP" msgstr "公网IP"
#: xpack/plugins/cloud/const.py:48 xpack/plugins/cloud/models.py:372 #: xpack/plugins/cloud/const.py:49 xpack/plugins/cloud/models.py:372
msgid "Instance name" msgid "Instance name"
msgstr "实例名称" msgstr "实例名称"
#: xpack/plugins/cloud/const.py:49 #: xpack/plugins/cloud/const.py:50
msgid "Instance name and Partial IP" msgid "Instance name and Partial IP"
msgstr "实例名称和部分IP" msgstr "实例名称和部分IP"
#: xpack/plugins/cloud/const.py:54 #: xpack/plugins/cloud/const.py:55
msgid "Succeed" msgid "Succeed"
msgstr "成功" msgstr "成功"
#: xpack/plugins/cloud/const.py:58 xpack/plugins/cloud/manager.py:107 #: xpack/plugins/cloud/const.py:59 xpack/plugins/cloud/manager.py:107
msgid "Unsync" msgid "Unsync"
msgstr "未同步" msgstr "未同步"
#: xpack/plugins/cloud/const.py:59 xpack/plugins/cloud/manager.py:106 #: xpack/plugins/cloud/const.py:60 xpack/plugins/cloud/manager.py:106
msgid "New Sync" msgid "New Sync"
msgstr "新同步" msgstr "新同步"
#: xpack/plugins/cloud/const.py:60 xpack/plugins/cloud/manager.py:106 #: xpack/plugins/cloud/const.py:61 xpack/plugins/cloud/manager.py:106
msgid "Synced" msgid "Synced"
msgstr "已同步" msgstr "已同步"
#: xpack/plugins/cloud/const.py:61 xpack/plugins/cloud/manager.py:108 #: xpack/plugins/cloud/const.py:62 xpack/plugins/cloud/manager.py:108
msgid "Released" msgid "Released"
msgstr "已释放" msgstr "已释放"
#: xpack/plugins/cloud/const.py:65 #: xpack/plugins/cloud/const.py:66
msgid "And" msgid "And"
msgstr "与" msgstr "与"
#: xpack/plugins/cloud/const.py:66 #: xpack/plugins/cloud/const.py:67
msgid "Or" msgid "Or"
msgstr "或" msgstr "或"
#: xpack/plugins/cloud/const.py:70 #: xpack/plugins/cloud/const.py:71
msgid "Sync region" msgid "Sync region"
msgstr "已同步组织" msgstr "已同步组织"
#: xpack/plugins/cloud/const.py:72 #: xpack/plugins/cloud/const.py:73
msgid "Imported" msgid "Imported"
msgstr "导入" msgstr "导入"
@ -10645,6 +10666,10 @@ msgstr "同步地区"
msgid "Get instances of region \"%s\" error, error: %s" msgid "Get instances of region \"%s\" error, error: %s"
msgstr "获取区域 \"%s\" 的实例错误,错误:%s" msgstr "获取区域 \"%s\" 的实例错误,错误:%s"
#: xpack/plugins/cloud/manager.py:161 xpack/plugins/cloud/models.py:289
msgid "Instance"
msgstr "实例"
#: xpack/plugins/cloud/manager.py:187 #: xpack/plugins/cloud/manager.py:187
#, python-format #, python-format
msgid "Failed to synchronize the instance \"%s\"" msgid "Failed to synchronize the instance \"%s\""
@ -10706,7 +10731,7 @@ msgid "Cloud center"
msgstr "云管中心" msgstr "云管中心"
#: xpack/plugins/cloud/models.py:43 #: xpack/plugins/cloud/models.py:43
#: xpack/plugins/cloud/serializers/account.py:99 #: xpack/plugins/cloud/serializers/account.py:101
msgid "Attrs" msgid "Attrs"
msgstr "属性" msgstr "属性"
@ -10723,7 +10748,7 @@ msgid "Test cloud account"
msgstr "测试云账号" msgstr "测试云账号"
#: xpack/plugins/cloud/models.py:109 #: xpack/plugins/cloud/models.py:109
#: xpack/plugins/cloud/serializers/account.py:77 #: xpack/plugins/cloud/serializers/account.py:79
#: xpack/plugins/cloud/serializers/task.py:170 #: xpack/plugins/cloud/serializers/task.py:170
#: xpack/plugins/cloud/serializers/task.py:171 #: xpack/plugins/cloud/serializers/task.py:171
msgid "Regions" msgid "Regions"
@ -10787,10 +10812,6 @@ msgstr "同步任务"
msgid "Sync instance task history" msgid "Sync instance task history"
msgstr "同步实例任务历史" msgstr "同步实例任务历史"
#: xpack/plugins/cloud/models.py:289
msgid "Instance"
msgstr "实例"
#: xpack/plugins/cloud/models.py:306 #: xpack/plugins/cloud/models.py:306
msgid "Sync instance detail" msgid "Sync instance detail"
msgstr "同步实例详情" msgstr "同步实例详情"
@ -11075,11 +11096,11 @@ msgstr "华东-宿迁"
msgid "Port \"%(port)s\" of instance IP \"%(ip)s\" is not reachable" msgid "Port \"%(port)s\" of instance IP \"%(ip)s\" is not reachable"
msgstr "实例 IP %(ip)s 的端口%(port)s 无法访问" msgstr "实例 IP %(ip)s 的端口%(port)s 无法访问"
#: xpack/plugins/cloud/serializers/account.py:100 #: xpack/plugins/cloud/serializers/account.py:102
msgid "Validity display" msgid "Validity display"
msgstr "有效性显示" msgstr "有效性显示"
#: xpack/plugins/cloud/serializers/account.py:101 #: xpack/plugins/cloud/serializers/account.py:103
msgid "Provider display" msgid "Provider display"
msgstr "服务商显示" msgstr "服务商显示"
@ -11095,11 +11116,15 @@ msgstr "订阅 ID"
msgid "Auto node classification" msgid "Auto node classification"
msgstr "自动节点分类" msgstr "自动节点分类"
#: xpack/plugins/cloud/serializers/account_attrs.py:108
msgid "domain_name"
msgstr "域名称"
#: xpack/plugins/cloud/serializers/account_attrs.py:114 #: xpack/plugins/cloud/serializers/account_attrs.py:114
#: xpack/plugins/cloud/serializers/account_attrs.py:118 #: xpack/plugins/cloud/serializers/account_attrs.py:118
#: xpack/plugins/cloud/serializers/account_attrs.py:150 #: xpack/plugins/cloud/serializers/account_attrs.py:157
#: xpack/plugins/cloud/serializers/account_attrs.py:180 #: xpack/plugins/cloud/serializers/account_attrs.py:187
#: xpack/plugins/cloud/serializers/account_attrs.py:230 #: xpack/plugins/cloud/serializers/account_attrs.py:237
msgid "API Endpoint" msgid "API Endpoint"
msgstr "API 端点" msgstr "API 端点"
@ -11115,31 +11140,31 @@ msgstr "如: http://openstack.example.com:5000/v3"
msgid "User domain" msgid "User domain"
msgstr "用户域" msgstr "用户域"
#: xpack/plugins/cloud/serializers/account_attrs.py:151 #: xpack/plugins/cloud/serializers/account_attrs.py:158
msgid "Cert File" msgid "Cert File"
msgstr "证书文件" msgstr "证书文件"
#: xpack/plugins/cloud/serializers/account_attrs.py:152 #: xpack/plugins/cloud/serializers/account_attrs.py:159
msgid "Key File" msgid "Key File"
msgstr "密钥文件" msgstr "密钥文件"
#: xpack/plugins/cloud/serializers/account_attrs.py:168 #: xpack/plugins/cloud/serializers/account_attrs.py:175
msgid "Service account key" msgid "Service account key"
msgstr "服务账号密钥" msgstr "服务账号密钥"
#: xpack/plugins/cloud/serializers/account_attrs.py:169 #: xpack/plugins/cloud/serializers/account_attrs.py:176
msgid "The file is in JSON format" msgid "The file is in JSON format"
msgstr "JSON 格式的文件" msgstr "JSON 格式的文件"
#: xpack/plugins/cloud/serializers/account_attrs.py:187 #: xpack/plugins/cloud/serializers/account_attrs.py:194
msgid "IP address invalid `{}`, {}" msgid "IP address invalid `{}`, {}"
msgstr "IP 地址无效: `{}`, {}" msgstr "IP 地址无效: `{}`, {}"
#: xpack/plugins/cloud/serializers/account_attrs.py:203 #: xpack/plugins/cloud/serializers/account_attrs.py:210
msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255" msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255"
msgstr "例: 192.168.1.0/24,10.0.0.0-10.0.0.255" msgstr "例: 192.168.1.0/24,10.0.0.0-10.0.0.255"
#: xpack/plugins/cloud/serializers/account_attrs.py:206 #: xpack/plugins/cloud/serializers/account_attrs.py:213
msgid "" msgid ""
"The port is used to detect the validity of the IP address. When the " "The port is used to detect the validity of the IP address. When the "
"synchronization task is executed, only the valid IP address will be " "synchronization task is executed, only the valid IP address will be "
@ -11148,23 +11173,23 @@ msgstr ""
"端口用来检测 IP 地址的有效性,在同步任务执行时,只会同步有效的 IP 地址。 <br>" "端口用来检测 IP 地址的有效性,在同步任务执行时,只会同步有效的 IP 地址。 <br>"
"如果端口为 0则表示所有 IP 地址均有效。" "如果端口为 0则表示所有 IP 地址均有效。"
#: xpack/plugins/cloud/serializers/account_attrs.py:214 #: xpack/plugins/cloud/serializers/account_attrs.py:221
msgid "Hostname prefix" msgid "Hostname prefix"
msgstr "主机名前缀" msgstr "主机名前缀"
#: xpack/plugins/cloud/serializers/account_attrs.py:217 #: xpack/plugins/cloud/serializers/account_attrs.py:224
msgid "IP segment" msgid "IP segment"
msgstr "IP 网段" msgstr "IP 网段"
#: xpack/plugins/cloud/serializers/account_attrs.py:221 #: xpack/plugins/cloud/serializers/account_attrs.py:228
msgid "Test port" msgid "Test port"
msgstr "测试端口" msgstr "测试端口"
#: xpack/plugins/cloud/serializers/account_attrs.py:224 #: xpack/plugins/cloud/serializers/account_attrs.py:231
msgid "Test timeout" msgid "Test timeout"
msgstr "测试超时时间" msgstr "测试超时时间"
#: xpack/plugins/cloud/serializers/account_attrs.py:240 #: xpack/plugins/cloud/serializers/account_attrs.py:247
msgid "Project" msgid "Project"
msgstr "project" msgstr "project"
@ -11251,5 +11276,3 @@ msgstr "许可证导入成功"
msgid "Invalid license" msgid "Invalid license"
msgstr "许可证无效" msgstr "许可证无效"
#~ msgid "domain_name"
#~ msgstr "域名称"

View File

@ -4,13 +4,16 @@ import json
import os import os
import re import re
import time import time
from urllib.parse import urlparse, quote
import pytz import pytz
from django.conf import settings from django.conf import settings
from django.core.exceptions import MiddlewareNotUsed from django.core.exceptions import MiddlewareNotUsed
from django.http.response import HttpResponseForbidden from django.http.response import HttpResponseForbidden
from django.shortcuts import HttpResponse from django.shortcuts import HttpResponse
from django.utils import timezone, translation from django.shortcuts import redirect
from django.urls import reverse
from django.utils import timezone
from .utils import set_current_request from .utils import set_current_request
@ -137,3 +140,31 @@ class EndMiddleware:
response = self.get_response(request) response = self.get_response(request)
request._e_time_end = time.time() request._e_time_end = time.time()
return response return response
class SafeRedirectMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
if not (300 <= response.status_code < 400):
return response
if request.resolver_match and request.resolver_match.namespace.startswith('authentication'):
# 认证相关的路由跳过验证core/auth/xxxx
return response
location = response.get('Location')
if not location:
return response
parsed = urlparse(location)
if parsed.scheme and parsed.netloc:
target_host = parsed.netloc
if target_host in [*settings.ALLOWED_HOSTS]:
return response
origin = f"{request.scheme}://{request.get_host()}"
target_origin = f"{parsed.scheme}://{target_host}"
if not target_origin.startswith(origin):
safe_redirect_url = '%s?%s' % (reverse('redirect-confirm'), f'next={quote(location)}')
return redirect(safe_redirect_url)
return response

View File

@ -172,6 +172,7 @@ MIDDLEWARE = [
'authentication.middleware.ThirdPartyLoginMiddleware', 'authentication.middleware.ThirdPartyLoginMiddleware',
'authentication.middleware.SessionCookieMiddleware', 'authentication.middleware.SessionCookieMiddleware',
'simple_history.middleware.HistoryRequestMiddleware', 'simple_history.middleware.HistoryRequestMiddleware',
'jumpserver.middleware.SafeRedirectMiddleware',
'jumpserver.middleware.EndMiddleware', 'jumpserver.middleware.EndMiddleware',
] ]

View File

@ -46,6 +46,7 @@ app_view_patterns = [
path('common/', include('common.urls.view_urls'), name='common'), path('common/', include('common.urls.view_urls'), name='common'),
re_path(r'flower/(?P<path>.*)', views.celery_flower_view, name='flower-view'), re_path(r'flower/(?P<path>.*)', views.celery_flower_view, name='flower-view'),
path('download/', views.ResourceDownload.as_view(), name='download'), path('download/', views.ResourceDownload.as_view(), name='download'),
path('redirect/confirm/', views.RedirectConfirm.as_view(), name='redirect-confirm'),
path('i18n/<str:lang>/', views.I18NView.as_view(), name='i18n-switch'), path('i18n/<str:lang>/', views.I18NView.as_view(), name='i18n-switch'),
] ]

View File

@ -1,9 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import re import re
from urllib.parse import urlparse
from django.conf import settings from django.conf import settings
from django.http import HttpResponse from django.http import HttpResponse
from django.http import HttpResponseBadRequest
from django.http import HttpResponseRedirect, JsonResponse, Http404 from django.http import HttpResponseRedirect, JsonResponse, Http404
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils import timezone from django.utils import timezone
@ -18,7 +20,7 @@ from common.views.http import HttpResponseTemporaryRedirect
__all__ = [ __all__ = [
'LunaView', 'I18NView', 'KokoView', 'WsView', 'LunaView', 'I18NView', 'KokoView', 'WsView',
'redirect_format_api', 'redirect_old_apps_view', 'UIView', 'redirect_format_api', 'redirect_old_apps_view', 'UIView',
'ResourceDownload', 'ResourceDownload', 'RedirectConfirm'
] ]
@ -128,3 +130,24 @@ def csrf_failure(request, reason=""):
from django.shortcuts import reverse from django.shortcuts import reverse
login_url = reverse('authentication:login') + '?csrf_failure=1&admin=1' login_url = reverse('authentication:login') + '?csrf_failure=1&admin=1'
return redirect(login_url) return redirect(login_url)
class RedirectConfirm(TemplateView):
template_name = 'redirect_confirm.html'
def get(self, request, *args, **kwargs):
next_url = self.request.GET.get("next")
if not self.is_valid_url(next_url):
return HttpResponseBadRequest("Invalid next url")
return self.render_to_response({"target_url": next_url})
@staticmethod
def is_valid_url(url):
if not url:
return False
parsed = urlparse(url)
if not parsed.scheme or not parsed.netloc:
return False
if parsed.scheme not in ['http', 'https']:
return False
return True

View File

@ -0,0 +1,46 @@
{% extends '_base_only_content.html' %}
{% load static %}
{% load i18n %}
{% block html_title %} {{ INTERFACE.login_title }} {% endblock %}
{% block title %} {{ INTERFACE.login_title }}{% endblock %}
{% block content %}
<style>
.alert.alert-msg {
background: #F5F5F7;
}
.target-url {
display: inline-block;
max-width: 100%;
min-width: 100px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
}
</style>
<div>
<p>
<div class="alert {% if error %} alert-danger {% else %} alert-info {% endif %}" id="messages">
{% trans 'You are about to be redirected to an external website. Please confirm that you trust this link: ' %}
<a class="target-url" href="{{ target_url }}">{{ target_url }}</a>
</div>
</p>
<div class="row">
<div class="col-sm-3">
<a href="/" class="btn btn-default block full-width m-b">
{% trans 'Cancel' %}
</a>
</div>
<div class="col-sm-3">
<a href="{{ target_url }}" class="btn btn-primary block full-width m-b">
{% trans 'Confirm' %}
</a>
</div>
</div>
</div>
{% endblock %}